When building gcc.c-torture/execute/20000412-6.c with -mcpu=m32c (pointers are 24 bits), ivopts introduces a truncation to "unsigned short" (sizetype, which is 16 bits) - truncating needed bits off the pointer. 107t.ivopts shows this: tmp_9 = tmp_16 + 2; D.1229_1 = (unsigned int) tmp_9; tmp_13 = (short unsigned int *) D.1229_1; if (bufend_6(D) > tmp_13) which ends up being a PSI -> HI -> PSI conversion (PSI-SI-HI-SI-PSI in 128r.expand)
I confirm this in 4.7.0. It's due to rewrite_use_nonlinear_expr() not checking whether TYPE_PRECISION(ctype) < TYPE_PRECISION(utype) before doing the pointer adjustment in ctype and converting back to utype. Something like this fixes it in my case: if (TYPE_PRECISION (ctype) < TYPE_PRECISION (utype)) { ctype = generic_type_for (utype); step = fold_convert (ctype, unshare_expr (step)); }
I can't see where you would place this change from looking at the function.
commit af66de00843896ad5d2980952994b31cadbf8421 Author: Peter A. Bigot <pabigot@users.sourceforge.net> Date: Thu Jun 21 06:35:44 2012 -0500 Anticipatory patch for PR middle-end/38756 Do not truncate to size_type when adding the step factor to a pointer. diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 0693c21..f8372fd 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -6199,6 +6199,11 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data, step = cand->iv->step; ctype = TREE_TYPE (step); utype = TREE_TYPE (cand->var_after); + if (TYPE_PRECISION (ctype) < TYPE_PRECISION (utype)) + { + ctype = generic_type_for (utype); + step = fold_convert (ctype, unshare_expr (step)); + } if (TREE_CODE (step) == NEGATE_EXPR) { incr_code = MINUS_EXPR;
On Thu, 21 Jun 2012, bigotp at acm dot org wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38756 > > --- Comment #3 from Peter A. Bigot <bigotp at acm dot org> 2012-06-21 12:04:34 UTC --- > commit af66de00843896ad5d2980952994b31cadbf8421 > Author: Peter A. Bigot <pabigot@users.sourceforge.net> > Date: Thu Jun 21 06:35:44 2012 -0500 > > Anticipatory patch for PR middle-end/38756 > > Do not truncate to size_type when adding the step factor to a pointer. > > diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c > index 0693c21..f8372fd 100644 > --- a/gcc/tree-ssa-loop-ivopts.c > +++ b/gcc/tree-ssa-loop-ivopts.c > @@ -6199,6 +6199,11 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data, > step = cand->iv->step; > ctype = TREE_TYPE (step); > utype = TREE_TYPE (cand->var_after); > + if (TYPE_PRECISION (ctype) < TYPE_PRECISION (utype)) > + { > + ctype = generic_type_for (utype); > + step = fold_convert (ctype, unshare_expr (step)); > + } > if (TREE_CODE (step) == NEGATE_EXPR) > { > incr_code = MINUS_EXPR; So the truncation happens here? /* Otherwise, add the necessary computations to express the iv. */ op = fold_convert (ctype, cand->var_before); comp = fold_convert (utype, build2 (incr_code, ctype, op, unshare_expr (step))); I think it makes sense to do the computation in generic_type_for (utype) anyways - even if that truncates the step. Because we truncate to utype anyways. Thus type = generic_type_for (utype); op = fold_convert (type, cand->var_before); comp = fold_convert (utype, fold_build2 (incr_code, type, op, fold_convert (type, unshare_expr (step)))); unconditionally.
Yes, that's where it happens. Your proposal makes sense; I've just been trying to avoid changing existing behavior on "normal" platforms. I'll give the unconditional solution a try on the next regression suite run.