diff options
author | dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-09-02 02:38:20 +0000 |
---|---|---|
committer | dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-09-02 02:38:20 +0000 |
commit | 3d5945610646adb6946a3251f4953929966fed2e (patch) | |
tree | 2c0f6158f507bd70b6411b29d1995dc05773b846 /gcc | |
parent | d38680bd5f747f61e19762de8d30ae8064707672 (diff) | |
download | gcc-3d5945610646adb6946a3251f4953929966fed2e.tar.gz |
* config/m32c/cond.md (cbranch<mode>4): Defer splitting until after reload.
(stzx_16): Likewise.
("stzx_24_<mode>"): Likewise.
("stzx_reversed_<mode>"): Likewise, and make mode-specific.
("cmp<mode>_op"): New.
(cmp<mode>): Change to expander; just save operands.
(b<code>_op): New.
(b<code>): Change to expander, emit compare here.
(s<code>_op): Change to use split and expander.
(s<code>_24_op): Likewise.
(s<code>_<mode>): New.
(s<code>_<mode>_24): New.
(movqicc_<code>_<mode): New.
(movhicc_<code>_<mode>): New.
(s<code>): New.
(s<code>_24): New.
* config/m32c/m32c.c (compare_op0, compare_op1): New.
(m32c_pend_compare): New.
(m32c_unpend_compare): New.
(m32c_expand_scc): New.
(m32c_expand_movcc): Emit the compare also.
* config/m32c/predicates.md (mra_nopp_operand): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116653 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/config/m32c/cond.md | 161 | ||||
-rw-r--r-- | gcc/config/m32c/m32c-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.c | 55 | ||||
-rw-r--r-- | gcc/config/m32c/predicates.md | 11 |
5 files changed, 233 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 077b1c32a53..2478b45d213 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2006-09-01 DJ Delorie <dj@redhat.com> + + * config/m32c/cond.md (cbranch<mode>4): Defer splitting until after reload. + (stzx_16): Likewise. + ("stzx_24_<mode>"): Likewise. + ("stzx_reversed_<mode>"): Likewise, and make mode-specific. + ("cmp<mode>_op"): New. + (cmp<mode>): Change to expander; just save operands. + (b<code>_op): New. + (b<code>): Change to expander, emit compare here. + (s<code>_op): Change to use split and expander. + (s<code>_24_op): Likewise. + (s<code>_<mode>): New. + (s<code>_<mode>_24): New. + (movqicc_<code>_<mode): New. + (movhicc_<code>_<mode>): New. + (s<code>): New. + (s<code>_24): New. + * config/m32c/m32c.c (compare_op0, compare_op1): New. + (m32c_pend_compare): New. + (m32c_unpend_compare): New. + (m32c_expand_scc): New. + (m32c_expand_movcc): Emit the compare also. + * config/m32c/predicates.md (mra_nopp_operand): New. + 2006-09-01 J"orn Rennecke <joern.rennecke@st.com> Richard Guenther <rguenther@suse.de> Adam Nemet <anemet@caviumnetworks.com> diff --git a/gcc/config/m32c/cond.md b/gcc/config/m32c/cond.md index 9df4d041409..be590afc49e 100644 --- a/gcc/config/m32c/cond.md +++ b/gcc/config/m32c/cond.md @@ -22,6 +22,20 @@ ; conditionals - cmp, jcc, setcc, etc. +; Special note about conditional instructions: GCC always emits the +; compare right before the insn, which is good, because m32c's mov +; insns modify the flags. However, this means that any conditional +; insn that may require reloading must be kept with its compare until +; after reload finishes, else the reload insns might clobber the +; flags. Thus, these rules: +; +; * the cmp* expanders just save the operands in compare_op0 and +; compare_op1 via m32c_pend_compare. +; * conditional insns that won't need reload can call +; m32c_unpend_compare before their expansion. +; * other insns must expand to include the compare operands within, +; then split after reload to a separate compare and conditional. + ; Until support for relaxing is supported in gas, we must assume that ; short labels won't reach, so we must use long labels. ; Unfortunately, there aren't any conditional jumps with long labels, @@ -41,7 +55,7 @@ (pc)))] "" "#" - "" + "reload_completed" [(set (reg:CC FLG_REGNO) (compare (match_dup 1) (match_dup 2))) @@ -56,7 +70,7 @@ (if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0)) (match_operand:QI 1 "const_int_operand" "i,i,0") (match_operand:QI 2 "const_int_operand" "i,0,i")))] - "TARGET_A16" + "TARGET_A16 && reload_completed" "@ stzx\t%1,%2,%0 stz\t%1,%0 @@ -69,30 +83,30 @@ (if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0)) (match_operand:QHI 1 "const_int_operand" "i,i,0") (match_operand:QHI 2 "const_int_operand" "i,0,i")))] - "TARGET_A24" + "TARGET_A24 && reload_completed" "@ stzx.<bwl>\t%1,%2,%0 stz.<bwl>\t%1,%0 stnz.<bwl>\t%2,%0" [(set_attr "flags" "n,n,n")]) -(define_insn_and_split "stzx_reversed" - [(set (match_operand 0 "m32c_r0_operand" "") - (if_then_else (ne (reg:CC FLG_REGNO) (const_int 0)) - (match_operand 1 "const_int_operand" "") - (match_operand 2 "const_int_operand" "")))] - "TARGET_A24 || GET_MODE (operands[0]) == QImode" +(define_insn_and_split "stzx_reversed_<mode>" + [(set (match_operand:QHI 0 "m32c_r0_operand" "") + (if_then_else:QHI (ne (reg:CC FLG_REGNO) (const_int 0)) + (match_operand:QHI 1 "const_int_operand" "") + (match_operand:QHI 2 "const_int_operand" "")))] + "(TARGET_A24 || GET_MODE (operands[0]) == QImode) && reload_completed" "#" "" [(set (match_dup 0) - (if_then_else (eq (reg:CC FLG_REGNO) (const_int 0)) + (if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0)) (match_dup 2) (match_dup 1)))] "" ) -(define_insn "cmp<mode>" +(define_insn "cmp<mode>_op" [(set (reg:CC FLG_REGNO) (compare (match_operand:QHPSI 0 "mra_operand" "RraSd") (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))] @@ -100,7 +114,14 @@ "* return m32c_output_compare(insn, operands); " [(set_attr "flags" "oszc")]) -(define_insn "b<code>" +(define_expand "cmp<mode>" + [(set (reg:CC FLG_REGNO) + (compare (match_operand:QHPSI 0 "mra_operand" "RraSd") + (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))] + "" + "m32c_pend_compare (operands); DONE;") + +(define_insn "b<code>_op" [(set (pc) (if_then_else (any_cond (reg:CC FLG_REGNO) (const_int 0)) @@ -111,23 +132,131 @@ [(set_attr "flags" "n")] ) +(define_expand "b<code>" + [(set (pc) + (if_then_else (any_cond (reg:CC FLG_REGNO) + (const_int 0)) + (label_ref (match_operand 0 "")) + (pc)))] + "" + "m32c_unpend_compare ();" +) + ;; m32c_conditional_register_usage changes the setcc_gen_code array to ;; point to the _24 variants if needed. -(define_insn "s<code>" +;; We need to keep the compare and conditional sets together through +;; reload, because reload might need to add address reloads to the +;; set, which would clobber the flags. By keeping them together, the +;; reloads get put before the compare, thus preserving the flags. + +;; These are the post-split patterns for the conditional sets. + +(define_insn "s<code>_op" [(set (match_operand:QI 0 "register_operand" "=Rqi") (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] - "TARGET_A16" + "TARGET_A16 && reload_completed" "* return m32c_scc_pattern(operands, <CODE>);") -(define_insn "s<code>_24" +(define_insn "s<code>_24_op" [(set (match_operand:HI 0 "mra_operand" "=RhiSd") (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] - "TARGET_A24" + "TARGET_A24 && reload_completed" "sc<code>\t%0" [(set_attr "flags" "n")] ) +;; These are the pre-split patterns for the conditional sets. Yes, +;; there are a lot of permutations. + +(define_insn_and_split "s<code>_<mode>" + [(set (match_operand:QI 0 "register_operand" "=Rqi") + (any_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd") + (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))] + "TARGET_A16" + "#" + "reload_completed" + [(set (reg:CC FLG_REGNO) + (compare (match_dup 1) + (match_dup 2))) + (set (match_dup 0) + (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + "" + [(set_attr "flags" "x")] +) + +(define_insn_and_split "s<code>_<mode>_24" + [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd") + (any_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd") + (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))] + "TARGET_A24" + "#" + "reload_completed" + [(set (reg:CC FLG_REGNO) + (compare (match_dup 1) + (match_dup 2))) + (set (match_dup 0) + (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] + "" + [(set_attr "flags" "x")] +) + +(define_insn_and_split "movqicc_<code>_<mode>" + [(set (match_operand:QI 0 "register_operand" "") + (if_then_else:QI (eqne_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd") + (match_operand:QHPSI 2 "mrai_operand" "RraSdi")) + (match_operand:QI 3 "const_int_operand" "") + (match_operand:QI 4 "const_int_operand" "")))] + "" + "#" + "reload_completed" + [(set (reg:CC FLG_REGNO) + (compare (match_dup 1) + (match_dup 2))) + (set (match_dup 0) + (if_then_else:QI (eqne_cond:QI (reg:CC FLG_REGNO) (const_int 0)) + (match_dup 3) + (match_dup 4)))] + "" + [(set_attr "flags" "x")] + ) + +(define_insn_and_split "movhicc_<code>_<mode>" + [(set (match_operand:HI 0 "register_operand" "") + (if_then_else:HI (eqne_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd") + (match_operand:QHPSI 2 "mrai_operand" "RraSdi")) + (match_operand:QI 3 "const_int_operand" "") + (match_operand:QI 4 "const_int_operand" "")))] + "TARGET_A24" + "#" + "reload_completed" + [(set (reg:CC FLG_REGNO) + (compare (match_dup 1) + (match_dup 2))) + (set (match_dup 0) + (if_then_else:HI (eqne_cond:HI (reg:CC FLG_REGNO) (const_int 0)) + (match_dup 3) + (match_dup 4)))] + "" + [(set_attr "flags" "x")] + ) + +;; And these are the expanders, which read the pending compare +;; operands to build a combined insn. + +(define_expand "s<code>" + [(set (match_operand:QI 0 "register_operand" "=Rqi") + (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + "TARGET_A16" + "m32c_expand_scc (<CODE>, operands); DONE;") + +(define_expand "s<code>_24" + [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd") + (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] + "TARGET_A24" + "m32c_expand_scc (<CODE>, operands); DONE;") + + (define_expand "movqicc" [(set (match_operand:QI 0 "register_operand" "") (if_then_else:QI (match_operand 1 "m32c_eqne_operator" "") diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h index 6979da278a2..06bd0070ac3 100644 --- a/gcc/config/m32c/m32c-protos.h +++ b/gcc/config/m32c/m32c-protos.h @@ -46,6 +46,7 @@ void m32c_register_pragmas (void); int m32c_regno_ok_for_base_p (int); int m32c_trampoline_alignment (void); int m32c_trampoline_size (void); +void m32c_unpend_compare (void); #if defined(RTX_CODE) && defined(TREE_CODE) @@ -68,6 +69,7 @@ int m32c_expand_movmemhi (rtx *); int m32c_expand_movstr (rtx *); void m32c_expand_neg_mulpsi3 (rtx *); int m32c_expand_setmemhi (rtx *); +void m32c_expand_scc (int, rtx *); int m32c_extra_constraint_p (rtx, char, const char *); int m32c_extra_constraint_p2 (rtx, char, const char *); int m32c_hard_regno_nregs (int, MM); @@ -86,6 +88,7 @@ int m32c_mode_dependent_address (rtx); int m32c_modes_tieable_p (MM, MM); bool m32c_mov_ok (rtx *, MM); char * m32c_output_compare (rtx, rtx *); +void m32c_pend_compare (rtx *); int m32c_preferred_output_reload_class (rtx, int); int m32c_preferred_reload_class (rtx, int); int m32c_prepare_move (rtx *, MM); diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index 4c2219e23d8..68467873976 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -3488,6 +3488,42 @@ m32c_expand_neg_mulpsi3 (rtx * operands) emit_insn (gen_truncsipsi2 (operands[0], temp2)); } +static rtx compare_op0, compare_op1; + +void +m32c_pend_compare (rtx *operands) +{ + compare_op0 = operands[0]; + compare_op1 = operands[1]; +} + +void +m32c_unpend_compare (void) +{ + switch (GET_MODE (compare_op0)) + { + case QImode: + emit_insn (gen_cmpqi_op (compare_op0, compare_op1)); + case HImode: + emit_insn (gen_cmphi_op (compare_op0, compare_op1)); + case PSImode: + emit_insn (gen_cmppsi_op (compare_op0, compare_op1)); + } +} + +void +m32c_expand_scc (int code, rtx *operands) +{ + enum machine_mode mode = TARGET_A16 ? QImode : HImode; + + emit_insn (gen_rtx_SET (mode, + operands[0], + gen_rtx_fmt_ee (code, + mode, + compare_op0, + compare_op1))); +} + /* Pattern Output Functions */ /* Returns a (OP (reg:CC FLG_REGNO) (const_int 0)) from some other @@ -3505,6 +3541,8 @@ int m32c_expand_movcc (rtx *operands) { rtx rel = operands[1]; + rtx cmp; + if (GET_CODE (rel) != EQ && GET_CODE (rel) != NE) return 1; if (GET_CODE (operands[2]) != CONST_INT @@ -3517,12 +3555,17 @@ m32c_expand_movcc (rtx *operands) operands[2] = operands[3]; operands[3] = tmp; } - if (TARGET_A16) - emit_insn (gen_stzx_16 (operands[0], operands[2], operands[3])); - else if (GET_MODE (operands[0]) == QImode) - emit_insn (gen_stzx_24_qi (operands[0], operands[2], operands[3])); - else - emit_insn (gen_stzx_24_hi (operands[0], operands[2], operands[3])); + + cmp = gen_rtx_fmt_ee (GET_CODE (rel), + GET_MODE (rel), + compare_op0, + compare_op1); + + emit_move_insn (operands[0], + gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + cmp, + operands[2], + operands[3])); return 0; } diff --git a/gcc/config/m32c/predicates.md b/gcc/config/m32c/predicates.md index 5b9549c6f7b..b0fbc846c89 100644 --- a/gcc/config/m32c/predicates.md +++ b/gcc/config/m32c/predicates.md @@ -141,6 +141,17 @@ (and (match_operand 0 "nonimmediate_operand" "") (not (match_operand 1 "cr_operand" "")))) +; As above, but no push/pop operations +(define_predicate "mra_nopp_operand" + (match_operand 0 "mra_operand" "") +{ + if (GET_CODE (op) == MEM + && (GET_CODE (XEXP (op, 0)) == PRE_DEC + || (GET_CODE (XEXP (op, 0)) == POST_INC))) + return 0; + return 1; +}) + ; TRUE for memory, r0..r3, a0..a1, or immediates. (define_predicate "mrai_operand" (and (and (match_operand 0 "m32c_any_operand" "") |