MIPS16/GCC: Emit bounds checking as RTL in `casesi'
authorMaciej W. Rozycki <macro@imgtec.com>
Wed, 14 Jun 2017 23:26:40 +0000 (23:26 +0000)
committerMaciej W. Rozycki <macro@gcc.gnu.org>
Wed, 14 Jun 2017 23:26:40 +0000 (23:26 +0000)
gcc/
* config/mips/mips.md (MIPS16_T_REGNUM): Remove constant.
(casesi): Emit bounds checking as RTL.
(casesi_internal_mips16_<mode>): Remove bounds checking.

gcc/testsuite/
* gcc.target/mips/data-sym-jump.c: Adjust for whitespace changes.
* gcc.target/mips/pr51513-1.c: New test.
* gcc.target/mips/pr51513-2.c: New test.

From-SVN: r249207

gcc/ChangeLog
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/data-sym-jump.c
gcc/testsuite/gcc.target/mips/pr51513-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/pr51513-2.c [new file with mode: 0644]

index 09435d094dd5b098baaa7da70e84ac703bcb4d99..2d5110c8d86b636fb6993e8cd3dd2ee5047d6f55 100644 (file)
@@ -1,3 +1,9 @@
+2017-06-14  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * config/mips/mips.md (MIPS16_T_REGNUM): Remove constant.
+       (casesi): Emit bounds checking as RTL.
+       (casesi_internal_mips16_<mode>): Remove bounds checking.
+
 2017-06-14  Max Filippov  <jcmvbkbc@gmail.com>
 
        * config/xtensa/xtensa.c (xtensa_option_override): Append
index 28e0a444ba9d76ad9d29451216a3b898771d76c4..971af6f8e097d811e8a1279a93921a1b6feadb70 100644 (file)
   [(TLS_GET_TP_REGNUM          3)
    (GET_FCSR_REGNUM            2)
    (SET_FCSR_REGNUM            4)
-   (MIPS16_T_REGNUM            24)
    (PIC_FUNCTION_ADDR_REGNUM   25)
    (RETURN_ADDR_REGNUM         31)
    (CPRESTORE_SLOT_REGNUM      76)
   if (!arith_operand (operands[0], SImode))
     operands[0] = force_reg (SImode, operands[0]);
 
-  operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
-
+  emit_cmp_and_jump_insns (operands[0], operands[2], GTU,
+                          NULL_RTX, SImode, 1, operands[4]);
   emit_jump_insn (PMODE_INSN (gen_casesi_internal_mips16,
-                             (operands[0], operands[2],
-                              operands[3], operands[4])));
-
+                             (operands[0], operands[3])));
   DONE;
 })
 
 (define_insn "casesi_internal_mips16_<mode>"
   [(set (pc)
-     (if_then_else
-       (ltu (match_operand:SI 0 "register_operand" "d")
-           (match_operand:SI 1 "arith_operand" "dI"))
-       (unspec:P
-        [(match_dup 0)
-        (label_ref (match_operand 2 "" ""))]
-       UNSPEC_CASESI_DISPATCH)
-       (label_ref (match_operand 3 "" ""))))
-   (clobber (match_scratch:P 4 "=d"))
-   (clobber (match_scratch:P 5 "=d"))
-   (clobber (reg:SI MIPS16_T_REGNUM))]
+       (unspec:P [(match_operand:SI 0 "register_operand" "d")
+                  (label_ref (match_operand 1 "" ""))]
+        UNSPEC_CASESI_DISPATCH))
+   (clobber (match_scratch:P 2 "=d"))
+   (clobber (match_scratch:P 3 "=d"))]
   "TARGET_MIPS16_SHORT_JUMP_TABLES"
 {
-  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2])));
+  rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[1])));
 
   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
-  
-  output_asm_insn ("sltu\t%0, %1", operands);
-  output_asm_insn ("bteqz\t%3", operands);
-  
+
   switch (GET_MODE (diff_vec))
     {
     case HImode:
-      output_asm_insn ("sll\t%5, %0, 1", operands);
-      output_asm_insn ("<d>la\t%4, %2", operands);
-      output_asm_insn ("<d>addu\t%5, %4, %5", operands);
-      output_asm_insn ("lh\t%5, 0(%5)", operands);
+      output_asm_insn ("sll\t%3,%0,1", operands);
+      output_asm_insn ("<d>la\t%2,%1", operands);
+      output_asm_insn ("<d>addu\t%3,%2,%3", operands);
+      output_asm_insn ("lh\t%3,0(%3)", operands);
       break;
 
     case SImode:
-      output_asm_insn ("sll\t%5, %0, 2", operands);
-      output_asm_insn ("<d>la\t%4, %2", operands);
-      output_asm_insn ("<d>addu\t%5, %4, %5", operands);
-      output_asm_insn ("lw\t%5, 0(%5)", operands);
+      output_asm_insn ("sll\t%3,%0,2", operands);
+      output_asm_insn ("<d>la\t%2,%1", operands);
+      output_asm_insn ("<d>addu\t%3,%2,%3", operands);
+      output_asm_insn ("lw\t%3,0(%3)", operands);
       break;
 
     default:
       gcc_unreachable ();
     }
 
-  output_asm_insn ("<d>addu\t%4, %4, %5", operands);
+  output_asm_insn ("<d>addu\t%2,%2,%3", operands);
 
   if (GENERATE_MIPS16E)
-    return "jrc\t%4";
+    return "jrc\t%2";
   else
-    return "jr\t%4";
+    return "jr\t%2";
 }
   [(set (attr "insn_count")
        (if_then_else (match_test "GENERATE_MIPS16E")
-                     (const_string "10")
-                     (const_string "11")))])
+                     (const_string "6")
+                     (const_string "7")))])
 
 ;; For TARGET_USE_GOT, we save the gp in the jmp_buf as well.
 ;; While it is possible to either pull it off the stack (in the
index a0c522ea6800568f5e2d5b03c02c8d20b5237a73..dc82af015570afc6a6faab1dbed7315e121ccf30 100644 (file)
@@ -1,3 +1,9 @@
+2017-06-14  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * gcc.target/mips/data-sym-jump.c: Adjust for whitespace changes.
+       * gcc.target/mips/pr51513-1.c: New test.
+       * gcc.target/mips/pr51513-2.c: New test.
+
 2017-06-14  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/81083
index c3ba2944cdcc9130016788dac683bc1c7d6e65ce..ae48c0b4b5c8ee5a96ab05d8151373ff469be31b 100644 (file)
@@ -25,7 +25,7 @@ frob (int i)
 
 /* Expect assembly like:
 
-       la      $2, $L4
+       la      $2,$L4
                                                # Anything goes here.
        .type   __jump_frob_4, @object          # Symbol # must match label.
 __jump_frob_4:                                 # The symbol must match.
@@ -47,4 +47,4 @@ __jend_frob_4:                                        # The symbol must match.
 
    that is `__jump_*'/`__jend_*' symbols inserted around a jump table.  */
 
