Driver/IRgen: Add support for -momit-leaf-frame-pointer.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107367 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 65284fb..f8ad189 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -149,6 +149,8 @@
   HelpText<"Limit float precision to the given value">;
 def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">,
   HelpText<"Do not put zero initialized data in the BSS">;
+def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">,
+  HelpText<"Omit frame pointer setup for leaf functions.">;
 def msoft_float : Flag<"-msoft-float">,
   HelpText<"Use software floating point">;
 def mrelax_all : Flag<"-mrelax-all">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 1e36695..b12f5be 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -462,6 +462,8 @@
 def marm : Flag<"-marm">, Alias<mno_thumb>;
 
 def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>;
+def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group<f_Group>;
+def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>;
 def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>;
 def mred_zone : Flag<"-mred-zone">, Group<m_Group>;
 def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>;
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 2d21f1d..c25cfb3 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -53,6 +53,8 @@
   unsigned NoImplicitFloat   : 1; /// Set when -mno-implicit-float is enabled.
   unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss
   unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use.
+  unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is
+                                     /// enabled.
   unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
   unsigned OptimizeSize      : 1; /// If -Os is specified.
   unsigned RelaxAll          : 1; /// Relax all machine code instructions.
@@ -109,6 +111,7 @@
     NoImplicitFloat = 0;
     NoZeroInitializedInBSS = 0;
     ObjCDispatchMethod = Legacy;
+    OmitLeafFramePointer = 0;
     OptimizationLevel = 0;
     OptimizeSize = 0;
     RelaxAll = 0;
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 793a4da..69efe43 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -160,7 +160,20 @@
   // FIXME: Expose these capabilities via actual APIs!!!! Aside from just
   // being gross, this is also totally broken if we ever care about
   // concurrency.
-  llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim;
+
+  // Set frame pointer elimination mode.
+  if (!CodeGenOpts.DisableFPElim) {
+    llvm::NoFramePointerElim = false;
+    llvm::NoFramePointerElimNonLeaf = false;
+  } else if (CodeGenOpts.OmitLeafFramePointer) {
+    llvm::NoFramePointerElim = false;
+    llvm::NoFramePointerElimNonLeaf = true;
+  } else {
+    llvm::NoFramePointerElim = true;
+    llvm::NoFramePointerElimNonLeaf = true;
+  }
+
+  // Set float ABI type.
   if (CodeGenOpts.FloatABI == "soft")
     llvm::FloatABIType = llvm::FloatABI::Soft;
   else if (CodeGenOpts.FloatABI == "hard")
@@ -169,6 +182,7 @@
     assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
     llvm::FloatABIType = llvm::FloatABI::Default;
   }
+
   NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
   llvm::UseSoftFloat = CodeGenOpts.SoftFloat;
   UnwindTablesMandatory = CodeGenOpts.UnwindTables;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 2a5c383..cfe4539 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -999,6 +999,11 @@
     break;
   }
 
+  // -mno-omit-leaf-frame-pointer is default.
+  if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
+                   options::OPT_mno_omit_leaf_frame_pointer, false))
+    CmdArgs.push_back("-momit-leaf-frame-pointer");
+
   // -fno-math-errno is default.
   if (Args.hasFlag(options::OPT_fmath_errno,
                    options::OPT_fno_math_errno,
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 76770ae..c19879f 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -132,6 +132,8 @@
     Res.push_back("-fno-common");
   if (Opts.NoImplicitFloat)
     Res.push_back("-no-implicit-float");
+  if (Opts.OmitLeafFramePointer)
+    Res.push_back("-momit-leaf-frame-pointer");
   if (Opts.OptimizeSize) {
     assert(Opts.OptimizationLevel == 2 && "Invalid options!");
     Res.push_back("-Os");
@@ -833,6 +835,7 @@
   Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
   Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
   Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
+  Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
   Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
   Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
   Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
diff --git a/test/CodeGen/frame-pointer-elim.c b/test/CodeGen/frame-pointer-elim.c
new file mode 100644
index 0000000..79c0599
--- /dev/null
+++ b/test/CodeGen/frame-pointer-elim.c
@@ -0,0 +1,29 @@
+// RUN: %clang -ccc-host-triple i386 -S -o - %s | \
+// RUN:   FileCheck --check-prefix=DEFAULT %s
+// DEFAULT: f0:
+// DEFAULT: pushl %ebp
+// DEFAULT: ret
+// DEFAULT: f1:
+// DEFAULT: pushl %ebp
+// DEFAULT: ret
+
+// RUN: %clang -ccc-host-triple i386 -S -o - -fomit-frame-pointer %s | \
+// RUN:   FileCheck --check-prefix=OMIT_ALL %s
+// OMIT_ALL: f0:
+// OMIT_ALL-NOT: pushl %ebp
+// OMIT_ALL: ret
+// OMIT_ALL: f1:
+// OMIT_ALL-NOT: pushl %ebp
+// OMIT_ALL: ret
+
+// RUN: %clang -ccc-host-triple i386 -S -o - -momit-leaf-frame-pointer %s | \
+// RUN:   FileCheck --check-prefix=OMIT_LEAF %s
+// OMIT_LEAF: f0:
+// OMIT_LEAF-NOT: pushl %ebp
+// OMIT_LEAF: ret
+// OMIT_LEAF: f1:
+// OMIT_LEAF: pushl %ebp
+// OMIT_LEAF: ret
+
+void f0() {}
+void f1() { f0(); }