Skip to content

Commit

Permalink
CGBuiltin: emit llvm.abs.* instead of neg+icmp+select for abs
Browse files Browse the repository at this point in the history
instcombine will combine neg+icmp+select to llvm.abs.*. Let's just emit
llvm.abs.* in the first place.
  • Loading branch information
MaskRay committed Sep 28, 2023
1 parent 11819a1 commit 0d8b864
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 37 deletions.
9 changes: 3 additions & 6 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
20 changes: 5 additions & 15 deletions clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -30,19 +28,15 @@ 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(
// 32BIT-NEXT: entry:
// 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) {
Expand All @@ -54,19 +48,15 @@ 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(
// 32BIT-NEXT: entry:
// 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) {
Expand Down
10 changes: 4 additions & 6 deletions clang/test/CodeGen/abs-overflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
15 changes: 6 additions & 9 deletions clang/test/CodeGen/builtin-abs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
3 changes: 2 additions & 1 deletion clang/test/CodeGenCXX/builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 0d8b864

Please sign in to comment.