X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FScalarEvolutionNormalization.cpp;h=3ccefb01101dcdc8d76bc7d7e64e958ac3f32255;hb=1cb132f921c55f9584d06787b849ef0f255403b2;hp=d9e909c95661702d19987993664ca3de9422b305;hpb=082d6b653694185d4049c3823eecc2a98c3aef58;p=oota-llvm.git diff --git a/lib/Analysis/ScalarEvolutionNormalization.cpp b/lib/Analysis/ScalarEvolutionNormalization.cpp index d9e909c9566..3ccefb01101 100644 --- a/lib/Analysis/ScalarEvolutionNormalization.cpp +++ b/lib/Analysis/ScalarEvolutionNormalization.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/Dominators.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" @@ -26,7 +26,7 @@ using namespace llvm; /// post-inc value when we cannot) or it can end up adding extra live-ranges to /// the loop, resulting in reg-reg copies (if we use the pre-inc value when we /// should use the post-inc value). -static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, +static bool IVUseShouldUsePostIncValue(Instruction *User, Value *Operand, const Loop *L, DominatorTree *DT) { // If the user is in the loop, use the preinc value. if (L->contains(User)) return false; @@ -45,35 +45,55 @@ static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, // their uses occur in the predecessor block, not the block the PHI lives in) // should still use the post-inc value. Check for this case now. PHINode *PN = dyn_cast(User); - if (!PN) return false; // not a phi, not dominated by latch block. + if (!PN || !Operand) return false; // not a phi, not dominated by latch block. - // Look at all of the uses of IV by the PHI node. If any use corresponds to - // a block that is not dominated by the latch block, give up and use the + // Look at all of the uses of Operand by the PHI node. If any use corresponds + // to a block that is not dominated by the latch block, give up and use the // preincremented value. for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) - if (PN->getIncomingValue(i) == IV && + if (PN->getIncomingValue(i) == Operand && !DT->dominates(LatchBlock, PN->getIncomingBlock(i))) return false; - // Okay, all uses of IV by PN are in predecessor blocks that really are + // Okay, all uses of Operand by PN are in predecessor blocks that really are // dominated by the latch block. Use the post-incremented value. return true; } -const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, - const SCEV *S, - Instruction *User, - Value *OperandValToReplace, - PostIncLoopSet &Loops, - ScalarEvolution &SE, - DominatorTree &DT) { - if (isa(S) || isa(S)) - return S; +namespace { + +/// Hold the state used during post-inc expression transformation, including a +/// map of transformed expressions. +class PostIncTransform { + TransformKind Kind; + PostIncLoopSet &Loops; + ScalarEvolution &SE; + DominatorTree &DT; + + DenseMap Transformed; + +public: + PostIncTransform(TransformKind kind, PostIncLoopSet &loops, + ScalarEvolution &se, DominatorTree &dt): + Kind(kind), Loops(loops), SE(se), DT(dt) {} + + const SCEV *TransformSubExpr(const SCEV *S, Instruction *User, + Value *OperandValToReplace); + +protected: + const SCEV *TransformImpl(const SCEV *S, Instruction *User, + Value *OperandValToReplace); +}; + +} // namespace + +/// Implement post-inc transformation for all valid expression types. +const SCEV *PostIncTransform:: +TransformImpl(const SCEV *S, Instruction *User, Value *OperandValToReplace) { if (const SCEVCastExpr *X = dyn_cast(S)) { const SCEV *O = X->getOperand(); - const SCEV *N = TransformForPostIncUse(Kind, O, User, OperandValToReplace, - Loops, SE, DT); + const SCEV *N = TransformSubExpr(O, User, OperandValToReplace); if (O != N) switch (S->getSCEVType()) { case scZeroExtend: return SE.getZeroExtendExpr(N, S->getType()); @@ -84,6 +104,89 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, return S; } + if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // An addrec. This is the interesting part. + SmallVector Operands; + const Loop *L = AR->getLoop(); + // The addrec conceptually uses its operands at loop entry. + Instruction *LUser = L->getHeader()->begin(); + // Transform each operand. + for (SCEVNAryExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); + I != E; ++I) { + Operands.push_back(TransformSubExpr(*I, LUser, nullptr)); + } + // Conservatively use AnyWrap until/unless we need FlagNW. + const SCEV *Result = SE.getAddRecExpr(Operands, L, SCEV::FlagAnyWrap); + switch (Kind) { + case NormalizeAutodetect: + // Normalize this SCEV by subtracting the expression for the final step. + // We only allow affine AddRecs to be normalized, otherwise we would not + // be able to correctly denormalize. + // e.g. {1,+,3,+,2} == {-2,+,1,+,2} + {3,+,2} + // Normalized form: {-2,+,1,+,2} + // Denormalized form: {1,+,3,+,2} + // + // However, denormalization would use the a different step expression than + // normalization (see getPostIncExpr), generating the wrong final + // expression: {-2,+,1,+,2} + {1,+,2} => {-1,+,3,+,2} + if (AR->isAffine() && + IVUseShouldUsePostIncValue(User, OperandValToReplace, L, &DT)) { + const SCEV *TransformedStep = + TransformSubExpr(AR->getStepRecurrence(SE), + User, OperandValToReplace); + Result = SE.getMinusSCEV(Result, TransformedStep); + Loops.insert(L); + } +#if 0 + // This assert is conceptually correct, but ScalarEvolution currently + // sometimes fails to canonicalize two equal SCEVs to exactly the same + // form. It's possibly a pessimization when this happens, but it isn't a + // correctness problem, so disable this assert for now. + assert(S == TransformSubExpr(Result, User, OperandValToReplace) && + "SCEV normalization is not invertible!"); +#endif + break; + case Normalize: + // We want to normalize step expression, because otherwise we might not be + // able to denormalize to the original expression. + // + // Here is an example what will happen if we don't normalize step: + // ORIGINAL ISE: + // {(100 /u {1,+,1}<%bb16>),+,(100 /u {1,+,1}<%bb16>)}<%bb25> + // NORMALIZED ISE: + // {((-1 * (100 /u {1,+,1}<%bb16>)) + (100 /u {0,+,1}<%bb16>)),+, + // (100 /u {0,+,1}<%bb16>)}<%bb25> + // DENORMALIZED BACK ISE: + // {((2 * (100 /u {1,+,1}<%bb16>)) + (-1 * (100 /u {2,+,1}<%bb16>))),+, + // (100 /u {1,+,1}<%bb16>)}<%bb25> + // Note that the initial value changes after normalization + + // denormalization, which isn't correct. + if (Loops.count(L)) { + const SCEV *TransformedStep = + TransformSubExpr(AR->getStepRecurrence(SE), + User, OperandValToReplace); + Result = SE.getMinusSCEV(Result, TransformedStep); + } +#if 0 + // See the comment on the assert above. + assert(S == TransformSubExpr(Result, User, OperandValToReplace) && + "SCEV normalization is not invertible!"); +#endif + break; + case Denormalize: + // Here we want to normalize step expressions for the same reasons, as + // stated above. + if (Loops.count(L)) { + const SCEV *TransformedStep = + TransformSubExpr(AR->getStepRecurrence(SE), + User, OperandValToReplace); + Result = SE.getAddExpr(Result, TransformedStep); + } + break; + } + return Result; + } + if (const SCEVNAryExpr *X = dyn_cast(S)) { SmallVector Operands; bool Changed = false; @@ -91,42 +194,11 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, for (SCEVNAryExpr::op_iterator I = X->op_begin(), E = X->op_end(); I != E; ++I) { const SCEV *O = *I; - const SCEV *N = TransformForPostIncUse(Kind, O, User, OperandValToReplace, - Loops, SE, DT); + const SCEV *N = TransformSubExpr(O, User, OperandValToReplace); Changed |= N != O; Operands.push_back(N); } - if (const SCEVAddRecExpr *AR = dyn_cast(S)) { - // An addrec. This is the interesting part. - const Loop *L = AR->getLoop(); - const SCEV *Result = SE.getAddRecExpr(Operands, L); - switch (Kind) { - default: llvm_unreachable("Unexpected transform name!"); - case NormalizeAutodetect: - if (Instruction *OI = dyn_cast(OperandValToReplace)) - if (IVUseShouldUsePostIncValue(User, OI, L, &DT)) { - const SCEV *TransformedStep = - TransformForPostIncUse(Kind, AR->getStepRecurrence(SE), - User, OperandValToReplace, Loops, SE, DT); - Result = SE.getMinusSCEV(Result, TransformedStep); - Loops.insert(L); - } - break; - case Normalize: - if (Loops.count(L)) { - const SCEV *TransformedStep = - TransformForPostIncUse(Kind, AR->getStepRecurrence(SE), - User, OperandValToReplace, Loops, SE, DT); - Result = SE.getMinusSCEV(Result, TransformedStep); - } - break; - case Denormalize: - if (Loops.count(L)) - Result = SE.getAddExpr(Result, AR->getStepRecurrence(SE)); - break; - } - return Result; - } + // If any operand actually changed, return a transformed result. if (Changed) switch (S->getSCEVType()) { case scAddExpr: return SE.getAddExpr(Operands); @@ -141,15 +213,42 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, if (const SCEVUDivExpr *X = dyn_cast(S)) { const SCEV *LO = X->getLHS(); const SCEV *RO = X->getRHS(); - const SCEV *LN = TransformForPostIncUse(Kind, LO, User, OperandValToReplace, - Loops, SE, DT); - const SCEV *RN = TransformForPostIncUse(Kind, RO, User, OperandValToReplace, - Loops, SE, DT); + const SCEV *LN = TransformSubExpr(LO, User, OperandValToReplace); + const SCEV *RN = TransformSubExpr(RO, User, OperandValToReplace); if (LO != LN || RO != RN) return SE.getUDivExpr(LN, RN); return S; } llvm_unreachable("Unexpected SCEV kind!"); - return 0; +} + +/// Manage recursive transformation across an expression DAG. Revisiting +/// expressions would lead to exponential recursion. +const SCEV *PostIncTransform:: +TransformSubExpr(const SCEV *S, Instruction *User, Value *OperandValToReplace) { + + if (isa(S) || isa(S)) + return S; + + const SCEV *Result = Transformed.lookup(S); + if (Result) + return Result; + + Result = TransformImpl(S, User, OperandValToReplace); + Transformed[S] = Result; + return Result; +} + +/// Top level driver for transforming an expression DAG into its requested +/// post-inc form (either "Normalized" or "Denormalized"). +const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, + const SCEV *S, + Instruction *User, + Value *OperandValToReplace, + PostIncLoopSet &Loops, + ScalarEvolution &SE, + DominatorTree &DT) { + PostIncTransform Transform(Kind, Loops, SE, DT); + return Transform.TransformSubExpr(S, User, OperandValToReplace); }