[AArch64] PR target/63596, honor tree-stdarg analysis result to improve VAARG codegen
authorJiong Wang <jiong.wang@arm.com>
Fri, 27 May 2016 13:05:34 +0000 (13:05 +0000)
committerJiong Wang <jiwang@gcc.gnu.org>
Fri, 27 May 2016 13:05:34 +0000 (13:05 +0000)
gcc/
PR target/63596
* config/aarch64/aarch64.c (aarch64_expand_builtin_va_start): Honor
tree-stdarg analysis results.
(aarch64_setup_incoming_varargs): Likewise.

gcc/testsuite/
* gcc.target/aarch64/va_arg_1.c: New testcase.
* gcc.target/aarch64/va_arg_2.c: Likewise.
* gcc.target/aarch64/va_arg_3.c: Likewise.

From-SVN: r236819

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/va_arg_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/va_arg_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/va_arg_3.c [new file with mode: 0644]

index 4e9498beb34b0984b1d5e9eef39fa9bb44a3cea1..55966de403482d372b64013e1158096a8b8c8cc1 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-27  Jiong Wang  <jiong.wang@arm.com>
+
+       PR target/63596
+       * config/aarch64/aarch64.c (aarch64_expand_builtin_va_start): Honor
+       tree-stdarg analysis results.
+       (aarch64_setup_incoming_varargs): Likewise.
+
 2016-05-27  Jiong Wang  <jiong.wang@arm.com>
 
        * config/aarch64/aarch64.c (aarch64_build_builtin_va_list): Initialize
index abb2b7b2bc2ba15bf3cca5cc53518a86f0eb58a7..2315939ebfad3bad3a514b716a8f23df23971537 100644 (file)
@@ -9330,7 +9330,7 @@ aarch64_build_builtin_va_list (void)
                        FIELD_DECL, get_identifier ("__vr_offs"),
                        integer_type_node);
 
-  /* Tell tree-stdarg pass what's our internal offset fields.
+  /* Tell tree-stdarg pass about our internal offset fields.
      NOTE: va_list_gpr/fpr_counter_field are only used for tree comparision
      purpose to identify whether the code is updating va_list internal
      offset fields through irregular way.  */
@@ -9369,15 +9369,17 @@ aarch64_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff;
   tree stack, grtop, vrtop, groff, vroff;
   tree t;
-  int gr_save_area_size;
-  int vr_save_area_size;
+  int gr_save_area_size = cfun->va_list_gpr_size;
+  int vr_save_area_size = cfun->va_list_fpr_size;
   int vr_offset;
 
   cum = &crtl->args.info;
