Skip to content

Commit 0c2ed79

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 f0febbd commit 0c2ed79

File tree

2 files changed

+40
-50
lines changed

2 files changed

+40
-50
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 30 additions & 25 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,17 +4617,16 @@ 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) {
4624-
if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q.getWithoutUndef(),
4625-
/* AllowRefinement */ false,
4626-
/* DropFlags */ nullptr, MaxRecurse) == TrueVal)
4620+
static Value *simplifySelectWithEquivalence(
4621+
ArrayRef<std::pair<Value *, Value *>> Replacements, Value *TrueVal,
4622+
Value *FalseVal, const SimplifyQuery &Q, unsigned MaxRecurse) {
4623+
if (simplifyWithOpsReplaced(FalseVal, Replacements, Q.getWithoutUndef(),
4624+
/* AllowRefinement */ false,
4625+
/* DropFlags */ nullptr, MaxRecurse) == TrueVal)
46274626
return FalseVal;
4628-
if (simplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q,
4629-
/* AllowRefinement */ true,
4630-
/* DropFlags */ nullptr, MaxRecurse) == FalseVal)
4627+
if (simplifyWithOpsReplaced(TrueVal, Replacements, Q,
4628+
/* AllowRefinement */ true,
4629+
/* DropFlags */ nullptr, MaxRecurse) == FalseVal)
46314630
return FalseVal;
46324631

46334632
return nullptr;
@@ -4721,10 +4720,10 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47214720
// the arms of the select. See if substituting this value into the arm and
47224721
// simplifying the result yields the same value as the other arm.
47234722
if (Pred == ICmpInst::ICMP_EQ) {
4724-
if (Value *V = simplifySelectWithEquivalence(CmpLHS, CmpRHS, TrueVal,
4723+
if (Value *V = simplifySelectWithEquivalence({{CmpLHS, CmpRHS}}, TrueVal,
47254724
FalseVal, Q, MaxRecurse))
47264725
return V;
4727-
if (Value *V = simplifySelectWithEquivalence(CmpRHS, CmpLHS, TrueVal,
4726+
if (Value *V = simplifySelectWithEquivalence({{CmpRHS, CmpLHS}}, TrueVal,
47284727
FalseVal, Q, MaxRecurse))
47294728
return V;
47304729

@@ -4734,23 +4733,29 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47344733
if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) &&
47354734
match(CmpRHS, m_Zero())) {
47364735
// (X | Y) == 0 implies X == 0 and Y == 0.
4737-
if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
4738-
Q, MaxRecurse))
4736+
if (Value *V = simplifySelectWithEquivalence(
4737+
{{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
47394738
return V;
4740-
if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
4741-
Q, MaxRecurse))
4739+
if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
4740+
FalseVal, Q, MaxRecurse))
4741+
return V;
4742+
if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
4743+
FalseVal, Q, MaxRecurse))
47424744
return V;
47434745
}
47444746

47454747
// select((X & Y) == -1 ? X : -1) --> -1 (commuted 2 ways)
47464748
if (match(CmpLHS, m_And(m_Value(X), m_Value(Y))) &&
47474749
match(CmpRHS, m_AllOnes())) {
47484750
// (X & Y) == -1 implies X == -1 and Y == -1.
4749-
if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
4750-
Q, MaxRecurse))
4751+
if (Value *V = simplifySelectWithEquivalence(
4752+
{{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
4753+
return V;
4754+
if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
4755+
FalseVal, Q, MaxRecurse))
47514756
return V;
4752-
if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
4753-
Q, MaxRecurse))
4757+
if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
4758+
FalseVal, Q, MaxRecurse))
47544759
return V;
47554760
}
47564761
}
@@ -4779,11 +4784,11 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
47794784
// This transforms is safe if at least one operand is known to not be zero.
47804785
// Otherwise, the select can change the sign of a zero operand.
47814786
if (IsEquiv) {
4782-
if (Value *V =
4783-
simplifySelectWithEquivalence(CmpLHS, CmpRHS, T, F, Q, MaxRecurse))
4787+
if (Value *V = simplifySelectWithEquivalence({{CmpLHS, CmpRHS}}, T, F, Q,
4788+
MaxRecurse))
47844789
return V;
4785-
if (Value *V =
4786-
simplifySelectWithEquivalence(CmpRHS, CmpLHS, T, F, Q, MaxRecurse))
4790+
if (Value *V = simplifySelectWithEquivalence({{CmpRHS, CmpLHS}}, T, F, Q,
4791+
MaxRecurse))
47874792
return V;
47884793
}
47894794

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 10 additions & 25 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
@@ -4453,11 +4444,8 @@ define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) {
44534444

44544445
define i32 @src_no_trans_select_or_eq0_or_xor(i32 %x, i32 %y) {
44554446
; CHECK-LABEL: @src_no_trans_select_or_eq0_or_xor(
4456-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
4457-
; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
4458-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
4459-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[XOR]]
4460-
; CHECK-NEXT: ret i32 [[COND]]
4447+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
4448+
; CHECK-NEXT: ret i32 [[XOR]]
44614449
;
44624450
%or = or i32 %x, %y
44634451
%or0 = icmp eq i32 %or, 0
@@ -4492,11 +4480,8 @@ define i32 @src_no_trans_select_or_eq0_xor_or(i32 %x, i32 %y) {
44924480

44934481
define i32 @src_no_trans_select_and_ne0_xor_or(i32 %x, i32 %y) {
44944482
; CHECK-LABEL: @src_no_trans_select_and_ne0_xor_or(
4495-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
4496-
; CHECK-NEXT: [[OR0_NOT:%.*]] = icmp eq i32 [[OR]], 0
4497-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
4498-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0_NOT]], i32 0, i32 [[XOR]]
4499-
; CHECK-NEXT: ret i32 [[COND]]
4483+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
4484+
; CHECK-NEXT: ret i32 [[XOR]]
45004485
;
45014486
%or = or i32 %x, %y
45024487
%or0 = icmp ne i32 %or, 0

0 commit comments

Comments
 (0)