This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Implement -fstack-usage


Hi,

While we are at it, here is another patch whose submission was delayed because 
of the already substantial backlog of AdaCore patches.  This is related to
 http://www.gccsummit.org/2005/view_abstract.php?content_key=18

Tested on i586-suse-linux. 


2006-06-19  Eric Botcazou  <ebotcazou@adacore.com>

	Stack usage support
	* common.opt (-fstack-usage): New option.
	* doc/invoke.texi (Debugging options): Document it.
	* expr.h (allocate_dynamic_stack_space): Add 4th bool parameter.
	* builtins.c (expand_builtin_apply): Pass TRUE as 4th argument to
	allocate_dynamic_stack_space.
	(expand_builtin_alloca): Add 4th bool parameter CANNOT_ACCUMULATE
	and propagate it to allocate_dynamic_stack_space.
	(expand_builtin) <BUILT_IN_ALLOCA>: Adjust for above change.
	* calls.c (initialize_argument_information): Pass TRUE as 4th
	argument to allocate_dynamic_stack_space.
	(expand_call): Set current_function_has_unbounded_dynamic_stack_size
	to 1 when pushing a variable-sized argument onto the stack.  Pass
	TRUE as 4th argument to allocate_dynamic_stack_space.
	Update current_function_pushed_stack_size.
	(emit_library_call_value_1): Likewise.
	* explow.c (allocate_dynamic_stack_space): Add 4th bool parameter
	CANNOT_ACCUMULATE.  If flag_stack_usage, look into the size and
	attempt to find an upper bound.  Remove redundant code for the
	SETJMP_VIA_SAVE_AREA case.
	* flow.c (rest_of_handle_flow2): Invoke output_stack_usage if needed.
	* function.h (struct function): Add new fields pushed_stack_size,
	dynamic_alloc_count, dynamic_stack_size and
	has_unbounded_dynamic_stack_size.
	(current_function_pushed_stack_size): New macro.
	(current_function_dynamic_alloc_count): Likewise.
	(current_function_dynamic_stack_size): Likewise.
	(current_function_has_unbounded_dynamic_stack_size): Likewise.
	(current_function_allocates_dynamic_stack_space): Likewise.
	* function.c (instantiate_virtual_regs): If SETJMP_VIA_SAVE_AREA,
	add the value of the dynamic offset to the dynamic stack usage.
	* gimplify.c (gimplify_decl_expr): Set CALL_FROM_THUNK_P on the call
	to BUILT_IN_ALLOCA for variable-sized objects.
	* stmt.c (expand_decl): Pass true to allocate_dynamic_stack_space.
	* toplev.h (output_stack_usage): Declare.
	* toplev.c (stack_usage_file): New file pointer.
	(output_stack_usage): New function.
	(open_auxiliary_file): Likewise.
	(lang_dependent_init): Open file if flag_stack_usage is set.
	(finalize): Close file if stack_usage_file is not null.
	* tree.h (CALL_FROM_THUNK_P): Document specialized usage.
	* target.h (struct gcc_target): Add get_static_stack_usage.
	* target-def.h (TARGET_GET_STATIC_STACK_USAGE): Define to 0.
	(TARGET_INITIALIZER): Add it.
	* doc/tm.texi (Frame layout): Document it.
	* config/alpha/alpha.c (compute_frame_size): New function.
	(alpha_expand_prologue): Use it.
	(alpha_start_function): Likewise.
	(alpha_expand_epilogue): Likewise.
	(alpha_get_static_stack_usage): New function.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.
	* config/i386/i386.c (ix86_get_static_stack_usage): New function.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.
	* config/ia64/ia64.c (ia64_get_static_stack_usage): New function.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.
	* config/mips/mips.c (mips_get_static_stack_usage): New function.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.
	* config/pa/pa.c (pa_get_static_stack_usage): New function.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.
	* config/rs6000/rs6000.c (rs6000_get_static_stack_usage): New.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.
	* config/sparc/sparc.c (sparc_get_static_stack_usage): New function.
	(TARGET_GET_STATIC_STACK_USAGE): Define to it.


-- 
Eric Botcazou
Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 114740)
+++ doc/tm.texi	(working copy)
@@ -3109,6 +3109,12 @@ in DWARF 2 debug information.  The defau
 may reduce the size of debug information on some ports.
 @end defmac
 
+@deftypefn {Target Hook} HOST_WIDE_INT TARGET_GET_STATIC_STACK_USAGE (void)
+This target hook should return the maximum static stack usage for the
+current function.  It is invoked just before prologue and epilogue are
+emitted for the function.
+@end deftypefn
+
 @node Exception Handling
 @subsection Exception Handling Support
 @cindex exception handling
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 114740)
+++ doc/invoke.texi	(working copy)
@@ -291,7 +291,7 @@ Objective-C and Objective-C++ Dialects}.
 -feliminate-unused-debug-symbols -femit-class-debug-always @gol
 -fmem-report -fprofile-arcs @gol
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
--ftest-coverage  -ftime-report -fvar-tracking @gol
+-fstack-usage  -ftest-coverage  -ftime-report -fvar-tracking @gol
 -g  -g@var{level}  -gcoff -gdwarf-2 @gol
 -ggdb  -gstabs  -gstabs+  -gvms  -gxcoff  -gxcoff+ @gol
 -p  -pg  -print-file-name=@var{library}  -print-libgcc-file-name @gol
@@ -3650,6 +3650,39 @@ pass when it finishes.
 Makes the compiler print some statistics about permanent memory
 allocation when it finishes.
 
