diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index bd1366485260..e7a97cf6bd3c 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -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(); diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h index c31d79f4e69b..08aca8160ac0 100644 --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -544,6 +544,28 @@ public: EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +//-------------------------------------------------- +// parser +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template<> +class parser : public basic_parser { +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 = 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); //-------------------------------------------------- // parser diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index e5fceba522be..faf3c35c4925 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -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 diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp index d8ec3406921b..7cc4c2db79f2 100644 --- a/llvm/lib/CodeGen/BranchFolding.cpp +++ b/llvm/lib/CodeGen/BranchFolding.cpp @@ -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 EnableTailMerge("enable-tail-merge", cl::Hidden); - +static cl::opt 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. diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp index 34c45f31352b..41f7e199a0a9 100644 --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -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)); diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp index 2b0798aa7705..1f5008a3faa7 100644 --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -36,6 +36,7 @@ using namespace cl; // Template instantiations and anchors. // TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); @@ -50,6 +51,7 @@ TEMPLATE_INSTANTIATION(class opt); void Option::anchor() {} void basic_parser_impl::anchor() {} void parser::anchor() {} +void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} @@ -767,6 +769,22 @@ bool parser::parse(Option &O, const char *ArgName, return false; } +// parser implementation +// +bool parser::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 implementation // bool parser::parse(Option &O, const char *ArgName, diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index df3e3d2257e7..6d5e05077379 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -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) { } diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/llvm/lib/Target/PowerPC/PPCTargetMachine.h index a249952aa109..fdf9d35e5716 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.h +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.h @@ -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.