MIPS/GCC: Mark trailing labels with `.insn'
authorMaciej W. Rozycki <macro@imgtec.com>
Tue, 15 Nov 2016 15:04:10 +0000 (15:04 +0000)
committerMaciej W. Rozycki <macro@gcc.gnu.org>
Tue, 15 Nov 2016 15:04:10 +0000 (15:04 +0000)
gcc/
* config/mips/mips.c (mips16_emit_constants): Emit `consttable'
insn at the beginning of the constant pool.
(mips_insert_insn_pseudos): New function.
(mips_machine_reorg2): Call it.
* config/mips/mips.md (unspec): Add UNSPEC_CONSTTABLE and
UNSPEC_INSN_PSEUDO enum values.
(insn_pseudo, consttable): New insns.

gcc/testsuite/
* gcc.target/mips/insn-casesi.c: New test case.
* gcc.target/mips/insn-pseudo-1.c: New test case.
* gcc.target/mips/insn-pseudo-2.c: New test case.
* gcc.target/mips/insn-pseudo-3.c: New test case.
* gcc.target/mips/insn-pseudo-4.c: New test case.
* gcc.target/mips/insn-tablejump.c: New test case.

From-SVN: r242424

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/insn-casesi.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/insn-pseudo-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/insn-pseudo-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/insn-pseudo-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/insn-pseudo-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/insn-tablejump.c [new file with mode: 0644]

index c4a660f0cff6ab62099983fb0730ccaf8526ae29..b91bf89652c2a5637574c4b9beab5b95bd2ea897 100644 (file)
@@ -1,3 +1,13 @@
+2016-11-15  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * config/mips/mips.c (mips16_emit_constants): Emit `consttable'
+       insn at the beginning of the constant pool.
+       (mips_insert_insn_pseudos): New function.
+       (mips_machine_reorg2): Call it.
+       * config/mips/mips.md (unspec): Add UNSPEC_CONSTTABLE and
+       UNSPEC_INSN_PSEUDO enum values.
+       (insn_pseudo, consttable): New insns.
+
 2016-11-15  Michael Matz  <matz@suse.de>
 
        PR missed-optimization/77881
index 552b73adaf740cc98c52cea45822a287f280266e..44cdeb72c1d41823091e4032983ae472cdfa53c3 100644 (file)
@@ -17140,6 +17140,8 @@ mips16_emit_constants (struct mips16_constant *constants, rtx_insn *insn)
   int align;
 
   align = 0;
+  if (constants)
+    insn = emit_insn_after (gen_consttable (), insn);
   for (c = constants; c != NULL; c = next)
     {
       /* If necessary, increase the alignment of PC.  */
@@ -19015,6 +19017,46 @@ mips16_split_long_branches (void)
   while (something_changed);
 }
 
+/* Insert a `.insn' assembly pseudo-op after any labels followed by
+   a MIPS16 constant pool or no insn at all.  This is needed so that
+   targets that have been optimized away are still marked as code
+   and therefore branches that remained and point to them are known
+   to retain the ISA mode and as such can be successfully assembled.  */
+
+static void
+mips_insert_insn_pseudos (void)
+{
+  bool insn_pseudo_needed = TRUE;
+  rtx_insn *insn;
+
+  for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn))
+    switch (GET_CODE (insn))
+      {
+      case INSN:
+       if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+           && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE)
+         {
+           insn_pseudo_needed = TRUE;
+           break;
+         }
+       /* Fall through.  */
+      case JUMP_INSN:
+      case CALL_INSN:
+      case JUMP_TABLE_DATA:
+       insn_pseudo_needed = FALSE;
+       break;
+      case CODE_LABEL:
+       if (insn_pseudo_needed)
+         {
+           emit_insn_after (gen_insn_pseudo (), insn);
+           insn_pseudo_needed = FALSE;
+         }
+       break;
+      default:
+       break;
+      }
+}
+
 /* Implement TARGET_MACHINE_DEPENDENT_REORG.  */
 
 static void
@@ -19050,6 +19092,7 @@ mips_machine_reorg2 (void)
        optimizations, but this should be an extremely rare case anyhow.  */
     mips_reorg_process_insns ();
   mips16_split_long_branches ();
+  mips_insert_insn_pseudos ();
   return 0;
 }
 
index d8d564fabd9cc74c268f98762d17e9e09987315e..b7e8e96820d77aa98a0f5c2e650bd6366c135967 100644 (file)
 
   ;; MIPS16 constant pools.
   UNSPEC_ALIGN
+  UNSPEC_CONSTTABLE
   UNSPEC_CONSTTABLE_INT
   UNSPEC_CONSTTABLE_FLOAT
 
 
   ;; Stack checking.
   UNSPEC_PROBE_STACK_RANGE
