Index: llvm/include/llvm/Analysis/ScalarEvolution.h =================================================================== --- llvm/include/llvm/Analysis/ScalarEvolution.h +++ llvm/include/llvm/Analysis/ScalarEvolution.h @@ -112,6 +112,24 @@ /// Note that NUW and NSW are also valid properties of a recurrence, and /// either implies NW. For convenience, NW will be set for a recurrence /// whenever either NUW or NSW are set. + /// + /// We require that the flag on a SCEV apply to the entire scope in which + /// that SCEV is defined. A SCEV's scope is set of locations dominated by + /// a defining location, which is in turn describes by the following rules: + /// * A SCEVUnknown is at the point of definition of the Value. + /// * A SCEVConstant is defined at all points. + /// * A SCEVAddRec is defined starting with the header of the associated + /// loop. + /// * All other SCEVs are defined at the earlest point all operands are + /// defined. + /// + /// The above rules describe a maximally hoisted form (without regards to + /// potential control dependence). A SCEV is defined anywhere a + /// corresponding instruction could be defined in said maximally hoisted + /// form. Note that SCEVUDivExpr (currently the only expression type which + /// can trap) can be defined per these rules in regions where it would trap + /// at runtime. A SCEV being defined does not require the existence of any + /// instruction within the defined scope. enum NoWrapFlags { FlagAnyWrap = 0, // No guarantee. FlagNW = (1 << 0), // No self-wrap. Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -13495,6 +13495,11 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) { auto CollectCondition = [&](ICmpInst::Predicate Predicate, const SCEV *LHS, const SCEV *RHS, ValueToSCEVMapTy &RewriteMap) { + // WARNING: It is generally unsound to apply any wrap flags to the proposed + // replacement SCEV which isn't directly implied by the replacee SCEV. In + // particular, using contextual facts to imply flags is *NOT* legal. See + // the scoping rules for flags in the header to understand why. + // If we have LHS == 0, check if LHS is computing a property of some unknown // SCEV %v which we can rewrite %v to express explicitly. const SCEVConstant *RHSC = dyn_cast(RHS); @@ -13509,7 +13514,7 @@ Value *V = LHSUnknown->getValue(); auto Multiple = getMulExpr(getUDivExpr(URemLHS, URemRHS), URemRHS, - (SCEV::NoWrapFlags)(SCEV::FlagNUW | SCEV::FlagNSW)); + SCEV::FlagAnyWrap); RewriteMap[V] = Multiple; return; }