This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][m68k] PR target/36133 Unnecessary TST insns


This patch changes the way GCC tracks the condition register for m68k shift instructions. This is a very different patch to the one previously posted here: http://gcc.gnu.org/ml/gcc-patches/2008-06/msg00317.html

Previously, the compiler just assumed that shift instructions clobbered CC0, and a TST instruction was necessary to use the result for a branch.

e.g.
    lsr.l #4,%d0
    tst.l %d0
    jeq .L5

With this patch, only the CC0 carry and overflow bits are clobbered. The support for the carry bit was not already present, so I've also added this.

e.g.
    lsr.l #4,%d0
    jeq .L5

Actually, the carry bit stuff is redundant, as it stands, because the overflow handling already does that same thing. This looks wrong to me - at least on Coldfire (note that this is target independent code) the GTU and LTU conditions do not involve the overflow bit. However this is probably related to this comment in condition.h:

/* ??? Note that for most targets this macro is misnamed as it applies
   to the carry flag, not the overflow flag.  */

I suspect that changing this will break other targets (and maybe Coldfire also), but it still seems to be best to do it right (hopefully this is it).

Unfortunately, although this patch fixes the issue, in the testcase given in PR36133, at -O2, it does not fix it at -Os. The problem there is that the TST is moved to another basic block before the RTL stage, and this prevents the optimisations working. I'm not sure what to do about this.

I've tested this patch and discovered no regressions.

OK?

Andrew Stubbs
2008-11-14  Andrew Stubbs  <ams@codesourcery.com>

	gcc/
	PR target/36133
	* conditions.h (CC_NO_CARRY): New define.
	* config/m68k/m68k.c (notice_update_cc): Set cc_status properly for
	shift instructions.
	* final.c (alter_cond): Handle CC_NO_CARRY.

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

---
 src/gcc-4.3/gcc/conditions.h                        |    4 ++++
 src/gcc-4.3/gcc/config/m68k/m68k.c                  |    4 +---
 src/gcc-4.3/gcc/final.c                             |   16 ++++++++++++++++
 src/gcc-4.3/gcc/testsuite/gcc.target/m68k/pr36133.c |   16 ++++++++++++++++
 4 files changed, 37 insertions(+), 3 deletions(-)

Index: issue3283/src/gcc-4.3/gcc/conditions.h
===================================================================
--- issue3283.orig/src/gcc-4.3/gcc/conditions.h	2008-11-14 11:24:08.000000000 +0000
+++ issue3283/src/gcc-4.3/gcc/conditions.h	2008-11-14 11:24:34.000000000 +0000
@@ -107,6 +107,10 @@ extern CC_STATUS cc_status;
    This is only used by machine description files.  */
 #define CC_NOT_SIGNED 0200
 
+/* This bit means that the current setting of the carry flag
+   is bogus and conditional jumps should pretend there is no carry.  */
+#define CC_NO_CARRY 0400
+
 /* This is how to initialize the variable cc_status.
    final does this at appropriate moments.  */
 
Index: issue3283/src/gcc-4.3/gcc/config/m68k/m68k.c
===================================================================
--- issue3283.orig/src/gcc-4.3/gcc/config/m68k/m68k.c	2008-11-14 11:24:08.000000000 +0000
+++ issue3283/src/gcc-4.3/gcc/config/m68k/m68k.c	2008-11-14 11:24:34.000000000 +0000
@@ -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_NO_OVERFLOW | CC_NO_CARRY;
 	break;
 
       case PLUS: case MINUS: case MULT:
Index: issue3283/src/gcc-4.3/gcc/final.c
===================================================================
--- issue3283.orig/src/gcc-4.3/gcc/final.c	2008-11-14 11:24:08.000000000 +0000
+++ issue3283/src/gcc-4.3/gcc/final.c	2008-11-14 11:24:34.000000000 +0000
@@ -2929,6 +2929,22 @@ alter_cond (rtx cond)
 	break;
       }
 
+  if (cc_status.flags & CC_NO_CARRY)
+    switch (GET_CODE (cond))
+      {
+      case GTU:
+	PUT_CODE (cond, NE);
+	value = 2;
+	break;
+
+      case LTU:
+	/* Jump becomes no-op.  */
+	return -1;
+
+      default:
+	break;
+      }
+
   if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
     switch (GET_CODE (cond))
       {
Index: issue3283/src/gcc-4.3/gcc/testsuite/gcc.target/m68k/pr36133.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ issue3283/src/gcc-4.3/gcc/testsuite/gcc.target/m68k/pr36133.c	2008-11-14 11:24:34.000000000 +0000
@@ -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");
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]