diff mbox series

[70/77] Make expand_fix/float check for scalar modes

Message ID 87r2xkbtes.fsf@linaro.org
State Accepted
Commit f4f6058097d99812ee3eda98d09c23fccdc7ba94
Headers show
Series Add wrapper classes for machine_modes | expand

Commit Message

Richard Sandiford July 13, 2017, 9:03 a.m. UTC
The expand_float code:

  /* Unsigned integer, and no way to convert directly.  Convert as signed,
     then unconditionally adjust the result.  */

and the expand_fix code:

  /* For an unsigned conversion, there is one more way to do it.
     If we have a signed conversion, we generate code that compares
     the real value to the largest representable positive number.  If if
     is smaller, the conversion is done normally.  Otherwise, subtract
     one plus the highest signed number, convert, and add it back.

are restricted to scalars, since the expansion branches on a
comparison of the value.  This patch makes that explicit.

2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* optabs.c (expand_float): Explicitly check for scalars before
	using a branching expansion.
	(expand_fix): Likewise.

Comments

Jeff Law Aug. 25, 2017, 5 a.m. UTC | #1
On 07/13/2017 03:03 AM, Richard Sandiford wrote:
> The expand_float code:

> 

>   /* Unsigned integer, and no way to convert directly.  Convert as signed,

>      then unconditionally adjust the result.  */

> 

> and the expand_fix code:

> 

>   /* For an unsigned conversion, there is one more way to do it.

>      If we have a signed conversion, we generate code that compares

>      the real value to the largest representable positive number.  If if

>      is smaller, the conversion is done normally.  Otherwise, subtract

>      one plus the highest signed number, convert, and add it back.

> 

> are restricted to scalars, since the expansion branches on a

> comparison of the value.  This patch makes that explicit.

> 

> 2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>

> 	    Alan Hayward  <alan.hayward@arm.com>

> 	    David Sherwood  <david.sherwood@arm.com>

> 

> gcc/

> 	* optabs.c (expand_float): Explicitly check for scalars before

> 	using a branching expansion.

> 	(expand_fix): Likewise.

OK.
jeff
diff mbox series

Patch

Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2017-07-13 09:18:53.274650323 +0100
+++ gcc/optabs.c	2017-07-13 09:18:56.346425666 +0100
@@ -4635,6 +4635,7 @@  expand_float (rtx to, rtx from, int unsi
 {
   enum insn_code icode;
   rtx target = to;
+  scalar_mode from_mode, to_mode;
   machine_mode fmode, imode;
   bool can_do_signed = false;
 
@@ -4684,7 +4685,10 @@  expand_float (rtx to, rtx from, int unsi
 
   /* Unsigned integer, and no way to convert directly.  Convert as signed,
      then unconditionally adjust the result.  */
