sra: Avoid totally scalarizing overallping field_decls (PR 93667)
authorMartin Jambor <mjambor@suse.cz>
Wed, 19 Feb 2020 10:08:40 +0000 (11:08 +0100)
committerMartin Jambor <mjambor@suse.cz>
Wed, 19 Feb 2020 10:08:40 +0000 (11:08 +0100)
[[no_unique_address]] C++ attribute can cause two fields of a
RECORD_TYPE overlap, which currently confuses the totally scalarizing
code into creating invalid access tree.  For GCC 10, I'd like to
simply disable total scalarization of types where this happens.

For GCC 11 I'll write down a TODO item to enable total scalarization
of cases like this where the problematic fields are basically empty -
despite having a non-zero size - i.e. when they are just RECORD_TYPEs
without any data fields.

2020-02-19  Martin Jambor  <mjambor@suse.cz>

gcc/

PR tree-optimization/93667
* tree-sra.c (scalarizable_type_p): Return false if record fields
do not follow wach other.

gcc/testsuite/

PR tree-optimization/93667
* g++.dg/tree-ssa/pr93667.C: New test.

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr93667.C [new file with mode: 0644]
gcc/tree-sra.c

index 77c2a9ad81094a70939ce181e0674dd30a0a6d2a..6b53f9a2f07e4b999ab4971f6fd1868df06133f4 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-19  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/93667
+       * tree-sra.c (scalarizable_type_p): Return false if record fields
+       do not follow wach other.
+
 2020-01-21  Kito Cheng  <kito.cheng@sifive.com>
 
        * config/riscv/riscv.c (riscv_output_move) Using fmv.x.w/fmv.w.x
index 9b4fe11a6f6de4556d6814bdfea84337b8ea5318..8033fa0a3bb009789d57da1e66f3a7da38b9c9e1 100644 (file)
@@ -1,3 +1,8 @@
+2020-02-19  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/93667
+       * g++.dg/tree-ssa/pr93667.C: New test.
+
 2020-02-19  Hongtao Liu  <hongtao.liu@intel.com>
 
        * g++.dg/other/i386-2.C: add -mavx512vbmi2
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr93667.C b/gcc/testsuite/g++.dg/tree-ssa/pr93667.C
new file mode 100644 (file)
index 0000000..d875f53
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++2a" } */
+
+struct a {};
+struct b { [[no_unique_address]] a aq; };
+struct c {
+  int d;
+  [[no_unique_address]] b e;
+};
+c f() {return {};}
+void g() { f(); }
index 0cfac0a81924bcd9255e270b6069db04f72010d4..4c7d651e6b9040ad1d28d987b181bf59801f95cb 100644 (file)
@@ -958,6 +958,9 @@ scalarizable_type_p (tree type, bool const_decl)
   if (type_contains_placeholder_p (type))
     return false;
 
+  bool have_predecessor_field = false;
+  HOST_WIDE_INT prev_pos = 0;
+
   switch (TREE_CODE (type))
   {
   case RECORD_TYPE:
@@ -966,6 +969,17 @@ scalarizable_type_p (tree type, bool const_decl)
        {
          tree ft = TREE_TYPE (fld);
 
+         if (zerop (DECL_SIZE (fld)))
+           continue;
+
+         HOST_WIDE_INT pos = int_bit_position (fld);
+         if (have_predecessor_field
+             && pos <= prev_pos)
+           return false;
+
+         have_predecessor_field = true;
+         prev_pos = pos;
+
          if (DECL_BIT_FIELD (fld))
            return false;