&& (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)
(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))
--- /dev/null
+/* { 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" } } */