[70/77] Make expand_fix/float check for scalar modes
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 30 Aug 2017 11:20:11 +0000 (11:20 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 30 Aug 2017 11:20:11 +0000 (11:20 +0000)
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-08-30  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.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r251521

gcc/ChangeLog
gcc/optabs.c

index 36cfad066477c7e5c39e4409cc1ff54114cd1829..c4407d6852d90abaec601bb02dc8db680aa4099d 100644 (file)
@@ -1,3 +1,11 @@
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * optabs.c (expand_float): Explicitly check for scalars before
+       using a branching expansion.
+       (expand_fix): Likewise.
+
 2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 49f35b007bee4219783595b5c75667fecb151d29..d3ceabab8f05c9373ace0193683b348714f8ed7c 100644 (file)
@@ -4637,6 +4637,7 @@ expand_float (rtx to, rtx from, int unsignedp)
 {
   enum insn_code icode;
   rtx target = to;
+  scalar_mode from_mode, to_mode;
   machine_mode fmode, imode;
   bool can_do_signed = false;
 
@@ -4686,7 +4687,10 @@ expand_float (rtx to, rtx from, int unsignedp)
 
   /* 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;
@@ -4696,19 +4700,19 @@ expand_float (rtx to, rtx from, int unsignedp)
         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 ();
@@ -4720,7 +4724,7 @@ expand_float (rtx to, rtx from, int unsignedp)
                  || 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.  */
@@ -4760,7 +4764,7 @@ expand_float (rtx to, rtx from, int unsignedp)
       /* 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);
 
@@ -4771,11 +4775,11 @@ expand_float (rtx to, rtx from, int unsignedp)
         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);
@@ -4903,11 +4907,14 @@ expand_fix (rtx to, rtx from, int unsignedp)
      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;
@@ -4915,7 +4922,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
          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 ();
@@ -4941,10 +4948,10 @@ expand_fix (rtx to, rtx from, int unsignedp)
          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)
@@ -4952,12 +4959,12 @@ expand_fix (rtx to, rtx from, int unsignedp)
 
          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);
            }