Author: Fangrui Song Date: 2023-09-27T21:29:56-07:00 New Revision: 0d8b864829073cf6f0a40f1b257d6631fc4145d0
URL: https://github.com/llvm/llvm-project/commit/0d8b864829073cf6f0a40f1b257d6631fc4145d0 DIFF: https://github.com/llvm/llvm-project/commit/0d8b864829073cf6f0a40f1b257d6631fc4145d0.diff LOG: CGBuiltin: emit llvm.abs.* instead of neg+icmp+select for abs instcombine will combine neg+icmp+select to llvm.abs.*. Let's just emit llvm.abs.* in the first place. Added: Modified: clang/lib/CodeGen/CGBuiltin.cpp clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c clang/test/CodeGen/abs-overflow.c clang/test/CodeGen/builtin-abs.c clang/test/CodeGenCXX/builtins.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 04c0325c7fd038b..b0fd38408806566 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1769,12 +1769,9 @@ Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E, } static Value *EmitAbs(CodeGenFunction &CGF, Value *ArgValue, bool HasNSW) { - // X < 0 ? -X : X - // TODO: Use phi-node (for better SimplifyCFGPass) - Value *NegOp = CGF.Builder.CreateNeg(ArgValue, "neg", false, HasNSW); - Constant *Zero = llvm::Constant::getNullValue(ArgValue->getType()); - Value *CmpResult = CGF.Builder.CreateICmpSLT(ArgValue, Zero, "abscond"); - return CGF.Builder.CreateSelect(CmpResult, NegOp, ArgValue, "abs"); + return CGF.Builder.CreateBinaryIntrinsic( + Intrinsic::abs, ArgValue, + ConstantInt::get(CGF.Builder.getInt1Ty(), HasNSW)); } static Value *EmitOverflowCheckedAbs(CodeGenFunction &CGF, const CallExpr *E, diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c index 64bd6e3ed41e8bb..2ef4c28a5e999a4 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c @@ -17,9 +17,7 @@ typedef __SIZE_TYPE__ size_t; // BOTH-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 // BOTH-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 // BOTH-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// BOTH-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[TMP0]] -// BOTH-NEXT: [[ABSCOND:%.*]] = icmp slt i32 [[TMP0]], 0 -// BOTH-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i32 [[NEG]], i32 [[TMP0]] +// BOTH-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 %0, i1 true) // BOTH-NEXT: ret i32 [[ABS]] signed int testabs(signed int a) { return __abs(a); @@ -30,9 +28,7 @@ signed int testabs(signed int a) { // 64BIT-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 // 64BIT-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 // 64BIT-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// 64BIT-NEXT: [[NEG:%.*]] = sub nsw i64 0, [[TMP0]] -// 64BIT-NEXT: [[ABSCOND:%.*]] = icmp slt i64 [[TMP0]], 0 -// 64BIT-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i64 [[NEG]], i64 [[TMP0]] +// 64BIT-NEXT: [[ABS:%.*]] = call i64 @llvm.abs.i64(i64 [[TMP0]], i1 true) // 64BIT-NEXT: ret i64 [[ABS]] // // 32BIT-LABEL: @testlabs( @@ -40,9 +36,7 @@ signed int testabs(signed int a) { // 32BIT-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 // 32BIT-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 // 32BIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// 32BIT-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[TMP0]] -// 32BIT-NEXT: [[ABSCOND:%.*]] = icmp slt i32 [[TMP0]], 0 -// 32BIT-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i32 [[NEG]], i32 [[TMP0]] +// 32BIT-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP0]], i1 true) // 32BIT-NEXT: ret i32 [[ABS]] // signed long testlabs(signed long a) { @@ -54,9 +48,7 @@ signed long testlabs(signed long a) { // 64BIT-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 // 64BIT-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 // 64BIT-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// 64BIT-NEXT: [[NEG:%.*]] = sub nsw i64 0, [[TMP0]] -// 64BIT-NEXT: [[ABSCOND:%.*]] = icmp slt i64 [[TMP0]], 0 -// 64BIT-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i64 [[NEG]], i64 [[TMP0]] +// 64BIT-NEXT: [[ABS:%.*]] = call i64 @llvm.abs.i64(i64 [[TMP0]], i1 true) // 64BIT-NEXT: ret i64 [[ABS]] // // 32BIT-LABEL: @testllabs( @@ -64,9 +56,7 @@ signed long testlabs(signed long a) { // 32BIT-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 // 32BIT-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 // 32BIT-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// 32BIT-NEXT: [[NEG:%.*]] = sub nsw i64 0, [[TMP0]] -// 32BIT-NEXT: [[ABSCOND:%.*]] = icmp slt i64 [[TMP0]], 0 -// 32BIT-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i64 [[NEG]], i64 [[TMP0]] +// 32BIT-NEXT: [[ABS:%.*]] = call i64 @llvm.abs.i64(i64 [[TMP0]], i1 true) // 32BIT-NEXT: ret i64 [[ABS]] // signed long long testllabs(signed long long a) { diff --git a/clang/test/CodeGen/abs-overflow.c b/clang/test/CodeGen/abs-overflow.c index 2b7647af9727096..aead4e282bd6211 100644 --- a/clang/test/CodeGen/abs-overflow.c +++ b/clang/test/CodeGen/abs-overflow.c @@ -6,9 +6,8 @@ extern int abs(int x); int absi(int x) { -// WRAPV: [[NEG:%.*]] = sub i32 0, [[X:%.*]] -// WRAPV: [[CMP:%.*]] = icmp slt i32 [[X]], 0 -// WRAPV: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[X]] +// WRAPV: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 %0, i1 false) +// WRAPV-NEXT: ret i32 [[ABS]] // // BOTH-TRAP: [[NEG:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 0, i32 [[X:%.*]]) // BOTH-TRAP: [[NEGV:%.*]] = extractvalue { i32, i1 } [[NEG]], 0 @@ -26,9 +25,8 @@ int absi(int x) { } int babsi(int x) { -// WRAPV: [[NEG:%.*]] = sub i32 0, [[X:%.*]] -// WRAPV: [[CMP:%.*]] = icmp slt i32 [[X]], 0 -// WRAPV: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[X]] +// WRAPV: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 %0, i1 false) +// WRAPV-NEXT: ret i32 [[ABS]] // // BOTH-TRAP: [[NEG:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 0, i32 [[X:%.*]]) // BOTH-TRAP: [[NEGV:%.*]] = extractvalue { i32, i1 } [[NEG]], 0 diff --git a/clang/test/CodeGen/builtin-abs.c b/clang/test/CodeGen/builtin-abs.c index 791395368a8c014..fd88b206f4a5a39 100644 --- a/clang/test/CodeGen/builtin-abs.c +++ b/clang/test/CodeGen/builtin-abs.c @@ -2,27 +2,24 @@ int absi(int x) { // CHECK-LABEL: @absi( -// CHECK: [[NEG:%.*]] = sub nsw i32 0, [[X:%.*]] -// CHECK: [[CMP:%.*]] = icmp slt i32 [[X]], 0 -// CHECK: [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[X]] +// CHECK: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 %0, i1 true) +// CHECK-NEXT: ret i32 [[ABS]] // return __builtin_abs(x); } long absl(long x) { // CHECK-LABEL: @absl( -// CHECK: [[NEG:%.*]] = sub nsw i64 0, [[X:%.*]] -// CHECK: [[CMP:%.*]] = icmp slt i64 [[X]], 0 -// CHECK: [[SEL:%.*]] = select i1 [[CMP]], i64 [[NEG]], i64 [[X]] +// CHECK: [[ABS:%.*]] = call i64 @llvm.abs.i64(i64 %0, i1 true) +// CHECK-NEXT: ret i64 [[ABS]] // return __builtin_labs(x); } long long absll(long long x) { // CHECK-LABEL: @absll( -// CHECK: [[NEG:%.*]] = sub nsw i64 0, [[X:%.*]] -// CHECK: [[CMP:%.*]] = icmp slt i64 [[X]], 0 -// CHECK: [[SEL:%.*]] = select i1 [[CMP]], i64 [[NEG]], i64 [[X]] +// CHECK: [[ABS:%.*]] = call i64 @llvm.abs.i64(i64 %0, i1 true) +// CHECK-NEXT: ret i64 [[ABS]] // return __builtin_llabs(x); } diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp index 39201595d55e6e4..90265186fb3d8c8 100644 --- a/clang/test/CodeGenCXX/builtins.cpp +++ b/clang/test/CodeGenCXX/builtins.cpp @@ -53,7 +53,8 @@ long __builtin_abs(long); // #2 extern "C" int __builtin_abs(int); // #3 int x = __builtin_abs(-2); -// CHECK: store i32 2, ptr @x, align 4 +// CHECK: [[X:%.+]] = call i32 @llvm.abs.i32(i32 -2, i1 true) +// CHECK-NEXT: store i32 [[X]], ptr @x, align 4 long y = __builtin_abs(-2l); // CHECK: [[Y:%.+]] = call noundef i64 @_Z13__builtin_absl(i64 noundef -2) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits