diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -39,6 +39,8 @@ BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc") BUILTIN(__builtin_arm_cls, "UiZUi", "nc") BUILTIN(__builtin_arm_cls64, "UiWUi", "nc") +BUILTIN(__builtin_arm_clz, "UiZUi", "nc") +BUILTIN(__builtin_arm_clz64, "UiWUi", "nc") // HINT BUILTIN(__builtin_arm_nop, "v", "") diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def --- a/clang/include/clang/Basic/BuiltinsARM.def +++ b/clang/include/clang/Basic/BuiltinsARM.def @@ -119,6 +119,8 @@ // Bit manipulation BUILTIN(__builtin_arm_rbit, "UiUi", "nc") +BUILTIN(__builtin_arm_clz, "UiZUi", "nc") +BUILTIN(__builtin_arm_clz64, "UiWUi", "nc") BUILTIN(__builtin_arm_cls, "UiZUi", "nc") BUILTIN(__builtin_arm_cls64, "UiWUi", "nc") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -7906,6 +7906,17 @@ CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); } + if (BuiltinID == clang::ARM::BI__builtin_arm_clz || + BuiltinID == clang::ARM::BI__builtin_arm_clz64) { + llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); + Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Arg->getType()); + Value *Res = Builder.CreateCall(F, {Arg, Builder.getInt1(false)}); + if (BuiltinID == clang::ARM::BI__builtin_arm_clz64) + Res = Builder.CreateTrunc(Res, Builder.getInt32Ty()); + return Res; + } + + if (BuiltinID == clang::ARM::BI__builtin_arm_cls) { llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_cls), Arg, "cls"); @@ -9988,6 +9999,16 @@ CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); } + if (BuiltinID == clang::AArch64::BI__builtin_arm_clz || + BuiltinID == clang::AArch64::BI__builtin_arm_clz64) { + llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); + Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Arg->getType()); + Value *Res = Builder.CreateCall(F, {Arg, Builder.getInt1(false)}); + if (BuiltinID == clang::AArch64::BI__builtin_arm_clz64) + Res = Builder.CreateTrunc(Res, Builder.getInt32Ty()); + return Res; + } + if (BuiltinID == clang::AArch64::BI__builtin_arm_cls) { llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_cls), Arg, diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h --- a/clang/lib/Headers/arm_acle.h +++ b/clang/lib/Headers/arm_acle.h @@ -140,17 +140,21 @@ /* CLZ */ static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__)) __clz(uint32_t __t) { - return (unsigned int)__builtin_clz(__t); + return __builtin_arm_clz(__t); } static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__)) __clzl(unsigned long __t) { - return (unsigned int)__builtin_clzl(__t); +#if __SIZEOF_LONG__ == 4 + return __builtin_arm_clz(__t); +#else + return __builtin_arm_clz64(__t); +#endif } static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__)) __clzll(uint64_t __t) { - return (unsigned int)__builtin_clzll(__t); + return __builtin_arm_clz64(__t); } /* CLS */