Skip to content

Commit a56467d

Browse files
committed
[InstCombine] Fold select of and/or(icmp, other_cond) to select of other_cond
1 parent 31ea022 commit a56467d

File tree

4 files changed

+68
-35
lines changed

4 files changed

+68
-35
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
442442
// into simplier select instruction using isImpliedCondition.
443443
Instruction *foldAndOrOfSelectUsingImpliedCond(Value *Op, SelectInst &SI,
444444
bool IsAnd);
445-
445+
Instruction *foldSelectOfAndOr(SelectInst &SI);
446446
Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp, Instruction &FMFSource);
447447

448448
public:

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,6 +2683,56 @@ Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond(Value *Op,
26832683
}
26842684
}
26852685

2686+
Instruction *InstCombinerImpl::foldSelectOfAndOr(SelectInst &SI) {
2687+
Value *CondVal = SI.getCondition();
2688+
Value *CondLHS, *CondRHS;
2689+
bool IsBitwise = !isa<SelectInst>(CondVal);
2690+
bool IsAnd;
2691+
2692+
if (match(CondVal, m_LogicalOr(m_Value(CondLHS), m_Value(CondRHS))))
2693+
IsAnd = false;
2694+
else if (match(CondVal, m_LogicalAnd(m_Value(CondLHS), m_Value(CondRHS))))
2695+
IsAnd = true;
2696+
else
2697+
return nullptr;
2698+
2699+
Value *TrueVal = SI.getTrueValue(), *FalseVal = SI.getFalseValue();
2700+
2701+
// %cmp = icmp eq i32 %a, %b
2702+
// %cond = or i1 %other_cond, %cmp
2703+
// %select = select i1 %cond, i32 %a, i32 %b
2704+
// =>
2705+
// %select = select i1 %other_cond, i32 %a, i32 %b
2706+
2707+
// Or for an inverted version, we fold it like:
2708+
// %cmp = icmp ne i32 %a, %b
2709+
// %cond = and i1 %other_cond, %cmp
2710+
// %select = select i1 %cond, i32 %a, i32 %b
2711+
// =>
2712+
// %select = select i1 %other_cond, i32 %a, i32 %b
2713+
2714+
auto FoldAndOrOfEquality = [&](Value *Cmp, Value *OtherCond,
2715+
bool NeedToFreeze) -> Instruction * {
2716+
ICmpInst::Predicate Pred;
2717+
if (!match(Cmp, m_c_ICmp(Pred, m_Specific(TrueVal), m_Specific(FalseVal))))
2718+
return nullptr;
2719+
if (Pred != (IsAnd ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ))
2720+
return nullptr;
2721+
if (NeedToFreeze)
2722+
OtherCond = Builder.CreateFreeze(OtherCond);
2723+
return SelectInst::Create(OtherCond, TrueVal, FalseVal);
2724+
};
2725+
2726+
// Order doesn't matter for bitwise and/or. We care about FreezeInst only when
2727+
// and/or is logical.
2728+
if (Instruction *Ret = FoldAndOrOfEquality(CondLHS, CondRHS, !IsBitwise))
2729+
return Ret;
2730+
if (Instruction *Ret = FoldAndOrOfEquality(CondRHS, CondLHS, false))
2731+
return Ret;
2732+
2733+
return nullptr;
2734+
}
2735+
26862736
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
26872737
// fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work.
26882738
static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
@@ -3409,6 +3459,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
34093459
}
34103460
}
34113461

3462+
if (Instruction *I = foldSelectOfAndOr(SI))
3463+
return I;
3464+
34123465
auto *SIFPOp = dyn_cast<FPMathOperator>(&SI);
34133466

