Skip to content

Commit 92a11eb

Browse files
committed
[ConstraintElim] Add facts implied by MinMaxIntrinsic
Fixes #63896 and rust-lang/rust#113757. This patch adds facts implied by llvm.smin/smax/umin/umax intrinsics. Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D155412
1 parent 047273f commit 92a11eb

File tree

2 files changed

+37
-21
lines changed

2 files changed

+37
-21
lines changed

Diff for: llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

+26-10
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,11 @@ void State::addInfoFor(BasicBlock &BB) {
784784
continue;
785785
}
786786

787+
if (isa<MinMaxIntrinsic>(&I)) {
788+
WorkList.push_back(FactOrCheck::getFact(DT.getNode(&BB), &I));
789+
continue;
790+
}
791+
787792
Value *Cond;
788793
// For now, just handle assumes with a single compare as condition.
789794
if (match(&I, m_Intrinsic<Intrinsic::assume>(m_Value(Cond))) &&
@@ -1363,22 +1368,14 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
13631368
}
13641369

13651370
LLVM_DEBUG(dbgs() << "fact to add to the system: " << *CB.Inst << "\n");
1366-
ICmpInst::Predicate Pred;
1367-
Value *A, *B;
1368-
Value *Cmp = CB.Inst;
1369-
match(Cmp, m_Intrinsic<Intrinsic::assume>(m_Value(Cmp)));
1370-
if (match(Cmp, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
1371+
auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B) {
13711372
if (Info.getCS(CmpInst::isSigned(Pred)).size() > MaxRows) {
13721373
LLVM_DEBUG(
13731374
dbgs()
13741375
<< "Skip adding constraint because system has too many rows.\n");
1375-
continue;
1376+
return;
13761377
}
13771378

1378-
// Use the inverse predicate if required.
1379-
if (CB.Not)
1380-
Pred = CmpInst::getInversePredicate(Pred);
1381-
13821379
Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
13831380
if (ReproducerModule && DFSInStack.size() > ReproducerCondStack.size())
13841381
ReproducerCondStack.emplace_back(Pred, A, B);
@@ -1394,6 +1391,25 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT,
13941391
nullptr, nullptr);
13951392
}
13961393
}
1394+
};
1395+
1396+
ICmpInst::Predicate Pred;
1397+
if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
1398+
Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
1399+
AddFact(Pred, MinMax, MinMax->getLHS());
1400+
AddFact(Pred, MinMax, MinMax->getRHS());
1401+
continue;
1402+
}
1403+
1404+
Value *A, *B;
1405+
Value *Cmp = CB.Inst;
1406+
match(Cmp, m_Intrinsic<Intrinsic::assume>(m_Value(Cmp)));
1407+
if (match(Cmp, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
1408+
// Use the inverse predicate if required.
1409+
if (CB.Not)
1410+
Pred = CmpInst::getInversePredicate(Pred);
1411+
1412+
AddFact(Pred, A, B);
13971413
}
13981414
}
13991415

Diff for: llvm/test/Transforms/ConstraintElimination/minmax.ll

