mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-28 03:25:23 +00:00
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:
@@ -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
|
||||||
|
@@ -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,
|
||||||
|
cl::boolOrDefault Override,
|
||||||
AnalysisID StandardID) {
|
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 = Pass::createPass(FinalID);
|
Pass *P;
|
||||||
|
if (FinalPtr.isInstance())
|
||||||
|
P = FinalPtr.getInstance();
|
||||||
|
else {
|
||||||
|
P = Pass::createPass(FinalPtr.getID());
|
||||||
if (!P)
|
if (!P)
|
||||||
llvm_unreachable("Pass ID not registered");
|
llvm_unreachable("Pass ID not registered");
|
||||||
addPass(P);
|
}
|
||||||
|
AnalysisID FinalID = P->getPassID();
|
||||||
|
addPass(P); // Ends the lifetime of 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;
|
||||||
|
if ((*I).second.isInstance())
|
||||||
|
NP = (*I).second.getInstance();
|
||||||
|
else {
|
||||||
|
NP = Pass::createPass((*I).second.getID());
|
||||||
assert(NP && "Pass ID not registered");
|
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
|
||||||
|
Reference in New Issue
Block a user