Skip to content

Commit 6f8afaf

Browse files
[InstCombine] Fold A == MIN_INT ? B != MIN_INT : A < B to A < B (#120177)
This PR folds: `A == MIN_INT ? B != MIN_INT : A < B` to `A < B` `A == MAX_INT ? B != MAX_INT : A > B` to `A > B` Proof: https://alive2.llvm.org/ce/z/bR6E2s This helps in optimizing comparison of optional unsigned non-zero types in rust-lang/rust#49892. Rust compiler's current output: https://rust.godbolt.org/z/9fxfq3Gn8
1 parent 94837c8 commit 6f8afaf

File tree

3 files changed

+501
-1
lines changed

3 files changed

+501
-1
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -7144,7 +7144,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
71447144
NewOps[1], I->getFastMathFlags(), Q, MaxRecurse);
71457145
case Instruction::Select:
71467146
return simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q, MaxRecurse);
7147-
break;
71487147
case Instruction::GetElementPtr: {
71497148
auto *GEPI = cast<GetElementPtrInst>(I);
71507149
return simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0],

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,46 @@ static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
17811781
return nullptr;
17821782
}
17831783

1784+
/// `A == MIN_INT ? B != MIN_INT : A < B` --> `A < B`
1785+
/// `A == MAX_INT ? B != MAX_INT : A > B` --> `A > B`
1786+
static Instruction *foldSelectWithExtremeEqCond(Value *CmpLHS, Value *CmpRHS,
1787+
Value *TrueVal,
1788+
Value *FalseVal) {
1789+
Type *Ty = CmpLHS->getType();
1790+
1791+
if (Ty->isPtrOrPtrVectorTy())
1792+
return nullptr;
1793+
1794+
CmpPredicate Pred;
1795+
Value *B;
1796+
1797+
if (!match(FalseVal, m_c_ICmp(Pred, m_Specific(CmpLHS), m_Value(B))))
1798+
return nullptr;
1799+
1800+
Value *TValRHS;
1801+
if (!match(TrueVal, m_SpecificICmp(ICmpInst::ICMP_NE, m_Specific(B),
1802+
m_Value(TValRHS))))
1803+
return nullptr;
1804+
1805+
APInt C;
1806+
unsigned BitWidth = Ty->getScalarSizeInBits();
1807+
1808+
if (ICmpInst::isLT(Pred)) {
1809+
C = CmpInst::isSigned(Pred) ? APInt::getSignedMinValue(BitWidth)
1810+
: APInt::getMinValue(BitWidth);
1811+
} else if (ICmpInst::isGT(Pred)) {
1812+
C = CmpInst::isSigned(Pred) ? APInt::getSignedMaxValue(BitWidth)
1813+
: APInt::getMaxValue(BitWidth);
1814+
} else {
1815+
return nullptr;
1816+
}
1817+
1818+
if (!match(CmpRHS, m_SpecificInt(C)) || !match(TValRHS, m_SpecificInt(C)))
1819+
return nullptr;
1820+
1821+
return new ICmpInst(Pred, CmpLHS, B);
1822+
}
1823+
17841824
static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
17851825
InstCombinerImpl &IC) {
17861826
ICmpInst::Predicate Pred = ICI->getPredicate();
@@ -1795,6 +1835,10 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
17951835
if (Pred == ICmpInst::ICMP_NE)
17961836
std::swap(TrueVal, FalseVal);
17971837

1838+
if (Instruction *Res =
1839+
foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))
1840+
return Res;
1841+
17981842
// Transform (X == C) ? X : Y -> (X == C) ? C : Y
17991843
// specific handling for Bitwise operation.
18001844
// x&y -> (x|y) ^ (x^y) or (x|y) & ~(x^y)

0 commit comments

Comments
 (0)