--- /dev/null
+/* { dg-do run { target { { *-*-linux* *-*-gnu* *-*-uclinux* } && mmap } } } */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+struct S {
+ int a;
+};
+struct M {
+ int a, b;
+};
+
+int __attribute__((noipa))
+f(struct S *p, int c, int d)
+{
+ int r;
+ if (c)
+ {
+ if (d)
+ r = p->a;
+ else
+ r = ((struct M*)p)->a;
+ }
+ else
+ r = ((struct M*)p)->b;
+ return r;
+}
+
+int main ()
+{
+ long pgsz = sysconf(_SC_PAGESIZE);
+ if (pgsz < sizeof (struct M))
+ return 0;
+ char *p = mmap ((void *) 0, 2 * pgsz, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ if (p == MAP_FAILED)
+ return 0;
+ if (mprotect (p, pgsz, PROT_READ | PROT_WRITE))
+ return 0;
+ struct S *q = (struct S *)(p + pgsz) - 1;
+ q->a = 42;
+ if (f (q, 1, 1) != 42)
+ abort ();
+ return 0;
+}
/* 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. */
- if (ref->set == set
- || alias_set_subset_of (set, ref->set))
+ if ((ref->set == set
+ || alias_set_subset_of (set, ref->set))
+ && (ref->base_set == base_set
+ || alias_set_subset_of (base_set, ref->base_set)))
;
else if (ref1->opcode != ref2->opcode
|| (ref1->opcode != MEM_REF
operands.release ();
continue;
}
- else if (alias_set_subset_of (ref->set, set))
+ else if (ref->set == set
+ || alias_set_subset_of (ref->set, set))
{
+ tree reft = reference_alias_ptr_type (rhs1);
ref->set = set;
+ ref->base_set = set;
if (ref1->opcode == MEM_REF)
ref1->op0
- = wide_int_to_tree (TREE_TYPE (ref2->op0),
+ = wide_int_to_tree (reft,
wi::to_wide (ref1->op0));
else
ref1->op2
- = wide_int_to_tree (TREE_TYPE (ref2->op2),
+ = wide_int_to_tree (reft,
wi::to_wide (ref1->op2));
}
else