Skip to content

Commit fe54d1a

Browse files
authored
[ConstraintElim] Simplify cmp after uadd.sat/usub.sat (#135603)
- Closes #135557
1 parent 14cb8c5 commit fe54d1a

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,8 @@ void State::addInfoFor(BasicBlock &BB) {
11411141
break;
11421142
[[fallthrough]];
11431143
case Intrinsic::abs:
1144+
case Intrinsic::uadd_sat:
1145+
case Intrinsic::usub_sat:
11441146
WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
11451147
break;
11461148
}
@@ -1891,13 +1893,26 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
18911893
AddFact(CmpInst::ICMP_SGE, CB.Inst, X);
18921894
continue;
18931895
}
1894-
18951896
if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
18961897
Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
18971898
AddFact(Pred, MinMax, MinMax->getLHS());
18981899
AddFact(Pred, MinMax, MinMax->getRHS());
18991900
continue;
19001901
}
1902+
if (auto *USatI = dyn_cast<SaturatingInst>(CB.Inst)) {
1903+
switch (USatI->getIntrinsicID()) {
1904+
default:
1905+
llvm_unreachable("Unexpected intrinsic.");
1906+
case Intrinsic::uadd_sat:
1907+
AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
1908+
AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
1909+
break;
1910+
case Intrinsic::usub_sat:
1911+
AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
1912+
break;
1913+
}
1914+
continue;
1915+
}
19011916
}
19021917

19031918
Value *A = nullptr, *B = nullptr;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3+
4+
declare i64 @llvm.uadd.sat.i64(i64, i64)
5+
declare i64 @llvm.usub.sat.i64(i64, i64)
6+
7+
define i1 @uadd_sat_uge(i64 %a, i64 %b) {
8+
; CHECK-LABEL: define i1 @uadd_sat_uge(
9+
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
10+
; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 [[B]])
11+
; CHECK-NEXT: [[CMP:%.*]] = and i1 true, true
12+
; CHECK-NEXT: ret i1 [[CMP]]
13+
;
14+
%add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b)
15+
%cmp1 = icmp uge i64 %add.sat, %a
16+
%cmp2 = icmp uge i64 %add.sat, %b
17+
%cmp = and i1 %cmp1, %cmp2
18+
ret i1 %cmp
19+
}
20+
21+
define i1 @usub_sat_ule_lhs(i64 %a, i64 %b) {
22+
; CHECK-LABEL: define i1 @usub_sat_ule_lhs(
23+
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
24+
; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
25+
; CHECK-NEXT: ret i1 true
26+
;
27+
%sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
28+
%cmp = icmp ule i64 %sub.sat, %a
29+
ret i1 %cmp
30+
}
31+
32+
; Negative test
33+
define i1 @usub_sat_not_ule_rhs(i64 %a, i64 %b) {
34+
; CHECK-LABEL: define i1 @usub_sat_not_ule_rhs(
35+
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
36+
; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
37+
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[B]]
38+
; CHECK-NEXT: ret i1 [[CMP]]
39+
;
40+
%sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
41+
%cmp = icmp ule i64 %sub.sat, %b
42+
ret i1 %cmp
43+
}

0 commit comments

Comments
 (0)