From 6079f00035e029f12e4be0281aa2cbfbb4817141 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Thu, 21 Nov 2013 06:33:32 +0000 Subject: [PATCH] Teach ISel not to optimize 'optnone' functions. Based on work by Andrea Di Biagio. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195317 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCCodeGenInfo.h | 3 ++ include/llvm/Target/TargetMachine.h | 6 ++- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 41 ++++++++++++++++++- lib/Target/TargetMachine.cpp | 5 +++ test/CodeGen/Generic/isel-optnone.ll | 31 ++++++++++++++ 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/Generic/isel-optnone.ll diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index d1765e1240a..84ce934d822 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -42,6 +42,9 @@ namespace llvm { CodeModel::Model getCodeModel() const { return CMModel; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } }; } // namespace llvm diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 91e4715eea3..11b0f5fb77f 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -75,7 +75,8 @@ protected: // Can only create subclasses. std::string TargetFS; /// CodeGenInfo - Low level target information such as relocation model. - const MCCodeGenInfo *CodeGenInfo; + /// Non-const to allow resetting optimization level per-function. + MCCodeGenInfo *CodeGenInfo; /// AsmInfo - Contains target specific asm information. /// @@ -213,6 +214,9 @@ public: /// Default, or Aggressive. CodeGenOpt::Level getOptLevel() const; + /// \brief Overrides the optimization level. + void setOptLevel(CodeGenOpt::Level Level) const; + void setFastISel(bool Enable) { Options.EnableFastISel = Enable; } bool shouldPrintMachineCode() const { return Options.PrintMachineCode; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 91cb125dc89..faca3ee823c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -222,6 +222,39 @@ defaultListDAGScheduler("default", "Best scheduler for the target", createDefaultScheduler); namespace llvm { + //===--------------------------------------------------------------------===// + /// \brief This struct is used by SelectionDAGISel to temporarily override + /// the optimization level on a per-function basis. + class OptLevelChanger { + SelectionDAGISel &IS; + CodeGenOpt::Level SavedOptLevel; + + public: + OptLevelChanger(SelectionDAGISel &ISel, + CodeGenOpt::Level NewOptLevel) : IS(ISel) { + SavedOptLevel = IS.OptLevel; + if (NewOptLevel == SavedOptLevel) + return; + IS.OptLevel = NewOptLevel; + IS.TM.setOptLevel(NewOptLevel); + DEBUG(dbgs() << "\nChanging optimization level for Function " + << IS.MF->getFunction()->getName() << "\n"); + DEBUG(dbgs() << "\tBefore: -O" << SavedOptLevel + << " ; After: -O" << NewOptLevel << "\n"); + } + + ~OptLevelChanger() { + if (IS.OptLevel == SavedOptLevel) + return; + DEBUG(dbgs() << "\nRestoring optimization level for Function " + << IS.MF->getFunction()->getName() << "\n"); + DEBUG(dbgs() << "\tBefore: -O" << IS.OptLevel + << " ; After: -O" << SavedOptLevel << "\n"); + IS.OptLevel = SavedOptLevel; + IS.TM.setOptLevel(SavedOptLevel); + } + }; + //===--------------------------------------------------------------------===// /// createDefaultScheduler - This creates an instruction scheduler appropriate /// for the target. @@ -370,6 +403,12 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { ST.resetSubtargetFeatures(MF); TM.resetTargetOptions(MF); + // Reset OptLevel to None for optnone functions. + CodeGenOpt::Level NewOptLevel = OptLevel; + if (Fn.hasFnAttribute(Attribute::OptimizeNone)) + NewOptLevel = CodeGenOpt::None; + OptLevelChanger OLC(*this, NewOptLevel); + DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); SplitCriticalSideEffectEdges(const_cast(Fn), this); @@ -948,7 +987,7 @@ static void collectFailStats(const Instruction *I) { void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { // Initialize the Fast-ISel state, if needed. FastISel *FastIS = 0; - if (TM.Options.EnableFastISel) + if (TM.Options.EnableFastISel || Fn.hasFnAttribute(Attribute::OptimizeNone)) FastIS = getTargetLowering()->createFastISel(*FuncInfo, LibInfo); // Iterate over all basic blocks in the function. diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index df4a03c9e8b..cb42e8311b8 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -164,6 +164,11 @@ CodeGenOpt::Level TargetMachine::getOptLevel() const { return CodeGenInfo->getOptLevel(); } +void TargetMachine::setOptLevel(CodeGenOpt::Level Level) const { + if (CodeGenInfo) + CodeGenInfo->setOptLevel(Level); +} + bool TargetMachine::getAsmVerbosityDefault() { return AsmVerbosityDefault; } diff --git a/test/CodeGen/Generic/isel-optnone.ll b/test/CodeGen/Generic/isel-optnone.ll new file mode 100644 index 00000000000..405a1bc50a8 --- /dev/null +++ b/test/CodeGen/Generic/isel-optnone.ll @@ -0,0 +1,31 @@ +; RUN: llc -debug < %s -o /dev/null 2>&1 | FileCheck %s + +; Verify that the backend correctly overrides the optimization level +; of optnone functions during instruction selection. + +define float @foo(float %x) #0 { +entry: + %add = fadd fast float %x, %x + %add1 = fadd fast float %add, %x + ret float %add1 +} + +; CHECK-NOT: Changing optimization level for Function foo +; CHECK-NOT: Restoring optimization level for Function foo + +; Function Attrs: noinline optnone +define float @fooWithOptnone(float %x) #1 { +entry: + %add = fadd fast float %x, %x + %add1 = fadd fast float %add, %x + ret float %add1 +} + +; CHECK: Changing optimization level for Function fooWithOptnone +; CHECK-NEXT: Before: -O2 ; After: -O0 + +; CHECK: Restoring optimization level for Function fooWithOptnone +; CHECK-NEXT: Before: -O0 ; After: -O2 + +attributes #0 = { "unsafe-fp-math"="true" } +attributes #1 = { noinline optnone "unsafe-fp-math"="true" } -- 2.34.1