+11-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ define i1 @umax_ugt(i32 %x, i32 %y) {
1111
; CHECK: if:
1212
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[Y]], [[X]]
1313
; CHECK-NEXT: [[CMP3:%.*]] = icmp uge i32 [[Y]], [[X]]
14-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
14+
; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true
1515
; CHECK-NEXT: ret i1 [[RET]]
1616
; CHECK: end:
1717
; CHECK-NEXT: ret i1 false
@@ -39,7 +39,7 @@ define i1 @umax_uge(i32 %x, i32 %y) {
3939
; CHECK: if:
4040
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[Y]], [[X]]
4141
; CHECK-NEXT: [[CMP3:%.*]] = icmp uge i32 [[Y]], [[X]]
42-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
42+
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true
4343
; CHECK-NEXT: ret i1 [[RET]]
4444
; CHECK: end:
4545
; CHECK-NEXT: ret i1 false
@@ -67,7 +67,7 @@ define i1 @umin_ult(i32 %x, i32 %y) {
6767
; CHECK: if:
6868
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y]], [[X]]
6969
; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[Y]], [[X]]
70-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
70+
; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true
7171
; CHECK-NEXT: ret i1 [[RET]]
7272
; CHECK: end:
7373
; CHECK-NEXT: ret i1 false
@@ -95,7 +95,7 @@ define i1 @umin_ule(i32 %x, i32 %y) {
9595
; CHECK: if:
9696
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y]], [[X]]
9797
; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[Y]], [[X]]
98-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
98+
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true
9999
; CHECK-NEXT: ret i1 [[RET]]
100100
; CHECK: end:
101101
; CHECK-NEXT: ret i1 false
@@ -123,7 +123,7 @@ define i1 @smax_sgt(i32 %x, i32 %y) {
123123
; CHECK: if:
124124
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y]], [[X]]
125125
; CHECK-NEXT: [[CMP3:%.*]] = icmp sge i32 [[Y]], [[X]]
126-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
126+
; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true
127127
; CHECK-NEXT: ret i1 [[RET]]
128128
; CHECK: end:
129129
; CHECK-NEXT: ret i1 false
@@ -151,7 +151,7 @@ define i1 @smax_sge(i32 %x, i32 %y) {
151151
; CHECK: if:
152152
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[Y]], [[X]]
153153
; CHECK-NEXT: [[CMP3:%.*]] = icmp sge i32 [[Y]], [[X]]
154-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
154+
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true
155155
; CHECK-NEXT: ret i1 [[RET]]
156156
; CHECK: end:
157157
; CHECK-NEXT: ret i1 false
@@ -179,7 +179,7 @@ define i1 @smin_slt(i32 %x, i32 %y) {
179179
; CHECK: if:
180180
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], [[X]]
181181
; CHECK-NEXT: [[CMP3:%.*]] = icmp sle i32 [[Y]], [[X]]
182-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
182+
; CHECK-NEXT: [[RET:%.*]] = xor i1 true, true
183183
; CHECK-NEXT: ret i1 [[RET]]
184184
; CHECK: end:
185185
; CHECK-NEXT: ret i1 false
@@ -207,7 +207,7 @@ define i1 @smin_sle(i32 %x, i32 %y) {
207207
; CHECK: if:
208208
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], [[X]]
209209
; CHECK-NEXT: [[CMP3:%.*]] = icmp sle i32 [[Y]], [[X]]
210-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], [[CMP3]]
210+
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP2]], true
211211
; CHECK-NEXT: ret i1 [[RET]]
212212
; CHECK: end:
213213
; CHECK-NEXT: ret i1 false
@@ -235,7 +235,7 @@ define i1 @umax_uge_ugt_with_add_nuw(i32 %x, i32 %y) {
235235
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
236236
; CHECK: if:
237237
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[Y]], [[X]]
238-
; CHECK-NEXT: ret i1 [[CMP2]]
238+
; CHECK-NEXT: ret i1 true
239239
; CHECK: end:
240240
; CHECK-NEXT: ret i1 false
241241
;
@@ -297,7 +297,7 @@ define i1 @umax_ugt_ugt_both(i32 %x, i32 %y, i32 %z) {
297297
; CHECK: if:
298298
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[Z]], [[X]]
299299
; CHECK-NEXT: [[CMP3:%.*]] = icmp ugt i32 [[Z]], [[Y]]
300-
; CHECK-NEXT: [[AND:%.*]] = xor i1 [[CMP2]], [[CMP3]]
300+
; CHECK-NEXT: [[AND:%.*]] = xor i1 true, true
301301
; CHECK-NEXT: ret i1 [[AND]]
302302
; CHECK: end:
303303
; CHECK-NEXT: ret i1 false
@@ -323,7 +323,7 @@ define i1 @smin_branchless(i32 %x, i32 %y) {
323323
; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y]])
324324
; CHECK-NEXT: [[CMP1:%.*]] = icmp sle i32 [[MIN]], [[X]]
325325
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[MIN]], [[X]]
326-
; CHECK-NEXT: [[RET:%.*]] = xor i1 [[CMP1]], [[CMP2]]
326+
; CHECK-NEXT: [[RET:%.*]] = xor i1 true, false
327327
; CHECK-NEXT: ret i1 [[RET]]
328328
;
329329
entry:

0 commit comments

Comments
 (0)