[llvm-commits] [llvm] r137197 - in /llvm/trunk: include/llvm/Analysis/IVUsers.h include/llvm/Transforms/Utils/SimplifyIndVar.h lib/Transforms/Scalar/IndVarSimplify.cpp lib/Transforms/Utils/SimplifyIndVar.cpp

Nick Lewycky nicholas at mxc.ca
Tue Aug 9 22:14:38 PDT 2011


Andrew Trick wrote:
> Author: atrick
> Date: Tue Aug  9 22:46:27 2011
> New Revision: 137197
>
> URL: http://llvm.org/viewvc/llvm-project?rev=137197&view=rev
> Log:
> Added a SimplifyIndVar utility to simplify induction variable users
> based on ScalarEvolution without changing the induction variable phis.
>
> This utility is the main tool of IndVarSimplifyPass, but the pass also
> restructures induction variables in strange ways that are sensitive to
> pass ordering. This provides a way for other loop passes to simplify
> new uses of induction variables created during transformation. The
> utility may be used by any pass that preserves ScalarEvolution. Soon
> LoopUnroll will use it.
>
> The net effect in this checkin is to cleanup the IndVarSimplify pass
> by factoring out the SimplifyIndVar algorithm into a standalone utility.
>
> Added:
>      llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
>      llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
> Modified:
>      llvm/trunk/include/llvm/Analysis/IVUsers.h
>      llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
>
> Modified: llvm/trunk/include/llvm/Analysis/IVUsers.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/IVUsers.h?rev=137197&r1=137196&r2=137197&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/IVUsers.h (original)
> +++ llvm/trunk/include/llvm/Analysis/IVUsers.h Tue Aug  9 22:46:27 2011
> @@ -140,6 +140,8 @@
>     static char ID; // Pass ID, replacement for typeid
>     IVUsers();
>
> +  Loop *getLoop() const { return L; }
> +
>     /// AddUsersIfInteresting - Inspect the specified Instruction.  If it is a
>     /// reducible SCEV, recursively add its users to the IVUsesByStride set and
>     /// return true.  Otherwise, return false.
>
> Added: llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h?rev=137197&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h (added)
> +++ llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h Tue Aug  9 22:46:27 2011
> @@ -0,0 +1,58 @@
> +//===-- llvm/Transforms/Utils/SimplifyIndVar.h - Indvar Utils ---*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file defines in interface for induction variable simplification. It does
> +// not define any actual pass or policy, but provides a single function to
> +// simplify a loop's induction variables based on ScalarEvolution.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
> +#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
> +
> +#include "llvm/Support/CommandLine.h"
> +
> +namespace llvm {
> +
> +extern cl::opt<bool>  DisableIVRewrite;
> +
> +class Loop;
> +class LoopInfo;
> +class DominatorTree;
> +class ScalarEvolution;
> +class LPPassManager;
> +class IVUsers;
> +
> +/// Interface for visiting interesting IV users that are recognized but not
> +/// simplified by this utility.
> +class IVVisitor {
> +public:
> +  virtual ~IVVisitor() {}
> +  virtual void visitCast(CastInst *Cast) = 0;
> +};
> +
> +/// simplifyUsersOfIV - Simplify instructions that use this induction variable
> +/// by using ScalarEvolution to analyze the IV's recurrence.
> +bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
> +                       SmallVectorImpl<WeakVH>  &Dead, IVVisitor *V = NULL);
> +
> +/// SimplifyLoopIVs - Simplify users of induction variables within this
> +/// loop. This does not actually change or add IVs.
> +bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
> +                     SmallVectorImpl<WeakVH>  &Dead);
> +
> +/// simplifyIVUsers - Simplify instructions recorded by the IVUsers pass.
> +/// This is a legacy implementation to reproduce the behavior of the
> +/// IndVarSimplify pass prior to DisableIVRewrite.
> +bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
> +                     SmallVectorImpl<WeakVH>  &Dead);
> +
> +} // namespace llvm
> +
> +#endif
>
> Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=137197&r1=137196&r2=137197&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Aug  9 22:46:27 2011
> @@ -11,8 +11,8 @@
>   // computations derived from them) into simpler forms suitable for subsequent
>   // analysis and transformation.
>   //
> -// This transformation makes the following changes to each loop with an
> -// identifiable induction variable:
> +// Additionally, unless -disable-iv-rewrite is on, this transformation makes the
> +// following changes to each loop with an identifiable induction variable:
>   //   1. All loops are transformed to have a SINGLE canonical induction variable
>   //      which starts at zero and steps by one.
>   //   2. The canonical induction variable is guaranteed to be the first PHI node
> @@ -57,11 +57,11 @@
>   #include "llvm/Support/raw_ostream.h"
>   #include "llvm/Transforms/Utils/Local.h"
>   #include "llvm/Transforms/Utils/BasicBlockUtils.h"
> +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
>   #include "llvm/Target/TargetData.h"
>   #include "llvm/ADT/DenseMap.h"
>   #include "llvm/ADT/SmallVector.h"
>   #include "llvm/ADT/Statistic.h"
> -#include "llvm/ADT/STLExtras.h"
>   using namespace llvm;
>
>   STATISTIC(NumRemoved     , "Number of aux indvars removed");
> @@ -69,16 +69,14 @@
>   STATISTIC(NumInserted    , "Number of canonical indvars added");
>   STATISTIC(NumReplaced    , "Number of exit values replaced");
>   STATISTIC(NumLFTR        , "Number of loop exit tests replaced");
> -STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
> -STATISTIC(NumElimOperand,  "Number of IV operands folded into a use");
>   STATISTIC(NumElimExt     , "Number of IV sign/zero extends eliminated");
> -STATISTIC(NumElimRem     , "Number of IV remainder operations eliminated");
> -STATISTIC(NumElimCmp     , "Number of IV comparisons eliminated");
>   STATISTIC(NumElimIV      , "Number of congruent IVs eliminated");
>
> -static cl::opt<bool>  DisableIVRewrite(
> -  "disable-iv-rewrite", cl::Hidden,
> -  cl::desc("Disable canonical induction variable rewriting"));
> +namespace llvm {
> +  cl::opt<bool>  DisableIVRewrite(
> +    "disable-iv-rewrite", cl::Hidden,
> +    cl::desc("Disable canonical induction variable rewriting"));
> +}
>
>   // Temporary flag for use with -disable-iv-rewrite to force a canonical IV for
>   // LFTR purposes.
> @@ -132,21 +130,12 @@
>       void HandleFloatingPointIV(Loop *L, PHINode *PH);
>       void RewriteNonIntegerIVs(Loop *L);
>
> -    void RewriteLoopExitValues(Loop *L, SCEVExpander&Rewriter);
> -
> -    void SimplifyIVUsers(SCEVExpander&Rewriter);
> -    void SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander&Rewriter);
> -
> -    bool EliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
> -    void EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
> -    void EliminateIVRemainder(BinaryOperator *Rem,
> -                              Value *IVOperand,
> -                              bool IsSigned);
> -
> -    bool FoldIVUser(Instruction *UseInst, Instruction *IVOperand);
> +    void SimplifyAndExtend(Loop *L, SCEVExpander&Rewriter, LPPassManager&LPM);
>
>       void SimplifyCongruentIVs(Loop *L);
>
> +    void RewriteLoopExitValues(Loop *L, SCEVExpander&Rewriter);
> +
>       void RewriteIVExpressions(Loop *L, SCEVExpander&Rewriter);
>
>       Value *LinearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
> @@ -475,6 +464,8 @@
>     // Add a new IVUsers entry for the newly-created integer PHI.
>     if (IU)
>       IU->AddUsersIfInteresting(NewPHI);
> +
> +  Changed = true;
>   }
>
>   void IndVarSimplify::RewriteNonIntegerIVs(Loop *L) {
> @@ -623,36 +614,6 @@
>   //  To be replaced by -disable-iv-rewrite.
>   //===----------------------------------------------------------------------===//
>
> -/// SimplifyIVUsers - Iteratively perform simplification on IVUsers within this
> -/// loop. IVUsers is treated as a worklist. Each successive simplification may
> -/// push more users which may themselves be candidates for simplification.
> -///
> -/// This is the old approach to IV simplification to be replaced by
> -/// SimplifyIVUsersNoRewrite.
> -///
> -void IndVarSimplify::SimplifyIVUsers(SCEVExpander&Rewriter) {
> -  // Each round of simplification involves a round of eliminating operations
> -  // followed by a round of widening IVs. A single IVUsers worklist is used
> -  // across all rounds. The inner loop advances the user. If widening exposes
> -  // more uses, then another pass through the outer loop is triggered.
> -  for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
> -    Instruction *UseInst = I->getUser();
> -    Value *IVOperand = I->getOperandValToReplace();
> -
> -    if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
> -      EliminateIVComparison(ICmp, IVOperand);
> -      continue;
> -    }
> -    if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
> -      bool IsSigned = Rem->getOpcode() == Instruction::SRem;
> -      if (IsSigned || Rem->getOpcode() == Instruction::URem) {
> -        EliminateIVRemainder(Rem, IVOperand, IsSigned);
> -        continue;
> -      }
> -    }
> -  }
> -}
> -
>   // FIXME: It is an extremely bad idea to indvar substitute anything more
>   // complex than affine induction variables.  Doing so will put expensive
>   // polynomial evaluations inside of the loop, and the str reduction pass
> @@ -775,17 +736,34 @@
>     // provides the input to WidenIV.
>     struct WideIVInfo {
>       Type *WidestNativeType; // Widest integer type created [sz]ext
> -    bool IsSigned;                // Was an sext user seen before a zext?
> +    bool IsSigned;          // Was an sext user seen before a zext?
>
>       WideIVInfo() : WidestNativeType(0), IsSigned(false) {}
>     };
> +
> +  class WideIVVisitor : public IVVisitor {
> +    ScalarEvolution *SE;
> +    const TargetData *TD;
> +
> +  public:
> +    WideIVInfo WI;
> +
> +    WideIVVisitor(ScalarEvolution *SCEV, const TargetData *TData) :
> +      SE(SCEV), TD(TData) {}
> +
> +    // Implement the interface used by simplifyUsersOfIV.
> +    virtual void visitCast(CastInst *Cast);
> +  };
>   }
>
> -/// CollectExtend - Update information about the induction variable that is
> +/// visitCast - Update information about the induction variable that is
>   /// extended by this sign or zero extend operation. This is used to determine
>   /// the final width of the IV before actually widening it.
> -static void CollectExtend(CastInst *Cast, bool IsSigned, WideIVInfo&WI,
> -                          ScalarEvolution *SE, const TargetData *TD) {
> +void WideIVVisitor::visitCast(CastInst *Cast) {
> +  bool IsSigned = Cast->getOpcode() == Instruction::SExt;
> +  if (!IsSigned&&  Cast->getOpcode() != Instruction::ZExt)
> +    return;
> +
>     Type *Ty = Cast->getType();
>     uint64_t Width = SE->getTypeSizeInBits(Ty);
>     if (TD&&  !TD->isLegalInteger(Width))
> @@ -1181,242 +1159,16 @@
>   //  Simplification of IV users based on SCEV evaluation.
>   //===----------------------------------------------------------------------===//
>
> -void IndVarSimplify::EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
> -  unsigned IVOperIdx = 0;
> -  ICmpInst::Predicate Pred = ICmp->getPredicate();
> -  if (IVOperand != ICmp->getOperand(0)) {
> -    // Swapped
> -    assert(IVOperand == ICmp->getOperand(1)&&  "Can't find IVOperand");
> -    IVOperIdx = 1;
> -    Pred = ICmpInst::getSwappedPredicate(Pred);
> -  }
> -
> -  // Get the SCEVs for the ICmp operands.
> -  const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
> -  const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
> -
> -  // Simplify unnecessary loops away.
> -  const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
> -  S = SE->getSCEVAtScope(S, ICmpLoop);
> -  X = SE->getSCEVAtScope(X, ICmpLoop);
> -
> -  // If the condition is always true or always false, replace it with
> -  // a constant value.
> -  if (SE->isKnownPredicate(Pred, S, X))
> -    ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
> -  else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
> -    ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
> -  else
> -    return;
> -
> -  DEBUG(dbgs()<<  "INDVARS: Eliminated comparison: "<<  *ICmp<<  '\n');
> -  ++NumElimCmp;
> -  Changed = true;
> -  DeadInsts.push_back(ICmp);
> -}
> -
> -void IndVarSimplify::EliminateIVRemainder(BinaryOperator *Rem,
> -                                          Value *IVOperand,
> -                                          bool IsSigned) {
> -  // We're only interested in the case where we know something about
> -  // the numerator.
> -  if (IVOperand != Rem->getOperand(0))
> -    return;
> -
> -  // Get the SCEVs for the ICmp operands.
> -  const SCEV *S = SE->getSCEV(Rem->getOperand(0));
> -  const SCEV *X = SE->getSCEV(Rem->getOperand(1));
> -
> -  // Simplify unnecessary loops away.
> -  const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
> -  S = SE->getSCEVAtScope(S, ICmpLoop);
> -  X = SE->getSCEVAtScope(X, ICmpLoop);
> -
> -  // i % n  -->   i  if i is in [0,n).
> -  if ((!IsSigned || SE->isKnownNonNegative(S))&&
> -      SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
> -                           S, X))
> -    Rem->replaceAllUsesWith(Rem->getOperand(0));
> -  else {
> -    // (i+1) % n  -->   (i+1)==n?0:(i+1)  if i is in [0,n).
> -    const SCEV *LessOne =
> -      SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
> -    if (IsSigned&&  !SE->isKnownNonNegative(LessOne))
> -      return;
> -
> -    if (!SE->isKnownPredicate(IsSigned ?
> -                              ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
> -                              LessOne, X))
> -      return;
> -
> -    ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
> -                                  Rem->getOperand(0), Rem->getOperand(1),
> -                                  "tmp");
> -    SelectInst *Sel =
> -      SelectInst::Create(ICmp,
> -                         ConstantInt::get(Rem->getType(), 0),
> -                         Rem->getOperand(0), "tmp", Rem);
> -    Rem->replaceAllUsesWith(Sel);
> -  }
> -
> -  // Inform IVUsers about the new users.
> -  if (IU) {
> -    if (Instruction *I = dyn_cast<Instruction>(Rem->getOperand(0)))
> -      IU->AddUsersIfInteresting(I);
> -  }
> -  DEBUG(dbgs()<<  "INDVARS: Simplified rem: "<<  *Rem<<  '\n');
> -  ++NumElimRem;
> -  Changed = true;
> -  DeadInsts.push_back(Rem);
> -}
> -
> -/// EliminateIVUser - Eliminate an operation that consumes a simple IV and has
> -/// no observable side-effect given the range of IV values.
> -bool IndVarSimplify::EliminateIVUser(Instruction *UseInst,
> -                                     Instruction *IVOperand) {
> -  if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
> -    EliminateIVComparison(ICmp, IVOperand);
> -    return true;
> -  }
> -  if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
> -    bool IsSigned = Rem->getOpcode() == Instruction::SRem;
> -    if (IsSigned || Rem->getOpcode() == Instruction::URem) {
> -      EliminateIVRemainder(Rem, IVOperand, IsSigned);
> -      return true;
> -    }
> -  }
> -
> -  // Eliminate any operation that SCEV can prove is an identity function.
> -  if (!SE->isSCEVable(UseInst->getType()) ||
> -      (UseInst->getType() != IVOperand->getType()) ||
> -      (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
> -    return false;
> -
> -  DEBUG(dbgs()<<  "INDVARS: Eliminated identity: "<<  *UseInst<<  '\n');
> -
> -  UseInst->replaceAllUsesWith(IVOperand);
> -  ++NumElimIdentity;
> -  Changed = true;
> -  DeadInsts.push_back(UseInst);
> -  return true;
> -}
> -
> -/// FoldIVUser - Fold an IV operand into its use.  This removes increments of an
> -/// aligned IV when used by a instruction that ignores the low bits.
> -bool IndVarSimplify::FoldIVUser(Instruction *UseInst, Instruction *IVOperand) {
> -  Value *IVSrc = 0;
> -  unsigned OperIdx = 0;
> -  const SCEV *FoldedExpr = 0;
> -  switch (UseInst->getOpcode()) {
> -  default:
> -    return false;
> -  case Instruction::UDiv:
> -  case Instruction::LShr:
> -    // We're only interested in the case where we know something about
> -    // the numerator and have a constant denominator.
> -    if (IVOperand != UseInst->getOperand(OperIdx) ||
> -        !isa<ConstantInt>(UseInst->getOperand(1)))
> -      return false;
> -
> -    // Attempt to fold a binary operator with constant operand.
> -    // e.g. ((I + 1)>>  2) =>  I>>  2
> -    if (IVOperand->getNumOperands() != 2 ||
> -        !isa<ConstantInt>(IVOperand->getOperand(1)))
> -      return false;
> -
> -    IVSrc = IVOperand->getOperand(0);
> -    // IVSrc must be the (SCEVable) IV, since the other operand is const.
> -    assert(SE->isSCEVable(IVSrc->getType())&&  "Expect SCEVable IV operand");
> -
> -    ConstantInt *D = cast<ConstantInt>(UseInst->getOperand(1));
> -    if (UseInst->getOpcode() == Instruction::LShr) {
> -      // Get a constant for the divisor. See createSCEV.
> -      uint32_t BitWidth = cast<IntegerType>(UseInst->getType())->getBitWidth();
> -      if (D->getValue().uge(BitWidth))
> -        return false;
> -
> -      D = ConstantInt::get(UseInst->getContext(),
> -                           APInt(BitWidth, 1).shl(D->getZExtValue()));
> -    }
> -    FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
> -  }
> -  // We have something that might fold it's operand. Compare SCEVs.
> -  if (!SE->isSCEVable(UseInst->getType()))
> -    return false;
> -
> -  // Bypass the operand if SCEV can prove it has no effect.
> -  if (SE->getSCEV(UseInst) != FoldedExpr)
> -    return false;
> -
> -  DEBUG(dbgs()<<  "INDVARS: Eliminated IV operand: "<<  *IVOperand
> -<<  " ->  "<<  *UseInst<<  '\n');
> -
> -  UseInst->setOperand(OperIdx, IVSrc);
> -  assert(SE->getSCEV(UseInst) == FoldedExpr&&  "bad SCEV with folded oper");
> -
> -  ++NumElimOperand;
> -  Changed = true;
> -  if (IVOperand->use_empty())
> -    DeadInsts.push_back(IVOperand);
> -  return true;
> -}
> -
> -/// pushIVUsers - Add all uses of Def to the current IV's worklist.
> -///
> -static void pushIVUsers(
> -  Instruction *Def,
> -  SmallPtrSet<Instruction*,16>  &Simplified,
> -  SmallVectorImpl<  std::pair<Instruction*,Instruction*>  >  &SimpleIVUsers) {
> -
> -  for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
> -       UI != E; ++UI) {
> -    Instruction *User = cast<Instruction>(*UI);
> -
> -    // Avoid infinite or exponential worklist processing.
> -    // Also ensure unique worklist users.
> -    // If Def is a LoopPhi, it may not be in the Simplified set, so check for
> -    // self edges first.
> -    if (User != Def&&  Simplified.insert(User))
> -      SimpleIVUsers.push_back(std::make_pair(User, Def));
> -  }
> -}
> -
> -/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
> -/// expression in terms of that IV.
> -///
> -/// This is similar to IVUsers' isInsteresting() but processes each instruction

