This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix PR target/10904 and PR target/13058
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Henderson <rth at redhat dot com>,Andrew Over <andrew dot over at cs dot anu dot edu dot au>
- Date: Tue, 27 Jan 2004 14:32:43 +0100
- Subject: Fix PR target/10904 and PR target/13058
The PRs are about failures caused by the inability for the compiler to
enforce FP register alignment on SPARC64, that is to make sure that an
odd-numbered FP register is not used where an even-numbered is required.
As Andrew pointed out, the docs contain these very explicit lines
" When a value occupying several consecutive registers is expected in a
certain class, all the registers used must belong to that class.
Therefore, register classes cannot be used to enforce a requirement for
a register pair to start with an even-numbered register. The way to
specify this requirement is with `HARD_REGNO_MODE_OK'."
HARD_REGNO_MODE_OK is already correct on SPARC64, so there is a hole
somewhere. It turns out that both failures are related to SI:DI paradoxical
subregs whose inner reg is assigned to a FP reg: the register allocator
fails to recognize that this subregization introduces a new alignment
constraint on SPARC64.
Andrew and I explored various (intrusive) ways to solve the problem. Now
Richard recently pointed out that PA64 has the same alignment requirement
for its FP regs, and it doesn't seem to be affected by the problem.
The reason is simple: PA64 forbids the subregization of SI mode values in FP
regs with CANNOT_CHANGE_MODE_CLASS. According to the comment, the rationale
is that LOAD_EXTEND_OP is not valid for FP regs, so SI->DI extension is not
allowed for FP regs (DImode == word_mode).
It turns out that this rationale applies to SPARC64 for the lower FP regs
(the upper FP regs can't hold SImode value), so borrowing the whole C_C_M_C
macro from PA64 makes sense. And of course solves the two PRs :-)
Bootstrapped/regtested on sparc64-sun-solaris2.9 (3.4 branch, except Ada),
applied to mainline and 3.4 branch (PR target/13058 is a regression).
2004-01-27 Eric Botcazou <ebotcazou@libertysurf.fr>
PR target/10904
PR target/13058
* config/sparc/sparc.h (CANNOT_CHANGE_MODE_CLASS): New.
Forbid mode changes from SImode for lower FP regs if ARCH64.
2004-01-27 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/20040127-1.c: New test.
* gcc.dg/20040127-2.c: New test.
--
Eric Botcazou
Index: config/sparc/sparc.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.h,v
retrieving revision 1.236
diff -u -p -r1.236 sparc.h
--- config/sparc/sparc.h 9 Nov 2003 14:05:10 -0000 1.236
+++ config/sparc/sparc.h 26 Jan 2004 15:03:49 -0000
@@ -1264,6 +1264,20 @@ enum reg_class { NO_REGS, FPCC_REGS, I64
{-1, -1, -1, 0x20}, /* GENERAL_OR_EXTRA_FP_REGS */ \
{-1, -1, -1, 0x3f}} /* ALL_REGS */
+/* Defines invalid mode changes. Borrowed from pa64-regs.h.
+
+ 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. */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (TARGET_ARCH64 \
+ && (FROM) == SImode \
+ && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
+
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
/* PR target/10904 */
/* Origin: <kminola@eng.umd.edu> */
/* Verify that the register allocator correctly aligns
floating-point registers on SPARC64. */
/* { dg-do assemble } */
/* { dg-options "-O2" } */
extern int foo1();
extern int foo2();
void foo(int n, int b)
{
int i, a;
foo1();
a = (long)(b * ((double) 0.1));
for (i=0; i < n; i++) {
foo2(a);
}
}
/* PR target/13058 */
/* Origin: Lloyd Parkes <lloyd@must-have-coffee.gen.nz> */
/* Reduced testcase by Falk Hueffner <falk@debian.org> */
/* Verify that the register allocator correctly aligns
floating-point registers on SPARC64. */
/* { dg-do compile } */
/* { dg-options "-O" } */
typedef struct { int ThumbnailSize; } ImageInfo_t;
double ConvertAnyFormat(void)
{
return 0;
}
void ProcessExifDir(ImageInfo_t *ImageInfoP, int NumDirEntries)
{
unsigned int ThumbnailSize;
for (; NumDirEntries;) {
Get16u();
switch (NumDirEntries) {
case 0x0201:
case 0x0202:
ThumbnailSize = ConvertAnyFormat();
}
}
ImageInfoP->ThumbnailSize = ThumbnailSize;
}