+@item -fstack-usage
+@opindex fstack-usage
+Makes the compiler output stack usage information for the program, on a
+per-function basis.  The filename for the dump is made by appending
+@file{.su} to the AUXNAME.  AUXNAME is generated from the name of
+the output file, if explicitly specified and it is not an executable,
+otherwise it is the basename of the source file.  An entry is made up
+of three fields:
+
+@itemize
+@item
+The name of the function.
+@item
+A number of bytes.
+@item
+One or more qualifiers: @code{static}, @code{dynamic}, @code{bounded}.
+@end itemize
+
+The qualifier @code{static} means that the function manipulates the stack
+statically: a fixed number of bytes are allocated for the frame on function
+entry and released on function exit; no stack adjustments are otherwise made
+in the function.  The second field is this fixed number of bytes.
+
+The qualifier @code{dynamic} means that the function manipulates the stack
+dynamically: in addition to the static allocation described above, stack
+adjustments are made in the body of the function, for example to push/pop
+arguments around function calls.  If the qualifier @code{bounded} is also
+present, the amount of these adjustments is bounded at compile-time and
+the second field is an upper bound of the total amount of stack used by
+the function.  If it is not present, the amount of these adjustments is
+not bounded at compile-time and the second field only represents the
+bounded part.
+
 @item -fprofile-arcs
 @opindex fprofile-arcs
 Add code so that program flow @dfn{arcs} are instrumented.  During
Index: tree.h
===================================================================
--- tree.h	(revision 114740)
+++ tree.h	(working copy)
@@ -1177,7 +1177,9 @@ extern void omp_clause_range_check_faile
 #define DECL_BY_REFERENCE(NODE) (DECL_COMMON_CHECK (NODE)->common.private_flag)
 
 /* In a CALL_EXPR, means that the call is the jump from a thunk to the
-   thunked-to function.  */
+   thunked-to function.  As a special case, if the function being called
+   is BUILT_IN_ALLOCA, means that it has been built for the declaration
+   of a variable-sized object.  */
 #define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->common.protected_flag)
 
 /* In a type, nonzero means that all objects of the type are guaranteed by the
Index: target.h
===================================================================
--- target.h	(revision 114740)
+++ target.h	(working copy)
@@ -649,6 +649,9 @@ struct gcc_target
      that is invoked when a check vs the guard variable fails.  */
   tree (* stack_protect_fail) (void);
 
+  /* Return the maximum static stack usage for the current function.  */
+  HOST_WIDE_INT (* get_static_stack_usage) (void);
+
   /* Returns NULL if target supports the insn within a doloop block,
      otherwise it returns an error message.  */
   const char * (*invalid_within_doloop) (rtx);
