[llvm] [InstCombine] Try optimizing with knownbits which determined from Cond (PR #91762)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 10 09:08:36 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: hanbeom (ParkHanbum)
<details>
<summary>Changes</summary>
This PR was submitted to implement the optimizations discussed in https://github.com/llvm/llvm-project/pull/73362.
Q.
I have very little experience sending PRs, is this the right way to write commit messages for tests related to a patch?
please let me know if I'm wrong
---
Patch is 24.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/91762.diff
6 Files Affected:
- (modified) llvm/include/llvm/Analysis/ValueTracking.h (+4)
- (modified) llvm/include/llvm/Transforms/InstCombine/InstCombiner.h (+7)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+3-3)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+158)
- (modified) llvm/test/Transforms/InstCombine/select-of-bittest.ll (+196-3)
- (modified) llvm/test/Transforms/InstCombine/select.ll (+13-34)
``````````diff
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 571e44cdac265..0bf8c4ce0faa7 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -94,6 +94,10 @@ void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, KnownBits &Known);
void computeKnownBitsFromContext(const Value *V, KnownBits &Known,
unsigned Depth, const SimplifyQuery &Q);
+void computeKnownBitsFromCond(const Value *V, Value *Cond, KnownBits &Known,
+ unsigned Depth, const SimplifyQuery &SQ,
+ bool Invert);
+
/// Using KnownBits LHS/RHS produce the known bits for logic op (and/xor/or).
KnownBits analyzeKnownBitsFromAndXorOr(const Operator *I,
const KnownBits &KnownLHS,
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index ea1f4fc3b85dc..e654eeb1b234a 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -438,6 +438,13 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
return llvm::computeKnownBits(V, Depth, SQ.getWithInstruction(CxtI));
}
+ void computeKnownBitsFromCond(const Value *V, ICmpInst *Cmp, KnownBits &Known,
+ unsigned Depth, const Instruction *CxtI,
+ bool Invert) const {
+ llvm::computeKnownBitsFromCond(V, Cmp, Known, Depth,
+ SQ.getWithInstruction(CxtI), Invert);
+ }
+
bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero = false,
unsigned Depth = 0,
const Instruction *CxtI = nullptr) {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index de38eddaa98fe..dba9b394ff165 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -735,9 +735,9 @@ static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp,
computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
}
-static void computeKnownBitsFromCond(const Value *V, Value *Cond,
- KnownBits &Known, unsigned Depth,
- const SimplifyQuery &SQ, bool Invert) {
+void llvm::computeKnownBitsFromCond(const Value *V, Value *Cond,
+ KnownBits &Known, unsigned Depth,
+ const SimplifyQuery &SQ, bool Invert) {
Value *A, *B;
if (Depth < MaxAnalysisRecursionDepth &&
match(Cond, m_LogicalOp(m_Value(A), m_Value(B)))) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 117eb7a1dcc93..ef9931f440d0d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1790,6 +1790,160 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
return nullptr;
}
+// ICmpInst of SelectInst is not included in the calculation of KnownBits
+// so we are missing the opportunity to optimize the Value of the True or
+// False Condition via ICmpInst with KnownBits.
+//
+// Consider:
+// %or = or i32 %x, %y
+// %or0 = icmp eq i32 %or, 0
+// %and = and i32 %x, %y
+// %cond = select i1 %or0, i32 %and, i32 %or
+// ret i32 %cond
+//
+// Expect:
+// %or = or i32 %x, %y
+// ret i32 %or
+//
+// We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
+static Instruction *foldSelectICmpBinOp(SelectInst &SI, ICmpInst *ICI,
+ Value *CmpLHS, Value *CmpRHS,
+ Value *TVal, Value *FVal,
+ InstCombinerImpl &IC) {
+ Value *X, *Y;
+ const APInt *C;
+
+ if (!((match(CmpLHS, m_BinOp(m_Value(X), m_Value(Y))) &&
+ match(CmpRHS, m_APInt(C))) &&
+ (match(TVal, m_c_BinOp(m_Specific(X), m_Value())) ||
+ match(TVal, m_c_BinOp(m_Specific(Y), m_Value())))))
+ return nullptr;
+
+ LLVM_DEBUG(dbgs() << "ENTER: ";CmpLHS->dump();CmpRHS->dump();TVal->dump(););
+ enum SpecialKnownBits {
+ NOTHING_SPECIAL = 0,
+ NO_COMMON_BITS = 1 << 1,
+ ALL_COMMON_BITS = 1 << 2,
+ ALL_BITS_ENABLED = 1 << 3,
+ };
+
+ // We cannot know exactly what bits is known in X Y.
+ // Instead, we just know what relationship exist for.
+ auto isSpecialKnownBitsFor = [&](const Instruction *CmpLHS,
+ const APInt *CmpRHS) -> unsigned {
+ unsigned Opc = CmpLHS->getOpcode();
+ if (Opc == Instruction::And) {
+ if (CmpRHS->isZero())
+ return NO_COMMON_BITS;
+ } else if (Opc == Instruction::Xor) {
+ if (CmpRHS->isAllOnes())
+ return NO_COMMON_BITS | ALL_BITS_ENABLED;
+ if (CmpRHS->isZero())
+ return ALL_COMMON_BITS;
+ }
+
+ return NOTHING_SPECIAL;
+ };
+
+ auto hasOperandAt = [&](Instruction *I, Value *Op) -> int {
+ for (unsigned Idx = 0; Idx < I->getNumOperands(); Idx++) {
+ if (I->getOperand(Idx) == Op)
+ return Idx + 1;
+ }
+ return 0;
+ };
+
+ Type *TValTy = TVal->getType();
+ unsigned BitWidth = TVal->getType()->getScalarSizeInBits();
+ auto TValBop = cast<BinaryOperator>(TVal);
+ auto CmpLHSBop = cast<BinaryOperator>(CmpLHS);
+ unsigned XOrder = hasOperandAt(TValBop, X);
+ unsigned YOrder = hasOperandAt(TValBop, Y);
+ unsigned SKB = isSpecialKnownBitsFor(CmpLHSBop, C);
+
+ KnownBits Known;
+ if (TValBop->isBitwiseLogicOp()) {
+ if (SKB != SpecialKnownBits::NOTHING_SPECIAL && XOrder && YOrder) {
+ if (SKB & SpecialKnownBits::NO_COMMON_BITS) {
+ if (SKB & (SpecialKnownBits::ALL_BITS_ENABLED)) {
+ if (TValBop->getOpcode() == Instruction::Xor)
+ Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+ }
+ if (TValBop->getOpcode() == Instruction::And)
+ Known = KnownBits::makeConstant(APInt(BitWidth, 0));
+ else if ((match(TVal, m_c_Or(m_Specific(X), m_Specific(Y))) &&
+ match(FVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) ||
+ (match(TVal, m_c_Xor(m_Specific(X), m_Specific(Y))) &&
+ match(FVal, m_c_Or(m_Specific(X), m_Specific(Y)))))
+ return IC.replaceInstUsesWith(SI, FVal);
+ } else if (SKB & SpecialKnownBits::ALL_COMMON_BITS) {
+ if (TValBop->getOpcode() == Instruction::And ||
+ TValBop->getOpcode() == Instruction::Or)
+ if (TValBop->hasOneUse())
+ return IC.replaceOperand(SI, 1, X);
+ } else if (SKB & SpecialKnownBits::ALL_BITS_ENABLED) {
+ if (TValBop->getOpcode() == Instruction::Or)
+ Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+ }
+ } else {
+ KnownBits XKnown, YKnown, Temp;
+ KnownBits TValBop0KB, TValBop1KB;
+ XKnown = IC.computeKnownBits(X, 0, &SI);
+ IC.computeKnownBitsFromCond(X, ICI, XKnown, 0, &SI, false);
+ YKnown = IC.computeKnownBits(Y, 0, &SI);
+ IC.computeKnownBitsFromCond(Y, ICI, YKnown, 0, &SI, false);
+
+ // Estimate additional KnownBits from the relationship between X and Y
+ CmpInst::Predicate Pred = ICI->getPredicate();
+ if (Pred == ICmpInst::ICMP_EQ) {
+ if (CmpLHSBop->getOpcode() == Instruction::And) {
+ XKnown.Zero |= ~*C & YKnown.One;
+ YKnown.Zero |= ~*C & XKnown.One;
+ }
+ if (CmpLHSBop->getOpcode() == Instruction::Or) {
+ XKnown.One |= *C & YKnown.Zero;
+ YKnown.One |= *C & XKnown.Zero;
+ }
+ if (CmpLHSBop->getOpcode() == Instruction::Xor) {
+ XKnown.One |= *C & YKnown.Zero;
+ XKnown.Zero |= *C & YKnown.One;
+ YKnown.One |= *C & XKnown.Zero;
+ YKnown.Zero |= *C & XKnown.One;
+ XKnown.Zero |= ~*C & YKnown.Zero;
+ XKnown.One |= ~*C & YKnown.One;
+ YKnown.Zero |= ~*C & XKnown.Zero;
+ YKnown.One |= ~*C & XKnown.One;
+ }
+ }
+
+ auto getTValBopKB = [&](unsigned OpNum) -> KnownBits {
+ unsigned Order = OpNum + 1;
+ if (Order == XOrder)
+ return XKnown;
+ else if (Order == YOrder)
+ return YKnown;
+
+ Value *V = TValBop->getOperand(OpNum);
+ KnownBits Known = IC.computeKnownBits(V, 0, &SI);
+ IC.computeKnownBitsFromCond(V, ICI, Known, 0, &SI, false);
+ return Known;
+ };
+ TValBop0KB = getTValBopKB(0);
+ TValBop1KB = getTValBopKB(1);
+ Known = analyzeKnownBitsFromAndXorOr(
+ cast<Operator>(TValBop), TValBop0KB, TValBop1KB, 0,
+ IC.getSimplifyQuery().getWithInstruction(&SI));
+ }
+ }
+
+ if (Known.isConstant()) {
+ auto Const = ConstantInt::get(TValTy, Known.getConstant());
+ return IC.replaceOperand(SI, 1, Const);
+ }
+
+ return nullptr;
+}
+
/// Visit a SelectInst that has an ICmpInst as its first operand.
Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
ICmpInst *ICI) {
@@ -1932,6 +2086,10 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
if (Value *V = foldAbsDiff(ICI, TrueVal, FalseVal, Builder))
return replaceInstUsesWith(SI, V);
+ if (Instruction *NewSel = foldSelectICmpBinOp(SI, ICI, CmpLHS, CmpRHS,
+ TrueVal, FalseVal, *this))
+ return NewSel;
+
return Changed ? &SI : nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index e3eb76de459e2..ab2b93252f0d6 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -3,7 +3,200 @@
; https://bugs.llvm.org/show_bug.cgi?id=36950
-; These all should be just and+icmp, there should be no select.
+
+
+; ====================== AND =======================
+define i8 @src_and_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_and_bit(
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 3
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 2
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 2, i8 1
+; CHECK-NEXT: ret i8 [[COND]]
+;
+ %and = and i8 %x, 3
+ %and1 = and i8 %x, 2
+ %and2 = and i8 %and, %x
+ %cmp = icmp eq i8 %and2, 2
+ %cond = select i1 %cmp, i8 %and1, i8 1
+ ret i8 %cond
+}
+define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %x, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 2, i8 2>
+ %and2 = and <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %x, <i8 poison, i8 3>
+ %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+ %and2 = and <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison2(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %x, <i8 poison, i8 3>
+ %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+ %and2 = and <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+
+; ====================== OR =======================
+define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @src_or_bit(
+; CHECK-NEXT: [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
+; CHECK-NEXT: [[SHL:%.*]] = and i8 [[AND1]], 12
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 3
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
+; CHECK-NEXT: ret i8 [[COND]]
+;
+ %and = and i8 %z, 3
+ %and1 = shl i8 %y, 2
+ %shl = and i8 %and1, 12
+ %or = or i8 %shl, %x
+ %cmp = icmp eq i8 %or, 3
+ %or2 = or i8 %and, %x
+ %cond = select i1 %cmp, i8 %or2, i8 1
+ ret i8 %cond
+}
+define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec(
+; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
+; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %z, <i8 3, i8 3>
+ %and1 = shl <2 x i8> %y, <i8 2, i8 2>
+ %shl = and <2 x i8> %and1, <i8 12, i8 12>
+ %or = or <2 x i8> %shl, %x
+ %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+ %or2 = or <2 x i8> %and, %x
+ %cond = select <2x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison(
+; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
+; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %z, <i8 3, i8 poison>
+ %and1 = shl <2 x i8> %y, <i8 2, i8 poison>
+ %shl = and <2 x i8> %and1, <i8 12, i8 poison>
+ %or = or <2 x i8> %shl, %x
+ %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+ %or2 = or <2 x i8> %and, %x
+ %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison2(
+; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
+; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %z, <i8 poison, i8 3>
+ %and1 = shl <2 x i8> %y, <i8 poison, i8 2>
+ %shl = and <2 x i8> %and1, <i8 poison, i8 12>
+ %or = or <2 x i8> %shl, %x
+ %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+ %or2 = or <2 x i8> %and, %x
+ %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+
+define i8 @src_xor_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_xor_bit(
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y:%.*]], 12
+; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XOR]], 3
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
+; CHECK-NEXT: ret i8 [[COND]]
+;
+ %and = and i8 %y, 12
+ %xor = xor i8 %and, %x
+ %cmp = icmp eq i8 %xor, 3
+ %and1 = and i8 %x, 3
+ %cond = select i1 %cmp, i8 %and1, i8 1
+ ret i8 %cond
+}
+define <2 x i8> @src_xor_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
+; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %y, <i8 12, i8 12>
+ %xor = xor <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 3, i8 3>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_xor_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %y, <i8 poison, i8 12>
+ %xor = xor <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 poison, i8 3>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_xor_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison2(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %y, <i8 poison, i8 12>
+ %xor = xor <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 3, i8 3>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
define i32 @and_lshr_and(i32 %arg) {
; CHECK-LABEL: @and_lshr_and(
@@ -590,13 +783,13 @@ define i32 @n5(i32 %arg) {
; CHECK-LABEL: @n5(
; CHECK-NEXT: [[T:%.*]] = and i32 [[ARG:%.*]], 2
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[T]], 0
-; CHECK-NEXT: [[T2:%.*]] = and i32 [[ARG]], 2
+; CHECK-NEXT: [[T2:%.*]] = and i32 [[ARG]], 3
; CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 1
; CHECK-NEXT: ret i32 [[T3]]
;
%t = and i32 %arg, 2
%t1 = icmp eq i32 %t, 0
- %t2 = and i32 %arg, 2 ; 2 instead of 1
+ %t2 = and i32 %arg, 3 ; 3 instead of 2
%t3 = select i1 %t1, i32 %t2, i32 1
ret i32 %t3
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 2efe2742ca491..e32cb17d85922 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3701,12 +3701,8 @@ exit:
define i32 @src_and_eq_0_or_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_and_eq_0_or_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
;
entry:
%and = and i32 %y, %x
@@ -3721,12 +3717,8 @@ entry:
define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
; CHECK-LABEL: @src_and_eq_0_xor_or(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CH...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/91762
More information about the llvm-commits
mailing list