Word-mode paradoxical subregs have been problematic on big-endian architectures for ages, and the PA and SPARC ports have a workaround for this in the form of the CANNOT_CHANGE_MODE_CLASS macro. The SPARC one was more limited in scope, but 10 ACATS tests fail at -O2 on the mainline because of this, so this patch extends it to fix them.
Tested on SPARC64/Solaris, applied on the mainline. 2012-02-12 Eric Botcazou <ebotca...@adacore.com> * config/sparc/sparc.h (CANNOT_CHANGE_MODE_CLASS): In 64-bit mode, disallow changes from SFmode to mode with different size in FP regs. -- Eric Botcazou
Index: config/sparc/sparc.h =================================================================== --- config/sparc/sparc.h (revision 183864) +++ config/sparc/sparc.h (working copy) @@ -894,18 +894,21 @@ extern enum reg_class sparc_regno_reg_cl #define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)] -/* Defines invalid mode changes. Borrowed from pa64-regs.h. +/* Defines invalid mode changes. Borrowed from the PA port. SImode loads to floating-point registers are not zero-extended. The definition for LOAD_EXTEND_OP specifies that integer loads narrower than BITS_PER_WORD will be zero-extended. As a result, we inhibit changes from SImode unless they are to a mode that is - identical in size. */ + identical in size. + + Likewise for SFmode, since word-mode paradoxical subregs are + problematic on big-endian architectures. */ #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ (TARGET_ARCH64 \ - && (FROM) == SImode \ - && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + && GET_MODE_SIZE (FROM) == 4 \ + && GET_MODE_SIZE (TO) != 4 \ ? reg_classes_intersect_p (CLASS, FP_REGS) : 0) /* This is the order in which to allocate registers normally.