Skip to content

Commit 6376b4c

Browse files
committed
[InstSimplify] Use multi-op replacement when simplify select
In the case of `select X | Y == 0 :...` or `select X & Y == -1 : ...` we can do more simplifications by trying to replace both `X` and `Y` with the respective constant at once. Handles some cases for #121672 more generically.
1 parent f7d43be commit 6376b4c

File tree

2 files changed

+32
-36
lines changed

2 files changed

+32
-36
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4397,7 +4397,7 @@ static Value *simplifyWithOpsReplaced(Value *V,
43974397
// (Op == -1) ? -1 : (Op | (binop C, Op) --> Op | (binop C, Op)
43984398
Constant *Absorber = ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
43994399
if ((NewOps[0] == Absorber || NewOps[1] == Absorber) &&
4400-
all_of(ValidReplacements,
4400+
any_of(ValidReplacements,
44014401
[=](const auto &Rep) { return impliesPoison(BO, Rep.first); }))
44024402
return Absorber;
44034403
}
@@ -4617,19 +4617,18 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
46174617

46184618
/// Try to simplify a select instruction when its condition operand is an
46194619
/// integer equality or floating-point equivalence comparison.
4620-
static Value *simplifySelectWithEquivalence(Value *CmpLHS, Value *CmpRHS,
4621-
Value *TrueVal, Value *FalseVal,
4622-
const SimplifyQuery &Q,
4623-
unsigned MaxRecurse) {
4620+
static Value *simplifySelectWithEquivalence(
4621+
ArrayRef<std::pair<Value *, Value *>> Replacements, Value *TrueVal,
4622+
Value *FalseVal, const SimplifyQuery &Q, unsigned MaxRecurse) {
46244623
Value *SimplifiedFalseVal =
4625-
simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q.getWithoutUndef(),
4624+
simplifyWithOpReplaced(FalseVal, Replacements, Q.getWithoutUndef(),
46264625
/* AllowRefinement */ false,
46274626
/* DropFlags */ nullptr, MaxRecurse);
46284627
if (!SimplifiedFalseVal)
46294628
SimplifiedFalseVal = FalseVal;
46304629

46314630
Value *SimplifiedTrueVal =
4632-
simplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q,
4631+
simplifyWithOpReplaced(TrueVal, Replacements, Q,
46334632
/* AllowRefinement */ true,
46344633
/* DropFlags */ nullptr, MaxRecurse);
46354634
if (!SimplifiedTrueVal)
@@ -4729,10 +4728,10 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47294728
// the arms of the select. See if substituting this value into the arm and
47304729
// simplifying the result yields the same value as the other arm.
47314730
if (Pred == ICmpInst::ICMP_EQ) {
4732-
if (Value *V = simplifySelectWithEquivalence(CmpLHS, CmpRHS, TrueVal,
4731+
if (Value *V = simplifySelectWithEquivalence({{CmpLHS, CmpRHS}}, TrueVal,
47334732
FalseVal, Q, MaxRecurse))
47344733
return V;
4735-
if (Value *V = simplifySelectWithEquivalence(CmpRHS, CmpLHS, TrueVal,
4734+
if (Value *V = simplifySelectWithEquivalence({{CmpRHS, CmpLHS}}, TrueVal,
47364735
FalseVal, Q, MaxRecurse))
47374736
return V;
47384737

@@ -4742,23 +4741,29 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47424741
if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) &&
47434742
match(CmpRHS, m_Zero())) {
47444743
// (X | Y) == 0 implies X == 0 and Y == 0.
4745-
if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
4746-
Q, MaxRecurse))
4744+
if (Value *V = simplifySelectWithEquivalence(
4745+
{{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
47474746
return V;
4748-
if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
4749-
Q, MaxRecurse))
4747+
if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
4748+
FalseVal, Q, MaxRecurse))
4749+
return V;
4750+
if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
4751+
FalseVal, Q, MaxRecurse))
47504752
return V;
47514753
}
47524754

47534755
// select((X & Y) == -1 ? X : -1) --> -1 (commuted 2 ways)
47544756
if (match(CmpLHS, m_And(m_Value(X), m_Value(Y))) &&
47554757
match(CmpRHS, m_AllOnes())) {
47564758
// (X & Y) == -1 implies X == -1 and Y == -1.
4757-
if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
4758-
Q, MaxRecurse))
4759+
if (Value *V = simplifySelectWithEquivalence(
4760+
{{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
4761+
return V;
4762+
if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
4763+
FalseVal, Q, MaxRecurse))
47594764
return V;
4760-
if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
4761-
Q, MaxRecurse))
4765+
if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
4766+
FalseVal, Q, MaxRecurse))
47624767
return V;
47634768
}
47644769
}
@@ -4787,11 +4792,11 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
47874792
// This transforms is safe if at least one operand is known to not be zero.
47884793
// Otherwise, the select can change the sign of a zero operand.
47894794
if (IsEquiv) {
4790-
if (Value *V =
4791-
simplifySelectWithEquivalence(CmpLHS, CmpRHS, T, F, Q, MaxRecurse))
4795+
if (Value *V = simplifySelectWithEquivalence({{CmpLHS, CmpRHS}}, T, F, Q,
4796+
MaxRecurse))
47924797
return V;
4793-
if (Value *V =
4794-
simplifySelectWithEquivalence(CmpRHS, CmpLHS, T, F, Q, MaxRecurse))
4798+
if (Value *V = simplifySelectWithEquivalence({{CmpRHS, CmpLHS}}, T, F, Q,
4799+
MaxRecurse))
47954800
return V;
47964801
}
47974802

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3937,11 +3937,8 @@ entry:
39373937
define i32 @src_or_eq_0_and_xor(i32 %x, i32 %y) {
39383938
; CHECK-LABEL: @src_or_eq_0_and_xor(
39393939
; CHECK-NEXT: entry:
3940-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
3941-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
3942-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
3943-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[XOR]]
3944-
; CHECK-NEXT: ret i32 [[COND]]
3940+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
3941+
; CHECK-NEXT: ret i32 [[XOR]]
39453942
;
39463943
entry:
39473944
%or = or i32 %y, %x
@@ -3956,11 +3953,8 @@ entry:
39563953
define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
39573954
; CHECK-LABEL: @src_or_eq_0_xor_and(
39583955
; CHECK-NEXT: entry:
3959-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
3960-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
3961-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
3962-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[AND]]
3963-
; CHECK-NEXT: ret i32 [[COND]]
3956+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
3957+
; CHECK-NEXT: ret i32 [[AND]]
39643958
;
39653959
entry:
39663960
%or = or i32 %y, %x
@@ -4438,11 +4432,8 @@ define i32 @src_no_trans_select_and_eq0_xor_and(i32 %x, i32 %y) {
44384432

44394433
define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) {
44404434
; CHECK-LABEL: @src_no_trans_select_or_eq0_or_and(
4441-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
4442-
; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
4443-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
4444-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[AND]]
4445-
; CHECK-NEXT: ret i32 [[COND]]
4435+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
4436+
; CHECK-NEXT: ret i32 [[AND]]
44464437
;
44474438
%or = or i32 %x, %y
44484439
%or0 = icmp eq i32 %or, 0

0 commit comments

Comments
 (0)