Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -501,6 +501,8 @@ return codegenoptions::LimitedDebugInfo; } +enum class FramePointerKeepKind { None, NonLeaf, All }; + static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { switch (Triple.getArch()){ default: @@ -574,32 +576,32 @@ return true; } -static bool shouldUseFramePointer(const ArgList &Args, - const llvm::Triple &Triple) { - if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, - options::OPT_fomit_frame_pointer)) - return A->getOption().matches(options::OPT_fno_omit_frame_pointer) || - mustUseNonLeafFramePointerForTarget(Triple); +static FramePointerKeepKind getFramePointerKind(const ArgList &Args, + const llvm::Triple &Triple) { + bool MayKeepAll, KeepNone = false; + if (mustUseNonLeafFramePointerForTarget(Triple)) { + MayKeepAll = true; + } else if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, + options::OPT_fomit_frame_pointer)) { + MayKeepAll = A->getOption().matches(options::OPT_fno_omit_frame_pointer); + KeepNone = !MayKeepAll; + } else { + MayKeepAll = Args.hasArg(options::OPT_pg) || + useFramePointerForTargetByDefault(Args, Triple); + } + bool OmitLeaf = + Args.hasFlag(options::OPT_momit_leaf_frame_pointer, + options::OPT_mno_omit_leaf_frame_pointer, Triple.isPS4CPU()); - if (Args.hasArg(options::OPT_pg)) - return true; + if (MayKeepAll) { + if (OmitLeaf) + return FramePointerKeepKind::NonLeaf; + return FramePointerKeepKind::All; + } else if (!KeepNone && OmitLeaf) { + return FramePointerKeepKind::NonLeaf; + } - return useFramePointerForTargetByDefault(Args, Triple); -} - -static bool shouldUseLeafFramePointer(const ArgList &Args, - const llvm::Triple &Triple) { - if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer, - options::OPT_momit_leaf_frame_pointer)) - return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer); - - if (Args.hasArg(options::OPT_pg)) - return true; - - if (Triple.isPS4CPU()) - return false; - - return useFramePointerForTargetByDefault(Args, Triple); + return FramePointerKeepKind::None; } /// Add a CC1 option to specify the debug compilation directory. @@ -3948,8 +3950,12 @@ if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-fdefault-calling-conv=stdcall"); - if (shouldUseFramePointer(Args, RawTriple)) + FramePointerKeepKind FPKeepKind = getFramePointerKind(Args, RawTriple); + if (FPKeepKind != FramePointerKeepKind::None) { CmdArgs.push_back("-mdisable-fp-elim"); + if (FPKeepKind == FramePointerKeepKind::NonLeaf) + CmdArgs.push_back("-momit-leaf-frame-pointer"); + } if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) CmdArgs.push_back("-mno-zero-initialized-in-bss"); @@ -4123,9 +4129,6 @@ CmdArgs.push_back(A->getValue()); } - if (!shouldUseLeafFramePointer(Args, RawTriple)) - CmdArgs.push_back("-momit-leaf-frame-pointer"); - // Explicitly error on some things we know we don't support and can't just // ignore. if (!Args.hasArg(options::OPT_fallow_unsupported)) { @@ -5480,7 +5483,7 @@ } if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (!shouldUseFramePointer(Args, Triple)) + if (getFramePointerKind(Args, RawTriple) == FramePointerKeepKind::None) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); Index: test/Driver/cl-options.c =================================================================== --- test/Driver/cl-options.c +++ test/Driver/cl-options.c @@ -161,28 +161,28 @@ // RUN: %clang_cl /Os --target=i686-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Os %s // RUN: %clang_cl /Os --target=x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Os %s // Os-NOT: -mdisable-fp-elim -// Os: -momit-leaf-frame-pointer +// Os-NOT: -momit-leaf-frame-pointer // Os: -Os // RUN: %clang_cl /Ot --target=i686-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ot %s // RUN: %clang_cl /Ot --target=x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ot %s // Ot-NOT: -mdisable-fp-elim -// Ot: -momit-leaf-frame-pointer +// Ot-NOT: -momit-leaf-frame-pointer // Ot: -O2 // RUN: %clang_cl /Ox --target=i686-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s // RUN: %clang_cl /Ox --target=x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s // Ox-NOT: -mdisable-fp-elim -// Ox: -momit-leaf-frame-pointer +// Ox-NOT: -momit-leaf-frame-pointer // Ox: -O2 // RUN: %clang_cl --target=i686-pc-win32 /O2sy- -### -- %s 2>&1 | FileCheck -check-prefix=PR24003 %s // PR24003: -mdisable-fp-elim -// PR24003: -momit-leaf-frame-pointer +// PR24003-NOT: -momit-leaf-frame-pointer // PR24003: -Os // RUN: %clang_cl --target=i686-pc-win32 -Werror /Oy- /O2 -### -- %s 2>&1 | FileCheck -check-prefix=Oy_2 %s -// Oy_2: -momit-leaf-frame-pointer +// Oy_2-NOT: -momit-leaf-frame-pointer // Oy_2: -O2 // RUN: %clang_cl --target=aarch64-pc-windows-msvc -Werror /Oy- /O2 -### -- %s 2>&1 | FileCheck -check-prefix=Oy_aarch64 %s Index: test/Driver/frame-pointer-elim.c =================================================================== --- test/Driver/frame-pointer-elim.c +++ test/Driver/frame-pointer-elim.c @@ -1,48 +1,50 @@ +// KEEP-ALL: "-mdisable-fp-elim" +// KEEP-ALL-NOT: "-momit-leaf-frame-pointer" + +// KEEP-NON-LEAF: "-mdisable-fp-elim" +// KEEP-NON-LEAF: "-momit-leaf-frame-pointer" + +// KEEP-NONE-NOT: "-mdisable-fp-elim" +// KEEP-NONE-NOT: "-momit-leaf-frame-pointer" + // For these next two tests when optimized we should omit the leaf frame // pointer, for unoptimized we should have a leaf frame pointer. // RUN: %clang -### -target i386-pc-linux-gnu -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=LINUX-OPT %s -// LINUX-OPT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-NONE %s // RUN: %clang -### -target i386-pc-linux-gnu -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=LINUX %s -// LINUX-NOT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-ALL %s + +// RUN: %clang -### -target i386-pc-linux-gnu -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-ALL %s // CloudABI follows the same rules as Linux. // RUN: %clang -### -target x86_64-unknown-cloudabi -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=CLOUDABI-OPT %s -// CLOUDABI-OPT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-NONE %s // RUN: %clang -### -target x86_64-unknown-cloudabi -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=CLOUDABI %s -// CLOUDABI-NOT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-ALL %s // NetBSD follows the same rules as Linux. // RUN: %clang -### -target x86_64-unknown-netbsd -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=NETBSD-OPT %s -// NETBSD-OPT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-NONE %s // RUN: %clang -### -target x86_64-unknown-netbsd -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=NETBSD %s -// NETBSD-NOT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-ALL %s // Darwin disables omitting the leaf frame pointer even under optimization // unless the command lines are given. // RUN: %clang -### -target i386-apple-darwin -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=DARWIN %s -// DARWIN: "-mdisable-fp-elim" +// RUN: FileCheck --check-prefix=KEEP-ALL %s // RUN: %clang -### -target i386-apple-darwin -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=DARWIN-OPT %s -// DARWIN-OPT-NOT: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-ALL %s // RUN: %clang -### -target i386-darwin -S -fomit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=OMIT_ALL %s -// OMIT_ALL-NOT: "-mdisable-fp-elim" +// RUN: FileCheck --check-prefix=KEEP-NONE %s // RUN: %clang -### -target i386-darwin -S -momit-leaf-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=OMIT_LEAF %s -// OMIT_LEAF: "-momit-leaf-frame-pointer" +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s // RUN: %clang -### -target armv7s-apple-ios -fomit-frame-pointer %s 2>&1 | \ // RUN: FileCheck --check-prefix=WARN-OMIT-7S %s @@ -63,11 +65,10 @@ // WARN-OMIT-LEAF-7S: "-momit-leaf-frame-pointer" // On the PS4, we default to omitting the frame pointer on leaf functions -// (OMIT_LEAF check line is above) // RUN: %clang -### -target x86_64-scei-ps4 -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=OMIT_LEAF %s +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s // RUN: %clang -### -target x86_64-scei-ps4 -S -O2 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=OMIT_LEAF %s +// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s void f0() {} void f1() { f0(); } Index: test/Driver/xcore-opts.c =================================================================== --- test/Driver/xcore-opts.c +++ test/Driver/xcore-opts.c @@ -4,8 +4,8 @@ // RUN: %clang -target xcore %s -g0 -### -o %t.o 2>&1 | FileCheck -check-prefix CHECK-G0 %s // CHECK: "-nostdsysteminc" -// CHECK: "-momit-leaf-frame-pointer" // CHECK-NOT: "-mdisable-fp-elim" +// CHECK-NOT: "-momit-leaf-frame-pointer" // CHECK: "-fno-signed-char" // CHECK: "-fno-use-cxa-atexit" // CHECK-NOT: "-fcxx-exceptions"