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] Avoid using alloca for stack_usage_map if argument size is excessively large


Hi!

GCC will not compile programs that pass excessively large arguments
by value, because it uses alloca unconditionally for stack_usage_map,
no matter how big the arguments are.
It is true that for running such program you need to increase
stack limits, but programs aren't necessarily compiled on the same
system as they are run on, so IMHO using xmalloc/free for really big
argument sizes certainly doesn't hurt.  256K is a random number, on the
other side making it --param sounds overkill to me.
Ok for HEAD?

2005-06-22  Jakub Jelinek  <jakub@redhat.com>

	* calls.c (expand_call, emit_library_call_value_1): Use xmalloc/free
	instead of alloca for really big argument sizes.

	* gcc.c-torture/compile/20050622-1.c: New test.

--- gcc/calls.c.jj	2005-05-16 09:44:21.000000000 +0200
+++ gcc/calls.c	2005-06-22 11:16:28.000000000 +0200
@@ -1864,6 +1864,7 @@ expand_call (tree exp, rtx target, int i
 
   int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
   char *initial_stack_usage_map = stack_usage_map;
+  char *stack_usage_map_buf = NULL;
 
   int old_stack_allocated;
 
@@ -2360,7 +2361,16 @@ expand_call (tree exp, rtx target, int i
 		  highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
 						     needed);
 #endif
-		  stack_usage_map = alloca (highest_outgoing_arg_in_use);
+		  if (highest_outgoing_arg_in_use >= 262144)
+		    {
+		      if (stack_usage_map_buf)
+			free (stack_usage_map_buf);
+		      stack_usage_map_buf
+			= xmalloc (highest_outgoing_arg_in_use);
+		      stack_usage_map = stack_usage_map_buf;
+		    }
+		  else
+		    stack_usage_map = alloca (highest_outgoing_arg_in_use);
 
 		  if (initial_highest_arg_in_use)
 		    memcpy (stack_usage_map, initial_stack_usage_map,
@@ -2465,7 +2475,16 @@ expand_call (tree exp, rtx target, int i
 		    = stack_arg_under_construction;
 		  stack_arg_under_construction = 0;
 		  /* Make a new map for the new argument list.  */
-		  stack_usage_map = alloca (highest_outgoing_arg_in_use);
+		  if (highest_outgoing_arg_in_use >= 262144)
+		    {
+		      if (stack_usage_map_buf)
+			free (stack_usage_map_buf);
+		      stack_usage_map_buf
+			= xmalloc (highest_outgoing_arg_in_use);
+		      stack_usage_map = stack_usage_map_buf;
+		    }
+		  else
+		    stack_usage_map = alloca (highest_outgoing_arg_in_use);
 		  memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
 		  highest_outgoing_arg_in_use = 0;
 		}
@@ -3019,6 +3038,9 @@ expand_call (tree exp, rtx target, int i
       emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx);
     }
 
+  if (stack_usage_map_buf)
+    free (stack_usage_map_buf);
+
   return target;
 }
 
@@ -3213,6 +3235,7 @@ emit_library_call_value_1 (int retval, r
   /* Size of the stack reserved for parameter registers.  */
   int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
   char *initial_stack_usage_map = stack_usage_map;
+  char *stack_usage_map_buf = NULL;
 
   rtx struct_value = targetm.calls.struct_value_rtx (0, 0);
 
@@ -3491,7 +3514,13 @@ emit_library_call_value_1 (int retval, r
       highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
 					 needed);
 #endif
-      stack_usage_map = alloca (highest_outgoing_arg_in_use);
+      if (highest_outgoing_arg_in_use >= 262144)
+	{
+	  stack_usage_map_buf = xmalloc (highest_outgoing_arg_in_use);
+	  stack_usage_map = stack_usage_map_buf;
+	}
+      else
+	stack_usage_map = alloca (highest_outgoing_arg_in_use);
 
       if (initial_highest_arg_in_use)
 	memcpy (stack_usage_map, initial_stack_usage_map,
@@ -3845,6 +3874,9 @@ emit_library_call_value_1 (int retval, r
       stack_usage_map = initial_stack_usage_map;
     }
 
+  if (stack_usage_map_buf)
+    free (stack_usage_map_buf);
+
   return value;
 
 }
--- gcc/testsuite/gcc.c-torture/compile/20050622-1.c.jj	2005-06-22 11:18:01.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/compile/20050622-1.c	2005-06-22 11:23:02.000000000 +0200
@@ -0,0 +1,16 @@
+#if __SCHAR_MAX__ == 127 && __INT_MAX__ >= 2147483647
+struct S { char buf[72*1024*1024]; };
+#else
+struct S { char buf[64]; };
+#endif
+
+extern void bar (struct S);
+
+struct S s;
+
+int
+foo (void)
+{
+  bar (s);
+  return 0;
+}

	Jakub


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