-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[InstCombine] Fold (X == 0 ? Y : 0) | X to X == 0 ? Y : X #138373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-transforms Author: None (YLChenZ) ChangesCloses #137161. Full diff: https://github.com/llvm/llvm-project/pull/138373.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index f059d87e581fd..77e886c98261c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3575,6 +3575,41 @@ static Value *foldOrOfInversions(BinaryOperator &I,
return nullptr;
}
+// Optimize patterns where an OR operation combines a select-based zero check
+// with its condition value. This handles both scalar and vector types.
+//
+// Given:
+// (X == 0 ? Y : 0) | X --> X == 0 ? Y : X
+// X | (X == 0 ? Y : 0) --> X == 0 ? Y : X
+//
+// Also handles cases where X might be wrapped in zero/sign extensions.
+static Instruction *foldOrOfSelectZero(BinaryOperator &BO, Value *Op0,
+ Value *Op1) {
+ CmpPredicate Pred;
+ Value *X, *Y;
+
+ // Check both operand orders to handle commutative OR
+ for (Value *SelVal : {Op0, Op1}) {
+ // The other operand in the OR operation (potentially X or extended X)
+ Value *Other = (SelVal == Op0) ? Op1 : Op0;
+
+ // Attempt to match the select pattern:
+ // select(icmp eq X, 0), Y, 0
+ // Where X might be:
+ // - Original value
+ // - Zero extended value (zext)
+ // - Sign extended value (sext)
+ if (match(SelVal, m_Select(m_c_ICmp(Pred, m_Value(X), m_Zero()), m_Value(Y),
+ m_Zero())) &&
+ Pred == ICmpInst::ICMP_EQ &&
+ match(Other, m_ZExtOrSExtOrSelf(m_Specific(X)))) {
+ return SelectInst::Create(cast<SelectInst>(SelVal)->getCondition(), Y,
+ Other);
+ }
+ }
+ return nullptr;
+}
+
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
// here. We should standardize that construct where it is needed or choose some
// other way to ensure that commutated variants of patterns are not missed.
@@ -3657,6 +3692,11 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
/*NSW=*/true, /*NUW=*/true))
return R;
}
+
+ // (X == 0 ? Y : 0) | X -> X == 0 ? Y : X
+ // X | (X == 0 ? Y : 0) -> X == 0 ? Y : X
+ if (Instruction *R = foldOrOfSelectZero(I, Op0, Op1))
+ return R;
Value *X, *Y;
const APInt *CV;
diff --git a/llvm/test/Transforms/InstCombine/or-select-zero-icmp.ll b/llvm/test/Transforms/InstCombine/or-select-zero-icmp.ll
new file mode 100644
index 0000000000000..fc6b47f0eeb17
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/or-select-zero-icmp.ll
@@ -0,0 +1,144 @@
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; Basic functional test
+define i32 @basic(i32 %a, i32 %b) {
+; CHECK-LABEL: @basic(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[B:%.*]], i32 [[A]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %cmp = icmp eq i32 %a, 0
+ %sel = select i1 %cmp, i32 %b, i32 0
+ %or = or i32 %sel, %a
+ ret i32 %or
+}
+
+; Operand order swap test
+define i32 @swap_operand_order(i32 %x, i32 %y) {
+; CHECK-LABEL: @swap_operand_order(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[Y:%.*]], i32 [[X]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %cmp = icmp eq i32 %x, 0
+ %sel = select i1 %cmp, i32 %y, i32 0
+ %or = or i32 %x, %sel
+ ret i32 %or
+}
+
+; Negative test: Non-zero false value in select
+define i32 @negative_non_zero_false_val(i32 %a, i32 %b) {
+; CHECK-LABEL: @negative_non_zero_false_val(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[B:%.*]], i32 1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[SEL]], [[A]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %cmp = icmp eq i32 %a, 0
+ %sel = select i1 %cmp, i32 %b, i32 1
+ %or = or i32 %sel, %a
+ ret i32 %or
+}
+
+; Negative test: Incorrect comparison predicate (NE)
+define i32 @negative_wrong_predicate(i32 %a, i32 %b) {
+; CHECK-LABEL: @negative_wrong_predicate(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 0, i32 [[B:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[SEL]], [[A]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %cmp = icmp ne i32 %a, 0
+ %sel = select i1 %cmp, i32 %b, i32 0
+ %or = or i32 %sel, %a
+ ret i32 %or
+}
+
+; Comparison direction swap test (0 == X)
+define i32 @cmp_swapped(i32 %x, i32 %y) {
+; CHECK-LABEL: @cmp_swapped(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[Y:%.*]], i32 [[X]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %cmp = icmp eq i32 0, %x
+ %sel = select i1 %cmp, i32 %y, i32 0
+ %or = or i32 %x, %sel
+ ret i32 %or
+}
+
+; Complex expression test
+define i32 @complex_expression(i32 %a, i32 %b) {
+; CHECK-LABEL: @complex_expression(
+; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 0
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[B:%.*]], i32 [[X]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %x = add i32 %a, 1
+ %cmp = icmp eq i32 %x, 0
+ %sel = select i1 %cmp, i32 %b, i32 0
+ %or = or i32 %sel, %x
+ ret i32 %or
+}
+
+; zext test
+define i32 @zext_cond(i8 %a, i32 %b) {
+; CHECK-LABEL: @zext_cond(
+; CHECK-NEXT: [[Z:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP]], i32 [[B:%.*]], i32 [[Z]]
+; CHECK-NEXT: ret i32 [[OR]]
+ %z = zext i8 %a to i32
+ %cmp = icmp eq i32 %z, 0
+ %sel = select i1 %cmp, i32 %b, i32 0
+ %or = or i32 %sel, %z
+ ret i32 %or
+}
+
+; sext test
+define i32 @sext_cond(i8 %a, i32 %b) {
+; CHECK-LABEL: @sext_cond(
+; CHECK-NEXT: [[S:%.*]] = sext i8 [[A:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP]], i32 [[B:%.*]], i32 [[S]]
+; CHECK-NEXT: ret i32 [[OR]]
+ %s = sext i8 %a to i32
+ %cmp = icmp eq i32 %s, 0
+ %sel = select i1 %cmp, i32 %b, i32 0
+ %or = or i32 %sel, %s
+ ret i32 %or
+}
+
+; Vector type test
+define <2 x i32> @vector_type(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @vector_type(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], zeroinitializer
+; CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[B:%.*]], <2 x i32> [[A]]
+; CHECK-NEXT: ret <2 x i32> [[RES]]
+;
+ %cmp = icmp eq <2 x i32> %a, zeroinitializer
+ %sel = select <2 x i1> %cmp, <2 x i32> %b, <2 x i32> zeroinitializer
+ %or = or <2 x i32> %sel, %a
+ ret <2 x i32> %or
+}
+
+; Pointer type test (should not trigger optimization)
+define i32* @pointer_type(i32* %p, i32* %q) {
+; CHECK-LABEL: @pointer_type(
+; CHECK-NEXT: [[A:%.*]] = ptrtoint ptr [[P:%.*]] to i64
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], null
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], ptr [[Q:%.*]], ptr null
+; CHECK-NEXT: [[SEL_INT:%.*]] = ptrtoint ptr [[SEL]] to i64
+; CHECK-NEXT: [[OR:%.*]] = or i64 [[A]], [[SEL_INT]]
+; CHECK-NEXT: [[RET:%.*]] = inttoptr i64 [[OR]] to ptr
+; CHECK-NEXT: ret ptr [[RET]]
+;
+ %a = ptrtoint i32* %p to i64
+ %cmp = icmp eq i64 %a, 0
+ %sel = select i1 %cmp, i32* %q, i32* null
+ %sel_int = ptrtoint i32* %sel to i64
+ %or_val = or i64 %a, %sel_int
+ %ret = inttoptr i64 %or_val to i32*
+ ret i32* %ret
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
// - Original value | ||
// - Zero extended value (zext) | ||
// - Sign extended value (sext) | ||
if (match(SelVal, m_Select(m_c_ICmp(Pred, m_Value(X), m_Zero()), m_Value(Y), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (match(SelVal, m_Select(m_c_ICmp(Pred, m_Value(X), m_Zero()), m_Value(Y), | |
if (match(SelVal, m_Select(m_ICmp(Pred, m_Value(X), m_Zero()), m_Value(Y), |
icmp constant is always on RHS.
%sel = select i1 %cmp, i32 %b, i32 0 | ||
%or = or i32 %sel, %z | ||
ret i32 %or | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this actually tests your zext handling. Don't you need something like this?
define i32 @src(i8 %a, i32 %b) {
%z = zext i8 %a to i32
%cmp = icmp eq i8 %a, 0
%sel = select i1 %cmp, i32 %b, i32 0
%or = or i32 %sel, %z
ret i32 %or
}
That is, the icmp needs to be on the non-zext value.
} | ||
|
||
; Pointer type test (should not trigger optimization) | ||
define i32* @pointer_type(i32* %p, i32* %q) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i32* -> ptr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please add a multi-use test? I don't think we want to do this transform if the select is not one-use. Converting an or to another select is probably not profitable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At a high level, this seems like we should be able to handle it generically with a FoldOpIntoSelect-style transform, but that currently only works with a constant binop operand.
You're right, we should add support for this kind of folding in FoldOpIntoSelect. |
%cmp = icmp eq i32 %x, 0 | ||
%sel = select i1 %cmp, i32 %m, i32 0 | ||
%or = or i32 %sel, %x | ||
%add = add i32 %sel, %x |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might not be the best test, add
should be equivalent to or
in this context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it like this?
define i32 @multi_use_test(i32 %x, i32 %m) {
%cmp = icmp eq i32 %x, 0
%sel = select i1 %cmp, i32 %m, i32 0
%or1 = or i32 %sel, %x
%or2 = or i32 %sel, %x
%res = add i32 %or1, %or2
ret i32 %res
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that add
could be CSEd with or
by some earlier instcombine rule, making the test non-multi-use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I seem to understand your point, so would it be appropriate for me to modify it like this?
define i32 @multi_use_test(i32 %x, i32 %m) {
%cmp = icmp eq i32 %x, 0
%sel = select i1 %cmp, i32 %m, i32 0
%or = or i32 %sel, %x
%mul = mul i32 %sel, %x
%res = add i32 %or, %mul
ret i32 %res
}
I think the mul should not be CSEd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the most reliable way of adding an extra use is to pass it to a call to some void @use(i32)
function. At least it is what I see often. I don't really know the best practices for writing IR tests, so I could be wrong here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the most reliable way of adding an extra use is to pass it to a call to some void use(i32) function.
Yes, I've seen this written in other IR tests.
I don't really know the best practices for writing IR tests, so I could be wrong here.
It's my first time to write such a test and I'm a novice regarding IR.
Thanks for the tips.:)
match(Other, m_ZExtOrSExtOrSelf(m_Specific(X)))) { | ||
return SelectInst::Create(SI->getCondition(), Y, Other); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we ignore the sext/zext case, is this additional code even needed? The reason I suggested FoldOpIntoSelect is that the code in
llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Lines 1658 to 1678 in 5f32b8f
static Value *simplifyOperationIntoSelectOperand(Instruction &I, SelectInst *SI, | |
bool IsTrueArm) { | |
SmallVector<Value *> Ops; | |
for (Value *Op : I.operands()) { | |
Value *V = nullptr; | |
if (Op == SI) { | |
V = IsTrueArm ? SI->getTrueValue() : SI->getFalseValue(); | |
} else if (match(SI->getCondition(), | |
m_SpecificICmp(IsTrueArm ? ICmpInst::ICMP_EQ | |
: ICmpInst::ICMP_NE, | |
m_Specific(Op), m_Value(V))) && | |
isGuaranteedNotToBeUndefOrPoison(V)) { | |
// Pass | |
} else { | |
V = Op; | |
} | |
Ops.push_back(V); | |
} | |
return simplifyInstructionWithOperands(&I, Ops, I.getDataLayout()); | |
} |
if (auto *R = FoldOpIntoSelect(I, SI, /* FoldWithMultiUse */ false)) | ||
return R; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are already calling FoldOpIntoSelect via foldBinOpIntoSelectOrPhi. But that function currently only calls FoldOpIntoSelect if the RHS is a constant.
I think to enable this fold be basically just need to lift that restriction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we ignore the sext/zext case and lift constant restriction, then do the test I get the following result:
llvm test
********************
Timed Out Tests (6):
LLVM :: Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
LLVM :: Transforms/InstCombine/icmp-and-lowbit-mask.ll
LLVM :: Transforms/InstCombine/logical-select-inseltpoison.ll
LLVM :: Transforms/InstCombine/logical-select.ll
LLVM :: Transforms/InstCombine/vec_sext.ll
LLVM :: Transforms/PhaseOrdering/vector-select.ll
********************
Failed Tests (16):
LLVM :: Transforms/InstCombine/binop-phi-operands.ll
LLVM :: Transforms/InstCombine/binop-select.ll
LLVM :: Transforms/InstCombine/dont-distribute-phi.ll
LLVM :: Transforms/InstCombine/fmul.ll
LLVM :: Transforms/InstCombine/free-inversion.ll
LLVM :: Transforms/InstCombine/icmp-or-of-select-with-zero.ll
LLVM :: Transforms/InstCombine/mul-inseltpoison.ll
LLVM :: Transforms/InstCombine/or-select-zero-icmp.ll
LLVM :: Transforms/InstCombine/pr82877.ll
LLVM :: Transforms/InstCombine/recurrence.ll
LLVM :: Transforms/InstCombine/select-cmp-cttz-ctlz.ll
LLVM :: Transforms/InstCombine/select.ll
LLVM :: Transforms/InstCombine/simplify-demanded-fpclass.ll
LLVM :: Transforms/InstCombine/sub-gep.ll
LLVM :: Transforms/InstCombine/xor.ll
LLVM :: Transforms/PhaseOrdering/AArch64/predicated-reduction.ll
clang test
********************
Timed Out Tests (1):
Clang :: CodeGen/SystemZ/builtins-systemz-zvector5.c
--timeout=100
I think the failed may be well handled , but the timed out is tricky, and there should seem to be infinite loops when folding. I don't know if I'm right about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd try to lift the constant restrict only for or
to start with (add an extra parameter AllowNonConstant or something), so we don't have to deal with too many things at once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Followed your tips and made changes accordingly:
Changed foldBinOpIntoSelectOrPhi
:
/// This is a convenience wrapper function for the above two functions.
Instruction *foldBinOpIntoSelectOrPhi(BinaryOperator &I, bool AllowNonConstRHS = false);
...
Instruction *InstCombinerImpl::foldBinOpIntoSelectOrPhi(BinaryOperator &I,
bool AllowNonConstRHS) {
if (!AllowNonConstRHS && !isa<Constant>(I.getOperand(1)))
return nullptr;
...
}
Changed visitOr
:
if (Instruction *FoldedLogic = foldBinOpIntoSelectOrPhi(I, /* AllowNonConstRHS */ true))
return FoldedLogic;
Then do the test, there is still a time out as last time.
So, I added some rough debug messages to some functions:
if (Instruction *FoldedLogic = foldBinOpIntoSelectOrPhi(I, /* AllowNonConstRHS */ true)) {
LLVM_DEBUG(dbgs() << "visitOr on foldBinOpIntoSelectOrPhi at: " << I << '\n');
return FoldedLogic;
}
Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
bool FoldWithMultiUse) {
LLVM_DEBUG(dbgs() << "FoldOpIntoSelect at: " << Op << '\n');
static Value *simplifyOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
bool IsTrueArm) {
LLVM_DEBUG(dbgs() << "simplifyOperationIntoSelectOperand at : " << I << " " <<*SI <<'\n');
static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
Value *NewOp, InstCombiner &IC) {
LLVM_DEBUG(dbgs() << "foldOperationIntoSelectOperand at: " << I << '\n');
And I took the example from vec_sext.ll
that caused time out:
define <4 x i32> @vec_select(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @vec_select(
; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i32> zeroinitializer, [[A:%.*]]
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <4 x i32> [[B:%.*]], zeroinitializer
; CHECK-NEXT: [[T2:%.*]] = select <4 x i1> [[ISNEG]], <4 x i32> zeroinitializer, <4 x i32> [[A]]
; CHECK-NEXT: [[ISNEG1:%.*]] = icmp slt <4 x i32> [[B]], zeroinitializer
; CHECK-NEXT: [[T3:%.*]] = select <4 x i1> [[ISNEG1]], <4 x i32> [[SUB]], <4 x i32> zeroinitializer
; CHECK-NEXT: [[COND:%.*]] = or <4 x i32> [[T2]], [[T3]]
; CHECK-NEXT: ret <4 x i32> [[COND]]
;
%cmp = icmp slt <4 x i32> %b, zeroinitializer
%sext = sext <4 x i1> %cmp to <4 x i32>
%sub = sub nsw <4 x i32> zeroinitializer, %a
%t0 = icmp slt <4 x i32> %sext, zeroinitializer
%sext3 = sext <4 x i1> %t0 to <4 x i32>
%t1 = xor <4 x i32> %sext3, <i32 -1, i32 -1, i32 -1, i32 -1>
%t2 = and <4 x i32> %a, %t1
%t3 = and <4 x i32> %sext3, %sub
%cond = or <4 x i32> %t2, %t3
ret <4 x i32> %cond
}
Test result:
INSTCOMBINE ITERATION #1 on vec_select
ADD: ret <4 x i32> %cond
ADD: %cond = or <4 x i32> %t2, %t3
ADD: %t3 = and <4 x i32> %sext3, %sub
ADD: %t2 = and <4 x i32> %a, %t1
ADD: %t1 = xor <4 x i32> %sext3, splat (i32 -1)
ADD: %sext3 = sext <4 x i1> %t0 to <4 x i32>
ADD: %t0 = icmp slt <4 x i32> %sext, zeroinitializer
ADD: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %sext = sext <4 x i1> %cmp to <4 x i32>
ADD: %cmp = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %cmp = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sext = sext <4 x i1> %cmp to <4 x i32>
ADD DEFERRED: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Replacing %sext = sext <4 x i1> %cmp to <4 x i32>
with %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Mod = %sext = sext <4 x i1> %cmp to <4 x i32>
New = %sext = sext <4 x i1> %cmp to <4 x i32>
IC: ERASE %sext = sext <4 x i1> %cmp to <4 x i32>
ADD DEFERRED: %cmp = icmp slt <4 x i32> %b, zeroinitializer
IC: ERASE %cmp = icmp slt <4 x i32> %b, zeroinitializer
ADD: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Visiting: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Visiting: %sub = sub nsw <4 x i32> zeroinitializer, %a
Negator: attempting to sink negation into <4 x i32> %a
Negator: failed to sink negation into <4 x i32> %a
IC: Visiting: %t0 = icmp slt <4 x i32> %b.lobit, zeroinitializer
ADD DEFERRED: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Mod = %t0 = icmp slt <4 x i32> %b.lobit, zeroinitializer
New = %t0 = icmp slt <4 x i32> %b, zeroinitializer
ADD: %t0 = icmp slt <4 x i32> %b, zeroinitializer
IC: ERASE %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Visiting: %t0 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sext3 = sext <4 x i1> %t0 to <4 x i32>
ADD DEFERRED: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Replacing %sext3 = sext <4 x i1> %t0 to <4 x i32>
with %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Mod = %sext3 = sext <4 x i1> %t0 to <4 x i32>
New = %sext3 = sext <4 x i1> %t0 to <4 x i32>
IC: ERASE %sext3 = sext <4 x i1> %t0 to <4 x i32>
ADD DEFERRED: %t0 = icmp slt <4 x i32> %b, zeroinitializer
IC: ERASE %t0 = icmp slt <4 x i32> %b, zeroinitializer
ADD: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Visiting: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Visiting: %t1 = xor <4 x i32> %b.lobit, splat (i32 -1)
IC: Visiting: %t2 = and <4 x i32> %a, %t1
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Old = %t2 = and <4 x i32> %a, %t1
New = <badref> = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD: %t2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: ERASE %1 = and <4 x i32> %a, %t1
ADD DEFERRED: %t1 = xor <4 x i32> %b.lobit, splat (i32 -1)
IC: ERASE %t1 = xor <4 x i32> %b.lobit, splat (i32 -1)
ADD DEFERRED: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
ADD DEFERRED: %t3 = and <4 x i32> %b.lobit, %sub
ADD: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
IC: Visiting: %t2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %t3 = and <4 x i32> %b.lobit, %sub
ADD DEFERRED: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Old = %t3 = and <4 x i32> %b.lobit, %sub
New = <badref> = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: ERASE %1 = and <4 x i32> %b.lobit, %sub
ADD DEFERRED: %b.lobit = ashr <4 x i32> %b, splat (i32 31)
ADD DEFERRED: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD DEFERRED: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %sub = sub nsw <4 x i32> zeroinitializer, %a
IC: ERASE %b.lobit = ashr <4 x i32> %b, splat (i32 31)
ADD: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sub = sub nsw <4 x i32> zeroinitializer, %a
Negator: attempting to sink negation into <4 x i32> %a
Negator: failed to sink negation into <4 x i32> %a
IC: Visiting: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = or <4 x i32> %t2, %t3
FoldOpIntoSelect at: %cond = or <4 x i32> %t2, %t3
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %t2, %t3 %t2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %t2, %t3 %t2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
foldOperationIntoSelectOperand at: %cond = or <4 x i32> %t2, %t3
ADD DEFERRED: %1 = or <4 x i32> %a, %t3
visitOr on foldBinOpIntoSelectOrPhi at: %cond = or <4 x i32> %t2, %t3
IC: Old = %cond = or <4 x i32> %t2, %t3
New = <badref> = select <4 x i1> %isneg, <4 x i32> %t3, <4 x i32> %1
ADD: %cond = select <4 x i1> %isneg, <4 x i32> %t3, <4 x i32> %1
IC: ERASE %2 = or <4 x i32> %t2, %t3
ADD DEFERRED: %t2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: ERASE %t2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %cond = select <4 x i1> %isneg, <4 x i32> %t3, <4 x i32> %1
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD: %1 = or <4 x i32> %a, %t3
IC: Visiting: %1 = or <4 x i32> %a, %t3
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = select <4 x i1> %isneg, <4 x i32> %t3, <4 x i32> %1
ADD DEFERRED: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Old = %cond = select <4 x i1> %isneg, <4 x i32> %t3, <4 x i32> %1
New = <badref> = or <4 x i32> %t3, %2
ADD: %cond = or <4 x i32> %t3, %2
IC: ERASE %3 = select <4 x i1> %isneg, <4 x i32> %t3, <4 x i32> %1
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %1 = or <4 x i32> %a, %t3
IC: ERASE %1 = or <4 x i32> %a, %t3
ADD DEFERRED: %cond = or <4 x i32> %t3, %1
ADD: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = or <4 x i32> %t3, %1
FoldOpIntoSelect at: %cond = or <4 x i32> %t3, %1
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %t3, %1 %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %t3, %1 %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
foldOperationIntoSelectOperand at: %cond = or <4 x i32> %t3, %1
ADD DEFERRED: %2 = or <4 x i32> %sub, %1
visitOr on foldBinOpIntoSelectOrPhi at: %cond = or <4 x i32> %t3, %1
IC: Old = %cond = or <4 x i32> %t3, %1
New = <badref> = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD: %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
IC: ERASE %3 = or <4 x i32> %t3, %1
ADD DEFERRED: %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: ERASE %t3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD DEFERRED: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = or <4 x i32> %sub, %1
IC: Visiting: %2 = or <4 x i32> %sub, %1
IC: Mod = %2 = or <4 x i32> %sub, %1
New = %2 = or <4 x i32> %1, %sub
ADD: %2 = or <4 x i32> %1, %sub
IC: Visiting: %2 = or <4 x i32> %1, %sub
FoldOpIntoSelect at: %2 = or <4 x i32> %1, %sub
IC: Visiting: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sub = sub nsw <4 x i32> zeroinitializer, %a
Negator: attempting to sink negation into <4 x i32> %a
Negator: failed to sink negation into <4 x i32> %a
IC: Visiting: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD DEFERRED: %3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Old = %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
New = <badref> = or <4 x i32> %1, %3
ADD: %cond = or <4 x i32> %1, %3
IC: ERASE %4 = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD DEFERRED: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %2 = or <4 x i32> %1, %sub
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: ERASE %2 = or <4 x i32> %1, %sub
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %cond = or <4 x i32> %1, %2
ADD DEFERRED: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sub = sub nsw <4 x i32> zeroinitializer, %a
Negator: attempting to sink negation into <4 x i32> %a
Negator: failed to sink negation into <4 x i32> %a
IC: Visiting: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %cond = or <4 x i32> %1, %2
FoldOpIntoSelect at: %cond = or <4 x i32> %1, %2
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
foldOperationIntoSelectOperand at: %cond = or <4 x i32> %1, %2
ADD DEFERRED: %3 = or <4 x i32> %a, %2
visitOr on foldBinOpIntoSelectOrPhi at: %cond = or <4 x i32> %1, %2
IC: Old = %cond = or <4 x i32> %1, %2
New = <badref> = select <4 x i1> %isneg, <4 x i32> %2, <4 x i32> %3
ADD: %cond = select <4 x i1> %isneg, <4 x i32> %2, <4 x i32> %3
IC: ERASE %4 = or <4 x i32> %1, %2
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: ERASE %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %cond = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = or <4 x i32> %a, %1
IC: Visiting: %2 = or <4 x i32> %a, %1
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
ADD DEFERRED: %3 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Old = %cond = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
New = <badref> = or <4 x i32> %1, %3
ADD: %cond = or <4 x i32> %1, %3
IC: ERASE %4 = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %2 = or <4 x i32> %a, %1
IC: ERASE %2 = or <4 x i32> %a, %1
ADD DEFERRED: %cond = or <4 x i32> %1, %2
ADD: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = or <4 x i32> %1, %2
FoldOpIntoSelect at: %cond = or <4 x i32> %1, %2
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
foldOperationIntoSelectOperand at: %cond = or <4 x i32> %1, %2
ADD DEFERRED: %3 = or <4 x i32> %sub, %2
visitOr on foldBinOpIntoSelectOrPhi at: %cond = or <4 x i32> %1, %2
IC: Old = %cond = or <4 x i32> %1, %2
New = <badref> = select <4 x i1> %isneg1, <4 x i32> %3, <4 x i32> %2
ADD: %cond = select <4 x i1> %isneg1, <4 x i32> %3, <4 x i32> %2
IC: ERASE %4 = or <4 x i32> %1, %2
ADD DEFERRED: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: ERASE %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD DEFERRED: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = or <4 x i32> %sub, %1
IC: Visiting: %2 = or <4 x i32> %sub, %1
IC: Mod = %2 = or <4 x i32> %sub, %1
New = %2 = or <4 x i32> %1, %sub
ADD: %2 = or <4 x i32> %1, %sub
IC: Visiting: %2 = or <4 x i32> %1, %sub
FoldOpIntoSelect at: %2 = or <4 x i32> %1, %sub
IC: Visiting: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sub = sub nsw <4 x i32> zeroinitializer, %a
Negator: attempting to sink negation into <4 x i32> %a
Negator: failed to sink negation into <4 x i32> %a
IC: Visiting: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD DEFERRED: %3 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Old = %cond = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
New = <badref> = or <4 x i32> %1, %3
ADD: %cond = or <4 x i32> %1, %3
IC: ERASE %4 = select <4 x i1> %isneg1, <4 x i32> %2, <4 x i32> %1
ADD DEFERRED: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %2 = or <4 x i32> %1, %sub
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: ERASE %2 = or <4 x i32> %1, %sub
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %cond = or <4 x i32> %1, %2
ADD DEFERRED: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %sub = sub nsw <4 x i32> zeroinitializer, %a
ADD: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %isneg1 = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %sub = sub nsw <4 x i32> zeroinitializer, %a
Negator: attempting to sink negation into <4 x i32> %a
Negator: failed to sink negation into <4 x i32> %a
IC: Visiting: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %cond = or <4 x i32> %1, %2
FoldOpIntoSelect at: %cond = or <4 x i32> %1, %2
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
foldOperationIntoSelectOperand at: %cond = or <4 x i32> %1, %2
ADD DEFERRED: %3 = or <4 x i32> %a, %2
visitOr on foldBinOpIntoSelectOrPhi at: %cond = or <4 x i32> %1, %2
IC: Old = %cond = or <4 x i32> %1, %2
New = <badref> = select <4 x i1> %isneg, <4 x i32> %2, <4 x i32> %3
ADD: %cond = select <4 x i1> %isneg, <4 x i32> %2, <4 x i32> %3
IC: ERASE %4 = or <4 x i32> %1, %2
ADD DEFERRED: %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %2 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: ERASE %1 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %cond = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = or <4 x i32> %a, %1
IC: Visiting: %2 = or <4 x i32> %a, %1
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
ADD DEFERRED: %3 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Old = %cond = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
New = <badref> = or <4 x i32> %1, %3
ADD: %cond = or <4 x i32> %1, %3
IC: ERASE %4 = select <4 x i1> %isneg, <4 x i32> %1, <4 x i32> %2
ADD DEFERRED: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD DEFERRED: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD DEFERRED: %2 = or <4 x i32> %a, %1
IC: ERASE %2 = or <4 x i32> %a, %1
ADD DEFERRED: %cond = or <4 x i32> %1, %2
ADD: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
ADD: %isneg = icmp slt <4 x i32> %b, zeroinitializer
ADD: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %2 = select <4 x i1> %isneg, <4 x i32> zeroinitializer, <4 x i32> %a
IC: Visiting: %isneg = icmp slt <4 x i32> %b, zeroinitializer
IC: Visiting: %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
IC: Visiting: %cond = or <4 x i32> %1, %2
FoldOpIntoSelect at: %cond = or <4 x i32> %1, %2
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
simplifyOperationIntoSelectOperand at : %cond = or <4 x i32> %1, %2 %1 = select <4 x i1> %isneg1, <4 x i32> %sub, <4 x i32> zeroinitializer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the reverse transformation is done by foldSelectIntoOp()
.
See the comment near getSelectFoldableOperands()
(initially introduced by 56e4d3d back in 2004).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting! A way to prevent the infinite loop would be to allow the non-constant case only in case both select operands fold (rather than only one).
Closes #137161.
Proof: https://alive2.llvm.org/ce/z/UzdBeu.