aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
diff options
context:
space:
mode:
authorAdam Nemet <anemet@apple.com>2016-04-27 05:28:18 +0000
committerAdam Nemet <anemet@apple.com>2016-04-27 05:28:18 +0000
commitd2fa41471828f9a1c022db095807110b6cfd6dec (patch)
treeb98e72f2b0f554c576b64242a6454b1eec0571db /llvm/lib/Transforms/Scalar/LoopDistribute.cpp
parent08efb0efcdacb079f0687ad94e64b2b85c6f051a (diff)
downloadllvm-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.cpp74
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);
+}
}