[clang] 0d8b864 - CGBuiltin: emit llvm.abs.* instead of neg+icmp+select for abs

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 27 21:30:01 PDT 2023


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)


        


More information about the cfe-commits mailing list