/// 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();
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>
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
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
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"; }
bool MadeChange;
private:
// Tail Merging.
+ bool EnableTailMerge;
bool TailMergeBlocks(MachineFunction &MF);
bool TryMergeBlocks(MachineBasicBlock* SuccBB,
MachineBasicBlock* PredBB);
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.
// 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());
// 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));
// 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>);
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() {}
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,
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) {
}
MachineCodeEmitter &MCE);
virtual bool addSimpleCodeEmitter(FunctionPassManager &PM, bool Fast,
MachineCodeEmitter &MCE);
+ virtual const bool DoTailMergeDefault() const;
};
/// PPC32TargetMachine - PowerPC 32-bit target machine.