tree-optimization/107699 - missed &data._M_elems + _1 != &data._M_elems folding
authorRichard Biener <rguenther@suse.de>
Thu, 8 Dec 2022 08:07:36 +0000 (09:07 +0100)
committerRichard Biener <rguenther@suse.de>
Thu, 8 Dec 2022 10:58:47 +0000 (11:58 +0100)
The following addresses a missed folding noticed in PR107699 that can
be fixed amending the existing &x + a != &x + b pattern to also handle
the case of only one side having a pointer plus.  I'm moving the
patterns next to related simpifications showing there'd be an existing
pattern matching this if it were not gated with an explicit single_use
constraint.  Note the new pattern also handles &x.a + a != &x.b, but
this hints at some unification / generalization opportunities here.

PR tree-optimization/107699
* match.pd (&a !=/== &a.b + c -> (&a - &a.b) !=/== c): New
pattern variant.

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

gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/pr107699.c [new file with mode: 0644]

index f48cbd9..127cef9 100644 (file)
@@ -2260,6 +2260,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && (CONSTANT_CLASS_P (@1) || (single_use (@2) && single_use (@3))))
    (op @1 { build_zero_cst (TREE_TYPE (@1)); }))))
 
+/* (&a + b) !=/== (&a[1] + c) -> (&a[0] - &a[1]) + b !=/== c */
+(for neeq (ne eq)
+ (simplify
+  (neeq:c ADDR_EXPR@0 (pointer_plus ADDR_EXPR@2 @3))
+   (with { poly_int64 diff; tree inner_type = TREE_TYPE (@3);}
+    (if (ptr_difference_const (@0, @2, &diff))
+     (neeq { build_int_cst_type (inner_type, diff); } @3))))
+ (simplify
+  (neeq (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3))
+   (with { poly_int64 diff; tree inner_type = TREE_TYPE (@1);}
+    (if (ptr_difference_const (@0, @2, &diff))
+     (neeq (plus { build_int_cst_type (inner_type, diff); } @1) @3)))))
+
 /* X - Y < X is the same as Y > 0 when there is no overflow.
    For equality, this is also true with wrapping overflow.  */
 (for op (simple_comparison)
@@ -2439,14 +2452,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (if (ptr_difference_const (@0, @2, &diff))
     (plus { build_int_cst_type (type, diff); } (convert (minus @1 @3))))))
 
-/* (&a+b) !=/== (&a[1] + c) ->  sizeof(a[0]) + b !=/== c */
-(for neeq (ne eq)
- (simplify
-  (neeq (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3))
-   (with { poly_int64 diff; tree inner_type = TREE_TYPE (@1);}
-    (if (ptr_difference_const (@0, @2, &diff))
-     (neeq (plus { build_int_cst_type (inner_type, diff); } @1) @3)))))
-
 /* Canonicalize (T *)(ptr - ptr-cst) to &MEM[ptr + -ptr-cst].  */
 (simplify
  (convert (pointer_diff @0 INTEGER_CST@1))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107699.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107699.c
new file mode 100644 (file)
index 0000000..4bf864d
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1" } */
+
+struct { int data[16]; } x;
+
+int foo (int n)
+{
+  int *p = x.data + n;
+  /* Should simplify this to n * 4 != 0.  */
+  if ((void *)&x != (void *)p)
+    return 1;
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump " != 0" "forwprop1" } } */