The following fixes a thinko in COMPONENT_REF handling in VN/PRE
where we falsely assumed the type of the FIELD_DECL specifies the
type of the COMPONENT_REF in full, disregarding address-space
qualification.

Bootstrapped and tested on x86_64-unknown-linux-gnu, I'm going to
push this tomorrow unless I hear back the testcase needs some
adjustment (I verified it builds, but I have no setup for
assembling or executing).

Richard.

        PR tree-optimization/60075
        * tree-ssa-sccvn.cc (copy_reference_ops_from_ref): Do not
        use the type of the FIELD_DECL for COMPONENT_REF ops.
        * tree-ssa-pre.cc (create_component_ref_by_pieces_1):
        Likewise.

        * gcc.target/avr/pr60075.c: New testcase.
---
 gcc/testsuite/gcc.target/avr/pr60075.c | 49 ++++++++++++++++++++++++++
 gcc/tree-ssa-pre.cc                    |  2 +-
 gcc/tree-ssa-sccvn.cc                  |  3 --
 3 files changed, 50 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/avr/pr60075.c

diff --git a/gcc/testsuite/gcc.target/avr/pr60075.c 
b/gcc/testsuite/gcc.target/avr/pr60075.c
new file mode 100644
index 00000000000..6c0b1e5b83b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr60075.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#define NI __attribute((noipa))
+typedef __UINT8_TYPE__ uint8_t;
+
+struct pair { uint8_t data; uint8_t cmd; };
+const __flash struct pair table[] =
+{
+  { 0x11, 1 }, { 0x33, 0 }, { 0x55, 1 }
+};
+
+uint8_t cnt;
+
+NI void write_data (uint8_t d)
+{
+  ++cnt;
+  if (cnt == 1 && d == 0x11)
+    { /*ok*/ }
+  else if (cnt == 3 && d == 0x55)
+    { /*ok*/ }
+  else
+    __builtin_abort ();
+}
+
+NI void write_cmd (uint8_t c)
+{
+  ++cnt;
+  if (cnt != 2 || c != 0x33)
+    __builtin_abort ();
+}
+
+NI void test (void)
+{
+  for (uint8_t i = 0; i < 3; i++)
+    {
+      // Bug is reading table[i].cmd from wrong AS.
+      if (table[i].cmd)
+        write_data (table[i].data);
+      else
+        write_cmd (table[i].data);
+    }
+}
+
+int main (void)
+{
+  test ();
+  return 0;
+}
diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
index 9353f19d405..47842251881 100644
--- a/gcc/tree-ssa-pre.cc
+++ b/gcc/tree-ssa-pre.cc
@@ -2950,7 +2950,7 @@ create_component_ref_by_pieces_1 (basic_block block, 
vn_reference_t ref,
            if (!genop2)
              return NULL_TREE;
          }
-       return build3 (COMPONENT_REF, TREE_TYPE (op1), op0, op1, genop2);
+       return build3 (COMPONENT_REF, currop->type, op0, op1, genop2);
       }
 
     case SSA_NAME:
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index c496ff93d11..03bf9a0ec4d 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -1003,9 +1003,6 @@ copy_reference_ops_from_ref (tree ref, 
vec<vn_reference_op_s> *result)
          temp.reverse = REF_REVERSE_STORAGE_ORDER (ref);
          break;
        case COMPONENT_REF:
-         /* The field decl is enough to unambiguously specify the field,
-            so use its type here.  */
-         temp.type = TREE_TYPE (TREE_OPERAND (ref, 1));
          temp.op0 = TREE_OPERAND (ref, 1);
          temp.op1 = TREE_OPERAND (ref, 2);
          temp.reverse = (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0)))
-- 
2.51.0

Reply via email to