OSDN Git Service

* config/mips/mips.c (mips_expand_prologue): Use a single insn to
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 14 Jul 2003 20:41:27 +0000 (20:41 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 14 Jul 2003 20:41:27 +0000 (20:41 +0000)
allocate 32768 bytes of stack.  Use addition rather than subtraction
when a single insn is enough.
* config/mips/mips.md: Remove insns and splitters for subtracting
constants.
(subsi3): Only accept register operands.
(subsi3_internal): Likewise.  Use for TARGET_MIPS16 as well.
(subdi3_internal_3, subsi3_internal_2): Likewise.
(casesi): Use expand_binop to subtract the lower bound.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@69357 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.md

index 76e3fc1..accf42b 100644 (file)
@@ -1,5 +1,17 @@
 2003-07-14  Richard Sandiford  <rsandifo@redhat.com>
 
+       * config/mips/mips.c (mips_expand_prologue): Use a single insn to
+       allocate 32768 bytes of stack.  Use addition rather than subtraction
+       when a single insn is enough.
+       * config/mips/mips.md: Remove insns and splitters for subtracting
+       constants.
+       (subsi3): Only accept register operands.
+       (subsi3_internal): Likewise.  Use for TARGET_MIPS16 as well.
+       (subdi3_internal_3, subsi3_internal_2): Likewise.
+       (casesi): Use expand_binop to subtract the lower bound.
+
+2003-07-14  Richard Sandiford  <rsandifo@redhat.com>
+
        * config/mips/mips.c (mips_in_small_data_p): Don't handle
        TARGET_MIPS16 specially.
 
index bb52f5c..5e069b7 100644 (file)
@@ -7424,27 +7424,24 @@ mips_expand_prologue ()
     {
       rtx tsize_rtx = GEN_INT (tsize);
 
-      /* If we are doing svr4-abi, sp move is done by
-         function_prologue.  In mips16 mode with a large frame, we
-         save the registers before adjusting the stack.  */
-      if (!TARGET_MIPS16 || tsize <= 32767)
+      /* In mips16 mode with a large frame, we save the registers before
+         adjusting the stack.  */
+      if (!TARGET_MIPS16 || tsize <= 32768)
        {
-         rtx adjustment_rtx;
-
-         if (tsize > 32767)
+         if (tsize > 32768)
            {
+             rtx adjustment_rtx;
+
              adjustment_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
              emit_move_insn (adjustment_rtx, tsize_rtx);
+             emit_insn (gen_sub3_insn (stack_pointer_rtx,
+                                       stack_pointer_rtx,
+                                       adjustment_rtx));
            }
          else
-           adjustment_rtx = tsize_rtx;
-
-         if (Pmode == DImode)
-           emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                  adjustment_rtx));
-         else
-           emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                  adjustment_rtx));
+           emit_insn (gen_add3_insn (stack_pointer_rtx,
+                                     stack_pointer_rtx,
+                                     GEN_INT (-tsize)));
 
          mips_set_frame_expr
            (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
@@ -7460,7 +7457,7 @@ mips_expand_prologue ()
        emit_insn (gen_cprestore
                   (GEN_INT (current_function_outgoing_args_size)));
 
-      if (TARGET_MIPS16 && tsize > 32767)
+      if (TARGET_MIPS16 && tsize > 32768)
        {
          rtx reg_rtx;
 
@@ -7470,14 +7467,9 @@ mips_expand_prologue ()
          reg_rtx = gen_rtx (REG, Pmode, 3);
          emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
          emit_move_insn (reg_rtx, tsize_rtx);
-         if (Pmode == DImode)
-           emit_insn (gen_subdi3 (hard_frame_pointer_rtx,
-                                  hard_frame_pointer_rtx,
-                                  reg_rtx));
-         else
-           emit_insn (gen_subsi3 (hard_frame_pointer_rtx,
-                                  hard_frame_pointer_rtx,
-                                  reg_rtx));
+         emit_insn (gen_sub3_insn (hard_frame_pointer_rtx,
+                                   hard_frame_pointer_rtx,
+                                   reg_rtx));
          emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
        }
 
index 0be1173..d30f469 100644 (file)
    (set_attr "mode"    "SF")])
 
 (define_expand "subsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ")
