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] Optimize stdarg functions with void * or char * va_list


On Tue, Sep 28, 2004 at 03:35:43PM -0700, Richard Henderson wrote:
> For future improvement, think about how we can handle e.g. sparc64,
> which uses a plain pointer (and thus has no fields to reference) but
> still could make use of knowing that a maximum of 3 registers are 
> accessed.

The following patch implements that.
This patch contains just the infrastructure, not the backend changes
to avoid saving unneeded registers.

Backends that use void * or char * va_list type shouldn't set
va_list_gpr_counter_field or va_list_fpr_counter_field, all they
need is just to look at cfun->va_list_gpr_size this pass computes
(va_list_fpr_size is not used on those arches, as void */char *
va_list is just one counter, not two).

2004-09-29  Jakub Jelinek  <jakub@redhat.com>

	* tree-stdarg.c (struct stdarg_info): Add va_list_escape_vars
	and va_list_escapes fields.
	(va_list_counter_bump): Handle WITH_SIZE_EXPR.
	Handle COUNTER being a VAR_DECL.
	(va_list_ptr_read, va_list_ptr_write, check_va_list_escapes,
	check_all_va_list_escapes): New functions.
	(execute_optimize_stdarg): Handle void * or char * va_list.

	* gcc.dg/tree-ssa/stdarg-2.c: Compile on all architectures,
	add { target x86_64-*-* powerpc-*-* } to current dg-final
	lines.  Add dg-final lines for void * or char * va_list
	architectures.
	* gcc.dg/tree-ssa/stdarg-3.c: Likewise.
	* gcc.dg/tree-ssa/stdarg-4.c: Likewise.

