config.gcc (mips*-*-*): Add frame-header-opt.o to extra_objs.
authorSteve Ellcey <sellcey@imgtec.com>
Fri, 9 Oct 2015 17:10:42 +0000 (17:10 +0000)
committerSteve Ellcey <sje@gcc.gnu.org>
Fri, 9 Oct 2015 17:10:42 +0000 (17:10 +0000)
2015-10-05  Steve Ellcey  <sellcey@imgtec.com>

* config.gcc (mips*-*-*): Add frame-header-opt.o to extra_objs.
* frame-header-opt.c: New file.
* config/mips/mips-proto.h (mips_register_frame_header_opt):
Add prototype.
* config/mips/mips.c (mips_compute_frame_info): Check
optimize_call_stack flag.
(mips_option_override): Register new frame_header_opt pass.
  (mips_frame_info, mips_int_mask, mips_shadow_set,
machine_function): Move these types to...
* config/mips/mips.h: here.
(machine_function): Add does_not_use_frame_header and
optimize_call_stack fields.
* config/mips/t-mips (frame-header-opt.o): Add new make rule.
* doc/invoke.texi (-mframe-header-opt, -mno-frame-header-opt):
Document new flags.
* config/mips/mips.opt (mframe-header-opt): Add new option.

From-SVN: r228666

gcc/ChangeLog
gcc/config.gcc
gcc/config/mips/frame-header-opt.c [new file with mode: 0644]
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.opt
gcc/config/mips/t-mips
gcc/doc/invoke.texi

index f7b9e9f5c3997fd5ffb9a471e6106008380a3a67..69743c318fb8b1c43f8ed17eb2dcf91c7b130f38 100644 (file)
@@ -1,3 +1,22 @@
+2015-10-09  Steve Ellcey  <sellcey@imgtec.com>
+
+       * config.gcc (mips*-*-*): Add frame-header-opt.o to extra_objs.
+       * frame-header-opt.c: New file.
+       * config/mips/mips-proto.h (mips_register_frame_header_opt):
+       Add prototype.
+       * config/mips/mips.c (mips_compute_frame_info): Check
+       optimize_call_stack flag.
+       (mips_option_override): Register new frame_header_opt pass.
+       (mips_frame_info, mips_int_mask, mips_shadow_set,
+       machine_function): Move these types to...
+       * config/mips/mips.h: here.
+       (machine_function): Add does_not_use_frame_header and
+       optimize_call_stack fields.
+       * config/mips/t-mips (frame-header-opt.o): Add new make rule.
+       * doc/invoke.texi (-mframe-header-opt, -mno-frame-header-opt):
+       Document new flags.
+       * config/mips/mips.opt (mframe-header-opt): Add new option.
+
 2015-10-09  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.c
index 58186634532af23ab3b735bc3964b1bbedc0d8f0..1962b0fa923816715ab6688a5b03294fcbf668b1 100644 (file)
@@ -420,6 +420,7 @@ microblaze*-*-*)
 mips*-*-*)
        cpu_type=mips
        extra_headers="loongson.h"
+       extra_objs="frame-header-opt.o"
        extra_options="${extra_options} g.opt fused-madd.opt mips/mips-tables.opt"
        ;;
 nds32*)