+
+  ;; The `.insn' pseudo-op.
+  UNSPEC_INSN_PSEUDO
 ])
 
 (define_constants
       return "#nop";
   }
   [(set_attr "type"    "nop")])
+
+;; The `.insn' pseudo-op.
+(define_insn "insn_pseudo"
+  [(unspec_volatile [(const_int 0)] UNSPEC_INSN_PSEUDO)]
+  ""
+  ".insn"
+  [(set_attr "mode" "none")
+   (set_attr "insn_count" "0")])
 \f
 ;; MIPS4 Conditional move instructions.
 
 ;;  ....................
 ;;
 
+(define_insn "consttable"
+  [(unspec_volatile [(const_int 0)] UNSPEC_CONSTTABLE)]
+  ""
+  ""
+  [(set_attr "mode" "none")
+   (set_attr "insn_count" "0")])
+
 (define_insn "consttable_tls_reloc"
   [(unspec_volatile [(match_operand 0 "tls_reloc_operand" "")
                     (match_operand 1 "const_int_operand" "")]
index e7e78506ef22098d307d442a9d9887122ac7963d..e0c99bf50a2d37749334f3bde8305bdf7da42e01 100644 (file)
@@ -1,3 +1,12 @@
+2016-11-15  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * gcc.target/mips/insn-casesi.c: New test case.
+       * gcc.target/mips/insn-pseudo-1.c: New test case.
+       * gcc.target/mips/insn-pseudo-2.c: New test case.
+       * gcc.target/mips/insn-pseudo-3.c: New test case.
+       * gcc.target/mips/insn-pseudo-4.c: New test case.
+       * gcc.target/mips/insn-tablejump.c: New test case.
+
 2016-11-15  Maciej W. Rozycki  <macro@imgtec.com>
 
        * gcc.target/mips/mips.exp (mips_option_tests): Add
diff --git a/gcc/testsuite/gcc.target/mips/insn-casesi.c b/gcc/testsuite/gcc.target/mips/insn-casesi.c
new file mode 100644 (file)
index 0000000..2b4c9f2
--- /dev/null
@@ -0,0 +1,112 @@
+/* { dg-do run } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+
+int __attribute__ ((noinline))
+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 (int argc, char **argv)
+{
+  asm ("" : "+r" (argc));
+  argc = frob ((argc & 10) - 5);
+  asm ("" : "+r" (argc));
+  return !argc;
+}
+
+/* This will result in assembly like:
+
+       .text
+       .align  2
+       .globl  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
+       sltu    $2,11
+       bteqz   $L2
+       sll     $3,$2,1
+       la      $2,$L4
+       addu    $3,$2,$3
+       lh      $3,0($3)
+       addu    $2,$2,$3
+       j       $2
+       .align  1
+       .align  2
+$L4:
+       .half   $L3-$L4
+       .half   $L2-$L4
+       .half   $L9-$L4
+       .half   $L2-$L4
+       .half   $L2-$L4
+       .half   $L8-$L4
+       .half   $L2-$L4
+       .half   $L2-$L4
+       .half   $L7-$L4
+       .half   $L2-$L4
+       .half   $L8-$L4
+$L8:
+       .set    noreorder
+       .set    nomacro
+       jr      $31
+       move    $2,$4
+       .set    macro
+       .set    reorder
+
+$L9:
+       li      $2,1
+       .set    noreorder
+       .set    nomacro
+       jr      $31
+       neg     $2,$2
+       .set    macro
+       .set    reorder
+
+$L3:
+       li      $2,2
+       .set    noreorder
+       .set    nomacro
+       jr      $31
+       neg     $2,$2
+       .set    macro
+       .set    reorder
+
+$L7:
+       .set    noreorder
+       .set    nomacro
+       jr      $31
+       li      $2,1
+       .set    macro
+       .set    reorder
+
+$L2:
+       .insn
+       .end    frob
+       .size   frob, .-frob
+
+  for `frob' and we want to make sure it links correctly owing to the
+  `.insn' pseudo-op which needs to be there at `$L2' as there's no
+  code following and the label is a MIPS16 branch target (even though
+  the branch is never taken.  See also insn-tablejump.c.  */
diff --git a/gcc/testsuite/gcc.target/mips/insn-pseudo-1.c b/gcc/testsuite/gcc.target/mips/insn-pseudo-1.c
new file mode 100644 (file)
index 0000000..4250195
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-micromips -mno-mips16" } */
+
+void
+unreachable (int i)
+{
+  asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (i) : : punt);
+punt:
+  __builtin_unreachable ();
+}
+
+/* Expect assembly like:
+
+       beqz    $4,$L2
+                               # Anything goes here.
+$L2:                           # The label must match.
+       .insn
+$L3 = .                                # It's there, but we don't care.
+       .end    unreachable
+
+   that is .insn to be inserted if a code label is at function's end.  */
+
+/* { dg-final { scan-assembler "\tbeqz\t\\\$\[0-9\]+,(.L\[0-9\]+)\n.*\n\\1:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.end\tunreachable\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/insn-pseudo-2.c b/gcc/testsuite/gcc.target/mips/insn-pseudo-2.c
new file mode 100644 (file)
index 0000000..81fb259
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mmicromips" } */
+
+void
+unreachable (int i)
+{
+  asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (i) : : punt);
+punt:
+  __builtin_unreachable ();
+}
+
+/* Expect assembly like:
+
+       beqz    $4,$L2
+                               # Anything goes here.
+$L2:                           # The label must match.
+       .insn
+$L3 = .                                # It's there, but we don't care.
+       .end    unreachable
+
+   that is .insn to be inserted if a code label is at function's end.  */
+
+/* { dg-final { scan-assembler "\tbeqz\t\\\$\[0-9\]+,(.L\[0-9\]+)\n.*\n\\1:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.end\tunreachable\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/insn-pseudo-3.c b/gcc/testsuite/gcc.target/mips/insn-pseudo-3.c
new file mode 100644 (file)
index 0000000..49b7622
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16" } */
+
+void
+unreachable (int i)
+{
+  asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (i) : : punt);
+punt:
+  __builtin_unreachable ();
+}
+
+/* Expect assembly like:
+
+       beqz    $4,$L2
+                               # Anything goes here.
+$L2:                           # The label must match.
+       .insn
+$L3 = .                                # It's there, but we don't care.
+       .end    unreachable
+
+   that is .insn to be inserted if a code label is at function's end.  */
+
+/* { dg-final { scan-assembler "\tbeqz\t\\\$\[0-9\]+,(.L\[0-9\]+)\n.*\n\\1:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.end\tunreachable\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c b/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c
new file mode 100644 (file)
index 0000000..49a4851
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+
+void
+unreachable (void)
+{
+  asm volatile goto ("b\t.\n\tbeqz\t%0,%l1" : : "r" (0x12345678) : : punt);
+punt:
+  __builtin_unreachable ();
+}
+
+/* Expect assembly like:
+
+       lw      $2,$L5
+                               # Anything goes here.
+       beqz    $2,$L2          # The register must match.
+                               # Anything goes here.
+$L2:                           # The label must match.
+       .insn
+$L3 = .                                # It's there, but we don't care.
+       .align  2
+$L5:                           # The label must match.
+       .word   305419896
+
+   that is .insn to be inserted if a code label is at a constant pool.  */
+
+/* { dg-final { scan-assembler "\tlw\t(\\\$\[0-9\]+),(.L\[0-9\]+)\n.*\tbeqz\t\\1,(.L\[0-9\]+)\n.*\n\\3:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.align\t2\n\\2:\n\t\\.word\t305419896\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/insn-tablejump.c b/gcc/testsuite/gcc.target/mips/insn-tablejump.c
new file mode 100644 (file)
index 0000000..ecba154
--- /dev/null
@@ -0,0 +1,98 @@
+/* { dg-do run } */
+/* { dg-options "-mmicromips" } */
+
+int __attribute__ ((noinline))
+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 (int argc, char **argv)
+{
+  asm ("" : "+r" (argc));
+  argc = frob ((argc & 10) - 5);
+  asm ("" : "+r" (argc));
+  return !argc;
+}
+
+/* This will result in assembly like:
+
+       .text
+       .align  2
+       .globl  frob
+       .set    nomips16
+       .set    micromips
+       .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
+       .set    noreorder
+       .set    nomacro
+       addiu   $3,$4,5
+       sltu    $2,$3,11
+       beqzc   $2,$L2
+       lui     $2,%hi($L4)
+       addiu   $2,$2,%lo($L4)
+       lwxs    $3,$3($2)
+       jrc     $3
+       .rdata
+       .align  2
+       .align  2
+$L4:
+       .word   $L3
+       .word   $L2
+       .word   $L9
+       .word   $L2
+       .word   $L2
+       .word   $L8
+       .word   $L2
+       .word   $L2
+       .word   $L7
+       .word   $L2
+       .word   $L8
+       .text
+$L8:
+       jr      $31
+       move    $2,$4
+
+$L9:
+       jr      $31
+       li      $2,-1                   # 0xffffffffffffffff
+
+$L3:
+       jr      $31
+       li      $2,-2                   # 0xfffffffffffffffe
+
+$L7:
+       jr      $31
+       li      $2,1                    # 0x1
+
+$L2:
+       .insn
+       .set    macro
+       .set    reorder
+       .end    frob
+       .size   frob, .-frob
+
+  for `frob' and we want to make sure it links correctly owing to the
+  `.insn' pseudo-op which needs to be there at `$L2' as there's no
+  code following and the label is a microMIPS branch target (even though
+  the branch is never taken.  See also insn-casesi.c.  */