This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][m68k] PR target/36133 Unnecessary TST insns
- From: Andrew Stubbs <ams at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 14 Nov 2008 14:05:56 +0000
- Subject: [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");
+}