diff --git a/gcc/config/mips/frame-header-opt.c b/gcc/config/mips/frame-header-opt.c
new file mode 100644 (file)
index 0000000..7c7b1f2
--- /dev/null
@@ -0,0 +1,216 @@
+/* Analyze functions to determine if callers need to allocate a frame header
+   on the stack.  The frame header is used by callees to save their arguments.
+   This optimization is specific to TARGET_OLDABI targets.  For TARGET_NEWABI
+   targets, if a frame header is required, it is allocated by the callee.
+
+
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "context.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tree-core.h"
+#include "tree-pass.h"
+#include "target.h"
+#include "target-globals.h"
+#include "cfg.h"
+#include "cgraph.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+
+static unsigned int frame_header_opt (void);
+
+namespace {
+
+const pass_data pass_data_ipa_frame_header_opt =
+{
+  IPA_PASS, /* type */
+  "frame-header-opt", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_CGRAPHOPT, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class pass_ipa_frame_header_opt : public ipa_opt_pass_d
+{
+public:
+  pass_ipa_frame_header_opt (gcc::context *ctxt)
+    : ipa_opt_pass_d (pass_data_ipa_frame_header_opt, ctxt,
+                      NULL, /* generate_summary */
+                      NULL, /* write_summary */
+                      NULL, /* read_summary */
+                      NULL, /* write_optimization_summary */
+                      NULL, /* read_optimization_summary */
+                      NULL, /* stmt_fixup */
+                      0, /* function_transform_todo_flags_start */
+                      NULL, /* function_transform */
+                      NULL) /* variable_transform */
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      /* This optimization has no affect if TARGET_NEWABI.   If optimize
+         is not at least 1 then the data needed for the optimization is
+         not available and nothing will be done anyway.  */
+      return TARGET_OLDABI && flag_frame_header_optimization;
+    }
+
+  virtual unsigned int execute (function *) { return frame_header_opt (); }
+
+}; // class pass_ipa_frame_header_opt
+
+} // anon namespace
+
+static ipa_opt_pass_d *
+make_pass_ipa_frame_header_opt (gcc::context *ctxt)
+{
+  return new pass_ipa_frame_header_opt (ctxt);
+}
+
+void
+mips_register_frame_header_opt (void)
+{
+  opt_pass *p = make_pass_ipa_frame_header_opt (g);
+  static struct register_pass_info f =
+    {p, "comdats", 1, PASS_POS_INSERT_AFTER };
+  register_pass (&f);
+}
+
+
+/* Return true if it is certain that this is a leaf function.  False if it is
+   not a leaf function or if it is impossible to tell.  */
+
+static bool
+is_leaf_function (function *fn)
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+
+  /* If we do not have a cfg for this function be conservative and assume
+     it is not a leaf function.  */
+  if (fn->cfg == NULL)
+    return false;
+
+  FOR_EACH_BB_FN (bb, fn)
+    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+      if (is_gimple_call (gsi_stmt (gsi)))
+       return false;
+  return true;
+}
+
+/* Return true if this function will use the stack space allocated by its
+   caller or if we cannot determine for certain that it does not.  */
+
+static bool
+needs_frame_header_p (function *fn)
+{
+  tree t;
+
+  if (fn->decl == NULL)
+    return true;
+
+  if (fn->stdarg || !is_leaf_function (fn))
+    return true;
+
+  for (t = DECL_ARGUMENTS (fn->decl); t; t = TREE_CHAIN (t))
+    {
+      if (!use_register_for_decl (t))
+         return true;
+    }
+
+  return false;
+}
+
+/* Returns TRUE if the argument stack space allocated by function FN is used.
+   Returns FALSE if the space is needed or if the need for the space cannot
+   be determined.  */
+
+static bool
+callees_functions_use_frame_header (function *fn)
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+  gimple *stmt;
+  tree called_fn_tree;
+  function *called_fn;
+
+  if (fn->cfg == NULL)
+    return true;
+
+  FOR_EACH_BB_FN (bb, fn)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         stmt = gsi_stmt (gsi);
+         if (is_gimple_call (stmt))
+           {
+             called_fn_tree = gimple_call_fndecl (stmt);
+             if (called_fn_tree != NULL)
+               {
+                 called_fn = DECL_STRUCT_FUNCTION (called_fn_tree);
+                 if (called_fn == NULL
+                     || DECL_WEAK (called_fn_tree) 
+                     || !called_fn->machine->does_not_use_frame_header)
+                   return true;
+               }
+             else
+               return true;
+            }
+        }
+    }
+  return false;
+}
+
+/* Scan each function to determine those that need its frame headers.  Perform
+   a second scan to determine if the allocation can be skipped because none of
+   their callees require the frame header.  */
+
+static unsigned int
+frame_header_opt ()
+{
+  struct cgraph_node *node;
+  function *fn;
+
+  FOR_EACH_DEFINED_FUNCTION (node)
+    {
+      fn = node->get_fun ();
+      if (fn != NULL)
+       fn->machine->does_not_use_frame_header = !needs_frame_header_p (fn);
+    }
+
+  FOR_EACH_DEFINED_FUNCTION (node)
+    {
+      fn = node->get_fun ();
+      if (fn != NULL)
+        fn->machine->optimize_call_stack
+         = !callees_functions_use_frame_header (fn);
+    }
+  return 0;
+}
index 8a9ae0147ed2aee8dab5a90db6d11d9b19f126dd..43774facdbe92b226bc6f5b590ac420327880694 100644 (file)
@@ -371,4 +371,6 @@ typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
 extern mulsidi3_gen_fn mips_mulsidi3_gen_fn (enum rtx_code);
 #endif
 