--- gcc/tree-stdarg.c.jj	2004-09-29 11:43:25.000000000 +0200
+++ gcc/tree-stdarg.c	2004-09-29 22:27:45.213207708 +0200
@@ -40,9 +40,10 @@ Boston, MA 02111-1307, USA.  */
 
 struct stdarg_info
 {
-  bitmap va_list_vars;
+  bitmap va_list_vars, va_list_escape_vars;
   basic_block va_start_bb, bb;
   int compute_sizes, va_start_count;
+  bool va_list_escapes;
 };
 
 /* Return true if basic block VA_ARG_BB is dominated by VA_START_BB and
@@ -127,6 +128,8 @@ va_list_counter_bump (tree counter, tree
     return 0;
 
   rhs1 = TREE_OPERAND (plus_stmt, 1);
+  if (TREE_CODE (rhs1) == WITH_SIZE_EXPR)
+    rhs1 = TREE_OPERAND (rhs1, 0);
 
   if (TREE_CODE (rhs1) != PLUS_EXPR
       || TREE_CODE (TREE_OPERAND (rhs1, 0)) != SSA_NAME
@@ -142,6 +145,9 @@ va_list_counter_bump (tree counter, tree
     return 0;
 
   counter1 = TREE_OPERAND (load_stmt, 1);
+  if (TREE_CODE (counter1) == WITH_SIZE_EXPR)
+    counter1 = TREE_OPERAND (counter1, 0);
+
   if (TREE_CODE (counter) != TREE_CODE (counter1))
     return 0;
 
@@ -152,7 +158,7 @@ va_list_counter_bump (tree counter, tree
 	  || TREE_OPERAND (counter, 1) != TREE_OPERAND (counter1, 1))
 	return 0;
     }
-  else
+  else if (counter != counter1)
     return 0;
 
   return tree_low_cst (TREE_OPERAND (rhs1, 1), 1);
@@ -267,6 +273,192 @@ va_list_counter_struct_op (struct stdarg
 }
 
 
+/* Check for TEM = AP.  Return true if found and the caller shouldn't
+   search for va_list references in the statement.  */
+
+static bool
+va_list_ptr_read (struct stdarg_info *si, tree ap, tree tem)
+{
+  if (TREE_CODE (ap) != VAR_DECL
+      || !bitmap_bit_p (si->va_list_vars, var_ann (ap)->uid))
+    return false;
+
+  if (TREE_CODE (tem) != SSA_NAME
+      || bitmap_bit_p (si->va_list_vars,
+		       var_ann (SSA_NAME_VAR (tem))->uid)
+      || is_global_var (SSA_NAME_VAR (tem)))
+    return false;
+
+  if (si->compute_sizes < 0)
+    {
+      si->compute_sizes = 0;
+      if (si->va_start_count == 1
+	  && reachable_at_most_once (si->bb, si->va_start_bb))
+	si->compute_sizes = 1;
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	fprintf (dump_file,
+		 "bb%d will %sbe executed at most once for each va_start "
+		 "in bb%d\n", si->bb->index, si->compute_sizes ? "" : "not ",
+		 si->va_start_bb->index);
+    }
+
+  /* For void * or char * va_list types, there is just one counter.
+     If va_arg is used in a loop, we don't know how many registers need
+     saving.  */
+  if (! si->compute_sizes)
+    return false;
+
+  /* Note the temporary, as we need to track whether it doesn't escape
+     the current function.  */
+  bitmap_set_bit (si->va_list_escape_vars,
+		  var_ann (SSA_NAME_VAR (tem))->uid);
+  return true;
+}
+
+
+/* Check for:
+     tem1 = AP;
+     TEM2 = tem1 + CST;
+     AP = TEM2;
+   sequence and update cfun->va_list_gpr_size.  Return true if found.  */
+
+static bool
+va_list_ptr_write (struct stdarg_info *si, tree ap, tree tem2)
+{
+  unsigned HOST_WIDE_INT increment;
+
+  if (TREE_CODE (ap) != VAR_DECL
+      || !bitmap_bit_p (si->va_list_vars, var_ann (ap)->uid))
+    return false;
+
+  if (TREE_CODE (tem2) != SSA_NAME
+      || bitmap_bit_p (si->va_list_vars, var_ann (SSA_NAME_VAR (tem2))->uid))
+    return false;
+
+  if (si->compute_sizes <= 0)
+    return false;
+
+  increment = va_list_counter_bump (ap, tem2);
+  if (increment == 0)
+    return false;
+
+  if (cfun->va_list_gpr_size + increment < VA_LIST_MAX_GPR_SIZE)
+    cfun->va_list_gpr_size += increment;
+  else
+    cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE;
+
+  return true;
+}
+
+
+/* If RHS is X, (some type *) X or X + CST for X a temporary variable
+   containing value of some va_list variable plus optionally some constant,
+   either set si->va_list_escapes or add LHS to si->va_list_escape_vars,
+   depending whether LHS is a function local temporary.  */
+
+static void
+check_va_list_escapes (struct stdarg_info *si, tree lhs, tree rhs)
+{
+  if (! POINTER_TYPE_P (TREE_TYPE (rhs)))
+    return;
+
+  if ((TREE_CODE (rhs) == PLUS_EXPR
+       && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
+      || TREE_CODE (rhs) == NOP_EXPR
+      || TREE_CODE (rhs) == CONVERT_EXPR)
+    rhs = TREE_OPERAND (rhs, 0);
+
+  if (TREE_CODE (rhs) != SSA_NAME
+      || ! bitmap_bit_p (si->va_list_escape_vars,
+			 var_ann (SSA_NAME_VAR (rhs))->uid))
+    return;
+
+  if (TREE_CODE (lhs) != SSA_NAME || is_global_var (SSA_NAME_VAR (lhs)))
+    si->va_list_escapes = true;
+  else
+    bitmap_set_bit (si->va_list_escape_vars,
+		    var_ann (SSA_NAME_VAR (lhs))->uid);
+}
+
+
+/* Check all uses of temporaries from si->va_list_escape_vars bitmap.
+   Return true if va_list might be escaping.  */
+
+static bool
+check_all_va_list_escapes (struct stdarg_info *si)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator i;
+
+      for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
+	{
+	  tree stmt = bsi_stmt (i), use;
+	  ssa_op_iter iter;
+
+	  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_USES)
+	    {
+	      if (! bitmap_bit_p (si->va_list_escape_vars,
+				  var_ann (SSA_NAME_VAR (use))->uid))
+		continue;
+
+	      if (TREE_CODE (stmt) == MODIFY_EXPR)
+		{
+		  tree lhs = TREE_OPERAND (stmt, 0);
+		  tree rhs = TREE_OPERAND (stmt, 1);
+
+		  if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
+		    rhs = TREE_OPERAND (rhs, 0);
+
+		  /* x = *ap_temp;  */
+		  if (TREE_CODE (rhs) == INDIRECT_REF
+		      && TREE_OPERAND (rhs, 0) == use)
+		    continue;
+
+		  /* va_arg sequences may contain
+		     other_ap_temp = ap_temp;
+		     other_ap_temp = ap_temp + constant;
+		     other_ap_temp = (some_type *) ap_temp;
+		     ap = ap_temp;
+		     statements.  */
+		  if ((TREE_CODE (rhs) == PLUS_EXPR
+		       && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
+		      || TREE_CODE (rhs) == NOP_EXPR
+		      || TREE_CODE (rhs) == CONVERT_EXPR)
+		    rhs = TREE_OPERAND (rhs, 0);
+
+		  if (rhs == use)
+		    {
+		      if (TREE_CODE (lhs) == SSA_NAME
+			  && bitmap_bit_p (si->va_list_escape_vars,
+					   var_ann (SSA_NAME_VAR (lhs))->uid))
+			continue;
+
+		      if (TREE_CODE (lhs) == VAR_DECL
+			  && bitmap_bit_p (si->va_list_vars,
+					   var_ann (lhs)->uid))
+			continue;
+		    }
+		}
+
+	      if (dump_file && (dump_flags & TDF_DETAILS))
+		{
+		  fputs ("va_list escapes in ", dump_file);
+		  print_generic_expr (dump_file, stmt, dump_flags);
+		  fputc ('\n', dump_file);
+		}
+	      return true;
+	    }
+        }
+    }
+
+  return false;
+}
+
+
 /* Return true if this optimization pass should be done.
    It makes only sense for stdarg functions.  */
 
