PR 68393: Handle SUBREG_PROMOTED_VAR_P in expand_direct_optab_fn

Do the usual dance when assigning to SUBREG_PROMOTED_VAR_P destinations:
first convert to the outer mode, then extend to the inner mode.

Tested that it fixes the powerpc64le-linux-gnu breakage.  Also tested
on x86_64-linux-gnu and powerpc64-linux-gnu.

gcc/
	PR bootstrap/68393
	* internal-fn.c (expand_direct_optab_fn): Handle SUBREG_PROMOTED_VAR_P
	destinations.

From-SVN: r230590
This commit is contained in:
Richard Sandiford 2015-11-19 08:17:21 +00:00 committed by Richard Sandiford
parent d0eccfcdc3
commit ee1326921d
2 changed files with 29 additions and 7 deletions

View File

@ -1,3 +1,9 @@
2015-11-19 Richard Sandiford <richard.sandiford@arm.com>
PR bootstrap/68393
* internal-fn.c (expand_direct_optab_fn): Handle SUBREG_PROMOTED_VAR_P
destinations.
2015-11-18 Jeff Law <law@redhat.com>
PR tree-optimization/68198

View File

@ -2124,14 +2124,30 @@ expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
expand_insn (icode, nargs + 1, ops);
if (!rtx_equal_p (lhs_rtx, ops[0].value))
{
if (INTEGRAL_TYPE_P (lhs_type))
/* Convert the operand to the required type, which is useful
for things that return an int regardless of the size of
the input. If the value produced by the instruction is
smaller than required, assume that it is signed. */
convert_move (lhs_rtx, ops[0].value, 0);
else
/* If the return value has an integral type, convert the instruction
result to that type. This is useful for things that return an
int regardless of the size of the input. If the instruction result
is smaller than required, assume that it is signed.
If the return value has a nonintegral type, its mode must match
the instruction result. */
if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
{
/* If this is a scalar in a register that is stored in a wider
mode than the declared mode, compute the result into its
declared mode and then convert to the wider mode. */
gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
convert_move (SUBREG_REG (lhs_rtx), tmp,
SUBREG_PROMOTED_SIGN (lhs_rtx));
}
else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
emit_move_insn (lhs_rtx, ops[0].value);
else
{
gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
convert_move (lhs_rtx, ops[0].value, 0);
}
}
}