Skip to content

Commit 25d7b61

Browse files
committed
[InstCombine] Convert logical and/or with icmp samesign into bitwise ops
1 parent 3dec6fe commit 25d7b61

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3115,6 +3115,39 @@ static Instruction *foldNestedSelects(SelectInst &OuterSelVal,
31153115
!IsAndVariant ? SelInner : InnerSel.FalseVal);
31163116
}
31173117

3118+
/// Return true if V is poison or \p Expected given that ValAssumedPoison is
3119+
/// already poison. For example, if ValAssumedPoison is `icmp samesign X, 10`
3120+
/// and V is `icmp ne X, 5`, impliesPoisonOrCond returns true.
3121+
static bool impliesPoisonOrCond(const Value *ValAssumedPoison, const Value *V,
3122+
bool Expected) {
3123+
if (impliesPoison(ValAssumedPoison, V))
3124+
return true;
3125+
3126+
// Handle the case that ValAssumedPoison is `icmp samesign pred X, C1` and V
3127+
// is `icmp pred X, C2`, where C1 is well-defined.
3128+
if (auto *ICmp = dyn_cast<ICmpInst>(ValAssumedPoison)) {
3129+
Value *LHS = ICmp->getOperand(0);
3130+
const APInt *RHSC1;
3131+
const APInt *RHSC2;
3132+
ICmpInst::Predicate Pred;
3133+
if (ICmp->hasSameSign() &&
3134+
match(ICmp->getOperand(1), m_APIntForbidPoison(RHSC1)) &&
3135+
match(V, m_ICmp(Pred, m_Specific(LHS), m_APIntAllowPoison(RHSC2)))) {
3136+
unsigned BitWidth = RHSC1->getBitWidth();
3137+
ConstantRange CRX =
3138+
RHSC1->isNonNegative()
3139+
? ConstantRange(APInt::getSignedMinValue(BitWidth),
3140+
APInt::getZero(BitWidth))
3141+
: ConstantRange(APInt::getZero(BitWidth),
3142+
APInt::getSignedMinValue(BitWidth));
3143+
return CRX.icmp(Expected ? Pred : ICmpInst::getInversePredicate(Pred),
3144+
*RHSC2);
3145+
}
3146+
}
3147+
3148+
return false;
3149+
}
3150+
31183151
Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
31193152
Value *CondVal = SI.getCondition();
31203153
Value *TrueVal = SI.getTrueValue();
@@ -3136,13 +3169,13 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
31363169
// checks whether folding it does not convert a well-defined value into
31373170
// poison.
31383171
if (match(TrueVal, m_One())) {
3139-
if (impliesPoison(FalseVal, CondVal)) {
3172+
if (impliesPoisonOrCond(FalseVal, CondVal, /*Expected=*/false)) {
31403173
// Change: A = select B, true, C --> A = or B, C
31413174
return BinaryOperator::CreateOr(CondVal, FalseVal);
31423175
}
31433176

31443177
if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_One(), m_Value(B)))) &&
3145-
impliesPoison(FalseVal, B)) {
3178+
impliesPoisonOrCond(FalseVal, B, /*Expected=*/false)) {
31463179
// (A || B) || C --> A || (B | C)
31473180
return replaceInstUsesWith(
31483181
SI, Builder.CreateLogicalOr(A, Builder.CreateOr(B, FalseVal)));
@@ -3178,13 +3211,13 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
31783211
}
31793212

