The following generalizes the few hacks we have to more loosely
allow VN through aggregate copies to a more general (but also
restrictive) feature to rewrite the lookup to a new base with
a constant offset. This should now allow all constant-indexed
aggregate copies and it does never leave any stray components
and hoping for the best.
This resolves the diagnostic regression reported in PR122824.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/122830
PR tree-optimization/122824
* tree-ssa-sccvn.cc (vn_reference_lookup_3): Generalize
aggregate copy handling when no variable offsets are
involved.
* gcc.dg/tree-ssa/ssa-fre-112.c: New testcase.
* g++.dg/warn/Warray-bounds-pr122824.C: Likewise.
---
.../g++.dg/warn/Warray-bounds-pr122824.C | 15 +++++++
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-112.c | 27 ++++++++++++
gcc/tree-ssa-sccvn.cc | 43 +++++++++++--------
3 files changed, 67 insertions(+), 18 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/warn/Warray-bounds-pr122824.C
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-112.c
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-pr122824.C
b/gcc/testsuite/g++.dg/warn/Warray-bounds-pr122824.C
new file mode 100644
index 00000000000..d390856deda
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-pr122824.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=gnu++23 -Warray-bounds" }
+
+#include <format>
+
+template <typename... Args>
+auto foo(std::format_string<Args...> && format, Args &&... args)
+{
+ return std::format(std::move(format), std::forward<Args>(args)...);
+}
+
+int main()
+{
+ auto a = foo("{}", 42);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-112.c
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-112.c
new file mode 100644
index 00000000000..8ab306bf5c2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-112.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1" } */
+
+struct s1
+{
+ int c;
+};
+struct s2
+{
+ struct s1 l;
+};
+
+void f(int fill)
+{
+ struct s1 D144916, last;
+ int a = fill;
+ D144916.c = a;
+ struct s2 D135323;
+ D135323.l = D144916;
+ struct s1 *s = &D135323.l;
+ const int *sc = &s->c;
+ if (*sc != a)
+ __builtin_abort();
+}
+
+/* We should be able to optimize out the condition guarding the abort. */
+/* { dg-final { scan-tree-dump-not "abort" "fre1" } } */
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index ed87ffc2286..b152dcb5943 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -3664,14 +3664,32 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void
*data_,
temj--;
}
}
- /* When the LHS is already at the outermost level simply
- adjust for any offset difference. Further lookups
- will fail when there's too gross of a type compatibility
- issue. */
- if (!found && j == 0)
+ /* When we cannot find a common base to reconstruct the full
+ reference instead try to reduce the lookup to the new
+ base plus a constant offset. */
+ if (!found)
{
- extra_off = vr->operands[i].off - lhs_ops[j].off;
- i--, j--;
+ while (j >= 0
+ && known_ne (lhs_ops[j].off, -1))
+ {
+ extra_off += -lhs_ops[j].off;
+ j--;
+ }
+ if (j != -1)
+ return (void *)-1;
+ while (i >= 0
+ && known_ne (vr->operands[i].off, -1))
+ {
+ /* Punt if the additional ops contain a storage order
+ barrier. */
+ if (vr->operands[i].opcode == VIEW_CONVERT_EXPR
+ && vr->operands[i].reverse)
+ break;
+ extra_off += vr->operands[i].off;
+ i--;
+ }
+ if (i != -1)
+ return (void *)-1;
found = true;
}
/* If we did find a match we'd eventually append a MEM_REF
@@ -3691,17 +3709,6 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void
*data_,
j--;
}
- /* When we still didn't manage to strip off all components from
- lhs_op, opportunistically continue for those we can handle
- via extra_off. Note this is an attempt to fixup secondary
- copies after we hit the !found && j == 0 case above. */
- while (j != -1
- && known_ne (lhs_ops[j].off, -1))
- {
- extra_off += -lhs_ops[j].off;
- j--;
- }
-
/* i now points to the first additional op.
??? LHS may not be completely contained in VR, one or more
VIEW_CONVERT_EXPRs could be in its way. We could at least
--
2.51.0