summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/BuiltinsAArch64.def2
-rw-r--r--clang/include/clang/Basic/BuiltinsARM.def2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp21
-rw-r--r--clang/lib/Headers/arm_acle.h20
-rw-r--r--clang/test/CodeGen/arm_acle.c18
-rw-r--r--clang/test/CodeGen/builtins-arm.c15
-rw-r--r--clang/test/CodeGen/builtins-arm64.c17
7 files changed, 95 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def
index 4df8d5a1676..f07c567053d 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -33,6 +33,8 @@ BUILTIN(__builtin_arm_clrex, "v", "")
// Bit manipulation
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc")
+BUILTIN(__builtin_arm_cls, "UiZUi", "nc")
+BUILTIN(__builtin_arm_cls64, "UiWUi", "nc")
// HINT
BUILTIN(__builtin_arm_nop, "v", "")
diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def
index 5f8308d2931..81991a57e2b 100644
--- a/clang/include/clang/Basic/BuiltinsARM.def
+++ b/clang/include/clang/Basic/BuiltinsARM.def
@@ -115,6 +115,8 @@ BUILTIN(__builtin_arm_smusdx, "iii", "nc")
// Bit manipulation
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
+BUILTIN(__builtin_arm_cls, "UiZUi", "nc")
+BUILTIN(__builtin_arm_cls64, "UiWUi", "nc")
// Store and load exclusive
BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "")
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9a56116173e..648837a6d15 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -6055,6 +6055,16 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit");
}
+ if (BuiltinID == ARM::BI__builtin_arm_cls) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_cls), Arg, "cls");
+ }
+ if (BuiltinID == ARM::BI__builtin_arm_cls64) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_cls64), Arg,
+ "cls");
+ }
+
if (BuiltinID == ARM::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
@@ -7108,6 +7118,17 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit");
}
+ if (BuiltinID == AArch64::BI__builtin_arm_cls) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_cls), Arg,
+ "cls");
+ }
+ if (BuiltinID == AArch64::BI__builtin_arm_cls64) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_cls64), Arg,
+ "cls");
+ }
+
if (BuiltinID == AArch64::BI__builtin_arm_jcvt) {
assert((getContext().getTypeSize(E->getType()) == 32) &&
"__jcvt of unusual size!");
diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h
index 942172f9f8e..137092fb9d7 100644
--- a/clang/lib/Headers/arm_acle.h
+++ b/clang/lib/Headers/arm_acle.h
@@ -139,6 +139,26 @@ __clzll(uint64_t __t) {
return __builtin_clzll(__t);
}
+/* CLS */
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
+__cls(uint32_t __t) {
+ return __builtin_arm_cls(__t);
+}
+
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
+__clsl(unsigned long __t) {
+#if __SIZEOF_LONG__ == 4
+ return __builtin_arm_cls(__t);
+#else
+ return __builtin_arm_cls64(__t);
+#endif
+}
+
+static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
+__clsll(uint64_t __t) {
+ return __builtin_arm_cls64(__t);
+}
+
/* REV */
static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__rev(uint32_t __t) {
diff --git a/clang/test/CodeGen/arm_acle.c b/clang/test/CodeGen/arm_acle.c
index 7463d0d8e1d..9f0ad22bda4 100644
--- a/clang/test/CodeGen/arm_acle.c
+++ b/clang/test/CodeGen/arm_acle.c
@@ -175,6 +175,24 @@ uint64_t test_clzll(uint64_t t) {
return __clzll(t);
}
+// ARM-LABEL: test_cls
+// ARM: call i32 @llvm.arm.cls(i32 %t)
+unsigned test_cls(uint32_t t) {
+ return __cls(t);
+}
+
+// ARM-LABEL: test_clsl
+// AArch32: call i32 @llvm.arm.cls(i32 %t)
+// AArch64: call i32 @llvm.arm.cls64(i64 %t)
+unsigned test_clsl(unsigned long t) {
+ return __clsl(t);
+}
+// ARM-LABEL: test_clsll
+// ARM: call i32 @llvm.arm.cls64(i64 %t)
+unsigned test_clsll(uint64_t t) {
+ return __clsll(t);
+}
+
// ARM-LABEL: test_rev
// ARM: call i32 @llvm.bswap.i32(i32 %t)
uint32_t test_rev(uint32_t t) {
diff --git a/clang/test/CodeGen/builtins-arm.c b/clang/test/CodeGen/builtins-arm.c
index 4941411bfbb..f3c4ecaeee9 100644
--- a/clang/test/CodeGen/builtins-arm.c
+++ b/clang/test/CodeGen/builtins-arm.c
@@ -256,6 +256,21 @@ void wsrp(void *v) {
__builtin_arm_wsrp("sysreg", v);
}
+unsigned int cls(uint32_t v) {
+ // CHECK: call i32 @llvm.arm.cls(i32 %v)
+ return __builtin_arm_cls(v);
+}
+
+unsigned int clsl(unsigned long v) {
+ // CHECK: call i32 @llvm.arm.cls(i32 %v)
+ return __builtin_arm_cls(v);
+}
+
+unsigned int clsll(uint64_t v) {
+ // CHECK: call i32 @llvm.arm.cls64(i64 %v)
+ return __builtin_arm_cls64(v);
+}
+
// CHECK: ![[M0]] = !{!"cp1:2:c3:c4:5"}
// CHECK: ![[M1]] = !{!"cp1:2:c3"}
// CHECK: ![[M2]] = !{!"sysreg"}
diff --git a/clang/test/CodeGen/builtins-arm64.c b/clang/test/CodeGen/builtins-arm64.c
index 7095396e6bb..f16cd4505f6 100644
--- a/clang/test/CodeGen/builtins-arm64.c
+++ b/clang/test/CodeGen/builtins-arm64.c
@@ -106,4 +106,21 @@ void wsrp(void *v) {
__builtin_arm_wsrp("1:2:3:4:5", v);
}
+unsigned int cls(uint32_t v) {
+ // CHECK: call i32 @llvm.aarch64.cls(i32 %v)
+ return __builtin_arm_cls(v);
+}
+
+unsigned int clsl(unsigned long v) {
+ // CHECK-WIN: [[V64:%[^ ]+]] = zext i32 %v to i64
+ // CHECK-WIN: call i32 @llvm.aarch64.cls64(i64 [[V64]]
+ // CHECK-LINUX: call i32 @llvm.aarch64.cls64(i64 %v)
+ return __builtin_arm_cls64(v);
+}
+
+unsigned int clsll(uint64_t v) {
+ // CHECK: call i32 @llvm.aarch64.cls64(i64 %v)
+ return __builtin_arm_cls64(v);
+}
+
// CHECK: ![[M0]] = !{!"1:2:3:4:5"}
OpenPOWER on IntegriCloud