Commit 0166ff05 by DJ Delorie Committed by DJ Delorie

cond.md (cbranch<mode>4): Defer splitting until after reload.

* 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.

From-SVN: r116653
parent 3a79c991
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>
......
......@@ -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" "")
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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" "")
......
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