119 lines
2.9 KiB
Diff
119 lines
2.9 KiB
Diff
2020-12-15 Jakub Jelinek <jakub@redhat.com>
|
|
|
|
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 <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); }
|