OSDN Git Service

PR target/49878
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Aug 2011 18:48:00 +0000 (18:48 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Aug 2011 18:48:00 +0000 (18:48 +0000)
h8300: Don't allow eliminable registers to be pushed.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177200 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 3772021..306d968 100644 (file)
@@ -1,5 +1,22 @@
 2011-08-02  Richard Henderson  <rth@redhat.com>
 
+       PR target/49878
+       * config/h8300/h8300.c (h8300_move_ok): New.
+       * config/h8300/h8300-protos.h: Declare it.
+       * config/h8300/h8300.md (P): New mode iterator.
+       (*movqi_h8300, *movqi_h8300hs, movqi): Use h8300_move_ok.
+       (*movqi_h8sx, *movhi_h8300, *movhi_h8300hs, movhi): Likewise.
+       (movsi, *movsi_h8300, *movsi_h8300hs): Likewise.
+       (*pushqi1_h8300): Rename from pushqi1_h8300; use PRE_MODIFY.
+       (*pushqi1_h8300hs_<P>): Macroize from pushqi1_h8300hs_advanced
+       and pushqi1_h8300hs_normal; use PRE_MODIFY and
+       register_no_sp_elim_operand.
+       (*pushhi1_h8300hs_<P>): Similarly.
+       (pushqi1, pushhi1, pushhi1_h8300): Remove.
+       * config/h8300/predicates.md (register_no_sp_elim_operand): New.
+
+2011-08-02  Richard Henderson  <rth@redhat.com>
+
        PR target/49881
        * config/avr/avr.md (push<MPUSH>1): Don't constrain the operand.
 
index da3b75a..aeac904 100644 (file)
@@ -101,6 +101,7 @@ extern int h8300_regs_ok_for_stm (int, rtx[]);
 extern int h8300_hard_regno_rename_ok (unsigned int, unsigned int);
 extern int h8300_hard_regno_nregs (int, enum machine_mode);
 extern int h8300_hard_regno_mode_ok (int, enum machine_mode);
+extern bool h8300_move_ok (rtx, rtx);
 
 struct cpp_reader;
 extern void h8300_pr_interrupt (struct cpp_reader *);
index 62e9e85..ef48395 100644 (file)
@@ -5813,6 +5813,40 @@ h8300_hard_regno_mode_ok (int regno, enum machine_mode mode)
        goes.  */
     return regno == MAC_REG ? mode == SImode : 1;
 }
+
+/* Helper function for the move patterns.  Make sure a move is legitimate.  */
+
+bool
+h8300_move_ok (rtx dest, rtx src)
+{
+  rtx addr, other;
+
+  /* Validate that at least one operand is a register.  */
+  if (MEM_P (dest))
+    {
+      if (MEM_P (src) || CONSTANT_P (src))
+       return false;
+      addr = XEXP (dest, 0);
+      other = src;
+    }
+  else if (MEM_P (src))
+    {
+      addr = XEXP (src, 0);
+      other = dest;
+    }
+  else
+    return true;
+
+  /* Validate that auto-inc doesn't affect OTHER.  */
+  if (GET_RTX_CLASS (GET_CODE (addr)) != RTX_AUTOINC)
+    return true;
+  addr = XEXP (addr, 0);
+
+  if (addr == stack_pointer_rtx)
+    return register_no_sp_elim_operand (other, VOIDmode);
+  else
+    return !reg_overlap_mentioned_p(other, addr);
+}
 \f
 /* Perform target dependent optabs initialization.  */
 static void
index db56e20..fa1809d 100644 (file)
 (include "constraints.md")
 \f
 ;; ----------------------------------------------------------------------