@@ -275,7 +467,7 @@ gate_optimize_stdarg (void)
 {
   /* This optimization is only for stdarg functions.  */
   return current_function_stdarg != 0;
-}  
+}
 
 
 /* Entry point to the stdarg optimization pass.  */
@@ -285,6 +477,7 @@ execute_optimize_stdarg (void)
 {
   basic_block bb;
   bool va_list_escapes = false;
+  bool va_list_simple_ptr;
   struct stdarg_info si;
   const char *funcname = NULL;
 
@@ -292,10 +485,15 @@ execute_optimize_stdarg (void)
   cfun->va_list_fpr_size = 0;
   memset (&si, 0, sizeof (si));
   si.va_list_vars = BITMAP_XMALLOC ();
+  si.va_list_escape_vars = BITMAP_XMALLOC ();
 
   if (dump_file)
     funcname = lang_hooks.decl_printable_name (current_function_decl, 2);
 
+  va_list_simple_ptr = POINTER_TYPE_P (va_list_type_node)
+		       && (TREE_TYPE (va_list_type_node) == void_type_node
+			   || TREE_TYPE (va_list_type_node) == char_type_node);
+
   FOR_EACH_BB (bb)
     {
       block_stmt_iterator i;
@@ -326,7 +524,7 @@ execute_optimize_stdarg (void)
 	      break;
 	    }
 
-	  ap = TREE_OPERAND (ap, 0);	    
+	  ap = TREE_OPERAND (ap, 0);
 	  if (is_global_var (ap))
 	    {
 	      va_list_escapes = true;
@@ -353,15 +551,29 @@ execute_optimize_stdarg (void)
   if (va_list_escapes)
     goto finish;
 
-  /* If the backend didn't tell us what the counter fields are, there is
-     nothing more we can do.  */
-  if (va_list_gpr_counter_field == NULL_TREE
+  /* For void * or char * va_list, something useful can be done only
+     if there is just one va_start.  */
+  if (va_list_simple_ptr && si.va_start_count > 1)
+    {
+      va_list_escapes = true;
+      goto finish;
+    }
+
+  /* For struct * va_list, if the backend didn't tell us what the counter fields
+     are, there is nothing more we can do.  */
+  if (!va_list_simple_ptr
+      && va_list_gpr_counter_field == NULL_TREE
       && va_list_fpr_counter_field == NULL_TREE)
     {
       va_list_escapes = true;
       goto finish;
     }
 
+  /* For void * or char * va_list there is just one counter
+     (va_list itself).  Use VA_LIST_GPR_SIZE for it.  */
+  if (va_list_simple_ptr)
+    cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE;
+
   FOR_EACH_BB (bb)
     {
       block_stmt_iterator i;
@@ -396,13 +608,33 @@ execute_optimize_stdarg (void)
 	      if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
 		rhs = TREE_OPERAND (rhs, 0);
 
-	      /* Check for ap[0].field = temp.  */
-	      if (va_list_counter_struct_op (&si, lhs, rhs, true))
-		continue;
+	      if (va_list_simple_ptr)
+		{
+		  /* Check for tem = ap.  */
+		  if (va_list_ptr_read (&si, rhs, lhs))
+		    continue;
+
+		  /* Check for the last insn in:
+		     tem1 = ap;
+		     tem2 = tem1 + CST;
+		     ap = tem2;
+		     sequence.  */
+		  else if (va_list_ptr_write (&si, lhs, rhs))
+		    continue;
 
-	      /* Check for temp = ap[0].field.  */
-	      else if (va_list_counter_struct_op (&si, rhs, lhs, false))
-		continue;
+		  else
+		    check_va_list_escapes (&si, lhs, rhs);
+		}
+	      else
+		{
+		  /* Check for ap[0].field = temp.  */
+		  if (va_list_counter_struct_op (&si, lhs, rhs, true))
+		    continue;
+
+		  /* Check for temp = ap[0].field.  */
+		  else if (va_list_counter_struct_op (&si, rhs, lhs, false))
+		    continue;
+		}
 	    }
 
 	  /* All other uses of va_list are either va_copy (that is not handled
@@ -411,7 +643,9 @@ execute_optimize_stdarg (void)
 	     escape the function and therefore va_start needs to set it up
 	     fully), or some unexpected use of va_list.  None of these should
 	     happen in a gimplified VA_ARG_EXPR.  */
-	  if (walk_tree (&stmt, find_va_list_reference, si.va_list_vars, NULL))
+	  if (si.va_list_escapes
+	      || walk_tree (&stmt, find_va_list_reference,
+			    si.va_list_vars, NULL))
 	    {
 	      if (dump_file && (dump_flags & TDF_DETAILS))
 		{
@@ -427,6 +661,12 @@ execute_optimize_stdarg (void)
 	break;
     }
 
+  if (! va_list_escapes
+      && va_list_simple_ptr
+      && bitmap_first_set_bit (si.va_list_escape_vars) >= 0
+      && check_all_va_list_escapes (&si))
+    va_list_escapes = true;
+
 finish:
   if (va_list_escapes)
     {
@@ -434,6 +674,7 @@ finish:
       cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE;
     }
   BITMAP_XFREE (si.va_list_vars);
+  BITMAP_XFREE (si.va_list_escape_vars);
   if (dump_file)
     {
       fprintf (dump_file, "%s: va_list escapes %d, needs to save ",
--- gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c.jj	2004-09-29 11:43:25.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c	2004-09-29 22:19:28.638321962 +0200
@@ -1,6 +1,8 @@
-/* This test is only for architectures that save general and floating point
-   registers separately in stdarg functions.  */
-/* { dg-do compile { target x86_64-*-* powerpc-*-* } } */
+/* First dg-final line after each function is for architectures that use
+   a struct {...} va_list[1] with separate GPR and FPR counters in the
+   structure.  Second dg-final line is for architectures that use void *
+   or char * va_list.  */
+/* { dg-do compile } */
 /* { dg-options "-O2 -fdump-tree-stdarg" } */
 
 #include <stdarg.h>
@@ -21,7 +23,8 @@ f1 (int i, ...)
     x = va_arg (ap, long);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f2 (int i, ...)
@@ -32,7 +35,8 @@ f2 (int i, ...)
     d = va_arg (ap, double);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 /* Here va_arg can be executed at most as many times as va_start.
    Only one GPR needs to be saved.  */
@@ -49,7 +53,8 @@ f3 (int i, ...)
       bar (x);
     }
 }
-/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f4 (int i, ...)
@@ -64,4 +69,5 @@ f4 (int i, ...)
       bar (d + 2.5);
     }
 }
-/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
--- gcc/testsuite/gcc.dg/tree-ssa/stdarg-3.c.jj	2004-09-29 11:43:25.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/stdarg-3.c	2004-09-29 22:19:23.040315524 +0200
@@ -1,6 +1,8 @@
-/* This test is only for architectures that save general and floating point
-   registers separately in stdarg functions.  */
-/* { dg-do compile { target x86_64-*-* powerpc-*-* } } */
+/* First dg-final line after each function is for architectures that use
+   a struct {...} va_list[1] with separate GPR and FPR counters in the
+   structure.  Second dg-final line is for architectures that use void *
+   or char * va_list.  */
+/* { dg-do compile } */
 /* { dg-options "-O2 -fdump-tree-stdarg" } */
 
 #include <stdarg.h>
@@ -18,7 +20,8 @@ f1 (int i, ...)
   x = va_arg (gap, long);
   va_end (gap);
 }
-/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f2 (int i, ...)
@@ -27,7 +30,8 @@ f2 (int i, ...)
   bar (i);
   va_end (gap);
 }
