Hi,

this is a followup to Richi's
https://gcc.gnu.org/ml/gcc-patches/2017-11/msg02396.html to fix PR
83141.  The basic idea is simple, be just as conservative about type
changing MEM_REFs as we are about actual VCEs.

I have checked how that would affect compilation of SPEC 2006 and (non
LTO) Mozilla Firefox and am happy to report that the difference was
tiny.  However, I had to make the test less strict, otherwise testcase
gcc.dg/guality/pr54970.c kept failing because it contains folded memcpy
and expects us to track values accross:

  int a[] = { 1, 2, 3 };
  /* ... */
  __builtin_memcpy (&a, (int [3]) { 4, 5, 6 }, sizeof (a));
                                /* { dg-final { gdb-test 31 "a\[0\]" "4" } } */
                                /* { dg-final { gdb-test 31 "a\[1\]" "5" } } */
                                /* { dg-final { gdb-test 31 "a\[2\]" "6" } } */
  
SRA is able to load replacement of a[0] directly from the temporary
array which is apparently necessary to generate proper debug info.  I
have therefore allowed the current transformation to go forward if the
source does not contain any padding or if it is a read-only declaration.
I would especially appreciate a review of the type_contains_padding_p
predicate as I am not sure it caches all cases.

The added call to contains_vce_or_bfcref_p in build_accesses_from_assign
is not strictly necessary, it is there to avoid attempting total
scalarization in vain.  This is also tested by the dump scan in the
added testcase.

A very similar patch has passed bootstrap and testing on x86_64, this
exact one is undergoing both now.  OK for trunk if it passes too?

Thanks,

Martin


2017-12-04  Martin Jambor  <mjam...@suse.cz>

        PR tree-optimization/83141

        * tree-sra.c (type_contains_padding_p): New function.
        (contains_vce_or_bfcref_p): Move up in the file, also test for
        MEM_REFs implicitely changing types with padding.  Remove inline
        keyword.
        (build_accesses_from_assign): Check contains_vce_or_bfcref_p
        before setting bit in should_scalarize_away_bitmap.

testsuite/
        * gcc.dg/tree-ssa/pr83141.c: New test.
---
 gcc/testsuite/gcc.dg/tree-ssa/pr83141.c |  31 +++++++++
 gcc/tree-sra.c                          | 116 ++++++++++++++++++++++++++------
 2 files changed, 128 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr83141.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr83141.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr83141.c
new file mode 100644
index 00000000000..86caf66025b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr83141.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-esra-details" } */
+
+volatile short vs;
+volatile long vl;
+
+struct A { short s; long i; long j; };
+struct A a, b;
+void foo ()
+{
+  struct A c;
+  __builtin_memcpy (&c, &b, sizeof (struct A));
+  __builtin_memcpy (&a, &c, sizeof (struct A));
+
+  vs = c.s;
+  vl = c.i;
+  vl = c.j;
+}
+int main()
+{
+  __builtin_memset (&b, 0, sizeof (struct A));
+  b.s = 1;
+  __builtin_memcpy ((char *)&b+2, &b, 2);
+  foo ();
+  __builtin_memcpy (&a, (char *)&a+2, 2);
+  if (a.s != 1)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "Will attempt to totally scalarize" "esra" 
} } */
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 866cff0edb0..0a9622e77f8 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1141,6 +1141,101 @@ contains_view_convert_expr_p (const_tree ref)
   return false;
 }
 
+/* Return false if we can determine that TYPE has no padding, otherwise return
+   true.  */
+
+static bool
+type_contains_padding_p (tree type)
+{
+  if (is_gimple_reg_type (type))
+    return false;
+
+  if (!tree_fits_uhwi_p (TYPE_SIZE (type)))
+    return true;
+
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+      {
+       unsigned HOST_WIDE_INT pos = 0;
+       for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
+         if (TREE_CODE (fld) == FIELD_DECL)
+           {
+             tree ft = TREE_TYPE (fld);
+
+             if (DECL_BIT_FIELD (fld)
+                 || DECL_PADDING_P (fld)
+                 || !tree_fits_uhwi_p (TYPE_SIZE (ft)))
+               return true;
+
+             tree t = bit_position (fld);
+             if (!tree_fits_uhwi_p (t))
+               return true;
+             unsigned HOST_WIDE_INT bp = tree_to_uhwi (t);
+             if (pos != bp)
+               return true;
+
+             pos += tree_to_uhwi (TYPE_SIZE (ft));
+             if (type_contains_padding_p (ft))
+               return true;
+           }
+
+       if (pos != tree_to_uhwi (TYPE_SIZE (type)))
+         return true;
+
+       return false;
+      }
+
+    case ARRAY_TYPE:
+      return type_contains_padding_p (TYPE_SIZE (type));
+
+    default:
+      return true;
+    }
+  gcc_unreachable ();
+}
+
+/* Return true if REF contains a MEM_REF that performs type conversion from a
+   type with padding or any VIEW_CONVERT_EXPR or a COMPONENT_REF with a
+   bit-field field declaration.  */
+
+static bool
+contains_vce_or_bfcref_p (const_tree ref)
+{
+  while (true)
+    {
+      if (TREE_CODE (ref) == MEM_REF)
+       {
+         tree op0 = TREE_OPERAND (ref, 0);
+         if (TREE_CODE (op0) == ADDR_EXPR)
+           {
+             tree mem = TREE_OPERAND (op0, 0);
+             if ((TYPE_MAIN_VARIANT (TREE_TYPE (ref))
+                  != TYPE_MAIN_VARIANT (TREE_TYPE (mem)))
+                 && !((DECL_P (mem) && TREE_READONLY (mem))
+                      || type_contains_padding_p (TREE_TYPE (mem))))
+               return true;
+
+             ref = mem;
+             continue;
+           }
+         else
+           return false;
+       }
+
+      if (!handled_component_p (ref))
+       return false;
+
+      if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
+         || (TREE_CODE (ref) == COMPONENT_REF
+             && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
+       return true;
+      ref = TREE_OPERAND (ref, 0);
+    }
+
+  return false;
+}
+
 /* Search the given tree for a declaration by skipping handled components and
    exclude it from the candidates.  */
 
@@ -1338,7 +1433,8 @@ build_accesses_from_assign (gimple *stmt)
     {
       racc->grp_assignment_read = 1;
       if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
-         && !is_gimple_reg_type (racc->type))
+         && !is_gimple_reg_type (racc->type)
+         && !contains_vce_or_bfcref_p (rhs))
        bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
       if (storage_order_barrier_p (lhs))
        racc->grp_unscalarizable_region = 1;
@@ -3416,24 +3512,6 @@ get_repl_default_def_ssa_name (struct access *racc)
   return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
 }
 
-/* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a
-   bit-field field declaration somewhere in it.  */
-
-static inline bool
-contains_vce_or_bfcref_p (const_tree ref)
-{
-  while (handled_component_p (ref))
-    {
-      if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
-         || (TREE_CODE (ref) == COMPONENT_REF
-             && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
-       return true;
-      ref = TREE_OPERAND (ref, 0);
-    }
-
-  return false;
-}
-
 /* Examine both sides of the assignment statement pointed to by STMT, replace
    them with a scalare replacement if there is one and generate copying of
    replacements if scalarized aggregates have been used in the assignment.  GSI
-- 
2.15.1



Reply via email to