On 17/08/12 16:20, Richard Earnshaw wrote: > Ok, in which case we have to give is_widening_mult_rhs_p enough smarts > to not strip > > (s32)u32 > > and return u32. > > I'll have another think about it.
Take two. This version should address your concerns about handling (u32)u16 * (u32)u16 -> u64 We now look at each operand directly, but when doing so we check whether the operand is the same size as the result or not. When it is, we can strip any conversion; when it isn't the conversion must preserve signedness of the inner operand and mustn't be a narrowing conversion. * tree-ssa-math-opts.c (widening_mult_conversion_strippable_p): New function. (is_widening_mult_rhs_p): Use it. Testing underway (again) OK? R.
--- tree-ssa-math-opts.c (revision 190502) +++ tree-ssa-math-opts.c (local) @@ -1958,6 +1958,43 @@ struct gimple_opt_pass pass_optimize_bsw } }; +/* Return true if stmt is a type conversion operation that can be stripped + when used in a widening multiply operation. */ +static bool +widening_mult_conversion_strippable_p (tree result_type, gimple stmt) +{ + enum tree_code rhs_code = gimple_assign_rhs_code (stmt); + + if (TREE_CODE (result_type) == INTEGER_TYPE) + { + tree op_type; + tree inner_op_type; + + if (!CONVERT_EXPR_CODE_P (rhs_code)) + return false; + + op_type = TREE_TYPE (gimple_assign_lhs (stmt)); + + /* If the type of OP has the same precision as the result, then + we can strip this conversion. The multiply operation will be + selected to create the correct extension as a by-product. */ + if (TYPE_PRECISION (result_type) == TYPE_PRECISION (op_type)) + return true; + + /* We can also strip a conversion if it preserves the signed-ness of + the operation and doesn't narrow the range. */ + inner_op_type = TREE_TYPE (gimple_assign_rhs1 (stmt)); + + if (TYPE_UNSIGNED (op_type) == TYPE_UNSIGNED (inner_op_type) + && TYPE_PRECISION (op_type) > TYPE_PRECISION (inner_op_type)) + return true; + + return false; + } + + return rhs_code == FIXED_CONVERT_EXPR; +} + /* Return true if RHS is a suitable operand for a widening multiplication, assuming a target type of TYPE. There are two cases: @@ -1982,9 +2019,7 @@ is_widening_mult_rhs_p (tree type, tree if (is_gimple_assign (stmt)) { rhs_code = gimple_assign_rhs_code (stmt); - if (TREE_CODE (type) == INTEGER_TYPE - ? !CONVERT_EXPR_CODE_P (rhs_code) - : rhs_code != FIXED_CONVERT_EXPR) + if (! widening_mult_conversion_strippable_p (type, stmt)) rhs1 = rhs; else {