* [SH] Miscellaneous changes for LRA.
authorKaz Kojima <kkojima@gcc.gnu.org>
Fri, 19 Dec 2014 04:49:16 +0000 (04:49 +0000)
committerKaz Kojima <kkojima@gcc.gnu.org>
Fri, 19 Dec 2014 04:49:16 +0000 (04:49 +0000)
From-SVN: r218889

gcc/ChangeLog
gcc/config/sh/predicates.md
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sh/sh.md

index fd92d5220579184597b046b834f3e78dc87a9277..2753fae33b20ca3a924593d7b0a45a107050b77f 100644 (file)
@@ -1,3 +1,17 @@
+2014-12-19  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * config/sh/predicates.md (general_movsrc_operand): Allow only
+       valid plus address expressions.
+       (general_movdst_operand): Likewise.
+       (t_reg_operand): Allow (zero_extend (reg t)).
+       * config/sh/sh-protos.h (sh_hard_regno_caller_save_mode): Declare.
+       * config/sh/sh.c (sh_hard_regno_caller_save_mode): New function.
+       (sh_secondary_reload): Return NO_REGS instead of FPUL_REGS in one
+       case.
+       * config/sh/sh.h (HARD_REGNO_CALLER_SAVE_MODE): Define.
+       * config/sh/sh.md (untyped_call): Clobber function value
+       registers before call.
+
 2014-12-19  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        * config/sh/sh.c (sh_lra_p): New function.
index 52267f71d23630b867693d49493fb3aa3b8f131b..152056ae360e604531d6079bd18879405bcbf6db 100644 (file)
          && GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
        return false;
 
-      if ((mode == QImode || mode == HImode)
+      if (GET_CODE (x) == PLUS)
+       {
+         rtx y = XEXP (x, 0);
+
+         if (! REG_P (y)
+             && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))))
+           return false;
+         y = XEXP (x, 1);
+         if (! REG_P (y)
+             && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y)))
+             && ! CONST_INT_P (y))
+           return false;
+       }
+
+      /* LRA will try to satisfy the constraints for the memory displacements
+        and thus we must not reject invalid displacements in the predicate,
+        or else LRA will bail out.
+        FIXME: maybe remove this check completely?  */
+      if (!lra_in_progress && (mode == QImode || mode == HImode)
          && GET_CODE (x) == PLUS
          && REG_P (XEXP (x, 0))
          && CONST_INT_P (XEXP (x, 1)))
          && GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
        return false;
 
-      if ((mode == QImode || mode == HImode)
+      if (GET_CODE (x) == PLUS)
+       {
+         rtx y = XEXP (x, 0);
+
+         if (! REG_P (y)
+             && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))))
+           return false;
+         y = XEXP (x, 1);
+         if (! REG_P (y)
+             && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y)))
+             && ! CONST_INT_P (y))
+           return false;
+       }
+
+      /* LRA will try to satisfy the constraints for the memory displacements
+        and thus we must not reject invalid displacements in the predicate,
+        or else LRA will bail out.
+        FIXME: maybe remove this check completely?  */
+      if (!lra_in_progress && (mode == QImode || mode == HImode)
          && GET_CODE (x) == PLUS
          && REG_P (XEXP (x, 0))
          && CONST_INT_P (XEXP (x, 1)))
 
       case ZERO_EXTEND:
       case SIGN_EXTEND:
+        if (REG_P (XEXP (op, 0)) && REGNO (XEXP (op, 0)) == T_REG)
+         return true;
        return GET_CODE (XEXP (op, 0)) == SUBREG
               && REG_P (SUBREG_REG (XEXP (op, 0)))
               && REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG;
index 262c4fb556add67ceb36079f32b022a7476ff686..7697c4cbe0be0b210ed2260ff5d34b532f0c924a 100644 (file)
@@ -262,5 +262,7 @@ extern int sh2a_get_function_vector_number (rtx);
 extern bool sh2a_is_function_vector_call (rtx);
 extern void sh_fix_range (const char *);
 extern bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
+extern machine_mode sh_hard_regno_caller_save_mode (unsigned int, unsigned int,
+                                                   machine_mode);
 extern bool sh_can_use_simple_return_p (void);
 #endif /* ! GCC_SH_PROTOS_H */
index e586f48c5ea4c529e279f23df6792b09097230cd..b01efb09d3fd7b097d37af4110aac7821c189c13 100644 (file)
@@ -12186,6 +12186,26 @@ sh_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
   return true;
 }
 
+/* Specify the modes required to caller save a given hard regno.
+   choose_hard_reg_mode chooses mode based on HARD_REGNO_MODE_OK
+   and returns ?Imode for float regs when sh_hard_regno_mode_ok
+   permits integer modes on them.  That makes LRA's split process
+   unhappy.  See PR55212.
+ */
+machine_mode
+sh_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
+                               machine_mode mode)
+{
+  if (FP_REGISTER_P (regno)
+      && (mode == SFmode
+         || mode == SCmode
+         || ((mode == DFmode || mode == DCmode)
+             && ((regno - FIRST_FP_REG) & 1) == 0)))
+    return mode;
+
+  return choose_hard_reg_mode (regno, nregs, false);
+}
+
 /* Return the class of registers for which a mode change from FROM to TO
    is invalid.  */
 bool
@@ -13183,7 +13203,7 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
     {
       if (rclass == FPUL_REGS)
        return GENERAL_REGS;
-      return FPUL_REGS;
+      return NO_REGS;  // LRA wants NO_REGS here, it used to be FPUL_REGS;
     }
   if ((rclass == TARGET_REGS
        || (TARGET_SHMEDIA && rclass == SIBCALL_REGS))
index 92835d7d8e0fd09d7a48abb8f9d36b595b37201a..ae1e39b51351ed6737d2e13ef1ec60fb3686c081 100644 (file)
@@ -905,6 +905,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
                              && (GET_MODE_SIZE (MODE2) <= 4)) \
                          : ((MODE1) != SFmode && (MODE2) != SFmode))))
 
+/* Specify the modes required to caller save a given hard regno.  */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)        \
+  sh_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
+
 /* A C expression that is nonzero if hard register NEW_REG can be
    considered for use as a rename register for OLD_REG register */
 #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
index 5aa50a25af9d0c39b8d47b806cd8fd582ff752c6..536a49896657bb3aee9ff931067d86506f03eadf 100644 (file)
@@ -10055,6 +10055,18 @@ label:
              (match_operand 2 "" "")])]
   "(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
 {
+  if (! TARGET_SHMEDIA)
+    {
+      /* RA does not know that the call sets the function value registers.
+        We avoid problems by claiming that those registers are clobbered
+        at this point.  */
+      for (int i = 0; i < XVECLEN (operands[2], 0); i++)
+       {
+         rtx set = XVECEXP (operands[2], 0, i);
+         emit_clobber (SET_SRC (set));
+       }
+    }
+
   emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
 
   for (int i = 0; i < XVECLEN (operands[2], 0); i++)