Skip to content

Commit d926bc1

Browse files
committed
[InstSimplify] Implement constant folding for UCMP/SCMP intrinsics
1 parent 19610f5 commit d926bc1

File tree

2 files changed

+36
-20
lines changed

2 files changed

+36
-20
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
15061506
case Intrinsic::smin:
15071507
case Intrinsic::umax:
15081508
case Intrinsic::umin:
1509+
case Intrinsic::scmp:
1510+
case Intrinsic::ucmp:
15091511
case Intrinsic::sadd_with_overflow:
15101512
case Intrinsic::uadd_with_overflow:
15111513
case Intrinsic::ssub_with_overflow:
@@ -2764,6 +2766,30 @@ static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty,
27642766
? *C0
27652767
: *C1);
27662768

2769+
case Intrinsic::scmp:
2770+
case Intrinsic::ucmp:
2771+
if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1]))
2772+
return PoisonValue::get(Ty);
2773+
2774+
if (!C0 || !C1)
2775+
return ConstantInt::get(Ty, 0);
2776+
2777+
if (ICmpInst::compare(*C0, *C1,
2778+
IntrinsicID == Intrinsic::scmp
2779+
? ICmpInst::ICMP_SLT
2780+
: ICmpInst::ICMP_ULT))
2781+
return ConstantInt::get(Ty, -1, true);
2782+
if (*C0 == *C1)
2783+
return ConstantInt::get(Ty, 0);
2784+
if (ICmpInst::compare(*C0, *C1,
2785+
IntrinsicID == Intrinsic::scmp
2786+
? ICmpInst::ICMP_SGT
2787+
: ICmpInst::ICMP_UGT))
2788+
return ConstantInt::get(Ty, 1);
2789+
2790+
llvm_unreachable("Integer values must compare as equal, or one must be "
2791+
"less than the other");
2792+
27672793
case Intrinsic::usub_with_overflow:
27682794
case Intrinsic::ssub_with_overflow:
27692795
// X - undef -> { 0, false }

llvm/test/Transforms/InstSimplify/uscmp.ll

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,89 +3,79 @@
33

44
define i8 @scmp_lt() {
55
; CHECK-LABEL: define i8 @scmp_lt() {
6-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 -7, i32 3)
7-
; CHECK-NEXT: ret i8 [[TMP1]]
6+
; CHECK-NEXT: ret i8 -1
87
;
98
%1 = call i8 @llvm.scmp(i32 -7, i32 3)
109
ret i8 %1
1110
}
1211

1312
define i8 @scmp_eq() {
1413
; CHECK-LABEL: define i8 @scmp_eq() {
15-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 2, i32 2)
16-
; CHECK-NEXT: ret i8 [[TMP1]]
14+
; CHECK-NEXT: ret i8 0
1715
;
1816
%1 = call i8 @llvm.scmp(i32 2, i32 2)
1917
ret i8 %1
2018
}
2119

2220
define i8 @scmp_gt() {
2321
; CHECK-LABEL: define i8 @scmp_gt() {
24-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 2, i32 -7)
25-
; CHECK-NEXT: ret i8 [[TMP1]]
22+
; CHECK-NEXT: ret i8 1
2623
;
2724
%1 = call i8 @llvm.scmp(i32 2, i32 -7)
2825
ret i8 %1
2926
}
3027

3128
define i8 @ucmp_lt() {
3229
; CHECK-LABEL: define i8 @ucmp_lt() {
33-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 7, i32 12)
34-
; CHECK-NEXT: ret i8 [[TMP1]]
30+
; CHECK-NEXT: ret i8 -1
3531
;
3632
%1 = call i8 @llvm.ucmp(i32 7, i32 12)
3733
ret i8 %1
3834
}
3935

4036
define i2 @ucmp_eq() {
4137
; CHECK-LABEL: define i2 @ucmp_eq() {
42-
; CHECK-NEXT: [[TMP1:%.*]] = call i2 @llvm.ucmp.i2.i32(i32 12, i32 12)
43-
; CHECK-NEXT: ret i2 [[TMP1]]
38+
; CHECK-NEXT: ret i2 0
4439
;
4540
%1 = call i2 @llvm.ucmp(i32 12, i32 12)
4641
ret i2 %1
4742
}
4843

4944
define i100 @ucmp_gt() {
5045
; CHECK-LABEL: define i100 @ucmp_gt() {
51-
; CHECK-NEXT: [[TMP1:%.*]] = call i100 @llvm.ucmp.i100.i32(i32 7, i32 3)
52-
; CHECK-NEXT: ret i100 [[TMP1]]
46+
; CHECK-NEXT: ret i100 1
5347
;
5448
%1 = call i100 @llvm.ucmp(i32 7, i32 3)
5549
ret i100 %1
5650
}
5751

5852
define i8 @ucmp_poison() {
5953
; CHECK-LABEL: define i8 @ucmp_poison() {
60-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 poison, i32 5)
61-
; CHECK-NEXT: ret i8 [[TMP1]]
54+
; CHECK-NEXT: ret i8 poison
6255
;
6356
%1 = call i8 @llvm.ucmp(i32 poison, i32 5)
6457
ret i8 %1
6558
}
6659

6760
define i8 @scmp_undef() {
6861
; CHECK-LABEL: define i8 @scmp_undef() {
69-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 undef, i32 -12)
70-
; CHECK-NEXT: ret i8 [[TMP1]]
62+
; CHECK-NEXT: ret i8 0
7163
;
7264
%1 = call i8 @llvm.scmp(i32 undef, i32 -12)
7365
ret i8 %1
7466
}
7567

7668
define <4 x i8> @ucmp_lt_splat() {
7769
; CHECK-LABEL: define <4 x i8> @ucmp_lt_splat() {
78-
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.ucmp.v4i8.v4i32(<4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 3, i32 3, i32 3, i32 3>)
79-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
70+
; CHECK-NEXT: ret <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>
8071
;
8172
%1 = call <4 x i8> @llvm.ucmp(<4 x i32> splat(i32 1), <4 x i32> splat(i32 3))
8273
ret <4 x i8> %1
8374
}
8475

8576
define <4 x i8> @scmp_nonsplat() {
8677
; CHECK-LABEL: define <4 x i8> @scmp_nonsplat() {
87-
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.scmp.v4i8.v4i32(<4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32> <i32 -1, i32 1, i32 -2, i32 4>)
88-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
78+
; CHECK-NEXT: ret <4 x i8> <i8 1, i8 0, i8 1, i8 -1>
8979
;
9080
%1 = call <4 x i8> @llvm.scmp(<4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32> <i32 -1, i32 1, i32 -2, i32 4>)
9181
ret <4 x i8> %1

0 commit comments

Comments
 (0)