From: Kyrylo Tkachov <[email protected]>

split_overlapping_partition_decls left PARM_DECLs and RESULT_DECLs alone, on
the grounds that they need a single partition holding the canonical RTL.  That
partition is the one of the default definition, which the rule already in place
keeps, so the exclusion was wider than it needed to be.

A parameter that stays live across a redefinition of itself needs two
partitions, and an oversized vector parameter puts both of them in memory: the
incoming argument slot and a local slot.  Every name of both partitions has the
PARM_DECL as its base, so both slots are given it as their MEM_EXPR:

  (mem/c:V2DI (reg/v/f:DI 126) [1 p+0 S16 A128])
  (mem/c:V2DI (plus:DI (reg/f:DI 96 virtual-stack-vars)
                       (const_int -128)) [1 p+0 S16 A128])

Two addresses claiming to be p+0 let the load/store pair-fusion pass fuse
accesses that belong to different slots, which miscompiles the new test on
aarch64 at -Os.

Drop the exclusion.  SSA_NAME_VAR is a VAR_DECL, a PARM_DECL or a RESULT_DECL
and set_rtl attaches any of them, so all three need the same treatment.  The
rename leaves default definitions alone, so the partition holding one still
owns the canonical RTL.

Bootstrapped and tested on aarch64-none-linux-gnu and
x86_64-pc-linux-gnu.

gcc/ChangeLog:

        PR middle-end/126405
        * tree-outof-ssa.cc (split_overlapping_partition_decls): Also split
        partitions of PARM_DECLs and RESULT_DECLs.

gcc/testsuite/ChangeLog:

        PR middle-end/126405
        * gcc.c-torture/execute/pr126405-3.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 .../gcc.c-torture/execute/pr126405-3.c        | 48 +++++++++++++++++++
 gcc/tree-outof-ssa.cc                         |  7 +--
 2 files changed, 52 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr126405-3.c

diff --git a/gcc/testsuite/gcc.c-torture/execute/pr126405-3.c 
b/gcc/testsuite/gcc.c-torture/execute/pr126405-3.c
new file mode 100644
index 00000000000..49b622cde79
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr126405-3.c
@@ -0,0 +1,48 @@
+/* A parameter that stays live across a redefinition of itself needs two
+   partitions, and an oversized vector parameter (V16DI, 128 bytes, no register
+   mode) puts both of them in memory.  Every name of both partitions has the
+   PARM_DECL as its base, so without a split the incoming argument slot and the
+   local slot both claim to be the parameter, and the load/store pair-fusion
+   pass fuses accesses across them.  Self-checking: aborts if the result is
+   wrong.  */
+
+typedef long __attribute__((vector_size (16 * sizeof (long)))) v16di;
+
+v16di g0, g1;
+
+/* The wrong value is read from an uninitialised stack slot, so make sure the
+   stack the callee reuses does not happen to be zero.  */
+__attribute__((noipa)) static void
+dirty_stack (void)
+{
+  volatile char buf[1024];
+  for (unsigned i = 0; i < sizeof (buf); i++)
+    buf[i] = 0xa5;
+}
+
+__attribute__((noipa)) static v16di
+f (v16di p)
+{
+  v16di old = p;
+  p = g0;
+  g1 = p;
+  return old + p;
+}
+
+int
+main (void)
+{
+  v16di a, r;
+
+  for (int i = 0; i < 16; i++)
+    {
+      a[i] = i + 1;
+      g0[i] = 100;
+    }
+  dirty_stack ();
+  r = f (a);
+  for (int i = 0; i < 16; i++)
+    if (r[i] != i + 101 || g1[i] != 100)
+      __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-outof-ssa.cc b/gcc/tree-outof-ssa.cc
index 309acd4fde2..af9d79fedcd 100644
--- a/gcc/tree-outof-ssa.cc
+++ b/gcc/tree-outof-ssa.cc
@@ -1062,8 +1062,9 @@ expand_phi_nodes (struct ssaexpand *sa)
    own artificial decl so the slots are distinguished at the source.
    The new decl carries a DECL_DEBUG_EXPR back to the user variable so debug
    info still attributes the storage to it (cf.  create_access_replacement in
-   tree-sra.cc).  PARM_DECLs and RESULT_DECLs are left alone, as they require
-   a single partition holding the canonical RTL.  */
+   tree-sra.cc).  A PARM_DECL or RESULT_DECL keeps the partition of its default
+   definition, which holds the canonical RTL, and only its other partitions are
+   split.  */
 
 static void
 split_overlapping_partition_decls (var_map map)
@@ -1106,7 +1107,7 @@ split_overlapping_partition_decls (var_map map)
       tree var = SSA_NAME_VAR (repr);
       if (part_var[i])
        var = expand_leader_merge (var, part_var[i]);
-      if (!var || !VAR_P (var))
+      if (!var)
        continue;
       /* Only partitions that will live in memory can end up with a
         misleading shared MEM_EXPR.  Mirror the decision that
-- 
2.50.1 (Apple Git-155)

Reply via email to