+extern void mips_register_frame_header_opt (void);
+
 #endif /* ! GCC_MIPS_PROTOS_H */
index 456db08d5f02dcb7955bb5b2f2236b7e2ad4f654..a4bb454bee9ff57959a824774b6b1d666a99733e 100644 (file)
@@ -328,153 +328,6 @@ static struct {
   bool fast_mult_zero_zero_p;
 } mips_tuning_info;
 
-/* Information about a function's frame layout.  */
-struct GTY(())  mips_frame_info {
-  /* The size of the frame in bytes.  */
-  HOST_WIDE_INT total_size;
-
-  /* The number of bytes allocated to variables.  */
-  HOST_WIDE_INT var_size;
-
-  /* The number of bytes allocated to outgoing function arguments.  */
-  HOST_WIDE_INT args_size;
-
-  /* The number of bytes allocated to the .cprestore slot, or 0 if there
-     is no such slot.  */
-  HOST_WIDE_INT cprestore_size;
-
-  /* Bit X is set if the function saves or restores GPR X.  */
-  unsigned int mask;
-
-  /* Likewise FPR X.  */
-  unsigned int fmask;
-
-  /* Likewise doubleword accumulator X ($acX).  */
-  unsigned int acc_mask;
-
-  /* The number of GPRs, FPRs, doubleword accumulators and COP0
-     registers saved.  */
-  unsigned int num_gp;
-  unsigned int num_fp;
-  unsigned int num_acc;
-  unsigned int num_cop0_regs;
-
-  /* The offset of the topmost GPR, FPR, accumulator and COP0-register
-     save slots from the top of the frame, or zero if no such slots are
-     needed.  */
-  HOST_WIDE_INT gp_save_offset;
-  HOST_WIDE_INT fp_save_offset;
-  HOST_WIDE_INT acc_save_offset;
-  HOST_WIDE_INT cop0_save_offset;
-
-  /* Likewise, but giving offsets from the bottom of the frame.  */
-  HOST_WIDE_INT gp_sp_offset;
-  HOST_WIDE_INT fp_sp_offset;
-  HOST_WIDE_INT acc_sp_offset;
-  HOST_WIDE_INT cop0_sp_offset;
-
-  /* Similar, but the value passed to _mcount.  */
-  HOST_WIDE_INT ra_fp_offset;
-
-  /* The offset of arg_pointer_rtx from the bottom of the frame.  */
-  HOST_WIDE_INT arg_pointer_offset;
-
-  /* The offset of hard_frame_pointer_rtx from the bottom of the frame.  */
-  HOST_WIDE_INT hard_frame_pointer_offset;
-};
-
-/* Enumeration for masked vectored (VI) and non-masked (EIC) interrupts.  */
-enum mips_int_mask
-{
-  INT_MASK_EIC = -1,
-  INT_MASK_SW0 = 0,
-  INT_MASK_SW1 = 1,
-  INT_MASK_HW0 = 2,
-  INT_MASK_HW1 = 3,
-  INT_MASK_HW2 = 4,
-  INT_MASK_HW3 = 5,
-  INT_MASK_HW4 = 6,
-  INT_MASK_HW5 = 7
-};
-
-/* Enumeration to mark the existence of the shadow register set.
-   SHADOW_SET_INTSTACK indicates a shadow register set with a valid stack
-   pointer.  */
-enum mips_shadow_set
-{
-  SHADOW_SET_NO,
-  SHADOW_SET_YES,
-  SHADOW_SET_INTSTACK
-};
-
-struct GTY(())  machine_function {
-  /* The next floating-point condition-code register to allocate
-     for ISA_HAS_8CC targets, relative to ST_REG_FIRST.  */
-  unsigned int next_fcc;
-
-  /* The register returned by mips16_gp_pseudo_reg; see there for details.  */
-  rtx mips16_gp_pseudo_rtx;
-
-  /* The number of extra stack bytes taken up by register varargs.
-     This area is allocated by the callee at the very top of the frame.  */
-  int varargs_size;
-
-  /* The current frame information, calculated by mips_compute_frame_info.  */
-  struct mips_frame_info frame;
-
-  /* The register to use as the function's global pointer, or INVALID_REGNUM
-     if the function doesn't need one.  */
-  unsigned int global_pointer;
-
-  /* How many instructions it takes to load a label into $AT, or 0 if
-     this property hasn't yet been calculated.  */
-  unsigned int load_label_num_insns;
-
-  /* True if mips_adjust_insn_length should ignore an instruction's
-     hazard attribute.  */
-  bool ignore_hazard_length_p;
-
-  /* True if the whole function is suitable for .set noreorder and
-     .set nomacro.  */
-  bool all_noreorder_p;
-
-  /* True if the function has "inflexible" and "flexible" references
-     to the global pointer.  See mips_cfun_has_inflexible_gp_ref_p
-     and mips_cfun_has_flexible_gp_ref_p for details.  */
-  bool has_inflexible_gp_insn_p;
-  bool has_flexible_gp_insn_p;
-
-  /* True if the function's prologue must load the global pointer
-     value into pic_offset_table_rtx and store the same value in
-     the function's cprestore slot (if any).  Even if this value
-     is currently false, we may decide to set it to true later;
-     see mips_must_initialize_gp_p () for details.  */
-  bool must_initialize_gp_p;
-
-  /* True if the current function must restore $gp after any potential
-     clobber.  This value is only meaningful during the first post-epilogue
-     split_insns pass; see mips_must_initialize_gp_p () for details.  */
-  bool must_restore_gp_when_clobbered_p;
-
-  /* True if this is an interrupt handler.  */
-  bool interrupt_handler_p;
-
-  /* Records the way in which interrupts should be masked.  Only used if
-     interrupts are not kept masked.  */
-  enum mips_int_mask int_mask;
-
-  /* Records if this is an interrupt handler that uses shadow registers.  */
-  enum mips_shadow_set use_shadow_register_set;
-
-  /* True if this is an interrupt handler that should keep interrupts
-     masked.  */
-  bool keep_interrupts_masked_p;
-
-  /* True if this is an interrupt handler that should use DERET
-     instead of ERET.  */
-  bool use_debug_exception_return_p;
-};
-
 /* Information about a single argument.  */
 struct mips_arg_info {
   /* True if the argument is passed in a floating-point register, or
@@ -10504,10 +10357,15 @@ mips_compute_frame_info (void)
   cfun->machine->global_pointer = mips_global_pointer ();
 
   /* The first two blocks contain the outgoing argument area and the $gp save
-     slot.  This area isn't needed in leaf functions, but if the
-     target-independent frame size is nonzero, we have already committed to
-     allocating these in STARTING_FRAME_OFFSET for !FRAME_GROWS_DOWNWARD.  */
-  if ((size == 0 || FRAME_GROWS_DOWNWARD) && crtl->is_leaf)
+     slot.  This area isn't needed in leaf functions.  We can also skip it
+     if we know that none of the called functions will use this space.
+
+     But if the target-independent frame size is nonzero, we have already
+     committed to allocating these in STARTING_FRAME_OFFSET for
+     !FRAME_GROWS_DOWNWARD.  */
+
+  if ((size == 0 || FRAME_GROWS_DOWNWARD)
+      && (crtl->is_leaf || (cfun->machine->optimize_call_stack && !flag_pic)))
     {
       /* The MIPS 3.0 linker does not like functions that dynamically
         allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it
@@ -18269,6 +18127,8 @@ mips_option_override (void)
 
   if (TARGET_HARD_FLOAT_ABI && TARGET_MIPS5900)
     REAL_MODE_FORMAT (SFmode) = &spu_single_format;
+
+  mips_register_frame_header_opt ();
 }
 
 /* Swap the register information for registers I and I + 1, which
index 25a1e0622cd4024f70e4c30431caeac6df83486a..be86c109b6c3c99b2eb46fdef2df504c94f2a881 100644 (file)
@@ -3119,6 +3119,161 @@ extern const struct mips_cpu_info *mips_tune_info;
 extern unsigned int mips_base_compression_flags;
 extern GTY(()) struct target_globals *mips16_globals;
 extern GTY(()) struct target_globals *micromips_globals;
+
+/* Information about a function's frame layout.  */
+struct GTY(())  mips_frame_info {
+  /* The size of the frame in bytes.  */
+  HOST_WIDE_INT total_size;
+
+  /* The number of bytes allocated to variables.  */
+  HOST_WIDE_INT var_size;
+
+  /* The number of bytes allocated to outgoing function arguments.  */
+  HOST_WIDE_INT args_size;
+
+  /* The number of bytes allocated to the .cprestore slot, or 0 if there
+     is no such slot.  */
+  HOST_WIDE_INT cprestore_size;
+
+  /* Bit X is set if the function saves or restores GPR X.  */
+  unsigned int mask;
+
+  /* Likewise FPR X.  */
+  unsigned int fmask;
+
+  /* Likewise doubleword accumulator X ($acX).  */
+  unsigned int acc_mask;
+
+  /* The number of GPRs, FPRs, doubleword accumulators and COP0
+     registers saved.  */
+  unsigned int num_gp;
+  unsigned int num_fp;
+  unsigned int num_acc;
+  unsigned int num_cop0_regs;
+
+  /* The offset of the topmost GPR, FPR, accumulator and COP0-register
+     save slots from the top of the frame, or zero if no such slots are
+     needed.  */
+  HOST_WIDE_INT gp_save_offset;
+  HOST_WIDE_INT fp_save_offset;
+  HOST_WIDE_INT acc_save_offset;
+  HOST_WIDE_INT cop0_save_offset;
+
+  /* Likewise, but giving offsets from the bottom of the frame.  */
+  HOST_WIDE_INT gp_sp_offset;
+  HOST_WIDE_INT fp_sp_offset;
+  HOST_WIDE_INT acc_sp_offset;
+  HOST_WIDE_INT cop0_sp_offset;
+
+  /* Similar, but the value passed to _mcount.  */
+  HOST_WIDE_INT ra_fp_offset;
+
+  /* The offset of arg_pointer_rtx from the bottom of the frame.  */
+  HOST_WIDE_INT arg_pointer_offset;
+
+  /* The offset of hard_frame_pointer_rtx from the bottom of the frame.  */
+  HOST_WIDE_INT hard_frame_pointer_offset;
+};
+
+/* Enumeration for masked vectored (VI) and non-masked (EIC) interrupts.  */
+enum mips_int_mask
+{
+  INT_MASK_EIC = -1,
+  INT_MASK_SW0 = 0,
+  INT_MASK_SW1 = 1,
+  INT_MASK_HW0 = 2,
+  INT_MASK_HW1 = 3,
+  INT_MASK_HW2 = 4,
+  INT_MASK_HW3 = 5,
+  INT_MASK_HW4 = 6,
+  INT_MASK_HW5 = 7
+};
+
+/* Enumeration to mark the existence of the shadow register set.
+   SHADOW_SET_INTSTACK indicates a shadow register set with a valid stack
+   pointer.  */
+enum mips_shadow_set
+{
+  SHADOW_SET_NO,
+  SHADOW_SET_YES,
+  SHADOW_SET_INTSTACK
+};
+
+struct GTY(())  machine_function {
+  /* The next floating-point condition-code register to allocate
+     for ISA_HAS_8CC targets, relative to ST_REG_FIRST.  */
+  unsigned int next_fcc;
+
+  /* The register returned by mips16_gp_pseudo_reg; see there for details.  */
+  rtx mips16_gp_pseudo_rtx;
+
+  /* The number of extra stack bytes taken up by register varargs.
+     This area is allocated by the callee at the very top of the frame.  */
+  int varargs_size;
+
+  /* The current frame information, calculated by mips_compute_frame_info.  */
+  struct mips_frame_info frame;
+
+  /* The register to use as the function's global pointer, or INVALID_REGNUM
+     if the function doesn't need one.  */
+  unsigned int global_pointer;
+
+  /* How many instructions it takes to load a label into $AT, or 0 if
+     this property hasn't yet been calculated.  */
+  unsigned int load_label_num_insns;
+
+  /* True if mips_adjust_insn_length should ignore an instruction's
+     hazard attribute.  */
+  bool ignore_hazard_length_p;
+
+  /* True if the whole function is suitable for .set noreorder and
+     .set nomacro.  */
+  bool all_noreorder_p;
+
+  /* True if the function has "inflexible" and "flexible" references
+     to the global pointer.  See mips_cfun_has_inflexible_gp_ref_p
+     and mips_cfun_has_flexible_gp_ref_p for details.  */
+  bool has_inflexible_gp_insn_p;
+  bool has_flexible_gp_insn_p;
+
+  /* True if the function's prologue must load the global pointer
+     value into pic_offset_table_rtx and store the same value in
+     the function's cprestore slot (if any).  Even if this value
+     is currently false, we may decide to set it to true later;
+     see mips_must_initialize_gp_p () for details.  */
+  bool must_initialize_gp_p;
+
+  /* True if the current function must restore $gp after any potential
+     clobber.  This value is only meaningful during the first post-epilogue
+     split_insns pass; see mips_must_initialize_gp_p () for details.  */
+  bool must_restore_gp_when_clobbered_p;
+
+  /* True if this is an interrupt handler.  */
+  bool interrupt_handler_p;
+
+  /* Records the way in which interrupts should be masked.  Only used if
+     interrupts are not kept masked.  */
+  enum mips_int_mask int_mask;
+
+  /* Records if this is an interrupt handler that uses shadow registers.  */
+  enum mips_shadow_set use_shadow_register_set;
+
+  /* True if this is an interrupt handler that should keep interrupts
+     masked.  */
+  bool keep_interrupts_masked_p;
+
+  /* True if this is an interrupt handler that should use DERET
+     instead of ERET.  */
+  bool use_debug_exception_return_p;
+
+  /* True if at least one of the formal parameters to a function must be
+     written to the frame header (probably so its address can be taken).  */
+  bool does_not_use_frame_header;
+
+  /* True if none of the functions that are called by this function need
+     stack space allocated for their arguments.  */
+  bool optimize_call_stack;
+};
 #endif
 
 /* Enable querying of DFA units.  */
index 84887d11623c47e5ed97b77cb2b297578404152b..b979eb51c593806284de69eda5c922be5bf370c0 100644 (file)
@@ -412,6 +412,10 @@ modd-spreg
 Target Report Mask(ODD_SPREG)
 Enable use of odd-numbered single-precision registers
 
+mframe-header-opt
+Target Report Var(flag_frame_header_optimization) Optimization
+Optimize frame header
+
 noasmopt
 Driver
 
index 01df1ad76a4a688109fee7f57cb63850e0e0ea8e..a8938411420c69408d5c3ba27f507f38b9dc1716 100644 (file)
@@ -20,3 +20,7 @@ $(srcdir)/config/mips/mips-tables.opt: $(srcdir)/config/mips/genopt.sh \
   $(srcdir)/config/mips/mips-cpus.def
        $(SHELL) $(srcdir)/config/mips/genopt.sh $(srcdir)/config/mips > \
                $(srcdir)/config/mips/mips-tables.opt
+
+frame-header-opt.o: $(srcdir)/config/mips/frame-header-opt.c
+       $(COMPILE) $<
+       $(POSTCOMPILE)
index 1b44b444cbe3e907269d3debf596c948b87fdb81..f10d7496c7968216a093d55778cbe19e69df0367 100644 (file)
@@ -818,7 +818,8 @@ Objective-C and Objective-C++ Dialects}.
 -mbranch-cost=@var{num}  -mbranch-likely  -mno-branch-likely @gol
 -mfp-exceptions -mno-fp-exceptions @gol
 -mvr4130-align -mno-vr4130-align -msynci -mno-synci @gol
--mrelax-pic-calls -mno-relax-pic-calls -mmcount-ra-address}
+-mrelax-pic-calls -mno-relax-pic-calls -mmcount-ra-address @gol
+-mframe-header-opt -mno-frame-header-opt}
 
 @emph{MMIX Options}
 @gccoptlist{-mlibfuncs  -mno-libfuncs  -mepsilon  -mno-epsilon  -mabi=gnu @gol
@@ -18108,6 +18109,17 @@ if @var{ra-address} is nonnull.
 
 The default is @option{-mno-mcount-ra-address}.
 
+@item -mframe-header-opt
+@itemx -mno-frame-header-opt
+@opindex mframe-header-opt
+Enable (disable) frame header optimization in the o32 ABI.  When using the
+o32 ABI, calling functions will allocate 16 bytes on the stack for the called
+function to write out register arguments.  When enabled, this optimization
+will suppress the allocation of the frame header if it can be determined that
+it is unused.
+
+This optimization is off by default at all optimization levels.
+
 @end table
 
 @node MMIX Options