+;; MACRO DEFINITIONS
+;; ----------------------------------------------------------------------
+
+;; This mode iterator allows :P to be used for patterns that operate on
+;; pointer-sized quantities.  Exactly one of the two alternatives will match.
+(define_mode_iterator P [(HI "Pmode == HImode") (SI "Pmode == SImode")])
+
+\f
+;; ----------------------------------------------------------------------
 ;; MOVE INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
   [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m")
        (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
   "TARGET_H8300
-   && (register_operand (operands[0], QImode)
-       || register_operand (operands[1], QImode))"
+   && h8300_move_ok (operands[0], operands[1])"
   "@
    sub.b       %X0,%X0
    mov.b       %R1,%X0
   [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m")
        (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
   "(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX
-   && (register_operand (operands[0], QImode)
-       || register_operand (operands[1], QImode))"
+   && h8300_move_ok (operands[0], operands[1])"
   "@
    sub.b       %X0,%X0
    mov.b       %R1,%X0
   [(set (match_operand:QI 0 "general_operand_dst" "")
        (match_operand:QI 1 "general_operand_src" ""))]
   ""
-  "
 {
   /* One of the ops has to be in a register.  */
-  if (!TARGET_H8300SX
-      && !register_operand (operand0, QImode)
-      && !register_operand (operand1, QImode))
-    {
-      operands[1] = copy_to_mode_reg (QImode, operand1);
-    }
-}")
+  if (!TARGET_H8300SX && !h8300_move_ok (operands[0], operands[1]))
+    operands[1] = copy_to_mode_reg (QImode, operands[1]);
+})
 
 (define_insn "movstrictqi"
   [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r"))
   [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
        (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
   "TARGET_H8300
-   && (register_operand (operands[0], HImode)
-       || register_operand (operands[1], HImode))
-   && !(GET_CODE (operands[0]) == MEM
-       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-       && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
-       && GET_CODE (operands[1]) == REG
-       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))"
+   && h8300_move_ok (operands[0], operands[1])"
   "@
    sub.w       %T0,%T0
    mov.w       %T1,%T0
   [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
        (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
   "(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX
-   && (register_operand (operands[0], HImode)
-       || register_operand (operands[1], HImode))"
+   && h8300_move_ok (operands[0], operands[1])"
   "@
    sub.w       %T0,%T0
    mov.w       %T1,%T0
   [(set (match_operand:HI 0 "general_operand_dst" "")
        (match_operand:HI 1 "general_operand_src" ""))]
   ""
-  "
 {
   /* One of the ops has to be in a register.  */
-  if (!register_operand (operand1, HImode)
-      && !register_operand (operand0, HImode))
-    {
-      operands[1] = copy_to_mode_reg (HImode, operand1);
-    }
-}")
+  if (!h8300_move_ok (operands[0], operands[1]))
+    operands[1] = copy_to_mode_reg (HImode, operand1);
+})
 
 (define_insn "movstricthi"
   [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r"))
   [(set (match_operand:SI 0 "general_operand_dst" "")
        (match_operand:SI 1 "general_operand_src" ""))]
   ""
-  "
 {
   if (TARGET_H8300)
     {
   else if (!TARGET_H8300SX)
     {
       /* One of the ops has to be in a register.  */
-      if (!register_operand (operand1, SImode)
-         && !register_operand (operand0, SImode))
-       {
-         operands[1] = copy_to_mode_reg (SImode, operand1);
-       }
+      if (!h8300_move_ok (operands[0], operands[1]))
+       operands[1] = copy_to_mode_reg (SImode, operand1);
     }
-}")
+})
 
 (define_insn "*movsi_h8300"
   [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,o,<,r")
        (match_operand:SI 1 "general_operand_src" "I,r,io,r,r,>"))]
   "TARGET_H8300
-   && (register_operand (operands[0], SImode)
-       || register_operand (operands[1], SImode))"
+   && h8300_move_ok (operands[0], operands[1])"
   "*
 {
   unsigned int rn = -1;
   [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r")
        (match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))]
   "(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX
-   && (register_operand (operands[0], SImode)
-       || register_operand (operands[1], SImode))
-   && !(GET_CODE (operands[0]) == MEM
-       && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-       && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
-       && GET_CODE (operands[1]) == REG
-       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))"
+   && h8300_move_ok (operands[0], operands[1])"
   "*
 {
   switch (which_alternative)
 ;; PUSH INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_insn "pushqi1_h8300"
-  [(set (reg:HI SP_REG)
-       (plus:HI (reg:HI SP_REG) (const_int -2)))
-   (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1)))
-       (match_operand:QI 0 "register_operand" "r"))]
-  "TARGET_H8300
-   && operands[0] != stack_pointer_rtx"
+(define_insn "*pushqi1_h8300"
+  [(set (mem:QI
+         (pre_modify:HI
+           (reg:HI SP_REG)
+           (plus:HI (reg:HI SP_REG) (const_int -2))))
+       (match_operand:QI 0 "register_no_sp_elim_operand" "r"))]
+  "TARGET_H8300"
   "mov.w\\t%T0,@-r7"
   [(set_attr "length" "2")])
 
-(define_insn "pushqi1_h8300hs_advanced"
-  [(set (reg:SI SP_REG)
-       (plus:SI (reg:SI SP_REG) (const_int -4)))
-   (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
-       (match_operand:QI 0 "register_operand" "r"))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && operands[0] != stack_pointer_rtx"
-  "mov.l\\t%S0,@-er7"
-  [(set_attr "length" "4")])
-
-(define_insn "pushqi1_h8300hs_normal"
-  [(set (reg:HI SP_REG)
-       (plus:HI (reg:HI SP_REG) (const_int -4)))
-   (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -3)))
-       (match_operand:QI 0 "register_operand" "r"))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && operands[0] != stack_pointer_rtx"
-  "mov.l\\t%S0,@-er7"
-  [(set_attr "length" "4")])
-
-(define_expand "pushqi1"
-  [(match_operand:QI 0 "register_operand" "")]
-  ""
-  "
-{
-  if (TARGET_H8300)
-    emit_insn (gen_pushqi1_h8300 (operands[0]));
-  else if (!TARGET_NORMAL_MODE)
-    emit_insn (gen_pushqi1_h8300hs_advanced (operands[0]));
-  else
-    emit_insn (gen_pushqi1_h8300hs_normal (operands[0]));
-  DONE;
-}")
-
-(define_expand "pushhi1_h8300"
-  [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
-       (match_operand:HI 0 "register_operand" ""))]
-  "TARGET_H8300
-   && operands[0] != stack_pointer_rtx"
-  "")
-
-(define_insn "pushhi1_h8300hs_advanced"
-  [(set (reg:SI SP_REG)
-       (plus:SI (reg:SI SP_REG) (const_int -4)))
-   (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
-       (match_operand:HI 0 "register_operand" "r"))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && operands[0] != stack_pointer_rtx"
+(define_insn "*pushqi1_h8300hs_<mode>"
+  [(set (mem:QI
+         (pre_modify:P
+           (reg:P SP_REG)
+           (plus:P (reg:P SP_REG) (const_int -4))))
+       (match_operand:QI 0 "register_no_sp_elim_operand" "r"))]
+  "TARGET_H8300H || TARGET_H8300S"
   "mov.l\\t%S0,@-er7"
   [(set_attr "length" "4")])
 
-(define_insn "pushhi1_h8300hs_normal"
-  [(set (reg:HI SP_REG)
-       (plus:HI (reg:HI SP_REG) (const_int -4)))
-   (set (mem:HI (plus:HI (reg:HI SP_REG) (const_int -2)))
-       (match_operand:HI 0 "register_operand" "r"))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && operands[0] != stack_pointer_rtx"
+(define_insn "*pushhi1_h8300hs_<mode>"
+  [(set (mem:HI
+         (pre_modify:P
+           (reg:P SP_REG)
+           (plus:P (reg:P SP_REG) (const_int -4))))
+       (match_operand:HI 0 "register_no_sp_elim_operand" "r"))]
+  "TARGET_H8300H || TARGET_H8300S"
   "mov.l\\t%S0,@-er7"
   [(set_attr "length" "4")])
-
-(define_expand "pushhi1"
-  [(match_operand:HI 0 "register_operand" "")]
-  ""
-  "
-{
-  if (TARGET_H8300)
-    emit_insn (gen_pushhi1_h8300 (operands[0]));
-  else if (!TARGET_NORMAL_MODE)
-    emit_insn (gen_pushhi1_h8300hs_advanced (operands[0]));
-  else
-    emit_insn (gen_pushhi1_h8300hs_normal (operands[0]));
-  DONE;
-}")
 \f
 ;; ----------------------------------------------------------------------
 ;; TEST INSTRUCTIONS
index 75714b3..3bb5e1a 100644 (file)
   return op == stack_pointer_rtx;
 })
 
+;; False if X is anything that might eliminate to the stack pointer.
+
+(define_predicate "register_no_sp_elim_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return !(op == stack_pointer_rtx
+          || op == arg_pointer_rtx
+          || op == frame_pointer_rtx
+          || IN_RANGE (REGNO (op),
+                       FIRST_PSEUDO_REGISTER, LAST_VIRTUAL_REGISTER));
+})
+
 ;; Return nonzero if X is a constant whose absolute value is greater
 ;; than 2.