-  if (unsignedp && can_do_signed)
+  if (unsignedp
+      && can_do_signed
+      && is_a <scalar_mode> (GET_MODE (to), &to_mode)
+      && is_a <scalar_mode> (GET_MODE (from), &from_mode))
     {
       rtx_code_label *label = gen_label_rtx ();
       rtx temp;
@@ -4694,19 +4698,19 @@  expand_float (rtx to, rtx from, int unsi
 	 least as wide as the target.  Using FMODE will avoid rounding woes
 	 with unsigned values greater than the signed maximum value.  */
 
-      FOR_EACH_MODE_FROM (fmode, GET_MODE (to))
-	if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
-	    && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
+      FOR_EACH_MODE_FROM (fmode, to_mode)
+	if (GET_MODE_PRECISION (from_mode) < GET_MODE_BITSIZE (fmode)
+	    && can_float_p (fmode, from_mode, 0) != CODE_FOR_nothing)
 	  break;
 
       if (fmode == VOIDmode)
 	{
 	  /* There is no such mode.  Pretend the target is wide enough.  */
-	  fmode = GET_MODE (to);
+	  fmode = to_mode;
 
 	  /* Avoid double-rounding when TO is narrower than FROM.  */
 	  if ((significand_size (fmode) + 1)
-	      < GET_MODE_PRECISION (GET_MODE (from)))
+	      < GET_MODE_PRECISION (from_mode))
 	    {
 	      rtx temp1;
 	      rtx_code_label *neglabel = gen_label_rtx ();
@@ -4718,7 +4722,7 @@  expand_float (rtx to, rtx from, int unsi
 		  || GET_MODE (target) != fmode)
 		target = gen_reg_rtx (fmode);
 
-	      imode = GET_MODE (from);
+	      imode = from_mode;
 	      do_pending_stack_adjust ();
 
 	      /* Test whether the sign bit is set.  */
@@ -4758,7 +4762,7 @@  expand_float (rtx to, rtx from, int unsi
       /* If we are about to do some arithmetic to correct for an
 	 unsigned operand, do it in a pseudo-register.  */
 
-      if (GET_MODE (to) != fmode
+      if (to_mode != fmode
 	  || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
 	target = gen_reg_rtx (fmode);
 
@@ -4769,11 +4773,11 @@  expand_float (rtx to, rtx from, int unsi
 	 correct its value by 2**bitwidth.  */
 
       do_pending_stack_adjust ();
-      emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
+      emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, from_mode,
 			       0, label);
 
 
-      real_2expN (&offset, GET_MODE_PRECISION (GET_MODE (from)), fmode);
+      real_2expN (&offset, GET_MODE_PRECISION (from_mode), fmode);
       temp = expand_binop (fmode, add_optab, target,
 			   const_double_from_real_value (offset, fmode),
 			   target, 0, OPTAB_LIB_WIDEN);
@@ -4901,11 +4905,14 @@  expand_fix (rtx to, rtx from, int unsign
      2^63.  The subtraction of 2^63 should not generate any rounding as it
      simply clears out that bit.  The rest is trivial.  */
 
-  if (unsignedp && GET_MODE_PRECISION (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
+  scalar_int_mode to_mode;
+  if (unsignedp
+      && is_a <scalar_int_mode> (GET_MODE (to), &to_mode)
+      && HWI_COMPUTABLE_MODE_P (to_mode))
     FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
-      if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
+      if (CODE_FOR_nothing != can_fix_p (to_mode, fmode, 0, &must_trunc)
 	  && (!DECIMAL_FLOAT_MODE_P (fmode)
-	      || GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (GET_MODE (to))))
+	      || GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (to_mode)))
 	{
 	  int bitsize;
 	  REAL_VALUE_TYPE offset;
@@ -4913,7 +4920,7 @@  expand_fix (rtx to, rtx from, int unsign
 	  rtx_code_label *lab1, *lab2;
 	  rtx_insn *insn;
 
-	  bitsize = GET_MODE_PRECISION (GET_MODE (to));
+	  bitsize = GET_MODE_PRECISION (to_mode);
 	  real_2expN (&offset, bitsize - 1, fmode);
 	  limit = const_double_from_real_value (offset, fmode);
 	  lab1 = gen_label_rtx ();
@@ -4939,10 +4946,10 @@  expand_fix (rtx to, rtx from, int unsign
 	  target = expand_binop (GET_MODE (from), sub_optab, from, limit,
 				 NULL_RTX, 0, OPTAB_LIB_WIDEN);
 	  expand_fix (to, target, 0);
-	  target = expand_binop (GET_MODE (to), xor_optab, to,
+	  target = expand_binop (to_mode, xor_optab, to,
 				 gen_int_mode
 				 (HOST_WIDE_INT_1 << (bitsize - 1),
-				  GET_MODE (to)),
+				  to_mode),
 				 to, 1, OPTAB_LIB_WIDEN);
 
 	  if (target != to)
@@ -4950,12 +4957,12 @@  expand_fix (rtx to, rtx from, int unsign
 
 	  emit_label (lab2);
 
-	  if (optab_handler (mov_optab, GET_MODE (to)) != CODE_FOR_nothing)
+	  if (optab_handler (mov_optab, to_mode) != CODE_FOR_nothing)
 	    {
 	      /* Make a place for a REG_NOTE and add it.  */
 	      insn = emit_move_insn (to, to);
 	      set_dst_reg_note (insn, REG_EQUAL,
-				gen_rtx_fmt_e (UNSIGNED_FIX, GET_MODE (to),
+				gen_rtx_fmt_e (UNSIGNED_FIX, to_mode,
 					       copy_rtx (from)),
 				to);
 	    }