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

Stepan Dyatkovskiy STPWORLD at narod.ru
Mon Jan 16 12:52:30 PST 2012


Oh... Sorry. It was changed on purpose. 100 is approximately equals to 50 for previous implementation. Comment fixed in r148252.

-- 
Truly yours,
Stepan Dyatkovskiy

17.01.2012, 00:05, "Chad Rosier" <mcrosier at apple.com>:
> 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