re PR target/36133 (GCC creates suboptimal ASM : Code includes unneeded TST instructions)
authorAndrew Stubbs <ams@codesourcery.com>
Wed, 19 Nov 2008 11:23:28 +0000 (11:23 +0000)
committerAndrew Stubbs <ams@gcc.gnu.org>
Wed, 19 Nov 2008 11:23:28 +0000 (11:23 +0000)
2008-11-19  Andrew Stubbs  <ams@codesourcery.com>

gcc/
PR target/36133
* config/m68k/m68k.h (CC_OVERFLOW_UNUSABLE, CC_NO_CARRY): New defines.
* config/m68k/m68k.c (notice_update_cc): Set cc_status properly for
shift instructions.
* config/m68k/m68k.md: Adjust all conditional branches that use the
carry and overflow flags so they understand CC_OVERFLOW_UNUSABLE.

gcc/testsuite/
PR target/36133
* gcc.target/m68k/pr36133.c: New test.

From-SVN: r141999

gcc/ChangeLog
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/m68k/pr36133.c [new file with mode: 0644]

index a32aa1297a8ee8bc983d97300405e73cb0407498..c1973fa52254ca995252dc73b9b8333d18c90760 100644 (file)
@@ -1,3 +1,12 @@
+2008-11-19  Andrew Stubbs  <ams@codesourcery.com>
+
+       PR target/36133
+       * config/m68k/m68k.h (CC_OVERFLOW_UNUSABLE, CC_NO_CARRY): New defines.
+       * config/m68k/m68k.c (notice_update_cc): Set cc_status properly for
+       shift instructions.
+       * config/m68k/m68k.md: Adjust all conditional branches that use the
+       carry and overflow flags so they understand CC_OVERFLOW_UNUSABLE.
+
 2008-11-18  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/37362
index c762a8ffb9e5e354b7b11c92cc47841820e55d54..d8cc370262c9b40cf1bd1825d5f84b8ce4f5db40 100644 (file)
@@ -3605,9 +3605,7 @@ notice_update_cc (rtx exp, rtx insn)
       case ROTATE: case ROTATERT:
        /* These instructions always clear the overflow bit, and set
           the carry to the bit shifted out.  */
-       /* ??? We don't currently have a way to signal carry not valid,
-          nor do we check for it in the branch insns.  */
-       CC_STATUS_INIT;
+       cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
        break;
 
       case PLUS: case MINUS: case MULT:
index 280f16d6076355c96d1990714da48dd486b8f208..8c0f4f20ed9d3b57d4e9079bbd17c29395e2c78c 100644 (file)
@@ -855,6 +855,14 @@ __transfer_from_trampoline ()                                      \
    some or all of the saved cc's so they won't be used.  */
 #define NOTICE_UPDATE_CC(EXP,INSN) notice_update_cc (EXP, INSN)
 
+/* The shift instructions always clear the overflow bit.  */
+#define CC_OVERFLOW_UNUSABLE 01000
+
+/* The shift instructions use the carry bit in a way not compatible with
+   conditional branches.  conditions.h uses CC_NO_OVERFLOW for this purpose.
+   Rename it to something more understandable.  */
+#define CC_NO_CARRY CC_NO_OVERFLOW
+
 #define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV)  \
 do { if (cc_prev_status.flags & CC_IN_68881)                   \
     return FLOAT;                                              \
index cf3e120590fff2741f0fa7d8108b7785e55ef224..75f36dcc89617e72355a6c46a3e0450dad78d8c9 100644 (file)
                      (pc)))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
 }
   [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))])
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "jhi %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jhi %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "blt"
                      (pc)))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0");
 }
   [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))])
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "jcs %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jcs %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "bge"
                      (pc)))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jge %l0", "fjge %l0", "jpl %l0");
 })
 
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "jcc %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jcc %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "ble"
                      (pc)))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jle %l0", "fjle %l0", 0);
 }
   [(set_attr "type" "bcc")])
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "jls %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jls %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "bordered"
                      (label_ref (match_operand 0 "" ""))))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0);
 }
   [(set_attr "type" "bcc")])
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   ""
-  "jls %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jls %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "*blt_rev"
                      (label_ref (match_operand 0 "" ""))))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0");
 }
   [(set_attr "type" "bcc")])
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   ""
-  "jcc %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jcc %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "*bge_rev"
                      (label_ref (match_operand 0 "" ""))))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0");
 }
   [(set_attr "type" "bcc")])
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   ""
-  "jcs %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jcs %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "*ble_rev"
                      (label_ref (match_operand 0 "" ""))))]
   ""
 {
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
   OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0);
 }
   [(set_attr "type" "bcc")])
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   ""
-  "jhi %l0"
+{
+  if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+    {
+      cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+      return 0;
+    }
+
+  return "jhi %l0";
+}
   [(set_attr "type" "bcc")])
 
 (define_insn "*bordered_rev"
index 5a80bd28d5dc742525a02dd269acc2fa4f8a4377..354eda68cc10cd67b55c1e1a72665a31ea73cd0c 100644 (file)
@@ -1,3 +1,8 @@
+2008-11-19  Andrew Stubbs  <ams@codesourcery.com>
+
+       PR target/36133
+       * gcc.target/m68k/pr36133.c: New test.
+
 2008-11-19  Maxim Kuvyrkov  <maxim@codesourcery.com>
   
        * gcc.gd/struct/wo_prof_global_var.c: Use uninitialized integer
diff --git a/gcc/testsuite/gcc.target/m68k/pr36133.c b/gcc/testsuite/gcc.target/m68k/pr36133.c
new file mode 100644 (file)
index 0000000..25237a8
--- /dev/null
@@ -0,0 +1,16 @@
+/* pr36133.c
+
+   This test ensures that conditional branches can use the condition codes
+   written by shift instructions, without the need for an extra TST.  */
+
+/* { dg-do compile }  */
+/* { dg-options "-O2" }  */
+/* { dg-final { scan-assembler-not "tst" } } */
+
+void
+f (unsigned int a)
+{
+  if (a >> 4)
+    asm volatile ("nop");
+  asm volatile ("nop");
+}