[PATCH V2] Add pattern for pointer-diff on addresses with same base/offset (PR 94234)
Richard Biener
richard.guenther@gmail.com
Tue Sep 1 07:38:08 GMT 2020
On Wed, Aug 19, 2020 at 11:17 AM Feng Xue OS
<fxue@os.amperecomputing.com> wrote:
>
> As Richard's comment, this patch is composed to simplify generalized
> binary-with-convert pattern like ((T) X) OP ((T) Y). Instead of creating
> almost duplicated rules into match.pd, we try to transform it to (T) (X OP Y),
> and apply simplification on (X OP Y) in forwprop pass.
>
> Regards,
> Feng
> ---
> 2020-08-19 Feng Xue <fxue@os.amperecomputing.com>
>
> gcc/
> PR tree-optimization/94234
> * tree-ssa-forwprop.c (simplify_binary_with_convert): New function.
> * (fwprop_ssa_val): Move it before its new caller.
No * at this line. There's an entry for (pass_forwprop::execute) missing.
I don't think the transform as implemented, ((T) X) OP ((T) Y) to
(T) (X OP Y) is useful to do in tree-ssa-forwprop.c. Instead what I
suggested was to do the original
+/* (T)(A * C) +- (T)(B * C) -> (T)((A +- B) * C) and
+ (T)(A * C) +- (T)(A) -> (T)(A * (C +- 1)). */
but realize we already do this for GENERIC in fold_plusminus_mult_expr, just
without the conversions (also look at the conditions in the callers). This
function takes great care for handling overflow correctly and thus I suggested
to take that over to GIMPLE in tree-ssa-forwprop.c and try extend it to cover
the conversions you need for the specific cases.
Alternatively one could move the GENERIC bits to match.pd, leaving a
worker in fold-const.c. Then try to extend that there.
I just remember this is a very fragile area with respect to overflow
correctness.
Thanks,
Richard.
> gcc/testsuite/
> PR tree-optimization/94234
> * gcc.dg/ifcvt-3.c: Modified to suppress forward propagation.
> * gcc.dg/tree-ssa/20030807-10.c: Likewise.
> * gcc.dg/pr94234-2.c: New test.
>
> > ________________________________________
> > From: Richard Biener <richard.guenther@gmail.com>
> > Sent: Monday, June 15, 2020 3:41 PM
> > To: Feng Xue OS
> > Cc: gcc-patches@gcc.gnu.org; Marc Glisse
> > Subject: Re: [PATCH] Add pattern for pointer-diff on addresses with same base/offset (PR 94234)
> >
> > On Fri, Jun 5, 2020 at 11:20 AM Feng Xue OS <fxue@os.amperecomputing.com> wrote:
> >>
> >> As Marc suggested, removed the new pointer_diff rule, and add another rule to fold
> >> convert-add expression. This new rule is:
> >>
> >> (T)(A * C) +- (T)(B * C) -> (T) ((A +- B) * C)
> >>
> >> Regards,
> >> Feng
> >>
> >> ---
> >> 2020-06-01 Feng Xue <fxue@os.amperecomputing.com>
> >>
> >> gcc/
> >> PR tree-optimization/94234
> >> * match.pd ((T)(A * C) +- (T)(B * C)) -> (T)((A +- B) * C): New
> >> simplification.
> >> * ((PTR_A + OFF) - (PTR_B + OFF)) -> (PTR_A - PTR_B): New
> >> simplification.
> >>
> >> gcc/testsuite/
> >> PR tree-optimization/94234
> >> * gcc.dg/pr94234.c: New test.
> >> ---
> >> gcc/match.pd | 28 ++++++++++++++++++++++++++++
> >> gcc/testsuite/gcc.dg/pr94234.c | 24 ++++++++++++++++++++++++
> >> 2 files changed, 52 insertions(+)
> >> create mode 100644 gcc/testsuite/gcc.dg/pr94234.c
> >>
> >> diff --git a/gcc/match.pd b/gcc/match.pd
> >> index 33ee1a920bf..4f340bfe40a 100644
> >> --- a/gcc/match.pd
> >> +++ b/gcc/match.pd
> >> @@ -2515,6 +2515,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >> && TREE_CODE (@2) == INTEGER_CST
> >> && tree_int_cst_sign_bit (@2) == 0))
> >> (minus (convert @1) (convert @2)))))
> >> + (simplify
> >> + (pointer_diff (pointer_plus @0 @2) (pointer_plus @1 @2))
> >> + (pointer_diff @0 @1))
> >
> > This new pattern is OK. Please commit it separately.
> >
> >> (simplify
> >> (pointer_diff (pointer_plus @@0 @1) (pointer_plus @0 @2))
> >> /* The second argument of pointer_plus must be interpreted as signed, and
> >> @@ -2526,6 +2529,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >> (minus (convert (view_convert:stype @1))
> >> (convert (view_convert:stype @2)))))))
> >>
> >> +/* (T)(A * C) +- (T)(B * C) -> (T)((A +- B) * C) and
> >> + (T)(A * C) +- (T)(A) -> (T)(A * (C +- 1)). */
> >> +(if (INTEGRAL_TYPE_P (type))
> >> + (for plusminus (plus minus)
> >> + (simplify
> >> + (plusminus (convert:s (mult:cs @0 @1)) (convert:s (mult:cs @0 @2)))
> >> + (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
> >> + && (TYPE_OVERFLOW_UNDEFINED (type) || TYPE_OVERFLOW_WRAPS (type))
> >> + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
> >> + (convert (mult (plusminus @1 @2) @0))))
> >> + (simplify
> >> + (plusminus (convert @0) (convert@2 (mult:c@3 @0 @1)))
> >> + (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
> >> + && (TYPE_OVERFLOW_UNDEFINED (type) || TYPE_OVERFLOW_WRAPS (type))
> >> + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
> >> + && single_use (@2) && single_use (@3))
> >> + (convert (mult (plusminus { build_one_cst (TREE_TYPE (@1)); } @1) @0))))
> >> + (simplify
> >> + (plusminus (convert@2 (mult:c@3 @0 @1)) (convert @0))
> >> + (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
> >> + && (TYPE_OVERFLOW_UNDEFINED (type) || TYPE_OVERFLOW_WRAPS (type))
> >> + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
> >> + && single_use (@2) && single_use (@3))
> >> + (convert (mult (plusminus @1 { build_one_cst (TREE_TYPE (@1)); }) @0))))))
> >> +
> >
> > This shows the limit of pattern matching IMHO. I'm also not convinced
> > it gets the
> > overflow cases correct (but I didn't spend too much time here). Note we have
> > similar functionality implemented in fold_plusminus_mult_expr. IMHO instead
> > of doing the above moving fold_plusminus_mult_expr to GIMPLE by executing
> > it from inside the forwprop pass would make more sense. Or finally biting the
> > bullet and try to teach reassociation about how to handle signed arithmetic
> > with non-wrapping overflow behavior.
> >
> > Richard.
>
More information about the Gcc-patches
mailing list