[PATCH][match-and-simplify] Complete associate_* patterns
Richard Biener
rguenther@suse.de
Thu Sep 11 11:02:00 GMT 2014
The following patch completes transitioning
tree-ssa-forwprop.c:associate_* to patterns.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Richard.
2014-09-11 Richard Biener <rguenther@suse.de>
* match-plusminus.pd: Complete associate_plusminus patterns.
Properly guard all patterns. Add associate_pointerplus_align
pattern.
Index: gcc/match-plusminus.pd
===================================================================
--- gcc/match-plusminus.pd (revision 215009)
+++ gcc/match-plusminus.pd (working copy)
@@ -17,101 +17,138 @@ You should have received a copy of the G
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-/* ??? Have simplify groups guarded with common
- predicates on the outermost type? */
-/* Contract negates. */
-(simplify
- (plus:c @0 (negate @1))
- (if (!TYPE_SATURATING (type))
- (minus @0 @1)))
-(simplify
- (minus @0 (negate @1))
- (if (!TYPE_SATURATING (type))
- (plus @0 @1)))
+/* From tree-ssa-forwprop.c:associate_plusminus. */
+/* We can't reassociate at all for saturating types. */
+(if (!TYPE_SATURATING (type))
-/* Match patterns that allow contracting a plus-minus pair
- irrespective of overflow issues.
- ??? !TYPE_SATURATING condition missing.
- ??? !FLOAT_TYPE_P && !FIXED_POINT_TYPE_P condition missing
- because of saturation to +-Inf. */
+ /* Contract negates. */
+ (simplify
+ (plus:c @0 (negate @1))
+ (minus @0 @1))
+ (simplify
+ (minus @0 (negate @1))
+ (plus @0 @1))
-(if (!TYPE_SATURATING (type)
- && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
+ /* We can't reassociate floating-point or fixed-point plus or minus
+ because of saturation to +-Inf. */
+ (if (!FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
+
+ /* Match patterns that allow contracting a plus-minus pair
+ irrespective of overflow issues. */
+ /* (A +- B) - A -> +- B */
+ /* (A +- B) -+ B -> A */
+ /* A - (A +- B) -> -+ B */
+ /* A +- (B -+ A) -> +- B */
(simplify
- (minus (plus @0 @1) @0)
+ (minus (plus:c @0 @1) @0)
@1)
-
(simplify
(minus (minus @0 @1) @0)
(negate @1))
-
(simplify
- (minus (plus @0 @1) @1)
+ (plus:c (minus @0 @1) @1)
@0)
-
(simplify
- (plus:c (minus @0 @1) @1)
- @0))
-
-/* (CST +- A) +- CST -> CST' +- A. */
-/* simplify handles constant folding for us so we can
- implement these as re-association patterns.
- Watch out for operand order and constant canonicalization
- we do! A - CST -> A + -CST, CST + A -> A + CST. */
-(simplify
- (plus (plus @0 INTEGER_CST@1) INTEGER_CST@2)
- /* If the constant operation overflows we cannot do the transform
- as we would introduce undefined overflow, for example
- with (a - 1) + INT_MIN. */
- (if (!TREE_OVERFLOW (@1 = int_const_binop (PLUS_EXPR, @1, @2)))
- (plus @0 @1)))
-(simplify
- (plus (minus INTEGER_CST@0 @1) INTEGER_CST@2)
- (minus (plus @0 @2) @1))
-/* TODO:
- (A +- CST) +- CST -> A +- CST
- ~A + A -> -1
- ~A + 1 -> -A
- A - (A +- B) -> -+ B
- A +- (B +- A) -> +- B
- CST +- (CST +- A) -> CST +- A
- CST +- (A +- CST) -> CST +- A
- A + ~A -> -1
- (T)(P + A) - (T)P -> (T)A
- */
+ (minus @0 (plus:c @0 @1))
+ (negate @1))
+ (simplify
+ (minus @0 (minus @0 @1))
+ @1)
-/* ~A + A -> -1 */
-(simplify
- (plus:c (bit_not @0) @0)
- { build_all_ones_cst (type); })
+ /* (A +- CST) +- CST -> A + CST */
+ (for outer_op (plus minus)
+ (for inner_op (plus minus)
+ (simplify
+ (outer_op (inner_op @0 INTEGER_CST@1) INTEGER_CST@2)
+ /* If the constant operation overflows we cannot do the transform
+ as we would introduce undefined overflow, for example
+ with (a - 1) + INT_MIN. */
+ (with { tree cst = int_const_binop (outer_op == inner_op
+ ? PLUS_EXPR : MINUS_EXPR, @1, @2); }
+ (if (!TREE_OVERFLOW (cst))
+ (inner_op @0 { cst; } ))))))
+
+ /* (CST - A) +- CST -> CST - A */
+ (for outer_op (plus minus)
+ (simplify
+ (outer_op (minus INTEGER_CST@1 @0) INTEGER_CST@2)
+ (with { tree cst = int_const_binop (outer_op, @1, @2); }
+ (if (!TREE_OVERFLOW (cst))
+ (minus { cst; } @0)))))
-/* ~A + 1 -> -A */
-(simplify
- (plus (bit_not integral_op_p@0) integer_onep)
- (negate @0))
+ /* ~A + A -> -1 */
+ (simplify
+ (plus:c (bit_not @0) @0)
+ { build_all_ones_cst (type); })
-/* A - (A +- B) -> -+ B */
-(simplify
- (minus @0 (plus:c @0 @1))
- (negate @1))
-(simplify
- (minus @0 (minus @0 @1))
- @1)
+ /* ~A + 1 -> -A */
+ (simplify
+ (plus (bit_not integral_op_p@0) integer_onep@1)
+ (if (TREE_CODE (TREE_TYPE (@1)) != COMPLEX_TYPE
+ || (TREE_CODE (@1) == COMPLEX_CST
+ && integer_onep (TREE_REALPART (@1))
+ && integer_onep (TREE_IMAGPART (@1))))
+ (negate @0)))
+
+ /* (T)(P + A) - (T)P -> (T) A */
+ (for add (plus pointer_plus)
+ (simplify
+ (minus (convert (add @0 @1))
+ (convert @0))
+ (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@1) == INTEGER_CST
+ && tree_int_cst_sign_bit (@1) == 0))
+ (convert @1))))))
-/* (T)(P + A) - (T)P -> (T) A */
-(simplify
- (minus (convert (pointer_plus @0 @1))
- (convert @0))
- (convert @1))
+/* From tree-ssa-forwprop.c:associate_pointerplus. */
-/* associate_pointerplus: (ptr p+ off1) p+ off2 -> ptr p+ (off1 + off2) */
+/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
(simplify
(pointer_plus (pointer_plus @0 @1) @3)
(pointer_plus @0 (plus @1 @3)))
-/* associate_pointerplus_diff: ptr1 p+ (ptr2 - ptr1) -> ptr2 */
-(simplify
- (pointer_plus @0 (convert (minus (convert @1) (convert @0))))
- @1)
+/* From tree-ssa-forwprop.c:associate_pointerplus_diff. */
+
+/* Pattern match
+ tem1 = (long) ptr1;
+ tem2 = (long) ptr2;
+ tem3 = tem2 - tem1;
+ tem4 = (unsigned long) tem3;
+ tem5 = ptr1 + tem4;
+ and produce
+ tem5 = ptr2; */
+(simplify
+ (pointer_plus @0 (convert?@2 (minus@3 (convert @1) (convert @0))))
+ /* Conditionally look through a sign-changing conversion. */
+ (if (TYPE_PRECISION (TREE_TYPE (@2)) == TYPE_PRECISION (TREE_TYPE (@3)))
+ @1))
+
+/* From tree-ssa-forwprop.c:associate_pointerplus_align. */
+
+/* Pattern match
+ tem = (sizetype) ptr;
+ tem = tem & algn;
+ tem = -tem;
+ ... = ptr p+ tem;
+ and produce the simpler and easier to analyze with respect to alignment
+ ... = ptr & ~algn; */
+(simplify
+ (pointer_plus @0 (negate (bit_and (convert @0) INTEGER_CST@1)))
+ (with { tree algn = wide_int_to_tree (TREE_TYPE (@0), wi::bit_not (@1)); }
+ (bit_and @0 { algn; })))
More information about the Gcc-patches
mailing list