[llvm-commits] [llvm] r147935 - in /llvm/trunk: lib/Transforms/Scalar/LoopUnswitch.cpp test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll

Chad Rosier mcrosier at apple.com
Mon Jan 16 12:05:26 PST 2012


Hi Stepan,
See comment below.

On Jan 11, 2012, at 12:40 AM, Stepan Dyatkovskiy wrote:

> Author: dyatkovskiy
> Date: Wed Jan 11 02:40:51 2012
> New Revision: 147935
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=147935&view=rev
> Log:
> Improved compile time:
> 1. Size heuristics changed. Now we calculate number of unswitching
> branches only once per loop.
> 2. Some checks was moved from UnswitchIfProfitable to
> processCurrentLoop, since it is not changed during processCurrentLoop
> iteration. It allows decide to skip some loops at an early stage.
> Extended statistics:
> - Added total number of instructions analyzed.
> 
> 
> Modified:
>    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
>    llvm/trunk/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=147935&r1=147934&r2=147935&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Wed Jan 11 02:40:51 2012
> @@ -56,12 +56,13 @@
> STATISTIC(NumSelects , "Number of selects unswitched");
> STATISTIC(NumTrivial , "Number of unswitches that are trivial");
> STATISTIC(NumSimplify, "Number of simplifications of unswitched code");
> +STATISTIC(TotalInsts,  "Total number of instructions analyzed");
> 
> // The specific value of 50 here was chosen based only on intuition and a
> // few specific examples.
> static cl::opt<unsigned>
> Threshold("loop-unswitch-threshold", cl::desc("Max loop size to unswitch"),
> -          cl::init(50), cl::Hidden);
> +          cl::init(100), cl::Hidden);

Was the default value changed from 50 to 100 on purpose?  If so, please update the comment.  Otherwise, please change back to 50.

 Chad

