------- Additional Comments From dje at gcc dot gnu dot org  2004-10-24 22:52 -------
This problem appears to be a confluence of issues between fix_truncdfdi2 and
limitations of reload, exacerbated by Apple's LL64 mode.

The problematic code is

typedef unsigned long clock_t;
clock_t clock(void);
  clock_t clock_start;
  clock_start = (double)clock();

On an LP64 system, clock_start would be DImode, but in the LL64 environment the
variable is SImode while GCC wants to perform computations in DImode.  (Note
that clock() also returns an SImode clock_t, but the code inserts the
unnecessary (double) conversion.)

It looks like this problem will occur whenever a DImode value is materialized in
an FPR (e.g., PPC64 fctid instruction is enabled) and one only accesses it as an
SImode value:

DFmode d;
SImode x = (SImode) (DImode) d;

One solution is to convince the compiler to collapse out the DImode and directly
convert the DFmode to SImode using fix_truncdfsi2 instead of fix_truncdfdi2.

With the intervening DImode remaining, GCC chooses fix_truncdfdi2, which
produces a DImode result in an FPR.  The only use of the DImode result is the
SImode user variable, so GCC uses the SImode pseudo wrapped in a DImode SUBREG
directly as the result.  When reload needs to spill the value to get it into a
GPR, it dies because it cannot spill the SImode value to its home location.

One could view this problem as reload not obeying CANNOT_CHANGE_MODE_CLASS
because it should not try to spill just the SImode SUBREG instead of creating a
DImode temporary on the stack.  It needs to spill the entire result, not just
the live portion.

This also could be solved by the fix_truncdfdi2 pattern explicitly moving the
result to a GPR instead of relying on reload to correctly implement that maneuver.

There are more and less complicated solutions, but I am not sure which one is
correct.

-- 


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

Reply via email to