Author: Craig Topper Date: 2025-12-30T14:49:30-08:00 New Revision: 0bc6491da0c827ce94bd8fa852422eaafe6c39e7
URL: https://github.com/llvm/llvm-project/commit/0bc6491da0c827ce94bd8fa852422eaafe6c39e7 DIFF: https://github.com/llvm/llvm-project/commit/0bc6491da0c827ce94bd8fa852422eaafe6c39e7.diff LOG: [Clang] Add NUW to the Sub in __builtin_clrsb expansion. (#174010) The ctlz will produce a value in the range [1..bitwidth]. It can't produce 0. This means the subtract of 1 will not have unsigned wrap. It also has no signed wrap, but the optimizer can figure that out on its own. It's very likely InstCombine will just drop the NUW when it canonicalizes to Add, but maybe it will be helpful in some case. Added: Modified: clang/lib/CodeGen/CGBuiltin.cpp clang/test/CodeGen/builtin_clrsb.c Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index d3abf6d2a1f2d..bd1ef267a7f22 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3292,7 +3292,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *Inverse = Builder.CreateNot(ArgValue, "not"); Value *Tmp = Builder.CreateSelect(IsNeg, Inverse, ArgValue); Value *Ctlz = Builder.CreateCall(F, {Tmp, Builder.getFalse()}); - Value *Result = Builder.CreateSub(Ctlz, llvm::ConstantInt::get(ArgType, 1)); + Value *Result = + Builder.CreateNUWSub(Ctlz, llvm::ConstantInt::get(ArgType, 1)); Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, "cast"); return RValue::get(Result); diff --git a/clang/test/CodeGen/builtin_clrsb.c b/clang/test/CodeGen/builtin_clrsb.c index c51777ed1222c..1f6c93ff4c570 100644 --- a/clang/test/CodeGen/builtin_clrsb.c +++ b/clang/test/CodeGen/builtin_clrsb.c @@ -6,7 +6,7 @@ int test__builtin_clrsb(int x) { // CHECK-NEXT: [[INV:%.*]] = xor i32 [[X]], -1 // CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[INV]], i32 [[X]] // CHECK-NEXT: [[CTLZ:%.*]] = call i32 @llvm.ctlz.i32(i32 [[SEL]], i1 false) -// CHECK-NEXT: [[SUB:%.*]] = sub i32 [[CTLZ]], 1 +// CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[CTLZ]], 1 return __builtin_clrsb(x); } @@ -16,7 +16,7 @@ int test__builtin_clrsbll(long long x) { // CHECK-NEXT: [[INV:%.*]] = xor i64 [[X]], -1 // CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i64 [[INV]], i64 [[X]] // CHECK-NEXT: [[CTLZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[SEL]], i1 false) -// CHECK-NEXT: [[SUB:%.*]] = sub i64 [[CTLZ]], 1 +// CHECK-NEXT: [[SUB:%.*]] = sub nuw i64 [[CTLZ]], 1 // CHECK-NEXT: trunc i64 [[SUB]] to i32 return __builtin_clrsbll(x); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
