I was overly cautionous when implementing this part of VN translation but given the code is never executed from PRE (and thus the result will never be inserted as real code) there's no TBAA issue to be avoided.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. >From b44f9be5b45bdf9c3604fcb78ba96cedfb7efa78 Mon Sep 17 00:00:00 2001 From: Richard Guenther <rguent...@suse.de> Date: Wed, 6 Jun 2018 12:16:38 +0200 Subject: [PATCH] fix-pr86062 2018-06-06 Richard Biener <rguent...@suse.de> PR tree-optimization/86062 * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle arbitrary component refs ontop of to be offsetted base. * g++.dg/tree-ssa/pr86062.C: New testcase. diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr86062.C b/gcc/testsuite/g++.dg/tree-ssa/pr86062.C new file mode 100644 index 00000000000..d62bdf6d2f7 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr86062.C @@ -0,0 +1,23 @@ +// { dg-do compile } +// { dg-require-effective-target c++14 } +// { dg-options "-O2 -ffinite-math-only -fdump-tree-fre1" } + +#include <array> + +struct I { double i,s; I(double d):i(d),s(d){} }; +typedef std::array<double,3> P; +typedef std::array<I,3> AP; + +static AP c(P const&p){ + return {p[0],p[1],p[2]}; +} +template<class T> auto const& ac(T const&p, int n){return p[n];} +static double g(P const&p, int n) +{ + I res = ac(c(p),n); + return res.s-res.i; +} + +__attribute__((flatten)) double fff(P p){ return g(p,1); } + +// { dg-final { scan-tree-dump "return 0.0;" "fre1" } } diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 4e946ba7baf..4aec41e96c1 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2270,14 +2270,16 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, /* Apply an extra offset to the inner MEM_REF of the RHS. */ if (maybe_ne (extra_off, 0)) { - if (rhs.length () < 2 - || rhs[0].opcode != MEM_REF - || known_eq (rhs[0].off, -1)) + if (rhs.length () < 2) return (void *)-1; - rhs[0].off += extra_off; - rhs[0].op0 = int_const_binop (PLUS_EXPR, rhs[0].op0, - build_int_cst (TREE_TYPE (rhs[0].op0), - extra_off)); + int ix = rhs.length () - 2; + if (rhs[ix].opcode != MEM_REF + || known_eq (rhs[ix].off, -1)) + return (void *)-1; + rhs[ix].off += extra_off; + rhs[ix].op0 = int_const_binop (PLUS_EXPR, rhs[ix].op0, + build_int_cst (TREE_TYPE (rhs[ix].op0), + extra_off)); } /* We need to pre-pend vr->operands[0..i] to rhs. */