31803213
if (match(FalseVal, m_Zero())) {
3181-
if (impliesPoison(TrueVal, CondVal)) {
3214+
if (impliesPoisonOrCond(TrueVal, CondVal, /*Expected=*/true)) {
31823215
// Change: A = select B, C, false --> A = and B, C
31833216
return BinaryOperator::CreateAnd(CondVal, TrueVal);
31843217
}
31853218

31863219
if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_Value(B), m_Zero()))) &&
3187-
impliesPoison(TrueVal, B)) {
3220+
impliesPoisonOrCond(TrueVal, B, /*Expected=*/true)) {
31883221
// (A && B) && C --> A && (B & C)
31893222
return replaceInstUsesWith(
31903223
SI, Builder.CreateLogicalAnd(A, Builder.CreateAnd(B, TrueVal)));

llvm/test/Transforms/InstCombine/logical-select.ll

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ define i1 @test_logical_and_icmp_samesign(i8 %x) {
15261526
; CHECK-LABEL: @test_logical_and_icmp_samesign(
15271527
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 9
15281528
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult i8 [[X]], 11
1529-
; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false
1529+
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
15301530
; CHECK-NEXT: ret i1 [[AND]]
15311531
;
15321532
%cmp1 = icmp ne i8 %x, 9
@@ -1539,7 +1539,7 @@ define i1 @test_logical_or_icmp_samesign(i8 %x) {
15391539
; CHECK-LABEL: @test_logical_or_icmp_samesign(
15401540
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], -9
15411541
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult i8 [[X]], -11
1542-
; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
1542+
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
15431543
; CHECK-NEXT: ret i1 [[OR]]
15441544
;
15451545
%cmp1 = icmp eq i8 %x, -9
@@ -1550,10 +1550,8 @@ define i1 @test_logical_or_icmp_samesign(i8 %x) {
15501550

15511551
define i1 @test_double_logical_and_icmp_samesign1(i1 %cond, i32 %y) {
15521552
; CHECK-LABEL: @test_double_logical_and_icmp_samesign1(
1553-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[Y:%.*]], 5
1554-
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 false
1555-
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult i32 [[Y]], 4
1556-
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[SEL1]], i1 [[CMP2]], i1 false
1553+
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult i32 [[Y:%.*]], 4
1554+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[SEL1:%.*]], i1 [[CMP2]], i1 false
15571555
; CHECK-NEXT: ret i1 [[SEL2]]
15581556
;
15591557
%cmp1 = icmp ne i32 %y, 5
@@ -1565,10 +1563,9 @@ define i1 @test_double_logical_and_icmp_samesign1(i1 %cond, i32 %y) {
15651563

15661564
define i1 @test_double_logical_and_icmp_samesign2(i1 %cond, i32 %y) {
15671565
; CHECK-LABEL: @test_double_logical_and_icmp_samesign2(
1568-
; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ugt i32 [[Y:%.*]], 65535
1569-
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 false
1570-
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult i32 [[Y]], 1114112
1571-
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[SEL1]], i1 [[CMP2]], i1 false
1566+
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], -65536
1567+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[TMP1]], 1048576
1568+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[SEL1:%.*]], i1 [[CMP2]], i1 false
15721569
; CHECK-NEXT: ret i1 [[SEL2]]
15731570
;
15741571
%cmp1 = icmp samesign ugt i32 %y, 65535
@@ -1582,7 +1579,7 @@ define <2 x i1> @test_logical_and_icmp_samesign_vec(<2 x i8> %x) {
15821579
; CHECK-LABEL: @test_logical_and_icmp_samesign_vec(
15831580
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i8> [[X:%.*]], splat (i8 9)
15841581
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult <2 x i8> [[X]], splat (i8 11)
1585-
; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[CMP1]], <2 x i1> [[CMP2]], <2 x i1> zeroinitializer
1582+
; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
15861583
; CHECK-NEXT: ret <2 x i1> [[AND]]
15871584
;
15881585
%cmp1 = icmp ne <2 x i8> %x, splat(i8 9)
@@ -1595,7 +1592,7 @@ define <2 x i1> @test_logical_and_icmp_samesign_vec_with_poison_cond(<2 x i8> %x
15951592
; CHECK-LABEL: @test_logical_and_icmp_samesign_vec_with_poison_cond(
15961593
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i8> [[X:%.*]], <i8 9, i8 poison>
15971594
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ult <2 x i8> [[X]], splat (i8 11)
1598-
; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[CMP1]], <2 x i1> [[CMP2]], <2 x i1> zeroinitializer
1595+
; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
15991596
; CHECK-NEXT: ret <2 x i1> [[AND]]
16001597
;
16011598
%cmp1 = icmp ne <2 x i8> %x, <i8 9, i8 poison>

0 commit comments

Comments
 (0)