> namespace {
>   class LoopUnswitch : public LoopPass {
> @@ -72,6 +73,18 @@
>     // after RewriteLoopBodyWithConditionConstant rewrites first loop.
>     std::vector<Loop*> LoopProcessWorklist;
> 
> +    struct LoopProperties {
> +      unsigned CanBeUnswitchedCount;
> +      unsigned SizeEstimation;
> +    };
> +    
> +    typedef DenseMap<const Loop*, LoopProperties> LoopPropsMap;
> +    typedef LoopPropsMap::iterator LoopPropsMapIt;
> +    LoopPropsMap LoopsProperties;
> +    
> +    // Max size of code we can produce on remained iterations.
> +    unsigned MaxSize;
> +    
>     // FIXME: Consider custom class for this.
>     std::map<const SwitchInst*, SmallPtrSet<const Value *,8> > UnswitchedVals;
> 
> @@ -93,7 +106,7 @@
>   public:
>     static char ID; // Pass ID, replacement for typeid
>     explicit LoopUnswitch(bool Os = false) : 
> -      LoopPass(ID), OptimizeForSize(Os), redoLoop(false), 
> +      LoopPass(ID), MaxSize(Threshold), OptimizeForSize(Os), redoLoop(false), 
>       currentLoop(NULL), DT(NULL), loopHeader(NULL),
>       loopPreheader(NULL) {
>         initializeLoopUnswitchPass(*PassRegistry::getPassRegistry());
> @@ -119,6 +132,15 @@
>   private:
> 
>     virtual void releaseMemory() {
> +      
> +      LoopPropsMapIt LIt = LoopsProperties.find(currentLoop);
> +
> +      if (LIt != LoopsProperties.end()) {
> +        LoopProperties& Props = LIt->second;
> +        MaxSize += Props.CanBeUnswitchedCount * Props.SizeEstimation;
> +        LoopsProperties.erase(LIt);
> +      }
> +      
>       // We need to forget about all switches in the current loop.
>       // FIXME: Do it better than enumerating all blocks of code
>       // and see if it is a switch instruction.
> @@ -143,7 +165,10 @@
>     /// already unswitched and has redundant successors.
>     /// Note, that new loop data is stored inside the VMap.
>     void CloneUnswitchedVals(const ValueToValueMapTy& VMap,
> -                                    const BasicBlock* SrcBB);     
> +                                    const BasicBlock* SrcBB);
> +    
> +    bool CountLoop(const Loop* L);
> +    void CloneLoopProperties(const Loop* NewLoop, const Loop* OldLoop);
> 
>     void initLoopData() {
>       loopHeader = currentLoop->getHeader();
> @@ -193,6 +218,10 @@
> /// invariant in the loop, or has an invariant piece, return the invariant.
> /// Otherwise, return null.
> static Value *FindLIVLoopCondition(Value *Cond, Loop *L, bool &Changed) {
> +  
> +  // We started analyze new instruction, increment scanned instructions counter.
> +  ++TotalInsts;
> +  
>   // We can never unswitch on vector conditions.
>   if (Cond->getType()->isVectorTy())
>     return 0;
> @@ -246,7 +275,19 @@
> /// and profitable.
> bool LoopUnswitch::processCurrentLoop() {
>   bool Changed = false;
> -  LLVMContext &Context = currentLoop->getHeader()->getContext();
> +
> +  initLoopData();
> +  
> +  // If LoopSimplify was unable to form a preheader, don't do any unswitching.
> +  if (!loopPreheader)
> +    return false;
> +  
> +  LLVMContext &Context = loopHeader->getContext();
> +  
> +  // Probably we reach the quota of branches for this loop. If so
> +  // stop unswitching.
> +  if (!CountLoop(currentLoop))
> +    return false;
> 
>   // Loop over all of the basic blocks in the loop.  If we find an interior
>   // block that is branching on a loop-invariant condition, we can unswitch this
> @@ -332,6 +373,58 @@
>   }
> }
> 
> +bool LoopUnswitch::CountLoop(const Loop* L) {
> +  std::pair<LoopPropsMapIt, bool> InsertRes =
> +      LoopsProperties.insert(std::make_pair(L, LoopProperties()));
> +  
> +  LoopProperties& Props = InsertRes.first->second;
> +   
> +  if (InsertRes.second) {
> +    // New loop.
> +
> +    // Limit the number of instructions to avoid causing significant code
> +    // expansion, and the number of basic blocks, to avoid loops with
> +    // large numbers of branches which cause loop unswitching to go crazy.
> +    // This is a very ad-hoc heuristic.
> +    
> +    // FIXME: This is overly conservative because it does not take into
> +    // consideration code simplification opportunities and code that can
> +    // be shared by the resultant unswitched loops.
> +    CodeMetrics Metrics;
> +    for (Loop::block_iterator I = L->block_begin(), 
> +           E = L->block_end();
> +         I != E; ++I)
> +      Metrics.analyzeBasicBlock(*I);    
> +
> +    Props.SizeEstimation = std::min(Metrics.NumInsts, Metrics.NumBlocks * 5);
> +    Props.CanBeUnswitchedCount = MaxSize / (Props.SizeEstimation);
> +    MaxSize -= Props.SizeEstimation * Props.CanBeUnswitchedCount;
> +  }
> +   
> +  if (!Props.CanBeUnswitchedCount) {
> +    DEBUG(dbgs() << "NOT unswitching loop %"
> +          << L->getHeader()->getName() << ", cost too high: "
> +          << L->getBlocks().size() << "\n");
> +    
> +    return false;
> +  }
> +  return true;
> +}
> +
> +void LoopUnswitch::CloneLoopProperties(
> +    const Loop* NewLoop, const Loop* OldLoop) {
> +  
> +  LoopProperties& OldLoopProps = LoopsProperties[OldLoop];
> +  LoopProperties& NewLoopProps = LoopsProperties[NewLoop];
> +  
> +  --OldLoopProps.CanBeUnswitchedCount;
> +  unsigned Quota = OldLoopProps.CanBeUnswitchedCount;
> +  NewLoopProps.CanBeUnswitchedCount = Quota / 2;
> +  OldLoopProps.CanBeUnswitchedCount = Quota - Quota / 2;
> +  
> +  NewLoopProps.SizeEstimation = OldLoopProps.SizeEstimation;  
> +}
> +
> /// isTrivialLoopExitBlock - Check to see if all paths from BB exit the
> /// loop with no side effects (including infinite loops).
> ///
> @@ -468,12 +561,6 @@
> /// unswitch the loop, reprocess the pieces, then return true.
> bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val) {
> 
> -  initLoopData();
> -
> -  // If LoopSimplify was unable to form a preheader, don't do any unswitching.
> -  if (!loopPreheader)
> -    return false;
> -
>   Function *F = loopHeader->getParent();
> 
>   Constant *CondVal = 0;
> @@ -491,34 +578,6 @@
>   if (OptimizeForSize || F->hasFnAttr(Attribute::OptimizeForSize))
>     return false;
> 
> -  // FIXME: This is overly conservative because it does not take into
> -  // consideration code simplification opportunities and code that can
> -  // be shared by the resultant unswitched loops.
> -  CodeMetrics Metrics;
> -  for (Loop::block_iterator I = currentLoop->block_begin(), 
> -         E = currentLoop->block_end();
> -       I != E; ++I)
> -    Metrics.analyzeBasicBlock(*I);
> -
> -  // Limit the number of instructions to avoid causing significant code
> -  // expansion, and the number of basic blocks, to avoid loops with
> -  // large numbers of branches which cause loop unswitching to go crazy.
> -  // This is a very ad-hoc heuristic.
> -  
> -  unsigned NumUnswitched =
> -      (NumSwitches + NumBranches) + 1 /*take in account current iteration*/;
> -  
> -  unsigned NumInsts = Metrics.NumInsts * NumUnswitched;
> -  unsigned NumBlocks = Metrics.NumBlocks * NumUnswitched;
> -  
> -  if (NumInsts > Threshold || NumBlocks * 5 > Threshold ||
> -      Metrics.containsIndirectBr || Metrics.isRecursive) {
> -    DEBUG(dbgs() << "NOT unswitching loop %"
> -          << currentLoop->getHeader()->getName() << ", cost too high: "
> -          << currentLoop->getBlocks().size() << "\n");
> -    return false;
> -  }
> -
>   UnswitchNontrivialCondition(LoopCond, Val, currentLoop);
>   return true;
> }
> @@ -701,6 +760,7 @@
> 
>   // Now we create the new Loop object for the versioned loop.
>   Loop *NewLoop = CloneLoop(L, L->getParentLoop(), VMap, LI, LPM);
> +  CloneLoopProperties(NewLoop, L);
>   Loop *ParentLoop = L->getParentLoop();
>   if (ParentLoop) {
>     // Make sure to add the cloned preheader and exit blocks to the parent loop
> 
> Modified: llvm/trunk/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll?rev=147935&r1=147934&r2=147935&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll (original)
> +++ llvm/trunk/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll Wed Jan 11 02:40:51 2012
> @@ -1,5 +1,5 @@
> -; RUN: opt -loop-unswitch -loop-unswitch-threshold 30 -disable-output -stats -info-output-file - < %s | FileCheck --check-prefix=STATS %s
> -; RUN: opt -S -loop-unswitch -loop-unswitch-threshold 30 -verify-loop-info -verify-dom-info %s | FileCheck %s
> +; RUN: opt -loop-unswitch -loop-unswitch-threshold 13 -disable-output -stats -info-output-file - < %s | FileCheck --check-prefix=STATS %s
> +; RUN: opt -S -loop-unswitch -loop-unswitch-threshold 13 -verify-loop-info -verify-dom-info %s | FileCheck %s
> 
> ; STATS: 1 loop-simplify - Number of pre-header or exit blocks inserted
> ; STATS: 1 loop-unswitch - Number of switches unswitched
> 
> 
> _______________________________________________
> 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