------- 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