2020-12-15 Jakub Jelinek PR tree-optimization/98282 * tree-ssa-pre.c (compute_avail): Don't try to adjust alias set if different when ref1->opcode is not MEM_REF or TARGET_MEM_REF. * g++.dg/opt/pr98282.C: New test. --- gcc/tree-ssa-pre.c.jj 2020-11-30 10:48:31.000000000 +0100 +++ gcc/tree-ssa-pre.c 2020-12-15 10:51:51.061206572 +0100 @@ -4176,13 +4176,17 @@ compute_avail (void) && ref2->opcode != MEM_REF && ref2 != &operands[0]) --ref2; - if ((ref1->opcode == TARGET_MEM_REF - || ref1->opcode == MEM_REF) - && (TYPE_ALIGN (ref1->type) - > TYPE_ALIGN (ref2->type))) - ref1->type - = build_aligned_type (ref1->type, - TYPE_ALIGN (ref2->type)); + if (ref1->opcode == TARGET_MEM_REF + || ref1->opcode == MEM_REF) + { + if (TYPE_ALIGN (ref1->type) + > TYPE_ALIGN (ref2->type)) + ref1->type + = build_aligned_type (ref1->type, + TYPE_ALIGN (ref2->type)); + } + else + set = ref->set; /* TBAA behavior is an obvious part so make sure that the hashtable one covers this as well by adjusting the ref alias set and its base. */ --- gcc/testsuite/g++.dg/opt/pr98282.C.jj 2020-12-15 12:26:25.868415230 +0100 +++ gcc/testsuite/g++.dg/opt/pr98282.C 2020-12-15 12:28:00.346353067 +0100 @@ -0,0 +1,80 @@ +// PR tree-optimization/98282 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } + +template struct g; +template struct g { typedef b c; }; +template typename g::c &&d(b &&e) { + return static_cast::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 void operator=(ah); +}; +struct I { + template void q(o ai) { + *ai = aj(); + s::m(); + } + h aj(); +}; +template class as; +struct J { + int a; + char av; +}; +template struct aw : J { + void ax(...) {} +}; +template +struct aw, an, n...> : aw, n...> { + using az = as; + using ba = aw; + char bb; + an &bc() { return *reinterpret_cast(this); } + void ax(az *bd) { + if (bb) + new (bd) an(d(bc())); + ba::ax(bd); + } +}; +template struct as : aw, n...> { + as(); + as(as &&be) { be.ax(this); } + void operator=(as be) { be.ax(this); } +}; +struct h { + as bg; +}; +using bh = t; +struct u { + bh bj; +}; +I bk(); +template void bl() { + h a; + bk().q(&a); +} +template void bn(int) { + u b; + b.bj = bl; +} +void bp() { bn(0); }