diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:25:46 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:25:46 +0000 | 
| commit | 7a7e6055035bfd93ab507051819373a6f171258b (patch) | |
| tree | dc9ac22b4fea4f445748feaf7232a146623f0dfa /contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp | |
| parent | b96a714f453e7f5aeeb3c2df2c3e1e8ad749f96f (diff) | |
| parent | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp')
| -rw-r--r-- | contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp | 299 | 
1 files changed, 78 insertions, 221 deletions
| diff --git a/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp b/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp index c1f9503816ee..2aaa4c1ae117 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp @@ -12,243 +12,100 @@  //  //===----------------------------------------------------------------------===// -#include "llvm/IR/Dominators.h"  #include "llvm/Analysis/LoopInfo.h"  #include "llvm/Analysis/ScalarEvolutionExpressions.h"  #include "llvm/Analysis/ScalarEvolutionNormalization.h"  using namespace llvm; -/// IVUseShouldUsePostIncValue - We have discovered a "User" of an IV expression -/// and now we need to decide whether the user should use the preinc or post-inc -/// value.  If this user should use the post-inc version of the IV, return true. -/// -/// Choosing wrong here can break dominance properties (if we choose to use the -/// 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, Value *Operand, -                                       const Loop *L, DominatorTree *DT) { -  // If the user is in the loop, use the preinc value. -  if (L->contains(User)) return false; - -  BasicBlock *LatchBlock = L->getLoopLatch(); -  if (!LatchBlock) -    return false; - -  // Ok, the user is outside of the loop.  If it is dominated by the latch -  // block, use the post-inc value. -  if (DT->dominates(LatchBlock, User->getParent())) -    return true; - -  // There is one case we have to be careful of: PHI nodes.  These little guys -  // can live in blocks that are not dominated by the latch block, but (since -  // 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<PHINode>(User); -  if (!PN || !Operand) return false; // not a phi, not dominated by latch block. - -  // 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) == Operand && -        !DT->dominates(LatchBlock, PN->getIncomingBlock(i))) -      return false; - -  // 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; -} +/// TransformKind - Different types of transformations that +/// TransformForPostIncUse can do. +enum TransformKind { +  /// Normalize - Normalize according to the given loops. +  Normalize, +  /// Denormalize - Perform the inverse transform on the expression with the +  /// given loop set. +  Denormalize +};  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<const SCEV*, const SCEV*> 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); +struct NormalizeDenormalizeRewriter +    : public SCEVRewriteVisitor<NormalizeDenormalizeRewriter> { +  const TransformKind Kind; + +  // NB! Pred is a function_ref.  Storing it here is okay only because +  // we're careful about the lifetime of NormalizeDenormalizeRewriter. +  const NormalizePredTy Pred; + +  NormalizeDenormalizeRewriter(TransformKind Kind, NormalizePredTy Pred, +                               ScalarEvolution &SE) +      : SCEVRewriteVisitor<NormalizeDenormalizeRewriter>(SE), Kind(Kind), +        Pred(Pred) {} +  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr);  }; -  } // 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<SCEVCastExpr>(S)) { -    const SCEV *O = X->getOperand(); -    const SCEV *N = TransformSubExpr(O, User, OperandValToReplace); -    if (O != N) -      switch (S->getSCEVType()) { -      case scZeroExtend: return SE.getZeroExtendExpr(N, S->getType()); -      case scSignExtend: return SE.getSignExtendExpr(N, S->getType()); -      case scTruncate: return SE.getTruncateExpr(N, S->getType()); -      default: llvm_unreachable("Unexpected SCEVCastExpr kind!"); -      } -    return S; -  } - -  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) { -    // An addrec. This is the interesting part. -    SmallVector<const SCEV *, 8> Operands; -    const Loop *L = AR->getLoop(); -    // The addrec conceptually uses its operands at loop entry. -    Instruction *LUser = &L->getHeader()->front(); -    // 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)); +const SCEV * +NormalizeDenormalizeRewriter::visitAddRecExpr(const SCEVAddRecExpr *AR) { +  SmallVector<const SCEV *, 8> Operands; + +  transform(AR->operands(), std::back_inserter(Operands), +            [&](const SCEV *Op) { return visit(Op); }); + +  // Conservatively use AnyWrap until/unless we need FlagNW. +  const SCEV *Result = +      SE.getAddRecExpr(Operands, AR->getLoop(), SCEV::FlagAnyWrap); +  switch (Kind) { +  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 (Pred(AR)) { +      const SCEV *TransformedStep = visit(AR->getStepRecurrence(SE)); +      Result = SE.getMinusSCEV(Result, TransformedStep);      } -    // 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 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; +    break; +  case Denormalize: +    // Here we want to normalize step expressions for the same reasons, as +    // stated above. +    if (Pred(AR)) { +      const SCEV *TransformedStep = visit(AR->getStepRecurrence(SE)); +      Result = SE.getAddExpr(Result, TransformedStep);      } -    return Result; -  } - -  if (const SCEVNAryExpr *X = dyn_cast<SCEVNAryExpr>(S)) { -    SmallVector<const SCEV *, 8> Operands; -    bool Changed = false; -    // Transform each operand. -    for (SCEVNAryExpr::op_iterator I = X->op_begin(), E = X->op_end(); -         I != E; ++I) { -      const SCEV *O = *I; -      const SCEV *N = TransformSubExpr(O, User, OperandValToReplace); -      Changed |= N != O; -      Operands.push_back(N); -    } -    // If any operand actually changed, return a transformed result. -    if (Changed) -      switch (S->getSCEVType()) { -      case scAddExpr: return SE.getAddExpr(Operands); -      case scMulExpr: return SE.getMulExpr(Operands); -      case scSMaxExpr: return SE.getSMaxExpr(Operands); -      case scUMaxExpr: return SE.getUMaxExpr(Operands); -      default: llvm_unreachable("Unexpected SCEVNAryExpr kind!"); -      } -    return S; -  } - -  if (const SCEVUDivExpr *X = dyn_cast<SCEVUDivExpr>(S)) { -    const SCEV *LO = X->getLHS(); -    const SCEV *RO = X->getRHS(); -    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; +    break;    } - -  llvm_unreachable("Unexpected SCEV kind!"); +  return Result;  } -/// 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<SCEVConstant>(S) || isa<SCEVUnknown>(S)) -    return S; - -  const SCEV *Result = Transformed.lookup(S); -  if (Result) -    return Result; +const SCEV *llvm::normalizeForPostIncUse(const SCEV *S, +                                         const PostIncLoopSet &Loops, +                                         ScalarEvolution &SE) { +  auto Pred = [&](const SCEVAddRecExpr *AR) { +    return Loops.count(AR->getLoop()); +  }; +  return NormalizeDenormalizeRewriter(Normalize, Pred, SE).visit(S); +} -  Result = TransformImpl(S, User, OperandValToReplace); -  Transformed[S] = Result; -  return Result; +const SCEV *llvm::normalizeForPostIncUseIf(const SCEV *S, NormalizePredTy Pred, +                                           ScalarEvolution &SE) { +  return NormalizeDenormalizeRewriter(Normalize, Pred, SE).visit(S);  } -/// 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); +const SCEV *llvm::denormalizeForPostIncUse(const SCEV *S, +                                           const PostIncLoopSet &Loops, +                                           ScalarEvolution &SE) { +  auto Pred = [&](const SCEVAddRecExpr *AR) { +    return Loops.count(AR->getLoop()); +  }; +  return NormalizeDenormalizeRewriter(Denormalize, Pred, SE).visit(S);  } | 