-  gr_save_area_size
-    = (NUM_ARG_REGS - cum->aapcs_ncrn) * UNITS_PER_WORD;
-  vr_save_area_size
-    = (NUM_FP_ARG_REGS - cum->aapcs_nvrn) * UNITS_PER_VREG;
+  if (cfun->va_list_gpr_size)
+    gr_save_area_size = MIN ((NUM_ARG_REGS - cum->aapcs_ncrn) * UNITS_PER_WORD,
+                            cfun->va_list_gpr_size);
+  if (cfun->va_list_fpr_size)
+    vr_save_area_size = MIN ((NUM_FP_ARG_REGS - cum->aapcs_nvrn)
+                            * UNITS_PER_VREG, cfun->va_list_fpr_size);
 
   if (!TARGET_FLOAT)
     {
@@ -9711,7 +9713,8 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   CUMULATIVE_ARGS local_cum;
-  int gr_saved, vr_saved;
+  int gr_saved = cfun->va_list_gpr_size;
+  int vr_saved = cfun->va_list_fpr_size;
 
   /* The caller has advanced CUM up to, but not beyond, the last named
      argument.  Advance a local copy of CUM past the last "real" named
@@ -9719,9 +9722,14 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
   local_cum = *cum;
   aarch64_function_arg_advance (pack_cumulative_args(&local_cum), mode, type, true);
 
-  /* Found out how many registers we need to save.  */
-  gr_saved = NUM_ARG_REGS - local_cum.aapcs_ncrn;
-  vr_saved = NUM_FP_ARG_REGS - local_cum.aapcs_nvrn;
+  /* Found out how many registers we need to save.
+     Honor tree-stdvar analysis results.  */
+  if (cfun->va_list_gpr_size)
+    gr_saved = MIN (NUM_ARG_REGS - local_cum.aapcs_ncrn,
+                   cfun->va_list_gpr_size / UNITS_PER_WORD);
+  if (cfun->va_list_fpr_size)
+    vr_saved = MIN (NUM_FP_ARG_REGS - local_cum.aapcs_nvrn,
+                   cfun->va_list_fpr_size / UNITS_PER_VREG);
 
   if (!TARGET_FLOAT)
     {
@@ -9749,7 +9757,7 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
          /* We can't use move_block_from_reg, because it will use
             the wrong mode, storing D regs only.  */
          machine_mode mode = TImode;
-         int off, i;
+         int off, i, vr_start;
 
          /* Set OFF to the offset from virtual_incoming_args_rtx of
             the first vector register.  The VR save area lies below
@@ -9758,14 +9766,15 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
                           STACK_BOUNDARY / BITS_PER_UNIT);
          off -= vr_saved * UNITS_PER_VREG;
 
-         for (i = local_cum.aapcs_nvrn; i < NUM_FP_ARG_REGS; ++i)
+         vr_start = V0_REGNUM + local_cum.aapcs_nvrn;
+         for (i = 0; i < vr_saved; ++i)
            {
              rtx ptr, mem;
 
              ptr = plus_constant (Pmode, virtual_incoming_args_rtx, off);
              mem = gen_frame_mem (mode, ptr);
              set_mem_alias_set (mem, get_varargs_alias_set ());
-             aarch64_emit_move (mem, gen_rtx_REG (mode, V0_REGNUM + i));
+             aarch64_emit_move (mem, gen_rtx_REG (mode, vr_start + i));
              off += UNITS_PER_VREG;
            }
        }
index dece85ffe4e6e55d6ff5f97b524cf013de997241..70b372510a9b3993197d202fb5b1210f1faf3958 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-27  Jiong Wang  <jiong.wang@arm.com>
+
+       PR target/63596
+       * gcc.target/aarch64/va_arg_1.c: New testcase.
+       * gcc.target/aarch64/va_arg_2.c: Likewise.
+       * gcc.target/aarch64/va_arg_3.c: Likewise.
+
 2016-05-27  Jiong Wang  <jiong.wang@arm.com>
 
        * gcc.dg/tree-ssa/stdarg-2.c: Enable all testcases for AArch64.
diff --git a/gcc/testsuite/gcc.target/aarch64/va_arg_1.c b/gcc/testsuite/gcc.target/aarch64/va_arg_1.c
new file mode 100644 (file)
index 0000000..e8e3cda
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 --save-temps" } */
+
+int
+f (int a, ...)
+{
+  /* { dg-final { scan-assembler-not "str" } } */
+  return a;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/va_arg_2.c b/gcc/testsuite/gcc.target/aarch64/va_arg_2.c
new file mode 100644 (file)
index 0000000..f5c46cb
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 --save-temps" } */
+
+int
+foo (char *fmt, ...)
+{
+  int d;
+  __builtin_va_list ap;
+
+  __builtin_va_start (ap, fmt);
+  d = __builtin_va_arg (ap, int);
+  __builtin_va_end (ap);
+
+  /* { dg-final { scan-assembler-not "x7" } } */
+  return d;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/va_arg_3.c b/gcc/testsuite/gcc.target/aarch64/va_arg_3.c
new file mode 100644 (file)
index 0000000..7f7601a
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 --save-temps" } */
+
+int d2i (double a);
+
+int
+foo (char *fmt, ...)
+{
+  int d, e;
+  double f, g;
+  __builtin_va_list ap;
+
+  __builtin_va_start (ap, fmt);
+  d = __builtin_va_arg (ap, int);
+  f = __builtin_va_arg (ap, double);
+  g = __builtin_va_arg (ap, double);
+  d += d2i (f);
+  d += d2i (g);
+  __builtin_va_end (ap);
+
+  /* { dg-final { scan-assembler-not "x7" } } */
+  /* { dg-final { scan-assembler-not "q7" } } */
+  return d;
+}
+
+/* { dg-final { cleanup-saved-temps } } */