decrement and branch on m68k
Herman ten Brugge
herman@htbrug.net.HCC.nl
Mon Dec 29 11:42:00 GMT 1997
Hello,
I found a bug in the define_peephole construct for decrement and branch
until zero. The bug shows itself when a wile loop is inside a for loop.
The program below shows the problem:
int a[10];
int z = 1;
void update()
{
z--;
}
int main()
{
int i;
for (i = 10 ; i >= 0 ; i--) {
z = i;
do {
update();
} while (a[z]);
}
return(0);
}
Compiled with gcc (2.7.2.1). The peephole is the same in egcs so we have the
same problem here.
#NO_APP
gcc2_compiled.:
___gnu_compiled_c:
.globl _z
.data
.even
_z:
.long 1
.text
.even
.globl _main
_main:
link a6,#0
movel a2,sp@-
movel d2,sp@-
jbsr ___main
moveq #10,d2
lea _a,a2
L15:
movel d2,_z
L16:
jbsr _update
movel _z,d0
tstl a2@(d0:l:4)
dbne d2,L15 <---- ERROR
jne L16 <---- ERROR
clrw d2
subql #1,d2
jpl L15
movel a6@(-8),d2
movel a6@(-4),a2
unlk a6
rts
.even
.globl _update
_update:
link a6,#0
subql #1,_z
unlk a6
rts
.comm _a,40
The problem is that the dbne and jne switched due to the peephole. This is
certainly wrong in this case. I made the following patch to solve this
problem.
Herman.
--- m68k.md.org Mon Dec 29 20:24:24 1997
+++ m68k.md Mon Dec 29 20:25:59 1997
@@ -7087,7 +7087,8 @@
(set (match_dup 0)
(plus:HI (match_dup 0)
(const_int -1)))])]
- "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()
+ && !dbcc_label_conflict (insn, operands[2], operands[1])"
"*
{
CC_STATUS_INIT;
@@ -7111,7 +7112,8 @@
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))])]
- "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()
+ && !dbcc_label_conflict (insn, operands[2], operands[1])"
"*
{
CC_STATUS_INIT;
--- m68k.c.org Mon Dec 29 20:24:27 1997
+++ m68k.c Mon Dec 29 20:27:22 1997
@@ -878,6 +878,28 @@
}
}
+/* check for while loop inside a decrement and branch loop */
+
+int
+dbcc_label_conflict (insn, jump, db)
+ rtx insn;
+ rtx jump;
+ rtx db;
+{
+ while (insn)
+ {
+ if (GET_CODE (insn) == CODE_LABEL)
+ {
+ if (CODE_LABEL_NUMBER(jump) == CODE_LABEL_NUMBER(insn))
+ return 1;
+ if (CODE_LABEL_NUMBER(db) == CODE_LABEL_NUMBER(insn))
+ return 0;
+ }
+ insn = PREV_INSN (insn);
+ }
+ return 1;
+}
+
/* Return non-zero if flags are currently in the 68881 flag register. */
int
flags_in_68881 ()
--
-------------------------------------------------------------------------
Herman ten Brugge Email: Haj.Ten.Brugge@net.HCC.nl
More information about the Gcc-bugs
mailing list