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