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.  */

Reply via email to