diff options
author | Adam Nemet <anemet@apple.com> | 2016-04-27 05:28:18 +0000 |
---|---|---|
committer | Adam Nemet <anemet@apple.com> | 2016-04-27 05:28:18 +0000 |
commit | d2fa41471828f9a1c022db095807110b6cfd6dec (patch) | |
tree | b98e72f2b0f554c576b64242a6454b1eec0571db /llvm/lib/Transforms/Scalar/LoopDistribute.cpp | |
parent | 08efb0efcdacb079f0687ad94e64b2b85c6f051a (diff) | |
download | llvm-d2fa41471828f9a1c022db095807110b6cfd6dec.zip llvm-d2fa41471828f9a1c022db095807110b6cfd6dec.tar.gz llvm-d2fa41471828f9a1c022db095807110b6cfd6dec.tar.bz2 |
[LoopDist] Add llvm.loop.distribute.enable loop metadata
Summary:
D19403 adds a new pragma for loop distribution. This change adds
support for the corresponding metadata that the pragma is translated to
by the FE.
As part of this I had to rethink the flag -enable-loop-distribute. My
goal was to be backward compatible with the existing behavior:
A1. pass is off by default from the optimization pipeline
unless -enable-loop-distribute is specified
A2. pass is on when invoked directly from opt (e.g. for unit-testing)
The new pragma/metadata overrides these defaults so the new behavior is:
B1. A1 + enable distribution for individual loop with the pragma/metadata
B2. A2 + disable distribution for individual loop with the pragma/metadata
The default value whether the pass is on or off comes from the initiator
of the pass. From the PassManagerBuilder the default is off, from opt
it's on.
I moved -enable-loop-distribute under the pass. If the flag is
specified it overrides the default from above.
Then the pragma/metadata can further modifies this per loop.
As a side-effect, we can now also use -enable-loop-distribute=0 from opt
to emulate the default from the optimization pipeline. So to be precise
this is the new behavior:
C1. pass is off by default from the optimization pipeline
unless -enable-loop-distribute or the pragma/metadata enables it
C2. pass is on when invoked directly from opt
unless -enable-loop-distribute=0 or the pragma/metadata disables it
Reviewers: hfinkel
Subscribers: joker.eph, mzolotukhin, llvm-commits
Differential Revision: http://reviews.llvm.org/D19431
llvm-svn: 267672
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LoopDistribute.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/LoopDistribute.cpp | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp index 196bec2..8bafb2d 100644 --- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp @@ -60,6 +60,19 @@ static cl::opt<unsigned> DistributeSCEVCheckThreshold( cl::desc("The maximum number of SCEV checks allowed for Loop " "Distribution")); +static cl::opt<unsigned> PragmaDistributeSCEVCheckThreshold( + "loop-distribute-scev-check-threshold-with-pragma", cl::init(128), + cl::Hidden, + cl::desc( + "The maximum number of SCEV checks allowed for Loop " + "Distribution for loop marked with #pragma loop distribute(enable)")); + +// Note that the initial value for this depends on whether the pass is invoked +// directly or from the optimization pipeline. +static cl::opt<bool> EnableLoopDistribute( + "enable-loop-distribute", cl::Hidden, + cl::desc("Enable the new, experimental LoopDistribution Pass")); + STATISTIC(NumLoopsDistributed, "Number of loops distributed"); namespace { @@ -576,7 +589,9 @@ class LoopDistributeForLoop { public: LoopDistributeForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI, DominatorTree *DT, ScalarEvolution *SE) - : L(L), LI(LI), LAI(LAI), DT(DT), SE(SE) {} + : L(L), LI(LI), LAI(LAI), DT(DT), SE(SE) { + setForced(); + } /// \brief Try to distribute an inner-most loop. bool processLoop() { @@ -683,7 +698,9 @@ public: // Don't distribute the loop if we need too many SCEV run-time checks. const SCEVUnionPredicate &Pred = LAI.PSE.getUnionPredicate(); - if (Pred.getComplexity() > DistributeSCEVCheckThreshold) { + if (Pred.getComplexity() > (IsForced.getValueOr(false) + ? PragmaDistributeSCEVCheckThreshold + : DistributeSCEVCheckThreshold)) { DEBUG(dbgs() << "Too many SCEV run-time checks needed.\n"); return false; } @@ -735,6 +752,13 @@ public: return true; } + /// \brief Return if distribution forced to be enabled/disabled for the loop. + /// + /// If the optional has a value, it indicates whether distribution was forced + /// to be enabled (true) or disabled (false). If the optional has no value + /// distribution was not forced either way. + const Optional<bool> &isForced() const { return IsForced; } + private: /// \brief Filter out checks between pointers from the same partition. /// @@ -775,18 +799,47 @@ private: return Checks; } + /// \brief Check whether the loop metadata is forcing distribution to be + /// enabled/disabled. + void setForced() { + Optional<const MDOperand *> Value = + findStringMetadataForLoop(L, "llvm.loop.distribute.enable"); + if (!Value) + return; + + const MDOperand *Op = *Value; + assert(Op && mdconst::hasa<ConstantInt>(*Op) && "invalid metadata"); + IsForced = mdconst::extract<ConstantInt>(*Op)->getZExtValue(); + } + // Analyses used. Loop *L; LoopInfo *LI; const LoopAccessInfo &LAI; DominatorTree *DT; ScalarEvolution *SE; + + /// \brief Indicates whether distribution is forced to be enabled/disabled for + /// the loop. + /// + /// If the optional has a value, it indicates whether distribution was forced + /// to be enabled (true) or disabled (false). If the optional has no value + /// distribution was not forced either way. + Optional<bool> IsForced; }; /// \brief The pass class. class LoopDistribute : public FunctionPass { public: - LoopDistribute() : FunctionPass(ID) { + /// \p ProcessAllLoopsByDefault specifies whether loop distribution should be + /// performed by default. Pass -enable-loop-distribute={0,1} overrides this + /// default. We use this to keep LoopDistribution off by default when invoked + /// from the optimization pipeline but on when invoked explicitly from opt. + LoopDistribute(bool ProcessAllLoopsByDefault = true) + : FunctionPass(ID), ProcessAllLoops(ProcessAllLoopsByDefault) { + // The default is set by the caller. + if (EnableLoopDistribute.getNumOccurrences() > 0) + ProcessAllLoops = EnableLoopDistribute; initializeLoopDistributePass(*PassRegistry::getPassRegistry()); } @@ -812,7 +865,11 @@ public: for (Loop *L : Worklist) { const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap()); LoopDistributeForLoop LDL(L, LI, LAI, DT, SE); - Changed |= LDL.processLoop(); + + // If distribution was forced for the specific loop to be + // enabled/disabled, follow that. Otherwise use the global flag. + if (LDL.isForced().getValueOr(ProcessAllLoops)) + Changed |= LDL.processLoop(); } // Process each loop nest in the function. @@ -829,6 +886,11 @@ public: } static char ID; + +private: + /// \brief Whether distribution should be on in this function. The per-loop + /// pragma can override this. + bool ProcessAllLoops; }; } // anonymous namespace @@ -843,5 +905,7 @@ INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) INITIALIZE_PASS_END(LoopDistribute, LDIST_NAME, ldist_name, false, false) namespace llvm { -FunctionPass *createLoopDistributePass() { return new LoopDistribute(); } +FunctionPass *createLoopDistributePass(bool ProcessAllLoopsByDefault) { + return new LoopDistribute(ProcessAllLoopsByDefault); +} } |