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>
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.
......
......@@ -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 *);
......
......@@ -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
......
......@@ -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
......
......@@ -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.
......
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