This is the mail archive of the gcc-bugs@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 rtl-optimization/49936] New: [4.7 regression] IRA handles CANNOT_CHANGE_MODE_CLASS poorly, + spills to memory on 4.7


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49936

           Summary: [4.7 regression] IRA handles CANNOT_CHANGE_MODE_CLASS
                    poorly, + spills to memory on 4.7
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: sandra@codesourcery.com
                CC: vmakarov@redhat.com


Created attachment 24885
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=24885
test case abstest.c

Consider the attached test case, compiled for MIPS with

mipsisa32r2-sde-elf-gcc -O3 -fno-inline -fno-unroll-loops -march=74kf1_1 -S
abstest.c 

On MIPS, the hardware floating-point abs and neg instructions aren't usable by
default because they do the wrong thing with NaNs.  And, the sign-bit-twiddling
used by the optabs.c expansions can't be performed in a floating-point register
because of CANNOT_CHANGE_MODE_CLASS.  

With a GCC 4.6 compiler, this snippet of code from the test1 function

  for (i=0; i<n; i++) { accum -= a[i]; }
  accum = fabs (accum);
  return accum;

produces

...
.L3:
    mtc1    $3,$f2
    ldc1    $f0,0($5)
    addiu    $5,$5,8
    mtc1    $2,$f3
    sub.d    $f2,$f2,$f0
    mfc1    $3,$f2
    bne    $5,$4,.L3
    mfc1    $2,$f3

    ext    $5,$2,0,31
    move    $4,$3
.L2:
    mtc1    $4,$f0
    j    $31
    mtc1    $5,$f1
...

Because it thinks it cannot use a floating-point register, IRA has decided to
put accum in a general-purpose register pair $2/$3, and is shuffling it back
and forth to $f2/$f3 on every iteration of the loop.

On 4.7 mainline trunk, it's now deciding accum must live in memory instead of a
register:

.L3:
    ldc1    $f0,0($2)
    addiu    $2,$2,8
    sub.d    $f2,$f2,$f0
    bne    $2,$3,.L3
    sdc1    $f2,0($sp)

    lw    $2,0($sp)
    ext    $3,$2,0,31
    lw    $2,4($sp)
.L2:
    sw    $2,4($sp)
    sw    $3,0($sp)
    lw    $3,4($sp)
    lw    $2,0($sp)
    addiu    $sp,$sp,8
    mtc1    $3,$f0
    j    $31
    mtc1    $2,$f1

I think a big part of the problem here is the code in ira-costs.c that refuses
to consider the FP regs at all in computing the costs for where to put the
accum variable.  Better that it should just add in the move costs for reloading
to some other register class, much as it would to satisfy normal insn register
constraints.

Naively commenting out all the #ifdef CANNOT_CHANGE_MODE_CLASS....#endif
instances in ira-costs.c gave this code in 4.6:

.L3:
    ldc1    $f2,0($2)
    addiu    $2,$2,8
    bne    $2,$4,.L3
    sub.d    $f0,$f0,$f2

    mfc1    $2,$f0
    mfc1    $3,$f0
    ext    $5,$2,0,31
    move    $4,$3
.L2:
    mtc1    $4,$f0
    j    $31
    mtc1    $5,$f1

However, same change on 4.7 didn't help; it's still preferring to spill to
memory.  I think there must be some other bug lurking here that's responsible
for these additional memory spills on 4.7.  I also saw them when experimenting
with a patch to the MIPS backend to attack this problem in a target-specific
way.

Also, while splitting live ranges might help with the code in the test1
function where the fabs call appears outside the loop, the code for the test2
function (fabs in the body of the loop) suffers from the same problem and is
spilling to memory on 4.7.


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