This avoids running into memory reference code in compute_avail by
properly classifying unfolded reference trees on constants.

Bootstrapped & tested on x86_64-unknown-linux-gnu, pushed.

2021-01-04  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/98282
        * tree-ssa-sccvn.c (vn_get_stmt_kind): Classify tcc_reference on
        invariants as VN_NARY.

        * g++.dg/opt/pr98282.C: New testcase.
---
 gcc/testsuite/g++.dg/opt/pr98282.C | 80 ++++++++++++++++++++++++++++++
 gcc/tree-ssa-sccvn.c               |  3 +-
 2 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/opt/pr98282.C

diff --git a/gcc/testsuite/g++.dg/opt/pr98282.C 
b/gcc/testsuite/g++.dg/opt/pr98282.C
new file mode 100644
index 00000000000..545084104d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr98282.C
@@ -0,0 +1,80 @@
+// PR tree-optimization/98282
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+template <typename> struct g;
+template <typename b> struct g<b &> { typedef b c; };
+template <typename b> typename g<b>::c &&d(b &&e) {
+  return static_cast<typename g<b>::c &&>(e);
+}
+void *operator new(__SIZE_TYPE__, void *f) { return f; }
+struct h;
+struct k {
+  using i = h *;
+};
+struct D {
+  k::i j;
+};
+struct p : D {
+  p(p &&) : D() {}
+};
+struct r {
+  using l = int;
+  r(r &&) : ad() {}
+  l *ad;
+};
+struct s {
+  static s m();
+};
+struct t {
+  template <typename ah> void operator=(ah);
+};
+struct I {
+  template <typename o> void q(o ai) {
+    *ai = aj();
+    s::m();
+  }
+  h aj();
+};
+template <typename...> class as;
+struct J {
+  int a;
+  char av;
+};
+template <typename...> struct aw : J {
+  void ax(...) {}
+};
+template <typename... ay, typename an, typename... n>
+struct aw<as<ay...>, an, n...> : aw<as<ay...>, n...> {
+  using az = as<ay...>;
+  using ba = aw<az, n...>;
+  char bb;
+  an &bc() { return *reinterpret_cast<an *>(this); }
+  void ax(az *bd) {
+    if (bb)
+      new (bd) an(d(bc()));
+    ba::ax(bd);
+  }
+};
+template <typename... n> struct as : aw<as<n...>, n...> {
+  as();
+  as(as &&be) { be.ax(this); }
+  void operator=(as be) { be.ax(this); }
+};
+struct h {
+  as<decltype(nullptr), r, p> bg;
+};
+using bh = t;
+struct u {
+  bh bj;
+};
+I bk();
+template <typename> void bl() {
+  h a;
+  bk().q(&a);
+}
+template <typename> void bn(int) {
+  u b;
+  b.bj = bl<int>;
+}
+void bp() { bn<int>(0); }
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index d944b9565ac..19defc0cccc 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -543,7 +543,8 @@ vn_get_stmt_kind (gimple *stmt)
                     || code == IMAGPART_EXPR
                     || code == VIEW_CONVERT_EXPR
                     || code == BIT_FIELD_REF)
-                   && TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
+                   && (TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME
+                       || is_gimple_min_invariant (TREE_OPERAND (rhs1, 0))))
                  return VN_NARY;
 
                /* Fallthrough.  */
-- 
2.26.2

Reply via email to