tree-optimization/107699 - missed &data._M_elems + _1 != &data._M_elems folding
Commit Message
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.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
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 | 21 +++++++++++++--------
gcc/testsuite/gcc.dg/tree-ssa/pr107699.c | 15 +++++++++++++++
2 files changed, 28 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr107699.c
@@ -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))
new file mode 100644
@@ -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" } } */