Index: include/clang/Basic/BuiltinsAArch64.def =================================================================== --- include/clang/Basic/BuiltinsAArch64.def +++ include/clang/Basic/BuiltinsAArch64.def @@ -53,6 +53,10 @@ // Prefetch BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") +// Rotate Right (ROR) +BUILTIN(__builtin_arm_ror, "UiUiUi", "n") +BUILTIN(__builtin_arm_ror64, "LUiLUiLUi", "n") + // System Registers BUILTIN(__builtin_arm_rsr, "UicC*", "nc") BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc") Index: include/clang/Basic/BuiltinsARM.def =================================================================== --- include/clang/Basic/BuiltinsARM.def +++ include/clang/Basic/BuiltinsARM.def @@ -94,6 +94,9 @@ // Prefetch BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc") +// Rotate Right (ROR) +BUILTIN(__builtin_arm_ror, "UiUiUi", "n") + // System registers (ACLE) BUILTIN(__builtin_arm_rsr, "UicC*", "nc") BUILTIN(__builtin_arm_rsr64, "LLUicC*", "nc") Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -3738,6 +3738,13 @@ if (auto Hint = GetValueForARMHint(BuiltinID)) return Hint; + if (BuiltinID == ARM::BI__builtin_arm_ror) { + Value *Val = EmitScalarExpr(E->getArg(0)); + Value *Shift = EmitScalarExpr(E->getArg(1)); + Function *F = CGM.getIntrinsic(Intrinsic::arm_ror); + return Builder.CreateCall(F, {Val, Shift}); + } + if (BuiltinID == ARM::BI__emit) { bool IsThumb = getTarget().getTriple().getArch() == llvm::Triple::thumb; llvm::FunctionType *FTy = @@ -4525,6 +4532,14 @@ return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID)); } + if (BuiltinID == AArch64::BI__builtin_arm_ror || + BuiltinID == AArch64::BI__builtin_arm_ror64) { + Value *Val = EmitScalarExpr(E->getArg(0)); + Value *Shift = EmitScalarExpr(E->getArg(1)); + Function *F = CGM.getIntrinsic(Intrinsic::aarch64_ror, Val->getType()); + return Builder.CreateCall(F, {Val, Shift}); + } + if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { Value *Address = EmitScalarExpr(E->getArg(0)); Value *RW = EmitScalarExpr(E->getArg(1)); Index: test/CodeGen/builtins-arm.c =================================================================== --- test/CodeGen/builtins-arm.c +++ test/CodeGen/builtins-arm.c @@ -72,6 +72,12 @@ return __builtin_arm_rbit(a); } +// CHECK: call {{.*}} @llvm.arm.ror(i32 %a, i32 %b) + +unsigned ror(unsigned a, unsigned b) { + return __builtin_arm_ror(a, b); +} + void prefetch(int i) { __builtin_arm_prefetch(&i, 0, 1); // CHECK: call {{.*}} @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 1) Index: test/CodeGen/builtins-arm64.c =================================================================== --- test/CodeGen/builtins-arm64.c +++ test/CodeGen/builtins-arm64.c @@ -20,6 +20,16 @@ return __builtin_arm_rbit64(a); } +// CHECK: call {{.*}} @llvm.aarch64.ror.i32(i32 %a, i32 %b) +unsigned ror(unsigned a, unsigned b) { + return __builtin_arm_ror(a, b); +} + +// CHECK: call {{.*}} @llvm.aarch64.ror.i64(i64 %a, i64 %b) +unsigned long long ror64(unsigned long long a, unsigned long long b) { + return __builtin_arm_ror64(a, b); +} + void hints() { __builtin_arm_nop(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 0) __builtin_arm_yield(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 1)