-                 (match_operand:SI 2 "arith_operand" "dI")))]
+  [(set (match_operand:SI 0 "register_operand" "")
+       (minus:SI (match_operand:SI 1 "register_operand" "")
+                 (match_operand:SI 2 "register_operand" "")))]
   ""
-  "
-{
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (INTVAL (operands[2]) == -32768
-         || (TARGET_MIPS16
-             && INTVAL (operands[2]) == -0x4000)))
-    operands[2] = force_reg (SImode, operands[2]);
-}")
+  "")
 
 (define_insn "subsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=d")
-       (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ")
-                 (match_operand:SI 2 "arith_operand" "dI")))]
-  "!TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
+       (minus:SI (match_operand:SI 1 "register_operand" "d")
+                 (match_operand:SI 2 "register_operand" "d")))]
+  ""
   "subu\\t%0,%z1,%2"
   [(set_attr "type"    "arith")
    (set_attr "mode"    "SI")])
 
-;; For the mips16, we need to recognize stack pointer subtractions
-;; explicitly, since we don't have a constraint for $sp.  These insns
-;; will be generated by the save_restore_insns functions.
-
-(define_insn ""
-  [(set (reg:SI 29)
-       (minus:SI (reg:SI 29)
-                 (match_operand:SI 0 "small_int" "I")))]
-  "TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
-  "addu\\t%$,%$,%n0"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "SI")
-   (set (attr "length")        (if_then_else (match_operand:VOID 0 "m16_nsimm8_8" "")
-                                     (const_int 4)
-                                     (const_int 8)))])
-
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (minus:SI (reg:SI 29)
-                 (match_operand:SI 1 "small_int" "I")))]
-  "TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
-  "addu\\t%0,%$,%n1"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "SI")
-   (set (attr "length")        (if_then_else (match_operand:VOID 1 "m16_nuimm8_4" "")
-                                     (const_int 4)
-                                     (const_int 8)))])
-
-
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-       (minus:SI (match_operand:SI 1 "register_operand" "0,d,d")
-                 (match_operand:SI 2 "arith_operand" "I,O,d")))]
-  "TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT
-       || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))"
-  "*
-{
-  if (REGNO (operands[0]) == REGNO (operands[1]))
-    return \"subu\\t%0,%2\";
-  return \"subu\\t%0,%1,%2\";
-}"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "SI")
-   (set_attr_alternative "length"
-               [(if_then_else (match_operand:VOID 2 "m16_nsimm8_1" "")
-                              (const_int 4)
-                              (const_int 8))
-                (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "")
-                              (const_int 4)
-                              (const_int 8))
-                (const_int 4)])])
-
-;; On the mips16, we can sometimes split a subtract of a constant
-;; which is a 4 byte instruction into two adds which are both 2 byte
-;; instructions.  There are two cases: one where we are setting a
-;; register to a register minus a constant, and one where we are
-;; simply subtracting a constant from a register.
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (minus:SI (match_dup 0)
-                 (match_operand:SI 1 "const_int_operand" "")))]
-  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
-   && GET_CODE (operands[0]) == REG
-   && M16_REG_P (REGNO (operands[0]))
-   && GET_CODE (operands[1]) == CONST_INT
-   && ((INTVAL (operands[1]) > 0x80
-       && INTVAL (operands[1]) <= 0x80 + 0x80)
-       || (INTVAL (operands[1]) < - 0x7f
-          && INTVAL (operands[1]) >= - 0x7f - 0x7f))"
-  [(set (match_dup 0) (minus:SI (match_dup 0) (match_dup 1)))
-   (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 2)))]
-  "
-{
-  HOST_WIDE_INT val = INTVAL (operands[1]);
-
-  if (val >= 0)
-    {
-      operands[1] = GEN_INT (0x80);
-      operands[2] = GEN_INT (val - 0x80);
-    }
-  else
-    {
-      operands[1] = GEN_INT (- 0x7f);
-      operands[2] = GEN_INT (val + 0x7f);
-    }
-}")
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (minus:SI (match_operand:SI 1 "register_operand" "")
-                 (match_operand:SI 2 "const_int_operand" "")))]
-  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
-   && GET_CODE (operands[0]) == REG
-   && M16_REG_P (REGNO (operands[0]))
-   && GET_CODE (operands[1]) == REG
-   && M16_REG_P (REGNO (operands[1]))
-   && REGNO (operands[0]) != REGNO (operands[1])
-   && GET_CODE (operands[2]) == CONST_INT
-   && ((INTVAL (operands[2]) > 0x8
-       && INTVAL (operands[2]) <= 0x8 + 0x80)
-       || (INTVAL (operands[2]) < - 0x7
-          && INTVAL (operands[2]) >= - 0x7 - 0x7f))"
-  [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 3)))]
-  "
-{
-  HOST_WIDE_INT val = INTVAL (operands[2]);
-
-  if (val >= 0)
-    {
-      operands[2] = GEN_INT (0x8);
-      operands[3] = GEN_INT (val - 0x8);
-    }
-  else
-    {
-      operands[2] = GEN_INT (- 0x7);
-      operands[3] = GEN_INT (val + 0x7);
-    }
-}")
-
 (define_expand "subdi3"
   [(parallel [(set (match_operand:DI 0 "register_operand" "=d")
                   (minus:DI (match_operand:DI 1 "register_operand" "d")
                  (match_dup 3)))]
   "")
 
-(define_insn "subdi3_internal_2"
-  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
-       (minus:DI (match_operand:DI 1 "register_operand" "d,d,d")
-                 (match_operand:DI 2 "small_int" "P,J,N")))
-   (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))]
-  "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16
-   && INTVAL (operands[2]) != -32768"
-  "@
-   sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,%3
-   move\\t%L0,%L1\;move\\t%M0,%M1
-   sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,1\;subu\\t%M0,%M0,%3"
-  [(set_attr "type"    "darith")
-   (set_attr "mode"    "DI")
-   (set_attr "length"  "12,8,16")])
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (minus:DI (match_operand:DI 1 "register_operand" "")
-                 (match_operand:DI 2 "small_int" "")))
-   (clobber (match_operand:SI 3 "register_operand" ""))]
-  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
-   && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16
-   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
-   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
-   && INTVAL (operands[2]) > 0"
-
-  [(set (match_dup 3)
-       (ltu:SI (subreg:SI (match_dup 1) 0)
-               (match_dup 2)))
-
-   (set (subreg:SI (match_dup 0) 0)
-       (minus:SI (subreg:SI (match_dup 1) 0)
-                 (match_dup 2)))
-
-   (set (subreg:SI (match_dup 0) 4)
-       (minus:SI (subreg:SI (match_dup 1) 4)
-                 (match_dup 3)))]
-  "")
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (minus:DI (match_operand:DI 1 "register_operand" "")
-                 (match_operand:DI 2 "small_int" "")))
-   (clobber (match_operand:SI 3 "register_operand" ""))]
-  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
-   && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16
-   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
-   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
-   && INTVAL (operands[2]) > 0"
-
-  [(set (match_dup 3)
-       (ltu:SI (subreg:SI (match_dup 1) 4)
-               (match_dup 2)))
-
-   (set (subreg:SI (match_dup 0) 4)
-       (minus:SI (subreg:SI (match_dup 1) 4)
-                 (match_dup 2)))
-
-   (set (subreg:SI (match_dup 0) 0)
-       (minus:SI (subreg:SI (match_dup 1) 0)
-                 (match_dup 3)))]
-  "")
-
 (define_insn "subdi3_internal_3"
   [(set (match_operand:DI 0 "register_operand" "=d")
-       (minus:DI (match_operand:DI 1 "reg_or_0_operand" "dJ")
-                 (match_operand:DI 2 "arith_operand" "dI")))]
-  "TARGET_64BIT && !TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
-  "*
-{
-  return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
-    ? \"daddu\\t%0,%z1,%n2\"
-    : \"dsubu\\t%0,%z1,%2\";
-}"
+       (minus:DI (match_operand:DI 1 "register_operand" "d")
+                 (match_operand:DI 2 "register_operand" "d")))]
+  "TARGET_64BIT"
+  "dsubu\\t%0,%1,%2"
   [(set_attr "type"    "darith")
    (set_attr "mode"    "DI")])
 