-/* { dg-final { scan-assembler "\tla\t\\\$\[0-9\]+, (.L(\[0-9\]+))\n.*\t\\.type\t(__jump_frob_\\2), @object\n\\3:\n\\1:\n(?:\t\\.(?:half|word)\t.L\[0-9\]+-\\1\n)\{11\}\t\\.type\t(__jend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
+/* { dg-final { scan-assembler "\tla\t\\\$\[0-9\]+,(.L(\[0-9\]+))\n.*\t\\.type\t(__jump_frob_\\2), @object\n\\3:\n\\1:\n(?:\t\\.(?:half|word)\t.L\[0-9\]+-\\1\n)\{11\}\t\\.type\t(__jend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/pr51513-1.c b/gcc/testsuite/gcc.target/mips/pr51513-1.c
new file mode 100644 (file)
index 0000000..b5e0d69
--- /dev/null
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+
+/* PR tree-optimization/51513 verification variant for MIPS16, #1.  */
+
+int __attribute__ ((weak))
+frob (int i)
+{
+  switch (i)
+    {
+    case -5:
+      return -2;
+    case -3:
+      return -1;
+    case 0:
+      return 0;
+    case 3:
+      return 1;
+    case 5:
+      break;
+    default:
+      __builtin_unreachable ();
+    }
+  return i;
+}
+
+/* Without the fix for PR tree-optimization/51513 truncated code
+   would be emitted for `frob', like:
+
+       .text
+       .align  2
+       .weak   frob
+       .set    mips16
+       .set    nomicromips
+       .ent    frob
+       .type   frob, @function
+frob:
+       .frame  $sp,0,$31               # vars= 0, regs= 0/0, args= 0, gp= 0
+       .mask   0x00000000,0
+       .fmask  0x00000000,0
+       addiu   $2,$4,5
+       .end    frob
+       .size   frob, .-frob
+
+  meaning `frob' will have no chance to return, let alone produce
+  the result expected.  */
+
+/* { dg-final { scan-assembler "\tjrc?\t\\\$31\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/pr51513-2.c b/gcc/testsuite/gcc.target/mips/pr51513-2.c
new file mode 100644 (file)
index 0000000..b921904
--- /dev/null
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+
+/* PR tree-optimization/51513 verification variant for MIPS16, #2.  */
+
+int __attribute__ ((weak))
+frob (int i)
+{
+  switch (i)
+    {
+    case -5:
+      return -2;
+    case -3:
+      return -1;
+    case 0:
+      return 0;
+    case 3:
+      return 1;
+    case 5:
+      break;
+    default:
+      __builtin_unreachable ();
+    }
+  return i;
+}
+
+int
+main (void)
+{
+  return !(frob (-5) == -2
+          & frob (-3) == -1
+          & frob (0) == 0
+          & frob (3) == 1
+          & frob (5) == 5);
+}
+
+/* Without the fix for PR tree-optimization/51513 truncated code
+   would be emitted for `frob', like:
+
+       .text
+       .align  2
+       .weak   frob
+       .set    mips16
+       .set    nomicromips
+       .ent    frob
+       .type   frob, @function
+frob:
+       .frame  $sp,0,$31               # vars= 0, regs= 0/0, args= 0, gp= 0
+       .mask   0x00000000,0
+       .fmask  0x00000000,0
+       addiu   $2,$4,5
+       .end    frob
+       .size   frob, .-frob
+
+  meaning `frob' will have no chance to return, let alone produce
+  the result expected.  */