Index: include/llvm/CodeGen/CommandFlags.h =================================================================== --- include/llvm/CodeGen/CommandFlags.h +++ include/llvm/CodeGen/CommandFlags.h @@ -230,6 +230,7 @@ TargetOptions Options; Options.LessPreciseFPMADOption = EnableFPMAD; Options.NoFramePointerElim = DisableFPElim; + Options.NoFramePointerElimOverride = DisableFPElim.getNumOccurrences() > 0; Options.AllowFPOpFusion = FuseFPOps; Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Index: include/llvm/Target/TargetFrameLowering.h =================================================================== --- include/llvm/Target/TargetFrameLowering.h +++ include/llvm/Target/TargetFrameLowering.h @@ -15,6 +15,7 @@ #define LLVM_TARGET_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetOptions.h" #include #include @@ -173,6 +174,12 @@ return false; } + /// Return true if the target needs to disable frame pointer elimination even + /// when TargetOptions::noFramePointerElim returns false. + virtual bool noFramePointerElim(const MachineFunction &MF) const { + return false; + } + /// hasFP - Return true if the specified function should have a dedicated /// frame pointer register. For most targets this is true only if the function /// has variable sized allocas or if frame pointer elimination is disabled. Index: include/llvm/Target/TargetOptions.h =================================================================== --- include/llvm/Target/TargetOptions.h +++ include/llvm/Target/TargetOptions.h @@ -60,6 +60,7 @@ public: TargetOptions() : PrintMachineCode(false), NoFramePointerElim(false), + NoFramePointerElimOverride(false), LessPreciseFPMADOption(false), UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), HonorSignDependentRoundingFPMathOption(false), @@ -74,6 +75,10 @@ AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single), ThreadModel(ThreadModel::POSIX) {} + /// Determine if frame pointer elimination should be disabled based on + /// NoFramePointerElim and F's function attribute "no-frame-pointer-elim". + bool noFramePointerElim(const Function &F) const; + /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging /// output from the code generator. @@ -84,6 +89,10 @@ /// elimination optimization, this option should disable it. unsigned NoFramePointerElim : 1; + /// This flag is true when NoFramePointerElim should override function + /// attribute "no-frame-pointer-elim". + unsigned NoFramePointerElimOverride : 1; + /// DisableFramePointerElim - This returns true if frame pointer elimination /// optimization should be disabled for the given machine function. bool DisableFramePointerElim(const MachineFunction &MF) const; Index: lib/CodeGen/TargetOptionsImpl.cpp =================================================================== --- lib/CodeGen/TargetOptionsImpl.cpp +++ lib/CodeGen/TargetOptionsImpl.cpp @@ -14,21 +14,32 @@ #include "llvm/IR/Function.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; +bool TargetOptions::noFramePointerElim(const Function &F) const { + if (!NoFramePointerElimOverride && F.hasFnAttribute("no-frame-pointer-elim")) + return F.getFnAttribute("no-frame-pointer-elim").getValueAsString() == + "true"; + + return NoFramePointerElim; +} + /// DisableFramePointerElim - This returns true if frame pointer elimination /// optimization should be disabled for the given machine function. bool TargetOptions::DisableFramePointerElim(const MachineFunction &MF) const { - // Check to see if we should eliminate non-leaf frame pointers and then - // check to see if we should eliminate all frame pointers. - if (MF.getFunction()->hasFnAttribute("no-frame-pointer-elim-non-leaf") && - !NoFramePointerElim) { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - return MFI->hasCalls(); - } + // Check to see if we should eliminate all frame pointers. + if (noFramePointerElim(*MF.getFunction()) || + MF.getSubtarget().getFrameLowering()->noFramePointerElim(MF)) + return true; - return NoFramePointerElim; + // Check to see if we should eliminate non-leaf frame pointers. + if (MF.getFunction()->hasFnAttribute("no-frame-pointer-elim-non-leaf")) + return MF.getFrameInfo()->hasCalls(); + + return false; } /// LessPreciseFPMAD - This flag return true when -enable-fp-mad option Index: lib/Target/ARM/ARMFastISel.cpp =================================================================== --- lib/Target/ARM/ARMFastISel.cpp +++ lib/Target/ARM/ARMFastISel.cpp @@ -3065,23 +3065,9 @@ namespace llvm { FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) { - const TargetMachine &TM = funcInfo.MF->getTarget(); - const ARMSubtarget &STI = - static_cast(funcInfo.MF->getSubtarget()); - // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl. - bool UseFastISel = false; - UseFastISel |= STI.isTargetMachO() && !STI.isThumb1Only(); - UseFastISel |= STI.isTargetLinux() && !STI.isThumb(); - UseFastISel |= STI.isTargetNaCl() && !STI.isThumb(); - - if (UseFastISel) { - // iOS always has a FP for backtracking, force other targets - // to keep their FP when doing FastISel. The emitted code is - // currently superior, and in cases like test-suite's lencod - // FastISel isn't quite correct when FP is eliminated. - TM.Options.NoFramePointerElim = true; + if (funcInfo.MF->getSubtarget().useFastISel()) return new ARMFastISel(funcInfo, libInfo); - } + return nullptr; } } Index: lib/Target/ARM/ARMFrameLowering.h =================================================================== --- lib/Target/ARM/ARMFrameLowering.h +++ lib/Target/ARM/ARMFrameLowering.h @@ -43,6 +43,8 @@ const std::vector &CSI, const TargetRegisterInfo *TRI) const override; + bool noFramePointerElim(const MachineFunction &MF) const override; + bool hasFP(const MachineFunction &MF) const override; bool hasReservedCallFrame(const MachineFunction &MF) const override; bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override; Index: lib/Target/ARM/ARMFrameLowering.cpp =================================================================== --- lib/Target/ARM/ARMFrameLowering.cpp +++ lib/Target/ARM/ARMFrameLowering.cpp @@ -43,6 +43,13 @@ : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 4), STI(sti) {} +bool ARMFrameLowering::noFramePointerElim(const MachineFunction &MF) const { + // iOS always has a FP for backtracking, force other targets to keep their FP + // when doing FastISel. The emitted code is currently superior, and in cases + // like test-suite's lencod FastISel isn't quite correct when FP is eliminated. + return MF.getSubtarget().useFastISel(); +} + /// hasFP - Return true if the specified function should have a dedicated frame /// pointer register. This is true if the function has variable sized allocas /// or if frame pointer elimination is disabled. Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -450,6 +450,8 @@ /// symbol. bool GVIsIndirectSymbol(const GlobalValue *GV, Reloc::Model RelocM) const; + /// True if fast-isel is used. + bool useFastISel() const; }; } // End llvm namespace Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -353,3 +353,10 @@ return UseMovt && (isTargetWindows() || !MF.getFunction()->hasFnAttribute(Attribute::MinSize)); } + +bool ARMSubtarget::useFastISel() const { + // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl. + return TM.Options.EnableFastISel && + ((isTargetMachO() && !isThumb1Only()) || + (isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb())); +} Index: lib/Target/TargetMachine.cpp =================================================================== --- lib/Target/TargetMachine.cpp +++ lib/Target/TargetMachine.cpp @@ -66,7 +66,6 @@ Options.X = (F.getFnAttribute(Y).getValueAsString() == "true"); \ } while (0) - RESET_OPTION(NoFramePointerElim, "no-frame-pointer-elim"); RESET_OPTION(LessPreciseFPMADOption, "less-precise-fpmad"); RESET_OPTION(UnsafeFPMath, "unsafe-fp-math"); RESET_OPTION(NoInfsFPMath, "no-infs-fp-math"); Index: test/CodeGen/ARM/disable-fp-elim.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/disable-fp-elim.ll @@ -0,0 +1,25 @@ +; RUN: llc < %s -mtriple armv7-none-linux-gnueabi -O1 | FileCheck %s --check-prefix=DISABLE-FP-ELIM +; RUN: llc < %s -mtriple armv7-none-linux-gnueabi -disable-fp-elim -O1 | FileCheck %s --check-prefix=DISABLE-FP-ELIM +; RUN: llc < %s -mtriple armv7-none-linux-gnueabi -disable-fp-elim=false -O1 | FileCheck %s --check-prefix=ENABLE-FP-ELIM +; RUN: llc < %s -mtriple armv7-none-linux-gnueabi -disable-fp-elim=false -O0 | FileCheck %s --check-prefix=DISABLE-FP-ELIM + +; Check that command line option "-disable-fp-elim" overrides function attribute +; "no-frame-pointer-elim". Also, check frame pointer elimination is disabled +; when fast-isel is used. + +; ENABLE-FP-ELIM-NOT: .setfp +; DISABLE-FP-ELIM: .setfp r11, sp + +define i32 @foo1(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) #0 { +entry: + %call = tail call i32 @foo2(i32 %a) + %add = add i32 %c, %b + %add1 = add i32 %add, %d + %add2 = add i32 %add1, %e + %add3 = add i32 %add2, %call + ret i32 %add3 +} + +declare i32 @foo2(i32) + +attributes #0 = { nounwind "no-frame-pointer-elim"="true" } Index: test/CodeGen/X86/2014-08-29-CompactUnwind.ll =================================================================== --- test/CodeGen/X86/2014-08-29-CompactUnwind.ll +++ test/CodeGen/X86/2014-08-29-CompactUnwind.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -disable-fp-elim -mtriple x86_64-apple-darwin11 -mcpu corei7 -filetype=obj -o - | llvm-objdump -d -unwind-info -s - | FileCheck %s +; RUN: llc < %s -mtriple x86_64-apple-darwin11 -mcpu corei7 -filetype=obj -o - | llvm-objdump -d -unwind-info -s - | FileCheck %s ; Regression test for http://llvm.org/bugs/show_bug.cgi?id=20800. ; ModuleID = 'asan_report.ii'