diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index e577d0cc7ad41..57fa4f29d5eff 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 855d1aeddfaee..f81150b7b31f6 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 8126d2a1acc27..085e4a81d17ee 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -747,9 +747,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 7d26807544d7e..3d667ec5f1b3f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1809,6 +1809,198 @@ 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; + unsigned CmpLHSOpc; + bool IsDisjoint = false; + // Specially handling for X^Y==0 transformed to X==Y + if (match(TVal, m_c_BitwiseLogic(m_Specific(CmpLHS), m_Specific(CmpRHS)))) { + X = CmpLHS; + Y = CmpRHS; + APInt ZeroVal = APInt::getZero(CmpLHS->getType()->getScalarSizeInBits()); + C = const_cast<APInt *>(&ZeroVal); + CmpLHSOpc = Instruction::Xor; + } else 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())))) { + if (auto Inst = dyn_cast<PossiblyDisjointInst>(CmpLHS)) { + if (Inst->isDisjoint()) + IsDisjoint = true; + CmpLHSOpc = Instruction::Or; + } else + CmpLHSOpc = cast<BinaryOperator>(CmpLHS)->getOpcode(); + } else + return nullptr; + + enum SpecialKnownBits { + NothingSpecial = 0, + NoCommonBits = 1 << 1, + AllCommonBits = 1 << 2, + AllBitsEnabled = 1 << 3, + }; + + // We cannot know exactly what bits is known in X Y. + // Instead, we just know what relationship exist for. + auto isSpecialKnownBitsFor = [&]() -> unsigned { + if (CmpLHSOpc == Instruction::And) { + if (C->isZero()) + return NoCommonBits; + } else if (CmpLHSOpc == Instruction::Xor) { + if (C->isAllOnes()) + return NoCommonBits | AllBitsEnabled; + if (C->isZero()) + return AllCommonBits; + } else if (CmpLHSOpc == Instruction::Or && IsDisjoint) { + if (C->isAllOnes()) + return NoCommonBits | AllBitsEnabled; + return NoCommonBits; + } + + return NothingSpecial; + }; + + 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); + unsigned XOrder = hasOperandAt(TValBop, X); + unsigned YOrder = hasOperandAt(TValBop, Y); + unsigned SKB = isSpecialKnownBitsFor(); + + KnownBits Known; + if (TValBop->isBitwiseLogicOp()) { + // We handle if we know specific knownbits from cond of selectinst. + // ex) X&Y==-1 ? X^Y : False + if (SKB != SpecialKnownBits::NothingSpecial && XOrder && YOrder) { + // No common bits between X, Y + if (SKB & SpecialKnownBits::NoCommonBits) { + if (SKB & (SpecialKnownBits::AllBitsEnabled)) { + // If X op Y == -1, then XOR must be -1 + if (TValBop->getOpcode() == Instruction::Xor) + Known = KnownBits::makeConstant(APInt(BitWidth, -1)); + } + // If Trueval is X&Y then it should be 0. + if (TValBop->getOpcode() == Instruction::And) + Known = KnownBits::makeConstant(APInt(BitWidth, 0)); + // X|Y can be replace with X^Y, X^Y can be replace with X|Y + // This replacing is meaningful when falseval is same. + 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); + // All common bits between X, Y + } else if (SKB & SpecialKnownBits::AllCommonBits) { + // We can replace (X&Y) and (X|Y) to X or Y + if (TValBop->getOpcode() == Instruction::And || + TValBop->getOpcode() == Instruction::Or) + if (TValBop->hasOneUse()) + return IC.replaceOperand(SI, 1, X); + } else if (SKB & SpecialKnownBits::AllBitsEnabled) { + // We can replace (X|Y) to -1 + if (TValBop->getOpcode() == Instruction::Or) + Known = KnownBits::makeConstant(APInt(BitWidth, -1)); + } + } else { + KnownBits XKnown, YKnown, Temp; + KnownBits TValBop0KB, TValBop1KB; + // computeKnowBits calculates the KnownBits in the branching condition + // that the specified variable passes in the execution flow. however, it + // does not contain the SelectInst condition, so there is an optimization + // opportunity to update the knownbits obtained by calculating KnownBits + // with the SelectInst condition. + 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); + CmpInst::Predicate Pred = ICI->getPredicate(); + if (Pred == ICmpInst::ICMP_EQ) { + // Estimate additional KnownBits from the relationship between X and Y + if (CmpLHSOpc == Instruction::And) { + // The bit that are set to 1 at `~C&Y` must be 0 in X + // The bit that are set to 1 at `~C&X` must be 0 in Y + XKnown.Zero |= ~*C & YKnown.One; + YKnown.Zero |= ~*C & XKnown.One; + } + if (CmpLHSOpc == Instruction::Or) { + // The bit that are set to 0 at `C&Y` must be 1 in X + // The bit that are set to 0 at `C&X` must be 1 in Y + XKnown.One |= *C & YKnown.Zero; + YKnown.One |= *C & XKnown.Zero; + } + if (CmpLHSOpc == Instruction::Xor) { + // If X^Y==C, then X and Y must be either (1,0) or (0,1) for the + // enabled bits in C. + XKnown.One |= *C & YKnown.Zero; + XKnown.Zero |= *C & YKnown.One; + YKnown.One |= *C & XKnown.Zero; + YKnown.Zero |= *C & XKnown.One; + // If X^Y==C, then X and Y must be either (0,0) or (1,1) for the + // disabled bits in C. + XKnown.Zero |= ~*C & YKnown.Zero; + XKnown.One |= ~*C & YKnown.One; + YKnown.Zero |= ~*C & XKnown.Zero; + YKnown.One |= ~*C & XKnown.One; + } + } + + // If TrueVal has X or Y, return the corresponding KnownBits, otherwise + // compute and return new KnownBits. + 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); + 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) { @@ -1951,6 +2143,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..b81b90c1a948e 100644 --- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll +++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll @@ -3,7 +3,408 @@ ; 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 +} + +define i8 @src_and_bit_ne(i8 %x, i8 %y) { +; CHECK-LABEL: @src_and_bit_ne( +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 3 +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[AND]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], 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 ne i8 %and2, 2 + %cond = select i1 %cmp, i8 1, i8 %and1 + ret i8 %cond +} + +define <2 x i8> @src_and_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_and_bit_vec_ne( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3> +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <2 x i8> %and2, <i8 2, i8 2> + %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1 + ret <2 x i8> %cond +} + +define <2 x i8> @src_and_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_and_bit_vec_poison_ne( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3> +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <2 x i8> %and2, <i8 2, i8 2> + %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1 + ret <2 x i8> %cond +} + +define <2 x i8> @src_and_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_and_bit_vec_poison2_ne( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3> +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <2 x i8> %and2, <i8 2, i8 2> + %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1 + 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_or_bit_ne(i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @src_or_bit_ne( +; CHECK-NEXT: [[AND1:%.*]] = shl i8 [[Y:%.*]], 2 +; CHECK-NEXT: [[SHL:%.*]] = and i8 [[AND1]], 12 +; CHECK-NEXT: [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[OR]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], 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 ne i8 %or, 3 + %or2 = or i8 %and, %x + %cond = select i1 %cmp, i8 1, i8 %or2 + ret i8 %cond +} + +define <2 x i8> @src_or_bit_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { +; CHECK-LABEL: @src_or_bit_vec_ne( +; 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_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <2 x i8> %or, <i8 3, i8 3> + %or2 = or <2 x i8> %and, %x + %cond = select <2x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2 + ret <2 x i8> %cond +} + +define <2 x i8> @src_or_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { +; CHECK-LABEL: @src_or_bit_vec_poison_ne( +; 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_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <2 x i8> %or, <i8 3, i8 3> + %or2 = or <2 x i8> %and, %x + %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2 + ret <2 x i8> %cond +} + +define <2 x i8> @src_or_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { +; CHECK-LABEL: @src_or_bit_vec_poison2_ne( +; 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_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <2 x i8> %or, <i8 3, i8 3> + %or2 = or <2 x i8> %and, %x + %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2 + ret <2 x i8> %cond +} + +; ====================== XOR ======================= +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 i8 @src_xor_bit_ne(i8 %x, i8 %y) { +; CHECK-LABEL: @src_xor_bit_ne( +; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y:%.*]], 12 +; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[XOR]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], i8 3, i8 1 +; CHECK-NEXT: ret i8 [[COND]] +; + %and = and i8 %y, 12 + %xor = xor i8 %and, %x + %cmp = icmp ne i8 %xor, 3 + %and1 = and i8 %x, 3 + %cond = select i1 %cmp, i8 1, i8 %and1 + ret i8 %cond +} + +define <2 x i8> @src_xor_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_xor_bit_vec_ne( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12> +; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <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> <i8 1, i8 1>, <2 x i8> %and1 + ret <2 x i8> %cond +} + +define <2 x i8> @src_xor_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_xor_bit_vec_poison_ne( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12> +; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <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> <i8 1, i8 1>, <2 x i8> %and1 + ret <2 x i8> %cond +} + +define <2 x i8> @src_xor_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_xor_bit_vec_poison2_ne( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12> +; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <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 ne <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> <i8 1, i8 1>, <2 x i8> %and1 + ret <2 x i8> %cond +} define i32 @and_lshr_and(i32 %arg) { ; CHECK-LABEL: @and_lshr_and( @@ -590,13 +991,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 b37e9175b26a5..6f95c379e9f29 100644 --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -3759,18 +3759,170 @@ exit: } ; Select icmp and/or/xor +; X|Y==-1?X^Y:-1 +define i32 @src_or_disjoint_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 -1 +; +entry: + %or.disjoint = or disjoint i32 %x, %y + %cmp = icmp eq i32 %or.disjoint, -1 + %xor = xor i32 %x, %y + %cond = select i1 %cmp, i32 %xor, i32 -1 + ret i32 %cond +} + +define i32 @src_or_disjoint_xor_comm(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_comm( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 -1 +; +entry: + %or.disjoint = or disjoint i32 %x, %y + %cmp = icmp eq i32 %or.disjoint, -1 + %xor = xor i32 %x, %y + %cond = select i1 %cmp, i32 %xor, i32 -1 + ret i32 %cond +} + +define i32 @src_or_disjoint_xor_ne(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_ne( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 -1 +; +entry: + %or.disjoint = or disjoint i32 %x, %y + %cmp = icmp ne i32 %or.disjoint, -1 + %xor = xor i32 %x, %y + %cond = select i1 %cmp, i32 -1, i32 %xor + ret i32 %cond +} + +define i32 @src_or_disjoint_xor_ne_comm(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_ne_comm( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 -1 +; +entry: + %or.disjoint = or disjoint i32 %y, %x + %cmp = icmp ne i32 %or.disjoint, -1 + %xor = xor i32 %y, %x + %cond = select i1 %cmp, i32 -1, i32 %xor + ret i32 %cond +} + +define <2 x i8> @src_or_disjoint_xor_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_or_disjoint_xor_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1> +; +entry: + %or.disjoint = or disjoint <2 x i8> %x, %y + %cmp = icmp eq <2 x i8> %or.disjoint, <i8 -1, i8 -1> + %xor = xor <2 x i8> %x, %y + %cond = select <2 x i1> %cmp, <2 x i8> %xor, <2 x i8> <i8 -1, i8 -1> + ret <2 x i8> %cond +} + +define <2 x i8> @src_or_disjoint_xor_comm_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_or_disjoint_xor_comm_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1> +; +entry: + %or.disjoint = or disjoint <2 x i8> %x, %y + %cmp = icmp eq <2 x i8> %or.disjoint, <i8 -1, i8 -1> + %xor = xor <2 x i8> %x, %y + %cond = select <2 x i1> %cmp, <2 x i8> %xor, <2 x i8> <i8 -1, i8 -1> + ret <2 x i8> %cond +} + +define <2 x i8> @src_or_disjoint_xor_ne_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_or_disjoint_xor_ne_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1> +; +entry: + %or.disjoint = or disjoint <2 x i8> %x, %y + %cmp = icmp ne <2 x i8> %or.disjoint, <i8 -1, i8 -1> + %xor = xor <2 x i8> %x, %y + %cond = select <2 x i1> %cmp, <2 x i8> <i8 -1, i8 -1>, <2 x i8> %xor + ret <2 x i8> %cond +} + +define <2 x i8> @src_or_disjoint_xor_ne_comm_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @src_or_disjoint_xor_ne_comm_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i8> <i8 -1, i8 -1> +; +entry: + %or.disjoint = or disjoint <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or.disjoint, <i8 -1, i8 -1> + %xor = xor <2 x i8> %y, %x + %cond = select <2 x i1> %cmp, <2 x i8> <i8 -1, i8 -1>, <2 x i8> %xor + ret <2 x i8> %cond +} + +define i32 @src_or_disjoint_xor_poison(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_poison( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 poison +; +entry: + %or.disjoint = or disjoint i32 %x, %y + %cmp = icmp eq i32 %or.disjoint, poison + %xor = xor i32 %x, %y + %cond = select i1 %cmp, i32 %xor, i32 poison + ret i32 %cond +} + +define i32 @src_or_disjoint_xor_comm_poison(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_comm_poison( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 poison +; +entry: + %or.disjoint = or disjoint i32 %x, %y + %cmp = icmp eq i32 %or.disjoint, poison + %xor = xor i32 %x, %y + %cond = select i1 %cmp, i32 %xor, i32 poison + ret i32 %cond +} + +define i32 @src_or_disjoint_xor_ne_poison(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_ne_poison( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 poison +; +entry: + %or.disjoint = or disjoint i32 %x, %y + %cmp = icmp ne i32 %or.disjoint, poison + %xor = xor i32 %x, %y + %cond = select i1 %cmp, i32 poison, i32 %xor + ret i32 %cond +} + +define i32 @src_or_disjoint_xor_ne_comm_poison(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_disjoint_xor_ne_comm_poison( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 poison +; +entry: + %or.disjoint = or disjoint i32 %y, %x + %cmp = icmp ne i32 %or.disjoint, poison + %xor = xor i32 %y, %x + %cond = select i1 %cmp, i32 poison, i32 %xor + ret i32 %cond +} + ; https://alive2.llvm.org/ce/z/QXQDwF ; X&Y==C?X|Y:X^Y, X&Y==C?X^Y:X|Y -; TODO: X&Y==0 could imply no_common_bit to TrueValue 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 @@ -3781,16 +3933,24 @@ entry: ret i32 %cond } -; TODO: X&Y==0 could imply no_common_bit to TrueValue +define i32 @src_and_ne_0_xor_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_and_ne_0_xor_or( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, 0 + %or = or i32 %y, %x + %xor = xor i32 %y, %x + %cond = select i1 %cmp, i32 %xor, i32 %or + ret i32 %cond +} + 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]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[OR]] ; entry: %and = and i32 %y, %x @@ -3801,15 +3961,26 @@ entry: ret i32 %cond } -; TODO: X&Y==-1 could imply all_common_bit to TrueValue +define i32 @src_and_ne_0_or_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_and_ne_0_or_xor( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, 0 + %xor = xor i32 %y, %x + %or = or i32 %y, %x + %cond = select i1 %cmp, i32 %or, i32 %xor + ret i32 %cond +} + define i32 @src_and_eq_neg1_or_xor(i32 %x, i32 %y) { ; CHECK-LABEL: @src_and_eq_neg1_or_xor( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1 -; 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: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[XOR]] ; CHECK-NEXT: ret i32 [[COND]] ; entry: @@ -3821,15 +3992,29 @@ entry: ret i32 %cond } -; TODO: X&Y==-1 could imply all_common_bit to TrueValue +define i32 @src_and_ne_neg1_xor_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_and_ne_neg1_xor_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], -1 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], i32 -1, i32 [[XOR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, -1 + %or = or i32 %y, %x + %xor = xor i32 %y, %x + %cond = select i1 %cmp, i32 %xor, i32 %or + ret i32 %cond +} + define i32 @src_and_eq_neg1_xor_or(i32 %x, i32 %y) { ; CHECK-LABEL: @src_and_eq_neg1_xor_or( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1 -; 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: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[OR]] ; CHECK-NEXT: ret i32 [[COND]] ; entry: @@ -3841,6 +4026,22 @@ entry: ret i32 %cond } +define i32 @src_and_ne_neg1_or_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_and_ne_neg1_or_xor( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[OR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, -1 + %xor = xor i32 %y, %x + %or = or i32 %y, %x + %cond = select i1 %cmp, i32 %or, i32 %xor + ret i32 %cond +} + define i32 @src_and_eq_C_or_xororC(i32 %x, i32 %y, i32 %c) { ; CHECK-LABEL: @src_and_eq_C_or_xororC( ; CHECK-NEXT: entry: @@ -3936,15 +4137,13 @@ entry: ; https://alive2.llvm.org/ce/z/9RPwfN ; X|Y==C?X&Y:X^Y, X|Y==C?X^Y:X&Y -; TODO: X|Y==0 could imply no_common_bit to TrueValue 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: [[AND:%.*]] = and i32 [[Y]], [[X]] ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[XOR]] ; CHECK-NEXT: ret i32 [[COND]] ; entry: @@ -3956,15 +4155,29 @@ entry: ret i32 %cond } -; TODO: X|Y==0 could imply no_common_bit to TrueValue +define i32 @src_or_ne_0_xor_and(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_ne_0_xor_and( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[OR]], 0 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[XOR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %or = or i32 %y, %x + %cmp = icmp ne i32 %or, 0 + %and = and i32 %y, %x + %xor = xor i32 %y, %x + %cond = select i1 %cmp, i32 %xor, i32 %and + ret i32 %cond +} + 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: [[XOR:%.*]] = xor i32 [[Y]], [[X]] ; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[AND]] ; CHECK-NEXT: ret i32 [[COND]] ; entry: @@ -3976,6 +4189,22 @@ entry: ret i32 %cond } +define i32 @src_or_ne_0_and_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_or_ne_0_and_xor( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[OR]], 0 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[AND]] +; CHECK-NEXT: ret i32 [[COND]] +; + %or = or i32 %y, %x + %cmp = icmp ne i32 %or, 0 + %xor = xor i32 %y, %x + %and = and i32 %y, %x + %cond = select i1 %cmp, i32 %and, i32 %xor + ret i32 %cond +} + define i32 @src_or_eq_neg1_and_xor(i32 %x, i32 %y) { ; CHECK-LABEL: @src_or_eq_neg1_and_xor( ; CHECK-NEXT: entry: @@ -4189,6 +4418,172 @@ entry: ret i32 %cond } +define i32 @src_select_or_eq0_or_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_or_eq0_or_xor( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[XOR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %or = or i32 %x, %y + %or0 = icmp eq i32 %or, 0 + %xor = xor i32 %x, %y + %cond = select i1 %or0, i32 %or, i32 %xor + ret i32 %cond +} + +define i32 @src_select_or_ne0_xor_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_or_ne0_xor_or( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[OR0_NOT:%.*]] = icmp eq i32 [[OR]], 0 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0_NOT]], i32 0, i32 [[XOR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %or = or i32 %x, %y + %or0 = icmp ne i32 %or, 0 + %xor = xor i32 %x, %y + %cond = select i1 %or0, i32 %xor, i32 %or + ret i32 %cond +} + +define i32 @src_select_or_eq0_and_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_or_eq0_and_or( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %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 +} + +define i32 @src_select_or_ne0_or_and(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_or_ne0_or_and( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %x, %y + %or0 = icmp ne i32 %or, 0 + %and = and i32 %x, %y + %cond = select i1 %or0, i32 %or, i32 %and + ret i32 %cond +} + +define i32 @src_select_xor_eq0_and_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_xor_eq0_and_xor( +; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]] +; CHECK-NEXT: [[COND:%.*]] = xor i32 [[XOR]], [[X]] +; CHECK-NEXT: ret i32 [[COND]] +; + %xor = xor i32 %x, %y + %xor0 = icmp eq i32 %xor, 0 + %and = and i32 %x, %y + %cond = select i1 %xor0, i32 %and, i32 %xor + ret i32 %cond +} + +define i32 @src_select_xor_ne0_xor_and(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_xor_ne0_xor_and( +; CHECK-NEXT: [[XOR0_NOT:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[Y]] +; CHECK-NEXT: [[COND:%.*]] = xor i32 [[XOR]], [[X]] +; CHECK-NEXT: ret i32 [[COND]] +; + %xor = xor i32 %x, %y + %xor0 = icmp ne i32 %xor, 0 + %and = and i32 %x, %y + %cond = select i1 %xor0, i32 %xor, i32 %and + ret i32 %cond +} + +define i32 @src_select_xor_eq0_or_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_xor_eq0_or_xor( +; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]] +; CHECK-NEXT: [[COND:%.*]] = xor i32 [[XOR]], [[X]] +; CHECK-NEXT: ret i32 [[COND]] +; + %xor = xor i32 %x, %y + %xor0 = icmp eq i32 %xor, 0 + %or = or i32 %x, %y + %cond = select i1 %xor0, i32 %or, i32 %xor + ret i32 %cond +} + +define i32 @src_select_xor_ne0_xor_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_xor_ne0_xor_or( +; CHECK-NEXT: [[XOR0_NOT:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[Y]] +; CHECK-NEXT: [[COND:%.*]] = xor i32 [[XOR]], [[X]] +; CHECK-NEXT: ret i32 [[COND]] +; + %xor = xor i32 %x, %y + %xor0 = icmp ne i32 %xor, 0 + %or = or i32 %x, %y + %cond = select i1 %xor0, i32 %xor, i32 %or + ret i32 %cond +} + +define i32 @src_select_or_eq0_xor_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_or_eq0_xor_or( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %x, %y + %or0 = icmp eq i32 %or, 0 + %xor = xor i32 %x, %y + %cond = select i1 %or0, i32 %xor, i32 %or + ret i32 %cond +} + +define i32 @src_select_or_ne0_or_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_or_ne0_or_xor( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %x, %y + %or0 = icmp ne i32 %or, 0 + %xor = xor i32 %x, %y + %cond = select i1 %or0, i32 %or, i32 %xor + ret i32 %cond +} + +define i32 @src_select_xor_max_negative_int(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_xor_max_negative_int( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %xor = xor i32 %x, %y + %xor0 = icmp eq i32 %xor, -1 + %and = and i32 %x, %y + %or = or i32 %x, %y + %cond = select i1 %xor0, i32 %and, i32 %or + ret i32 %cond +} + +define i32 @src_select_xor_max_negative_int_ne(i32 %x, i32 %y) { +; CHECK-LABEL: @src_select_xor_max_negative_int_ne( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR0_NOT:%.*]] = icmp eq i32 [[XOR]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[OR]] +; CHECK-NEXT: ret i32 [[COND]] +; + %xor = xor i32 %x, %y + %xor0 = icmp ne i32 %xor, -1 + %and = and i32 %x, %y + %or = or i32 %x, %y + %cond = select i1 %xor0, i32 %or, i32 %and + ret i32 %cond +} + ; Select icmp and/or/xor ; NO TRANSFORMED - select condition is compare with not 0 define i32 @src_select_and_min_positive_int(i32 %x, i32 %y) { @@ -4361,23 +4756,6 @@ define i32 @src_select_xor_min_negative_int(i32 %x, i32 %y) { ret i32 %cond } -define i32 @src_select_xor_max_negative_int(i32 %x, i32 %y) { -; CHECK-LABEL: @src_select_xor_max_negative_int( -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]] -; CHECK-NEXT: ret i32 [[COND]] -; - %xor = xor i32 %x, %y - %xor0 = icmp eq i32 %xor, -1 - %and = and i32 %x, %y - %or = or i32 %x, %y - %cond = select i1 %xor0, i32 %and, i32 %or - ret i32 %cond -} - ; Select icmp and/or/xor ; https://alive2.llvm.org/ce/z/BVgrJ- ; NO TRANSFORMED - not supported @@ -4456,51 +4834,6 @@ define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) { ret i32 %cond } -define i32 @src_no_trans_select_or_eq0_or_xor(i32 %x, i32 %y) { -; CHECK-LABEL: @src_no_trans_select_or_eq0_or_xor( -; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0 -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[XOR]] -; CHECK-NEXT: ret i32 [[COND]] -; - %or = or i32 %x, %y - %or0 = icmp eq i32 %or, 0 - %xor = xor i32 %x, %y - %cond = select i1 %or0, i32 %or, i32 %xor - ret i32 %cond -} - -define i32 @src_no_trans_select_or_eq0_and_or(i32 %x, i32 %y) { -; CHECK-LABEL: @src_no_trans_select_or_eq0_and_or( -; 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 [[AND]], i32 [[OR]] -; CHECK-NEXT: ret i32 [[COND]] -; - %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 -} - -define i32 @src_no_trans_select_or_eq0_xor_or(i32 %x, i32 %y) { -; CHECK-LABEL: @src_no_trans_select_or_eq0_xor_or( -; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0 -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[XOR]], i32 [[OR]] -; CHECK-NEXT: ret i32 [[COND]] -; - %or = or i32 %x, %y - %or0 = icmp eq i32 %or, 0 - %xor = xor i32 %x, %y - %cond = select i1 %or0, i32 %xor, i32 %or - ret i32 %cond -} - define i32 @src_no_trans_select_and_ne0_xor_or(i32 %x, i32 %y) { ; CHECK-LABEL: @src_no_trans_select_and_ne0_xor_or( ; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] @@ -4530,8 +4863,8 @@ define i32 @src_no_trans_select_xor_eq0_xor_and(i32 %x, i32 %y) { ret i32 %cond } -define i32 @src_no_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) { -; CHECK-LABEL: @src_no_trans_select_xor_eq0_xor_or( +define i32 @src_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) { +; CHECK-LABEL: @src_trans_select_xor_eq0_xor_or( ; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]] ; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]] @@ -4544,12 +4877,11 @@ define i32 @src_no_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) { ret i32 %cond } -define i32 @src_no_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) { -; CHECK-LABEL: @src_no_trans_select_xor_eq0_and_xor( -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[XOR]] +define i32 @src_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_trans_select_xor_eq0_and_xor( +; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]] +; CHECK-NEXT: [[COND:%.*]] = xor i32 [[XOR]], [[X]] ; CHECK-NEXT: ret i32 [[COND]] ; %xor = xor i32 %x, %y @@ -4559,13 +4891,11 @@ define i32 @src_no_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) { ret i32 %cond } -; https://alive2.llvm.org/ce/z/SBe8ei -define i32 @src_no_trans_select_xor_eq0_or_xor(i32 %x, i32 %y) { -; CHECK-LABEL: @src_no_trans_select_xor_eq0_or_xor( -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]] -; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[OR]], i32 [[XOR]] +define i32 @src_trans_select_xor_eq0_or_xor(i32 %x, i32 %y) { +; CHECK-LABEL: @src_trans_select_xor_eq0_or_xor( +; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]] +; CHECK-NEXT: [[COND:%.*]] = xor i32 [[XOR]], [[X]] ; CHECK-NEXT: ret i32 [[COND]] ; %xor = xor i32 %x, %y