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