Skip to content

Commit bb12ded

Browse files
committed
[InstCombine] Refactor and/or of icmp with constant (NFCI)
Rather than testing for many specific combinations of predicates and values, compute the exact icmp regions for both comparisons and check whether they union/intersect exactly. If they do, construct the equivalent icmp for the new range. Assuming that the existing code handled all possible cases, this should be NFC. Differential Revision: https://reviews.llvm.org/D113367
1 parent 8d499bd commit bb12ded

File tree

1 file changed

+30
-191
lines changed

1 file changed

+30
-191
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 30 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,107 +1322,23 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS,
13221322
if (LHS0 != RHS0)
13231323
return nullptr;
13241324

1325-
// ICMP_[US][GL]E X, C is folded to ICMP_[US][GL]T elsewhere.
1326-
if (PredL == ICmpInst::ICMP_UGE || PredL == ICmpInst::ICMP_ULE ||
1327-
PredR == ICmpInst::ICMP_UGE || PredR == ICmpInst::ICMP_ULE ||
1328-
PredL == ICmpInst::ICMP_SGE || PredL == ICmpInst::ICMP_SLE ||
1329-
PredR == ICmpInst::ICMP_SGE || PredR == ICmpInst::ICMP_SLE)
1325+
ConstantRange CR1 =
1326+
ConstantRange::makeExactICmpRegion(PredL, LHSC->getValue());
1327+
ConstantRange CR2 =
1328+
ConstantRange::makeExactICmpRegion(PredR, RHSC->getValue());
1329+
Optional<ConstantRange> CR = CR1.exactIntersectWith(CR2);
1330+
if (!CR)
13301331
return nullptr;
13311332

1332-
// We can't fold (ugt x, C) & (sgt x, C2).
1333-
if (!predicatesFoldable(PredL, PredR))
1334-
return nullptr;
1335-
1336-
// Ensure that the larger constant is on the RHS.
1337-
bool ShouldSwap;
1338-
if (CmpInst::isSigned(PredL) ||
1339-
(ICmpInst::isEquality(PredL) && CmpInst::isSigned(PredR)))
1340-
ShouldSwap = LHSC->getValue().sgt(RHSC->getValue());
1341-
else
1342-
ShouldSwap = LHSC->getValue().ugt(RHSC->getValue());
1343-
1344-
if (ShouldSwap) {
1345-
std::swap(LHS, RHS);
1346-
std::swap(LHSC, RHSC);
1347-
std::swap(PredL, PredR);
1348-
}
1349-
1350-
// At this point, we know we have two icmp instructions
1351-
// comparing a value against two constants and and'ing the result
1352-
// together. Because of the above check, we know that we only have
1353-
// icmp eq, icmp ne, icmp [su]lt, and icmp [SU]gt here. We also know
1354-
// (from the icmp folding check above), that the two constants
1355-
// are not equal and that the larger constant is on the RHS
1356-
assert(LHSC != RHSC && "Compares not folded above?");
1357-
1358-
switch (PredL) {
1359-
default:
1360-
llvm_unreachable("Unknown integer condition code!");
1361-
case ICmpInst::ICMP_NE:
1362-
switch (PredR) {
1363-
default:
1364-
llvm_unreachable("Unknown integer condition code!");
1365-
case ICmpInst::ICMP_ULT:
1366-
// (X != 13 & X u< 14) -> X < 13
1367-
if (LHSC->getValue() == (RHSC->getValue() - 1))
1368-
return Builder.CreateICmpULT(LHS0, LHSC);
1369-
if (LHSC->isZero()) // (X != 0 & X u< C) -> X-1 u< C-1
1370-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(),
1371-
false, true);
1372-
break; // (X != 13 & X u< 15) -> no change
1373-
case ICmpInst::ICMP_SLT:
1374-
// (X != 13 & X s< 14) -> X < 13
1375-
if (LHSC->getValue() == (RHSC->getValue() - 1))
1376-
return Builder.CreateICmpSLT(LHS0, LHSC);
1377-
// (X != INT_MIN & X s< C) -> X-(INT_MIN+1) u< (C-(INT_MIN+1))
1378-
if (LHSC->isMinValue(true))
1379-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(),
1380-
true, true);
1381-
break; // (X != 13 & X s< 15) -> no change
1382-
case ICmpInst::ICMP_NE:
1383-
// Potential folds for this case should already be handled.
1384-
break;
1385-
}
1386-
break;
1387-
case ICmpInst::ICMP_UGT:
1388-
switch (PredR) {
1389-
default:
1390-
llvm_unreachable("Unknown integer condition code!");
1391-
case ICmpInst::ICMP_NE:
1392-
// (X u> 13 & X != 14) -> X u> 14
1393-
if (RHSC->getValue() == (LHSC->getValue() + 1))
1394-
return Builder.CreateICmp(PredL, LHS0, RHSC);
1395-
// X u> C & X != UINT_MAX -> (X-(C+1)) u< UINT_MAX-(C+1)
1396-
if (RHSC->isMaxValue(false))
1397-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(),
1398-
false, true);
1399-
break; // (X u> 13 & X != 15) -> no change
1400-
case ICmpInst::ICMP_ULT: // (X u> 13 & X u< 15) -> (X-14) u< 1
1401-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(),
1402-
false, true);
1403-
}
1404-
break;
1405-
case ICmpInst::ICMP_SGT:
1406-
switch (PredR) {
1407-
default:
1408-
llvm_unreachable("Unknown integer condition code!");
1409-
case ICmpInst::ICMP_NE:
1410-
// (X s> 13 & X != 14) -> X s> 14
1411-
if (RHSC->getValue() == (LHSC->getValue() + 1))
1412-
return Builder.CreateICmp(PredL, LHS0, RHSC);
1413-
// X s> C & X != INT_MAX -> (X-(C+1)) u< INT_MAX-(C+1)
1414-
if (RHSC->isMaxValue(true))
1415-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(),
1416-
true, true);
1417-
break; // (X s> 13 & X != 15) -> no change
1418-
case ICmpInst::ICMP_SLT: // (X s> 13 & X s< 15) -> (X-14) u< 1
1419-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(), true,
1420-
true);
1421-
}
1422-
break;
1423-
}
1424-
1425-
return nullptr;
1333+
CmpInst::Predicate Pred;
1334+
APInt NewRHS, Offset;
1335+
CR->getEquivalentICmp(Pred, NewRHS, Offset);
1336+
1337+
Type *Ty = LHS0->getType();
1338+
Value *NewLHS = LHS0;
1339+
if (Offset != 0)
1340+
NewLHS = Builder.CreateAdd(NewLHS, ConstantInt::get(Ty, Offset));
1341+
return Builder.CreateICmp(Pred, NewLHS, ConstantInt::get(Ty, NewRHS));
14261342
}
14271343

