Commit f9b4f8c1 by Richard Henderson Committed by Richard Henderson

re PR target/49878 ([h8300] ICE in based_loc_descr, at dwarf2out.c:10478)

PR target/49878
h8300: Don't allow eliminable registers to be pushed.

From-SVN: r177200
parent 2b756fa2
2011-08-02 Richard Henderson <rth@redhat.com> 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 PR target/49881
* config/avr/avr.md (push<MPUSH>1): Don't constrain the operand. * config/avr/avr.md (push<MPUSH>1): Don't constrain the operand.
......
...@@ -101,6 +101,7 @@ extern int h8300_regs_ok_for_stm (int, rtx[]); ...@@ -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_rename_ok (unsigned int, unsigned int);
extern int h8300_hard_regno_nregs (int, enum machine_mode); extern int h8300_hard_regno_nregs (int, enum machine_mode);
extern int h8300_hard_regno_mode_ok (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; struct cpp_reader;
extern void h8300_pr_interrupt (struct cpp_reader *); extern void h8300_pr_interrupt (struct cpp_reader *);
......
...@@ -5813,6 +5813,40 @@ h8300_hard_regno_mode_ok (int regno, enum machine_mode mode) ...@@ -5813,6 +5813,40 @@ h8300_hard_regno_mode_ok (int regno, enum machine_mode mode)
goes. */ goes. */
return regno == MAC_REG ? mode == SImode : 1; 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. */ /* Perform target dependent optabs initialization. */
static void static void
......
...@@ -180,6 +180,15 @@ ...@@ -180,6 +180,15 @@
(include "constraints.md") (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 ;; MOVE INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
...@@ -189,8 +198,7 @@ ...@@ -189,8 +198,7 @@
[(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m") [(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"))] (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
"TARGET_H8300 "TARGET_H8300
&& (register_operand (operands[0], QImode) && h8300_move_ok (operands[0], operands[1])"
|| register_operand (operands[1], QImode))"
"@ "@
sub.b %X0,%X0 sub.b %X0,%X0
mov.b %R1,%X0 mov.b %R1,%X0
...@@ -205,8 +213,7 @@ ...@@ -205,8 +213,7 @@
[(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m") [(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"))] (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
"(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX "(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX
&& (register_operand (operands[0], QImode) && h8300_move_ok (operands[0], operands[1])"
|| register_operand (operands[1], QImode))"
"@ "@
sub.b %X0,%X0 sub.b %X0,%X0
mov.b %R1,%X0 mov.b %R1,%X0
...@@ -232,16 +239,11 @@ ...@@ -232,16 +239,11 @@
[(set (match_operand:QI 0 "general_operand_dst" "") [(set (match_operand:QI 0 "general_operand_dst" "")
(match_operand:QI 1 "general_operand_src" ""))] (match_operand:QI 1 "general_operand_src" ""))]
"" ""
"
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!TARGET_H8300SX if (!TARGET_H8300SX && !h8300_move_ok (operands[0], operands[1]))
&& !register_operand (operand0, QImode) operands[1] = copy_to_mode_reg (QImode, operands[1]);
&& !register_operand (operand1, QImode)) })
{
operands[1] = copy_to_mode_reg (QImode, operand1);
}
}")
(define_insn "movstrictqi" (define_insn "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r")) [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r"))
...@@ -260,13 +262,7 @@ ...@@ -260,13 +262,7 @@
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m") [(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"))] (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
"TARGET_H8300 "TARGET_H8300
&& (register_operand (operands[0], HImode) && h8300_move_ok (operands[0], operands[1])"
|| 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]))"
"@ "@
sub.w %T0,%T0 sub.w %T0,%T0
mov.w %T1,%T0 mov.w %T1,%T0
...@@ -282,8 +278,7 @@ ...@@ -282,8 +278,7 @@
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m") [(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"))] (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
"(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX "(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX
&& (register_operand (operands[0], HImode) && h8300_move_ok (operands[0], operands[1])"
|| register_operand (operands[1], HImode))"
"@ "@
sub.w %T0,%T0 sub.w %T0,%T0
mov.w %T1,%T0 mov.w %T1,%T0
...@@ -313,15 +308,11 @@ ...@@ -313,15 +308,11 @@
[(set (match_operand:HI 0 "general_operand_dst" "") [(set (match_operand:HI 0 "general_operand_dst" "")
(match_operand:HI 1 "general_operand_src" ""))] (match_operand:HI 1 "general_operand_src" ""))]
"" ""
"
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!register_operand (operand1, HImode) if (!h8300_move_ok (operands[0], operands[1]))
&& !register_operand (operand0, HImode)) operands[1] = copy_to_mode_reg (HImode, operand1);
{ })
operands[1] = copy_to_mode_reg (HImode, operand1);
}
}")
(define_insn "movstricthi" (define_insn "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r")) [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r"))
...@@ -341,7 +332,6 @@ ...@@ -341,7 +332,6 @@
[(set (match_operand:SI 0 "general_operand_dst" "") [(set (match_operand:SI 0 "general_operand_dst" "")
(match_operand:SI 1 "general_operand_src" ""))] (match_operand:SI 1 "general_operand_src" ""))]
"" ""
"
{ {
if (TARGET_H8300) if (TARGET_H8300)
{ {
...@@ -351,20 +341,16 @@ ...@@ -351,20 +341,16 @@
else if (!TARGET_H8300SX) else if (!TARGET_H8300SX)
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!register_operand (operand1, SImode) if (!h8300_move_ok (operands[0], operands[1]))
&& !register_operand (operand0, SImode)) operands[1] = copy_to_mode_reg (SImode, operand1);
{
operands[1] = copy_to_mode_reg (SImode, operand1);
}
} }
}") })
(define_insn "*movsi_h8300" (define_insn "*movsi_h8300"
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,o,<,r") [(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,>"))] (match_operand:SI 1 "general_operand_src" "I,r,io,r,r,>"))]
"TARGET_H8300 "TARGET_H8300
&& (register_operand (operands[0], SImode) && h8300_move_ok (operands[0], operands[1])"
|| register_operand (operands[1], SImode))"
"* "*
{ {
unsigned int rn = -1; unsigned int rn = -1;
...@@ -434,13 +420,7 @@ ...@@ -434,13 +420,7 @@
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r") [(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"))] (match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))]
"(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX "(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX
&& (register_operand (operands[0], SImode) && h8300_move_ok (operands[0], operands[1])"
|| 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]))"
"* "*
{ {
switch (which_alternative) switch (which_alternative)
...@@ -872,90 +852,35 @@ ...@@ -872,90 +852,35 @@
;; PUSH INSTRUCTIONS ;; PUSH INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "pushqi1_h8300" (define_insn "*pushqi1_h8300"
[(set (reg:HI SP_REG) [(set (mem:QI
(plus:HI (reg:HI SP_REG) (const_int -2))) (pre_modify:HI
(set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1))) (reg:HI SP_REG)
(match_operand:QI 0 "register_operand" "r"))] (plus:HI (reg:HI SP_REG) (const_int -2))))
"TARGET_H8300 (match_operand:QI 0 "register_no_sp_elim_operand" "r"))]
&& operands[0] != stack_pointer_rtx" "TARGET_H8300"
"mov.w\\t%T0,@-r7" "mov.w\\t%T0,@-r7"
[(set_attr "length" "2")]) [(set_attr "length" "2")])
(define_insn "pushqi1_h8300hs_advanced" (define_insn "*pushqi1_h8300hs_<mode>"
[(set (reg:SI SP_REG) [(set (mem:QI
(plus:SI (reg:SI SP_REG) (const_int -4))) (pre_modify:P
(set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3))) (reg:P SP_REG)
(match_operand:QI 0 "register_operand" "r"))] (plus:P (reg:P SP_REG) (const_int -4))))
"(TARGET_H8300H || TARGET_H8300S) (match_operand:QI 0 "register_no_sp_elim_operand" "r"))]
&& operands[0] != stack_pointer_rtx" "TARGET_H8300H || TARGET_H8300S"
"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"
"mov.l\\t%S0,@-er7" "mov.l\\t%S0,@-er7"
[(set_attr "length" "4")]) [(set_attr "length" "4")])
(define_insn "pushhi1_h8300hs_normal" (define_insn "*pushhi1_h8300hs_<mode>"
[(set (reg:HI SP_REG) [(set (mem:HI
(plus:HI (reg:HI SP_REG) (const_int -4))) (pre_modify:P
(set (mem:HI (plus:HI (reg:HI SP_REG) (const_int -2))) (reg:P SP_REG)
(match_operand:HI 0 "register_operand" "r"))] (plus:P (reg:P SP_REG) (const_int -4))))
"(TARGET_H8300H || TARGET_H8300S) (match_operand:HI 0 "register_no_sp_elim_operand" "r"))]
&& operands[0] != stack_pointer_rtx" "TARGET_H8300H || TARGET_H8300S"
"mov.l\\t%S0,@-er7" "mov.l\\t%S0,@-er7"
[(set_attr "length" "4")]) [(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 ;; TEST INSTRUCTIONS
......
...@@ -375,6 +375,20 @@ ...@@ -375,6 +375,20 @@
return op == stack_pointer_rtx; 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 ;; Return nonzero if X is a constant whose absolute value is greater
;; than 2. ;; than 2.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment