diff mbox

PR 68393: Handle SUBREG_PROMOTED_VAR_P in expand_direct_optab_fn

Message ID 878u5vjmis.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Nov. 18, 2015, 4:32 p.m. UTC
Do the usual dance when assigning to SUBREG_PROMOTED_VAR_P destinations:
first convert to the outer mode, then extend to the inner mode.
This fixes the powerpc64le bootstrap failure reported in PR 68393.

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

Thanks,
Richard

PS. Sorry for the delay in fixing this.  I posted a patch to bugzilla
yesterday to fix the case where the modes of the lhs and .md pattern
are different, but we need the same behaviour when the modes are the same.


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

Comments

Bernd Schmidt Nov. 19, 2015, 12:28 a.m. UTC | #1
On 11/18/2015 05:32 PM, Richard Sandiford wrote:
> Do the usual dance when assigning to SUBREG_PROMOTED_VAR_P destinations:
> first convert to the outer mode, then extend to the inner mode.
> This fixes the powerpc64le bootstrap failure reported in PR 68393.

Ok.


Bernd
diff mbox

Patch

diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index df3b7dc..bc77bdc 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -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);
+	}
     }
 }