diff mbox

[H8] Fix target/49878

Message ID 4E3848A1.1030507@redhat.com
State New
Headers show

Commit Message

Richard Henderson Aug. 2, 2011, 6:57 p.m. UTC
The problem here is that reload finds a push of arg_pointer_rtx
and disables register elimination of AP->SP because of it.  This
leads to a register elimination (and assertion) failure when it
comes time to output debug info.

Preventing eliminable registers from being pushed fixes this.

The change to the pushqi/pushhi patterns, aside from using
register_no_sp_elim_operand, is cosmetic.  We can do a better
job with single_set insns, and PRE_MODIFY does the job fine.
Moreover, that's the pattern that will automatically be
generated by emit_single_push_insn.

The exact formulation of h8300_move_ok is perhaps more 
conservative than it needs to be.  The existing checks,

> -   && !(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]))"

only check for overlap on a store.  I assumed it was
merely an oversight that we didn't check for overlap
on a pre_inc load as well.

Committed.


r~
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.
diff mbox

Patch

diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index da3b75a..aeac904 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -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 *);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 62e9e85..ef48395 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -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);
+}
 
 /* Perform target dependent optabs initialization.  */
 static void
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index db56e20..fa1809d 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -180,6 +180,15 @@ 
 (include "constraints.md")
 
 ;; ----------------------------------------------------------------------
+;; 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")])
+
+
+;; ----------------------------------------------------------------------
 ;; MOVE INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
@@ -189,8 +198,7 @@ 
   [(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
@@ -205,8 +213,7 @@ 
   [(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
@@ -232,16 +239,11 @@ 
   [(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"))
@@ -260,13 +262,7 @@ 
   [(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
@@ -282,8 +278,7 @@ 
   [(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
@@ -313,15 +308,11 @@ 
   [(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"))
@@ -341,7 +332,6 @@ 
   [(set (match_operand:SI 0 "general_operand_dst" "")
 	(match_operand:SI 1 "general_operand_src" ""))]
   ""
-  "
 {
   if (TARGET_H8300)
     {
@@ -351,20 +341,16 @@ 
   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;
@@ -434,13 +420,7 @@ 
   [(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)
@@ -872,90 +852,35 @@ 
 ;; 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;
-}")
 
 ;; ----------------------------------------------------------------------
 ;; TEST INSTRUCTIONS
diff --git a/gcc/config/h8300/predicates.md b/gcc/config/h8300/predicates.md
index 75714b3..3bb5e1a 100644
--- a/gcc/config/h8300/predicates.md
+++ b/gcc/config/h8300/predicates.md
@@ -375,6 +375,20 @@ 
   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.