This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Bug in gcc-20020114: m68k doesn't use tstsf/tstdf patterns
- From: Peter Barada <pbarada at mail dot wm dot sps dot mot dot com>
- To: gcc at gcc dot gnu dot org
- Date: Mon, 21 Jan 2002 15:30:11 -0500
- Subject: Bug in gcc-20020114: m68k doesn't use tstsf/tstdf patterns
The following code:
typedef float ftype;
int tstf(ftype x0, ftype x1)
{
int i,err;
ftype sigma;
for (err=0, i=0; i<100; ++i) {
sigma = sigma * x0 + x1;
if (sigma < (ftype)0.0)
err = 1;
}
return err;
}
when compiled with:
[pbarada: /tmp] > /tmp/crap.new/bin/m68k-elf-gcc -v
Reading specs from /tmp/crap.new/lib/gcc-lib/m68k-elf/3.1/specs
Configured with: /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-20020114/configure --target=m68k-elf --prefix=/tmp/crap.new --enable-languages=c --with-local-prefix=/tmp/crap.new/m68k-elf
Thread model: single
gcc version 3.1 20020114 (experimental)
[pbarada: /tmp] > /tmp/crap.new/bin/m68k-elf-gcc -O3 -S -m68881 zz.c
generates the following output:
tstf:
link.w %a6,#0
move.l %d2,-(%sp)
move.l 8(%a6),%d2
move.l 12(%a6),%d0
fmovecr #0xf,%fp0
sub.l %a0,%a0
fmove.x %fp0,%fp1
moveq.l #99,%d1
.L5:
fsglmul.s %d2,%fp0
fadd.s %d0,%fp0
fcmp.x %fp1,%fp0 <-- notice fcmp.x instead of ftst.x
fbnlt .L4
move.w #1,%a0
.L4:
subq.l #1,%d1
jbpl .L5
move.l %a0,%d0
move.l (%sp)+,%d2
unlk %a6
rts
.Lfe1:
.size tstf,.Lfe1-tstf
.ident "GCC: (GNU) 3.1 20020114 (experimental)"
This is caused by the code in gcc/prepare_cmp_insn():
/* If we are inside an appropriately-short loop and one operand is an
expensive constant, force it into a register. */
if (CONSTANT_P (x) && preserve_subexpressions_p ()
&& rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
x = force_reg (mode, x);
if (CONSTANT_P (y) && preserve_subexpressions_p ()
&& rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
y = force_reg (mode, y);
forcing y into a register since the rtx_cost(y, COMPARE) is 5 which is
larger than COSTS_N_INSNS (1):
Breakpoint 8, prepare_cmp_insn (px=0xbfffee84, py=0xbfffee88,
pcomparison=0xbfffeea8, size=0x0, pmode=0xbfffeeb0, punsignedp=0xbfffeeb4,
purpose=ccp_jump)
at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-20020114/gcc/optabs.c:3083
(gdb) call dbueg_rtx(y)
No symbol "dbueg_rtx" in current context.
(gdb) call debug_rtx(y)
(const_double:SF 0 [0x0] 0 [0x0] 0 [0x0])
(gdb) p rtx_cost(y, COMPARE)
$17 = 5
(gdb) fra 0
#0 prepare_cmp_insn (px=0xbfffee84, py=0xbfffee88, pcomparison=0xbfffeea8,
size=0x0, pmode=0xbfffeeb0, punsignedp=0xbfffeeb4, purpose=ccp_jump)
at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-20020114/gcc/optabs.c:3083
(gdb) n
(gdb) n
(gdb) call debug_rtx(y)
(reg:SF 36)
To fix this, I changed the COST_DOUBLE clause of CONSTS_COSTS in
gcc/config/m68k/m68k.h to be:
case CONST_DOUBLE: \
/* Make sure that 0.0 is *really* cheap enough for tstsf/tstdf */ \
if ((RTX) == CONST0_RTX (SFmode) || (RTX) == CONST0_RTX (DFmode)) \
return COSTS_N_INSNS (1); \
else \
return 5;
--
Peter Barada Peter.Barada@motorola.com
Wizard 781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola) 781-270-0193 (fax)