tree-optimization/104162 - CSE of &MEM[ptr].a[i] and ptr + CST
Commit Message
This adds the capability to value-numbering of treating complex
address expressions where the offset becomes invariant as equal
to a POINTER_PLUS_EXPR. This restores CSE that is now prevented
by early lowering of &MEM[ptr + CST] to a POINTER_PLUS_EXPR.
Unfortunately this regresses gcc.dg/asan/pr99673.c again, so
the testcase is adjusted accordingly.
Re-bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
Richard.
2022-01-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/104162
* tree-ssa-sccvn.cc (vn_reference_lookup): Handle
&MEM[_1 + 5].a[i] like a POINTER_PLUS_EXPR if the offset
becomes invariant.
(vn_reference_insert): Likewise.
* gcc.dg/tree-ssa/ssa-fre-99.c: New testcase.
* gcc.dg/asan/pr99673.c: Adjust.
---
gcc/testsuite/gcc.dg/asan/pr99673.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c | 27 +++++++++
gcc/tree-ssa-sccvn.cc | 66 +++++++++++++++++++++-
3 files changed, 95 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c
@@ -1,4 +1,6 @@
/* { dg-do compile } */
+/* Skip XPASS cases. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O2 -flto" } { "" } } */
/* { dg-additional-options "-Wstringop-overread" } */
struct B {
@@ -22,6 +24,6 @@ void g (struct C *pc, struct D *pd, int i)
pd->i = pb->i;
const short *psa = pb->a[i].sa;
- if (f (psa))
+ if (f (psa)) /* { dg-bogus "from a region of size" "pr99673" { xfail *-*-* } } */
return;
}
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* Disable FRE1 because that for the sake of __builtin_object_size
+ will not consider the equality but still valueize 'i', defeating
+ the purpose of the check. */
+/* { dg-options "-O -fdump-tree-fre3 -fdisable-tree-fre1" } */
+
+struct S { int a[4]; };
+
+int i;
+int bar (struct S *p)
+{
+ char *q = (char *)p + 4;
+ i = 1;
+ int *r = &((struct S *)p)->a[i];
+ return q == (char *)r;
+}
+int baz (struct S *p)
+{
+ i = 1;
+ int *r = &((struct S *)p)->a[i];
+ char *q = (char *)p + 4;
+ return q == (char *)r;
+}
+
+/* Verify FRE can handle valueizing &p->a[i] and value-numbering it
+ equal to a POINTER_PLUS_EXPR. */
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "fre3" } } */
@@ -3666,6 +3666,38 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
vr1.vuse = vuse_ssa_val (vuse);
vr1.operands = operands
= valueize_shared_reference_ops_from_ref (op, &valueized_anything);
+
+ /* Handle &MEM[ptr + 5].b[1].c as POINTER_PLUS_EXPR. Avoid doing
+ this before the pass folding __builtin_object_size had a chance to run. */
+ if ((cfun->curr_properties & PROP_objsz)
+ && operands[0].opcode == ADDR_EXPR
+ && operands.last ().opcode == SSA_NAME)
+ {
+ poly_int64 off = 0;
+ vn_reference_op_t vro;
+ unsigned i;
+ for (i = 1; operands.iterate (i, &vro); ++i)
+ {
+ if (vro->opcode == SSA_NAME)
+ break;
+ else if (known_eq (vro->off, -1))
+ break;
+ off += vro->off;
+ }
+ if (i == operands.length () - 1)
+ {
+ gcc_assert (operands[i-1].opcode == MEM_REF);
+ tree ops[2];
+ ops[0] = operands[i].op0;
+ ops[1] = wide_int_to_tree (sizetype, off);
+ tree res = vn_nary_op_lookup_pieces (2, POINTER_PLUS_EXPR,
+ TREE_TYPE (op), ops, NULL);
+ if (res)
+ return res;
+ return NULL_TREE;
+ }
+ }
+
vr1.type = TREE_TYPE (op);
ao_ref op_ref;
ao_ref_init (&op_ref, op);
@@ -3757,13 +3789,45 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
vn_reference_t vr1;
bool tem;
+ vec<vn_reference_op_s> operands
+ = valueize_shared_reference_ops_from_ref (op, &tem);
+ /* Handle &MEM[ptr + 5].b[1].c as POINTER_PLUS_EXPR. Avoid doing this
+ before the pass folding __builtin_object_size had a chance to run. */
+ if ((cfun->curr_properties & PROP_objsz)
+ && operands[0].opcode == ADDR_EXPR
+ && operands.last ().opcode == SSA_NAME)
+ {
+ poly_int64 off = 0;
+ vn_reference_op_t vro;
+ unsigned i;
+ for (i = 1; operands.iterate (i, &vro); ++i)
+ {
+ if (vro->opcode == SSA_NAME)
+ break;
+ else if (known_eq (vro->off, -1))
+ break;
+ off += vro->off;
+ }
+ if (i == operands.length () - 1)
+ {
+ gcc_assert (operands[i-1].opcode == MEM_REF);
+ tree ops[2];
+ ops[0] = operands[i].op0;
+ ops[1] = wide_int_to_tree (sizetype, off);
+ vn_nary_op_insert_pieces (2, POINTER_PLUS_EXPR,
+ TREE_TYPE (op), ops, result,
+ VN_INFO (result)->value_id);
+ return;
+ }
+ }
+
vr1 = XOBNEW (&vn_tables_obstack, vn_reference_s);
if (TREE_CODE (result) == SSA_NAME)
vr1->value_id = VN_INFO (result)->value_id;
else
vr1->value_id = get_or_alloc_constant_value_id (result);
vr1->vuse = vuse_ssa_val (vuse);
- vr1->operands = valueize_shared_reference_ops_from_ref (op, &tem).copy ();
+ vr1->operands = operands.copy ();
vr1->type = TREE_TYPE (op);
vr1->punned = false;
ao_ref op_ref;