https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71698
Peter Bergner <bergner at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED Assignee|segher at gcc dot gnu.org |bergner at gcc dot gnu.org --- Comment #5 from Peter Bergner <bergner at gcc dot gnu.org> --- The vararg thing is just a red herring, it just introduced a copy between a FP/VSX reg to/from a GPR reg which exposes the problem. The problem is that when we see a copy like that, we normally will try to emit a direct move instruction, but we can't do that for TDmode, for endian reasons. See the rs6000.md commentary for the *mov<mode>_64bit_dm and *movtd_64bit_nodm patterns for why not. That said, rs6000_secondary_reload_simple_move() is not checking for mode == TDmode when determining whether a copy between VSX regs and GPR regs is ok. I'm currently testing the following patch. Index: rs6000.c =================================================================== --- rs6000.c (revision 237873) +++ rs6000.c (working copy) @@ -19169,7 +19169,8 @@ rs6000_secondary_reload_simple_move (enu simple move insns are issued. At present, 32-bit integers are not allowed in FPR/VSX registers. Single precision binary floating is not a simple move because we need to convert to the single precision memory layout. - The 4-byte SDmode can be moved. */ + The 4-byte SDmode can be moved. TDmode values cannot be moved due to + endian issues. */ size = GET_MODE_SIZE (mode); if (TARGET_DIRECT_MOVE && ((mode == SDmode) || (TARGET_POWERPC64 && size == 8)) @@ -19177,7 +19178,7 @@ rs6000_secondary_reload_simple_move (enu || (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE))) return true; - else if (TARGET_DIRECT_MOVE_128 && size == 16 + else if (TARGET_DIRECT_MOVE_128 && size == 16 && mode != TDmode && ((to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE) || (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE))) return true;