Generalize the PassConfig API and remove addFinalizeRegAlloc().

The target hooks are getting out of hand. What does it mean to run
before or after regalloc anyway? Allowing either Pass* or AnalysisID
pass identification should make it much easier for targets to use the
substitutePass and insertPass APIs, and create less need for badly
named target hooks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179140 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick
2013-04-10 01:06:56 +00:00
parent a9a5c537ad
commit 5ed028385c
2 changed files with 95 additions and 50 deletions

View File

@@ -35,6 +35,46 @@ namespace llvm {
class PassConfigImpl; class PassConfigImpl;
/// Discriminated union of Pass ID types.
///
/// The PassConfig API prefers dealing with IDs because they are safer and more
/// efficient. IDs decouple configuration from instantiation. This way, when a
/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to
/// refer to a Pass pointer after adding it to a pass manager, which deletes
/// redundant pass instances.
///
/// However, it is convient to directly instantiate target passes with
/// non-default ctors. These often don't have a registered PassInfo. Rather than
/// force all target passes to implement the pass registry boilerplate, allow
/// the PassConfig API to handle either type.
///
/// AnalysisID is sadly char*, so PointerIntPair won't work.
class IdentifyingPassPtr {
void *P;
bool IsInstance;
public:
IdentifyingPassPtr(): P(0), IsInstance(false) {}
IdentifyingPassPtr(AnalysisID IDPtr): P((void*)IDPtr), IsInstance(false) {}
IdentifyingPassPtr(Pass *InstancePtr)
: P((void*)InstancePtr), IsInstance(true) {}
bool isValid() const { return P; }
bool isInstance() const { return IsInstance; }
AnalysisID getID() const {
assert(!IsInstance && "Not a Pass ID");
return (AnalysisID)P;
}
Pass *getInstance() const {
assert(IsInstance && "Not a Pass Instance");
return (Pass *)P;
}
};
template <> struct isPodLike<IdentifyingPassPtr> {
static const bool value = true;
};
/// Target-Independent Code Generator Pass Configuration Options. /// Target-Independent Code Generator Pass Configuration Options.
/// ///
/// This is an ImmutablePass solely for the purpose of exposing CodeGen options /// This is an ImmutablePass solely for the purpose of exposing CodeGen options
@@ -117,20 +157,22 @@ public:
/// Allow the target to override a specific pass without overriding the pass /// Allow the target to override a specific pass without overriding the pass
/// pipeline. When passes are added to the standard pipeline at the /// pipeline. When passes are added to the standard pipeline at the
/// point where StandardID is expected, add TargetID in its place. /// point where StandardID is expected, add TargetID in its place.
void substitutePass(AnalysisID StandardID, AnalysisID TargetID); void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID);
/// Insert InsertedPassID pass after TargetPassID pass. /// Insert InsertedPassID pass after TargetPassID pass.
void insertPass(AnalysisID TargetPassID, AnalysisID InsertedPassID); void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID);
/// Allow the target to enable a specific standard pass by default. /// Allow the target to enable a specific standard pass by default.
void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); }
/// Allow the target to disable a specific standard pass by default. /// Allow the target to disable a specific standard pass by default.
void disablePass(AnalysisID PassID) { substitutePass(PassID, 0); } void disablePass(AnalysisID PassID) {
substitutePass(PassID, IdentifyingPassPtr());
}
/// Return the pass substituted for StandardID by the target. /// Return the pass substituted for StandardID by the target.
/// If no substitution exists, return StandardID. /// If no substitution exists, return StandardID.
AnalysisID getPassSubstitution(AnalysisID StandardID) const; IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const;
/// Return true if the optimized regalloc pipeline is enabled. /// Return true if the optimized regalloc pipeline is enabled.
bool getOptimizeRegAlloc() const; bool getOptimizeRegAlloc() const;
@@ -222,17 +264,6 @@ protected:
return false; return false;
} }
/// addFinalizeRegAlloc - This method may be implemented by targets that want
/// to run passes within the regalloc pipeline, immediately after the register
/// allocation pass itself. These passes run as soon as virtual regisiters
/// have been rewritten to physical registers but before and other postRA
/// optimization happens. Targets that have marked instructions for bundling
/// must have finalized those bundles by the time these passes have run,
/// because subsequent passes are not guaranteed to be bundle-aware.
virtual bool addFinalizeRegAlloc() {
return false;
}
/// addPostRegAlloc - This method may be implemented by targets that want to /// addPostRegAlloc - This method may be implemented by targets that want to
/// run passes after register allocation pass pipeline but before /// run passes after register allocation pass pipeline but before
/// prolog-epilog insertion. This should return true if -print-machineinstrs /// prolog-epilog insertion. This should return true if -print-machineinstrs

