Skip to content

Commit c497efb

Browse files
authored
[InstCombine] Convert logical and/or with trunc nuw to i1 into bitwise ops (#198178)
if it is know that `trunc nuw to i1 ` can not be poison logical and/or can be folded to bitwise ops. proof https://alive2.llvm.org/ce/z/xQ2Sj-
1 parent 0e92b55 commit c497efb

2 files changed

Lines changed: 68 additions & 5 deletions

File tree

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,7 +3653,7 @@ static Instruction *foldNestedSelects(SelectInst &OuterSelVal,
36533653
/// already poison. For example, if ValAssumedPoison is `icmp samesign X, 10`
36543654
/// and V is `icmp ne X, 5`, impliesPoisonOrCond returns true.
36553655
static bool impliesPoisonOrCond(const Value *ValAssumedPoison, const Value *V,
3656-
bool Expected) {
3656+
bool Expected, const SimplifyQuery &SQ) {
36573657
if (impliesPoison(ValAssumedPoison, V))
36583658
return true;
36593659

@@ -3678,6 +3678,14 @@ static bool impliesPoisonOrCond(const Value *ValAssumedPoison, const Value *V,
36783678
*RHSC2);
36793679
}
36803680
}
3681+
Value *A;
3682+
if (match(ValAssumedPoison, m_NUWTrunc(m_Value(A))) &&
3683+
isGuaranteedNotToBePoison(A)) {
3684+
assert(ValAssumedPoison->getType()->isIntOrIntVectorTy(1));
3685+
return computeKnownBits(
3686+
A, SQ.getWithInstruction(cast<Instruction>(ValAssumedPoison)))
3687+
.getMaxValue() == 1;
3688+
}
36813689

36823690
return false;
36833691
}
@@ -3703,13 +3711,13 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
37033711
// checks whether folding it does not convert a well-defined value into
37043712
// poison.
37053713
if (match(TrueVal, m_One())) {
3706-
if (impliesPoisonOrCond(FalseVal, CondVal, /*Expected=*/false)) {
3714+
if (impliesPoisonOrCond(FalseVal, CondVal, /*Expected=*/false, SQ)) {
37073715
// Change: A = select B, true, C --> A = or B, C
37083716
return BinaryOperator::CreateOr(CondVal, FalseVal);
37093717
}
37103718

37113719
if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_One(), m_Value(B)))) &&
3712-
impliesPoisonOrCond(FalseVal, B, /*Expected=*/false)) {
3720+
impliesPoisonOrCond(FalseVal, B, /*Expected=*/false, SQ)) {
37133721
// (A || B) || C --> A || (B | C)
37143722
Value *LOr = Builder.CreateLogicalOr(A, Builder.CreateOr(B, FalseVal));
37153723
if (auto *I = dyn_cast<Instruction>(LOr)) {
@@ -3749,13 +3757,13 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
37493757
}
37503758

37513759
if (match(FalseVal, m_Zero())) {
3752-
if (impliesPoisonOrCond(TrueVal, CondVal, /*Expected=*/true)) {
3760+
if (impliesPoisonOrCond(TrueVal, CondVal, /*Expected=*/true, SQ)) {
37533761
// Change: A = select B, C, false --> A = and B, C
37543762
return BinaryOperator::CreateAnd(CondVal, TrueVal);
37553763
}
37563764

37573765
if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_Value(B), m_Zero()))) &&
3758-
impliesPoisonOrCond(TrueVal, B, /*Expected=*/true)) {
3766+
impliesPoisonOrCond(TrueVal, B, /*Expected=*/true, SQ)) {
37593767
// (A && B) && C --> A && (B & C)
37603768
Value *LAnd = Builder.CreateLogicalAnd(A, Builder.CreateAnd(B, TrueVal));
37613769
if (auto *I = dyn_cast<Instruction>(LAnd)) {

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,3 +1637,58 @@ define <2 x i1> @test_logical_and_icmp_samesign_vec_with_poison_tv(<2 x i8> %x)
16371637
%and = select <2 x i1> %cmp1, <2 x i1> %cmp2, <2 x i1> zeroinitializer
16381638
ret <2 x i1> %and
16391639
}
1640+
1641+
define i1 @test_logical_and_trunc_nuw(i1 %c, i8 noundef range(i8 0,2) %x) {
1642+
; CHECK-LABEL: @test_logical_and_trunc_nuw(
1643+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
1644+
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C:%.*]], [[TRUNC]]
1645+
; CHECK-NEXT: ret i1 [[AND]]
1646+
;
1647+
%trunc = trunc nuw i8 %x to i1
1648+
%and = select i1 %c, i1 %trunc, i1 false
1649+
ret i1 %and
1650+
}
1651+
1652+
define i1 @test_logical_or_trunc_nuw(i1 %c, i8 noundef range(i8 0,2) %x) {
1653+
; CHECK-LABEL: @test_logical_or_trunc_nuw(
1654+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
1655+
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C:%.*]], [[TRUNC]]
1656+
; CHECK-NEXT: ret i1 [[OR]]
1657+
;
1658+
%trunc = trunc nuw i8 %x to i1
1659+
%or = select i1 %c, i1 true, i1 %trunc
1660+
ret i1 %or
1661+
}
1662+
1663+
define <2 x i1> @test_logical_and_trunc_nuw_vec(<2 x i1> %c, <2 x i8> noundef range(i8 0,2) %x) {
1664+
; CHECK-LABEL: @test_logical_and_trunc_nuw_vec(
1665+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1>
1666+
; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[C:%.*]], [[TRUNC]]
1667+
; CHECK-NEXT: ret <2 x i1> [[AND]]
1668+
;
1669+
%trunc = trunc nuw <2 x i8> %x to <2 x i1>
1670+
%and = select <2 x i1> %c, <2 x i1> %trunc, <2 x i1> zeroinitializer
1671+
ret <2 x i1> %and
1672+
}
1673+
1674+
define i1 @neg_test_logical_and_trunc_nuw_no_range(i1 %c, i8 noundef %x) {
1675+
; CHECK-LABEL: @neg_test_logical_and_trunc_nuw_no_range(
1676+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
1677+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[C:%.*]], i1 [[TRUNC]], i1 false
1678+
; CHECK-NEXT: ret i1 [[AND]]
1679+
;
1680+
%trunc = trunc nuw i8 %x to i1
1681+
%and = select i1 %c, i1 %trunc, i1 false
1682+
ret i1 %and
1683+
}
1684+
1685+
define i1 @neg_test_logical_and_trunc_nuw_no_noundef(i1 %c, i8 range(i8 0,2) %x) {
1686+
; CHECK-LABEL: @neg_test_logical_and_trunc_nuw_no_noundef(
1687+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
1688+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[C:%.*]], i1 [[TRUNC]], i1 false
1689+
; CHECK-NEXT: ret i1 [[AND]]
1690+
;
1691+
%trunc = trunc nuw i8 %x to i1
1692+
%and = select i1 %c, i1 %trunc, i1 false
1693+
ret i1 %and
1694+
}

0 commit comments

Comments
 (0)