tree-optimization/100051 - disambiguate access size vs decl
authorRichard Biener <rguenther@suse.de>
Tue, 13 Apr 2021 08:12:03 +0000 (10:12 +0200)
committerRichard Biener <rguenther@suse.de>
Tue, 27 Apr 2021 09:06:33 +0000 (11:06 +0200)
This adds disambiguation of the access size vs. the decl size
in the pointer based vs. decl based disambiguator.  We have
a TBAA based check like this already but that's fend off when
seeing alias-sets of zero or when -fno-strict-aliasing is in
effect.  Also the perceived dynamic type could be smaller than
the actual access.

2021-04-13  Richard Biener  <rguenther@suse.de>

PR tree-optimization/100051
* tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Add
disambiguator based on access size vs. decl size.

* gcc.dg/tree-ssa/ssa-fre-92.c: New testcase.

gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-92.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-92.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-92.c
new file mode 100644 (file)
index 0000000..c67fcea
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
+
+extern void foo(void);
+int a, c, *f, **d = &f;
+char b;
+int main()
+{
+  if (a) {
+    b = 0;
+    int *g = &c;
+    *g = 0;
+    f = *d;
+    *d = f;
+    if ((2 ^ b) == 0)
+      foo();
+  }
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "fre1" } } */
index ebb3f49..6c7d2f1 100644 (file)
@@ -2034,6 +2034,17 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
   if (TREE_CODE (base1) != TARGET_MEM_REF
       && !ranges_maybe_overlap_p (offset1 + moff, -1, offset2, max_size2))
     return false;
+
+  /* If the pointer based access is bigger than the variable they cannot
+     alias.  This is similar to the check below where we use TBAA to
+     increase the size of the pointer based access based on the dynamic
+     type of a containing object we can infer from it.  */
+  poly_int64 dsize2;
+  if (known_size_p (size1)
+      && poly_int_tree_p (DECL_SIZE (base2), &dsize2)
+      && known_lt (dsize2, size1))
+    return false;
+
   /* They also cannot alias if the pointer may not point to the decl.  */
   if (!ptr_deref_may_alias_decl_p (ptr1, base2))
     return false;