View File

@@ -93,9 +93,10 @@ static cl::opt<bool> EarlyLiveIntervals("early-live-intervals", cl::Hidden,
/// simple binary flags that either suppress the pass or do nothing. /// simple binary flags that either suppress the pass or do nothing.
/// i.e. -disable-mypass=false has no effect. /// i.e. -disable-mypass=false has no effect.
/// These should be converted to boolOrDefault in order to use applyOverride. /// These should be converted to boolOrDefault in order to use applyOverride.
static AnalysisID applyDisable(AnalysisID PassID, bool Override) { static IdentifyingPassPtr applyDisable(IdentifyingPassPtr PassID,
bool Override) {
if (Override) if (Override)
return 0; return IdentifyingPassPtr();
return PassID; return PassID;
} }
@@ -103,19 +104,20 @@ static AnalysisID applyDisable(AnalysisID PassID, bool Override) {
/// flags with ternary conditions. TargetID is passed through by default. The /// flags with ternary conditions. TargetID is passed through by default. The
/// pass is suppressed when the option is false. When the option is true, the /// pass is suppressed when the option is false. When the option is true, the
/// StandardID is selected if the target provides no default. /// StandardID is selected if the target provides no default.
static AnalysisID applyOverride(AnalysisID TargetID, cl::boolOrDefault Override, static IdentifyingPassPtr applyOverride(IdentifyingPassPtr TargetID,
AnalysisID StandardID) { cl::boolOrDefault Override,
AnalysisID StandardID) {
switch (Override) { switch (Override) {
case cl::BOU_UNSET: case cl::BOU_UNSET:
return TargetID; return TargetID;
case cl::BOU_TRUE: case cl::BOU_TRUE:
if (TargetID) if (TargetID.isValid())
return TargetID; return TargetID;
if (StandardID == 0) if (StandardID == 0)
report_fatal_error("Target cannot enable pass"); report_fatal_error("Target cannot enable pass");
return StandardID; return StandardID;
case cl::BOU_FALSE: case cl::BOU_FALSE:
return 0; return IdentifyingPassPtr();
} }
llvm_unreachable("Invalid command line option state"); llvm_unreachable("Invalid command line option state");
} }
@@ -132,7 +134,8 @@ static AnalysisID applyOverride(AnalysisID TargetID, cl::boolOrDefault Override,
/// StandardID may be a pseudo ID. In that case TargetID is the name of the real /// StandardID may be a pseudo ID. In that case TargetID is the name of the real
/// pass to run. This allows multiple options to control a single pass depending /// pass to run. This allows multiple options to control a single pass depending
/// on where in the pipeline that pass is added. /// on where in the pipeline that pass is added.
static AnalysisID overridePass(AnalysisID StandardID, AnalysisID TargetID) { static IdentifyingPassPtr overridePass(AnalysisID StandardID,
IdentifyingPassPtr TargetID) {
if (StandardID == &PostRASchedulerID) if (StandardID == &PostRASchedulerID)
return applyDisable(TargetID, DisablePostRA); return applyDisable(TargetID, DisablePostRA);
@@ -200,11 +203,11 @@ public:
// user interface. For example, a target may disable a standard pass by // user interface. For example, a target may disable a standard pass by
// default by substituting a pass ID of zero, and the user may still enable // default by substituting a pass ID of zero, and the user may still enable
// that standard pass with an explicit command line option. // that standard pass with an explicit command line option.
DenseMap<AnalysisID,AnalysisID> TargetPasses; DenseMap<AnalysisID,IdentifyingPassPtr> TargetPasses;
/// Store the pairs of <AnalysisID, AnalysisID> of which the second pass /// Store the pairs of <AnalysisID, AnalysisID> of which the second pass
/// is inserted after each instance of the first one. /// is inserted after each instance of the first one.
SmallVector<std::pair<AnalysisID, AnalysisID>, 4> InsertedPasses; SmallVector<std::pair<AnalysisID, IdentifyingPassPtr>, 4> InsertedPasses;
}; };
} // namespace llvm } // namespace llvm
@@ -239,9 +242,13 @@ TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
/// Insert InsertedPassID pass after TargetPassID. /// Insert InsertedPassID pass after TargetPassID.
void TargetPassConfig::insertPass(AnalysisID TargetPassID, void TargetPassConfig::insertPass(AnalysisID TargetPassID,
AnalysisID InsertedPassID) { IdentifyingPassPtr InsertedPassID) {
assert(TargetPassID != InsertedPassID && "Insert a pass after itself!"); assert((!InsertedPassID.isInstance() &&
std::pair<AnalysisID, AnalysisID> P(TargetPassID, InsertedPassID); TargetPassID != InsertedPassID.getID()) ||
(InsertedPassID.isInstance() &&
TargetPassID != InsertedPassID.getInstance()->getPassID()) &&
"Insert a pass after itself!");
std::pair<AnalysisID, IdentifyingPassPtr> P(TargetPassID, InsertedPassID);
Impl->InsertedPasses.push_back(P); Impl->InsertedPasses.push_back(P);
} }
@@ -265,12 +272,12 @@ void TargetPassConfig::setOpt(bool &Opt, bool Val) {
} }
void TargetPassConfig::substitutePass(AnalysisID StandardID, void TargetPassConfig::substitutePass(AnalysisID StandardID,
AnalysisID TargetID) { IdentifyingPassPtr TargetID) {
Impl->TargetPasses[StandardID] = TargetID; Impl->TargetPasses[StandardID] = TargetID;
} }
AnalysisID TargetPassConfig::getPassSubstitution(AnalysisID ID) const { IdentifyingPassPtr TargetPassConfig::getPassSubstitution(AnalysisID ID) const {
DenseMap<AnalysisID, AnalysisID>::const_iterator DenseMap<AnalysisID, IdentifyingPassPtr>::const_iterator
I = Impl->TargetPasses.find(ID); I = Impl->TargetPasses.find(ID);
if (I == Impl->TargetPasses.end()) if (I == Impl->TargetPasses.end())
return ID; return ID;
@@ -303,24 +310,39 @@ void TargetPassConfig::addPass(Pass *P) {
/// Add a CodeGen pass at this point in the pipeline after checking for target /// Add a CodeGen pass at this point in the pipeline after checking for target
/// and command line overrides. /// and command line overrides.
///
/// addPass cannot return a pointer to the pass instance because is internal the
/// PassManager and the instance we create here may already be freed.
AnalysisID TargetPassConfig::addPass(AnalysisID PassID) { AnalysisID TargetPassConfig::addPass(AnalysisID PassID) {
AnalysisID TargetID = getPassSubstitution(PassID); IdentifyingPassPtr TargetID = getPassSubstitution(PassID);
AnalysisID FinalID = overridePass(PassID, TargetID); IdentifyingPassPtr FinalPtr = overridePass(PassID, TargetID);
if (FinalID == 0) if (!FinalPtr.isValid())
return FinalID; return 0;
Pass *P;
if (FinalPtr.isInstance())
P = FinalPtr.getInstance();
else {
P = Pass::createPass(FinalPtr.getID());
if (!P)
llvm_unreachable("Pass ID not registered");
}
AnalysisID FinalID = P->getPassID();
addPass(P); // Ends the lifetime of P.
Pass *P = Pass::createPass(FinalID);
if (!P)
llvm_unreachable("Pass ID not registered");
addPass(P);
// Add the passes after the pass P if there is any. // Add the passes after the pass P if there is any.
for (SmallVector<std::pair<AnalysisID, AnalysisID>, 4>::iterator for (SmallVector<std::pair<AnalysisID, IdentifyingPassPtr>, 4>::iterator
I = Impl->InsertedPasses.begin(), E = Impl->InsertedPasses.end(); I = Impl->InsertedPasses.begin(), E = Impl->InsertedPasses.end();
I != E; ++I) { I != E; ++I) {
if ((*I).first == PassID) { if ((*I).first == PassID) {
assert((*I).second && "Illegal Pass ID!"); assert((*I).second.isValid() && "Illegal Pass ID!");
Pass *NP = Pass::createPass((*I).second); Pass *NP;
assert(NP && "Pass ID not registered"); if ((*I).second.isInstance())
NP = (*I).second.getInstance();
else {
NP = Pass::createPass((*I).second.getID());
assert(NP && "Pass ID not registered");
}
addPass(NP); addPass(NP);
} }
} }
@@ -687,14 +709,6 @@ void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
addPass(&VirtRegRewriterID); addPass(&VirtRegRewriterID);
printAndVerify("After Virtual Register Rewriter"); printAndVerify("After Virtual Register Rewriter");
// FinalizeRegAlloc is convenient until MachineInstrBundles is more mature,
// but eventually, all users of it should probably be moved to addPostRA and
// it can go away. Currently, it's the intended place for targets to run
// FinalizeMachineBundles, because passes other than MachineScheduling an
// RegAlloc itself may not be aware of bundles.
if (addFinalizeRegAlloc())
printAndVerify("After RegAlloc finalization");
// Perform stack slot coloring and post-ra machine LICM. // Perform stack slot coloring and post-ra machine LICM.
// //
// FIXME: Re-enable coloring with register when it's capable of adding // FIXME: Re-enable coloring with register when it's capable of adding