-/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 /* tree-stdarg.c only handles va_list variables, not arrays of them or
    va_list fields embedded in structures.  */
@@ -39,7 +43,8 @@ f3 (int i, ...)
   x = va_arg (aps[4], long);
   va_end (aps[4]);
 }
-/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f4 (int i, ...)
@@ -49,7 +54,8 @@ f4 (int i, ...)
   bar (i);
   va_end (aps[4]);
 }
-/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f5 (int i, ...)
@@ -59,7 +65,8 @@ f5 (int i, ...)
   foo (i, aps[4]);
   va_end (aps[4]);
 }
-/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 struct A { int i; va_list g; va_list h[2]; };
 
@@ -71,7 +78,8 @@ f6 (int i, ...)
   x = va_arg (a.g, long);
   va_end (a.g);
 }
-/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f7 (int i, ...)
@@ -81,7 +89,8 @@ f7 (int i, ...)
   bar (i);
   va_end (a.g);
 }
-/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f8 (int i, ...)
@@ -91,7 +100,8 @@ f8 (int i, ...)
   foo (i, a.g);
   va_end (a.g);
 }
-/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f10 (int i, ...)
@@ -101,7 +111,8 @@ f10 (int i, ...)
   x = va_arg (a.h[1], long);
   va_end (a.h[1]);
 }
