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]

Repost: Gcc-3.0 bug affects spec2000 benchmarks


Some people couldn't read the original message, so I am reposting it.
--------------------------------------------------------

The following program when compiled with gcc-3.0 on a powerpc system
generates wrong code.

This bug causes spec2000 253.perlbmk benchmark to loop forever.

Regards
Edmar W. Jr.



Program:
=======

double x;

double
foo (void)
{
  double value;
  value = x;
  if (value == 0.0)
    value = 1.0;
  return value;
}

Compiled with:
=============
gcc -O2 -mcpu=750 -S foo.c

Generates the assembler:
=======================
        .file   "foo.c"
        .section        ".rodata"
        .align 3
.LC0:
        .long 0x0
        .long 0x0
        .align 3
.LC1:
        .long 0x3ff00000
        .long 0x0
        .section        ".text"
        .align 2
        .globl foo
        .type   foo,@function
foo:
        lis 9,.LC0@ha
        la 9,.LC0@l(9)
        lfd 0,0(9)
        lis 9,x@ha
        lfd 1,x@l(9)
        lis 9,.LC1@ha
        la 9,.LC1@l(9)
        fsub 0,1,0
        lfd 13,0(9)
        fsel 1,0,13,1
        blr
.Lfe1:
        .size   foo,.Lfe1-foo
        .comm   x,8,8
        .ident  "GCC: (GNU) 3.0"

Description:
===========
The bug is in the following segment of rs6000.md file.
This segments repeats on movsfcc and movdfcc.

  if (GET_MODE (rs6000_compare_op0) == DFmode)
    {
      temp = gen_reg_rtx (DFmode);
      emit_insn (gen_subdf3 (temp, op0, op1));
      emit_insn (gen_fseldfsf4 (operands[0], temp, operands[2], operands[3]));
      if (code == EQ)
        {
          emit_insn (gen_negdf2 (temp, temp));
          emit_insn (gen_fseldfsf4 (operands[0], temp, operands[0], operands[3]));
        }
    }
  else
    {
      temp = gen_reg_rtx (SFmode);
      emit_insn (gen_subsf3 (temp, op0, op1));
      emit_insn (gen_fselsfsf4 (operands[0], temp, operands[2], operands[3]));
      if (code == EQ)
        {
          emit_insn (gen_negsf2 (temp, temp));
          emit_insn (gen_fselsfsf4 (operands[0], temp, operands[0], operands[3]));
        }
    }


The problem is that for this particular program (foo function above),
the function movdfcc is invoked with operand[3] aliased to
operand[0]. In this case the code is expanded to

...
fsel op[0], temp, op[2], op[0]
fneg temp, temp
fsel op[0], temp, op[0], op[0]
...

The optimizer recognizes that the last instruction is useless, and deletes it,
then the fneg is dead and is deleted as well.
On foo.s above we see only the first fsel.

Possible fix:
============

Create a new temporary that copies the value of operand[3], and them use it
in the second fsel.

If operands are not aliased, the copy should be coalesced away, with no
loss in poerformance.

If operands are aliased, the copy should be coalesced on different register,
with no loss in performance.



--
/*----------------------------------------------------------------------*/
/* Edmar Wienskoski Jr.                   Motorola Inc    TX32  MD:PL30 */
/* (512)996-4935 fax:(512)996-7439        7700 W Parmer Lane, Bldg C    */
/* edmar@motorola.com                     Austin, Texas 78729           */
/*----------------------------------------------------------------------*/
     ____
    | [] |                                                 ______()_||_
 ---+----+---  ------------  ------------  ------------     | []       |
 | |      | |  |          |  |          |  |          |  ___|          |
 |_|______|_|  |__________|  |__________|  |__________|  |______________\
"o-o      o-o""o-o      o-o""o-o      o-o""o-o      o-o""o-o  O-O-O  o-o "



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