-;; For the mips16, we need to recognize stack pointer subtractions
-;; explicitly, since we don't have a constraint for $sp.  These insns
-;; will be generated by the save_restore_insns functions.
-
-(define_insn ""
-  [(set (reg:DI 29)
-       (minus:DI (reg:DI 29)
-                 (match_operand:DI 0 "small_int" "I")))]
-  "TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
-  "daddu\\t%$,%$,%n0"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "DI")
-   (set (attr "length")        (if_then_else (match_operand:VOID 0 "m16_nsimm8_8" "")
-                                     (const_int 4)
-                                     (const_int 8)))])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=d")
-       (minus:DI (reg:DI 29)
-                 (match_operand:DI 1 "small_int" "I")))]
-  "TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
-  "daddu\\t%0,%$,%n1"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "DI")
-   (set (attr "length")        (if_then_else (match_operand:VOID 0 "m16_nuimm5_4" "")
-                                     (const_int 4)
-                                     (const_int 8)))])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
-       (minus:DI (match_operand:DI 1 "register_operand" "0,d,d")
-                 (match_operand:DI 2 "arith_operand" "I,O,d")))]
-  "TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT
-       || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))"
-  "*
-{
-  if (REGNO (operands[0]) == REGNO (operands[1]))
-    return \"dsubu\\t%0,%2\";
-  return \"dsubu\\t%0,%1,%2\";
-}"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "DI")
-   (set_attr_alternative "length"
-               [(if_then_else (match_operand:VOID 2 "m16_nsimm5_1" "")
-                              (const_int 4)
-                              (const_int 8))
-                (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "")
-                              (const_int 4)
-                              (const_int 8))
-                (const_int 4)])])
-
-;; On the mips16, we can sometimes split an add of a constant which is
-;; a 4 byte instruction into two adds which are both 2 byte
-;; instructions.  There are two cases: one where we are adding a
-;; constant plus a register to another register, and one where we are
-;; simply adding a constant to a register.
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (minus:DI (match_dup 0)
-                 (match_operand:DI 1 "const_int_operand" "")))]
-  "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
-   && GET_CODE (operands[0]) == REG
-   && M16_REG_P (REGNO (operands[0]))
-   && GET_CODE (operands[1]) == CONST_INT
-   && ((INTVAL (operands[1]) > 0x10
-       && INTVAL (operands[1]) <= 0x10 + 0x10)
-       || (INTVAL (operands[1]) < - 0xf
-          && INTVAL (operands[1]) >= - 0xf - 0xf))"
-  [(set (match_dup 0) (minus:DI (match_dup 0) (match_dup 1)))
-   (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))]
-  "
-{
-  HOST_WIDE_INT val = INTVAL (operands[1]);
-
-  if (val >= 0)
-    {
-      operands[1] = GEN_INT (0xf);
-      operands[2] = GEN_INT (val - 0xf);
-    }
-  else
-    {
-      operands[1] = GEN_INT (- 0x10);
-      operands[2] = GEN_INT (val + 0x10);
-    }
-}")
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (minus:DI (match_operand:DI 1 "register_operand" "")
-                 (match_operand:DI 2 "const_int_operand" "")))]
-  "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
-   && GET_CODE (operands[0]) == REG
-   && M16_REG_P (REGNO (operands[0]))
-   && GET_CODE (operands[1]) == REG
-   && M16_REG_P (REGNO (operands[1]))
-   && REGNO (operands[0]) != REGNO (operands[1])
-   && GET_CODE (operands[2]) == CONST_INT
-   && ((INTVAL (operands[2]) > 0x8
-       && INTVAL (operands[2]) <= 0x8 + 0x10)
-       || (INTVAL (operands[2]) < - 0x7
-          && INTVAL (operands[2]) >= - 0x7 - 0xf))"
-  [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 3)))]
-  "
-{
-  HOST_WIDE_INT val = INTVAL (operands[2]);
-
-  if (val >= 0)
-    {
-      operands[2] = GEN_INT (0x8);
-      operands[3] = GEN_INT (val - 0x8);
-    }
-  else
-    {
-      operands[2] = GEN_INT (- 0x7);
-      operands[3] = GEN_INT (val + 0x7);
-    }
-}")
-
 (define_insn "subsi3_internal_2"
   [(set (match_operand:DI 0 "register_operand" "=d")
-       (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ")
-                                 (match_operand:SI 2 "arith_operand" "dI"))))]
-  "TARGET_64BIT && !TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
-  "*
-{
-  return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
-    ? \"addu\\t%0,%z1,%n2\"
-    : \"subu\\t%0,%z1,%2\";
-}"
+       (sign_extend:DI
+           (minus:SI (match_operand:SI 1 "register_operand" "d")
+                     (match_operand:SI 2 "register_operand" "d"))))]
+  "TARGET_64BIT"
+  "subu\t%0,%1,%2"
   [(set_attr "type"    "arith")
    (set_attr "mode"    "DI")])
