[llvm] [InstSimplify] Discard unnecessary `select` when the conditions are `ICmps` with EQ (PR #179183)
Gábor Spaits via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 4 04:44:10 PST 2026
https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/179183
>From ab65b67bd437c4ed319945489bc8aaf2db509aa4 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 25 Feb 2026 12:54:16 +0100
Subject: [PATCH 1/2] [InstSimplify] Implement `Cond ? V : V` -> `V` when no
Refinment allowed
Related to #179183 and #177410 .
I am not sure how profitable would this be. But I may be somewhat optimistic, since there is use for this in #177410 and optimizations can already improve code without the cases in #177410. See the tests.
When the select wasn't a poison barrier and returning an arm also isn't a refinment some optimizations can be done with selects in `simplifyWithOpsReplaced`.
The new recursive function was needed because `impliesPoison` can't really give any useful information, when a select is assumed poison and the right side of the implication isn't a user of that select. (Because of select poison semantics.) Also the behaviour of this recursive function could be added to `impliesPoison`, but then it would need extra parameters.
I have some test cases but I see that there is more to add.
Alove2 for the current cases: https://alive2.llvm.org/ce/z/pKwffE
---
llvm/lib/Analysis/InstructionSimplify.cpp | 82 ++++++++++++++++
.../Transforms/InstSimplify/select-icmp.ll | 95 +++++++++++++++++++
2 files changed, 177 insertions(+)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 3d5ee74c0e2e8..ceadee5a7705b 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -48,6 +48,7 @@
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/KnownFPClass.h"
#include <algorithm>
+#include <iterator>
#include <optional>
using namespace llvm;
using namespace llvm::PatternMatch;
@@ -4395,6 +4396,50 @@ Value *llvm::simplifyFCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS,
return ::simplifyFCmpInst(Predicate, LHS, RHS, FMF, Q, RecursionLimit);
}
+// The value is only poison, if any of these values are poison.
+// It can be useful to decide if replacing a value with another would be
+// refining or introduce more poison.
+//
+// It is especially useful for select instructions. When it comes to selects and
+// impliesPoison, if select is the ValueAssumedToBePoison it is rare that it
+// yields true for any Value, that isn't a user of the select, due to the fact
+// that a select has more complex poison propagation than other instruction.
+static bool areTheseAllTheValuesThatMayCausePoisonInValue(
+ const SmallVector<const Value *, 2> ValuesAssumedPoison, const Value *V,
+ unsigned Depth) {
+ if (any_of(ValuesAssumedPoison, [V](const auto *P) { return P == V; }))
+ return true;
+
+ if (const Instruction *I = dyn_cast<Instruction>(V)) {
+ if (I->hasPoisonGeneratingAnnotations())
+ return false;
+
+ SmallVector<const Value *, 2> ValuesImplyingPoison;
+ copy_if(ValuesAssumedPoison, std::back_inserter(ValuesImplyingPoison),
+ [V](const auto *P) { return impliesPoison(P, V); });
+
+ if (ValuesImplyingPoison.empty())
+ return false;
+
+ const unsigned MaxDepth = 2;
+ if (Depth > MaxDepth)
+ return false;
+
+ return all_of(I->operand_values(),
+ [&ValuesImplyingPoison, Depth](const auto *Op) {
+ return areTheseAllTheValuesThatMayCausePoisonInValue(
+ ValuesImplyingPoison, Op, Depth + 1);
+ });
+ }
+ return false;
+}
+
+static bool areTheseAllTheValuesThatMayCausePoisonInValue(
+ const SmallVector<const Value *, 2> ValuesAssumedPoison, const Value *V) {
+ return areTheseAllTheValuesThatMayCausePoisonInValue(ValuesAssumedPoison, V,
+ 0);
+}
+
static Value *simplifyWithOpsReplaced(Value *V,
ArrayRef<std::pair<Value *, Value *>> Ops,
const SimplifyQuery &Q,
@@ -4538,6 +4583,43 @@ static Value *simplifyWithOpsReplaced(Value *V,
if (NewOps.size() == 2 && match(NewOps[1], m_Zero()))
return NewOps[0];
}
+
+ if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
+ Value *SimplifiedValue = nullptr;
+ Value *Cond = SI->getCondition();
+
+ // The select couldn't act as a poison barrirer for its old operands and
+ // the new condition can't be more poisonus than the old one.
+ if (impliesPoison(NewOps[0], Cond) &&
+ impliesPoison(SI->getTrueValue(), Cond) &&
+ impliesPoison(SI->getFalseValue(), Cond)) {
+
+ // Cond ? V : V -> V
+ // We know that after replacement both of the operands will be the same.
+ // We have to make sure that no refinment happens. This is done by
+ // checking if the select condition can only be poison if any of the
+ // arms are poison. If the condition could be poison and neither of the
+ // arms would be poison, returning the less poisonus value would be a
+ // refinment.
+ if (NewOps[1] == NewOps[2] &&
+ areTheseAllTheValuesThatMayCausePoisonInValue(
+ {SI->getFalseValue(), SI->getTrueValue()}, Cond))
+ SimplifiedValue = NewOps[1];
+
+ // TODO: Implement more non refining select optimizations here!
+
+ // If we could do any simplification check if it has any poison
+ // generating flags and handle them.
+ if (SimplifiedValue) {
+ if (SI->hasPoisonGeneratingAnnotations()) {
+ if (!DropFlags)
+ return nullptr;
+ DropFlags->push_back(SI);
+ }
+ return SimplifiedValue;
+ }
+ }
+ }
} else {
// The simplification queries below may return the original value. Consider:
// %div = udiv i32 %arg, %arg2
diff --git a/llvm/test/Transforms/InstSimplify/select-icmp.ll b/llvm/test/Transforms/InstSimplify/select-icmp.ll
index 5ee10bb954766..efe676d9fcd26 100755
--- a/llvm/test/Transforms/InstSimplify/select-icmp.ll
+++ b/llvm/test/Transforms/InstSimplify/select-icmp.ll
@@ -309,3 +309,98 @@ define <2 x ptr> @ptr_eq_replace_vector_constant(<2 x ptr> %a) {
%sel = select <2 x i1> %cmp, <2 x ptr> %a, <2 x ptr> <ptr inttoptr (i64 42 to ptr), ptr inttoptr (i64 88 to ptr)>
ret <2 x ptr> %sel
}
+
+define i32 @selectICmpSelectInArmNotSimplifiedDueToMorePoison(i32 %1, i32 %2, i1 %scond) {
+; CHECK-LABEL: @selectICmpSelectInArmNotSimplifiedDueToMorePoison(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[SCOND:%.*]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP0]], i32 [[TMP4]]
+; CHECK-NEXT: ret i32 [[TMP5]]
+;
+ %4 = icmp eq i32 %1, %2
+ %5 = select i1 %scond, i32 %2, i32 %1
+ %6 = select i1 %4, i32 %1, i32 %5
+ ret i32 %6
+}
+
+define i32 @selectICmpSelectInArmSimplifiedDueToSameValues(i32 %1, i32 %2, i1 %scond) {
+; CHECK-LABEL: @selectICmpSelectInArmSimplifiedDueToSameValues(
+; CHECK-NEXT: [[SAMEVALUES:%.*]] = icmp ule i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[SAMEVALUES]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: ret i32 [[TMP6]]
+;
+ %4 = icmp eq i32 %1, %2
+ %sameValues = icmp ule i32 %1, %2
+ %5 = select i1 %sameValues, i32 %2, i32 %1
+ %6 = select i1 %4, i32 %1, i32 %5
+ ret i32 %6
+}
+
+define i32 @selectICmpSelectInArmSimplifiedNoPoisonFlagOnCondUseDefChain(i32 %1, i32 %2, i1 %scond) {
+; CHECK-LABEL: @selectICmpSelectInArmSimplifiedNoPoisonFlagOnCondUseDefChain(
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: [[WITHPOISONFLAG:%.*]] = or i32 [[TMP0]], 42
+; CHECK-NEXT: [[SAMEVALUES:%.*]] = icmp ule i32 [[WITHPOISONFLAG]], [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[SAMEVALUES]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i32 [[TMP0]], i32 [[TMP3]]
+; CHECK-NEXT: ret i32 [[TMP5]]
+;
+ %4 = icmp eq i32 %1, %2
+ %withPoisonFlag = or i32 %1, 42
+ %sameValues = icmp ule i32 %withPoisonFlag, %2
+ %5 = select i1 %sameValues, i32 %2, i32 %1
+ %6 = select i1 %4, i32 %1, i32 %5
+ ret i32 %6
+}
+
+define i32 @selectICmpSelectInArmNotSimplifiedPoisonFlagOnCondUseDefChain(i32 %1, i32 %2, i1 %scond) {
+; CHECK-LABEL: @selectICmpSelectInArmNotSimplifiedPoisonFlagOnCondUseDefChain(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: [[WITHPOISONFLAG:%.*]] = or disjoint i32 [[TMP0]], 42
+; CHECK-NEXT: [[SAMEVALUES:%.*]] = icmp ule i32 [[WITHPOISONFLAG]], [[TMP1]]
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[SAMEVALUES]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP0]], i32 [[TMP4]]
+; CHECK-NEXT: ret i32 [[TMP5]]
+;
+ %4 = icmp eq i32 %1, %2
+ %withPoisonFlag = or disjoint i32 %1, 42
+ %sameValues = icmp ule i32 %withPoisonFlag, %2
+ %5 = select i1 %sameValues, i32 %2, i32 %1
+ %6 = select i1 %4, i32 %1, i32 %5
+ ret i32 %6
+}
+
+define i32 @selectICmpSelectInArmNotSimplifiedSecondSelectPoisonBarrier(i32 %1, i32 %2, i1 %scond) {
+; CHECK-LABEL: @selectICmpSelectInArmNotSimplifiedSecondSelectPoisonBarrier(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: [[SAMEVALUES:%.*]] = icmp ule i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[OR:%.*]] = or i1 [[SAMEVALUES]], [[SCOND:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[OR]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP0]], i32 [[TMP4]]
+; CHECK-NEXT: ret i32 [[TMP5]]
+;
+ %4 = icmp eq i32 %1, %2
+ %sameValues = icmp ule i32 %1, %2
+ %or = or i1 %sameValues, %scond
+ %5 = select i1 %or, i32 %2, i32 %1
+ %6 = select i1 %4, i32 %1, i32 %5
+ ret i32 %6
+}
+
+define i32 @selectICmpSelectInArmNotSimplifiedSecondSelectPoisonBarrierPoisonFlagInCond(i32 %1, i32 %2, i1 %scond) {
+; CHECK-LABEL: @selectICmpSelectInArmNotSimplifiedSecondSelectPoisonBarrierPoisonFlagInCond(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: [[SAMEVALUES:%.*]] = icmp ule i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i1 [[SAMEVALUES]], [[SCOND:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[OR]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP0]], i32 [[TMP4]]
+; CHECK-NEXT: ret i32 [[TMP5]]
+;
+ %4 = icmp eq i32 %1, %2
+ %sameValues = icmp ule i32 %1, %2
+ %or = or disjoint i1 %sameValues, %scond
+ %5 = select i1 %or, i32 %2, i32 %1
+ %6 = select i1 %4, i32 %1, i32 %5
+ ret i32 %6
+}
+
>From eedae8781e75110f0f3bf4e3f2b7b60df4f8f957 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 4 Mar 2026 13:42:07 +0100
Subject: [PATCH 2/2] [InstSimplify] Decompose and/or trees to simplify selects
---
llvm/lib/Analysis/InstructionSimplify.cpp | 23 ++-
llvm/lib/Analysis/ValueTracking.cpp | 2 +-
.../Transforms/InstSimplify/select-select.ll | 174 ++++++++++++++++++
3 files changed, 197 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/Transforms/InstSimplify/select-select.ll
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index ceadee5a7705b..97aa01304424e 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -35,6 +35,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
+#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantFPRange.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/DataLayout.h"
@@ -45,6 +46,7 @@
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Statepoint.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/KnownFPClass.h"
#include <algorithm>
@@ -4411,9 +4413,13 @@ static bool areTheseAllTheValuesThatMayCausePoisonInValue(
return true;
if (const Instruction *I = dyn_cast<Instruction>(V)) {
+ // Having a poison generating annotation means that it can be poison
+ // without any of the given values being poison.
if (I->hasPoisonGeneratingAnnotations())
return false;
+ // Filtering out the assumed poison values, so only the relevant ones are
+ // brought forward to the next recursive call.
SmallVector<const Value *, 2> ValuesImplyingPoison;
copy_if(ValuesAssumedPoison, std::back_inserter(ValuesImplyingPoison),
[V](const auto *P) { return impliesPoison(P, V); });
@@ -4431,6 +4437,11 @@ static bool areTheseAllTheValuesThatMayCausePoisonInValue(
ValuesImplyingPoison, Op, Depth + 1);
});
}
+
+ // A constant can't cause poison, unless it is itself a poison.
+ if (const Constant *C = dyn_cast<Constant>(V))
+ return !C->containsUndefOrPoisonElement();
+
return false;
}
@@ -4603,7 +4614,7 @@ static Value *simplifyWithOpsReplaced(Value *V,
// refinment.
if (NewOps[1] == NewOps[2] &&
areTheseAllTheValuesThatMayCausePoisonInValue(
- {SI->getFalseValue(), SI->getTrueValue()}, Cond))
+ {SI->getFalseValue(), SI->getTrueValue(), NewOps[1]}, Cond))
SimplifiedValue = NewOps[1];
// TODO: Implement more non refining select optimizations here!
@@ -5280,6 +5291,16 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
return ConstantVector::get(NewC);
}
+ CmpPredicate Pred1, Pred2;
+ Value *V1, *V2, *EQV;
+ if (match(Cond,
+ m_And(m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(V1), m_Value(EQV)),
+ m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(V2),
+ m_Deferred(EQV)))))
+ if (Value *V = simplifySelectWithEquivalence(
+ {{V2, EQV}, {V1, EQV}}, TrueVal, FalseVal, Q, MaxRecurse))
+ return V;
+
if (Value *V =
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
return V;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c8f53f903428d..4c542b667a05b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7611,7 +7611,7 @@ static bool directlyImpliesPoison(const Value *ValAssumedPoison, const Value *V,
if (ValAssumedPoison == V)
return true;
- const unsigned MaxDepth = 2;
+ const unsigned MaxDepth = 3;
if (Depth >= MaxDepth)
return false;
diff --git a/llvm/test/Transforms/InstSimplify/select-select.ll b/llvm/test/Transforms/InstSimplify/select-select.ll
new file mode 100644
index 0000000000000..393d6bb6f0253
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/select-select.ll
@@ -0,0 +1,174 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+define i32 @AndICmpConstant(i32 %6, i32 %44) {
+; CHECK-LABEL: @AndICmpConstant(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46
+ %48 = xor i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+
+define i32 @AndICmp(i32 %6, i32 %44, i32 %val) {
+; CHECK-LABEL: @AndICmp(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], [[VAL:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], [[VAL]]
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, %val
+ %47 = icmp eq i32 %6, %val
+ %or.cond.i = and i1 %47, %46
+ %48 = xor i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 %val, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @AndICmpRemovedNonConst(i32 %6, i32 %44, i32 %val) {
+; CHECK-LABEL: @AndICmpRemovedNonConst(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], [[VAL:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], [[VAL]]
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP5]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 [[VAL]], i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, %val
+ %47 = icmp eq i32 %6, %val
+ %or.cond.i = and i1 %47, %46
+ %48 = xor i1 %47, true
+ %spec.select.i = select i1 %48, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 %val, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @AndICmpAnd(i32 %6, i32 %44) {
+; CHECK-LABEL: @AndICmpAnd(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46
+ %48 = xor i1 %47, true
+ %49 = and i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @AndICmpAnd2(i32 %6, i32 %44) {
+; CHECK-LABEL: @AndICmpAnd2(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP5]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46
+ %48 = and i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @negative_firstSelectPoisonBarrier(i32 %6, i32 %44, i1 %cond) {
+; CHECK-LABEL: @negative_firstSelectPoisonBarrier(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[COND:%.*]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46
+ %spec.select.i = select i1 %cond, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @negative_selectCondOnlyMutualOneArm(i32 %6, i32 %44) {
+; CHECK-LABEL: @negative_selectCondOnlyMutualOneArm(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP4]], i32 [[TMP0]], i32 [[TMP1:%.*]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46
+ %48 = xor i1 %47, true
+ %spec.select.i = select i1 %48, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @negative_condMorePoisonThanArm(i32 %0, i32 %1) {
+; CHECK-LABEL: @negative_condMorePoisonThanArm(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i1 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP5]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %3 = icmp eq i32 %1, 4
+ %4 = icmp eq i32 %0, 4
+ %or.cond.i = and i1 %4, %3
+ %5 = and i1 %4, true
+ %6 = or disjoint i1 %3, %5
+ %spec.select.i = select i1 %6, i32 %0, i32 %1
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @negative_CmpUsed(i32 %6, i32 %44) {
+; CHECK-LABEL: @negative_CmpUsed(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: call void @use32(i1 [[OR_COND_I]])
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46
+ %48 = xor i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ call void @use32(i1 %or.cond.i)
+ ret i32 %.0.i8
+}
+
+declare void @use32(i1)
More information about the llvm-commits
mailing list