forked from OSchip/llvm-project
Make tail merging the default, except on powerPC. There was no prior art
for a target-dependent default with a command-line override; this way should be generally usable. llvm-svn: 37285
This commit is contained in:
parent
83d7dd419a
commit
82810c8a13
|
@ -79,7 +79,7 @@ namespace llvm {
|
|||
/// optimizations to delete branches to branches, eliminate branches to
|
||||
/// successor blocks (creating fall throughs), and eliminating branches over
|
||||
/// branches.
|
||||
FunctionPass *createBranchFoldingPass();
|
||||
FunctionPass *createBranchFoldingPass(bool DefaultEnableTailMerge);
|
||||
|
||||
/// IfConverter Pass - This pass performs machine code if conversion.
|
||||
FunctionPass *createIfConverterPass();
|
||||
|
|
|
@ -544,6 +544,28 @@ public:
|
|||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>);
|
||||
|
||||
//--------------------------------------------------
|
||||
// parser<boolOrDefault>
|
||||
enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
|
||||
template<>
|
||||
class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
|
||||
public:
|
||||
// parse - Return true on error.
|
||||
bool parse(Option &O, const char *ArgName, const std::string &Arg,
|
||||
boolOrDefault &Val);
|
||||
|
||||
enum ValueExpected getValueExpectedFlagDefault() const {
|
||||
return ValueOptional;
|
||||
}
|
||||
|
||||
// getValueName - Do not print =<value> at all.
|
||||
virtual const char *getValueName() const { return 0; }
|
||||
|
||||
// An out-of-line virtual method to provide a 'home' for this class.
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
|
||||
|
||||
//--------------------------------------------------
|
||||
// parser<int>
|
||||
|
|
|
@ -185,6 +185,10 @@ public:
|
|||
AssemblyFile, ObjectFile, DynamicLibrary
|
||||
};
|
||||
|
||||
/// DoTailMergeDefault - Whether it is generally a good idea to do this
|
||||
/// on this target. User flag overrides.
|
||||
virtual const bool DoTailMergeDefault() const { return true; }
|
||||
|
||||
/// addPassesToEmitFile - Add passes to the specified pass manager to get the
|
||||
/// specified file emitted. Typically this will involve several steps of code
|
||||
/// generation. If Fast is set to true, the code generator should emit code
|
||||
|
@ -315,6 +319,10 @@ public:
|
|||
MachineCodeEmitter &MCE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// DoTailMergeDefault - Whether it is generally a good idea to do this
|
||||
/// on this target. User flag overrides.
|
||||
virtual const bool DoTailMergeDefault() const { return true; }
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
|
|
@ -35,12 +35,19 @@ using namespace llvm;
|
|||
STATISTIC(NumDeadBlocks, "Number of dead blocks removed");
|
||||
STATISTIC(NumBranchOpts, "Number of branches optimized");
|
||||
STATISTIC(NumTailMerge , "Number of block tails merged");
|
||||
static cl::opt<bool> EnableTailMerge("enable-tail-merge", cl::Hidden);
|
||||
|
||||
static cl::opt<cl::boolOrDefault> FlagEnableTailMerge("enable-tail-merge",
|
||||
cl::init(cl::BOU_UNSET), cl::Hidden);
|
||||
namespace {
|
||||
struct BranchFolder : public MachineFunctionPass {
|
||||
static char ID;
|
||||
BranchFolder() : MachineFunctionPass((intptr_t)&ID) {}
|
||||
BranchFolder(bool defaultEnableTailMerge) :
|
||||
MachineFunctionPass((intptr_t)&ID) {
|
||||
switch (FlagEnableTailMerge) {
|
||||
case cl::BOU_UNSET: EnableTailMerge = defaultEnableTailMerge; break;
|
||||
case cl::BOU_TRUE: EnableTailMerge = true; break;
|
||||
case cl::BOU_FALSE: EnableTailMerge = false; break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
virtual const char *getPassName() const { return "Control Flow Optimizer"; }
|
||||
|
@ -49,6 +56,7 @@ namespace {
|
|||
bool MadeChange;
|
||||
private:
|
||||
// Tail Merging.
|
||||
bool EnableTailMerge;
|
||||
bool TailMergeBlocks(MachineFunction &MF);
|
||||
bool TryMergeBlocks(MachineBasicBlock* SuccBB,
|
||||
MachineBasicBlock* PredBB);
|
||||
|
@ -79,7 +87,8 @@ static bool CorrectExtraCFGEdges(MachineBasicBlock &MBB,
|
|||
bool isCond,
|
||||
MachineFunction::iterator FallThru);
|
||||
|
||||
FunctionPass *llvm::createBranchFoldingPass() { return new BranchFolder(); }
|
||||
FunctionPass *llvm::createBranchFoldingPass(bool DefaultEnableTailMerge) {
|
||||
return new BranchFolder(DefaultEnableTailMerge); }
|
||||
|
||||
/// RemoveDeadBlock - Remove the specified dead machine basic block from the
|
||||
/// function, updating the CFG.
|
||||
|
|
|
@ -78,7 +78,7 @@ LLVMTargetMachine::addPassesToEmitFile(FunctionPassManager &PM,
|
|||
|
||||
// Branch folding must be run after regalloc and prolog/epilog insertion.
|
||||
if (!Fast)
|
||||
PM.add(createBranchFoldingPass());
|
||||
PM.add(createBranchFoldingPass(DoTailMergeDefault()));
|
||||
|
||||
// Fold redundant debug labels.
|
||||
PM.add(createDebugLabelFoldingPass());
|
||||
|
@ -181,7 +181,7 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
|
|||
|
||||
// Branch folding must be run after regalloc and prolog/epilog insertion.
|
||||
if (!Fast)
|
||||
PM.add(createBranchFoldingPass());
|
||||
PM.add(createBranchFoldingPass(DoTailMergeDefault()));
|
||||
|
||||
if (addPreEmitPass(PM, Fast) && PrintMachineCode)
|
||||
PM.add(createMachineFunctionPrinterPass(cerr));
|
||||
|
|
|
@ -36,6 +36,7 @@ using namespace cl;
|
|||
// Template instantiations and anchors.
|
||||
//
|
||||
TEMPLATE_INSTANTIATION(class basic_parser<bool>);
|
||||
TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
|
||||
TEMPLATE_INSTANTIATION(class basic_parser<int>);
|
||||
TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
|
||||
TEMPLATE_INSTANTIATION(class basic_parser<double>);
|
||||
|
@ -50,6 +51,7 @@ TEMPLATE_INSTANTIATION(class opt<bool>);
|
|||
void Option::anchor() {}
|
||||
void basic_parser_impl::anchor() {}
|
||||
void parser<bool>::anchor() {}
|
||||
void parser<boolOrDefault>::anchor() {}
|
||||
void parser<int>::anchor() {}
|
||||
void parser<unsigned>::anchor() {}
|
||||
void parser<double>::anchor() {}
|
||||
|
@ -767,6 +769,22 @@ bool parser<bool>::parse(Option &O, const char *ArgName,
|
|||
return false;
|
||||
}
|
||||
|
||||
// parser<boolOrDefault> implementation
|
||||
//
|
||||
bool parser<boolOrDefault>::parse(Option &O, const char *ArgName,
|
||||
const std::string &Arg, boolOrDefault &Value) {
|
||||
if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
|
||||
Arg == "1") {
|
||||
Value = BOU_TRUE;
|
||||
} else if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
|
||||
Value = BOU_FALSE;
|
||||
} else {
|
||||
return O.error(": '" + Arg +
|
||||
"' is invalid value for boolean argument! Try 0 or 1");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// parser<int> implementation
|
||||
//
|
||||
bool parser<int>::parse(Option &O, const char *ArgName,
|
||||
|
|
|
@ -96,6 +96,10 @@ PPCTargetMachine::PPCTargetMachine(const Module &M, const std::string &FS,
|
|||
setRelocationModel(Reloc::Static);
|
||||
}
|
||||
|
||||
/// Override this for PowerPC. Tail merging happily breaks up instruction issue
|
||||
/// groups, which typically degrades performance.
|
||||
const bool PPCTargetMachine::DoTailMergeDefault() const { return false; }
|
||||
|
||||
PPC32TargetMachine::PPC32TargetMachine(const Module &M, const std::string &FS)
|
||||
: PPCTargetMachine(M, FS, false) {
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
MachineCodeEmitter &MCE);
|
||||
virtual bool addSimpleCodeEmitter(FunctionPassManager &PM, bool Fast,
|
||||
MachineCodeEmitter &MCE);
|
||||
virtual const bool DoTailMergeDefault() const;
|
||||
};
|
||||
|
||||
/// PPC32TargetMachine - PowerPC 32-bit target machine.
|
||||
|
|
Loading…
Reference in New Issue