-
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
-       (sign_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0,d,d")
-                                 (match_operand:SI 2 "arith_operand" "I,O,d"))))]
-  "TARGET_64BIT && TARGET_MIPS16
-   && (GET_CODE (operands[2]) != CONST_INT
-       || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))"
-  "*
-{
-  if (REGNO (operands[0]) == REGNO (operands[1]))
-    return \"subu\\t%0,%2\";
-  return \"subu\\t%0,%1,%2\";
-}"
-  [(set_attr "type"    "arith")
-   (set_attr "mode"    "SI")
-   (set_attr_alternative "length"
-               [(if_then_else (match_operand:VOID 2 "m16_nsimm8_1" "")
-                              (const_int 4)
-                              (const_int 8))
-                (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "")
-                              (const_int 4)
-                              (const_int 8))
-                (const_int 4)])])
-
-
 \f
 ;;
 ;;  ....................
@@ -8540,8 +8185,8 @@ move\\t%0,%z4\\n\\
 
 (define_expand "casesi"
   [(set (match_dup 5)
-       (minus:SI (match_operand:SI 0 "register_operand" "d")
-                 (match_operand:SI 1 "arith_operand" "dI")))
+       (minus:SI (match_operand:SI 0 "register_operand" "")
+                 (match_operand:SI 1 "const_int_operand" "")))
    (set (cc0)
        (compare:CC (match_dup 5)
                    (match_operand:SI 2 "arith_operand" "")))
@@ -8562,19 +8207,20 @@ move\\t%0,%z4\\n\\
 {
   if (operands[0])
     {
-      rtx reg = gen_reg_rtx (SImode);
+      rtx index;
 
       /* If the index is too large, go to the default label.  */
-      emit_insn (gen_subsi3 (reg, operands[0], operands[1]));
-      emit_insn (gen_cmpsi (reg, operands[2]));
+      index = expand_binop (SImode, sub_optab, operands[0],
+                           operands[1], 0, 0, OPTAB_WIDEN);
+      emit_insn (gen_cmpsi (index, operands[2]));
       emit_insn (gen_bgtu (operands[4]));
 
       /* Do the PIC jump.  */
       if (Pmode != DImode)
-        emit_jump_insn (gen_casesi_internal (reg, operands[3],
+        emit_jump_insn (gen_casesi_internal (index, operands[3],
                                             gen_reg_rtx (SImode)));
       else
-        emit_jump_insn (gen_casesi_internal_di (reg, operands[3],
+        emit_jump_insn (gen_casesi_internal_di (index, operands[3],
                                                gen_reg_rtx (DImode)));
 
       DONE;