[PATCH] Fix PR66313
Richard Biener
rguenther@suse.de
Tue Jun 13 10:25:00 GMT 2017
On Tue, 13 Jun 2017, Richard Sandiford wrote:
> Richard Biener <rguenther@suse.de> writes:
> > So I've come back to PR66313 and found a solution to the tailrecursion
> > missed optimization when fixing the factoring folding to use an unsigned
> > type when we're not sure of overflow.
> >
> > The folding part is identical to my last try from 2015, the tailrecursion
> > part makes us handle intermittent stmts that were introduced by foldings
> > that "clobber" our quest walking the single-use chain of stmts between
> > the call and the return (and failing at all stmts that are not part
> > of said chain). A simple solution is to move the stmts that are not
> > part of the chain and that we can move before the call. That handles
> > the leaf conversions that now appear for tree-ssa/tailrecursion-6.c
> >
> > Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> >
> > Richard.
> >
> > 2017-05-31 Richard Biener <rguenther@suse.de>
> >
> > PR middle-end/66313
> > * fold-const.c (fold_plusminus_mult_expr): If the factored
> > factor may be zero use a wrapping type for the inner operation.
> > * tree-tailcall.c (independent_of_stmt_p): Pass in to_move bitmap
> > and handle moved defs.
> > (process_assignment): Properly guard the unary op case. Return a
> > tri-state indicating that moving the stmt before the call may allow
> > to continue. Pass through to_move.
> > (find_tail_calls): Handle moving unrelated defs before
> > the call.
> >
> > * c-c++-common/ubsan/pr66313.c: New testcase.
> > * gcc.dg/tree-ssa/loop-15.c: Adjust.
> >
> > Index: gcc/fold-const.c
> > ===================================================================
> > *** gcc/fold-const.c.orig 2015-10-29 12:32:33.302782318 +0100
> > --- gcc/fold-const.c 2015-10-29 14:08:39.936497739 +0100
> > *************** fold_plusminus_mult_expr (location_t loc
> > *** 6916,6925 ****
> > }
> > same = NULL_TREE;
> >
> > ! if (operand_equal_p (arg01, arg11, 0))
> > ! same = arg01, alt0 = arg00, alt1 = arg10;
> > ! else if (operand_equal_p (arg00, arg10, 0))
> > same = arg00, alt0 = arg01, alt1 = arg11;
> > else if (operand_equal_p (arg00, arg11, 0))
> > same = arg00, alt0 = arg01, alt1 = arg10;
> > else if (operand_equal_p (arg01, arg10, 0))
> > --- 6916,6926 ----
> > }
> > same = NULL_TREE;
> >
> > ! /* Prefer factoring a common non-constant. */
> > ! if (operand_equal_p (arg00, arg10, 0))
> > same = arg00, alt0 = arg01, alt1 = arg11;
> > + else if (operand_equal_p (arg01, arg11, 0))
> > + same = arg01, alt0 = arg00, alt1 = arg10;
> > else if (operand_equal_p (arg00, arg11, 0))
> > same = arg00, alt0 = arg01, alt1 = arg10;
> > else if (operand_equal_p (arg01, arg10, 0))
> > *************** fold_plusminus_mult_expr (location_t loc
> > *** 6974,6987 ****
> > }
> > }
> >
> > ! if (same)
> > return fold_build2_loc (loc, MULT_EXPR, type,
> > fold_build2_loc (loc, code, type,
> > fold_convert_loc (loc, type, alt0),
> > fold_convert_loc (loc, type, alt1)),
> > fold_convert_loc (loc, type, same));
> >
> > ! return NULL_TREE;
> > }
> >
> > /* Subroutine of native_encode_expr. Encode the INTEGER_CST
> > --- 6975,7010 ----
> > }
> > }
> >
> > ! if (!same)
> > ! return NULL_TREE;
> > !
> > ! if (! INTEGRAL_TYPE_P (type)
> > ! || TYPE_OVERFLOW_WRAPS (type)
> > ! /* We are neither factoring zero nor minus one. */
> > ! || TREE_CODE (same) == INTEGER_CST)
> > return fold_build2_loc (loc, MULT_EXPR, type,
> > fold_build2_loc (loc, code, type,
> > fold_convert_loc (loc, type, alt0),
> > fold_convert_loc (loc, type, alt1)),
> > fold_convert_loc (loc, type, same));
> >
> > ! /* Same may be zero and thus the operation 'code' may overflow. Likewise
> > ! same may be minus one and thus the multiplication may overflow. Perform
> > ! the operations in an unsigned type. */
> > ! tree utype = unsigned_type_for (type);
> > ! tree tem = fold_build2_loc (loc, code, utype,
> > ! fold_convert_loc (loc, utype, alt0),
> > ! fold_convert_loc (loc, utype, alt1));
> > ! /* If the sum evaluated to a constant that is not -INF the multiplication
> > ! cannot overflow. */
> > ! if (TREE_CODE (tem) == INTEGER_CST
> > ! && ! wi::eq_p (tem, wi::min_value (TYPE_PRECISION (utype), SIGNED)))
> > ! return fold_build2_loc (loc, MULT_EXPR, type,
> > ! fold_convert (type, tem), same);
> > !
> > ! return fold_convert_loc (loc, type,
> > ! fold_build2_loc (loc, MULT_EXPR, utype, tem,
> > ! fold_convert_loc (loc, utype, same)));
> > }
> >
> > /* Subroutine of native_encode_expr. Encode the INTEGER_CST
>
> Sorry if you already know, but this part means that we can no longer
> vectorise:
>
> int
> f (int *x, int b1, int b2, int b3)
> {
> int foo = 0;
> for (int i1 = 0; i1 < b1; ++i1)
> for (int i2 = 0; i2 < b2; ++i2)
> for (int i3 = 0; i3 < b3; ++i3)
> foo += x[i1 * b2 * b3 + i2 * b3 + (i3 - 1)];
> return foo;
> }
>
> We now convert all the arithmetic in the [...] to unsigned int
> and reassociate it so that the "- 1" is applied last. We then assume
> that the overflow in this subtraction is well-defined and that the
> &x[...] might not be linear for the inner loop.
Can you file a PR?
# i3_44 = PHI <i3_32(6), 0(4)>
i3.2_7 = (unsigned int) i3_44;
_9 = i3.2_7 + _34;
_10 = (int) _9;
_11 = (long unsigned int) _10;
_12 = _11 * 4;
_13 = x_30(D) + _12;
_14 = *_13;
...
i3_32 = i3_44 + 1;
so we have *(x_30(D) + 4 * ((sizetype)(int)((unsigned){ 0, + , 1} + X))
It might mean that we need to avoid this re-association. Not sure how
to detect worthwhile vs. not worthwhile cases during folding. At least
I see no easy way to recover from it in SCEV analysis unless the
number of iterations is constrained more than in your example.
Ideas welcome ;)
Thanks,
Richard.
More information about the Gcc-patches
mailing list