34143467
if (auto *FCmp = dyn_cast<FCmpInst>(CondVal)) {

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

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -968,9 +968,7 @@ define i1 @or_and3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) {
968968

969969
define i32 @or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
970970
; CHECK-LABEL: @or_eq_a_b(
971-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
972-
; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
973-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
971+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
974972
; CHECK-NEXT: ret i32 [[SELECT]]
975973
;
976974
%cmp = icmp eq i32 %a, %b
@@ -981,9 +979,7 @@ define i32 @or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
981979

982980
define i32 @and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
983981
; CHECK-LABEL: @and_ne_a_b(
984-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
985-
; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[OTHER_COND:%.*]]
986-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
982+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
987983
; CHECK-NEXT: ret i32 [[SELECT]]
988984
;
989985
%cmp = icmp ne i32 %a, %b
@@ -994,9 +990,7 @@ define i32 @and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
994990

995991
define i32 @or_eq_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
996992
; CHECK-LABEL: @or_eq_a_b_commuted(
997-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
998-
; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
999-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
993+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[B:%.*]], i32 [[A:%.*]]
1000994
; CHECK-NEXT: ret i32 [[SELECT]]
1001995
;
1002996
%cmp = icmp eq i32 %a, %b
@@ -1007,9 +1001,7 @@ define i32 @or_eq_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
10071001

10081002
define i32 @and_ne_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
10091003
; CHECK-LABEL: @and_ne_a_b_commuted(
1010-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
1011-
; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[OTHER_COND:%.*]]
1012-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
1004+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[B:%.*]], i32 [[A:%.*]]
10131005
; CHECK-NEXT: ret i32 [[SELECT]]
10141006
;
10151007
%cmp = icmp ne i32 %a, %b
@@ -1022,9 +1014,7 @@ define i32 @or_eq_different_operands(i32 %a, i32 %b, i32 %c) {
10221014
; CHECK-LABEL: @or_eq_different_operands(
10231015
; CHECK-NEXT: entry:
10241016
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[C:%.*]]
1025-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[B:%.*]], [[A]]
1026-
; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[CMP1]]
1027-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
1017+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B:%.*]]
10281018
; CHECK-NEXT: ret i32 [[SELECT]]
10291019
;
10301020
entry:
@@ -1041,7 +1031,7 @@ define i32 @or_eq_a_b_multi_use(i1 %other_cond, i32 %a, i32 %b) {
10411031
; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
10421032
; CHECK-NEXT: call void @use(i1 [[CMP]])
10431033
; CHECK-NEXT: call void @use(i1 [[COND]])
1044-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
1034+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND]], i32 [[A]], i32 [[B]]
10451035
; CHECK-NEXT: ret i32 [[SELECT]]
10461036
;
10471037
%cmp = icmp eq i32 %a, %b
@@ -1055,9 +1045,7 @@ define i32 @or_eq_a_b_multi_use(i1 %other_cond, i32 %a, i32 %b) {
10551045
define <2 x i32> @or_eq_a_b_vec(<2 x i1> %other_cond ,<2 x i32> %a, <2 x i32> %b) {
10561046
; CHECK-LABEL: @or_eq_a_b_vec(
10571047
; CHECK-NEXT: entry:
1058-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], [[B:%.*]]
1059-
; CHECK-NEXT: [[COND:%.*]] = or <2 x i1> [[CMP]], [[OTHER_COND:%.*]]
1060-
; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[A]], <2 x i32> [[B]]
1048+
; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[OTHER_COND:%.*]], <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]
10611049
; CHECK-NEXT: ret <2 x i32> [[SELECT]]
10621050
;
10631051
entry:
@@ -1116,9 +1104,7 @@ entry:
11161104

11171105
define i32 @logical_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
11181106
; CHECK-LABEL: @logical_or_eq_a_b(
1119-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
1120-
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 true, i1 [[CMP]]
1121-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
1107+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
11221108
; CHECK-NEXT: ret i32 [[SELECT]]
11231109
;
11241110
%cmp = icmp eq i32 %a, %b
@@ -1129,9 +1115,8 @@ define i32 @logical_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
11291115

11301116
define i32 @logical_commuted_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
11311117
; CHECK-LABEL: @logical_commuted_or_eq_a_b(
1132-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
1133-
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[OTHER_COND:%.*]]
1134-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
1118+
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[OTHER_COND:%.*]]
1119+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TMP1]], i32 [[A:%.*]], i32 [[B:%.*]]
11351120
; CHECK-NEXT: ret i32 [[SELECT]]
11361121
;
11371122
%cmp = icmp eq i32 %a, %b
@@ -1142,9 +1127,7 @@ define i32 @logical_commuted_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
11421127

11431128
define i32 @logical_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
11441129
; CHECK-LABEL: @logical_and_ne_a_b(
1145-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
1146-
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 [[CMP]], i1 false
1147-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
1130+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
11481131
; CHECK-NEXT: ret i32 [[SELECT]]
11491132
;
11501133
%cmp = icmp ne i32 %a, %b
@@ -1155,9 +1138,8 @@ define i32 @logical_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
11551138

11561139
define i32 @logical_commuted_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
11571140
; CHECK-LABEL: @logical_commuted_and_ne_a_b(
1158-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
1159-
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[OTHER_COND:%.*]], i1 false
1160-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
1141+
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[OTHER_COND:%.*]]
1142+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TMP1]], i32 [[A:%.*]], i32 [[B:%.*]]
11611143
; CHECK-NEXT: ret i32 [[SELECT]]
11621144
;
11631145
%cmp = icmp ne i32 %a, %b

llvm/test/Transforms/Reassociate/basictest.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,8 @@ define i32 @test14(i32 %X1, i32 %X2) {
239239

240240
define i32 @test15(i32 %X1, i32 %X2, i32 %X3) {
241241
; CHECK-LABEL: @test15(
242-
; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X1:%.*]], 0
243242
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[X2:%.*]], [[X3:%.*]]
244-
; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]]
245-
; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X1]], i32 0
243+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X1:%.*]], i32 0
246244
; CHECK-NEXT: ret i32 [[D]]
247245
;
248246
%A = icmp ne i32 %X1, 0

0 commit comments

Comments
 (0)