This is a regression present on the mainline and 9 branch: the compiler (LRA)
generates an instruction using unaligned double FP registers. This has been a
known weakness since the switch to LRA because there is no longer an explicit
constraint for aligned double FP registers.
Bootstrapped/regtested on SPARC/Solaris and SPARC64/Linux, applied on the
mainline and 9 branch.
2019-09-20 Eric Botcazou <ebotca...@adacore.com>
PR target/91269
* config/sparc/sparc.h (HARD_REGNO_CALLER_SAVE_MODE): Define.
2019-09-20 Eric Botcazou <ebotca...@adacore.com>
* gcc.dg/pr91269.c: New test.
--
Eric Botcazou
Index: config/sparc/sparc.h
===================================================================
--- config/sparc/sparc.h (revision 275746)
+++ config/sparc/sparc.h (working copy)
@@ -711,6 +711,13 @@ along with GCC; see the file COPYING3.
register window instruction in the prologue. */
#define HARD_REGNO_RENAME_OK(FROM, TO) ((FROM) != 1)
+/* Select a register mode required for caller save of hard regno REGNO.
+ Contrary to what is documented, the default is not the smallest suitable
+ mode but the largest suitable mode for the given (REGNO, NREGS) pair and
+ it quickly creates paradoxical subregs that can be problematic. */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+ ((MODE) == VOIDmode ? choose_hard_reg_mode (REGNO, NREGS, false) : (MODE))
+
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
/* PR target/91269 */
/* Testcase by Sergei Trofimovich <sly...@inbox.ru> */
/* { dg-do assemble } */
/* { dg-options "-O2 -Wno-int-conversion" } */
/* { dg-additional-options "-fcall-used-g6 -fPIE -mcpu=niagara4" { target sparc*-*-* } } */
struct m;
enum { a = 2 };
int b[1];
int d[2715];
int e, f, h;
enum { i = 2 } j;
inline int c(int k) {
char *cp;
if (k >= 62 && k <= 247)
cp = b[k];
if (cp)
return 65533;
return 2;
}
inline int g(int k) {
if (k < sizeof(d))
return e;
return 0;
}
int u(struct m*, char*, char*);
int l(struct m *k, char n, long o, int *p) {
int q, flags = j, r, s, lasttwo = *p;
char inptr, outptr;
while (inptr) {
if (__builtin_expect(h, 0))
break;
unsigned ch = inptr;
if (lasttwo) {
long need = lasttwo >> 3;
if (__builtin_expect(need > n, 0))
break;
} else if (s == i) {
long t = c(ch);
if (t != 65533) {
int jch = g(ch);
if (jch & 8)
continue;
}
}
if (ch <= 5)
;
else {
long t = c(ch);
if (t != 65533)
;
else {
switch (f >> 8)
case 79:
q = f == 20308 || f == 20350;
if (q)
if (j)
r = u(k, &inptr, &outptr);
s = *p;
if (r)
if (o && flags & a)
break;
}
}
}
}