+2019-01-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/88775
+ * match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)): Optimize
+ equal == 0 equality pointer comparisons some more if compared in
+ integral types and either one points to an automatic var and the
+ other to a global, or we can prove at least one points to the middle
+ or both point to start or both point to end.
+
2019-01-14 Andi Kleen <ak@linux.intel.com>
* Makefile.in: Lower autofdo sampling rate by 10x.
|| TREE_CODE (base1) == SSA_NAME
|| TREE_CODE (base1) == STRING_CST))
equal = (base0 == base1);
+ if (equal == 0)
+ {
+ if (!DECL_P (base0) || !DECL_P (base1))
+ equal = 2;
+ else if (cmp != EQ_EXPR && cmp != NE_EXPR)
+ equal = 2;
+ /* If this is a pointer comparison, ignore for now even
+ valid equalities where one pointer is the offset zero
+ of one object and the other to one past end of another one. */
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (@2)))
+ ;
+ /* Assume that automatic variables can't be adjacent to global
+ variables. */
+ else if (is_global_var (base0) != is_global_var (base1))
+ ;
+ else
+ {
+ tree sz0 = DECL_SIZE_UNIT (base0);
+ tree sz1 = DECL_SIZE_UNIT (base1);
+ /* If sizes are unknown, e.g. VLA or not representable,
+ punt. */
+ if (!tree_fits_poly_int64_p (sz0)
+ || !tree_fits_poly_int64_p (sz1))
+ equal = 2;
+ else
+ {
+ poly_int64 size0 = tree_to_poly_int64 (sz0);
+ poly_int64 size1 = tree_to_poly_int64 (sz1);
+ /* If one offset is pointing (or could be) to the beginning
+ of one object and the other is pointing to one past the
+ last byte of the other object, punt. */
+ if (maybe_eq (off0, 0) && maybe_eq (off1, size1))
+ equal = 2;
+ else if (maybe_eq (off1, 0) && maybe_eq (off0, size0))
+ equal = 2;
+ /* If both offsets are the same, there are some cases
+ we know that are ok. Either if we know they aren't
+ zero, or if we know both sizes are no zero. */
+ if (equal == 2
+ && known_eq (off0, off1)
+ && (known_ne (off0, 0)
+ || (known_ne (size0, 0) && known_ne (size1, 0))))
+ equal = 0;
+ }
+ }
+ }
}
(if (equal == 1
&& (cmp == EQ_EXPR || cmp == NE_EXPR
{ constant_boolean_node (known_ge (off0, off1), type); })
(if (cmp == GT_EXPR && (known_gt (off0, off1) || known_le (off0, off1)))
{ constant_boolean_node (known_gt (off0, off1), type); }))
- (if (equal == 0
- && DECL_P (base0) && DECL_P (base1)
- /* If we compare this as integers require equal offset. */
- && (!INTEGRAL_TYPE_P (TREE_TYPE (@2))
- || known_eq (off0, off1)))
- (switch
- (if (cmp == EQ_EXPR)
- { constant_boolean_node (false, type); })
- (if (cmp == NE_EXPR)
- { constant_boolean_node (true, type); })))))))))
+ (if (equal == 0)
+ (switch
+ (if (cmp == EQ_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (cmp == NE_EXPR)
+ { constant_boolean_node (true, type); })))))))))
/* Simplify pointer equality compares using PTA. */
(for neeq (ne eq)
--- /dev/null
+/* PR tree-optimization/88775 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 10 "optimized" } } */
+
+int a[64] = {};
+int b[64] = {};
+
+int
+f1 (void)
+{
+ return (__UINTPTR_TYPE__) &a[2] != (__UINTPTR_TYPE__) &b[2];
+}
+
+int
+f2 (void)
+{
+ return (__UINTPTR_TYPE__) &a[2] != (__UINTPTR_TYPE__) &b[10];
+}
+
+int
+f3 (void)
+{
+ return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &b[0];
+}
+
+int
+f4 (void)
+{
+ return (__UINTPTR_TYPE__) &a[64] != (__UINTPTR_TYPE__) &b[64];
+}
+
+int
+f5 (void)
+{
+ int c[64] = {};
+ return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &c[64];
+}
+
+int
+f6 (void)
+{
+ int c[64] = {};
+ return (__UINTPTR_TYPE__) &b[64] != (__UINTPTR_TYPE__) &c[0];
+}
+
+int
+f7 (void)
+{
+ int c[64] = {}, d[64] = {};
+ return (__UINTPTR_TYPE__) &c[2] != (__UINTPTR_TYPE__) &d[2];
+}
+
+int
+f8 (void)
+{
+ int c[64] = {}, d[64] = {};
+ return (__UINTPTR_TYPE__) &c[2] != (__UINTPTR_TYPE__) &d[10];
+}
+
+int
+f9 (void)
+{
+ int c[64] = {}, d[64] = {};
+ return (__UINTPTR_TYPE__) &c[0] != (__UINTPTR_TYPE__) &d[0];
+}
+
+int
+f10 (void)
+{
+ int c[64] = {}, d[64] = {};
+ return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[64];
+}
--- /dev/null
+/* PR tree-optimization/88775 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* These can't be decided until we know how the variables will
+ be laid out in memory. */
+/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */
+
+int a[64] = {};
+int b[64] = {};
+int e[0] = {};
+int f[0] = {};
+
+int
+f1 (void)
+{
+ return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &b[64];
+}
+
+int
+f2 (void)
+{
+ return (__UINTPTR_TYPE__) &a[64] != (__UINTPTR_TYPE__) &b[0];
+}
+
+int
+f3 (void)
+{
+ return (__UINTPTR_TYPE__) &e[0] != (__UINTPTR_TYPE__) &f[0];
+}
+
+int
+f4 (void)
+{
+ int c[64] = {}, d[64] = {};
+ return (__UINTPTR_TYPE__) &c[0] != (__UINTPTR_TYPE__) &d[64];
+}
+
+int
+f5 (void)
+{
+ int c[64] = {}, d[64] = {};
+ return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[0];
+}