[llvm] [InstSimplify] Use multi-op replacement when simplify `select` (PR #121708)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 6 14:27:37 PST 2025
https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/121708
>From a3b88b8d3e93439d811457828a669ade52cbe46a Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Mon, 6 Jan 2025 16:00:50 -0600
Subject: [PATCH 1/5] [InstSimpify] Add tests for simplify select with `X & Y
== -1` cond; NFC
---
llvm/test/Transforms/InstCombine/select.ll | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 9de3c2483ba49c..0e3203dc04b9a7 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -4837,3 +4837,19 @@ define i32 @replace_and_cond_multiuse2(i1 %cond1, i1 %cond2) {
%mux = select i1 %cond1, i32 %sel, i32 1
ret i32 %mux
}
+
+define i32 @src_simplify_2x_at_once_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_simplify_2x_at_once_and(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], -1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 0, i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, -1
+ %sub = sub i32 %x, %y
+ %xor = xor i32 %x, %y
+ %cond = select i1 %and0, i32 %sub, i32 %xor
+ ret i32 %cond
+}
>From f7d43be269d20ba4424f55caffdc651e347de221 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sun, 5 Jan 2025 15:05:16 -0600
Subject: [PATCH 2/5] [InstSimplify] Refactor `simplifyWithOpsReplaced` to
allow multiple replacements; NFC
This allows for multiple ops to be replaced at once. This can be
useful if say replacing in the context of `X | Y == 0`, where some
replacements will only be available if we replace `X` and `Y` with `0`
at the same time.
---
llvm/lib/Analysis/InstructionSimplify.cpp | 70 +++++++++++++++--------
1 file changed, 46 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 515806428cbb29..9839464ee47ed7 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4275,25 +4275,23 @@ Value *llvm::simplifyFCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS,
return ::simplifyFCmpInst(Predicate, LHS, RHS, FMF, Q, RecursionLimit);
}
-static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
- const SimplifyQuery &Q,
- bool AllowRefinement,
- SmallVectorImpl<Instruction *> *DropFlags,
- unsigned MaxRecurse) {
+static Value *simplifyWithOpsReplaced(Value *V,
+ ArrayRef<std::pair<Value *, Value *>> Ops,
+ const SimplifyQuery &Q,
+ bool AllowRefinement,
+ SmallVectorImpl<Instruction *> *DropFlags,
+ unsigned MaxRecurse) {
assert((AllowRefinement || !Q.CanUseUndef) &&
"If AllowRefinement=false then CanUseUndef=false");
-
- // Trivial replacement.
- if (V == Op)
- return RepOp;
+ for (const auto &OpAndRepOp : Ops) {
+ // Trivial replacement.
+ if (V == OpAndRepOp.first)
+ return OpAndRepOp.second;
+ }
if (!MaxRecurse--)
return nullptr;
- // We cannot replace a constant, and shouldn't even try.
- if (isa<Constant>(Op))
- return nullptr;
-
auto *I = dyn_cast<Instruction>(V);
if (!I)
return nullptr;
@@ -4303,11 +4301,6 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
if (isa<PHINode>(I))
return nullptr;
- // For vector types, the simplification must hold per-lane, so forbid
- // potentially cross-lane operations like shufflevector.
- if (Op->getType()->isVectorTy() && !isNotCrossLaneOperation(I))
- return nullptr;
-
// Don't fold away llvm.is.constant checks based on assumptions.
if (match(I, m_Intrinsic<Intrinsic::is_constant>()))
return nullptr;
@@ -4316,12 +4309,30 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
if (isa<FreezeInst>(I))
return nullptr;
+ SmallVector<std::pair<Value *, Value *>> ValidReplacements{};
+ for (const auto &OpAndRepOp : Ops) {
+ // We cannot replace a constant, and shouldn't even try.
+ if (isa<Constant>(OpAndRepOp.first))
+ return nullptr;
+
+ // For vector types, the simplification must hold per-lane, so forbid
+ // potentially cross-lane operations like shufflevector.
+ if (OpAndRepOp.first->getType()->isVectorTy() &&
+ !isNotCrossLaneOperation(I))
+ continue;
+ ValidReplacements.emplace_back(OpAndRepOp);
+ }
+
+ if (ValidReplacements.empty())
+ return nullptr;
+
// Replace Op with RepOp in instruction operands.
SmallVector<Value *, 8> NewOps;
bool AnyReplaced = false;
for (Value *InstOp : I->operands()) {
- if (Value *NewInstOp = simplifyWithOpReplaced(
- InstOp, Op, RepOp, Q, AllowRefinement, DropFlags, MaxRecurse)) {
+ if (Value *NewInstOp =
+ simplifyWithOpsReplaced(InstOp, ValidReplacements, Q,
+ AllowRefinement, DropFlags, MaxRecurse)) {
NewOps.push_back(NewInstOp);
AnyReplaced = InstOp != NewInstOp;
} else {
@@ -4372,7 +4383,9 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
// by assumption and this case never wraps, so nowrap flags can be
// ignored.
if ((Opcode == Instruction::Sub || Opcode == Instruction::Xor) &&
- NewOps[0] == RepOp && NewOps[1] == RepOp)
+ any_of(ValidReplacements, [=](const auto &Rep) {
+ return NewOps[0] == NewOps[1] && NewOps[0] == Rep.second;
+ }))
return Constant::getNullValue(I->getType());
// If we are substituting an absorber constant into a binop and extra
@@ -4382,10 +4395,10 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
// (Op == 0) ? 0 : (Op & -Op) --> Op & -Op
// (Op == 0) ? 0 : (Op * (binop Op, C)) --> Op * (binop Op, C)
// (Op == -1) ? -1 : (Op | (binop C, Op) --> Op | (binop C, Op)
- Constant *Absorber =
- ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
+ Constant *Absorber = ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
if ((NewOps[0] == Absorber || NewOps[1] == Absorber) &&
- impliesPoison(BO, Op))
+ all_of(ValidReplacements,
+ [=](const auto &Rep) { return impliesPoison(BO, Rep.first); }))
return Absorber;
}
@@ -4453,6 +4466,15 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
/*AllowNonDeterministic=*/false);
}
+static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
+ const SimplifyQuery &Q,
+ bool AllowRefinement,
+ SmallVectorImpl<Instruction *> *DropFlags,
+ unsigned MaxRecurse) {
+ return simplifyWithOpsReplaced(V, {{Op, RepOp}}, Q, AllowRefinement,
+ DropFlags, MaxRecurse);
+}
+
Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
const SimplifyQuery &Q,
bool AllowRefinement,
>From 6376b4c052e33b45432ec059f4922fa0aeb4a728 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sun, 5 Jan 2025 15:51:37 -0600
Subject: [PATCH 3/5] [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.
---
llvm/lib/Analysis/InstructionSimplify.cpp | 47 ++++++++++++----------
llvm/test/Transforms/InstCombine/select.ll | 21 +++-------
2 files changed, 32 insertions(+), 36 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 9839464ee47ed7..1fa3c9bbd9a330 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4397,7 +4397,7 @@ static Value *simplifyWithOpsReplaced(Value *V,
// (Op == -1) ? -1 : (Op | (binop C, Op) --> Op | (binop C, Op)
Constant *Absorber = ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
if ((NewOps[0] == Absorber || NewOps[1] == Absorber) &&
- all_of(ValidReplacements,
+ any_of(ValidReplacements,
[=](const auto &Rep) { return impliesPoison(BO, Rep.first); }))
return Absorber;
}
@@ -4617,19 +4617,18 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
/// Try to simplify a select instruction when its condition operand is an
/// integer equality or floating-point equivalence comparison.
-static Value *simplifySelectWithEquivalence(Value *CmpLHS, Value *CmpRHS,
- Value *TrueVal, Value *FalseVal,
- const SimplifyQuery &Q,
- unsigned MaxRecurse) {
+static Value *simplifySelectWithEquivalence(
+ ArrayRef<std::pair<Value *, Value *>> Replacements, Value *TrueVal,
+ Value *FalseVal, const SimplifyQuery &Q, unsigned MaxRecurse) {
Value *SimplifiedFalseVal =
- simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q.getWithoutUndef(),
+ simplifyWithOpReplaced(FalseVal, Replacements, Q.getWithoutUndef(),
/* AllowRefinement */ false,
/* DropFlags */ nullptr, MaxRecurse);
if (!SimplifiedFalseVal)
SimplifiedFalseVal = FalseVal;
Value *SimplifiedTrueVal =
- simplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q,
+ simplifyWithOpReplaced(TrueVal, Replacements, Q,
/* AllowRefinement */ true,
/* DropFlags */ nullptr, MaxRecurse);
if (!SimplifiedTrueVal)
@@ -4729,10 +4728,10 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
// the arms of the select. See if substituting this value into the arm and
// simplifying the result yields the same value as the other arm.
if (Pred == ICmpInst::ICMP_EQ) {
- if (Value *V = simplifySelectWithEquivalence(CmpLHS, CmpRHS, TrueVal,
+ if (Value *V = simplifySelectWithEquivalence({{CmpLHS, CmpRHS}}, TrueVal,
FalseVal, Q, MaxRecurse))
return V;
- if (Value *V = simplifySelectWithEquivalence(CmpRHS, CmpLHS, TrueVal,
+ if (Value *V = simplifySelectWithEquivalence({{CmpRHS, CmpLHS}}, TrueVal,
FalseVal, Q, MaxRecurse))
return V;
@@ -4742,11 +4741,14 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) &&
match(CmpRHS, m_Zero())) {
// (X | Y) == 0 implies X == 0 and Y == 0.
- if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
- Q, MaxRecurse))
+ if (Value *V = simplifySelectWithEquivalence(
+ {{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
return V;
- if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
- Q, MaxRecurse))
+ if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
+ FalseVal, Q, MaxRecurse))
+ return V;
+ if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
+ FalseVal, Q, MaxRecurse))
return V;
}
@@ -4754,11 +4756,14 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
if (match(CmpLHS, m_And(m_Value(X), m_Value(Y))) &&
match(CmpRHS, m_AllOnes())) {
// (X & Y) == -1 implies X == -1 and Y == -1.
- if (Value *V = simplifySelectWithEquivalence(X, CmpRHS, TrueVal, FalseVal,
- Q, MaxRecurse))
+ if (Value *V = simplifySelectWithEquivalence(
+ {{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
+ return V;
+ if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
+ FalseVal, Q, MaxRecurse))
return V;
- if (Value *V = simplifySelectWithEquivalence(Y, CmpRHS, TrueVal, FalseVal,
- Q, MaxRecurse))
+ if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
+ FalseVal, Q, MaxRecurse))
return V;
}
}
@@ -4787,11 +4792,11 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
// This transforms is safe if at least one operand is known to not be zero.
// Otherwise, the select can change the sign of a zero operand.
if (IsEquiv) {
- if (Value *V =
- simplifySelectWithEquivalence(CmpLHS, CmpRHS, T, F, Q, MaxRecurse))
+ if (Value *V = simplifySelectWithEquivalence({{CmpLHS, CmpRHS}}, T, F, Q,
+ MaxRecurse))
return V;
- if (Value *V =
- simplifySelectWithEquivalence(CmpRHS, CmpLHS, T, F, Q, MaxRecurse))
+ if (Value *V = simplifySelectWithEquivalence({{CmpRHS, CmpLHS}}, T, F, Q,
+ MaxRecurse))
return V;
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 0e3203dc04b9a7..dae55063a5da0c 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3937,11 +3937,8 @@ entry:
define i32 @src_or_eq_0_and_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_0_and_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[XOR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
;
entry:
%or = or i32 %y, %x
@@ -3956,11 +3953,8 @@ entry:
define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_0_xor_and(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[AND]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[AND]]
;
entry:
%or = or i32 %y, %x
@@ -4438,11 +4432,8 @@ define i32 @src_no_trans_select_and_eq0_xor_and(i32 %x, i32 %y) {
define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_no_trans_select_or_eq0_or_and(
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[AND]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[AND]]
;
%or = or i32 %x, %y
%or0 = icmp eq i32 %or, 0
>From 55fbdadcb4decf17e24ff2e40b9566a625c5c22f Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Mon, 6 Jan 2025 13:45:50 -0600
Subject: [PATCH 4/5] Fixup: Only one call after rebase
---
llvm/lib/Analysis/InstructionSimplify.cpp | 24 ++++++-----------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 1fa3c9bbd9a330..0cb963af51ba7c 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4621,16 +4621,16 @@ static Value *simplifySelectWithEquivalence(
ArrayRef<std::pair<Value *, Value *>> Replacements, Value *TrueVal,
Value *FalseVal, const SimplifyQuery &Q, unsigned MaxRecurse) {
Value *SimplifiedFalseVal =
- simplifyWithOpReplaced(FalseVal, Replacements, Q.getWithoutUndef(),
- /* AllowRefinement */ false,
- /* DropFlags */ nullptr, MaxRecurse);
+ simplifyWithOpsReplaced(FalseVal, Replacements, Q.getWithoutUndef(),
+ /* AllowRefinement */ false,
+ /* DropFlags */ nullptr, MaxRecurse);
if (!SimplifiedFalseVal)
SimplifiedFalseVal = FalseVal;
Value *SimplifiedTrueVal =
- simplifyWithOpReplaced(TrueVal, Replacements, Q,
- /* AllowRefinement */ true,
- /* DropFlags */ nullptr, MaxRecurse);
+ simplifyWithOpsReplaced(TrueVal, Replacements, Q,
+ /* AllowRefinement */ true,
+ /* DropFlags */ nullptr, MaxRecurse);
if (!SimplifiedTrueVal)
SimplifiedTrueVal = TrueVal;
@@ -4744,12 +4744,6 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
if (Value *V = simplifySelectWithEquivalence(
{{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
return V;
- if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
- FalseVal, Q, MaxRecurse))
- return V;
- if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
- FalseVal, Q, MaxRecurse))
- return V;
}
// select((X & Y) == -1 ? X : -1) --> -1 (commuted 2 ways)
@@ -4759,12 +4753,6 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
if (Value *V = simplifySelectWithEquivalence(
{{X, CmpRHS}, {Y, CmpRHS}}, TrueVal, FalseVal, Q, MaxRecurse))
return V;
- if (Value *V = simplifySelectWithEquivalence({{X, CmpRHS}}, TrueVal,
- FalseVal, Q, MaxRecurse))
- return V;
- if (Value *V = simplifySelectWithEquivalence({{Y, CmpRHS}}, TrueVal,
- FalseVal, Q, MaxRecurse))
- return V;
}
}
>From 4d864c7fd3daeeb8f788b7bf02403f5421e88861 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Mon, 6 Jan 2025 15:39:21 -0600
Subject: [PATCH 5/5] Fixups + more tests
---
llvm/lib/Analysis/InstructionSimplify.cpp | 27 ++++++++--------------
llvm/test/Transforms/InstCombine/select.ll | 7 ++----
2 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 0cb963af51ba7c..999386c0a04917 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4284,6 +4284,10 @@ static Value *simplifyWithOpsReplaced(Value *V,
assert((AllowRefinement || !Q.CanUseUndef) &&
"If AllowRefinement=false then CanUseUndef=false");
for (const auto &OpAndRepOp : Ops) {
+ // We cannot replace a constant, and shouldn't even try.
+ if (isa<Constant>(OpAndRepOp.first))
+ return nullptr;
+
// Trivial replacement.
if (V == OpAndRepOp.first)
return OpAndRepOp.second;
@@ -4309,30 +4313,20 @@ static Value *simplifyWithOpsReplaced(Value *V,
if (isa<FreezeInst>(I))
return nullptr;
- SmallVector<std::pair<Value *, Value *>> ValidReplacements{};
for (const auto &OpAndRepOp : Ops) {
- // We cannot replace a constant, and shouldn't even try.
- if (isa<Constant>(OpAndRepOp.first))
- return nullptr;
-
// For vector types, the simplification must hold per-lane, so forbid
// potentially cross-lane operations like shufflevector.
if (OpAndRepOp.first->getType()->isVectorTy() &&
!isNotCrossLaneOperation(I))
- continue;
- ValidReplacements.emplace_back(OpAndRepOp);
+ return nullptr;
}
- if (ValidReplacements.empty())
- return nullptr;
-
// Replace Op with RepOp in instruction operands.
SmallVector<Value *, 8> NewOps;
bool AnyReplaced = false;
for (Value *InstOp : I->operands()) {
- if (Value *NewInstOp =
- simplifyWithOpsReplaced(InstOp, ValidReplacements, Q,
- AllowRefinement, DropFlags, MaxRecurse)) {
+ if (Value *NewInstOp = simplifyWithOpsReplaced(
+ InstOp, Ops, Q, AllowRefinement, DropFlags, MaxRecurse)) {
NewOps.push_back(NewInstOp);
AnyReplaced = InstOp != NewInstOp;
} else {
@@ -4383,9 +4377,8 @@ static Value *simplifyWithOpsReplaced(Value *V,
// by assumption and this case never wraps, so nowrap flags can be
// ignored.
if ((Opcode == Instruction::Sub || Opcode == Instruction::Xor) &&
- any_of(ValidReplacements, [=](const auto &Rep) {
- return NewOps[0] == NewOps[1] && NewOps[0] == Rep.second;
- }))
+ NewOps[0] == NewOps[1] &&
+ any_of(Ops, [=](const auto &Rep) { return NewOps[0] == Rep.second; }))
return Constant::getNullValue(I->getType());
// If we are substituting an absorber constant into a binop and extra
@@ -4397,7 +4390,7 @@ static Value *simplifyWithOpsReplaced(Value *V,
// (Op == -1) ? -1 : (Op | (binop C, Op) --> Op | (binop C, Op)
Constant *Absorber = ConstantExpr::getBinOpAbsorber(Opcode, I->getType());
if ((NewOps[0] == Absorber || NewOps[1] == Absorber) &&
- any_of(ValidReplacements,
+ any_of(Ops,
[=](const auto &Rep) { return impliesPoison(BO, Rep.first); }))
return Absorber;
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index dae55063a5da0c..0f15fa6c0cc50a 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -4831,11 +4831,8 @@ define i32 @replace_and_cond_multiuse2(i1 %cond1, i1 %cond2) {
define i32 @src_simplify_2x_at_once_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_simplify_2x_at_once_and(
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 0, i32 [[XOR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
;
%and = and i32 %x, %y
%and0 = icmp eq i32 %and, -1
More information about the llvm-commits
mailing list