mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-22 03:58:16 +00:00
Teach ISel not to optimize 'optnone' functions (revised).
Improvements over r195317: - Set/restore EnableFastISel flag instead of just running FastISel within SelectAllBasicBlocks; the flag is checked in various places, and FastISel won't run properly if those places don't do the right thing. - Test looks for normal ISel versus FastISel behavior, and not something more subtle that doesn't work everywhere. Based on work by Andrea Di Biagio. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195491 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
09f1b252af
commit
16c7e0b48c
@ -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
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -222,6 +222,44 @@ defaultListDAGScheduler("default", "Best scheduler for the target",
|
||||
createDefaultScheduler);
|
||||
|
||||
namespace llvm {
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// \brief This class is used by SelectionDAGISel to temporarily override
|
||||
/// the optimization level on a per-function basis.
|
||||
class OptLevelChanger {
|
||||
SelectionDAGISel &IS;
|
||||
CodeGenOpt::Level SavedOptLevel;
|
||||
bool SavedFastISel;
|
||||
|
||||
public:
|
||||
OptLevelChanger(SelectionDAGISel &ISel,
|
||||
CodeGenOpt::Level NewOptLevel) : IS(ISel) {
|
||||
SavedOptLevel = IS.OptLevel;
|
||||
if (NewOptLevel == SavedOptLevel)
|
||||
return;
|
||||
IS.OptLevel = NewOptLevel;
|
||||
IS.TM.setOptLevel(NewOptLevel);
|
||||
SavedFastISel = IS.TM.Options.EnableFastISel;
|
||||
if (NewOptLevel == CodeGenOpt::None)
|
||||
IS.TM.setFastISel(true);
|
||||
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);
|
||||
IS.TM.setFastISel(SavedFastISel);
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// createDefaultScheduler - This creates an instruction scheduler appropriate
|
||||
/// for the target.
|
||||
@ -370,6 +408,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<Function&>(Fn), this);
|
||||
|
@ -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;
|
||||
}
|
||||
|
42
test/CodeGen/X86/isel-optnone.ll
Normal file
42
test/CodeGen/X86/isel-optnone.ll
Normal file
@ -0,0 +1,42 @@
|
||||
; RUN: llc -O2 -march=x86 < %s | FileCheck %s
|
||||
|
||||
define i32* @fooOptnone(i32* %p, i32* %q, i32** %z) #0 {
|
||||
entry:
|
||||
%r = load i32* %p
|
||||
%s = load i32* %q
|
||||
%y = load i32** %z
|
||||
|
||||
%t0 = add i32 %r, %s
|
||||
%t1 = add i32 %t0, 1
|
||||
%t2 = getelementptr i32* %y, i32 1
|
||||
%t3 = getelementptr i32* %t2, i32 %t1
|
||||
|
||||
ret i32* %t3
|
||||
|
||||
; 'optnone' should use fast-isel which will not produce 'lea'.
|
||||
; CHECK-LABEL: fooOptnone:
|
||||
; CHECK-NOT: lea
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
define i32* @fooNormal(i32* %p, i32* %q, i32** %z) #1 {
|
||||
entry:
|
||||
%r = load i32* %p
|
||||
%s = load i32* %q
|
||||
%y = load i32** %z
|
||||
|
||||
%t0 = add i32 %r, %s
|
||||
%t1 = add i32 %t0, 1
|
||||
%t2 = getelementptr i32* %y, i32 1
|
||||
%t3 = getelementptr i32* %t2, i32 %t1
|
||||
|
||||
ret i32* %t3
|
||||
|
||||
; Normal ISel will produce 'lea'.
|
||||
; CHECK-LABEL: fooNormal:
|
||||
; CHECK: lea
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
attributes #0 = { nounwind optnone noinline }
|
||||
attributes #1 = { nounwind }
|
Loading…
Reference in New Issue
Block a user