Index: builtins.c
===================================================================
--- builtins.c	(revision 114740)
+++ builtins.c	(working copy)
@@ -126,7 +126,7 @@ static rtx expand_builtin_strstr (tree, 
 static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
-static rtx expand_builtin_alloca (tree, rtx);
+static rtx expand_builtin_alloca (tree, rtx, bool);
 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
 static rtx expand_builtin_frame_address (tree, tree);
 static rtx expand_builtin_fputs (tree, rtx, bool);
@@ -1428,8 +1428,10 @@ expand_builtin_apply (rtx function, rtx 
     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
 
   /* Allocate a block of memory onto the stack and copy the memory
-     arguments to the outgoing arguments address.  */
-  allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
+     arguments to the outgoing arguments address.  We can pass TRUE
+     as the 4th argument because we just saved the stack pointer
+     and will restore it right after the call.  */
+  allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT, TRUE);
   dest = virtual_outgoing_args_rtx;
 #ifndef STACK_GROWS_DOWNWARD
   if (GET_CODE (argsize) == CONST_INT)
@@ -4537,10 +4539,11 @@ expand_builtin_frame_address (tree fndec
 
 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
    we failed and the caller should emit a normal call, otherwise try to get
-   the result in TARGET, if convenient.  */
+   the result in TARGET, if convenient.  CANNOT_ACCUMULATE is the same as
+   for allocate_dynamic_stack_space.  */
 
 static rtx
-expand_builtin_alloca (tree arglist, rtx target)
+expand_builtin_alloca (tree arglist, rtx target, bool cannot_accumulate)
 {
   rtx op0;
   rtx result;
@@ -4558,7 +4561,8 @@ expand_builtin_alloca (tree arglist, rtx
   op0 = expand_normal (TREE_VALUE (arglist));
 
   /* Allocate the desired space.  */
-  result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
+  result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT,
+					 cannot_accumulate);
   result = convert_memory_address (ptr_mode, result);
 
   return result;
@@ -5813,7 +5817,10 @@ expand_builtin (tree exp, rtx target, rt
 	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
 
     case BUILT_IN_ALLOCA:
-      target = expand_builtin_alloca (arglist, target);
+      /* If the allocation stems from the declaration of a variable-sized
+	 object, it cannot accumulate.  */
+      target = expand_builtin_alloca (arglist, target,
+				      CALL_FROM_THUNK_P (exp));
       if (target)
 	return target;
       break;
Index: toplev.c
===================================================================
--- toplev.c	(revision 114740)
+++ toplev.c	(working copy)
@@ -388,6 +388,7 @@ static const param_info lang_independent
 
 FILE *asm_out_file;
 FILE *aux_info_file;
+FILE *stack_usage_file = NULL;
 FILE *dump_file = NULL;
 const char *dump_file_name;
 
@@ -1431,6 +1432,91 @@ default_tree_printer (pretty_printer * p
   return true;
 }
 
+/* Output stack usage information.  */
+void
+output_stack_usage (void)
+{
+  static bool warning_issued = false;
+  enum stack_usage_kind_type { STATIC = 0, DYNAMIC, DYNAMIC_BOUNDED };
+  const char *stack_usage_kind_str[] = {
+    "static",
+    "dynamic",
+    "dynamic,bounded"
+  };
+  HOST_WIDE_INT stack_usage = -1;
+  enum stack_usage_kind_type stack_usage_kind;
+  const char *raw_id, *id;
+
+  /* Rely on the back-end to compute the maximum static stack usage.
+     The back-end needs this information at one point or another to
+     reserve storage for the frame.  */
+  if (targetm.get_static_stack_usage)
+    stack_usage = targetm.get_static_stack_usage ();
+
+  if (stack_usage == -1)
+    {
+      if (!warning_issued)
+	{
+	  warning (OPT_fstack_usage,
+		   "-fstack-usage not supported for this target");
+	  warning_issued = true;
+	}
+      return;
+    }
+
+  stack_usage_kind = STATIC;
+
+  /* Add the maximum amount of space pushed onto the stack.  */
+  if (current_function_pushed_stack_size > 0)
+    {
+      stack_usage += current_function_pushed_stack_size;
+      stack_usage_kind = DYNAMIC_BOUNDED;
+    }
+
+  /* Now on to the tricky part: dynamic stack allocation.  */
+  if (current_function_allocates_dynamic_stack_space)
+    {
+      if (current_function_has_unbounded_dynamic_stack_size)
+	stack_usage_kind = DYNAMIC;
+      else
+	stack_usage_kind = DYNAMIC_BOUNDED;
+
+      /* Add the size even in the unbounded case, this can't hurt.  */
+      stack_usage += current_function_dynamic_stack_size;
+    }
+
+  /* Strip the scope prefix if any.  */
+  raw_id = lang_hooks.decl_printable_name (current_function_decl, 2);
+  id = strrchr (raw_id, '.');
+  if (id)
+    id++;
+  else
+    id = raw_id;
+
+  fprintf (stack_usage_file,
+	   "%s:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n",
+	   basename (DECL_SOURCE_FILE (current_function_decl)),
+	   DECL_SOURCE_LINE (current_function_decl),
+	   id,
+	   stack_usage,
+	   stack_usage_kind_str[stack_usage_kind]);
+}
+
+/* Open an auxiliary output file.  */
+static FILE *
+open_auxiliary_file (const char *ext)
+{
+  char *filename;
+  FILE *file;
+
+  filename = concat (aux_base_name, ".", ext, NULL);
+  file = fopen (filename, "w");
+  if (!file)
+    fatal_error ("can't open %s for writing: %m", filename);
+  free (filename);
+  return file;
+}
+
 /* Initialization of the front end environment, before command line
    options are parsed.  Signal handlers, internationalization etc.
    ARGV0 is main's argv[0].  */
@@ -1867,6 +1953,10 @@ lang_dependent_init (const char *name)
 
   init_asm_output (name);
 
+  /* If stack usage information is desired, open the output file.  */
+  if (flag_stack_usage)
+    stack_usage_file = open_auxiliary_file ("su");
+
   /* These create various _DECL nodes, so need to be called after the
      front end is initialized.  */
   init_eh ();
@@ -1921,6 +2011,9 @@ finalize (void)
 	fatal_error ("error closing %s: %m", asm_file_name);
     }
 
+  if (stack_usage_file)
+    fclose (stack_usage_file);
+
   finish_optimization_passes ();
 
   if (mem_report)
Index: toplev.h
===================================================================
--- toplev.h	(revision 114740)
+++ toplev.h	(working copy)
@@ -100,6 +100,9 @@ extern void check_global_declarations (t
 extern void emit_debug_global_declarations (tree *, int);
 extern void write_global_declarations (void);
 
+/* Output stack usage information.  */
+extern void output_stack_usage (void);
+
 /* A unique local time stamp, might be zero if none is available.  */
 extern unsigned local_tick;
 
Index: flow.c
===================================================================
--- flow.c	(revision 114740)
+++ flow.c	(working copy)
@@ -4699,6 +4699,10 @@ rest_of_handle_flow2 (void)
   if (optimize)
     cleanup_cfg (CLEANUP_EXPENSIVE);
 
+  /* The IA-64 port invalidates its static stack usage info right after.  */
+  if (flag_stack_usage)
+    output_stack_usage ();
+
   /* On some machines, the prologue and epilogue code, or parts thereof,
      can be represented as RTL.  Doing so lets us schedule insns between
      it and the rest of the code and also allows delayed branch
Index: expr.h
===================================================================
--- expr.h	(revision 114740)
+++ expr.h	(working copy)
@@ -701,9 +701,8 @@ extern void emit_stack_restore (enum sav
 /* Invoke emit_stack_save for the nonlocal_goto_save_area.  */
 extern void update_nonlocal_goto_save_area (void);
 
-/* Allocate some space on the stack dynamically and return its address.  An rtx
-   says how many bytes.  */
-extern rtx allocate_dynamic_stack_space (rtx, rtx, int);
+/* Allocate some space on the stack dynamically and return its address.  */
+extern rtx allocate_dynamic_stack_space (rtx, rtx, int, bool);
 
 /* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
    FIRST is a constant and size is a Pmode RTX.  These are offsets from the
Index: function.c
===================================================================
--- function.c	(revision 114740)
+++ function.c	(working copy)
@@ -1726,6 +1726,18 @@ instantiate_virtual_regs (void)
   /* Indicate that, from now on, assign_stack_local should use
      frame_pointer_rtx.  */
   virtuals_instantiated = 1;
+
+  /* See allocate_dynamic_stack_space for the rationale.  */
+#ifdef SETJMP_VIA_SAVE_AREA
+  if (flag_stack_usage && current_function_calls_setjmp)
+    {
+      int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
+      dynamic_offset = (dynamic_offset + align - 1) / align * align;
+      current_function_dynamic_stack_size
+	+= current_function_dynamic_alloc_count * dynamic_offset;
+    }
+#endif
+
   return 0;
 }
 
Index: function.h
===================================================================
--- function.h	(revision 114740)
+++ function.h	(working copy)
@@ -216,6 +216,17 @@ struct function GTY(())
      defined, the needed space is pushed by the prologue.  */
   int outgoing_args_size;
 
+  /* # of bytes of space pushed onto the stack after the prologue.  If
+     !ACCUMULATE_OUTGOING_ARGS, it contains the outgoing arguments.  */
+  int pushed_stack_size;
+
+  /* # of dynamic allocations in the function.  */
+  unsigned int dynamic_alloc_count;
+
+  /* # of bytes of dynamic stack space allocated by the function.  This is
+     meaningful only if has_unbounded_dynamic_stack_size is zero.  */
+  HOST_WIDE_INT dynamic_stack_size;
+
   /* This is the offset from the arg pointer to the place where the first
      anonymous arg can be found, if there is one.  */
   rtx arg_offset_rtx;
@@ -399,6 +410,10 @@ struct function GTY(())
      function.  */
   unsigned int has_nonlocal_goto : 1;
 
+  /* Nonzero if the amount of stack space allocated dynamically cannot
+     be bounded at compile-time.  */
+  unsigned int has_unbounded_dynamic_stack_size : 1;
+
   /* Nonzero if the current function is a thunk, i.e., a lightweight
      function implemented by the output_mi_thunk hook) that just
      adjusts one of its arguments and forwards to another
@@ -496,6 +511,9 @@ extern int trampolines_created;
 #define current_function_args_size (cfun->args_size)
 #define current_function_pretend_args_size (cfun->pretend_args_size)
 #define current_function_outgoing_args_size (cfun->outgoing_args_size)
+#define current_function_pushed_stack_size (cfun->pushed_stack_size)
+#define current_function_dynamic_alloc_count (cfun->dynamic_alloc_count)
+#define current_function_dynamic_stack_size (cfun->dynamic_stack_size)
 #define current_function_arg_offset_rtx (cfun->arg_offset_rtx)
 #define current_function_stdarg (cfun->stdarg)
 #define current_function_internal_arg_pointer (cfun->internal_arg_pointer)
@@ -508,6 +526,11 @@ extern int trampolines_created;
 #define current_function_epilogue_delay_list (cfun->epilogue_delay_list)
 #define current_function_has_nonlocal_label (cfun->has_nonlocal_label)
 #define current_function_has_nonlocal_goto (cfun->has_nonlocal_goto)
+#define current_function_has_unbounded_dynamic_stack_size \
+  (cfun->has_unbounded_dynamic_stack_size)
+#define current_function_allocates_dynamic_stack_space   \
+  (current_function_dynamic_stack_size != 0              \
+   || current_function_has_unbounded_dynamic_stack_size)
 
 #define return_label (cfun->x_return_label)
 #define naked_return_label (cfun->x_naked_return_label)
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 114740)
+++ gimplify.c	(working copy)
@@ -1212,6 +1212,8 @@ gimplify_decl_expr (tree *stmt_p)
 	  args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL);
 	  t = built_in_decls[BUILT_IN_ALLOCA];
 	  t = build_function_call_expr (t, args);
+	  /* The call has been built for a variable-sized object.  */
+	  CALL_FROM_THUNK_P (t) = 1;
 	  t = fold_convert (ptr_type, t);
 	  t = build2 (MODIFY_EXPR, void_type_node, addr, t);
 
Index: calls.c
===================================================================
--- calls.c	(revision 114740)
+++ calls.c	(working copy)
@@ -1040,9 +1040,13 @@ initialize_argument_information (int num
 		      pending_stack_adjust = 0;
 		    }
 
+		  /* We can pass TRUE as the 4th argument because we just
+		     saved the stack pointer and will restore it right after
+		     the call.  */
 		  copy = gen_rtx_MEM (BLKmode,
 				      allocate_dynamic_stack_space
-				      (size_rtx, NULL_RTX, TYPE_ALIGN (type)));
+				      (size_rtx, NULL_RTX,
+				       TYPE_ALIGN (type), TRUE));
 		  set_mem_attributes (copy, type, 1);
 		}
 	      else
@@ -2318,6 +2322,7 @@ expand_call (tree exp, rtx target, int i
 	      stack_arg_under_construction = 0;
 	    }
 	  argblock = push_block (ARGS_SIZE_RTX (adjusted_args_size), 0, 0);
+	  current_function_has_unbounded_dynamic_stack_size = 1;
 	}
       else
 	{
@@ -2482,8 +2487,11 @@ expand_call (tree exp, rtx target, int i
 		  memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
 		  highest_outgoing_arg_in_use = 0;
 		}
+	      /* We can pass TRUE as the 4th argument because we just
+		 saved the stack pointer and will restore it right after
+		 the call.  */
 	      allocate_dynamic_stack_space (push_size, NULL_RTX,
-					    BITS_PER_UNIT);
+					    BITS_PER_UNIT, TRUE);
 	    }
 
 	  /* If argument evaluation might modify the stack pointer,
@@ -2524,6 +2532,18 @@ expand_call (tree exp, rtx target, int i
 	 be deferred during the evaluation of the arguments.  */
       NO_DEFER_POP;
 