Typo, "isInsteresting".

Nick

> -/// non-recursively when the operand is already known to be a simpleIVUser.
> -///
> -static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
> -  if (!SE->isSCEVable(I->getType()))
> -    return false;
> -
> -  // Get the symbolic expression for this instruction.
> -  const SCEV *S = SE->getSCEV(I);
> -
> -  // Only consider affine recurrences.
> -  const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S);
> -  if (AR&&  AR->getLoop() == L)
> -    return true;
> -
> -  return false;
> -}
>
> -/// SimplifyIVUsersNoRewrite - Iteratively perform simplification on a worklist
> -/// of IV users. Each successive simplification may push more users which may
> +/// SimplifyAndExtend - Iteratively perform simplification on a worklist of IV
> +/// users. Each successive simplification may push more users which may
>   /// themselves be candidates for simplification.
>   ///
> -/// The "NoRewrite" algorithm does not require IVUsers analysis. Instead, it
> -/// simplifies instructions in-place during analysis. Rather than rewriting
> -/// induction variables bottom-up from their users, it transforms a chain of
> -/// IVUsers top-down, updating the IR only when it encouters a clear
> -/// optimization opportunitiy. A SCEVExpander "Rewriter" instance is still
> -/// needed, but only used to generate a new IV (phi) of wider type for sign/zero
> -/// extend elimination.
> +/// Sign/Zero extend elimination is interleaved with IV simplification.
>   ///
> -/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
> -///
> -void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander&Rewriter) {
> +void IndVarSimplify::SimplifyAndExtend(Loop *L,
> +                                       SCEVExpander&Rewriter,
> +                                       LPPassManager&LPM) {
>     std::map<PHINode *, WideIVInfo>  WideIVMap;
>
>     SmallVector<PHINode*, 8>  LoopPhis;
> @@ -1433,49 +1185,17 @@
>       // extension. The first time SCEV attempts to normalize sign/zero extension,
>       // the result becomes final. So for the most predictable results, we delay
>       // evaluation of sign/zero extend evaluation until needed, and avoid running
> -    // other SCEV based analysis prior to SimplifyIVUsersNoRewrite.
> +    // other SCEV based analysis prior to SimplifyAndExtend.
>       do {
>         PHINode *CurrIV = LoopPhis.pop_back_val();
>
>         // Information about sign/zero extensions of CurrIV.
> -      WideIVInfo WI;
> -
> -      // Instructions processed by SimplifyIVUsers for CurrIV.
> -      SmallPtrSet<Instruction*,16>  Simplified;
> -
> -      // Use-def pairs if IV users waiting to be processed for CurrIV.
> -      SmallVector<std::pair<Instruction*, Instruction*>, 8>  SimpleIVUsers;
> -
> -      // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
> -      // called multiple times for the same LoopPhi. This is the proper thing to
> -      // do for loop header phis that use each other.
> -      pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
> -
> -      while (!SimpleIVUsers.empty()) {
> -        std::pair<Instruction*, Instruction*>  UseOper =
> -          SimpleIVUsers.pop_back_val();
> -        // Bypass back edges to avoid extra work.
> -        if (UseOper.first == CurrIV) continue;
> +      WideIVVisitor WIV(SE, TD);
>
> -        FoldIVUser(UseOper.first, UseOper.second);
> +      Changed |= simplifyUsersOfIV(CurrIV,&LPM, DeadInsts,&WIV);
>
> -        if (EliminateIVUser(UseOper.first, UseOper.second)) {
> -          pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
> -          continue;
> -        }
> -        if (CastInst *Cast = dyn_cast<CastInst>(UseOper.first)) {
> -          bool IsSigned = Cast->getOpcode() == Instruction::SExt;
> -          if (IsSigned || Cast->getOpcode() == Instruction::ZExt) {
> -            CollectExtend(Cast, IsSigned, WI, SE, TD);
> -          }
> -          continue;
> -        }
> -        if (isSimpleIVUser(UseOper.first, L, SE)) {
> -          pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
> -        }
> -      }
> -      if (WI.WidestNativeType) {
> -        WideIVMap[CurrIV] = WI;
> +      if (WIV.WI.WidestNativeType) {
> +        WideIVMap[CurrIV] = WIV.WI;
>         }
>       } while(!LoopPhis.empty());
>
> @@ -1492,7 +1212,7 @@
>   }
>
>   /// SimplifyCongruentIVs - Check for congruent phis in this loop header and
> -/// populate ExprToIVMap for use later.
> +/// replace them with their chosen representative.
>   ///
>   void IndVarSimplify::SimplifyCongruentIVs(Loop *L) {
>     DenseMap<const SCEV *, PHINode *>  ExprToIVMap;
> @@ -2097,7 +1817,7 @@
>     // set no-wrap flags before normalizing sign/zero extension.
>     if (DisableIVRewrite) {
>       Rewriter.disableCanonicalMode();
> -    SimplifyIVUsersNoRewrite(L, Rewriter);
> +    SimplifyAndExtend(L, Rewriter, LPM);
>     }
>
>     // Check to see if this loop has a computable loop-invariant execution count.
> @@ -2111,7 +1831,7 @@
>
>     // Eliminate redundant IV users.
>     if (!DisableIVRewrite)
> -    SimplifyIVUsers(Rewriter);
> +    Changed |= simplifyIVUsers(IU,&LPM, DeadInsts);
>
>     // Eliminate redundant IV cycles.
>     if (DisableIVRewrite)
>
> Added: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137197&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (added)
> +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Aug  9 22:46:27 2011
> @@ -0,0 +1,413 @@
> +//===-- SimplifyIndVar.cpp - Induction variable simplification ------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements induction variable simplification. It does
> +// not define any actual pass or policy, but provides a single function to
> +// simplify a loop's induction variables based on ScalarEvolution.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "indvars"
> +
> +#include "llvm/Instructions.h"
> +#include "llvm/Analysis/Dominators.h"
> +#include "llvm/Analysis/IVUsers.h"
> +#include "llvm/Analysis/LoopInfo.h"
> +#include "llvm/Analysis/LoopPass.h"
> +#include "llvm/Analysis/ScalarEvolutionExpressions.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
> +#include "llvm/Target/TargetData.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/Statistic.h"
> +
> +using namespace llvm;
> +
> +STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
> +STATISTIC(NumElimOperand,  "Number of IV operands folded into a use");
> +STATISTIC(NumElimRem     , "Number of IV remainder operations eliminated");
> +STATISTIC(NumElimCmp     , "Number of IV comparisons eliminated");
> +
> +namespace {
> +  /// SimplifyIndvar - This is a utility for simplifying induction variables
> +  /// based on ScalarEvolution. It is the primary instrument of the
> +  /// IndvarSimplify pass, but it may also be directly invoked to cleanup after
> +  /// other loop passes that preserve SCEV.
> +  class SimplifyIndvar {
> +    Loop             *L;
> +    LoopInfo         *LI;
> +    DominatorTree    *DT;
> +    ScalarEvolution  *SE;
> +    IVUsers          *IU; // NULL for DisableIVRewrite
> +    const TargetData *TD; // May be NULL
> +
> +    SmallVectorImpl<WeakVH>  &DeadInsts;
> +
> +    bool Changed;
> +
> +  public:
> +    SimplifyIndvar(Loop *Loop, LPPassManager *LPM,
> +                   SmallVectorImpl<WeakVH>  &Dead, IVUsers *IVU = NULL) :
> +      L(Loop),
> +      LI(LPM->getAnalysisIfAvailable<LoopInfo>()),
> +      SE(LPM->getAnalysisIfAvailable<ScalarEvolution>()),
> +      IU(IVU),
> +      TD(LPM->getAnalysisIfAvailable<TargetData>()),
> +      DeadInsts(Dead),
> +      Changed(false) {
> +      assert(LI&&  SE&&  "IV simplification requires ScalarEvolution");
> +    }
> +
> +    bool hasChanged() const { return Changed; }
> +
> +    /// Iteratively perform simplification on a worklist of users of the
> +    /// specified induction variable. This is the top-level driver that applies
> +    /// all simplicitions to users of an IV.
> +    void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
> +
> +    bool foldIVUser(Instruction *UseInst, Instruction *IVOperand);
> +
> +    bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
> +    void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
> +    void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,
> +                              bool IsSigned);
> +  };
> +}
> +
> +/// foldIVUser - Fold an IV operand into its use.  This removes increments of an
> +/// aligned IV when used by a instruction that ignores the low bits.
> +bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
> +  Value *IVSrc = 0;
> +  unsigned OperIdx = 0;
> +  const SCEV *FoldedExpr = 0;
> +  switch (UseInst->getOpcode()) {
> +  default:
> +    return false;
> +  case Instruction::UDiv:
> +  case Instruction::LShr:
> +    // We're only interested in the case where we know something about
> +    // the numerator and have a constant denominator.
> +    if (IVOperand != UseInst->getOperand(OperIdx) ||
> +        !isa<ConstantInt>(UseInst->getOperand(1)))
> +      return false;
> +
> +    // Attempt to fold a binary operator with constant operand.
> +    // e.g. ((I + 1)>>  2) =>  I>>  2
> +    if (IVOperand->getNumOperands() != 2 ||
> +        !isa<ConstantInt>(IVOperand->getOperand(1)))
> +      return false;
> +
> +    IVSrc = IVOperand->getOperand(0);
> +    // IVSrc must be the (SCEVable) IV, since the other operand is const.
> +    assert(SE->isSCEVable(IVSrc->getType())&&  "Expect SCEVable IV operand");
> +
> +    ConstantInt *D = cast<ConstantInt>(UseInst->getOperand(1));
> +    if (UseInst->getOpcode() == Instruction::LShr) {
> +      // Get a constant for the divisor. See createSCEV.
> +      uint32_t BitWidth = cast<IntegerType>(UseInst->getType())->getBitWidth();
> +      if (D->getValue().uge(BitWidth))
> +        return false;
> +
> +      D = ConstantInt::get(UseInst->getContext(),
> +                           APInt(BitWidth, 1).shl(D->getZExtValue()));
> +    }
> +    FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
> +  }
> +  // We have something that might fold it's operand. Compare SCEVs.
> +  if (!SE->isSCEVable(UseInst->getType()))
> +    return false;
> +
> +  // Bypass the operand if SCEV can prove it has no effect.
> +  if (SE->getSCEV(UseInst) != FoldedExpr)
> +    return false;
> +
> +  DEBUG(dbgs()<<  "INDVARS: Eliminated IV operand: "<<  *IVOperand
> +<<  " ->  "<<  *UseInst<<  '\n');
> +
> +  UseInst->setOperand(OperIdx, IVSrc);
> +  assert(SE->getSCEV(UseInst) == FoldedExpr&&  "bad SCEV with folded oper");
> +
> +  ++NumElimOperand;
> +  Changed = true;
> +  if (IVOperand->use_empty())
> +    DeadInsts.push_back(IVOperand);
> +  return true;
> +}
> +
> +/// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
> +/// comparisons against an induction variable.
> +void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
> +  unsigned IVOperIdx = 0;
> +  ICmpInst::Predicate Pred = ICmp->getPredicate();
> +  if (IVOperand != ICmp->getOperand(0)) {
> +    // Swapped
> +    assert(IVOperand == ICmp->getOperand(1)&&  "Can't find IVOperand");
> +    IVOperIdx = 1;
> +    Pred = ICmpInst::getSwappedPredicate(Pred);
> +  }
> +
> +  // Get the SCEVs for the ICmp operands.
> +  const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
> +  const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
> +
> +  // Simplify unnecessary loops away.
> +  const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
> +  S = SE->getSCEVAtScope(S, ICmpLoop);
> +  X = SE->getSCEVAtScope(X, ICmpLoop);
> +
> +  // If the condition is always true or always false, replace it with
> +  // a constant value.
> +  if (SE->isKnownPredicate(Pred, S, X))
> +    ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
> +  else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
> +    ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
> +  else
> +    return;
> +
> +  DEBUG(dbgs()<<  "INDVARS: Eliminated comparison: "<<  *ICmp<<  '\n');
> +  ++NumElimCmp;
> +  Changed = true;
> +  DeadInsts.push_back(ICmp);
> +}
> +
> +/// eliminateIVRemainder - SimplifyIVUsers helper for eliminating useless
> +/// remainder operations operating on an induction variable.
> +void SimplifyIndvar::eliminateIVRemainder(BinaryOperator *Rem,
> +                                      Value *IVOperand,
> +                                      bool IsSigned) {
> +  // We're only interested in the case where we know something about
> +  // the numerator.
> +  if (IVOperand != Rem->getOperand(0))
> +    return;
> +
> +  // Get the SCEVs for the ICmp operands.
> +  const SCEV *S = SE->getSCEV(Rem->getOperand(0));
> +  const SCEV *X = SE->getSCEV(Rem->getOperand(1));
> +
> +  // Simplify unnecessary loops away.
> +  const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
> +  S = SE->getSCEVAtScope(S, ICmpLoop);
> +  X = SE->getSCEVAtScope(X, ICmpLoop);
> +
> +  // i % n  -->   i  if i is in [0,n).
> +  if ((!IsSigned || SE->isKnownNonNegative(S))&&
> +      SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
> +                           S, X))
> +    Rem->replaceAllUsesWith(Rem->getOperand(0));
> +  else {
> +    // (i+1) % n  -->   (i+1)==n?0:(i+1)  if i is in [0,n).
> +    const SCEV *LessOne =
> +      SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
> +    if (IsSigned&&  !SE->isKnownNonNegative(LessOne))
> +      return;
> +
> +    if (!SE->isKnownPredicate(IsSigned ?
> +                              ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
> +                              LessOne, X))
> +      return;
> +
> +    ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
> +                                  Rem->getOperand(0), Rem->getOperand(1),
> +                                  "tmp");
> +    SelectInst *Sel =
> +      SelectInst::Create(ICmp,
> +                         ConstantInt::get(Rem->getType(), 0),
> +                         Rem->getOperand(0), "tmp", Rem);
> +    Rem->replaceAllUsesWith(Sel);
> +  }
> +
> +  // Inform IVUsers about the new users.
> +  if (IU) {
> +    if (Instruction *I = dyn_cast<Instruction>(Rem->getOperand(0)))
> +      IU->AddUsersIfInteresting(I);
> +  }
> +  DEBUG(dbgs()<<  "INDVARS: Simplified rem: "<<  *Rem<<  '\n');
> +  ++NumElimRem;
> +  Changed = true;
> +  DeadInsts.push_back(Rem);
> +}
> +
> +/// eliminateIVUser - Eliminate an operation that consumes a simple IV and has
> +/// no observable side-effect given the range of IV values.
> +bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
> +                                     Instruction *IVOperand) {
> +  if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
> +    eliminateIVComparison(ICmp, IVOperand);
> +    return true;
> +  }
> +  if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
> +    bool IsSigned = Rem->getOpcode() == Instruction::SRem;
> +    if (IsSigned || Rem->getOpcode() == Instruction::URem) {
> +      eliminateIVRemainder(Rem, IVOperand, IsSigned);
> +      return true;
> +    }
> +  }
> +
> +  // Eliminate any operation that SCEV can prove is an identity function.
> +  if (!SE->isSCEVable(UseInst->getType()) ||
> +      (UseInst->getType() != IVOperand->getType()) ||
> +      (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
> +    return false;
> +
> +  DEBUG(dbgs()<<  "INDVARS: Eliminated identity: "<<  *UseInst<<  '\n');
> +
> +  UseInst->replaceAllUsesWith(IVOperand);
> +  ++NumElimIdentity;
> +  Changed = true;
> +  DeadInsts.push_back(UseInst);
> +  return true;
> +}
> +
> +/// pushIVUsers - Add all uses of Def to the current IV's worklist.
> +///
> +static void pushIVUsers(
> +  Instruction *Def,
> +  SmallPtrSet<Instruction*,16>  &Simplified,
> +  SmallVectorImpl<  std::pair<Instruction*,Instruction*>  >  &SimpleIVUsers) {
> +
> +  for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
> +       UI != E; ++UI) {
> +    Instruction *User = cast<Instruction>(*UI);
> +
> +    // Avoid infinite or exponential worklist processing.
> +    // Also ensure unique worklist users.
> +    // If Def is a LoopPhi, it may not be in the Simplified set, so check for
> +    // self edges first.
> +    if (User != Def&&  Simplified.insert(User))
> +      SimpleIVUsers.push_back(std::make_pair(User, Def));
> +  }
> +}
> +
> +/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
> +/// expression in terms of that IV.
> +///
> +/// This is similar to IVUsers' isInsteresting() but processes each instruction
> +/// non-recursively when the operand is already known to be a simpleIVUser.
> +///
> +static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
> +  if (!SE->isSCEVable(I->getType()))
> +    return false;
> +
> +  // Get the symbolic expression for this instruction.
> +  const SCEV *S = SE->getSCEV(I);
> +
> +  // Only consider affine recurrences.
> +  const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S);
> +  if (AR&&  AR->getLoop() == L)
> +    return true;
> +
> +  return false;
> +}
> +
> +/// simplifyUsers - Iteratively perform simplification on a worklist of users
> +/// of the specified induction variable. Each successive simplification may push
> +/// more users which may themselves be candidates for simplification.
> +///
> +/// This algorithm does not require IVUsers analysis. Instead, it simplifies
> +/// instructions in-place during analysis. Rather than rewriting induction
> +/// variables bottom-up from their users, it transforms a chain of IVUsers
> +/// top-down, updating the IR only when it encouters a clear optimization
> +/// opportunitiy.
> +///
> +/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
> +///
> +void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
> +  // Instructions processed by SimplifyIndvar for CurrIV.
> +  SmallPtrSet<Instruction*,16>  Simplified;
> +
> +  // Use-def pairs if IV users waiting to be processed for CurrIV.
> +  SmallVector<std::pair<Instruction*, Instruction*>, 8>  SimpleIVUsers;
> +
> +  // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
> +  // called multiple times for the same LoopPhi. This is the proper thing to
> +  // do for loop header phis that use each other.
> +  pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
> +
> +  while (!SimpleIVUsers.empty()) {
> +    std::pair<Instruction*, Instruction*>  UseOper =
> +      SimpleIVUsers.pop_back_val();
> +    // Bypass back edges to avoid extra work.
> +    if (UseOper.first == CurrIV) continue;
> +
> +    foldIVUser(UseOper.first, UseOper.second);
> +
> +    if (eliminateIVUser(UseOper.first, UseOper.second)) {
> +      pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
> +      continue;
> +    }
> +    CastInst *Cast = dyn_cast<CastInst>(UseOper.first);
> +    if (V&&  Cast) {
> +      V->visitCast(Cast);
> +      continue;
> +    }
> +    if (isSimpleIVUser(UseOper.first, L, SE)) {
> +      pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
> +    }
> +  }
> +}
> +
> +namespace llvm {
> +
> +/// simplifyUsersOfIV - Simplify instructions that use this induction variable
> +/// by using ScalarEvolution to analyze the IV's recurrence.
> +bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
> +                       SmallVectorImpl<WeakVH>  &Dead, IVVisitor *V)
> +{
> +  LoopInfo *LI =&LPM->getAnalysis<LoopInfo>();
> +  SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), LPM, Dead);
> +  SIV.simplifyUsers(CurrIV, V);
> +  return SIV.hasChanged();
> +}
> +
> +/// simplifyLoopIVs - Simplify users of induction variables within this
> +/// loop. This does not actually change or add IVs.
> +bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
> +                     SmallVectorImpl<WeakVH>  &Dead) {
> +  bool Changed = false;
> +  for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
> +    Changed |= simplifyUsersOfIV(cast<PHINode>(I), LPM, Dead);
> +  }
> +  return Changed;
> +}
> +
> +/// simplifyIVUsers - Perform simplification on instructions recorded by the
> +/// IVUsers pass.
> +///
> +/// This is the old approach to IV simplification to be replaced by
> +/// SimplifyLoopIVs.
> +bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
> +                     SmallVectorImpl<WeakVH>  &Dead) {
> +  SimplifyIndvar SIV(IU->getLoop(), LPM, Dead);
> +
> +  // Each round of simplification involves a round of eliminating operations
> +  // followed by a round of widening IVs. A single IVUsers worklist is used
> +  // across all rounds. The inner loop advances the user. If widening exposes
> +  // more uses, then another pass through the outer loop is triggered.
> +  for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
> +    Instruction *UseInst = I->getUser();
> +    Value *IVOperand = I->getOperandValToReplace();
> +
> +    if (ICmpInst *ICmp = dyn_cast<ICmpInst>(UseInst)) {
> +      SIV.eliminateIVComparison(ICmp, IVOperand);
> +      continue;
> +    }
> +    if (BinaryOperator *Rem = dyn_cast<BinaryOperator>(UseInst)) {
> +      bool IsSigned = Rem->getOpcode() == Instruction::SRem;
> +      if (IsSigned || Rem->getOpcode() == Instruction::URem) {
> +        SIV.eliminateIVRemainder(Rem, IVOperand, IsSigned);
> +        continue;
> +      }
> +    }
> +  }
> +  return SIV.hasChanged();
> +}
> +
> +} // namespace llvm
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list