-/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f11 (int i, ...)
@@ -111,7 +122,8 @@ f11 (int i, ...)
   bar (i);
   va_end (a.h[1]);
 }
-/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f12 (int i, ...)
@@ -121,4 +133,5 @@ f12 (int i, ...)
   foo (i, a.h[1]);
   va_end (a.h[1]);
 }
-/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
--- gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c.jj	2004-09-29 11:43:25.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c	2004-09-29 22:20:11.009801642 +0200
@@ -1,6 +1,8 @@
-/* This test is only for architectures that save general and floating point
-   registers separately in stdarg functions.  */
-/* { dg-do compile { target x86_64-*-* powerpc-*-* } } */
+/* First dg-final line after each function is for architectures that use
+   a struct {...} va_list[1] with separate GPR and FPR counters in the
+   structure.  Second dg-final line is for architectures that use void *
+   or char * va_list.  */
+/* { dg-do compile } */
 /* { dg-options "-O2 -fdump-tree-stdarg" } */
 
 #include <stdarg.h>
@@ -19,7 +21,8 @@ f1 (int i, ...)
   va_start (ap, i);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f2 (int i, ...)
@@ -33,7 +36,8 @@ f2 (int i, ...)
 }
 /* Assume the counters can be number of registers or bytes on 32-bit
    architecture or bytes on 64-bit architecture.  */
-/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f3 (int i, ...)
@@ -43,7 +47,8 @@ f3 (int i, ...)
   d = va_arg (ap, double);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f4 (int i, ...)
@@ -54,7 +59,8 @@ f4 (int i, ...)
   foo (i, ap);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f5 (int i, ...)
@@ -66,7 +72,8 @@ f5 (int i, ...)
   va_end (ap);
   va_end (gap);
 }
-/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f6 (int i, ...)
@@ -80,7 +87,8 @@ f6 (int i, ...)
   bar (x);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f7 (int i, ...)
@@ -91,7 +99,8 @@ f7 (int i, ...)
   bar (6);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f8 (int i, ...)
@@ -104,7 +113,8 @@ f8 (int i, ...)
   bar (x);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f9 (int i, ...)
@@ -115,7 +125,8 @@ f9 (int i, ...)
   bar (6);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
 
 void
 f10 (int i, ...)
@@ -128,4 +139,20 @@ f10 (int i, ...)
   bar (x);
   va_end (ap);
 }
-/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" } } */
+/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */
+
+void
+f11 (int i, ...)
+{
+  va_list ap;
+  va_start (ap, i);
+  bar (d);
+  x = va_arg (ap, long);
+  x += va_arg (ap, long);
+  x += va_arg (ap, long);
+  bar (x);
+  va_end (ap);
+}
+/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target x86_64-*-* powerpc-*-* } } } */
+/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* i?86-*-* } } } */


	Jakub


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