Skip to content

Commit aa847ce

Browse files
authored
[InstCombine] handle trunc to i1 in foldSelectICmpAndBinOp (llvm#127390)
for `trunc nuw` saves a instruction and otherwise only other instructions without the select, same behavior as for bit test before. proof: https://alive2.llvm.org/ce/z/a6QmyV
1 parent 8ecd788 commit aa847ce

File tree

2 files changed

+49
-42
lines changed

2 files changed

+49
-42
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -746,39 +746,47 @@ static Value *foldSelectICmpLshrAshr(const ICmpInst *IC, Value *TrueVal,
746746
/// 1. The icmp predicate is inverted
747747
/// 2. The select operands are reversed
748748
/// 3. The magnitude of C2 and C1 are flipped
749-
static Value *foldSelectICmpAndBinOp(const ICmpInst *IC, Value *TrueVal,
750-
Value *FalseVal,
751-
InstCombiner::BuilderTy &Builder) {
749+
static Value *foldSelectICmpAndBinOp(Value *CondVal, Value *TrueVal,
750+
Value *FalseVal,
751+
InstCombiner::BuilderTy &Builder) {
752752
// Only handle integer compares. Also, if this is a vector select, we need a
753753
// vector compare.
754754
if (!TrueVal->getType()->isIntOrIntVectorTy() ||
755-
TrueVal->getType()->isVectorTy() != IC->getType()->isVectorTy())
755+
TrueVal->getType()->isVectorTy() != CondVal->getType()->isVectorTy())
756756
return nullptr;
757757

758-
Value *CmpLHS = IC->getOperand(0);
759-
Value *CmpRHS = IC->getOperand(1);
760-
761758
unsigned C1Log;
762759
bool NeedAnd = false;
763-
CmpInst::Predicate Pred = IC->getPredicate();
764-
if (IC->isEquality()) {
765-
if (!match(CmpRHS, m_Zero()))
766-
return nullptr;
760+
CmpPredicate Pred;
761+
Value *CmpLHS, *CmpRHS;
767762

768-
const APInt *C1;
769-
if (!match(CmpLHS, m_And(m_Value(), m_Power2(C1))))
770-
return nullptr;
763+
if (match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS)))) {
764+
if (ICmpInst::isEquality(Pred)) {
765+
if (!match(CmpRHS, m_Zero()))
766+
return nullptr;
771767

772-
C1Log = C1->logBase2();
773-
} else {
774-
auto Res = decomposeBitTestICmp(CmpLHS, CmpRHS, Pred);
775-
if (!Res || !Res->Mask.isPowerOf2())
776-
return nullptr;
768+
const APInt *C1;
769+
if (!match(CmpLHS, m_And(m_Value(), m_Power2(C1))))
770+
return nullptr;
777771

778-
CmpLHS = Res->X;
779-
Pred = Res->Pred;
780-
C1Log = Res->Mask.logBase2();
781-
NeedAnd = true;
772+
C1Log = C1->logBase2();
773+
} else {
774+
auto Res = decomposeBitTestICmp(CmpLHS, CmpRHS, Pred);
775+
if (!Res || !Res->Mask.isPowerOf2())
776+
return nullptr;
777+
778+
CmpLHS = Res->X;
779+
Pred = Res->Pred;
780+
C1Log = Res->Mask.logBase2();
781+
NeedAnd = true;
782+
}
783+
} else if (auto *Trunc = dyn_cast<TruncInst>(CondVal)) {
784+
CmpLHS = Trunc->getOperand(0);
785+
C1Log = 0;
786+
Pred = ICmpInst::ICMP_NE;
787+
NeedAnd = !Trunc->hasNoUnsignedWrap();
788+
} else {
789+
return nullptr;
782790
}
783791

784792
Value *Y, *V = CmpLHS;
@@ -812,7 +820,7 @@ static Value *foldSelectICmpAndBinOp(const ICmpInst *IC, Value *TrueVal,
812820

813821
// Make sure we don't create more instructions than we save.
814822
if ((NeedShift + NeedXor + NeedZExtTrunc + NeedAnd) >
815-
(IC->hasOneUse() + BinOp->hasOneUse()))
823+
(CondVal->hasOneUse() + BinOp->hasOneUse()))
816824
return nullptr;
817825

818826
if (NeedAnd) {
@@ -1990,9 +1998,6 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
19901998
if (Instruction *V = foldSelectZeroOrOnes(ICI, TrueVal, FalseVal, Builder))
19911999
return V;
19922000

1993-
if (Value *V = foldSelectICmpAndBinOp(ICI, TrueVal, FalseVal, Builder))
1994-
return replaceInstUsesWith(SI, V);
1995-
19962001
if (Value *V = foldSelectICmpLshrAshr(ICI, TrueVal, FalseVal, Builder))
19972002
return replaceInstUsesWith(SI, V);
19982003

@@ -3950,6 +3955,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
39503955
if (Instruction *Result = foldSelectInstWithICmp(SI, ICI))
39513956
return Result;
39523957

3958+
if (Value *V = foldSelectICmpAndBinOp(CondVal, TrueVal, FalseVal, Builder))
3959+
return replaceInstUsesWith(SI, V);
3960+
39533961
if (Instruction *Add = foldAddSubSelect(SI, Builder))
39543962
return Add;
39553963
if (Instruction *Add = foldOverflowingAddSubSelect(SI, Builder))

llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,9 +1754,9 @@ define i8 @select_icmp_eq_and_1_0_lshr_tv(i8 %x, i8 %y) {
17541754

17551755
define i8 @select_trunc_or_2(i8 %x, i8 %y) {
17561756
; CHECK-LABEL: @select_trunc_or_2(
1757-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
1758-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], 2
1759-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i8 [[OR]], i8 [[Y]]
1757+
; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[X:%.*]], 1
1758+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 2
1759+
; CHECK-NEXT: [[SELECT:%.*]] = or i8 [[Y:%.*]], [[TMP2]]
17601760
; CHECK-NEXT: ret i8 [[SELECT]]
17611761
;
17621762
%trunc = trunc i8 %x to i1
@@ -1767,9 +1767,9 @@ define i8 @select_trunc_or_2(i8 %x, i8 %y) {
17671767

17681768
define i8 @select_not_trunc_or_2(i8 %x, i8 %y) {
17691769
; CHECK-LABEL: @select_not_trunc_or_2(
1770-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
1771-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], 2
1772-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i8 [[OR]], i8 [[Y]]
1770+
; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[X:%.*]], 1
1771+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 2
1772+
; CHECK-NEXT: [[SELECT:%.*]] = or i8 [[Y:%.*]], [[TMP2]]
17731773
; CHECK-NEXT: ret i8 [[SELECT]]
17741774
;
17751775
%trunc = trunc i8 %x to i1
@@ -1781,9 +1781,8 @@ define i8 @select_not_trunc_or_2(i8 %x, i8 %y) {
17811781

17821782
define i8 @select_trunc_nuw_or_2(i8 %x, i8 %y) {
17831783
; CHECK-LABEL: @select_trunc_nuw_or_2(
1784-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
1785-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], 2
1786-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i8 [[OR]], i8 [[Y]]
1784+
; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[X:%.*]], 1
1785+
; CHECK-NEXT: [[SELECT:%.*]] = or i8 [[Y:%.*]], [[TMP1]]
17871786
; CHECK-NEXT: ret i8 [[SELECT]]
17881787
;
17891788
%trunc = trunc nuw i8 %x to i1
@@ -1794,9 +1793,9 @@ define i8 @select_trunc_nuw_or_2(i8 %x, i8 %y) {
17941793

17951794
define i8 @select_trunc_nsw_or_2(i8 %x, i8 %y) {
17961795
; CHECK-LABEL: @select_trunc_nsw_or_2(
1797-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nsw i8 [[X:%.*]] to i1
1798-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], 2
1799-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i8 [[OR]], i8 [[Y]]
1796+
; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[X:%.*]], 1
1797+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], 2
1798+
; CHECK-NEXT: [[SELECT:%.*]] = or i8 [[Y:%.*]], [[TMP2]]
18001799
; CHECK-NEXT: ret i8 [[SELECT]]
18011800
;
18021801
%trunc = trunc nsw i8 %x to i1
@@ -1807,9 +1806,9 @@ define i8 @select_trunc_nsw_or_2(i8 %x, i8 %y) {
18071806

18081807
define <2 x i8> @select_trunc_or_2_vec(<2 x i8> %x, <2 x i8> %y) {
18091808
; CHECK-LABEL: @select_trunc_or_2_vec(
1810-
; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i8> [[X:%.*]] to <2 x i1>
1811-
; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[Y:%.*]], splat (i8 2)
1812-
; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[TRUNC]], <2 x i8> [[OR]], <2 x i8> [[Y]]
1809+
; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i8> [[X:%.*]], splat (i8 1)
1810+
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i8> [[TMP1]], splat (i8 2)
1811+
; CHECK-NEXT: [[SELECT:%.*]] = or <2 x i8> [[Y:%.*]], [[TMP2]]
18131812
; CHECK-NEXT: ret <2 x i8> [[SELECT]]
18141813
;
18151814
%trunc = trunc <2 x i8> %x to <2 x i1>

0 commit comments

Comments
 (0)