From e8bd1224a97d706ed251d4b5a7ebc4e6348788e6 Mon Sep 17 00:00:00 2001 From: rth Date: Tue, 2 Aug 2011 18:48:00 +0000 Subject: [PATCH] PR target/49878 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 | 17 +++++ gcc/config/h8300/h8300-protos.h | 1 + gcc/config/h8300/h8300.c | 34 +++++++++ gcc/config/h8300/h8300.md | 165 +++++++++++----------------------------- gcc/config/h8300/predicates.md | 14 ++++ 5 files changed, 111 insertions(+), 120 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3772021..306d968 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2011-08-02 Richard Henderson + 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_

): Macroize from pushqi1_h8300hs_advanced + and pushqi1_h8300hs_normal; use PRE_MODIFY and + register_no_sp_elim_operand. + (*pushhi1_h8300hs_

): Similarly. + (pushqi1, pushhi1, pushhi1_h8300): Remove. + * config/h8300/predicates.md (register_no_sp_elim_operand): New. + +2011-08-02 Richard Henderson + PR target/49881 * config/avr/avr.md (push1): Don't constrain the operand. 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_" + [(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_" + [(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. -- 2.7.4