expr: Move reduce_bit_field target mode check [PR96151]

In some cases, expand_expr_real_2 prefers to use the mode of the
caller-suggested target instead of the mode of the expression when
passing values to reduce_to_bit_field_precision.  E.g.:

      else if (target == 0)
        op0 = convert_to_mode (mode, op0,
                               TYPE_UNSIGNED (TREE_TYPE
                                              (treeop0)));
      else
        {
          convert_move (target, op0,
                        TYPE_UNSIGNED (TREE_TYPE (treeop0)));
          op0 = target;
        }

where “op0” might not have “mode” for the “else” branch,
but does for all the others.

reduce_to_bit_field_precision discards the suggested target if it
has the wrong mode.  This patch moves that to expand_expr_real_2
instead (conditional on reduce_bit_field).

gcc/
	PR middle-end/96151
	* expr.c (expand_expr_real_2): When reducing bit fields,
	clear the target if it has a different mode from the expression.
	(reduce_to_bit_field_precision): Don't do that here.  Instead
	assert that the target already has the correct mode.
This commit is contained in:
Richard Sandiford 2020-07-10 19:06:46 +01:00
parent efe99cca78
commit 510125d227

View File

@ -8664,7 +8664,9 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
reduce_bit_field = (INTEGRAL_TYPE_P (type) reduce_bit_field = (INTEGRAL_TYPE_P (type)
&& !type_has_mode_precision_p (type)); && !type_has_mode_precision_p (type));
if (reduce_bit_field && modifier == EXPAND_STACK_PARM) if (reduce_bit_field
&& (modifier == EXPAND_STACK_PARM
|| (target && GET_MODE (target) != mode)))
target = 0; target = 0;
/* Use subtarget as the target for operand 0 of a binary operation. */ /* Use subtarget as the target for operand 0 of a binary operation. */
@ -11527,9 +11529,8 @@ reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
{ {
scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type); scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
HOST_WIDE_INT prec = TYPE_PRECISION (type); HOST_WIDE_INT prec = TYPE_PRECISION (type);
gcc_assert (GET_MODE (exp) == VOIDmode || GET_MODE (exp) == mode); gcc_assert ((GET_MODE (exp) == VOIDmode || GET_MODE (exp) == mode)
if (target && GET_MODE (target) != mode) && (!target || GET_MODE (target) == mode));
target = 0;
/* For constant values, reduce using wide_int_to_tree. */ /* For constant values, reduce using wide_int_to_tree. */
if (poly_int_rtx_p (exp)) if (poly_int_rtx_p (exp))