aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2013-08-30 11:13:20 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2013-08-30 11:13:20 +0000
commitf7e088e7de99b6ab31dc56d2a3ed358647207256 (patch)
tree28d46552357ed039d57e797a50db601708d5d55e
parentbec9ec3fc1f24d55a37a6c90ac03dc60f87d4d72 (diff)
downloadgcc-f7e088e7de99b6ab31dc56d2a3ed358647207256.zip
gcc-f7e088e7de99b6ab31dc56d2a3ed358647207256.tar.gz
gcc-f7e088e7de99b6ab31dc56d2a3ed358647207256.tar.bz2
function.c (assign_parm_setup_reg): For a parameter passed by pointer and which can live in a register...
* 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
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/function.c26
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/guality/param-1.c33
-rw-r--r--gcc/testsuite/gcc.dg/guality/param-2.c33
-rw-r--r--gcc/var-tracking.c24
6 files changed, 120 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 171988a..9321385 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/function.c b/gcc/function.c
index c1550a2..08731e84 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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)))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 68861a8..53aeadc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..480ad3c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/param-1.c
@@ -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
index 0000000..64678bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/param-2.c
@@ -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" } } */
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index d82d262..cf1f08b 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -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
{