14281344
Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
@@ -2551,100 +2467,23 @@ Value *InstCombinerImpl::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
25512467
if (LHS0 != RHS0)
25522468
return nullptr;
25532469

2554-
// ICMP_[US][GL]E X, C is folded to ICMP_[US][GL]T elsewhere.
2555-
if (PredL == ICmpInst::ICMP_UGE || PredL == ICmpInst::ICMP_ULE ||
2556-
PredR == ICmpInst::ICMP_UGE || PredR == ICmpInst::ICMP_ULE ||
2557-
PredL == ICmpInst::ICMP_SGE || PredL == ICmpInst::ICMP_SLE ||
2558-
PredR == ICmpInst::ICMP_SGE || PredR == ICmpInst::ICMP_SLE)
2470+
ConstantRange CR1 =
2471+
ConstantRange::makeExactICmpRegion(PredL, LHSC->getValue());
2472+
ConstantRange CR2 =
2473+
ConstantRange::makeExactICmpRegion(PredR, RHSC->getValue());
2474+
Optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
2475+
if (!CR)
25592476
return nullptr;
25602477

2561-
// We can't fold (ugt x, C) | (sgt x, C2).
2562-
if (!predicatesFoldable(PredL, PredR))
2563-
return nullptr;
2564-
2565-
// Ensure that the larger constant is on the RHS.
2566-
bool ShouldSwap;
2567-
if (CmpInst::isSigned(PredL) ||
2568-
(ICmpInst::isEquality(PredL) && CmpInst::isSigned(PredR)))
2569-
ShouldSwap = LHSC->getValue().sgt(RHSC->getValue());
2570-
else
2571-
ShouldSwap = LHSC->getValue().ugt(RHSC->getValue());
2572-
2573-
if (ShouldSwap) {
2574-
std::swap(LHS, RHS);
2575-
std::swap(LHSC, RHSC);
2576-
std::swap(PredL, PredR);
2577-
}
2578-
2579-
// At this point, we know we have two icmp instructions
2580-
// comparing a value against two constants and or'ing the result
2581-
// together. Because of the above check, we know that we only have
2582-
// ICMP_EQ, ICMP_NE, ICMP_LT, and ICMP_GT here. We also know (from the
2583-
// icmp folding check above), that the two constants are not
2584-
// equal.
2585-
assert(LHSC != RHSC && "Compares not folded above?");
2586-
2587-
switch (PredL) {
2588-
default:
2589-
llvm_unreachable("Unknown integer condition code!");
2590-
case ICmpInst::ICMP_EQ:
2591-
switch (PredR) {
2592-
default:
2593-
llvm_unreachable("Unknown integer condition code!");
2594-
case ICmpInst::ICMP_EQ:
2595-
// Potential folds for this case should already be handled.
2596-
break;
2597-
case ICmpInst::ICMP_UGT:
2598-
// (X == 0 || X u> C) -> (X-1) u>= C
2599-
if (LHSC->isMinValue(false))
2600-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue() + 1,
2601-
false, false);
2602-
// (X == 13 | X u> 14) -> no change
2603-
break;
2604-
case ICmpInst::ICMP_SGT:
2605-
// (X == INT_MIN || X s> C) -> (X-(INT_MIN+1)) u>= C-INT_MIN
2606-
if (LHSC->isMinValue(true))
2607-
return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue() + 1,
2608-
true, false);
2609-
// (X == 13 | X s> 14) -> no change
2610-
break;
2611-
}
2612-
break;
2613-
case ICmpInst::ICMP_ULT:
2614-
switch (PredR) {
2615-
default:
2616-
llvm_unreachable("Unknown integer condition code!");
2617-
case ICmpInst::ICMP_EQ: // (X u< 13 | X == 14) -> no change
2618-
// (X u< C || X == UINT_MAX) => (X-C) u>= UINT_MAX-C
2619-
if (RHSC->isMaxValue(false))
2620-
return insertRangeTest(LHS0, LHSC->getValue(), RHSC->getValue(),
2621-
false, false);
2622-
break;
2623-
case ICmpInst::ICMP_UGT: // (X u< 13 | X u> 15) -> (X-13) u> 2
2624-
assert(!RHSC->isMaxValue(false) && "Missed icmp simplification");
2625-
return insertRangeTest(LHS0, LHSC->getValue(), RHSC->getValue() + 1,
2626-
false, false);
2627-
}
2628-
break;
2629-
case ICmpInst::ICMP_SLT:
2630-
switch (PredR) {
2631-
default:
2632-
llvm_unreachable("Unknown integer condition code!");
2633-
case ICmpInst::ICMP_EQ:
2634-
// (X s< C || X == INT_MAX) => (X-C) u>= INT_MAX-C
2635-
if (RHSC->isMaxValue(true))
2636-
return insertRangeTest(LHS0, LHSC->getValue(), RHSC->getValue(),
2637-
true, false);
2638-
// (X s< 13 | X == 14) -> no change
2639-
break;
2640-
case ICmpInst::ICMP_SGT: // (X s< 13 | X s> 15) -> (X-13) u> 2
2641-
assert(!RHSC->isMaxValue(true) && "Missed icmp simplification");
2642-
return insertRangeTest(LHS0, LHSC->getValue(), RHSC->getValue() + 1, true,
2643-
false);
2644-
}
2645-
break;
2646-
}
2647-
return nullptr;
2478+
CmpInst::Predicate Pred;
2479+
APInt NewRHS, Offset;
2480+
CR->getEquivalentICmp(Pred, NewRHS, Offset);
2481+
2482+
Type *Ty = LHS0->getType();
2483+
Value *NewLHS = LHS0;
2484+
if (Offset != 0)
2485+
NewLHS = Builder.CreateAdd(NewLHS, ConstantInt::get(Ty, Offset));
2486+
return Builder.CreateICmp(Pred, NewLHS, ConstantInt::get(Ty, NewRHS));
26482487
}
26492488

26502489
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches

0 commit comments

Comments
 (0)