This is the mail archive of the gcc@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]

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)


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