function.c (assign_parm_setup_reg): For a parameter passed by pointer and which can...
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 30 Aug 2013 11:13:20 +0000 (11:13 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 30 Aug 2013 11:13:20 +0000 (11:13 +0000)
* function.c (assign_parm_setup_reg): For a parameter passed by pointer
and which can live in a register, always retrieve the value on entry.
* var-tracking.c (add_stores): Treat the copy on entry for a parameter
passed by invisible reference specially.
(emit_notes_in_bb) <MO_VAL_USE>: Emit notes before the instruction.
(vt_add_function_parameter): Correctly deal with a parameter passed by
invisible reference.

From-SVN: r202102

gcc/ChangeLog
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/guality/param-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/param-2.c [new file with mode: 0644]
gcc/var-tracking.c

index 171988a5c5aaecf775fdb890501acfbcf2487343..9321385270661e8264bed12c0c1c97ae6bc24aab 100644 (file)
@@ -1,4 +1,14 @@
-2013-08-29  Jan Hubicka  <jh@suse.cz>
+2013-08-30  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * function.c (assign_parm_setup_reg): For a parameter passed by pointer
+       and which can live in a register, always retrieve the value on entry.
+       * var-tracking.c (add_stores): Treat the copy on entry for a parameter
+       passed by invisible reference specially.
+       (emit_notes_in_bb) <MO_VAL_USE>: Emit notes before the instruction.
+       (vt_add_function_parameter): Correctly deal with a parameter passed by
+       invisible reference.
+
+2013-08-30  Jan Hubicka  <jh@suse.cz>
 
        * tree.c (set_call_expr_flags): Fix handling of TM_PURE.
 
index c1550a25393d0ee24ced28f5a02c7ac49512ae61..08731e845022996a3dafddd742a421b02124569b 100644 (file)
@@ -3101,17 +3101,27 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
     emit_move_insn (parmreg, validated_mem);
 
   /* If we were passed a pointer but the actual value can safely live
-     in a register, put it in one.  */
-  if (data->passed_pointer
-      && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
-      /* If by-reference argument was promoted, demote it.  */
-      && (TYPE_MODE (TREE_TYPE (parm)) != GET_MODE (DECL_RTL (parm))
-         || use_register_for_decl (parm)))
+     in a register, retrieve it and use it directly.  */
+  if (data->passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode)
     {
       /* We can't use nominal_mode, because it will have been set to
         Pmode above.  We must use the actual mode of the parm.  */
-      parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
-      mark_user_reg (parmreg);
+      if (use_register_for_decl (parm))
+       {
+         parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
+         mark_user_reg (parmreg);
+       }
+      else
+       {
+         int align = STACK_SLOT_ALIGNMENT (TREE_TYPE (parm),
+                                           TYPE_MODE (TREE_TYPE (parm)),
+                                           TYPE_ALIGN (TREE_TYPE (parm)));
+         parmreg
+           = assign_stack_local (TYPE_MODE (TREE_TYPE (parm)),
+                                 GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parm))),
+                                 align);
+         set_mem_attributes (parmreg, parm, 1);
+       }
 
       if (GET_MODE (parmreg) != GET_MODE (DECL_RTL (parm)))
        {
index 68861a8e1ab0ca276fa41575c41d5ad53d6a8023..53aeadcd0ed4e4da09058c61ef64f01869e16dbf 100644 (file)
@@ -1,3 +1,8 @@
+2013-08-30  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.dg/guality/param-1.c: New test.
+       * gcc.dg/guality/param-2.c: Likewise.
+
 2013-08-30  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/58228
diff --git a/gcc/testsuite/gcc.dg/guality/param-1.c b/gcc/testsuite/gcc.dg/guality/param-1.c
new file mode 100644 (file)
index 0000000..480ad3c
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-options "-g" } */
+/* { dg-skip-if "" { *-*-* }  { "*" } { "-O0" } } */
+
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+__attribute__((noinline, noclone)) int
+sub (int a, int b)
+{
+  return a - b;
+}
+
+typedef struct { uintptr_t pa; uintptr_t pb; } fatp_t
+  __attribute__ ((aligned (2 * __alignof__ (uintptr_t))));
+
+__attribute__((noinline, noclone)) void
+foo (fatp_t str, int a, int b)
+{
+  int i = sub (a, b);
+  if (i == 0)           /* BREAK */
+    i = sub (b, a);
+}
+
+int
+main (void)
+{
+  fatp_t ptr = { 31415927, 27182818 };
+  foo (ptr, 1, 2);
+  return 0;
+}
+
+/* { dg-final { gdb-test 20 "str.pa" "31415927" } } */
+/* { dg-final { gdb-test 20 "str.pb" "27182818" } } */
diff --git a/gcc/testsuite/gcc.dg/guality/param-2.c b/gcc/testsuite/gcc.dg/guality/param-2.c
new file mode 100644 (file)
index 0000000..64678bd
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-options "-g -fno-var-tracking-assignments" } */
+/* { dg-skip-if "" { *-*-* }  { "*" } { "-O0" "-O1" } } */
+
+typedef __UINTPTR_TYPE__ uintptr_t;
+
+__attribute__((noinline, noclone)) int
+sub (int a, int b)
+{
+  return a - b;
+}
+
+typedef struct { uintptr_t pa; uintptr_t pb; } fatp_t
+  __attribute__ ((aligned (2 * __alignof__ (uintptr_t))));
+
+__attribute__((noinline, noclone)) void
+foo (fatp_t str, int a, int b)
+{
+  int i = sub (a, b);
+  if (i == 0)           /* BREAK */
+    foo (str, a - 1, b);
+}
+
+int
+main (void)
+{
+  fatp_t ptr = { 31415927, 27182818 };
+  foo (ptr, 1, 2);
+  return 0;
+}
+
+/* { dg-final { gdb-test 20 "str.pa" "31415927" } } */
+/* { dg-final { gdb-test 20 "str.pb" "27182818" } } */
index d82d2621fc69ea7dbdff5b9547fe200102c46206..cf1f08bc252cb6badf0a3ee59e0cfdd6c60a8a1b 100644 (file)
@@ -5836,7 +5836,24 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
            {
              rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
              if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
-               mo.type = MO_COPY;
+               {
+                 /* If this is an instruction copying (part of) a parameter
+                    passed by invisible reference to its register location,
+                    pretend it's a SET so that the initial memory location
+                    is discarded, as the parameter register can be reused
+                    for other purposes and we do not track locations based
+                    on generic registers.  */
+                 if (MEM_P (src)
+                     && REG_EXPR (loc)
+                     && TREE_CODE (REG_EXPR (loc)) == PARM_DECL
+                     && DECL_MODE (REG_EXPR (loc)) != BLKmode
+                     && MEM_P (DECL_INCOMING_RTL (REG_EXPR (loc)))
+                     && XEXP (DECL_INCOMING_RTL (REG_EXPR (loc)), 0)
+                        != arg_pointer_rtx)
+                   mo.type = MO_SET;
+                 else
+                   mo.type = MO_COPY;
+               }
              else
                mo.type = MO_SET;
              mo.u.loc = xexpr;
@@ -9086,7 +9103,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
              else
                var_mem_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
 
-             emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
+             emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars);
            }
            break;
 
@@ -9533,12 +9550,11 @@ vt_add_function_parameter (tree parm)
 
   if (!vt_get_decl_and_offset (incoming, &decl, &offset))
     {
-      if (REG_P (incoming) || MEM_P (incoming))
+      if (MEM_P (incoming))
        {
          /* This means argument is passed by invisible reference.  */
          offset = 0;
          decl = parm;
-         incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
        }
       else
        {