Skip to content

Commit

Permalink
[ARM][AArch64] Add ARM specific builtin for clz that is not undefined…
Browse files Browse the repository at this point in the history
… for 0 in ubsan.

D152023 made ubsan consider __builtin_clz of 0 undefined regardless of
the target. This ensures portability and matches gcc.

This causes the ACLE intrinsics to also be considered to also be
considered to be undefined for 0 since they used the generic builtins
as their implementation.

This patch adds builtins for ARM that ubsan doesn't know about to make
the behavior defined for 0. Alternatively, I could have added a zero
check to the intrinsics, but the dedicated builtin will give better -O0
codegen.

Fixes #63113.

Reviewed By: tmatheson

Differential Revision: https://reviews.llvm.org/D154915
  • Loading branch information
topperc committed Jul 12, 2023
1 parent d3ddcfd commit 85b27ac
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 3 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/BuiltinsAArch64.def
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
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", "")
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/BuiltinsARM.def
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ BUILTIN(__builtin_arm_smusdx, "iii", "nc")

// 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")

Expand Down
21 changes: 21 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7906,6 +7906,17 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
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");
Expand Down Expand Up @@ -9988,6 +9999,16 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
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,
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Headers/arm_acle.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,21 @@ __rorl(unsigned long __x, uint32_t __y) {
/* 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 */
Expand Down

0 comments on commit 85b27ac

Please sign in to comment.