https://gcc.gnu.org/g:1c7824f0b88ab6e4a471c69c5f903ba6c25cbc18
commit r16-6714-g1c7824f0b88ab6e4a471c69c5f903ba6c25cbc18 Author: Richard Biener <[email protected]> Date: Mon Jan 12 10:04:49 2026 +0100 tree-optimization/122830 - move VN through aggregate copies 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. 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. Diff: --- gcc/testsuite/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(-) 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 000000000000..d390856deda9 --- /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 000000000000..8ab306bf5c26 --- /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 ed87ffc22862..b152dcb5943f 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
