On Mon, Dec 19, 2011 at 10:39 PM, Richard Sandiford <rdsandif...@googlemail.com> wrote: > The recent(ish) improvements to widening multiplication support have > disabled madd and msub for fixed-point types. The problem is that the > optab is now chosen based on: > > optype = build_nonstandard_integer_type (from_mode, from_unsigned1); > > which is specific to integer types. > > The only time optype differs from type1 is when we've switched to using > unsigned types, possibly with a wider mode. As written, the handling of > mixed signedness really is only suitable for integer types, so this patch > enforces that and makes the call above conditional on it. It also fixes > the first argument to be the precision rather than the mode. > > (As the argument mismatch proved, the precision doesn't actually > matter here; only the signedness does. I think an equivalent fix > would be to call: > > optype = unsigned_type_for (type1); > > That ought to work for fixed point types too, but is a little less > obvious and a little less future-proof. Since the rest of the block > hasn't been adapted to fixed point types, it didn't seem worth the > confusion.) > > Tested on mips-sde-elf, where it fixes gcc.target/mips/dpaq_sa_l_w.c > and gcc.target/mips/dpsq_sa_l_w.c. OK to install?
Ok with ... > Richard > > > gcc/ > * tree-ssa-math-opts.c (convert_plusminus_to_widen): Restrict > handling of signedness differences to integer types. Only build > a new optype if type1 isn't correct. > > Index: gcc/tree-ssa-math-opts.c > =================================================================== > --- gcc/tree-ssa-math-opts.c 2011-12-19 21:18:43.000000000 +0000 > +++ gcc/tree-ssa-math-opts.c 2011-12-19 21:23:12.000000000 +0000 > @@ -2304,10 +2304,13 @@ convert_plusminus_to_widen (gimple_stmt_ > from_mode = TYPE_MODE (type1); > from_unsigned1 = TYPE_UNSIGNED (type1); > from_unsigned2 = TYPE_UNSIGNED (type2); > + optype = type1; > > /* There's no such thing as a mixed sign madd yet, so use a wider mode. */ > if (from_unsigned1 != from_unsigned2) > { > + if (TREE_CODE (type) != INTEGER_TYPE) > + return false; using INTEGRAL_TYPE_P (type) instead. That way it still works when applied to enum type multiplications. Thanks, Richard. > /* We can use a signed multiply with unsigned types as long as > there is a wider mode to use, or it is the smaller of the two > types that is unsigned. Note that type1 >= type2, always. */ > @@ -2322,6 +2325,8 @@ convert_plusminus_to_widen (gimple_stmt_ > } > > from_unsigned1 = from_unsigned2 = false; > + optype = build_nonstandard_integer_type (GET_MODE_PRECISION > (from_mode), > + false); > } > > /* If there was a conversion between the multiply and addition > @@ -2355,7 +2360,6 @@ convert_plusminus_to_widen (gimple_stmt_ > /* Verify that the machine can perform a widening multiply > accumulate in this mode/signedness combination, otherwise > this transformation is likely to pessimize code. */ > - optype = build_nonstandard_integer_type (from_mode, from_unsigned1); > this_optab = optab_for_tree_code (wmult_code, optype, optab_default); > handler = find_widening_optab_handler_and_mode (this_optab, to_mode, > from_mode, 0, &actual_mode);