2004-04-18 13:20:17 +08:00
|
|
|
//===-- LoopUnroll.cpp - Loop unroller pass -------------------------------===//
|
2005-04-22 07:48:37 +08:00
|
|
|
//
|
2004-04-18 13:20:17 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 07:48:37 +08:00
|
|
|
//
|
2004-04-18 13:20:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This pass implements a simple loop unroller. It works best when loops have
|
|
|
|
// been canonicalized by the -indvars pass, allowing it to determine the trip
|
|
|
|
// counts of loops easily.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2015-02-13 11:57:40 +08:00
|
|
|
#include "llvm/ADT/SetVector.h"
|
2015-01-04 20:03:27 +08:00
|
|
|
#include "llvm/Analysis/AssumptionCache.h"
|
2011-01-02 15:35:53 +08:00
|
|
|
#include "llvm/Analysis/CodeMetrics.h"
|
2015-03-24 03:32:43 +08:00
|
|
|
#include "llvm/Analysis/InstructionSimplify.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Analysis/LoopPass.h"
|
2010-07-27 02:11:16 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolution.h"
|
2015-02-05 10:34:00 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
2013-01-21 21:04:33 +08:00
|
|
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2014-06-17 07:53:02 +08:00
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
2014-01-13 17:26:24 +08:00
|
|
|
#include "llvm/IR/Dominators.h"
|
2015-03-24 03:32:43 +08:00
|
|
|
#include "llvm/IR/InstVisitor.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
2014-06-17 07:53:02 +08:00
|
|
|
#include "llvm/IR/Metadata.h"
|
2004-09-02 06:55:40 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2009-07-25 08:23:56 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-05-14 08:24:14 +08:00
|
|
|
#include "llvm/Transforms/Utils/UnrollLoop.h"
|
2008-05-16 17:30:00 +08:00
|
|
|
#include <climits>
|
2004-04-18 13:20:17 +08:00
|
|
|
|
2008-05-14 08:24:14 +08:00
|
|
|
using namespace llvm;
|
2004-04-18 13:20:17 +08:00
|
|
|
|
2014-04-22 10:55:47 +08:00
|
|
|
#define DEBUG_TYPE "loop-unroll"
|
|
|
|
|
2008-05-13 08:00:25 +08:00
|
|
|
static cl::opt<unsigned>
|
2010-09-11 01:57:00 +08:00
|
|
|
UnrollThreshold("unroll-threshold", cl::init(150), cl::Hidden,
|
2008-05-13 08:00:25 +08:00
|
|
|
cl::desc("The cut-off point for automatic loop unrolling"));
|
2007-05-12 04:53:41 +08:00
|
|
|
|
2015-02-05 10:34:00 +08:00
|
|
|
static cl::opt<unsigned> UnrollMaxIterationsCountToAnalyze(
|
2015-02-13 13:31:46 +08:00
|
|
|
"unroll-max-iteration-count-to-analyze", cl::init(0), cl::Hidden,
|
2015-02-05 10:34:00 +08:00
|
|
|
cl::desc("Don't allow loop unrolling to simulate more than this number of"
|
|
|
|
"iterations when checking full unroll profitability"));
|
|
|
|
|
2015-02-07 04:20:40 +08:00
|
|
|
static cl::opt<unsigned> UnrollMinPercentOfOptimized(
|
|
|
|
"unroll-percent-of-optimized-for-complete-unroll", cl::init(20), cl::Hidden,
|
|
|
|
cl::desc("If complete unrolling could trigger further optimizations, and, "
|
|
|
|
"by that, remove the given percent of instructions, perform the "
|
|
|
|
"complete unroll even if it's beyond the threshold"));
|
|
|
|
|
|
|
|
static cl::opt<unsigned> UnrollAbsoluteThreshold(
|
|
|
|
"unroll-absolute-threshold", cl::init(2000), cl::Hidden,
|
|
|
|
cl::desc("Don't unroll if the unrolled size is bigger than this threshold,"
|
|
|
|
" even if we can remove big portion of instructions later."));
|
|
|
|
|
2008-05-13 08:00:25 +08:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
UnrollCount("unroll-count", cl::init(0), cl::Hidden,
|
2014-06-17 07:53:02 +08:00
|
|
|
cl::desc("Use this unroll count for all loops including those with "
|
|
|
|
"unroll_count pragma values, for testing purposes"));
|
2004-04-18 13:20:17 +08:00
|
|
|
|
2008-07-29 21:21:23 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Allows loops to be partially unrolled until "
|
|
|
|
"-unroll-threshold loop size is reached."));
|
|
|
|
|
2011-12-09 14:19:40 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
UnrollRuntime("unroll-runtime", cl::ZeroOrMore, cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Unroll loops with run-time trip counts"));
|
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
PragmaUnrollThreshold("pragma-unroll-threshold", cl::init(16 * 1024), cl::Hidden,
|
2014-07-24 01:31:37 +08:00
|
|
|
cl::desc("Unrolled size limit for loops with an unroll(full) or "
|
2014-06-17 07:53:02 +08:00
|
|
|
"unroll_count pragma."));
|
|
|
|
|
2008-05-13 08:00:25 +08:00
|
|
|
namespace {
|
2009-09-02 14:11:42 +08:00
|
|
|
class LoopUnroll : public LoopPass {
|
2004-04-18 13:20:17 +08:00
|
|
|
public:
|
2007-05-03 09:11:54 +08:00
|
|
|
static char ID; // Pass ID, replacement for typeid
|
2013-11-05 08:08:03 +08:00
|
|
|
LoopUnroll(int T = -1, int C = -1, int P = -1, int R = -1) : LoopPass(ID) {
|
2011-04-14 10:27:25 +08:00
|
|
|
CurrentThreshold = (T == -1) ? UnrollThreshold : unsigned(T);
|
2015-02-07 04:20:40 +08:00
|
|
|
CurrentAbsoluteThreshold = UnrollAbsoluteThreshold;
|
|
|
|
CurrentMinPercentOfOptimized = UnrollMinPercentOfOptimized;
|
2011-04-14 10:27:25 +08:00
|
|
|
CurrentCount = (C == -1) ? UnrollCount : unsigned(C);
|
2011-04-14 00:15:29 +08:00
|
|
|
CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P;
|
2013-11-05 08:08:03 +08:00
|
|
|
CurrentRuntime = (R == -1) ? UnrollRuntime : (bool)R;
|
2011-04-14 00:15:29 +08:00
|
|
|
|
|
|
|
UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0);
|
2015-02-07 04:20:40 +08:00
|
|
|
UserAbsoluteThreshold = (UnrollAbsoluteThreshold.getNumOccurrences() > 0);
|
|
|
|
UserPercentOfOptimized =
|
|
|
|
(UnrollMinPercentOfOptimized.getNumOccurrences() > 0);
|
2013-09-12 03:25:43 +08:00
|
|
|
UserAllowPartial = (P != -1) ||
|
|
|
|
(UnrollAllowPartial.getNumOccurrences() > 0);
|
2013-11-05 08:08:03 +08:00
|
|
|
UserRuntime = (R != -1) || (UnrollRuntime.getNumOccurrences() > 0);
|
2013-09-12 03:25:43 +08:00
|
|
|
UserCount = (C != -1) || (UnrollCount.getNumOccurrences() > 0);
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2010-10-20 01:21:58 +08:00
|
|
|
initializeLoopUnrollPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2007-05-02 05:15:47 +08:00
|
|
|
|
2007-05-12 04:53:41 +08:00
|
|
|
/// A magic value for use with the Threshold parameter to indicate
|
|
|
|
/// that the loop unroll should be performed regardless of how much
|
|
|
|
/// code expansion would result.
|
|
|
|
static const unsigned NoThreshold = UINT_MAX;
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2010-09-08 07:15:30 +08:00
|
|
|
// Threshold to use when optsize is specified (and there is no
|
|
|
|
// explicit -unroll-threshold).
|
|
|
|
static const unsigned OptSizeUnrollThreshold = 50;
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2011-12-09 14:19:40 +08:00
|
|
|
// Default unroll count for loops with run-time trip count if
|
|
|
|
// -unroll-count is not set
|
|
|
|
static const unsigned UnrollRuntimeCount = 8;
|
|
|
|
|
2011-04-14 00:15:29 +08:00
|
|
|
unsigned CurrentCount;
|
2010-09-08 07:15:30 +08:00
|
|
|
unsigned CurrentThreshold;
|
2015-02-07 04:20:40 +08:00
|
|
|
unsigned CurrentAbsoluteThreshold;
|
|
|
|
unsigned CurrentMinPercentOfOptimized;
|
2011-04-14 00:15:29 +08:00
|
|
|
bool CurrentAllowPartial;
|
2013-11-05 08:08:03 +08:00
|
|
|
bool CurrentRuntime;
|
2013-09-12 03:25:43 +08:00
|
|
|
bool UserCount; // CurrentCount is user-specified.
|
2011-04-14 00:15:29 +08:00
|
|
|
bool UserThreshold; // CurrentThreshold is user-specified.
|
2015-02-07 04:20:40 +08:00
|
|
|
bool UserAbsoluteThreshold; // CurrentAbsoluteThreshold is
|
|
|
|
// user-specified.
|
|
|
|
bool UserPercentOfOptimized; // CurrentMinPercentOfOptimized is
|
|
|
|
// user-specified.
|
2013-09-12 03:25:43 +08:00
|
|
|
bool UserAllowPartial; // CurrentAllowPartial is user-specified.
|
2013-11-05 08:08:03 +08:00
|
|
|
bool UserRuntime; // CurrentRuntime is user-specified.
|
2007-05-12 04:53:41 +08:00
|
|
|
|
2014-03-05 17:10:37 +08:00
|
|
|
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
2004-04-18 13:20:17 +08:00
|
|
|
|
|
|
|
/// This transformation requires natural loop information & requires that
|
|
|
|
/// loop preheaders be inserted into the CFG...
|
|
|
|
///
|
2014-03-05 17:10:37 +08:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2015-01-04 20:03:27 +08:00
|
|
|
AU.addRequired<AssumptionCacheTracker>();
|
2015-01-17 22:16:18 +08:00
|
|
|
AU.addRequired<LoopInfoWrapperPass>();
|
|
|
|
AU.addPreserved<LoopInfoWrapperPass>();
|
2004-04-18 13:20:17 +08:00
|
|
|
AU.addRequiredID(LoopSimplifyID);
|
2010-07-27 02:11:16 +08:00
|
|
|
AU.addPreservedID(LoopSimplifyID);
|
2006-08-25 05:28:19 +08:00
|
|
|
AU.addRequiredID(LCSSAID);
|
|
|
|
AU.addPreservedID(LCSSAID);
|
2011-08-10 12:29:49 +08:00
|
|
|
AU.addRequired<ScalarEvolution>();
|
2010-08-30 01:21:35 +08:00
|
|
|
AU.addPreserved<ScalarEvolution>();
|
[PM] Change the core design of the TTI analysis to use a polymorphic
type erased interface and a single analysis pass rather than an
extremely complex analysis group.
The end result is that the TTI analysis can contain a type erased
implementation that supports the polymorphic TTI interface. We can build
one from a target-specific implementation or from a dummy one in the IR.
I've also factored all of the code into "mix-in"-able base classes,
including CRTP base classes to facilitate calling back up to the most
specialized form when delegating horizontally across the surface. These
aren't as clean as I would like and I'm planning to work on cleaning
some of this up, but I wanted to start by putting into the right form.
There are a number of reasons for this change, and this particular
design. The first and foremost reason is that an analysis group is
complete overkill, and the chaining delegation strategy was so opaque,
confusing, and high overhead that TTI was suffering greatly for it.
Several of the TTI functions had failed to be implemented in all places
because of the chaining-based delegation making there be no checking of
this. A few other functions were implemented with incorrect delegation.
The message to me was very clear working on this -- the delegation and
analysis group structure was too confusing to be useful here.
The other reason of course is that this is *much* more natural fit for
the new pass manager. This will lay the ground work for a type-erased
per-function info object that can look up the correct subtarget and even
cache it.
Yet another benefit is that this will significantly simplify the
interaction of the pass managers and the TargetMachine. See the future
work below.
The downside of this change is that it is very, very verbose. I'm going
to work to improve that, but it is somewhat an implementation necessity
in C++ to do type erasure. =/ I discussed this design really extensively
with Eric and Hal prior to going down this path, and afterward showed
them the result. No one was really thrilled with it, but there doesn't
seem to be a substantially better alternative. Using a base class and
virtual method dispatch would make the code much shorter, but as
discussed in the update to the programmer's manual and elsewhere,
a polymorphic interface feels like the more principled approach even if
this is perhaps the least compelling example of it. ;]
Ultimately, there is still a lot more to be done here, but this was the
huge chunk that I couldn't really split things out of because this was
the interface change to TTI. I've tried to minimize all the other parts
of this. The follow up work should include at least:
1) Improving the TargetMachine interface by having it directly return
a TTI object. Because we have a non-pass object with value semantics
and an internal type erasure mechanism, we can narrow the interface
of the TargetMachine to *just* do what we need: build and return
a TTI object that we can then insert into the pass pipeline.
2) Make the TTI object be fully specialized for a particular function.
This will include splitting off a minimal form of it which is
sufficient for the inliner and the old pass manager.
3) Add a new pass manager analysis which produces TTI objects from the
target machine for each function. This may actually be done as part
of #2 in order to use the new analysis to implement #2.
4) Work on narrowing the API between TTI and the targets so that it is
easier to understand and less verbose to type erase.
5) Work on narrowing the API between TTI and its clients so that it is
easier to understand and less verbose to forward.
6) Try to improve the CRTP-based delegation. I feel like this code is
just a bit messy and exacerbating the complexity of implementing
the TTI in each target.
Many thanks to Eric and Hal for their help here. I ended up blocked on
this somewhat more abruptly than I expected, and so I appreciate getting
it sorted out very quickly.
Differential Revision: http://reviews.llvm.org/D7293
llvm-svn: 227669
2015-01-31 11:43:40 +08:00
|
|
|
AU.addRequired<TargetTransformInfoWrapperPass>();
|
2008-07-03 15:04:22 +08:00
|
|
|
// FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
|
|
|
|
// If loop unroll does not preserve dom info then LCSSA pass on next
|
|
|
|
// loop will receive invalid dom info.
|
|
|
|
// For now, recreate dom info, if loop is unrolled.
|
2014-01-13 21:07:17 +08:00
|
|
|
AU.addPreserved<DominatorTreeWrapperPass>();
|
2004-04-18 13:20:17 +08:00
|
|
|
}
|
2014-06-17 07:53:02 +08:00
|
|
|
|
|
|
|
// Fill in the UnrollingPreferences parameter with values from the
|
|
|
|
// TargetTransformationInfo.
|
2015-02-01 22:37:03 +08:00
|
|
|
void getUnrollingPreferences(Loop *L, const TargetTransformInfo &TTI,
|
2014-06-17 07:53:02 +08:00
|
|
|
TargetTransformInfo::UnrollingPreferences &UP) {
|
|
|
|
UP.Threshold = CurrentThreshold;
|
2015-02-07 04:20:40 +08:00
|
|
|
UP.AbsoluteThreshold = CurrentAbsoluteThreshold;
|
|
|
|
UP.MinPercentOfOptimized = CurrentMinPercentOfOptimized;
|
2014-06-17 07:53:02 +08:00
|
|
|
UP.OptSizeThreshold = OptSizeUnrollThreshold;
|
|
|
|
UP.PartialThreshold = CurrentThreshold;
|
|
|
|
UP.PartialOptSizeThreshold = OptSizeUnrollThreshold;
|
|
|
|
UP.Count = CurrentCount;
|
|
|
|
UP.MaxCount = UINT_MAX;
|
|
|
|
UP.Partial = CurrentAllowPartial;
|
|
|
|
UP.Runtime = CurrentRuntime;
|
2015-04-14 11:20:38 +08:00
|
|
|
UP.AllowExpensiveTripCount = false;
|
2015-02-01 22:37:03 +08:00
|
|
|
TTI.getUnrollingPreferences(L, UP);
|
2014-06-17 07:53:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Select and return an unroll count based on parameters from
|
|
|
|
// user, unroll preferences, unroll pragmas, or a heuristic.
|
|
|
|
// SetExplicitly is set to true if the unroll count is is set by
|
|
|
|
// the user or a pragma rather than selected heuristically.
|
|
|
|
unsigned
|
2014-07-24 01:31:37 +08:00
|
|
|
selectUnrollCount(const Loop *L, unsigned TripCount, bool PragmaFullUnroll,
|
2014-06-17 07:53:02 +08:00
|
|
|
unsigned PragmaCount,
|
|
|
|
const TargetTransformInfo::UnrollingPreferences &UP,
|
|
|
|
bool &SetExplicitly);
|
|
|
|
|
|
|
|
// Select threshold values used to limit unrolling based on a
|
|
|
|
// total unrolled size. Parameters Threshold and PartialThreshold
|
|
|
|
// are set to the maximum unrolled size for fully and partially
|
|
|
|
// unrolled loops respectively.
|
|
|
|
void selectThresholds(const Loop *L, bool HasPragma,
|
|
|
|
const TargetTransformInfo::UnrollingPreferences &UP,
|
2015-02-05 10:34:00 +08:00
|
|
|
unsigned &Threshold, unsigned &PartialThreshold,
|
2015-05-13 01:20:03 +08:00
|
|
|
unsigned &AbsoluteThreshold,
|
|
|
|
unsigned &PercentOfOptimizedForCompleteUnroll) {
|
2014-06-17 07:53:02 +08:00
|
|
|
// Determine the current unrolling threshold. While this is
|
|
|
|
// normally set from UnrollThreshold, it is overridden to a
|
|
|
|
// smaller value if the current function is marked as
|
|
|
|
// optimize-for-size, and the unroll threshold was not user
|
|
|
|
// specified.
|
|
|
|
Threshold = UserThreshold ? CurrentThreshold : UP.Threshold;
|
|
|
|
PartialThreshold = UserThreshold ? CurrentThreshold : UP.PartialThreshold;
|
2015-05-13 01:20:03 +08:00
|
|
|
AbsoluteThreshold = UserAbsoluteThreshold ? CurrentAbsoluteThreshold
|
|
|
|
: UP.AbsoluteThreshold;
|
|
|
|
PercentOfOptimizedForCompleteUnroll = UserPercentOfOptimized
|
|
|
|
? CurrentMinPercentOfOptimized
|
|
|
|
: UP.MinPercentOfOptimized;
|
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
if (!UserThreshold &&
|
2015-02-14 09:11:29 +08:00
|
|
|
L->getHeader()->getParent()->hasFnAttribute(
|
|
|
|
Attribute::OptimizeForSize)) {
|
2014-06-17 07:53:02 +08:00
|
|
|
Threshold = UP.OptSizeThreshold;
|
|
|
|
PartialThreshold = UP.PartialOptSizeThreshold;
|
|
|
|
}
|
|
|
|
if (HasPragma) {
|
|
|
|
// If the loop has an unrolling pragma, we want to be more
|
|
|
|
// aggressive with unrolling limits. Set thresholds to at
|
|
|
|
// least the PragmaTheshold value which is larger than the
|
|
|
|
// default limits.
|
|
|
|
if (Threshold != NoThreshold)
|
|
|
|
Threshold = std::max<unsigned>(Threshold, PragmaUnrollThreshold);
|
|
|
|
if (PartialThreshold != NoThreshold)
|
|
|
|
PartialThreshold =
|
|
|
|
std::max<unsigned>(PartialThreshold, PragmaUnrollThreshold);
|
|
|
|
}
|
|
|
|
}
|
2015-05-13 01:20:03 +08:00
|
|
|
bool canUnrollCompletely(Loop *L, unsigned Threshold,
|
|
|
|
unsigned AbsoluteThreshold, uint64_t UnrolledSize,
|
|
|
|
unsigned NumberOfOptimizedInstructions,
|
|
|
|
unsigned PercentOfOptimizedForCompleteUnroll);
|
2004-04-18 13:20:17 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2008-05-13 08:00:25 +08:00
|
|
|
char LoopUnroll::ID = 0;
|
2010-10-13 03:48:12 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(LoopUnroll, "loop-unroll", "Unroll loops", false, false)
|
[PM] Change the core design of the TTI analysis to use a polymorphic
type erased interface and a single analysis pass rather than an
extremely complex analysis group.
The end result is that the TTI analysis can contain a type erased
implementation that supports the polymorphic TTI interface. We can build
one from a target-specific implementation or from a dummy one in the IR.
I've also factored all of the code into "mix-in"-able base classes,
including CRTP base classes to facilitate calling back up to the most
specialized form when delegating horizontally across the surface. These
aren't as clean as I would like and I'm planning to work on cleaning
some of this up, but I wanted to start by putting into the right form.
There are a number of reasons for this change, and this particular
design. The first and foremost reason is that an analysis group is
complete overkill, and the chaining delegation strategy was so opaque,
confusing, and high overhead that TTI was suffering greatly for it.
Several of the TTI functions had failed to be implemented in all places
because of the chaining-based delegation making there be no checking of
this. A few other functions were implemented with incorrect delegation.
The message to me was very clear working on this -- the delegation and
analysis group structure was too confusing to be useful here.
The other reason of course is that this is *much* more natural fit for
the new pass manager. This will lay the ground work for a type-erased
per-function info object that can look up the correct subtarget and even
cache it.
Yet another benefit is that this will significantly simplify the
interaction of the pass managers and the TargetMachine. See the future
work below.
The downside of this change is that it is very, very verbose. I'm going
to work to improve that, but it is somewhat an implementation necessity
in C++ to do type erasure. =/ I discussed this design really extensively
with Eric and Hal prior to going down this path, and afterward showed
them the result. No one was really thrilled with it, but there doesn't
seem to be a substantially better alternative. Using a base class and
virtual method dispatch would make the code much shorter, but as
discussed in the update to the programmer's manual and elsewhere,
a polymorphic interface feels like the more principled approach even if
this is perhaps the least compelling example of it. ;]
Ultimately, there is still a lot more to be done here, but this was the
huge chunk that I couldn't really split things out of because this was
the interface change to TTI. I've tried to minimize all the other parts
of this. The follow up work should include at least:
1) Improving the TargetMachine interface by having it directly return
a TTI object. Because we have a non-pass object with value semantics
and an internal type erasure mechanism, we can narrow the interface
of the TargetMachine to *just* do what we need: build and return
a TTI object that we can then insert into the pass pipeline.
2) Make the TTI object be fully specialized for a particular function.
This will include splitting off a minimal form of it which is
sufficient for the inliner and the old pass manager.
3) Add a new pass manager analysis which produces TTI objects from the
target machine for each function. This may actually be done as part
of #2 in order to use the new analysis to implement #2.
4) Work on narrowing the API between TTI and the targets so that it is
easier to understand and less verbose to type erase.
5) Work on narrowing the API between TTI and its clients so that it is
easier to understand and less verbose to forward.
6) Try to improve the CRTP-based delegation. I feel like this code is
just a bit messy and exacerbating the complexity of implementing
the TTI in each target.
Many thanks to Eric and Hal for their help here. I ended up blocked on
this somewhat more abruptly than I expected, and so I appreciate getting
it sorted out very quickly.
Differential Revision: http://reviews.llvm.org/D7293
llvm-svn: 227669
2015-01-31 11:43:40 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
|
2015-01-04 20:03:27 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
2015-01-17 22:16:18 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
2010-10-13 03:48:12 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(LCSSA)
|
2011-10-20 07:56:07 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
|
2010-10-13 03:48:12 +08:00
|
|
|
INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false)
|
2008-05-13 08:00:25 +08:00
|
|
|
|
2013-11-05 08:08:03 +08:00
|
|
|
Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial,
|
|
|
|
int Runtime) {
|
|
|
|
return new LoopUnroll(Threshold, Count, AllowPartial, Runtime);
|
2011-04-14 00:15:29 +08:00
|
|
|
}
|
2004-04-18 13:20:17 +08:00
|
|
|
|
2014-04-01 07:23:51 +08:00
|
|
|
Pass *llvm::createSimpleLoopUnrollPass() {
|
|
|
|
return llvm::createLoopUnrollPass(-1, -1, 0, 0);
|
|
|
|
}
|
|
|
|
|
2015-03-23 20:30:58 +08:00
|
|
|
namespace {
|
2015-05-13 01:20:03 +08:00
|
|
|
/// \brief SCEV expressions visitor used for finding expressions that would
|
|
|
|
/// become constants if the loop L is unrolled.
|
2015-02-05 10:34:00 +08:00
|
|
|
struct FindConstantPointers {
|
2015-05-13 01:20:03 +08:00
|
|
|
/// \brief Shows whether the expression is ConstAddress+Constant or not.
|
2015-02-05 10:34:00 +08:00
|
|
|
bool IndexIsConstant;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
/// \brief Used for filtering out SCEV expressions with two or more AddRec
|
|
|
|
/// subexpressions.
|
|
|
|
///
|
|
|
|
/// Used to filter out complicated SCEV expressions, having several AddRec
|
|
|
|
/// sub-expressions. We don't handle them, because unrolling one loop
|
|
|
|
/// would help to replace only one of these inductions with a constant, and
|
|
|
|
/// consequently, the expression would remain non-constant.
|
|
|
|
bool HaveSeenAR;
|
|
|
|
|
|
|
|
/// \brief If the SCEV expression becomes ConstAddress+Constant, this value
|
|
|
|
/// holds ConstAddress. Otherwise, it's nullptr.
|
2015-02-05 10:34:00 +08:00
|
|
|
Value *BaseAddress;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
/// \brief The loop, which we try to completely unroll.
|
2015-02-05 10:34:00 +08:00
|
|
|
const Loop *L;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
2015-02-05 10:34:00 +08:00
|
|
|
ScalarEvolution &SE;
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
FindConstantPointers(const Loop *L, ScalarEvolution &SE)
|
|
|
|
: IndexIsConstant(true), HaveSeenAR(false), BaseAddress(nullptr),
|
|
|
|
L(L), SE(SE) {}
|
|
|
|
|
|
|
|
/// Examine the given expression S and figure out, if it can be a part of an
|
|
|
|
/// expression, that could become a constant after the loop is unrolled.
|
|
|
|
/// The routine sets IndexIsConstant and HaveSeenAR according to the analysis
|
|
|
|
/// results.
|
|
|
|
/// \returns true if we need to examine subexpressions, and false otherwise.
|
2015-02-05 10:34:00 +08:00
|
|
|
bool follow(const SCEV *S) {
|
|
|
|
if (const SCEVUnknown *SC = dyn_cast<SCEVUnknown>(S)) {
|
|
|
|
// We've reached the leaf node of SCEV, it's most probably just a
|
2015-05-13 01:20:03 +08:00
|
|
|
// variable.
|
|
|
|
// If it's the only one SCEV-subexpression, then it might be a base
|
|
|
|
// address of an index expression.
|
|
|
|
// If we've already recorded base address, then just give up on this SCEV
|
|
|
|
// - it's too complicated.
|
|
|
|
if (BaseAddress) {
|
|
|
|
IndexIsConstant = false;
|
|
|
|
return false;
|
|
|
|
}
|
2015-02-05 10:34:00 +08:00
|
|
|
BaseAddress = SC->getValue();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (isa<SCEVConstant>(S))
|
2015-05-13 01:20:03 +08:00
|
|
|
return false;
|
2015-02-05 10:34:00 +08:00
|
|
|
if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
|
|
|
|
// If the current SCEV expression is AddRec, and its loop isn't the loop
|
|
|
|
// we are about to unroll, then we won't get a constant address after
|
|
|
|
// unrolling, and thus, won't be able to eliminate the load.
|
2015-05-13 01:20:03 +08:00
|
|
|
if (AR->getLoop() != L) {
|
|
|
|
IndexIsConstant = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// We don't handle multiple AddRecs here, so give up in this case.
|
|
|
|
if (HaveSeenAR) {
|
|
|
|
IndexIsConstant = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
HaveSeenAR = true;
|
2015-02-05 10:34:00 +08:00
|
|
|
}
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
// Continue traversal.
|
|
|
|
return true;
|
2015-02-05 10:34:00 +08:00
|
|
|
}
|
|
|
|
bool isDone() const { return !IndexIsConstant; }
|
|
|
|
};
|
2015-05-22 11:02:22 +08:00
|
|
|
} // End anonymous namespace.
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2015-05-22 11:02:22 +08:00
|
|
|
namespace {
|
|
|
|
/// \brief Struct to represent a GEP whose start and step are known fixed
|
|
|
|
/// offsets from a base address due to SCEV's analysis.
|
|
|
|
struct SCEVGEPDescriptor {
|
|
|
|
Value *BaseAddr;
|
|
|
|
unsigned Start;
|
|
|
|
unsigned Step;
|
|
|
|
};
|
|
|
|
} // End anonymous namespace.
|
|
|
|
|
|
|
|
/// \brief Build a cache of all the GEP instructions which SCEV can describe.
|
|
|
|
///
|
|
|
|
/// Visit all GEPs in the loop and find those which after complete loop
|
|
|
|
/// unrolling would become a constant, or BaseAddress+Constant. For those where
|
|
|
|
/// we can identify small constant starts and steps from a base address, return
|
|
|
|
/// a map from the GEP to the base, start, and step relevant for that GEP. This
|
|
|
|
/// is essentially a simplified and fast to query form of the SCEV analysis
|
|
|
|
/// which we can afford to look into repeatedly for different iterations of the
|
|
|
|
/// loop.
|
|
|
|
static SmallDenseMap<Value *, SCEVGEPDescriptor>
|
|
|
|
buildSCEVGEPCache(const Loop &L, ScalarEvolution &SE) {
|
|
|
|
SmallDenseMap<Value *, SCEVGEPDescriptor> Cache;
|
|
|
|
|
|
|
|
for (auto BB : L.getBlocks()) {
|
|
|
|
for (Instruction &I : *BB) {
|
|
|
|
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
|
|
|
|
Value *V = cast<Value>(GEP);
|
|
|
|
if (!SE.isSCEVable(V->getType()))
|
|
|
|
continue;
|
|
|
|
const SCEV *S = SE.getSCEV(V);
|
|
|
|
// FIXME: Hoist the initialization out of the loop.
|
|
|
|
FindConstantPointers Visitor(&L, SE);
|
|
|
|
SCEVTraversal<FindConstantPointers> T(Visitor);
|
|
|
|
// Try to find (BaseAddress+Step+Offset) tuple.
|
|
|
|
// If succeeded, save it to the cache - it might help in folding
|
|
|
|
// loads.
|
|
|
|
T.visitAll(S);
|
|
|
|
if (!Visitor.IndexIsConstant || !Visitor.BaseAddress)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const SCEV *BaseAddrSE = SE.getSCEV(Visitor.BaseAddress);
|
|
|
|
if (BaseAddrSE->getType() != S->getType())
|
|
|
|
continue;
|
|
|
|
const SCEV *OffSE = SE.getMinusSCEV(S, BaseAddrSE);
|
|
|
|
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(OffSE);
|
|
|
|
|
|
|
|
if (!AR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const SCEVConstant *StepSE =
|
|
|
|
dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE));
|
|
|
|
const SCEVConstant *StartSE = dyn_cast<SCEVConstant>(AR->getStart());
|
|
|
|
if (!StepSE || !StartSE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Check and skip caching if doing so would require lots of bits to
|
|
|
|
// avoid overflow.
|
|
|
|
APInt Start = StartSE->getValue()->getValue();
|
|
|
|
APInt Step = StepSE->getValue()->getValue();
|
|
|
|
if (Start.getActiveBits() > 32 || Step.getActiveBits() > 32)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// We found a cacheable SCEV model for the GEP.
|
|
|
|
Cache[V] = {Visitor.BaseAddress,
|
|
|
|
(unsigned)Start.getLimitedValue(),
|
|
|
|
(unsigned)Step.getLimitedValue()};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
2015-02-05 10:34:00 +08:00
|
|
|
// This class is used to get an estimate of the optimization effects that we
|
|
|
|
// could get from complete loop unrolling. It comes from the fact that some
|
|
|
|
// loads might be replaced with concrete constant values and that could trigger
|
|
|
|
// a chain of instruction simplifications.
|
|
|
|
//
|
|
|
|
// E.g. we might have:
|
|
|
|
// int a[] = {0, 1, 0};
|
|
|
|
// v = 0;
|
|
|
|
// for (i = 0; i < 3; i ++)
|
|
|
|
// v += b[i]*a[i];
|
|
|
|
// If we completely unroll the loop, we would get:
|
|
|
|
// v = b[0]*a[0] + b[1]*a[1] + b[2]*a[2]
|
|
|
|
// Which then will be simplified to:
|
|
|
|
// v = b[0]* 0 + b[1]* 1 + b[2]* 0
|
|
|
|
// And finally:
|
|
|
|
// v = b[1]
|
|
|
|
class UnrollAnalyzer : public InstVisitor<UnrollAnalyzer, bool> {
|
|
|
|
typedef InstVisitor<UnrollAnalyzer, bool> Base;
|
|
|
|
friend class InstVisitor<UnrollAnalyzer, bool>;
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
/// \brief The loop we're going to analyze.
|
2015-02-05 10:34:00 +08:00
|
|
|
const Loop *L;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
/// \brief TripCount of the given loop.
|
2015-02-05 10:34:00 +08:00
|
|
|
unsigned TripCount;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
2015-02-05 10:34:00 +08:00
|
|
|
ScalarEvolution &SE;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
2015-02-05 10:34:00 +08:00
|
|
|
const TargetTransformInfo &TTI;
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
// While we walk the loop instructions, we we build up and maintain a mapping
|
|
|
|
// of simplified values specific to this iteration. The idea is to propagate
|
|
|
|
// any special information we have about loads that can be replaced with
|
|
|
|
// constants after complete unrolling, and account for likely simplifications
|
|
|
|
// post-unrolling.
|
2015-02-05 10:34:00 +08:00
|
|
|
DenseMap<Value *, Constant *> SimplifiedValues;
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
// To avoid requesting SCEV info on every iteration, request it once, and
|
|
|
|
// for each value that would become ConstAddress+Constant after loop
|
|
|
|
// unrolling, save the corresponding data.
|
2015-05-22 11:02:22 +08:00
|
|
|
SmallDenseMap<Value *, SCEVGEPDescriptor> SCEVGEPCache;
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
/// \brief Number of currently simulated iteration.
|
|
|
|
///
|
|
|
|
/// If an expression is ConstAddress+Constant, then the Constant is
|
|
|
|
/// Start + Iteration*Step, where Start and Step could be obtained from
|
2015-05-22 11:02:22 +08:00
|
|
|
/// SCEVGEPCache.
|
2015-05-13 01:20:03 +08:00
|
|
|
unsigned Iteration;
|
|
|
|
|
|
|
|
/// \brief Upper threshold for complete unrolling.
|
|
|
|
unsigned MaxUnrolledLoopSize;
|
2015-02-13 10:10:56 +08:00
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
/// Base case for the instruction visitor.
|
2015-02-05 10:34:00 +08:00
|
|
|
bool visitInstruction(Instruction &I) { return false; };
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
/// TODO: Add visitors for other instruction types, e.g. ZExt, SExt.
|
|
|
|
|
|
|
|
/// Try to simplify binary operator I.
|
|
|
|
///
|
|
|
|
/// TODO: Probaly it's worth to hoist the code for estimating the
|
|
|
|
/// simplifications effects to a separate class, since we have a very similar
|
|
|
|
/// code in InlineCost already.
|
2015-02-05 10:34:00 +08:00
|
|
|
bool visitBinaryOperator(BinaryOperator &I) {
|
|
|
|
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
|
|
|
if (!isa<Constant>(LHS))
|
|
|
|
if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS))
|
|
|
|
LHS = SimpleLHS;
|
|
|
|
if (!isa<Constant>(RHS))
|
|
|
|
if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS))
|
|
|
|
RHS = SimpleRHS;
|
2015-02-07 04:02:51 +08:00
|
|
|
Value *SimpleV = nullptr;
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL = I.getModule()->getDataLayout();
|
2015-02-07 04:02:51 +08:00
|
|
|
if (auto FI = dyn_cast<FPMathOperator>(&I))
|
|
|
|
SimpleV =
|
2015-03-10 10:37:25 +08:00
|
|
|
SimplifyFPBinOp(I.getOpcode(), LHS, RHS, FI->getFastMathFlags(), DL);
|
2015-02-07 04:02:51 +08:00
|
|
|
else
|
2015-03-10 10:37:25 +08:00
|
|
|
SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS, DL);
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2015-05-22 10:47:29 +08:00
|
|
|
if (Constant *C = dyn_cast_or_null<Constant>(SimpleV))
|
2015-02-05 10:34:00 +08:00
|
|
|
SimplifiedValues[&I] = C;
|
2015-05-22 10:47:29 +08:00
|
|
|
|
|
|
|
return SimpleV;
|
2015-02-05 10:34:00 +08:00
|
|
|
}
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
/// Try to fold load I.
|
|
|
|
bool visitLoad(LoadInst &I) {
|
|
|
|
Value *AddrOp = I.getPointerOperand();
|
|
|
|
if (!isa<Constant>(AddrOp))
|
|
|
|
if (Constant *SimplifiedAddrOp = SimplifiedValues.lookup(AddrOp))
|
|
|
|
AddrOp = SimplifiedAddrOp;
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2015-05-22 11:02:22 +08:00
|
|
|
auto It = SCEVGEPCache.find(AddrOp);
|
|
|
|
if (It == SCEVGEPCache.end())
|
2015-05-13 01:20:03 +08:00
|
|
|
return false;
|
|
|
|
SCEVGEPDescriptor GEPDesc = It->second;
|
|
|
|
|
|
|
|
auto GV = dyn_cast<GlobalVariable>(GEPDesc.BaseAddr);
|
|
|
|
// We're only interested in loads that can be completely folded to a
|
|
|
|
// constant.
|
|
|
|
if (!GV || !GV->hasInitializer())
|
|
|
|
return false;
|
2015-02-05 10:34:00 +08:00
|
|
|
|
|
|
|
ConstantDataSequential *CDS =
|
|
|
|
dyn_cast<ConstantDataSequential>(GV->getInitializer());
|
|
|
|
if (!CDS)
|
2015-05-13 01:20:03 +08:00
|
|
|
return false;
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2015-05-13 07:32:56 +08:00
|
|
|
// This calculation should never overflow because we bound Iteration quite
|
|
|
|
// low and both the start and step are 32-bit integers. We use signed
|
|
|
|
// integers so that UBSan will catch if a bug sneaks into the code.
|
|
|
|
int ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U;
|
|
|
|
int64_t Index = ((int64_t)GEPDesc.Start +
|
|
|
|
(int64_t)GEPDesc.Step * (int64_t)Iteration) /
|
2015-05-13 01:20:03 +08:00
|
|
|
ElemSize;
|
|
|
|
if (Index >= CDS->getNumElements()) {
|
|
|
|
// FIXME: For now we conservatively ignore out of bound accesses, but
|
|
|
|
// we're allowed to perform the optimization in this case.
|
|
|
|
return false;
|
|
|
|
}
|
2015-02-05 10:34:00 +08:00
|
|
|
|
|
|
|
Constant *CV = CDS->getElementAsConstant(Index);
|
2015-05-13 01:20:03 +08:00
|
|
|
assert(CV && "Constant expected.");
|
|
|
|
SimplifiedValues[&I] = CV;
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
return true;
|
2015-02-05 10:34:00 +08:00
|
|
|
}
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
public:
|
|
|
|
UnrollAnalyzer(const Loop *L, unsigned TripCount, ScalarEvolution &SE,
|
|
|
|
const TargetTransformInfo &TTI, unsigned MaxUnrolledLoopSize)
|
|
|
|
: L(L), TripCount(TripCount), SE(SE), TTI(TTI),
|
|
|
|
MaxUnrolledLoopSize(MaxUnrolledLoopSize),
|
|
|
|
NumberOfOptimizedInstructions(0), UnrolledLoopSize(0) {}
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
/// \brief Count the number of optimized instructions.
|
|
|
|
unsigned NumberOfOptimizedInstructions;
|
2015-02-13 10:10:56 +08:00
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
/// \brief Count the total number of instructions.
|
|
|
|
unsigned UnrolledLoopSize;
|
|
|
|
|
|
|
|
/// \brief Figure out if the loop is worth full unrolling.
|
|
|
|
///
|
|
|
|
/// Complete loop unrolling can make some loads constant, and we need to know
|
|
|
|
/// if that would expose any further optimization opportunities. This routine
|
|
|
|
/// estimates this optimization. It assigns computed number of instructions,
|
|
|
|
/// that potentially might be optimized away, to
|
|
|
|
/// NumberOfOptimizedInstructions, and total number of instructions to
|
|
|
|
/// UnrolledLoopSize (not counting blocks that won't be reached, if we were
|
|
|
|
/// able to compute the condition).
|
|
|
|
/// \returns false if we can't analyze the loop, or if we discovered that
|
|
|
|
/// unrolling won't give anything. Otherwise, returns true.
|
|
|
|
bool analyzeLoop() {
|
|
|
|
SmallSetVector<BasicBlock *, 16> BBWorklist;
|
|
|
|
|
2015-05-13 07:32:56 +08:00
|
|
|
// We want to be able to scale offsets by the trip count and add more
|
|
|
|
// offsets to them without checking for overflows, and we already don't want
|
|
|
|
// to analyze *massive* trip counts, so we force the max to be reasonably
|
|
|
|
// small.
|
|
|
|
assert(UnrollMaxIterationsCountToAnalyze < (INT_MAX / 2) &&
|
|
|
|
"The unroll iterations max is too large!");
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
// Don't simulate loops with a big or unknown tripcount
|
|
|
|
if (!UnrollMaxIterationsCountToAnalyze || !TripCount ||
|
|
|
|
TripCount > UnrollMaxIterationsCountToAnalyze)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// To avoid compute SCEV-expressions on every iteration, compute them once
|
2015-05-22 11:02:22 +08:00
|
|
|
// and store interesting to us in SCEVGEPCache.
|
|
|
|
SCEVGEPCache = buildSCEVGEPCache(*L, SE);
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
// Simulate execution of each iteration of the loop counting instructions,
|
|
|
|
// which would be simplified.
|
|
|
|
// Since the same load will take different values on different iterations,
|
|
|
|
// we literally have to go through all loop's iterations.
|
|
|
|
for (Iteration = 0; Iteration < TripCount; ++Iteration) {
|
|
|
|
SimplifiedValues.clear();
|
|
|
|
BBWorklist.clear();
|
|
|
|
BBWorklist.insert(L->getHeader());
|
|
|
|
// Note that we *must not* cache the size, this loop grows the worklist.
|
|
|
|
for (unsigned Idx = 0; Idx != BBWorklist.size(); ++Idx) {
|
|
|
|
BasicBlock *BB = BBWorklist[Idx];
|
|
|
|
|
|
|
|
// Visit all instructions in the given basic block and try to simplify
|
|
|
|
// it. We don't change the actual IR, just count optimization
|
|
|
|
// opportunities.
|
|
|
|
for (Instruction &I : *BB) {
|
|
|
|
UnrolledLoopSize += TTI.getUserCost(&I);
|
2015-05-22 10:47:29 +08:00
|
|
|
|
|
|
|
// Visit the instruction to analyze its loop cost after unrolling,
|
|
|
|
// and if the visitor returns true, then we can optimize this
|
|
|
|
// instruction away.
|
|
|
|
if (Base::visit(I))
|
|
|
|
NumberOfOptimizedInstructions += TTI.getUserCost(&I);
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
// If unrolled body turns out to be too big, bail out.
|
|
|
|
if (UnrolledLoopSize - NumberOfOptimizedInstructions >
|
|
|
|
MaxUnrolledLoopSize)
|
|
|
|
return false;
|
|
|
|
}
|
2015-02-13 10:17:39 +08:00
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
// Add BB's successors to the worklist.
|
|
|
|
for (BasicBlock *Succ : successors(BB))
|
|
|
|
if (L->contains(Succ))
|
|
|
|
BBWorklist.insert(Succ);
|
[unroll] Make the unroll cost analysis terminate deterministically and
reasonably quickly.
I don't have a reduced test case, but for a version of FFMPEG, this
makes the loop unroller start finishing at all (after over 15 minutes of
running, it hadn't terminated for me, no idea if it was a true infloop
or just exponential work).
The key thing here is to check the DeadInstructions set when pulling
things off the worklist. Without this, we would re-walk the user list of
already dead instructions again and again and again. Consider phi nodes
with many, many operands and other patterns.
The other important aspect of this is that because we would keep
re-visiting instructions that were already known dead, we kept adding
their cost savings to this! This would cause our cost savings to be
*insanely* inflated from this.
While I was here, I also rotated the operand walk out of the worklist
loop to make the code easier to read. There is still work to be done to
minimize worklist traffic because we don't de-duplicate operands. This
means we may add the same instruction onto the worklist 1000s of times
if it shows up in 1000s of operansd to a PHI node for example.
Still, with this patch, the ffmpeg testcase I have finishes quickly and
I can't measure the runtime impact of the unroll analysis any more. I'll
probably try to do a few more cleanups to this code, but not sure how
much cleanup I can justify right now.
llvm-svn: 229038
2015-02-13 11:40:58 +08:00
|
|
|
}
|
2015-05-13 01:20:03 +08:00
|
|
|
|
|
|
|
// If we found no optimization opportunities on the first iteration, we
|
|
|
|
// won't find them on later ones too.
|
|
|
|
if (!NumberOfOptimizedInstructions)
|
|
|
|
return false;
|
2015-02-05 10:34:00 +08:00
|
|
|
}
|
2015-05-13 01:20:03 +08:00
|
|
|
return true;
|
2015-02-05 10:34:00 +08:00
|
|
|
}
|
|
|
|
};
|
2015-03-23 20:30:58 +08:00
|
|
|
} // namespace
|
2015-02-05 10:34:00 +08:00
|
|
|
|
2007-05-08 23:14:19 +08:00
|
|
|
/// ApproximateLoopSize - Approximate the size of the loop.
|
2011-10-01 09:39:05 +08:00
|
|
|
static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls,
|
2013-01-21 21:04:33 +08:00
|
|
|
bool &NotDuplicatable,
|
2014-09-07 21:49:57 +08:00
|
|
|
const TargetTransformInfo &TTI,
|
2015-01-04 20:03:27 +08:00
|
|
|
AssumptionCache *AC) {
|
2014-09-07 21:49:57 +08:00
|
|
|
SmallPtrSet<const Value *, 32> EphValues;
|
2015-01-04 20:03:27 +08:00
|
|
|
CodeMetrics::collectEphemeralValues(L, AC, EphValues);
|
2014-09-07 21:49:57 +08:00
|
|
|
|
2009-10-31 22:54:17 +08:00
|
|
|
CodeMetrics Metrics;
|
2008-06-23 04:18:58 +08:00
|
|
|
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
|
2009-10-31 22:54:17 +08:00
|
|
|
I != E; ++I)
|
2014-09-07 21:49:57 +08:00
|
|
|
Metrics.analyzeBasicBlock(*I, TTI, EphValues);
|
2010-09-10 04:32:23 +08:00
|
|
|
NumCalls = Metrics.NumInlineCandidates;
|
2012-12-21 00:04:27 +08:00
|
|
|
NotDuplicatable = Metrics.notDuplicatable;
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2010-09-10 03:07:31 +08:00
|
|
|
unsigned LoopSize = Metrics.NumInsts;
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2010-09-10 03:07:31 +08:00
|
|
|
// Don't allow an estimate of size zero. This would allows unrolling of loops
|
|
|
|
// with huge iteration counts, which is a compile time problem even if it's
|
2015-01-10 08:30:55 +08:00
|
|
|
// not a problem for code quality. Also, the code using this size may assume
|
|
|
|
// that each loop has at least three instructions (likely a conditional
|
|
|
|
// branch, a comparison feeding that branch, and some kind of loop increment
|
|
|
|
// feeding that comparison instruction).
|
|
|
|
LoopSize = std::max(LoopSize, 3u);
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2010-09-10 03:07:31 +08:00
|
|
|
return LoopSize;
|
2004-04-18 13:20:17 +08:00
|
|
|
}
|
|
|
|
|
2014-07-24 01:31:37 +08:00
|
|
|
// Returns the loop hint metadata node with the given name (for example,
|
|
|
|
// "llvm.loop.unroll.count"). If no such metadata node exists, then nullptr is
|
|
|
|
// returned.
|
2015-02-03 04:41:11 +08:00
|
|
|
static MDNode *GetUnrollMetadataForLoop(const Loop *L, StringRef Name) {
|
|
|
|
if (MDNode *LoopID = L->getLoopID())
|
|
|
|
return GetUnrollMetadata(LoopID, Name);
|
|
|
|
return nullptr;
|
2014-06-17 07:53:02 +08:00
|
|
|
}
|
|
|
|
|
2014-07-24 01:31:37 +08:00
|
|
|
// Returns true if the loop has an unroll(full) pragma.
|
|
|
|
static bool HasUnrollFullPragma(const Loop *L) {
|
2015-02-01 10:27:45 +08:00
|
|
|
return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.full");
|
2014-06-17 07:53:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if the loop has an unroll(disable) pragma.
|
|
|
|
static bool HasUnrollDisablePragma(const Loop *L) {
|
2015-02-01 10:27:45 +08:00
|
|
|
return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.disable");
|
2014-06-17 07:53:02 +08:00
|
|
|
}
|
|
|
|
|
2015-03-09 14:14:18 +08:00
|
|
|
// Returns true if the loop has an runtime unroll(disable) pragma.
|
|
|
|
static bool HasRuntimeUnrollDisablePragma(const Loop *L) {
|
|
|
|
return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.runtime.disable");
|
|
|
|
}
|
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
// If loop has an unroll_count pragma return the (necessarily
|
|
|
|
// positive) value from the pragma. Otherwise return 0.
|
|
|
|
static unsigned UnrollCountPragmaValue(const Loop *L) {
|
2015-02-03 04:41:11 +08:00
|
|
|
MDNode *MD = GetUnrollMetadataForLoop(L, "llvm.loop.unroll.count");
|
2014-07-24 01:31:37 +08:00
|
|
|
if (MD) {
|
|
|
|
assert(MD->getNumOperands() == 2 &&
|
|
|
|
"Unroll count hint metadata should have two operands.");
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
unsigned Count =
|
|
|
|
mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue();
|
2014-06-17 07:53:02 +08:00
|
|
|
assert(Count >= 1 && "Unroll count must be positive.");
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-19 05:04:33 +08:00
|
|
|
// Remove existing unroll metadata and add unroll disable metadata to
|
|
|
|
// indicate the loop has already been unrolled. This prevents a loop
|
|
|
|
// from being unrolled more than is directed by a pragma if the loop
|
|
|
|
// unrolling pass is run more than once (which it generally is).
|
|
|
|
static void SetLoopAlreadyUnrolled(Loop *L) {
|
|
|
|
MDNode *LoopID = L->getLoopID();
|
|
|
|
if (!LoopID) return;
|
|
|
|
|
|
|
|
// First remove any existing loop unrolling metadata.
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
SmallVector<Metadata *, 4> MDs;
|
2014-07-19 05:04:33 +08:00
|
|
|
// Reserve first location for self reference to the LoopID metadata node.
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
MDs.push_back(nullptr);
|
2014-07-19 05:04:33 +08:00
|
|
|
for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) {
|
|
|
|
bool IsUnrollMetadata = false;
|
|
|
|
MDNode *MD = dyn_cast<MDNode>(LoopID->getOperand(i));
|
|
|
|
if (MD) {
|
|
|
|
const MDString *S = dyn_cast<MDString>(MD->getOperand(0));
|
|
|
|
IsUnrollMetadata = S && S->getString().startswith("llvm.loop.unroll.");
|
|
|
|
}
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
if (!IsUnrollMetadata)
|
|
|
|
MDs.push_back(LoopID->getOperand(i));
|
2014-07-19 05:04:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add unroll(disable) metadata to disable future unrolling.
|
|
|
|
LLVMContext &Context = L->getHeader()->getContext();
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
SmallVector<Metadata *, 1> DisableOperands;
|
2014-07-24 01:31:37 +08:00
|
|
|
DisableOperands.push_back(MDString::get(Context, "llvm.loop.unroll.disable"));
|
2014-07-19 05:29:41 +08:00
|
|
|
MDNode *DisableNode = MDNode::get(Context, DisableOperands);
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
MDs.push_back(DisableNode);
|
2014-07-19 05:04:33 +08:00
|
|
|
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
MDNode *NewLoopID = MDNode::get(Context, MDs);
|
2014-07-19 05:04:33 +08:00
|
|
|
// Set operand 0 to refer to the loop id itself.
|
|
|
|
NewLoopID->replaceOperandWith(0, NewLoopID);
|
|
|
|
L->setLoopID(NewLoopID);
|
|
|
|
}
|
|
|
|
|
2015-05-13 01:20:03 +08:00
|
|
|
bool LoopUnroll::canUnrollCompletely(
|
|
|
|
Loop *L, unsigned Threshold, unsigned AbsoluteThreshold,
|
|
|
|
uint64_t UnrolledSize, unsigned NumberOfOptimizedInstructions,
|
|
|
|
unsigned PercentOfOptimizedForCompleteUnroll) {
|
|
|
|
|
|
|
|
if (Threshold == NoThreshold) {
|
|
|
|
DEBUG(dbgs() << " Can fully unroll, because no threshold is set.\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UnrolledSize <= Threshold) {
|
|
|
|
DEBUG(dbgs() << " Can fully unroll, because unrolled size: "
|
|
|
|
<< UnrolledSize << "<" << Threshold << "\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(UnrolledSize && "UnrolledSize can't be 0 at this point.");
|
|
|
|
unsigned PercentOfOptimizedInstructions =
|
|
|
|
(uint64_t)NumberOfOptimizedInstructions * 100ull / UnrolledSize;
|
|
|
|
|
|
|
|
if (UnrolledSize <= AbsoluteThreshold &&
|
|
|
|
PercentOfOptimizedInstructions >= PercentOfOptimizedForCompleteUnroll) {
|
|
|
|
DEBUG(dbgs() << " Can fully unroll, because unrolling will help removing "
|
|
|
|
<< PercentOfOptimizedInstructions
|
|
|
|
<< "% instructions (threshold: "
|
|
|
|
<< PercentOfOptimizedForCompleteUnroll << "%)\n");
|
|
|
|
DEBUG(dbgs() << " Unrolled size (" << UnrolledSize
|
|
|
|
<< ") is less than the threshold (" << AbsoluteThreshold
|
|
|
|
<< ").\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG(dbgs() << " Too large to fully unroll:\n");
|
|
|
|
DEBUG(dbgs() << " Unrolled size: " << UnrolledSize << "\n");
|
|
|
|
DEBUG(dbgs() << " Estimated number of optimized instructions: "
|
|
|
|
<< NumberOfOptimizedInstructions << "\n");
|
|
|
|
DEBUG(dbgs() << " Absolute threshold: " << AbsoluteThreshold << "\n");
|
|
|
|
DEBUG(dbgs() << " Minimum percent of removed instructions: "
|
|
|
|
<< PercentOfOptimizedForCompleteUnroll << "\n");
|
|
|
|
DEBUG(dbgs() << " Threshold for small loops: " << Threshold << "\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
unsigned LoopUnroll::selectUnrollCount(
|
2014-07-24 01:31:37 +08:00
|
|
|
const Loop *L, unsigned TripCount, bool PragmaFullUnroll,
|
2014-06-17 07:53:02 +08:00
|
|
|
unsigned PragmaCount, const TargetTransformInfo::UnrollingPreferences &UP,
|
|
|
|
bool &SetExplicitly) {
|
|
|
|
SetExplicitly = true;
|
|
|
|
|
|
|
|
// User-specified count (either as a command-line option or
|
|
|
|
// constructor parameter) has highest precedence.
|
|
|
|
unsigned Count = UserCount ? CurrentCount : 0;
|
|
|
|
|
|
|
|
// If there is no user-specified count, unroll pragmas have the next
|
|
|
|
// highest precendence.
|
|
|
|
if (Count == 0) {
|
|
|
|
if (PragmaCount) {
|
|
|
|
Count = PragmaCount;
|
2014-07-24 01:31:37 +08:00
|
|
|
} else if (PragmaFullUnroll) {
|
2014-06-17 07:53:02 +08:00
|
|
|
Count = TripCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Count == 0)
|
|
|
|
Count = UP.Count;
|
|
|
|
|
|
|
|
if (Count == 0) {
|
|
|
|
SetExplicitly = false;
|
|
|
|
if (TripCount == 0)
|
|
|
|
// Runtime trip count.
|
|
|
|
Count = UnrollRuntimeCount;
|
|
|
|
else
|
|
|
|
// Conservative heuristic: if we know the trip count, see if we can
|
|
|
|
// completely unroll (subject to the threshold, checked below); otherwise
|
|
|
|
// try to find greatest modulo of the trip count which is still under
|
|
|
|
// threshold value.
|
|
|
|
Count = TripCount;
|
|
|
|
}
|
|
|
|
if (TripCount && Count > TripCount)
|
|
|
|
return TripCount;
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2007-03-07 09:38:05 +08:00
|
|
|
bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
|
2014-02-06 08:07:05 +08:00
|
|
|
if (skipOptnoneFunction(L))
|
|
|
|
return false;
|
|
|
|
|
2015-02-01 20:01:35 +08:00
|
|
|
Function &F = *L->getHeader()->getParent();
|
|
|
|
|
2015-01-17 22:16:18 +08:00
|
|
|
LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
2011-08-12 07:36:16 +08:00
|
|
|
ScalarEvolution *SE = &getAnalysis<ScalarEvolution>();
|
[PM] Change the core design of the TTI analysis to use a polymorphic
type erased interface and a single analysis pass rather than an
extremely complex analysis group.
The end result is that the TTI analysis can contain a type erased
implementation that supports the polymorphic TTI interface. We can build
one from a target-specific implementation or from a dummy one in the IR.
I've also factored all of the code into "mix-in"-able base classes,
including CRTP base classes to facilitate calling back up to the most
specialized form when delegating horizontally across the surface. These
aren't as clean as I would like and I'm planning to work on cleaning
some of this up, but I wanted to start by putting into the right form.
There are a number of reasons for this change, and this particular
design. The first and foremost reason is that an analysis group is
complete overkill, and the chaining delegation strategy was so opaque,
confusing, and high overhead that TTI was suffering greatly for it.
Several of the TTI functions had failed to be implemented in all places
because of the chaining-based delegation making there be no checking of
this. A few other functions were implemented with incorrect delegation.
The message to me was very clear working on this -- the delegation and
analysis group structure was too confusing to be useful here.
The other reason of course is that this is *much* more natural fit for
the new pass manager. This will lay the ground work for a type-erased
per-function info object that can look up the correct subtarget and even
cache it.
Yet another benefit is that this will significantly simplify the
interaction of the pass managers and the TargetMachine. See the future
work below.
The downside of this change is that it is very, very verbose. I'm going
to work to improve that, but it is somewhat an implementation necessity
in C++ to do type erasure. =/ I discussed this design really extensively
with Eric and Hal prior to going down this path, and afterward showed
them the result. No one was really thrilled with it, but there doesn't
seem to be a substantially better alternative. Using a base class and
virtual method dispatch would make the code much shorter, but as
discussed in the update to the programmer's manual and elsewhere,
a polymorphic interface feels like the more principled approach even if
this is perhaps the least compelling example of it. ;]
Ultimately, there is still a lot more to be done here, but this was the
huge chunk that I couldn't really split things out of because this was
the interface change to TTI. I've tried to minimize all the other parts
of this. The follow up work should include at least:
1) Improving the TargetMachine interface by having it directly return
a TTI object. Because we have a non-pass object with value semantics
and an internal type erasure mechanism, we can narrow the interface
of the TargetMachine to *just* do what we need: build and return
a TTI object that we can then insert into the pass pipeline.
2) Make the TTI object be fully specialized for a particular function.
This will include splitting off a minimal form of it which is
sufficient for the inliner and the old pass manager.
3) Add a new pass manager analysis which produces TTI objects from the
target machine for each function. This may actually be done as part
of #2 in order to use the new analysis to implement #2.
4) Work on narrowing the API between TTI and the targets so that it is
easier to understand and less verbose to type erase.
5) Work on narrowing the API between TTI and its clients so that it is
easier to understand and less verbose to forward.
6) Try to improve the CRTP-based delegation. I feel like this code is
just a bit messy and exacerbating the complexity of implementing
the TTI in each target.
Many thanks to Eric and Hal for their help here. I ended up blocked on
this somewhat more abruptly than I expected, and so I appreciate getting
it sorted out very quickly.
Differential Revision: http://reviews.llvm.org/D7293
llvm-svn: 227669
2015-01-31 11:43:40 +08:00
|
|
|
const TargetTransformInfo &TTI =
|
2015-02-01 20:01:35 +08:00
|
|
|
getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
|
|
|
|
auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
|
2007-05-12 04:53:41 +08:00
|
|
|
|
2007-05-08 23:19:19 +08:00
|
|
|
BasicBlock *Header = L->getHeader();
|
2010-01-05 09:27:44 +08:00
|
|
|
DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()
|
2009-07-25 08:23:56 +08:00
|
|
|
<< "] Loop %" << Header->getName() << "\n");
|
2011-07-23 08:29:16 +08:00
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
if (HasUnrollDisablePragma(L)) {
|
|
|
|
return false;
|
2014-04-02 02:50:30 +08:00
|
|
|
}
|
2014-07-24 01:31:37 +08:00
|
|
|
bool PragmaFullUnroll = HasUnrollFullPragma(L);
|
2014-06-17 07:53:02 +08:00
|
|
|
unsigned PragmaCount = UnrollCountPragmaValue(L);
|
2014-07-24 01:31:37 +08:00
|
|
|
bool HasPragma = PragmaFullUnroll || PragmaCount > 0;
|
2014-06-17 07:53:02 +08:00
|
|
|
|
|
|
|
TargetTransformInfo::UnrollingPreferences UP;
|
2015-02-01 22:37:03 +08:00
|
|
|
getUnrollingPreferences(L, TTI, UP);
|
2004-04-18 13:20:17 +08:00
|
|
|
|
2011-08-12 07:36:16 +08:00
|
|
|
// Find trip count and trip multiple if count is not available
|
|
|
|
unsigned TripCount = 0;
|
2011-07-23 08:33:05 +08:00
|
|
|
unsigned TripMultiple = 1;
|
2014-10-11 08:12:11 +08:00
|
|
|
// If there are multiple exiting blocks but one of them is the latch, use the
|
|
|
|
// latch for the trip count estimation. Otherwise insist on a single exiting
|
|
|
|
// block for the trip count estimation.
|
|
|
|
BasicBlock *ExitingBlock = L->getLoopLatch();
|
|
|
|
if (!ExitingBlock || !L->isLoopExiting(ExitingBlock))
|
|
|
|
ExitingBlock = L->getExitingBlock();
|
|
|
|
if (ExitingBlock) {
|
|
|
|
TripCount = SE->getSmallConstantTripCount(L, ExitingBlock);
|
|
|
|
TripMultiple = SE->getSmallConstantTripMultiple(L, ExitingBlock);
|
2011-08-12 07:36:16 +08:00
|
|
|
}
|
2013-09-12 03:25:43 +08:00
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
// Select an initial unroll count. This may be reduced later based
|
|
|
|
// on size thresholds.
|
|
|
|
bool CountSetExplicitly;
|
2014-07-24 01:31:37 +08:00
|
|
|
unsigned Count = selectUnrollCount(L, TripCount, PragmaFullUnroll,
|
|
|
|
PragmaCount, UP, CountSetExplicitly);
|
2014-06-17 07:53:02 +08:00
|
|
|
|
|
|
|
unsigned NumInlineCandidates;
|
|
|
|
bool notDuplicatable;
|
|
|
|
unsigned LoopSize =
|
2015-01-04 20:03:27 +08:00
|
|
|
ApproximateLoopSize(L, NumInlineCandidates, notDuplicatable, TTI, &AC);
|
2014-06-17 07:53:02 +08:00
|
|
|
DEBUG(dbgs() << " Loop Size = " << LoopSize << "\n");
|
2015-01-10 08:30:55 +08:00
|
|
|
|
|
|
|
// When computing the unrolled size, note that the conditional branch on the
|
|
|
|
// backedge and the comparison feeding it are not replicated like the rest of
|
|
|
|
// the loop body (which is why 2 is subtracted).
|
|
|
|
uint64_t UnrolledSize = (uint64_t)(LoopSize-2) * Count + 2;
|
2014-06-17 07:53:02 +08:00
|
|
|
if (notDuplicatable) {
|
|
|
|
DEBUG(dbgs() << " Not unrolling loop which contains non-duplicatable"
|
|
|
|
<< " instructions.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (NumInlineCandidates != 0) {
|
|
|
|
DEBUG(dbgs() << " Not unrolling loop with inlinable calls.\n");
|
|
|
|
return false;
|
|
|
|
}
|
2011-12-09 14:19:40 +08:00
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
unsigned Threshold, PartialThreshold;
|
2015-05-13 01:20:03 +08:00
|
|
|
unsigned AbsoluteThreshold, PercentOfOptimizedForCompleteUnroll;
|
2015-02-05 10:34:00 +08:00
|
|
|
selectThresholds(L, HasPragma, UP, Threshold, PartialThreshold,
|
2015-05-13 01:20:03 +08:00
|
|
|
AbsoluteThreshold, PercentOfOptimizedForCompleteUnroll);
|
2014-06-17 07:53:02 +08:00
|
|
|
|
|
|
|
// Given Count, TripCount and thresholds determine the type of
|
|
|
|
// unrolling which is to be performed.
|
|
|
|
enum { Full = 0, Partial = 1, Runtime = 2 };
|
|
|
|
int Unrolling;
|
|
|
|
if (TripCount && Count == TripCount) {
|
2015-05-13 01:20:03 +08:00
|
|
|
Unrolling = Partial;
|
|
|
|
// If the loop is really small, we don't need to run an expensive analysis.
|
|
|
|
if (canUnrollCompletely(
|
|
|
|
L, Threshold, AbsoluteThreshold,
|
|
|
|
UnrolledSize, 0, 100)) {
|
2014-06-17 07:53:02 +08:00
|
|
|
Unrolling = Full;
|
2015-05-13 01:20:03 +08:00
|
|
|
} else {
|
|
|
|
// The loop isn't that small, but we still can fully unroll it if that
|
|
|
|
// helps to remove a significant number of instructions.
|
|
|
|
// To check that, run additional analysis on the loop.
|
|
|
|
UnrollAnalyzer UA(L, TripCount, *SE, TTI, AbsoluteThreshold);
|
|
|
|
if (UA.analyzeLoop() &&
|
|
|
|
canUnrollCompletely(L, Threshold, AbsoluteThreshold,
|
|
|
|
UA.UnrolledLoopSize,
|
|
|
|
UA.NumberOfOptimizedInstructions,
|
|
|
|
PercentOfOptimizedForCompleteUnroll)) {
|
|
|
|
Unrolling = Full;
|
|
|
|
}
|
2014-06-17 07:53:02 +08:00
|
|
|
}
|
|
|
|
} else if (TripCount && Count < TripCount) {
|
|
|
|
Unrolling = Partial;
|
|
|
|
} else {
|
|
|
|
Unrolling = Runtime;
|
2007-05-12 04:53:41 +08:00
|
|
|
}
|
2007-03-03 07:31:34 +08:00
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
// Reduce count based on the type of unrolling and the threshold values.
|
|
|
|
unsigned OriginalCount = Count;
|
|
|
|
bool AllowRuntime = UserRuntime ? CurrentRuntime : UP.Runtime;
|
2015-03-09 14:14:18 +08:00
|
|
|
if (HasRuntimeUnrollDisablePragma(L)) {
|
|
|
|
AllowRuntime = false;
|
|
|
|
}
|
2014-06-17 07:53:02 +08:00
|
|
|
if (Unrolling == Partial) {
|
|
|
|
bool AllowPartial = UserAllowPartial ? CurrentAllowPartial : UP.Partial;
|
|
|
|
if (!AllowPartial && !CountSetExplicitly) {
|
|
|
|
DEBUG(dbgs() << " will not try to unroll partially because "
|
|
|
|
<< "-unroll-allow-partial not given\n");
|
2012-12-21 00:04:27 +08:00
|
|
|
return false;
|
|
|
|
}
|
2014-06-17 07:53:02 +08:00
|
|
|
if (PartialThreshold != NoThreshold && UnrolledSize > PartialThreshold) {
|
|
|
|
// Reduce unroll count to be modulo of TripCount for partial unrolling.
|
2015-01-10 08:30:55 +08:00
|
|
|
Count = (std::max(PartialThreshold, 3u)-2) / (LoopSize-2);
|
2014-06-17 07:53:02 +08:00
|
|
|
while (Count != 0 && TripCount % Count != 0)
|
|
|
|
Count--;
|
|
|
|
}
|
|
|
|
} else if (Unrolling == Runtime) {
|
|
|
|
if (!AllowRuntime && !CountSetExplicitly) {
|
|
|
|
DEBUG(dbgs() << " will not try to unroll loop with runtime trip count "
|
|
|
|
<< "-unroll-runtime not given\n");
|
2010-09-10 04:02:23 +08:00
|
|
|
return false;
|
2010-02-06 07:21:31 +08:00
|
|
|
}
|
2014-06-17 07:53:02 +08:00
|
|
|
// Reduce unroll count to be the largest power-of-two factor of
|
|
|
|
// the original count which satisfies the threshold limit.
|
|
|
|
while (Count != 0 && UnrolledSize > PartialThreshold) {
|
|
|
|
Count >>= 1;
|
2015-01-10 08:30:55 +08:00
|
|
|
UnrolledSize = (LoopSize-2) * Count + 2;
|
2014-06-17 07:53:02 +08:00
|
|
|
}
|
|
|
|
if (Count > UP.MaxCount)
|
|
|
|
Count = UP.MaxCount;
|
|
|
|
DEBUG(dbgs() << " partially unrolling with count: " << Count << "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HasPragma) {
|
2014-07-24 04:05:44 +08:00
|
|
|
if (PragmaCount != 0)
|
|
|
|
// If loop has an unroll count pragma mark loop as unrolled to prevent
|
|
|
|
// unrolling beyond that requested by the pragma.
|
|
|
|
SetLoopAlreadyUnrolled(L);
|
2014-07-19 05:04:33 +08:00
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
// Emit optimization remarks if we are unable to unroll the loop
|
|
|
|
// as directed by a pragma.
|
|
|
|
DebugLoc LoopLoc = L->getStartLoc();
|
|
|
|
Function *F = Header->getParent();
|
|
|
|
LLVMContext &Ctx = F->getContext();
|
2014-07-24 01:31:37 +08:00
|
|
|
if (PragmaFullUnroll && PragmaCount == 0) {
|
2014-06-17 07:53:02 +08:00
|
|
|
if (TripCount && Count != TripCount) {
|
|
|
|
emitOptimizationRemarkMissed(
|
|
|
|
Ctx, DEBUG_TYPE, *F, LoopLoc,
|
2014-07-24 01:31:37 +08:00
|
|
|
"Unable to fully unroll loop as directed by unroll(full) pragma "
|
2014-06-17 07:53:02 +08:00
|
|
|
"because unrolled size is too large.");
|
|
|
|
} else if (!TripCount) {
|
|
|
|
emitOptimizationRemarkMissed(
|
|
|
|
Ctx, DEBUG_TYPE, *F, LoopLoc,
|
2014-07-24 01:31:37 +08:00
|
|
|
"Unable to fully unroll loop as directed by unroll(full) pragma "
|
2014-06-17 07:53:02 +08:00
|
|
|
"because loop has a runtime trip count.");
|
2009-08-13 11:00:57 +08:00
|
|
|
}
|
2014-06-17 07:53:02 +08:00
|
|
|
} else if (PragmaCount > 0 && Count != OriginalCount) {
|
|
|
|
emitOptimizationRemarkMissed(
|
|
|
|
Ctx, DEBUG_TYPE, *F, LoopLoc,
|
|
|
|
"Unable to unroll loop the number of times directed by "
|
|
|
|
"unroll_count pragma because unrolled size is too large.");
|
2007-05-12 04:53:41 +08:00
|
|
|
}
|
2004-04-18 13:20:17 +08:00
|
|
|
}
|
2005-04-22 07:48:37 +08:00
|
|
|
|
2014-06-17 07:53:02 +08:00
|
|
|
if (Unrolling != Full && Count < 2) {
|
|
|
|
// Partial unrolling by 1 is a nop. For full unrolling, a factor
|
|
|
|
// of 1 makes sense because loop control can be eliminated.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-05-14 08:24:14 +08:00
|
|
|
// Unroll the loop.
|
2015-04-14 11:20:38 +08:00
|
|
|
if (!UnrollLoop(L, Count, TripCount, AllowRuntime, UP.AllowExpensiveTripCount,
|
|
|
|
TripMultiple, LI, this, &LPM, &AC))
|
2008-05-14 08:24:14 +08:00
|
|
|
return false;
|
2004-04-18 13:20:17 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|