diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -820,6 +820,9 @@ return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; } + /// Returns if this cmp is only used by a singular assume + bool isOnlyAssumedTrue() const; + static StringRef getPredicateName(Predicate P); bool isFPPredicate() const { return isFPPredicate(getPredicate()); } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -630,6 +630,7 @@ Value *RHS; CmpInst::Predicate Pred; auto m_V = m_CombineOr(m_Specific(V), m_PtrToInt(m_Specific(V))); + // TODO: Also handle assume(V & M) and assume(V + C1 u< C2) if (!match(I->getArgOperand(0), m_c_ICmp(Pred, m_V, m_Value(RHS)))) return false; @@ -2319,8 +2320,10 @@ } static bool isKnownNonNullFromDominatingCondition(const Value *V, - const Instruction *CtxI, - const DominatorTree *DT) { + const Query &Q) { + const Instruction *CtxI = Q.CxtI; + const DominatorTree *DT = Q.DT; + if (isa(V)) return false; @@ -2356,20 +2359,58 @@ // Consider only compare instructions uniquely controlling a branch Value *RHS; CmpInst::Predicate Pred; - if (!match(U, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS)))) - continue; + bool MatchExtraAdd = false; bool NonNullIfTrue; - if (cmpExcludesZero(Pred, RHS)) - NonNullIfTrue = true; - else if (cmpExcludesZero(CmpInst::getInversePredicate(Pred), RHS)) - NonNullIfTrue = false; - else + auto *CmpUse = U; + if (!match(U, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS)))) { + CmpUse = nullptr; + bool MatchExtraAnd = false; + const APInt *AddC; + if (match(U, m_c_And(m_Specific(V), m_Value()))) { + // If And(A, B) is non-zero then neither A nor B can be zero. + if (isKnownNonZeroFromAssume(U, Q)) + return true; + MatchExtraAnd = true; + } else if (match(U, m_c_Add(m_Specific(V), m_APInt(AddC)))) + MatchExtraAdd = true; + if (MatchExtraAnd || MatchExtraAdd) { + for (const auto *U2 : U->users()) { + if (match(U2, m_c_ICmp(Pred, m_Specific(U), m_Value(RHS)))) { + // Only handle (A + C1) u< C2, which is the canonical form of A > C3 + // && A < C4 + if (MatchExtraAdd) { + auto *RHSC = dyn_cast(RHS); + if (RHSC == nullptr || Pred != ICmpInst::ICMP_ULT) + continue; + NonNullIfTrue = RHSC->getValue().ult(*AddC); + if(NonNullIfTrue && dyn_cast(U2)->isOnlyAssumedTrue()) + return true; + } + CmpUse = U2; + break; + } + } + } + } + + if (CmpUse == nullptr) continue; + + if(!MatchExtraAdd) { + if (cmpExcludesZero(Pred, RHS)) + NonNullIfTrue = true; + else if (cmpExcludesZero(CmpInst::getInversePredicate(Pred), RHS)) + NonNullIfTrue = false; + else + continue; + } + SmallVector WorkList; SmallPtrSet Visited; - for (const auto *CmpU : U->users()) { + for (const auto *CmpU : CmpUse->users()) { + assert(WorkList.empty() && "Should be!"); if (Visited.insert(CmpU).second) WorkList.push_back(CmpU); @@ -2563,8 +2604,7 @@ } } - if (!isa(V) && - isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT)) + if (!isa(V) && isKnownNonNullFromDominatingCondition(V, Q)) return true; const Operator *I = dyn_cast(V); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" @@ -4060,6 +4061,10 @@ llvm_unreachable("Unsupported predicate kind"); } +bool CmpInst::isOnlyAssumedTrue() const { + return hasOneUse() && dyn_cast(user_back()) != nullptr; +} + CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) { switch (pred) { default: llvm_unreachable("Unknown cmp predicate!"); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2843,9 +2843,13 @@ // (X + -1) X <=u C (if X is never null) if (Pred == CmpInst::ICMP_ULT && C2->isAllOnes()) { - const SimplifyQuery Q = SQ.getWithInstruction(&Cmp); - if (llvm::isKnownNonZero(X, DL, 0, Q.AC, Q.CxtI, Q.DT)) - return new ICmpInst(ICmpInst::ICMP_ULE, X, ConstantInt::get(Ty, C)); + // Don't make this transform if the only use of this Cmp is assume as we + // both lose information and de-canonicalize the (A < C1 && A > C2) case + if (!Cmp.isOnlyAssumedTrue()) { + const SimplifyQuery Q = SQ.getWithInstruction(&Cmp); + if (llvm::isKnownNonZero(X, DL, 0, Q.AC, Q.CxtI, Q.DT)) + return new ICmpInst(ICmpInst::ICMP_ULE, X, ConstantInt::get(Ty, C)); + } } if (!Add->hasOneUse()) diff --git a/llvm/test/Transforms/InstCombine/icmp-binop.ll b/llvm/test/Transforms/InstCombine/icmp-binop.ll --- a/llvm/test/Transforms/InstCombine/icmp-binop.ll +++ b/llvm/test/Transforms/InstCombine/icmp-binop.ll @@ -244,8 +244,7 @@ ; CHECK-NEXT: tail call void @llvm.assume(i1 [[OR_COND]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[OTHER:%.*]], 8 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP2]]) -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[OTHER]], [[V]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i64 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i64 [[OTHER]], 0 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL_NOT]] to i64 ; CHECK-NEXT: ret i64 [[CONV]] ; @@ -869,9 +868,7 @@ ; CHECK-NEXT: [[CMP4:%.*]] = icmp ne i64 [[OTHER]], 0 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP2]]) ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP4]]) -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i64 [[V]], 0 -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL_NOT]] to i64 -; CHECK-NEXT: ret i64 [[CONV]] +; CHECK-NEXT: ret i64 0 ; entry: %0 = add i64 %v, -2 @@ -1572,8 +1569,7 @@ ; CHECK-NEXT: tail call void @llvm.assume(i1 [[OR_COND]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[OTHER:%.*]], 8 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP2]]) -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[OTHER]], [[V]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[OTHER]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_THEN5:%.*]], label [[IF_END6:%.*]] ; CHECK: if.then5: ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 (...) @foo32() @@ -2278,17 +2274,14 @@ define signext i16 @mul_br_V_oddV_s16_brnz(i16 signext %v, i16 signext %other) { ; CHECK-LABEL: @mul_br_V_oddV_s16_brnz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[OTHER:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = and i16 [[OTHER:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[V:%.*]] to i32 -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV2]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i16 [[V:%.*]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END6:%.*]], label [[IF_THEN4:%.*]] ; CHECK: if.then4: ; CHECK-NEXT: [[CALL5:%.*]] = tail call signext i16 (...) @foo16() @@ -2386,33 +2379,28 @@ define signext i16 @mul_br_oddV_oddV_s16_brnz(i16 signext %v, i16 signext %other) { ; CHECK-LABEL: @mul_br_oddV_oddV_s16_brnz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[V:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = and i16 [[V:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[OTHER:%.*]] to i32 -; CHECK-NEXT: [[AND3:%.*]] = and i32 [[CONV2]], 1 -; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[AND3]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[OTHER:%.*]], 1 +; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i16 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[CMP4]], label [[IF_THEN6:%.*]], label [[IF_END8:%.*]] ; CHECK: if.then6: ; CHECK-NEXT: [[CALL7:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end8: -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[MUL]], 0 -; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END13:%.*]], label [[IF_THEN11:%.*]] +; CHECK-NEXT: br i1 false, label [[IF_END13:%.*]], label [[IF_THEN11:%.*]] ; CHECK: if.then11: ; CHECK-NEXT: [[CALL12:%.*]] = tail call signext i16 (...) @foo16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end13: -; CHECK-NEXT: [[CALL14:%.*]] = tail call signext i16 (...) @bar16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i16 [ [[CALL]], [[IF_THEN]] ], [ [[CALL7]], [[IF_THEN6]] ], [ [[CALL12]], [[IF_THEN11]] ], [ [[CALL14]], [[IF_END13]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i16 [ [[CALL]], [[IF_THEN]] ], [ [[CALL7]], [[IF_THEN6]] ], [ [[CALL12]], [[IF_THEN11]] ], [ poison, [[IF_END13]] ] ; CHECK-NEXT: ret i16 [[RETVAL_0]] ; entry: @@ -2456,24 +2444,21 @@ define signext i16 @mul_br_oddV_evenV_s16_brnz(i16 signext %v, i16 signext %other) { ; CHECK-LABEL: @mul_br_oddV_evenV_s16_brnz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[V:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = and i16 [[V:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[OTHER:%.*]] to i32 -; CHECK-NEXT: [[AND3:%.*]] = and i32 [[CONV2]], 1 -; CHECK-NEXT: [[CMP4_NOT:%.*]] = icmp eq i32 [[AND3]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[OTHER:%.*]], 1 +; CHECK-NEXT: [[CMP4_NOT:%.*]] = icmp eq i16 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[CMP4_NOT]], label [[IF_END8:%.*]], label [[IF_THEN6:%.*]] ; CHECK: if.then6: ; CHECK-NEXT: [[CALL7:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end8: -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i16 [[OTHER]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END13:%.*]], label [[IF_THEN11:%.*]] ; CHECK: if.then11: ; CHECK-NEXT: [[CALL12:%.*]] = tail call signext i16 (...) @foo16() @@ -2736,8 +2721,7 @@ define signext i16 @mul_br_no_of_nz3_s16_brnz(i16 signext %v, i16 signext %other) { ; CHECK-LABEL: @mul_br_no_of_nz3_s16_brnz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[V:%.*]] to i32 -; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[V]], -8 +; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[V:%.*]], -8 ; CHECK-NEXT: [[OR_COND:%.*]] = icmp ult i16 [[TMP0]], -6 ; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: @@ -2752,18 +2736,14 @@ ; CHECK-NEXT: [[CALL13:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end14: -; CHECK-NEXT: [[CONV5:%.*]] = sext i16 [[OTHER]] to i32 -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV5]], [[CONV]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[MUL]], 0 -; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END19:%.*]], label [[IF_THEN17:%.*]] +; CHECK-NEXT: br i1 false, label [[IF_END19:%.*]], label [[IF_THEN17:%.*]] ; CHECK: if.then17: ; CHECK-NEXT: [[CALL18:%.*]] = tail call signext i16 (...) @foo16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end19: -; CHECK-NEXT: [[CALL20:%.*]] = tail call signext i16 (...) @bar16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i16 [ [[CALL]], [[IF_THEN]] ], [ [[CALL13]], [[IF_THEN12]] ], [ [[CALL18]], [[IF_THEN17]] ], [ [[CALL20]], [[IF_END19]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i16 [ [[CALL]], [[IF_THEN]] ], [ [[CALL13]], [[IF_THEN12]] ], [ [[CALL18]], [[IF_THEN17]] ], [ poison, [[IF_END19]] ] ; CHECK-NEXT: ret i16 [[RETVAL_0]] ; entry: @@ -3184,33 +3164,28 @@ define signext i16 @or_br_oddV_oddV_s16_brnz(i16 signext %v, i16 signext %other) { ; CHECK-LABEL: @or_br_oddV_oddV_s16_brnz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[V:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = and i16 [[V:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[OTHER:%.*]] to i32 -; CHECK-NEXT: [[AND3:%.*]] = and i32 [[CONV2]], 1 -; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[AND3]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[OTHER:%.*]], 1 +; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i16 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[CMP4]], label [[IF_THEN6:%.*]], label [[IF_END8:%.*]] ; CHECK: if.then6: ; CHECK-NEXT: [[CALL7:%.*]] = tail call signext i16 (...) @baz16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end8: -; CHECK-NEXT: [[OR:%.*]] = or i32 [[CONV2]], [[CONV]] -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[OR]], 0 -; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END13:%.*]], label [[IF_THEN11:%.*]] +; CHECK-NEXT: br i1 false, label [[IF_END13:%.*]], label [[IF_THEN11:%.*]] ; CHECK: if.then11: ; CHECK-NEXT: [[CALL12:%.*]] = tail call signext i16 (...) @foo16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end13: -; CHECK-NEXT: [[CALL14:%.*]] = tail call signext i16 (...) @bar16() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i16 [ [[CALL]], [[IF_THEN]] ], [ [[CALL7]], [[IF_THEN6]] ], [ [[CALL12]], [[IF_THEN11]] ], [ [[CALL14]], [[IF_END13]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i16 [ [[CALL]], [[IF_THEN]] ], [ [[CALL7]], [[IF_THEN6]] ], [ [[CALL12]], [[IF_THEN11]] ], [ poison, [[IF_END13]] ] ; CHECK-NEXT: ret i16 [[RETVAL_0]] ; entry: @@ -3621,17 +3596,14 @@ define zeroext i8 @mul_br_V_oddV_u8_setz(i8 zeroext %v, i8 zeroext %other) { ; CHECK-LABEL: @mul_br_V_oddV_u8_setz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[OTHER:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[OTHER:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call zeroext i8 (...) @baz8() ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[V:%.*]] to i32 -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], [[CONV2]] -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[V:%.*]], 0 ; CHECK-NEXT: [[CONV5:%.*]] = zext i1 [[TOBOOL]] to i8 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: @@ -3734,24 +3706,21 @@ define zeroext i8 @mul_br_oddV_evenV_u8_setz(i8 zeroext %v, i8 zeroext %other) { ; CHECK-LABEL: @mul_br_oddV_evenV_u8_setz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[V:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[CONV]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[V:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP0]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call zeroext i8 (...) @baz8() ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[OTHER:%.*]] to i32 -; CHECK-NEXT: [[AND3:%.*]] = and i32 [[CONV2]], 1 -; CHECK-NEXT: [[CMP4_NOT:%.*]] = icmp eq i32 [[AND3]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[OTHER:%.*]], 1 +; CHECK-NEXT: [[CMP4_NOT:%.*]] = icmp eq i8 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[CMP4_NOT]], label [[IF_END8:%.*]], label [[IF_THEN6:%.*]] ; CHECK: if.then6: ; CHECK-NEXT: [[CALL7:%.*]] = tail call zeroext i8 (...) @baz8() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end8: -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV2]], [[CONV]] -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[OTHER]], 0 ; CHECK-NEXT: [[CONV12:%.*]] = zext i1 [[TOBOOL]] to i8 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: @@ -3846,8 +3815,7 @@ define zeroext i8 @mul_br_no_of_nz1_u8_setz(i8 zeroext %v, i8 zeroext %other) { ; CHECK-LABEL: @mul_br_no_of_nz1_u8_setz( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[V:%.*]] to i32 -; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[V]], -8 +; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[V:%.*]], -8 ; CHECK-NEXT: [[OR_COND:%.*]] = icmp ult i8 [[TMP0]], -7 ; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: @@ -3860,9 +3828,7 @@ ; CHECK-NEXT: [[CALL9:%.*]] = tail call zeroext i8 (...) @baz8() ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end10: -; CHECK-NEXT: [[CONV5:%.*]] = zext i8 [[OTHER]] to i32 -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV5]], [[CONV]] -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[MUL]], 0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[OTHER]], 0 ; CHECK-NEXT: [[CONV14:%.*]] = zext i1 [[TOBOOL]] to i8 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: