Skip to content

Commit c9a4bc8

Browse files
committed
[InstCombine] Generalize foldAndOrOfICmpsUsingRanges to handle more cases.
1 parent 9630974 commit c9a4bc8

File tree

3 files changed

+49
-87
lines changed

3 files changed

+49
-87
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,74 +1320,49 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
13201320
Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,
13211321
ICmpInst *ICmp2,
13221322
bool IsAnd) {
1323-
CmpPredicate Pred1, Pred2;
1324-
Value *V1, *V2;
1325-
const APInt *C1, *C2;
1326-
if (!match(ICmp1, m_ICmp(Pred1, m_Value(V1), m_APInt(C1))) ||
1327-
!match(ICmp2, m_ICmp(Pred2, m_Value(V2), m_APInt(C2))))
1328-
return nullptr;
1329-
1330-
// Look through add of a constant offset on V1, V2, or both operands. This
1331-
// allows us to interpret the V + C' < C'' range idiom into a proper range.
1332-
const APInt *Offset1 = nullptr, *Offset2 = nullptr;
1333-
if (V1 != V2) {
1334-
Value *X;
1335-
if (match(V1, m_Add(m_Value(X), m_APInt(Offset1))))
1336-
V1 = X;
1337-
if (match(V2, m_Add(m_Value(X), m_APInt(Offset2))))
1338-
V2 = X;
1339-
}
1340-
1341-
// Look through and with a negative power of 2 mask on V1 or V2. This
1342-
// detects idioms of the form `(x == A) || ((x & Mask) == A + 1)` where A + 1
1343-
// is aligned to the mask and A + 1 >= |Mask|. This pattern corresponds to a
1344-
// contiguous range check, which can be folded into an addition and compare.
1345-
// The same applies for `(x != A) && ((x & Mask) != A + 1)`.
1346-
auto AreContiguousRangePredicates = [](CmpPredicate Pred1, CmpPredicate Pred2,
1347-
bool IsAnd) {
1348-
if (IsAnd)
1349-
return Pred1 == ICmpInst::ICMP_NE && Pred2 == ICmpInst::ICMP_NE;
1350-
return Pred1 == ICmpInst::ICMP_EQ && Pred2 == ICmpInst::ICMP_EQ;
1351-
};
1352-
const APInt *Mask1 = nullptr, *Mask2 = nullptr;
1353-
bool MatchedAnd1 = false, MatchedAnd2 = false;
1354-
if (V1 != V2 && AreContiguousRangePredicates(Pred1, Pred2, IsAnd)) {
1323+
auto MatchRangeCheck =
1324+
[](ICmpInst *ICmp) -> std::optional<std::pair<Value *, ConstantRange>> {
1325+
const APInt *C;
1326+
if (!match(ICmp->getOperand(1), m_APInt(C)))
1327+
return std::nullopt;
1328+
Value *LHS = ICmp->getOperand(0);
1329+
CmpPredicate Pred = ICmp->getPredicate();
13551330
Value *X;
1356-
if (match(V1, m_OneUse(m_And(m_Value(X), m_NegatedPower2(Mask1)))) &&
1357-
C1->getBitWidth() == C2->getBitWidth() && *C1 == *C2 + 1 &&
1358-
C1->uge(Mask1->abs()) && C1->isPowerOf2()) {
1359-
MatchedAnd1 = true;
1360-
V1 = X;
1361-
}
1362-
if (match(V2, m_OneUse(m_And(m_Value(X), m_NegatedPower2(Mask2)))) &&
1363-
C1->getBitWidth() == C2->getBitWidth() && *C2 == *C1 + 1 &&
1364-
C2->uge(Mask2->abs()) && C2->isPowerOf2()) {
1365-
MatchedAnd2 = true;
1366-
V2 = X;
1331+
// Match (x & NegPow2) ==/!= C
1332+
const APInt *Mask;
1333+
if (ICmpInst::isEquality(Pred) &&
1334+
match(LHS, m_OneUse(m_And(m_Value(X), m_NegatedPower2(Mask)))) &&
1335+
C->countr_zero() >= Mask->countr_zero()) {
1336+
ConstantRange CR{*C, *C - *Mask};
1337+
if (Pred == ICmpInst::ICMP_NE)
1338+
CR = CR.inverse();
1339+
return std::make_pair(X, CR);
13671340
}
1368-
}
1341+
ConstantRange CR = ConstantRange::makeExactICmpRegion(Pred, *C);
1342+
// Match (add X, C1) pred C
1343+
const APInt *C1;
1344+
if (match(LHS, m_AddLike(m_Value(X), m_APInt(C1))))
1345+
return std::make_pair(X, CR.subtract(*C1));
1346+
return std::make_pair(LHS, CR);
1347+
};
1348+
1349+
auto RC1 = MatchRangeCheck(ICmp1);
1350+
if (!RC1)
1351+
return nullptr;
13691352

1370-
if (V1 != V2)
1353+
auto RC2 = MatchRangeCheck(ICmp2);
1354+
if (!RC2)
13711355
return nullptr;
13721356

1373-
ConstantRange CR1 =
1374-
MatchedAnd1
1375-
? ConstantRange(*C1, *C1 - *Mask1)
1376-
: ConstantRange::makeExactICmpRegion(
1377-
IsAnd ? ICmpInst::getInverseCmpPredicate(Pred1) : Pred1, *C1);
1378-
if (Offset1)
1379-
CR1 = CR1.subtract(*Offset1);
1380-
1381-
ConstantRange CR2 =
1382-
MatchedAnd2
1383-
? ConstantRange(*C2, *C2 - *Mask2)
1384-
: ConstantRange::makeExactICmpRegion(
1385-
IsAnd ? ICmpInst::getInverseCmpPredicate(Pred2) : Pred2, *C2);
1386-
if (Offset2)
1387-
CR2 = CR2.subtract(*Offset2);
1388-
1389-
Type *Ty = V1->getType();
1390-
Value *NewV = V1;
1357+
if (RC1->first != RC2->first)
1358+
return nullptr;
1359+
1360+
Value *V = RC1->first;
1361+
auto CR1 = IsAnd ? RC1->second.inverse() : RC1->second;
1362+
auto CR2 = IsAnd ? RC2->second.inverse() : RC2->second;
1363+
1364+
Type *Ty = V->getType();
1365+
Value *NewV = V;
13911366
std::optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
13921367
if (!CR) {
13931368
if (!(ICmp1->hasOneUse() && ICmp2->hasOneUse()) || CR1.isWrappedSet() ||

llvm/test/Transforms/InstCombine/and-or-icmps.ll

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3672,13 +3672,11 @@ define i1 @neg_or_icmp_eq_double_and_pow2(i32 %x) {
36723672
ret i1 %ret
36733673
}
36743674

3675-
define i1 @neg_select_icmp_eq_and_pow2(i32 %x) {
3676-
; CHECK-LABEL: @neg_select_icmp_eq_and_pow2(
3677-
; CHECK-NEXT: [[ICMP1:%.*]] = icmp sgt i32 [[X:%.*]], 127
3678-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], -32
3679-
; CHECK-NEXT: [[ICMP2:%.*]] = icmp eq i32 [[AND]], 128
3680-
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[ICMP1]], [[ICMP2]]
3681-
; CHECK-NEXT: ret i1 [[TMP1]]
3675+
define i1 @implied_select_icmp_eq_and_pow2(i32 %x) {
3676+
; CHECK-LABEL: @implied_select_icmp_eq_and_pow2(
3677+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -32
3678+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 128
3679+
; CHECK-NEXT: ret i1 [[TMP2]]
36823680
;
36833681
%icmp1 = icmp sgt i32 %x, 127
36843682
%and = and i32 %x, -32
@@ -3689,11 +3687,9 @@ define i1 @neg_select_icmp_eq_and_pow2(i32 %x) {
36893687

36903688
define i1 @implied_range_check(i8 %a) {
36913689
; CHECK-LABEL: @implied_range_check(
3692-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], 5
3693-
; CHECK-NEXT: [[MASKED:%.*]] = and i8 [[A]], -2
3690+
; CHECK-NEXT: [[MASKED:%.*]] = and i8 [[A:%.*]], -2
36943691
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[MASKED]], 2
3695-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
3696-
; CHECK-NEXT: ret i1 [[AND]]
3692+
; CHECK-NEXT: ret i1 [[CMP2]]
36973693
;
36983694
%cmp1 = icmp ult i8 %a, 5
36993695
%masked = and i8 %a, -2
@@ -3704,11 +3700,8 @@ define i1 @implied_range_check(i8 %a) {
37043700

37053701
define i1 @merge_range_check_and(i8 %a) {
37063702
; CHECK-LABEL: @merge_range_check_and(
3707-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], 3
3708-
; CHECK-NEXT: [[MASKED:%.*]] = and i8 [[A]], -2
3709-
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[MASKED]], 2
3710-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
3711-
; CHECK-NEXT: ret i1 [[AND]]
3703+
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[MASKED:%.*]], 2
3704+
; CHECK-NEXT: ret i1 [[CMP2]]
37123705
;
37133706
%cmp1 = icmp ult i8 %a, 3
37143707
%masked = and i8 %a, -2
@@ -3719,10 +3712,7 @@ define i1 @merge_range_check_and(i8 %a) {
37193712

37203713
define i1 @merge_range_check_or(i8 %a) {
37213714
; CHECK-LABEL: @merge_range_check_or(
3722-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], 3
3723-
; CHECK-NEXT: [[MASKED:%.*]] = and i8 [[A]], -2
3724-
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[MASKED]], 2
3725-
; CHECK-NEXT: [[AND:%.*]] = or i1 [[CMP1]], [[CMP2]]
3715+
; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[A:%.*]], 4
37263716
; CHECK-NEXT: ret i1 [[AND]]
37273717
;
37283718
%cmp1 = icmp ult i8 %a, 3

llvm/test/Transforms/InstCombine/icmp-range.ll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,10 +1678,7 @@ define i1 @icmp_slt_sext_ne_otherwise_nofold(i32 %a) {
16781678
; tests from PR59555
16791679
define i1 @isFloat(i64 %0) {
16801680
; CHECK-LABEL: @isFloat(
1681-
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0:%.*]], 281474976710655
1682-
; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP0]], -281474976710656
1683-
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[TMP3]], 281474976710656
1684-
; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[TMP4]]
1681+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP0:%.*]], 562949953421311
16851682
; CHECK-NEXT: ret i1 [[TMP5]]
16861683
;
16871684
%2 = icmp ugt i64 %0, 281474976710655

0 commit comments

Comments
 (0)