+      if (!ACCUMULATE_OUTGOING_ARGS && pass && adjusted_args_size.var == 0)
+	{
+	  int needed = adjusted_args_size.constant + pending_stack_adjust;
+
+	  /* Record the maximum pushed stack space size.  We need to
+	     delay it this far to take into account the optimization
+	     done by combine_pending_stack_adjustment_and_call.  */
+
+	  if (needed > current_function_pushed_stack_size)
+	    current_function_pushed_stack_size = needed;
+	}
+
       funexp = rtx_for_function_call (fndecl, addr);
 
       /* Figure out the register where the value, if any, will come back.  */
@@ -3506,8 +3526,23 @@ emit_library_call_value_1 (int retval, r
   args_size.constant -= reg_parm_stack_space;
 #endif
 
-  if (args_size.constant > current_function_outgoing_args_size)
-    current_function_outgoing_args_size = args_size.constant;
+  {
+    int needed = args_size.constant;
+
+    /* Store the maximum argument space used.  It will be pushed by
+       the prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow
+       checking).  */
+
+    if (needed > current_function_outgoing_args_size)
+      current_function_outgoing_args_size = needed;
+
+    if (!ACCUMULATE_OUTGOING_ARGS)
+      {
+	needed += pending_stack_adjust;
+	if (needed  > current_function_pushed_stack_size)
+	  current_function_pushed_stack_size = needed;
+      }
+  }
 
   if (ACCUMULATE_OUTGOING_ARGS)
     {
Index: explow.c
===================================================================
--- explow.c	(revision 114740)
+++ explow.c	(working copy)
@@ -1080,11 +1080,23 @@ update_nonlocal_goto_save_area (void)
    SIZE is an rtx representing the size of the area.
    TARGET is a place in which the address can be placed.
 
-   KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */
+   KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.
+
+   If CANNOT_ACCUMULATE is set to TRUE, the caller guarantees that the
+   stack space allocated by the generated code cannot be added with itself
+   in the course of the execution of the function.  It is always safe to
+   pass FALSE here and the following criterion is sufficient in order to
+   pass TRUE: every path in the CFG that starts at the allocation point and
+   loops to it executes the associated deallocation code (that always exists
+   if the function does not use the depressed stack pointer mechanism).  */
 
 rtx
-allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
+allocate_dynamic_stack_space (rtx size, rtx target, int known_align,
+			      bool cannot_accumulate)
 {
+  HOST_WIDE_INT stack_usage_size = -1;
+  bool known_align_valid = true;
+
   /* If we're asking for zero bytes, it doesn't matter what we point
      to since we can't dereference it.  But return a reasonable
      address anyway.  */
@@ -1094,6 +1106,38 @@ allocate_dynamic_stack_space (rtx size, 
   /* Otherwise, show we're calling alloca or equivalent.  */
   current_function_calls_alloca = 1;
 
+  /* If stack usage info is requested, look into the size we are passed.
+     We need to do so this early to avoid the obfuscation that may be
+     introduced later by the various alignment operations.  */
+  if (flag_stack_usage)
+    {
+      if (GET_CODE (size) == CONST_INT)
+	stack_usage_size = INTVAL (size);
+      else if (GET_CODE (size) == REG)
+        {
+	  /* Look into the last emitted insn and see if we can deduce
+	     something for the register.  */
+	  rtx insn, set, note;
+	  insn = get_last_insn ();
+	  if ((set = single_set (insn))
+	      && rtx_equal_p (SET_DEST (set), size))
+	    {
+	      if (GET_CODE (SET_SRC (set)) == CONST_INT)
+		stack_usage_size = INTVAL (SET_SRC (set));
+	      else if ((note = find_reg_equal_equiv_note (insn))
+		       && GET_CODE (XEXP (note, 0)) == CONST_INT)
+		stack_usage_size = INTVAL (XEXP (note, 0));
+	    }
+	}
+
+      /* If the size is not constant, we can't say anything.  */
+      if (stack_usage_size == -1)
+	{
+	  current_function_has_unbounded_dynamic_stack_size = 1;
+	  stack_usage_size = 0;
+	}
+    }
+
   /* Ensure the size is in the proper mode.  */
   if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
     size = convert_to_mode (Pmode, size, 1);
@@ -1123,10 +1167,17 @@ allocate_dynamic_stack_space (rtx size, 
 #endif
 
   if (MUST_ALIGN)
-    size
-      = force_operand (plus_constant (size,
-				      BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
-		       NULL_RTX);
+    {
+      size
+        = force_operand (plus_constant (size,
+					BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
+			 NULL_RTX);
+
+      if (flag_stack_usage)
+	stack_usage_size += BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1;
+
+      known_align_valid = false;
+    }
 
 #ifdef SETJMP_VIA_SAVE_AREA
   /* If setjmp restores regs from a save area in the stack frame,
@@ -1140,32 +1191,7 @@ allocate_dynamic_stack_space (rtx size, 
      would use reg notes to store the "optimized" size and fix things
      up later.  These days we know this information before we ever
      start building RTL so the reg notes are unnecessary.  */
-  if (!current_function_calls_setjmp)
-    {
-      int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
-
-      /* ??? Code below assumes that the save area needs maximal
-	 alignment.  This constraint may be too strong.  */
-      gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
-
-      if (GET_CODE (size) == CONST_INT)
-	{
-	  HOST_WIDE_INT new = INTVAL (size) / align * align;
-
-	  if (INTVAL (size) != new)
-	    size = GEN_INT (new);
-	}
-      else
-	{
-	  /* Since we know overflow is not possible, we avoid using
-	     CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead.  */
-	  size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
-				GEN_INT (align), NULL_RTX, 1);
-	  size = expand_mult (Pmode, size,
-			      GEN_INT (align), NULL_RTX, 1);
-	}
-    }
-  else
+  if (current_function_calls_setjmp)
     {
       rtx dynamic_offset
 	= expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
@@ -1173,6 +1199,14 @@ allocate_dynamic_stack_space (rtx size, 
 
       size = expand_binop (Pmode, add_optab, size, dynamic_offset,
 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
+
+      /* The above dynamic offset cannot be computed statically at this
+	 point, but it will be possible to do so after RTL expansion is
+	 done.  Record how many times we will need to add it.  */
+      if (flag_stack_usage)
+	current_function_dynamic_alloc_count++;
+
+      known_align_valid = false;
     }
 #endif /* SETJMP_VIA_SAVE_AREA */
 
@@ -1189,13 +1223,28 @@ allocate_dynamic_stack_space (rtx size, 
      insns.  Since this is an extremely rare event, we have no reliable
      way of knowing which systems have this problem.  So we avoid even
      momentarily mis-aligning the stack.  */
+  if (!known_align_valid || known_align % PREFERRED_STACK_BOUNDARY != 0)
+    {
+      size = round_push (size);
 
-  /* If we added a variable amount to SIZE,
-     we can no longer assume it is aligned.  */
-#if !defined (SETJMP_VIA_SAVE_AREA)
-  if (MUST_ALIGN || known_align % PREFERRED_STACK_BOUNDARY != 0)
-#endif
-    size = round_push (size);
+      if (flag_stack_usage)
+	{
+	  int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
+	  stack_usage_size = (stack_usage_size + align - 1) / align * align;
+	}
+    }
+
+  /* The size is supposed to be fully adjusted at this point so record it
+     if stack usage info is requested.  */
+  if (flag_stack_usage)
+    {
+      current_function_dynamic_stack_size += stack_usage_size;
+
+      /* ??? This is gross but the only safe stance in the absence
+	 of stack usage oriented flow analysis.  */
+      if (!cannot_accumulate)
+	current_function_has_unbounded_dynamic_stack_size = 1;
+    }
 
   do_pending_stack_adjust ();
 
Index: common.opt
===================================================================
--- common.opt	(revision 114740)
+++ common.opt	(working copy)
@@ -858,6 +858,10 @@ fstack-protector-all
 Common Report RejectNegative Var(flag_stack_protect, 2) VarExists
 Use a stack protection method for every function
 
+fstack-usage
+Common RejectNegative Var(flag_stack_usage)
+Output stack usage information on a per-function basis
+
 fstrength-reduce
 Common
 Does nothing.  Preserved for backward compatibility.
Index: target-def.h
===================================================================
--- target-def.h	(revision 114740)
+++ target-def.h	(working copy)
@@ -469,6 +469,8 @@ Foundation, 51 Franklin Street, Fifth Fl
 #define TARGET_STACK_PROTECT_GUARD  default_stack_protect_guard
 #define TARGET_STACK_PROTECT_FAIL   default_external_stack_protect_fail
 
+#define TARGET_GET_STATIC_STACK_USAGE 0
+
 #define TARGET_ARM_EABI_UNWINDER false
 
 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_false
@@ -666,6 +668,7 @@ Foundation, 51 Franklin Street, Fifth Fl
   TARGET_STDARG_OPTIMIZE_HOOK,			\
   TARGET_STACK_PROTECT_GUARD,			\
   TARGET_STACK_PROTECT_FAIL,			\
+  TARGET_GET_STATIC_STACK_USAGE,		\
   TARGET_INVALID_WITHIN_DOLOOP,			\
   TARGET_VALID_DLLIMPORT_ATTRIBUTE_P,		\
   TARGET_CALLS,					\
Index: config/alpha/alpha.c
===================================================================
--- config/alpha/alpha.c	(revision 114740)
+++ config/alpha/alpha.c	(working copy)
@@ -7496,6 +7496,38 @@ emit_frame_store (unsigned int regno, rt
   emit_frame_store_1 (reg, base_reg, frame_bias, base_ofs, reg);
 }
 
+/* Compute the frame size.  SIZE is the size of the "naked" frame
+   and SA_SIZE is the size of the register save area.  */
+
+static HOST_WIDE_INT
+compute_frame_size (HOST_WIDE_INT size, HOST_WIDE_INT sa_size)
+{
+  if (TARGET_ABI_OPEN_VMS)
+    return ALPHA_ROUND (sa_size 
+			+ (alpha_procedure_type == PT_STACK ? 8 : 0)
+			+ size
+			+ current_function_pretend_args_size);
+  else if (TARGET_ABI_UNICOSMK)
+    /* We have to allocate space for the DSIB if we generate a frame.  */
+    return ALPHA_ROUND (sa_size
+			+ (alpha_procedure_type == PT_STACK ? 48 : 0))
+	   + ALPHA_ROUND (size
+			  + current_function_outgoing_args_size);
+  else
+    return ALPHA_ROUND (current_function_outgoing_args_size)
+	   + sa_size
+	   + ALPHA_ROUND (size
+			  + current_function_pretend_args_size);
+}
+
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+alpha_get_static_stack_usage (void)
+{
+  return compute_frame_size (get_frame_size (), alpha_sa_size ());
+}
+
 /* Write function prologue.  */
 
 /* On vms we have two kinds of functions:
@@ -7529,24 +7561,7 @@ alpha_expand_prologue (void)
   int i;
 
   sa_size = alpha_sa_size ();
-
-  frame_size = get_frame_size ();
-  if (TARGET_ABI_OPEN_VMS)
-    frame_size = ALPHA_ROUND (sa_size
-			      + (alpha_procedure_type == PT_STACK ? 8 : 0)
-			      + frame_size
-			      + current_function_pretend_args_size);
-  else if (TARGET_ABI_UNICOSMK)
-    /* We have to allocate space for the DSIB if we generate a frame.  */
-    frame_size = ALPHA_ROUND (sa_size
-			      + (alpha_procedure_type == PT_STACK ? 48 : 0))
-		 + ALPHA_ROUND (frame_size
-				+ current_function_outgoing_args_size);
-  else
-    frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
-		  + sa_size
-		  + ALPHA_ROUND (frame_size
-				 + current_function_pretend_args_size));
+  frame_size = compute_frame_size (get_frame_size (), sa_size);
 
   if (TARGET_ABI_OPEN_VMS)
     reg_offset = 8;
@@ -7851,23 +7866,7 @@ alpha_start_function (FILE *file, const 
 
   alpha_fnname = fnname;
   sa_size = alpha_sa_size ();
-
-  frame_size = get_frame_size ();
-  if (TARGET_ABI_OPEN_VMS)
-    frame_size = ALPHA_ROUND (sa_size
-			      + (alpha_procedure_type == PT_STACK ? 8 : 0)
-			      + frame_size
-			      + current_function_pretend_args_size);
-  else if (TARGET_ABI_UNICOSMK)
-    frame_size = ALPHA_ROUND (sa_size
-			      + (alpha_procedure_type == PT_STACK ? 48 : 0))
-		 + ALPHA_ROUND (frame_size
-			      + current_function_outgoing_args_size);
-  else
-    frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
-		  + sa_size
-		  + ALPHA_ROUND (frame_size
-				 + current_function_pretend_args_size));
+  frame_size = compute_frame_size (get_frame_size (), sa_size);
 
   if (TARGET_ABI_OPEN_VMS)
     reg_offset = 8;
@@ -8050,23 +8049,7 @@ alpha_expand_epilogue (void)
   int i;
 
   sa_size = alpha_sa_size ();
-
-  frame_size = get_frame_size ();
-  if (TARGET_ABI_OPEN_VMS)
-    frame_size = ALPHA_ROUND (sa_size
-			      + (alpha_procedure_type == PT_STACK ? 8 : 0)
-			      + frame_size
-			      + current_function_pretend_args_size);
-  else if (TARGET_ABI_UNICOSMK)
-    frame_size = ALPHA_ROUND (sa_size
-			      + (alpha_procedure_type == PT_STACK ? 48 : 0))
-		 + ALPHA_ROUND (frame_size
-			      + current_function_outgoing_args_size);
-  else
-    frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
-		  + sa_size
-		  + ALPHA_ROUND (frame_size
-				 + current_function_pretend_args_size));
+  frame_size = compute_frame_size (get_frame_size (), sa_size);
 
   if (TARGET_ABI_OPEN_VMS)
     {
@@ -10751,6 +10734,9 @@ alpha_init_libfuncs (void)
 #define TARGET_MANGLE_FUNDAMENTAL_TYPE alpha_mangle_fundamental_type
 #endif
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE alpha_get_static_stack_usage
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c	(revision 114740)
+++ config/sparc/sparc.c	(working copy)
@@ -344,6 +344,7 @@ static void emit_pic_helper (void);
 static void load_pic_register (bool);
 static int save_or_restore_regs (int, int, rtx, int, int);
 static void emit_save_or_restore_regs (int);
+static HOST_WIDE_INT sparc_get_static_stack_usage (void);
 static void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT);
 static void sparc_asm_function_epilogue (FILE *, HOST_WIDE_INT);
 #ifdef OBJECT_FORMAT_ELF
@@ -484,6 +485,9 @@ static bool fpu_option_set = false;
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE sparc_get_static_stack_usage
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS sparc_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -3727,6 +3731,15 @@ sparc_compute_frame_size (HOST_WIDE_INT 
   return SPARC_STACK_ALIGN (actual_fsize);
 }
 
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+sparc_get_static_stack_usage (void)
+{
+  return sparc_compute_frame_size (get_frame_size (),
+				   current_function_uses_only_leaf_regs);
+}
+
 /* Output any necessary .register pseudo-ops.  */
 
 void
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 114740)
+++ config/i386/i386.c	(working copy)
@@ -1139,6 +1139,7 @@ static int ix86_fp_comparison_cost (enum
 static unsigned int ix86_select_alt_pic_regnum (void);
 static int ix86_save_reg (unsigned int, int);
 static void ix86_compute_frame_layout (struct ix86_frame *);
+static HOST_WIDE_INT ix86_get_static_stack_usage (void);
 static int ix86_comp_type_attributes (tree, tree);
 static int ix86_function_regparm (tree, tree);
 const struct attribute_spec ix86_attribute_table[];
@@ -1365,6 +1366,9 @@ static section *x86_64_elf_select_sectio
 #undef TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE ix86_function_value
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE ix86_get_static_stack_usage
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -5147,6 +5151,22 @@ ix86_compute_frame_layout (struct ix86_f
 #endif
 }
 
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+ix86_get_static_stack_usage (void)
+{
+  struct ix86_frame frame;
+
+  ix86_compute_frame_layout (&frame);
+
+  /* We start at the ARG_POINTER register's address.  */
+  return (UNITS_PER_WORD /* return address */
+	  + (frame_pointer_needed ? UNITS_PER_WORD : 0) /* saved fp */
+	  + frame.nregs * UNITS_PER_WORD /* saved regs */
+	  + frame.to_allocate); /* static frame */
+}
+
 /* Emit code to save registers in the prologue.  */
 
 static void
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c	(revision 114740)
+++ config/ia64/ia64.c	(working copy)
@@ -206,6 +206,7 @@ static void process_epilogue (FILE *, rt
 static int process_set (FILE *, rtx, rtx, bool, bool);
 
 static bool ia64_assemble_integer (rtx, unsigned int, int);
+static HOST_WIDE_INT ia64_get_static_stack_usage (void);
 static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void ia64_output_function_end_prologue (FILE *);
@@ -395,6 +396,9 @@ static const struct attribute_spec ia64_
 #undef TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START ia64_file_start
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE ia64_get_static_stack_usage
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS ia64_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -2568,6 +2572,16 @@ ia64_compute_frame_size (HOST_WIDE_INT s
   current_frame_info.initialized = reload_completed;
 }
 
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+ia64_get_static_stack_usage (void)
+{
+  ia64_compute_frame_size (get_frame_size ());
+  gcc_assert (current_frame_info.initialized);
+  return current_frame_info.total_size;
+}
+
 /* Compute the initial difference between the specified pair of registers.  */
 
 HOST_WIDE_INT
Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c	(revision 114740)
+++ config/rs6000/rs6000.c	(working copy)
@@ -685,6 +685,7 @@ static rtx spe_expand_predicate_builtin 
 static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
 static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
 static rs6000_stack_t *rs6000_stack_info (void);
+static HOST_WIDE_INT rs6000_get_static_stack_usage (void);
 static void debug_stack_info (rs6000_stack_t *);
 
 static rtx altivec_expand_builtin (tree, rtx, bool *);
@@ -1045,6 +1046,9 @@ static const char alt_reg_names[][8] =
 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P rs6000_use_blocks_for_constant_p
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE rs6000_get_static_stack_usage
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -13198,6 +13202,15 @@ rs6000_stack_info (void)
   return info_ptr;
 }
 
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+rs6000_get_static_stack_usage (void)
+{
+  rs6000_stack_t *info = rs6000_stack_info ();
+  return info->total_size;
+}
+
 /* Return true if the current function uses any GPRs in 64-bit SIMD
    mode.  */
 
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 114740)
+++ config/pa/pa.c	(working copy)
@@ -101,6 +101,7 @@ static void store_reg (int, HOST_WIDE_IN
 static void store_reg_modify (int, int, HOST_WIDE_INT);
 static void load_reg (int, HOST_WIDE_INT, int);
 static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);
+static HOST_WIDE_INT pa_get_static_stack_usage (void);
 static void pa_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void update_total_code_bytes (int);
 static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -266,6 +267,9 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS pa_init_builtins
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE pa_get_static_stack_usage
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS hppa_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -3489,6 +3493,15 @@ compute_frame_size (HOST_WIDE_INT size, 
 	  & ~(PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1));
 }
 
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+pa_get_static_stack_usage (void)
+{
+  int fregs_live;
+  return compute_frame_size (get_frame_size (), &fregs_live);
+}
+
 /* Generate the assembly code for function entry.  FILE is a stdio
    stream to output the code to.  SIZE is an int: how many units of
    temporary storage to allocate.
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c	(revision 114740)
+++ config/mips/mips.c	(working copy)
@@ -319,6 +319,7 @@ static void mips_save_restore_reg (enum 
 static void mips_for_each_saved_reg (HOST_WIDE_INT, mips_save_restore_fn);
 static void mips_output_cplocal (void);
 static void mips_emit_loadgp (void);
+static HOST_WIDE_INT mips_get_static_stack_usage (void);
 static void mips_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void mips_set_frame_expr (rtx);
 static rtx mips_frame_set (rtx, rtx);
@@ -1122,6 +1123,9 @@ static struct mips_rtx_cost_data const m
 #undef TARGET_RETURN_IN_MSB
 #define TARGET_RETURN_IN_MSB mips_return_in_msb
 
+#undef TARGET_GET_STATIC_STACK_USAGE
+#define TARGET_GET_STATIC_STACK_USAGE mips_get_static_stack_usage
+
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK mips_output_mi_thunk
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
@@ -6423,6 +6427,14 @@ compute_frame_size (HOST_WIDE_INT size)
   /* Ok, we're done.  */
   return total_size;
 }
+
+/* Return the maximum static stack usage for the current function.  */
+
+static HOST_WIDE_INT
+mips_get_static_stack_usage (void)
+{
+  return compute_frame_size (get_frame_size ());
+}
 
 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
    pointer or argument pointer.  TO is either the stack pointer or
Index: stmt.c
===================================================================
--- stmt.c	(revision 114740)
+++ stmt.c	(working copy)
@@ -1966,7 +1966,8 @@ expand_decl (tree decl)
 	 cannot use it to conclude anything about the alignment of
 	 the size.  */
       address = allocate_dynamic_stack_space (size, NULL_RTX,
-					      TYPE_ALIGN (TREE_TYPE (decl)));
+					      TYPE_ALIGN (TREE_TYPE (decl)),
+					      true);
 
       /* Reference the variable indirect through that rtx.  */
       x = gen_rtx_MEM (DECL_MODE (decl), address);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]