Skip to content

Commit 28f7512

Browse files
committed
[InstSimplify] Implement constant folding for UCMP/SCMP intrinsics
1 parent a21ce63 commit 28f7512

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 29 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,33 @@ 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 UndefValue::get(Ty);
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+
}
2783+
if (ICmpInst::compare(*C0, *C1, ICmpInst::ICMP_EQ)) {
2784+
return ConstantInt::get(Ty, 0);
2785+
}
2786+
if (ICmpInst::compare(*C0, *C1,
2787+
IntrinsicID == Intrinsic::scmp
2788+
? ICmpInst::ICMP_SGT
2789+
: ICmpInst::ICMP_UGT)) {
2790+
return ConstantInt::get(Ty, 1);
2791+
}
2792+
2793+
assert(false && "Integer values must compare as equal, or one must be "
2794+
"less than the other");
2795+
27672796
case Intrinsic::usub_with_overflow:
27682797
case Intrinsic::ssub_with_overflow:
27692798
// X - undef -> { 0, false }

llvm/test/Transforms/InstSimplify/uscmp.ll

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,39 @@
22
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
33
define i8 @scmp_lt() {
44
; CHECK-LABEL: define i8 @scmp_lt() {
5-
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 -7, i32 3)
6-
; CHECK-NEXT: ret i8 [[TMP1]]
5+
; CHECK-NEXT: ret i8 -1
76
;
87
%1 = call i8 @llvm.scmp(i32 -7, i32 3)
98
ret i8 %1
109
}
1110

1211
define i2 @ucmp_eq() {
1312
; CHECK-LABEL: define i2 @ucmp_eq() {
14-
; CHECK-NEXT: [[TMP1:%.*]] = call i2 @llvm.ucmp.i2.i32(i32 12, i32 12)
15-
; CHECK-NEXT: ret i2 [[TMP1]]
13+
; CHECK-NEXT: ret i2 0
1614
;
1715
%1 = call i2 @llvm.ucmp(i32 12, i32 12)
1816
ret i2 %1
1917
}
2018

2119
define i100 @ucmp_gt() {
2220
; CHECK-LABEL: define i100 @ucmp_gt() {
23-
; CHECK-NEXT: [[TMP1:%.*]] = call i100 @llvm.ucmp.i100.i32(i32 7, i32 3)
24-
; CHECK-NEXT: ret i100 [[TMP1]]
21+
; CHECK-NEXT: ret i100 1
2522
;
2623
%1 = call i100 @llvm.ucmp(i32 7, i32 3)
2724
ret i100 %1
2825
}
2926

3027
define <4 x i8> @ucmp_lt_splat() {
3128
; CHECK-LABEL: define <4 x i8> @ucmp_lt_splat() {
32-
; 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>)
33-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
29+
; CHECK-NEXT: ret <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>
3430
;
3531
%1 = call <4 x i8> @llvm.ucmp(<4 x i32> splat(i32 1), <4 x i32> splat(i32 3))
3632
ret <4 x i8> %1
3733
}
3834

3935
define <4 x i8> @scmp_nonsplat() {
4036
; CHECK-LABEL: define <4 x i8> @scmp_nonsplat() {
41-
; 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>)
42-
; CHECK-NEXT: ret <4 x i8> [[TMP1]]
37+
; CHECK-NEXT: ret <4 x i8> <i8 1, i8 0, i8 1, i8 -1>
4338
;
4439
%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>)
4540
ret <4 x i8> %1

0 commit comments

Comments
 (0)