Index: llvm/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LICM.cpp +++ llvm/lib/Transforms/Scalar/LICM.cpp @@ -173,7 +173,8 @@ /// Try to simplify things like (A < INV_1 AND icmp A < INV_2) into (A < /// min(INV_1, INV_2)), if INV_1 and INV_2 are both loop invariants and their /// minimun can be computed outside of loop, and X is not a loop-invariant. -static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, +static bool hoistMinMax(Instruction &I, Loop &L, DominatorTree *DT, + AssumptionCache *AC, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU); static Instruction *cloneInstructionInExitBlock( Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI, @@ -992,7 +993,7 @@ // Optimize complex patterns, such as (x < INV1 && x < INV2), turning them // into (x < min(INV1, INV2)), and hoisting the invariant part of this // expression out of the loop. - if (hoistMinMax(I, *CurLoop, *SafetyInfo, MSSAU)) { + if (hoistMinMax(I, *CurLoop, DT, AC, *SafetyInfo, MSSAU)) { ++NumMinMaxHoisted; Changed = true; continue; @@ -2413,16 +2414,25 @@ return false; } -static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, +static bool hoistMinMax(Instruction &I, Loop &L, DominatorTree *DT, + AssumptionCache *AC, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU) { auto *Preheader = L.getLoopPreheader(); assert(Preheader && "Loop is not in simplify form?"); bool Inverse = false; + bool NeedsPoisonCheck = false; using namespace PatternMatch; Value *Cond1, *Cond2; if (match(&I, m_Or(m_Value(Cond1), m_Value(Cond2)))) Inverse = true; - else if (!match(&I, m_And(m_Value(Cond1), m_Value(Cond2)))) + else if (match(&I, m_LogicalOr(m_Value(Cond1), m_Value(Cond2)))) { + Inverse = true; + NeedsPoisonCheck = true; + } else if (match(&I, m_And(m_Value(Cond1), m_Value(Cond2)))) { + // Do nothing + } else if (match(&I, m_LogicalAnd(m_Value(Cond1), m_Value(Cond2)))) + NeedsPoisonCheck = true; + else return false; auto MatchICmpAgainstInvariant = [&](Value *C, ICmpInst::Predicate &P, @@ -2454,6 +2464,14 @@ if (P1 != P2 || LHS1 != LHS2) return false; + // We are about to introduce a use of RHS2 in a place where it wouldn't + // otherwise exist. If we are dealing with a logical AND/OR, we need to make + // sure it's not poisoned. Note that this is not required for LHS and RHS1, + // because they did have a guaranteed use in the same place. + if (NeedsPoisonCheck && + !llvm::isGuaranteedNotToBeUndefOrPoison(RHS2, AC, &I, DT)) + return false; + // Everything is fine, we can do the transform. bool UseMin = ICmpInst::isLT(P1) || ICmpInst::isLE(P1); assert( Index: llvm/test/Transforms/LICM/min_max.ll =================================================================== --- llvm/test/Transforms/LICM/min_max.ll +++ llvm/test/Transforms/LICM/min_max.ll @@ -753,17 +753,16 @@ ret i32 %iv } -; TODO: turn to %iv