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

Reply via email to