diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2020-01-22 05:54:15 +0100 |
---|---|---|
committer | Hans-Peter Nilsson <hp@axis.com> | 2020-05-09 03:34:18 +0200 |
commit | fb062a8b7bca66243d52213a897c7a241f2b14e1 (patch) | |
tree | b0244f19be34c052025f71d62aa727335759201f /gcc/config/cris | |
parent | d0780379c1b621813fbea60449bc51b65f6f8c6e (diff) | |
download | gcc-fb062a8b7bca66243d52213a897c7a241f2b14e1.tar.gz |
cris: Move trivially from cc0 to reg:CC model, removing most optimizations.
In the parlance of <https://gcc.gnu.org/wiki/CC0Transition>,
this is a basic "type 2" conversion, without
condition-code-related optimizations (just plain CCmode), but
with "cstore{M}4" defined. CRIS is somewhat similar to the
m68k; most instructions affect condition-codes. To wit, it
lacks sufficient instructions to compose an arbitrary valid
address in a register, specifically from a valid address where
involved registers have to be spilled or adjusted, without
affecting condition-codes in CRIS_CC0_REGNUM aka. dccr.
On the other hand, moving dccr to and from a stackpointer-plus-
constant-offset-address *can* be done without additional register
use, and moving to or from a general register does not affect
it. There's no instruction to add a constant to a register or
to put a constant in a register, without affecting dccr, but
there *is* an instruction to add a register (optionally scaled)
to another without affecting dccr (i.e. "addi"). Also, moves
*to* memory from any register do not affect dccr, and likewise
between another special registers and a general register. Maybe
some of that opens up the solution-space to a better solution
than clobbering dccr until reload_completed; to be investigated.
FAOD: I know what to do in the direction of defining and using
additional CCmodes, but prefer to do the full transition in
smaller steps.
Regarding the similarity to m68k, I didn't follow the steps of
the m68k cc0 transition, making use of the final_postscan_insn
hook as with the a NOTICE_UPDATE_CC machinery. For one, because
it seems to be lacking in that it keeps compare-elimination
restricted to output-time, but also because it seems a bad match
considering that CRIS has delay-slots; better try to eliminate
compares earlier. Another approach which I originally intended
to implement, that of the visium port of defining three variants
for most insns (not counting the define_subst expansions;
unaffecting-before-reload, clobbering and setting), seems
overworked and bloating the machine description. I may be
proven wrong, but I prefer we fix gcc if some something bails on
seeing a parallel with a clobber of that specific hard-register.
Also, I chose to remove most anonymous combination-matching
patterns; matchers, splitters and peepholes instead of
converting them to add clobbers of CRIS_CC0_REGNUM. There are
exclusions: those covered in the test-suite, if trivial enough.
Many of these patterns are used to handle the side-effect-
assignment addressing-modes as put together by combine: a
"prefix instruction" before the main instruction, where the main
instruction uses the post-incremented-register addressing-mode
and the "left-over" instruction-field in the prefixed insn to
assign a register. An example: the hopefully descriptive
"move.d $r9,[$r0=$r1+1234]" compared to "move.d $r9,[$r1+1234]";
both formed by the prefix insn "biap.w 1234,$r1" before
respectively "move.d $r9,[$r0+]" and "move.d $r9,[$r0]". Other
prefix variants exist. Useful, but optional, except where
side-effect assignment was used in a special case in the
function prologue; adjusted to a less optimal combination.
Support like the function cris_side_effect_mode_ok is kept.
I intend to put back as many as I find use for, of those
anonymous patterns in a controlled manner, with self-contained
test-cases proving their usability, rather than symmetry with
other instructions and similar addressing modes, which guided
the original introduction. I've entered pr93372 to track code
performance regressions related to this transition, with focus
on target-side causes and fixes; besides the function prologue
special-case, there were some checking presence of the bit-test
(btstq) instruction.
The now-gone "tst<mode>" patterns deserve a comment too: they
were an artefact from pre-"cbranch" era, now fully folded into
the "cmp<mode>" patterns.
I've left the now-unused "cc" insn attribute in, for the time
being; to be removed, used or transformed to be useful with
further work to fix pr93372. It can't be used as is, because
"normal" doesn't mean "like a compare instruction" but "handled
by NOTICE_UPDATE_CC" and may in fact be reflecting e.g. reverse
operands, something that bit me during the conversion.
gcc:
Move trivially from cc0 to reg:CC model, removing most optimizations.
* config/cris/cris.md: Remove all side-effect patterns and their
splitters. Remove most peepholes. Add clobbers of CRIS_CC0_REGNUM
to all but post-reload control-flow and movem insns. Remove
constraints on all modified expanders. Remove obsoleted cc0-related
references.
(attr "cc"): Remove alternative "rev".
(mode_iterator BWDD, DI_, SI_): New.
(mode_attr sCC_destc, cmp_op1c, cmp_op2c): New.
("tst<mode>"): Remove; fold as "M" alternative into compare insn.
("mstep_shift", "mstep_mul"): Remove patterns.
("s<rcond>", "s<ocond>", "s<ncond>"): Anonymize.
* config/cris/cris.c: Change all non-condition-code,
non-control-flow emitted insns to add a parallel with clobber of
CRIS_CC0_REGNUM, mostly by changing from gen_rtx_SET with
emit_insn to use of emit_move_insn, gen_add2_insn or
cris_emit_insn, as convenient.
(cris_reg_overlap_mentioned_p)
(cris_normal_notice_update_cc, cris_notice_update_cc): Remove.
(cris_movem_load_rest_p): Don't assume all elements in a
PARALLEL are SETs.
(cris_store_multiple_op_p): Ditto.
(cris_emit_insn): New function.
* cris/cris-protos.h (cris_emit_insn): Declare.
Diffstat (limited to 'gcc/config/cris')
-rw-r--r-- | gcc/config/cris/cris-protos.h | 5 | ||||
-rw-r--r-- | gcc/config/cris/cris.c | 539 | ||||
-rw-r--r-- | gcc/config/cris/cris.h | 7 | ||||
-rw-r--r-- | gcc/config/cris/cris.md | 2598 | ||||
-rw-r--r-- | gcc/config/cris/predicates.md | 2 | ||||
-rw-r--r-- | gcc/config/cris/sync.md | 6 |
6 files changed, 587 insertions, 2570 deletions
diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h index f78eba45ea0..4d8e76f6e39 100644 --- a/gcc/config/cris/cris-protos.h +++ b/gcc/config/cris/cris-protos.h @@ -36,11 +36,12 @@ extern void cris_reduce_compare (rtx *, rtx *, rtx *); extern bool cris_biap_index_p (const_rtx, bool); extern bool cris_legitimate_address_p (machine_mode, rtx, bool); extern bool cris_store_multiple_op_p (rtx); -extern bool cris_movem_load_rest_p (rtx, int); +extern bool cris_movem_load_rest_p (rtx); extern void cris_asm_output_symbol_ref (FILE *, rtx); extern void cris_asm_output_case_end (FILE *, int, rtx_insn *); -extern rtx cris_gen_movem_load (rtx, rtx, int); +extern rtx cris_gen_movem_load (rtx, rtx); extern rtx cris_emit_movem_store (rtx, rtx, int, bool); +extern rtx_insn *cris_emit_insn (rtx x); extern void cris_order_for_addsi3 (rtx *, int); extern void cris_emit_trap_for_misalignment (rtx); #endif /* RTX_CODE */ diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 6f7cdaee66e..9fdabe2ac9b 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -90,9 +90,6 @@ static char cris_output_insn_is_bound = 0; goes in code or in a static initializer. */ static int in_code = 0; -/* Fix for reg_overlap_mentioned_p. */ -static int cris_reg_overlap_mentioned_p (rtx, rtx); - static machine_mode cris_promote_function_mode (const_tree, machine_mode, int *, const_tree, int); @@ -290,9 +287,9 @@ struct gcc_target targetm = TARGET_INITIALIZER; /* Helper for cris_load_multiple_op and cris_ret_movem_op. */ bool -cris_movem_load_rest_p (rtx op, int offs) +cris_movem_load_rest_p (rtx op) { - unsigned int reg_count = XVECLEN (op, 0) - offs; + unsigned int reg_count = XVECLEN (op, 0); rtx src_addr; int i; rtx elt; @@ -303,35 +300,36 @@ cris_movem_load_rest_p (rtx op, int offs) /* Perform a quick check so we don't blow up below. FIXME: Adjust for other than (MEM reg). */ if (reg_count <= 1 - || GET_CODE (XVECEXP (op, 0, offs)) != SET - || !REG_P (SET_DEST (XVECEXP (op, 0, offs))) - || !MEM_P (SET_SRC (XVECEXP (op, 0, offs)))) + || GET_CODE (XVECEXP (op, 0, 0)) != SET + || !REG_P (SET_DEST (XVECEXP (op, 0, 0))) + || !MEM_P (SET_SRC (XVECEXP (op, 0, 0)))) return false; /* Check a possible post-inc indicator. */ - if (GET_CODE (SET_SRC (XVECEXP (op, 0, offs + 1))) == PLUS) + if (GET_CODE (XVECEXP (op, 0, 1)) == SET + && GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS) { - rtx reg = XEXP (SET_SRC (XVECEXP (op, 0, offs + 1)), 0); - rtx inc = XEXP (SET_SRC (XVECEXP (op, 0, offs + 1)), 1); + rtx reg = XEXP (SET_SRC (XVECEXP (op, 0, 1)), 0); + rtx inc = XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1); reg_count--; if (reg_count == 1 || !REG_P (reg) - || !REG_P (SET_DEST (XVECEXP (op, 0, offs + 1))) - || REGNO (reg) != REGNO (SET_DEST (XVECEXP (op, 0, offs + 1))) + || !REG_P (SET_DEST (XVECEXP (op, 0, 1))) + || REGNO (reg) != REGNO (SET_DEST (XVECEXP (op, 0, 1))) || !CONST_INT_P (inc) || INTVAL (inc) != (HOST_WIDE_INT) reg_count * 4) return false; - i = offs + 2; + i = 2; } else - i = offs + 1; + i = 1; regno_dir = -1; regno = reg_count - 1; - elt = XVECEXP (op, 0, offs); + elt = XVECEXP (op, 0, 0); src_addr = XEXP (SET_SRC (elt), 0); if (GET_CODE (elt) != SET @@ -399,15 +397,15 @@ cris_store_multiple_op_p (rtx op) dest_addr = XEXP (dest, 0); /* Check a possible post-inc indicator. */ - if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS) + if (GET_CODE (XVECEXP (op, 0, 1)) == SET + && GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS) { rtx reg = XEXP (SET_SRC (XVECEXP (op, 0, 1)), 0); rtx inc = XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1); reg_count--; - if (reg_count == 1 - || !REG_P (reg) + if (!REG_P (reg) || !REG_P (SET_DEST (XVECEXP (op, 0, 1))) || REGNO (reg) != REGNO (SET_DEST (XVECEXP (op, 0, 1))) || !CONST_INT_P (inc) @@ -1501,302 +1499,6 @@ cris_memory_move_cost (machine_mode mode, return 6; } -/* Worker for cris_notice_update_cc; handles the "normal" cases. - FIXME: this code is historical; its functionality should be - refactored to look at insn attributes and moved to - cris_notice_update_cc. Except, we better lose cc0 entirely. */ - -static void -cris_normal_notice_update_cc (rtx exp, rtx insn) -{ - /* "Normal" means, for: - (set (cc0) (...)): - CC is (...). - - (set (reg) (...)): - CC is (reg) and (...) - unless (...) is 0 or reg is a special - register, then CC does not change. - CC_NO_OVERFLOW unless (...) is reg or mem. - - (set (mem) (...)): - CC does not change. - - (set (pc) (...)): - CC does not change. - - (parallel - (set (reg1) (mem (bdap/biap))) - (set (reg2) (bdap/biap))): - CC is (reg1) and (mem (reg2)) - - (parallel - (set (mem (bdap/biap)) (reg1)) [or 0] - (set (reg2) (bdap/biap))): - CC does not change. - - (where reg and mem includes strict_low_parts variants thereof) - - For all others, assume CC is clobbered. - Note that we do not have to care about setting CC_NO_OVERFLOW, - since the overflow flag is set to 0 (i.e. right) for - instructions where it does not have any sane sense, but where - other flags have meanings. (This includes shifts; the carry is - not set by them). - - Note that there are other parallel constructs we could match, - but we don't do that yet. */ - - if (GET_CODE (exp) == SET) - { - /* FIXME: Check when this happens. It looks like we should - actually do a CC_STATUS_INIT here to be safe. */ - if (SET_DEST (exp) == pc_rtx) - return; - - /* Record CC0 changes, so we do not have to output multiple - test insns. */ - if (SET_DEST (exp) == cc0_rtx) - { - CC_STATUS_INIT; - - if (GET_CODE (SET_SRC (exp)) == COMPARE - && XEXP (SET_SRC (exp), 1) == const0_rtx) - cc_status.value1 = XEXP (SET_SRC (exp), 0); - else - cc_status.value1 = SET_SRC (exp); - - /* Handle flags for the special btstq on one bit. */ - if (GET_CODE (cc_status.value1) == ZERO_EXTRACT - && XEXP (cc_status.value1, 1) == const1_rtx) - { - if (CONST_INT_P (XEXP (cc_status.value1, 0))) - /* Using cmpq. */ - cc_status.flags = CC_INVERTED; - else - /* A one-bit btstq. */ - cc_status.flags = CC_Z_IN_NOT_N; - } - - else if (GET_CODE (SET_SRC (exp)) == COMPARE) - { - if (!REG_P (XEXP (SET_SRC (exp), 0)) - && XEXP (SET_SRC (exp), 1) != const0_rtx) - /* For some reason gcc will not canonicalize compare - operations, reversing the sign by itself if - operands are in wrong order. */ - /* (But NOT inverted; eq is still eq.) */ - cc_status.flags = CC_REVERSED; - - /* This seems to be overlooked by gcc. FIXME: Check again. - FIXME: Is it really safe? */ - cc_status.value2 - = gen_rtx_MINUS (GET_MODE (SET_SRC (exp)), - XEXP (SET_SRC (exp), 0), - XEXP (SET_SRC (exp), 1)); - } - return; - } - else if (REG_P (SET_DEST (exp)) - || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART - && REG_P (XEXP (SET_DEST (exp), 0)))) - { - /* A register is set; normally CC is set to show that no - test insn is needed. Catch the exceptions. */ - - /* If not to cc0, then no "set"s in non-natural mode give - ok cc0... */ - if (GET_MODE_SIZE (GET_MODE (SET_DEST (exp))) > UNITS_PER_WORD - || GET_MODE_CLASS (GET_MODE (SET_DEST (exp))) == MODE_FLOAT) - { - /* ... except add:s and sub:s in DImode. */ - if (GET_MODE (SET_DEST (exp)) == DImode - && (GET_CODE (SET_SRC (exp)) == PLUS - || GET_CODE (SET_SRC (exp)) == MINUS)) - { - CC_STATUS_INIT; - cc_status.value1 = SET_DEST (exp); - cc_status.value2 = SET_SRC (exp); - - if (cris_reg_overlap_mentioned_p (cc_status.value1, - cc_status.value2)) - cc_status.value2 = 0; - - /* Add and sub may set V, which gets us - unoptimizable results in "gt" and "le" condition - codes. */ - cc_status.flags |= CC_NO_OVERFLOW; - - return; - } - } - else if (SET_SRC (exp) == const0_rtx - || (REG_P (SET_SRC (exp)) - && (REGNO (SET_SRC (exp)) - > CRIS_LAST_GENERAL_REGISTER))) - { - /* There's no CC0 change for this case. Just check - for overlap. */ - if (cc_status.value1 - && modified_in_p (cc_status.value1, insn)) - cc_status.value1 = 0; - - if (cc_status.value2 - && modified_in_p (cc_status.value2, insn)) - cc_status.value2 = 0; - - return; - } - else - { - CC_STATUS_INIT; - cc_status.value1 = SET_DEST (exp); - cc_status.value2 = SET_SRC (exp); - - if (cris_reg_overlap_mentioned_p (cc_status.value1, - cc_status.value2)) - cc_status.value2 = 0; - - /* Some operations may set V, which gets us - unoptimizable results in "gt" and "le" condition - codes. */ - if (GET_CODE (SET_SRC (exp)) == PLUS - || GET_CODE (SET_SRC (exp)) == MINUS - || GET_CODE (SET_SRC (exp)) == NEG) - cc_status.flags |= CC_NO_OVERFLOW; - - return; - } - } - else if (MEM_P (SET_DEST (exp)) - || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART - && MEM_P (XEXP (SET_DEST (exp), 0)))) - { - /* When SET to MEM, then CC is not changed (except for - overlap). */ - if (cc_status.value1 - && modified_in_p (cc_status.value1, insn)) - cc_status.value1 = 0; - - if (cc_status.value2 - && modified_in_p (cc_status.value2, insn)) - cc_status.value2 = 0; - - return; - } - } - else if (GET_CODE (exp) == PARALLEL) - { - if (GET_CODE (XVECEXP (exp, 0, 0)) == SET - && GET_CODE (XVECEXP (exp, 0, 1)) == SET - && REG_P (XEXP (XVECEXP (exp, 0, 1), 0))) - { - if (REG_P (XEXP (XVECEXP (exp, 0, 0), 0)) - && MEM_P (XEXP (XVECEXP (exp, 0, 0), 1))) - { - CC_STATUS_INIT; - - /* For "move.S [rx=ry+o],rz", say CC reflects - value1=rz and value2=[rx] */ - cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0); - cc_status.value2 - = replace_equiv_address (XEXP (XVECEXP (exp, 0, 0), 1), - XEXP (XVECEXP (exp, 0, 1), 0)); - - /* Huh? A side-effect cannot change the destination - register. */ - if (cris_reg_overlap_mentioned_p (cc_status.value1, - cc_status.value2)) - internal_error ("internal error: sideeffect-insn affecting main effect"); - return; - } - else if ((REG_P (XEXP (XVECEXP (exp, 0, 0), 1)) - || XEXP (XVECEXP (exp, 0, 0), 1) == const0_rtx) - && MEM_P (XEXP (XVECEXP (exp, 0, 0), 0))) - { - /* For "move.S rz,[rx=ry+o]" and "clear.S [rx=ry+o]", - say flags are not changed, except for overlap. */ - if (cc_status.value1 - && modified_in_p (cc_status.value1, insn)) - cc_status.value1 = 0; - - if (cc_status.value2 - && modified_in_p (cc_status.value2, insn)) - cc_status.value2 = 0; - - return; - } - } - } - - /* If we got here, the case wasn't covered by the code above. */ - CC_STATUS_INIT; -} - -/* This function looks into the pattern to see how this insn affects - condition codes. - - Used when to eliminate test insns before a condition-code user, - such as a "scc" insn or a conditional branch. This includes - checking if the entities that cc was updated by, are changed by the - operation. - - Currently a jumble of the old peek-inside-the-insn and the newer - check-cc-attribute methods. */ - -void -cris_notice_update_cc (rtx exp, rtx_insn *insn) -{ - enum attr_cc attrval = get_attr_cc (insn); - - /* Check if user specified "-mcc-init" as a bug-workaround. Remember - to still set CC_REVERSED as below, since that's required by some - compare insn alternatives. (FIXME: GCC should do this virtual - operand swap by itself.) A test-case that may otherwise fail is - gcc.c-torture/execute/20000217-1.c -O0 and -O1. */ - if (TARGET_CCINIT) - { - CC_STATUS_INIT; - - if (attrval == CC_REV) - cc_status.flags = CC_REVERSED; - return; - } - - /* Slowly, we're converting to using attributes to control the setting - of condition-code status. */ - switch (attrval) - { - case CC_NONE: - /* Even if it is "none", a setting may clobber a previous - cc-value, so check. */ - if (GET_CODE (exp) == SET) - { - if (cc_status.value1 - && modified_in_p (cc_status.value1, insn)) - cc_status.value1 = 0; - - if (cc_status.value2 - && modified_in_p (cc_status.value2, insn)) - cc_status.value2 = 0; - } - return; - - case CC_CLOBBER: - CC_STATUS_INIT; - return; - - case CC_REV: - case CC_NORMAL: - cris_normal_notice_update_cc (exp, insn); - return; - - default: - internal_error ("unknown cc_attr value"); - } - - CC_STATUS_INIT; -} - /* Return != 0 if the return sequence for the current function is short, like "ret" or "jump [sp+]". Prior to reloading, we can't tell if registers must be saved, so return 0 then. */ @@ -2208,23 +1910,6 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops, internal_error ("internal error: cris_side_effect_mode_ok with bad operands"); } -/* The function reg_overlap_mentioned_p in CVS (still as of 2001-05-16) - does not handle the case where the IN operand is strict_low_part; it - does handle it for X. Test-case in Axis-20010516. This function takes - care of that for THIS port. FIXME: strict_low_part is going away - anyway. */ - -static int -cris_reg_overlap_mentioned_p (rtx x, rtx in) -{ - /* The function reg_overlap_mentioned now handles when X is - strict_low_part, but not when IN is a STRICT_LOW_PART. */ - if (GET_CODE (in) == STRICT_LOW_PART) - in = XEXP (in, 0); - - return reg_overlap_mentioned_p (x, in); -} - /* Queue an .ident string in the queue of top-level asm statements. If the front-end is done, we must be being called from toplev.c. In that case, do nothing. */ @@ -2480,22 +2165,20 @@ cris_split_movdx (rtx *operands) /* We normally copy the low-numbered register first. However, if the first register operand 0 is the same as the second register of operand 1, we must copy in the opposite order. */ - emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode), - operand_subword (src, reverse, TRUE, mode))); + emit_move_insn (operand_subword (dest, reverse, TRUE, mode), + operand_subword (src, reverse, TRUE, mode)); - emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode), - operand_subword (src, !reverse, TRUE, mode))); + emit_move_insn (operand_subword (dest, !reverse, TRUE, mode), + operand_subword (src, !reverse, TRUE, mode)); } /* Constant-to-reg copy. */ else if (CONST_INT_P (src) || GET_CODE (src) == CONST_DOUBLE) { rtx words[2]; split_double (src, &words[0], &words[1]); - emit_insn (gen_rtx_SET (operand_subword (dest, 0, TRUE, mode), - words[0])); + emit_move_insn (operand_subword (dest, 0, TRUE, mode), words[0]); - emit_insn (gen_rtx_SET (operand_subword (dest, 1, TRUE, mode), - words[1])); + emit_move_insn (operand_subword (dest, 1, TRUE, mode), words[1]); } /* Mem-to-reg copy. */ else if (MEM_P (src)) @@ -2522,18 +2205,15 @@ cris_split_movdx (rtx *operands) addresses ourselves, we must add a post-inc note manually. */ mem = change_address (src, SImode, addr); - insn - = gen_rtx_SET (operand_subword (dest, 0, TRUE, mode), mem); - insn = emit_insn (insn); + insn = emit_move_insn (operand_subword (dest, 0, TRUE, mode), + mem); if (GET_CODE (XEXP (mem, 0)) == POST_INC) REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (XEXP (mem, 0), 0), REG_NOTES (insn)); mem = copy_rtx (mem); - insn - = gen_rtx_SET (operand_subword (dest, 1, TRUE, mode), mem); - insn = emit_insn (insn); + insn = emit_move_insn (operand_subword (dest, 1, TRUE, mode), mem); if (GET_CODE (XEXP (mem, 0)) == POST_INC) REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (XEXP (mem, 0), 0), @@ -2548,19 +2228,17 @@ cris_split_movdx (rtx *operands) if (side_effects_p (addr)) fatal_insn ("unexpected side-effects in address", addr); - emit_insn (gen_rtx_SET - (operand_subword (dest, reverse, TRUE, mode), - change_address - (src, SImode, - plus_constant (Pmode, addr, - reverse * UNITS_PER_WORD)))); - emit_insn (gen_rtx_SET - (operand_subword (dest, ! reverse, TRUE, mode), - change_address - (src, SImode, - plus_constant (Pmode, addr, - (! reverse) * - UNITS_PER_WORD)))); + emit_move_insn (operand_subword (dest, reverse, TRUE, mode), + change_address + (src, SImode, + plus_constant (Pmode, addr, + reverse * UNITS_PER_WORD))); + emit_move_insn (operand_subword (dest, ! reverse, TRUE, mode), + change_address + (src, SImode, + plus_constant (Pmode, addr, + (! reverse) * + UNITS_PER_WORD))); } } else @@ -2582,17 +2260,14 @@ cris_split_movdx (rtx *operands) /* Whenever we emit insns with post-incremented addresses ourselves, we must add a post-inc note manually. */ mem = change_address (dest, SImode, addr); - insn - = gen_rtx_SET (mem, operand_subword (src, 0, TRUE, mode)); - insn = emit_insn (insn); + insn = emit_move_insn (mem, operand_subword (src, 0, TRUE, mode)); if (GET_CODE (XEXP (mem, 0)) == POST_INC) REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (XEXP (mem, 0), 0), REG_NOTES (insn)); mem = copy_rtx (mem); - insn = gen_rtx_SET (mem, operand_subword (src, 1, TRUE, mode)); - insn = emit_insn (insn); + insn = emit_move_insn (mem, operand_subword (src, 1, TRUE, mode)); if (GET_CODE (XEXP (mem, 0)) == POST_INC) REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (XEXP (mem, 0), 0), @@ -2606,15 +2281,13 @@ cris_split_movdx (rtx *operands) if (side_effects_p (addr)) fatal_insn ("unexpected side-effects in address", addr); - emit_insn (gen_rtx_SET - (change_address (dest, SImode, addr), - operand_subword (src, 0, TRUE, mode))); + emit_move_insn (change_address (dest, SImode, addr), + operand_subword (src, 0, TRUE, mode)); - emit_insn (gen_rtx_SET - (change_address (dest, SImode, - plus_constant (Pmode, addr, - UNITS_PER_WORD)), - operand_subword (src, 1, TRUE, mode))); + emit_move_insn (change_address (dest, SImode, + plus_constant (Pmode, addr, + UNITS_PER_WORD)), + operand_subword (src, 1, TRUE, mode)); } } @@ -2727,10 +2400,7 @@ cris_expand_prologue (void) stdarg_regs > 0; regno--, pretend -= 4, stdarg_regs--) { - insn = emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, - stack_pointer_rtx, - -4))); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4))); /* FIXME: When dwarf2 frame output and unless asynchronous exceptions, make dwarf2 bundle together all stack adjustments like it does for registers between stack @@ -2755,9 +2425,8 @@ cris_expand_prologue (void) /* Save SRP if not a leaf function. */ if (return_address_on_stack) { - insn = emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - -4 - pretend))); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-4 - pretend))); pretend = 0; RTX_FRAME_RELATED_P (insn) = 1; @@ -2771,9 +2440,8 @@ cris_expand_prologue (void) /* Set up the frame pointer, if needed. */ if (frame_pointer_needed) { - insn = emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - -4 - pretend))); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-4 - pretend))); pretend = 0; RTX_FRAME_RELATED_P (insn) = 1; @@ -2820,7 +2488,10 @@ cris_expand_prologue (void) side-effects insns are allowed. */ if ((last_movem_reg + 1) * 4 + size >= 64 && (last_movem_reg + 1) * 4 + size <= 128 - && (cris_cpu_version >= CRIS_CPU_SVINTO || n_saved == 1) + && cris_cpu_version >= CRIS_CPU_SVINTO + /* Don't use side-effect assignment for a single + move. */ + && n_saved > 1 && TARGET_SIDE_EFFECT_PREFIXES) { mem @@ -2836,10 +2507,9 @@ cris_expand_prologue (void) else { insn - = gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - -(n_saved * 4 + size))); - insn = emit_insn (insn); + = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-(n_saved * 4 + + size)))); RTX_FRAME_RELATED_P (insn) = 1; mem = gen_rtx_MEM (SImode, stack_pointer_rtx); @@ -2853,10 +2523,8 @@ cris_expand_prologue (void) size = 0; } - insn = emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, - stack_pointer_rtx, - -4 - size))); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-4 - size))); RTX_FRAME_RELATED_P (insn) = 1; mem = gen_rtx_MEM (SImode, stack_pointer_rtx); @@ -2880,7 +2548,9 @@ cris_expand_prologue (void) do it if side-effects insns are allowed. */ if ((last_movem_reg + 1) * 4 + size >= 64 && (last_movem_reg + 1) * 4 + size <= 128 - && (cris_cpu_version >= CRIS_CPU_SVINTO || n_saved == 1) + && cris_cpu_version >= CRIS_CPU_SVINTO + /* Don't use side-effect assignment for a single move. */ + && n_saved > 1 && TARGET_SIDE_EFFECT_PREFIXES) { mem @@ -2893,11 +2563,8 @@ cris_expand_prologue (void) } else { - insn - = gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - -(n_saved * 4 + size))); - insn = emit_insn (insn); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-(n_saved * 4 + size)))); RTX_FRAME_RELATED_P (insn) = 1; mem = gen_rtx_MEM (SImode, stack_pointer_rtx); @@ -2909,20 +2576,16 @@ cris_expand_prologue (void) /* We have to put outgoing argument space after regs. */ if (cfoa_size) { - insn = emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, - stack_pointer_rtx, - -cfoa_size))); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-cfoa_size))); RTX_FRAME_RELATED_P (insn) = 1; framesize += cfoa_size; } } else if ((size + cfoa_size) > 0) { - insn = emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, - stack_pointer_rtx, - -(cfoa_size + size)))); + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-(cfoa_size + size)))); RTX_FRAME_RELATED_P (insn) = 1; framesize += size + cfoa_size; } @@ -2988,9 +2651,8 @@ cris_expand_epilogue (void) { /* There is an area for outgoing parameters located before the saved registers. We have to adjust for that. */ - emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - argspace_offset))); + emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (argspace_offset))); /* Make sure we only do this once. */ argspace_offset = 0; } @@ -3013,9 +2675,7 @@ cris_expand_epilogue (void) if (argspace_offset) { - emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - argspace_offset))); + emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (argspace_offset))); argspace_offset = 0; } @@ -3023,8 +2683,7 @@ cris_expand_epilogue (void) gen_rtx_POST_INC (SImode, stack_pointer_rtx)); set_mem_alias_set (mem, get_frame_alias_set ()); insn - = emit_insn (cris_gen_movem_load (mem, - GEN_INT (last_movem_reg + 1), 0)); + = emit_insn (cris_gen_movem_load (mem, GEN_INT (last_movem_reg + 1))); /* Whenever we emit insns with post-incremented addresses ourselves, we must add a post-inc note manually. */ if (side_effects_p (PATTERN (insn))) @@ -3071,8 +2730,7 @@ cris_expand_epilogue (void) yet. */ size += argspace_offset; - emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, size))); + emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (size))); } /* If this function has no pushed register parameters @@ -3097,9 +2755,8 @@ cris_expand_epilogue (void) = alloc_EXPR_LIST (REG_INC, stack_pointer_rtx, REG_NOTES (insn)); if (crtl->calls_eh_return) - emit_insn (gen_addsi3 (stack_pointer_rtx, - stack_pointer_rtx, - gen_raw_REG (SImode, CRIS_STACKADJ_REG))); + emit_insn (gen_add2_insn (stack_pointer_rtx, + gen_raw_REG (SImode, CRIS_STACKADJ_REG))); cris_expand_return (false); } else @@ -3131,23 +2788,20 @@ cris_expand_epilogue (void) = alloc_EXPR_LIST (REG_INC, stack_pointer_rtx, REG_NOTES (insn)); } - emit_insn (gen_rtx_SET (stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, - pretend))); + emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (pretend))); } /* Perform the "physical" unwinding that the EH machinery calculated. */ if (crtl->calls_eh_return) - emit_insn (gen_addsi3 (stack_pointer_rtx, - stack_pointer_rtx, - gen_raw_REG (SImode, CRIS_STACKADJ_REG))); + emit_insn (gen_add2_insn (stack_pointer_rtx, + gen_raw_REG (SImode, CRIS_STACKADJ_REG))); cris_expand_return (false); } /* Worker function for generating movem from mem for load_multiple. */ rtx -cris_gen_movem_load (rtx src, rtx nregs_rtx, int nprefix) +cris_gen_movem_load (rtx src, rtx nregs_rtx) { int nregs = INTVAL (nregs_rtx); rtvec vec; @@ -3166,24 +2820,23 @@ cris_gen_movem_load (rtx src, rtx nregs_rtx, int nprefix) if (nregs == 1) return gen_movsi (gen_rtx_REG (SImode, 0), src); - vec = rtvec_alloc (nprefix + nregs - + (GET_CODE (XEXP (src, 0)) == POST_INC)); + vec = rtvec_alloc (nregs + (GET_CODE (XEXP (src, 0)) == POST_INC)); if (GET_CODE (XEXP (src, 0)) == POST_INC) { - RTVEC_ELT (vec, nprefix + 1) + RTVEC_ELT (vec, 1) = gen_rtx_SET (srcreg, plus_constant (Pmode, srcreg, nregs * 4)); eltno++; } src = replace_equiv_address (src, srcreg); - RTVEC_ELT (vec, nprefix) + RTVEC_ELT (vec, 0) = gen_rtx_SET (gen_rtx_REG (SImode, regno), src); regno += regno_inc; for (i = 1; i < nregs; i++, eltno++) { - RTVEC_ELT (vec, nprefix + eltno) + RTVEC_ELT (vec, eltno) = gen_rtx_SET (gen_rtx_REG (SImode, regno), adjust_address_nv (src, SImode, i * 4)); regno += regno_inc; @@ -3192,6 +2845,22 @@ cris_gen_movem_load (rtx src, rtx nregs_rtx, int nprefix) return gen_rtx_PARALLEL (VOIDmode, vec); } +/* Convenience function for CRIS-local use of emit_insn, wrapping the + argument in a parallel with a clobber of CRIS_CC0_REGNUM before + passing on to emit_insn. */ + +rtx_insn * +cris_emit_insn (rtx x) +{ + rtvec vec = rtvec_alloc (2); + + RTVEC_ELT (vec, 0) = x; + RTVEC_ELT (vec, 1) + = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CRIS_CC0_REGNUM)); + + return emit_insn (gen_rtx_PARALLEL (VOIDmode, vec)); +} + /* Worker function for generating movem to mem. If FRAME_RELATED, notes are added that the dwarf2 machinery understands. */ @@ -3219,11 +2888,9 @@ cris_emit_movem_store (rtx dest, rtx nregs_rtx, int increment, /* Don't use movem for just one insn. The insns are equivalent. */ if (nregs == 1) { - rtx mov = gen_rtx_SET (dest, gen_rtx_REG (SImode, 0)); - if (increment == 0) { - insn = emit_insn (mov); + insn = emit_move_insn (dest, gen_rtx_REG (SImode, 0)); if (frame_related) RTX_FRAME_RELATED_P (insn) = 1; return insn; @@ -3231,11 +2898,15 @@ cris_emit_movem_store (rtx dest, rtx nregs_rtx, int increment, /* If there was a request for a side-effect, create the ordinary parallel. */ - vec = rtvec_alloc (2); + vec = rtvec_alloc (3); + rtx mov = gen_rtx_SET (dest, gen_rtx_REG (SImode, 0)); RTVEC_ELT (vec, 0) = mov; RTVEC_ELT (vec, 1) = gen_rtx_SET (destreg, plus_constant (Pmode, destreg, increment)); + RTVEC_ELT (vec, 2) + = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CRIS_CC0_REGNUM)); + if (frame_related) { RTX_FRAME_RELATED_P (mov) = 1; diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 4aa12b8c276..e721d12d0a2 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -698,11 +698,8 @@ struct cum_args {int regs;}; /* Node: Condition Code */ -#define NOTICE_UPDATE_CC(EXP, INSN) cris_notice_update_cc (EXP, INSN) - -/* FIXME: Maybe define CANONICALIZE_COMPARISON later, when playing with - optimizations. It is needed; currently we do this with instruction - patterns and NOTICE_UPDATE_CC. */ +/* FIXME: Maybe define TARGET_CANONICALIZE_COMPARISON later, when + playing with optimizations. Definitely define SELECT_CC_MODE. */ /* Node: Costs */ diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index 9fe1f85552e..7690d7f0658 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -23,9 +23,6 @@ ;; See files "md.texi" and "rtl.def" for documentation on define_insn, ;; match_*, et. al. -;; -;; The function cris_notice_update_cc in cris.c handles condition code -;; updates for most instructions, helped by the "cc" attribute. ;; There are several instructions that are orthogonal in size, and seems ;; they could be matched by a single pattern without a specified size @@ -120,9 +117,9 @@ (const_string "no")) ;; We also need attributes to sanely determine the condition code -;; state. See cris_notice_update_cc for how this is used. +;; state. -(define_attr "cc" "none,clobber,normal,rev" (const_string "normal")) +(define_attr "cc" "none,clobber,normal" (const_string "normal")) ;; At the moment, this attribute is just used to help bb-reorder do its ;; work; the default 0 doesn't help it. Many insns have other lengths, @@ -155,6 +152,13 @@ ;; For the "usual" pattern size alternatives. (define_mode_iterator BWD [SI HI QI]) +(define_mode_iterator BWDD [DI SI HI QI]) + +;; To be able to refer to the same mode_attr for both a multi-mode +;; and a mode-specific pattern, we use some singleton iterators. +(define_mode_iterator DI_ [DI]) +(define_mode_iterator SI_ [SI]) + (define_mode_iterator WD [SI HI]) (define_mode_iterator BW [HI QI]) (define_mode_attr S [(SI "HI") (HI "QI")]) @@ -189,42 +193,35 @@ (include "predicates.md") (include "constraints.md") -;; Test insns. - -;; No test insns with side-effect on the mem addressing. -;; -;; See note on cmp-insns with side-effects (or lack of them) - -;; Normal named test patterns from SI on. - -(define_insn "tst<mode>" - [(set (cc0) - (compare (match_operand:BWD 0 "nonimmediate_operand" "r,Q>,m") - (const_int 0)))] - "" - "test<m> %0" - [(set_attr "slottable" "yes,yes,no")]) - ;; It seems that the position of the sign-bit and the fact that 0.0 is ;; all 0-bits would make "tstsf" a straight-forward implementation; ;; either "test.d" it for positive/negative or "btstq 30,r" it for ;; zeroness. ;; -;; FIXME: Do that some time; check next_cc0_user to determine if -;; zero or negative is tested for. +;; FIXME: Do that some time. ;; Compare insns. +;; These are used for compare insn, cbranch and cstore. +;; FIXME: Port-local reversing of operands is not done. Still needed? +;; (It shouldn't be; it should be done as part of register allocation.) +(define_mode_attr sCC_destc + [(DI "r, r,r,r,r,r,r") (SI "r,r, r, r,r,r") (HI "r, r, r,r") (QI "r, r, r,r")]) +(define_mode_attr cmp_op1c + [(DI "rm,r,r,r,r,r,r") (SI "r,r, rQ>,r,r,m") (HI "r, rQ>,r,m") (QI "r, rQ>,r,m")]) +(define_mode_attr cmp_op2c + [(DI "M,Kc,I,P,n,r,o") (SI "I,rQ>,M, P,g,M") (HI "rQ>,M, g,M") (QI "rQ>,M, g,M")]) + ;; We could optimize the sizes of the immediate operands for various ;; cases, but that is not worth it because of the very little usage of ;; DImode for anything else but a structure/block-mode. Just do the ;; obvious stuff for the straight-forward constraint letters. (define_insn "*cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "rm,r,r,r,r,r,r,o") - (match_operand:DI 1 "general_operand" "M,Kc,I,P,n,r,o,r")))] - "" + [(set (reg:CC CRIS_CC0_REGNUM) + (compare:CC (match_operand:DI_ 0 "nonimmediate_operand" "<cmp_op1c>") + (match_operand:DI_ 1 "general_operand" "<cmp_op2c>")))] + "reload_completed" "@ test.d %M0\;ax\;test.d %H0 cmpq %1,%M0\;ax\;cmpq 0,%H0 @@ -232,8 +229,7 @@ cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0 cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0 - cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0 - cmp.d %M0,%M1\;ax\;cmp.d %H0,%H1") + cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0") ;; Note that compare insns with side effect addressing mode (e.g.): ;; @@ -255,63 +251,44 @@ ;; (memory) operands. Avoid side-effect patterns, though (see above). (define_insn "*cmp_ext<mode>" - [(set (cc0) - (compare + [(set (reg:CC CRIS_CC0_REGNUM) + (compare:CC (match_operand:SI 0 "register_operand" "r,r") (match_operator:SI 2 "cris_extend_operator" [(match_operand:BW 1 "memory_operand" "Q>,m")])))] - "" + "reload_completed" "cmp%e2<m> %1,%0" [(set_attr "slottable" "yes,no")]) - -;; Swap operands; it seems the canonical look (if any) is not enforced. -;; -;; FIXME: Investigate that. - -(define_insn "*cmp_swapext<mode>" - [(set (cc0) - (compare - (match_operator:SI 2 "cris_extend_operator" - [(match_operand:BW 0 "memory_operand" "Q>,m")]) - (match_operand:SI 1 "register_operand" "r,r")))] - "" - "cmp%e2<m> %0,%1" - [(set_attr "slottable" "yes,no") - (set_attr "cc" "rev")]) ;; The "normal" compare patterns, from SI on. Special-cases with zero ;; are covered above. (define_insn "*cmpsi" - [(set (cc0) - (compare - (match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m") - (match_operand:SI 1 "general_operand" "I,r,Q>,r, P,g,r")))] - "" + [(set (reg:CC CRIS_CC0_REGNUM) + (compare:CC + (match_operand:SI_ 0 "nonimmediate_operand" "<cmp_op1c>") + (match_operand:SI_ 1 "general_operand" "<cmp_op2c>")))] + "reload_completed" "@ cmpq %1,%0 cmp.d %1,%0 - cmp.d %1,%0 - cmp.d %0,%1 + test.d %0 cmp%e1.%z1 %1,%0 cmp.d %1,%0 - cmp.d %0,%1" - [(set_attr "slottable" "yes,yes,yes,yes,no,no,no") - (set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")]) + test.d %0" + [(set_attr "slottable" "yes,yes,yes,no,no,no")]) (define_insn "*cmp<mode>" - [(set (cc0) - (compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m") - (match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))] - "" + [(set (reg:CC CRIS_CC0_REGNUM) + (compare:CC (match_operand:BW 0 "nonimmediate_operand" "<cmp_op1c>") + (match_operand:BW 1 "general_operand" "<cmp_op2c>")))] + "reload_completed" "@ cmp<m> %1,%0 + test<m> %0 cmp<m> %1,%0 - cmp<m> %0,%1 - cmp<m> %1,%0 - cmp<m> %0,%1" - [(set_attr "slottable" "yes,yes,yes,no,no") - (set_attr "cc" "normal,normal,rev,normal,rev")]) + test<m> %0" + [(set_attr "slottable" "yes,yes,no,no")]) ;; Pattern matching the BTST insn. ;; It is useful for "if (i & val)" constructs, where val is an exact @@ -321,8 +298,8 @@ ;; SImode. This mode is the only one needed, since gcc automatically ;; extends subregs for lower-size modes. FIXME: Add testcase. (define_insn "*btst" - [(set (cc0) - (compare + [(set (reg:CC CRIS_CC0_REGNUM) + (compare:CC (zero_extract:SI (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") @@ -330,7 +307,8 @@ (const_int 0)))] ;; Either it is a single bit, or consecutive ones starting at 0. ;; The btst ones depend on stuff in NOTICE_UPDATE_CC. - "CONST_INT_P (operands[1]) + "reload_completed + && CONST_INT_P (operands[1]) && (operands[1] == const1_rtx || operands[2] == const0_rtx) && (REG_S_P (operands[0]) || (operands[1] == const1_rtx @@ -399,8 +377,10 @@ ;; insn with pseudos that need more reloading. The question is where. (define_expand "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))] + [(parallel + [(set (match_operand:DI 0 "nonimmediate_operand") + (match_operand:DI 1 "general_operand")) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { if (MEM_P (operands[0]) @@ -437,7 +417,8 @@ (define_insn_and_split "*movdi_insn" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rx,m") - (match_operand:DI 1 "general_operand" "rx,g,rxM"))] + (match_operand:DI 1 "general_operand" "rx,g,rxM")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "(register_operand (operands[0], DImode) || register_operand (operands[1], DImode) || operands[1] == const0_rtx)" @@ -446,333 +427,14 @@ [(match_dup 2)] "operands[2] = cris_split_movdx (operands);") -;; Side-effect patterns for move.S1 [rx=ry+rx.S2],rw -;; and move.S1 [rx=ry+i],rz -;; Then movs.S1 and movu.S1 for both modes. -;; -;; move.S1 [rx=ry+rz.S],rw avoiding when rx is ry, or rw is rx -;; FIXME: These could have anonymous mode for operand 0. -;; FIXME: Special registers' alternatives too. - -(define_insn "*mov_side<mode>_biap" - [(set (match_operand:BW 0 "register_operand" "=r,r") - (mem:BW (plus:SI - (mult:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "const_int_operand" "n,n")) - (match_operand:SI 3 "register_operand" "r,r")))) - (set (match_operand:SI 4 "register_operand" "=*3,r") - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 3)))] - "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" - "@ - # - move<m> [%4=%3+%1%T2],%0") - -(define_insn "*mov_sidesisf_biap" - [(set (match_operand 0 "register_operand" "=r,r,x,x") - (mem (plus:SI - (mult:SI (match_operand:SI 1 "register_operand" "r,r,r,r") - (match_operand:SI 2 "const_int_operand" "n,n,n,n")) - (match_operand:SI 3 "register_operand" "r,r,r,r")))) - (set (match_operand:SI 4 "register_operand" "=*3,r,*3,r") - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 3)))] - "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD - && cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" - "@ - # - move.%s0 [%4=%3+%1%T2],%0 - # - move [%4=%3+%1%T2],%0") - -;; move.S1 [rx=ry+i],rz -;; avoiding move.S1 [ry=ry+i],rz -;; and move.S1 [rz=ry+i],rz -;; Note that "i" is allowed to be a register. - -(define_insn "*mov_side<mode>" - [(set (match_operand:BW 0 "register_operand" "=r,r,r,r,r") - (mem:BW - (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))) - (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r") - (plus:SI (match_dup 1) - (match_dup 2)))] - "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[2]) - || INTVAL (operands[2]) > 127 - || INTVAL (operands[2]) < -128 - || satisfies_constraint_N (operands[2]) - || satisfies_constraint_J (operands[2]))) - return "#"; - if (which_alternative == 4) - return "move<m> [%3=%2%S1],%0"; - return "move<m> [%3=%1%S2],%0"; -}) - -(define_insn "*mov_sidesisf" - [(set (match_operand 0 "register_operand" "=r,r,r,x,x,x,r,r,x,x") - (mem - (plus:SI - (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,r,r,r,R,R,R,R") - (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r>Rn,r,>Rn,r,r,r,r")))) - (set (match_operand:SI 3 "register_operand" "=*1,r,r,*1,r,r,*2,r,*2,r") - (plus:SI (match_dup 1) - (match_dup 2)))] - "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD - && cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" -{ - if ((which_alternative == 0 - || which_alternative == 3 - || which_alternative == 6 - || which_alternative == 8) - && (!CONST_INT_P (operands[2]) - || INTVAL (operands[2]) > 127 - || INTVAL (operands[2]) < -128 - || satisfies_constraint_N (operands[2]) - || satisfies_constraint_J (operands[2]))) - return "#"; - if (which_alternative < 3) - return "move.%s0 [%3=%1%S2],%0"; - if (which_alternative == 7) - return "move.%s0 [%3=%2%S1],%0"; - if (which_alternative == 9) - return "move [%3=%2%S1],%0"; - return "move [%3=%1%S2],%0"; -}) - -;; Other way around; move to memory. - -;; Note that the condition (which for side-effect patterns is usually a -;; call to cris_side_effect_mode_ok), isn't consulted for register -;; allocation preferences -- constraints is the method for that. The -;; drawback is that we can't exclude register allocation to cause -;; "move.s rw,[rx=ry+rz.S]" when rw==rx without also excluding rx==ry or -;; rx==rz if we use an earlyclobber modifier for the constraint for rx. -;; Instead of that, we recognize and split the cases where dangerous -;; register combinations are spotted: where a register is set in the -;; side-effect, and used in the main insn. We don't handle the case where -;; the set in the main insn overlaps the set in the side-effect; that case -;; must be handled in gcc. We handle just the case where the set in the -;; side-effect overlaps the input operand of the main insn (i.e. just -;; moves to memory). - -;; -;; move.s rz,[ry=rx+rw.S] - -(define_insn "*mov_side<mode>_biap_mem" - [(set (mem:BW (plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "const_int_operand" "n,n,n")) - (match_operand:SI 2 "register_operand" "r,r,r"))) - (match_operand:BW 3 "register_operand" "r,r,r")) - (set (match_operand:SI 4 "register_operand" "=*2,!3,r") - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 2)))] - "cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)" - "@ - # - # - move<m> %3,[%4=%2+%0%T1]") - -(define_insn "*mov_sidesisf_biap_mem" - [(set (mem (plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "r,r,r,r,r,r") - (match_operand:SI 1 "const_int_operand" "n,n,n,n,n,n")) - (match_operand:SI 2 "register_operand" "r,r,r,r,r,r"))) - (match_operand 3 "register_operand" "r,r,r,x,x,x")) - (set (match_operand:SI 4 "register_operand" "=*2,!3,r,*2,!3,r") - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 2)))] - "GET_MODE_SIZE (GET_MODE (operands[3])) == UNITS_PER_WORD - && cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)" - "@ - # - # - move.%s3 %3,[%4=%2+%0%T1] - # - # - move %3,[%4=%2+%0%T1]") - -;; Split for the case above where we're out of luck with register -;; allocation (again, the condition isn't checked for that), and we end up -;; with the set in the side-effect getting the same register as the input -;; register. - -(define_split - [(parallel - [(set (match_operator - 6 "cris_mem_op" - [(plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" "")) - (match_operand:SI 2 "register_operand" ""))]) - (match_operand 3 "register_operand" "")) - (set (match_operand:SI 4 "cris_nonsp_register_operand" "") - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 2)))])] - "reload_completed && reg_overlap_mentioned_p (operands[4], operands[3])" - [(set (match_dup 5) (match_dup 3)) - (set (match_dup 4) (match_dup 2)) - (set (match_dup 4) - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 4)))] - "operands[5] - = replace_equiv_address (operands[6], - gen_rtx_PLUS (SImode, - gen_rtx_MULT (SImode, - operands[0], - operands[1]), - operands[2]));") - -;; move.s rx,[ry=rz+i] -;; FIXME: These could have anonymous mode for operand 2. - -;; QImode - -(define_insn "*mov_side<mode>_mem" - [(set (mem:BW - (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r,R,R,R") - (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn,r,r,r"))) - (match_operand:BW 2 "register_operand" "r,r,r,r,r,r,r")) - (set (match_operand:SI 3 "register_operand" "=*0,!*2,r,r,*1,!*2,r") - (plus:SI (match_dup 0) - (match_dup 1)))] - "cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)" -{ - if ((which_alternative == 0 || which_alternative == 4) - && (!CONST_INT_P (operands[1]) - || INTVAL (operands[1]) > 127 - || INTVAL (operands[1]) < -128 - || satisfies_constraint_N (operands[1]) - || satisfies_constraint_J (operands[1]))) - return "#"; - if (which_alternative == 1 || which_alternative == 5) - return "#"; - if (which_alternative == 6) - return "move.%s2 %2,[%3=%1%S0]"; - return "move<m> %2,[%3=%0%S1]"; -}) - -;; SImode - -(define_insn "*mov_sidesisf_mem" - [(set (mem - (plus:SI - (match_operand:SI - 0 "cris_bdap_operand" - "%r, r, r,r, r, r,r, R,R, R,R, R") - (match_operand:SI - 1 "cris_bdap_operand" - "r>Rn,r>Rn,r,>Rn,r>Rn,r,>Rn,r,r, r,r, r"))) - (match_operand 2 "register_operand" - "r, r, r,r, x, x,x, r,r, r,x, x")) - (set (match_operand:SI 3 "register_operand" - "=*0,!2, r,r, *0, r,r, *1,!*2,r,*1,r") - (plus:SI (match_dup 0) - (match_dup 1)))] - "GET_MODE_SIZE (GET_MODE (operands[2])) == UNITS_PER_WORD - && cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)" -{ - if ((which_alternative == 0 || which_alternative == 4) - && (!CONST_INT_P (operands[1]) - || INTVAL (operands[1]) > 127 - || INTVAL (operands[1]) < -128 - || satisfies_constraint_N (operands[1]) - || satisfies_constraint_J (operands[1]))) - return "#"; - if (which_alternative == 1 - || which_alternative == 7 - || which_alternative == 8 - || which_alternative == 10) - return "#"; - if (which_alternative < 4) - return "move.%s2 %2,[%3=%0%S1]"; - if (which_alternative == 9) - return "move.%s2 %2,[%3=%1%S0]"; - if (which_alternative == 11) - return "move %2,[%3=%1%S0]"; - return "move %2,[%3=%0%S1]"; -}) - -;; Like the biap case, a split where the set in the side-effect gets the -;; same register as the input register to the main insn, since the -;; condition isn't checked at register allocation. - -(define_split - [(parallel - [(set (match_operator - 4 "cris_mem_op" - [(plus:SI - (match_operand:SI 0 "cris_bdap_operand" "") - (match_operand:SI 1 "cris_bdap_operand" ""))]) - (match_operand 2 "register_operand" "")) - (set (match_operand:SI 3 "cris_nonsp_register_operand" "") - (plus:SI (match_dup 0) (match_dup 1)))])] - "reload_completed && reg_overlap_mentioned_p (operands[3], operands[2])" - [(set (match_dup 4) (match_dup 2)) - (set (match_dup 3) (match_dup 0)) - (set (match_dup 3) (plus:SI (match_dup 3) (match_dup 1)))] - "") - -;; Clear memory side-effect patterns. It is hard to get to the mode if -;; the MEM was anonymous, so there will be one for each mode. - -;; clear.[bwd] [ry=rx+rw.s2] - -(define_insn "*clear_side<mode>_biap" - [(set (mem:BWD (plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "const_int_operand" "n,n")) - (match_operand:SI 2 "register_operand" "r,r"))) - (const_int 0)) - (set (match_operand:SI 3 "register_operand" "=*2,r") - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 2)))] - "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)" - "@ - # - clear<m> [%3=%2+%0%T1]") - -;; clear.[bwd] [ry=rz+i] - -(define_insn "*clear_side<mode>" - [(set (mem:BWD - (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn,r,r"))) - (const_int 0)) - (set (match_operand:SI 2 "register_operand" "=*0,r,r,*1,r") - (plus:SI (match_dup 0) - (match_dup 1)))] - "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[1]) - || INTVAL (operands[1]) > 127 - || INTVAL (operands[1]) < -128 - || satisfies_constraint_N (operands[1]) - || satisfies_constraint_J (operands[1]))) - return "#"; - if (which_alternative == 4) - return "clear<m> [%2=%1%S0]"; - return "clear<m> [%2=%0%S1]"; -}) - ;; Normal move patterns from SI on. (define_expand "movsi" - [(set - (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" ""))] + [(parallel + [(set + (match_operand:SI 0 "nonimmediate_operand") + (match_operand:SI 1 "general_operand")) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { /* If the output goes to a MEM, make sure we have zero or a register as @@ -789,7 +451,8 @@ (match_operand:SI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,g,r,r,g,rQ>,x, m,x") (match_operand:SI 1 "general_operand" - "r,Q>,M,M, I,r, M,n,g,r,x, rQ>,x,gi"))] + "r,Q>,M,M, I,r, M,n,g,r,x, rQ>,x,gi")) + (clobber (reg:CC CRIS_CC0_REGNUM))] ;; Note that we prefer not to use the S alternative (if for some reason ;; it competes with others) above, but g matches S. "" @@ -844,108 +507,13 @@ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,yes,yes,no,no") (set_attr "cc" "*,*,*,*,*,*,*,*,*,*,none,none,none,none")]) -;; Extend operations with side-effect from mem to register, using -;; MOVS/MOVU. These are from mem to register only. -;; -;; [rx=ry+rz.S] -;; -;; QImode to HImode -;; -;; FIXME: Can we omit extend to HImode, since GCC should truncate for -;; HImode by itself? Perhaps use only anonymous modes? - -(define_insn "*ext_sideqihi_biap" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI - 5 "cris_extend_operator" - [(mem:QI (plus:SI - (mult:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "const_int_operand" "n,n")) - (match_operand:SI 3 "register_operand" "r,r")))])) - (set (match_operand:SI 4 "register_operand" "=*3,r") - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 3)))] - "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" - "@ - # - mov%e5.%m5 [%4=%3+%1%T2],%0") - -(define_insn "*ext_side<mode>si_biap" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI - 5 "cris_extend_operator" - [(mem:BW (plus:SI - (mult:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "const_int_operand" "n,n")) - (match_operand:SI 3 "register_operand" "r,r")))])) - (set (match_operand:SI 4 "register_operand" "=*3,r") - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 3)))] - "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" - "@ - # - mov%e5<m> [%4=%3+%1%T2],%0") - -;; Same but [rx=ry+i] - -;; QImode to HImode - -(define_insn "*ext_sideqihi" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") - (match_operator:HI - 4 "cris_extend_operator" - [(mem:QI (plus:SI - (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])) - (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r") - (plus:SI (match_dup 1) - (match_dup 2)))] - "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[2]) - || INTVAL (operands[2]) > 127 - || INTVAL (operands[2]) < -128 - || satisfies_constraint_N (operands[2]) - || satisfies_constraint_J (operands[2]))) - return "#"; - if (which_alternative == 4) - return "mov%e4.%m4 [%3=%2%S1],%0"; - return "mov%e4.%m4 [%3=%1%S2],%0"; -}) - -(define_insn "*ext_side<mode>si" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (match_operator:SI - 4 "cris_extend_operator" - [(mem:BW (plus:SI - (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])) - (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r") - (plus:SI (match_dup 1) - (match_dup 2)))] - "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[2]) - || INTVAL (operands[2]) > 127 - || INTVAL (operands[2]) < -128 - || satisfies_constraint_N (operands[2]) - || satisfies_constraint_J (operands[2]))) - return "#"; - if (which_alternative == 4) - return "mov%e4<m> [%3=%2%S1],%0"; - return "mov%e4<m> [%3=%1%S2],%0"; -}) - ;; FIXME: See movsi. (define_insn "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r,r,x") - (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r"))] + (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" { switch (which_alternative) @@ -987,7 +555,8 @@ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+r,r, r,Q>,Q>,g,r,g")) - (match_operand:HI 1 "general_operand" "r,Q>,M,M, r, M,g,r"))] + (match_operand:HI 1 "general_operand" "r,Q>,M,M, r, M,g,r")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ move.w %1,%0 @@ -1018,7 +587,8 @@ (define_insn "movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r,r,x") - (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r"))] + (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ move.b %1,%0 @@ -1039,7 +609,8 @@ (define_insn "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+r,Q>,r, r,Q>,g,g,r")) - (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, M,r,g"))] + (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, M,r,g")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ move.b %1,%0 @@ -1059,7 +630,8 @@ (define_insn "movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x") - (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g"))] + (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ move.d %1,%0 @@ -1117,19 +689,22 @@ (define_insn "extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:SI 1 "general_operand" "g")))] + (sign_extend:DI (match_operand:SI 1 "general_operand" "g"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "move.d %1,%M0\;smi %H0\;neg.d %H0,%H0") (define_insn "extend<mode>di2" [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:BW 1 "general_operand" "g")))] + (sign_extend:DI (match_operand:BW 1 "general_operand" "g"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "movs<m> %1,%M0\;smi %H0\;neg.d %H0,%H0") (define_insn "extend<mode>si2" [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (sign_extend:SI (match_operand:BW 1 "general_operand" "r,Q>,g")))] + (sign_extend:SI (match_operand:BW 1 "general_operand" "r,Q>,g"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "movs<m> %1,%0" [(set_attr "slottable" "yes,yes,no")]) @@ -1139,7 +714,8 @@ (define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (sign_extend:HI (match_operand:QI 1 "general_operand" "r,Q>,g")))] + (sign_extend:HI (match_operand:QI 1 "general_operand" "r,Q>,g"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "movs.b %1,%0" [(set_attr "slottable" "yes,yes,no")]) @@ -1151,7 +727,8 @@ (define_insn "zero_extend<mode>si2" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (zero_extend:SI - (match_operand:BW 1 "nonimmediate_operand" "r,Q>,m")))] + (match_operand:BW 1 "nonimmediate_operand" "r,Q>,m"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "movu<m> %1,%0" [(set_attr "slottable" "yes,yes,no")]) @@ -1161,139 +738,31 @@ (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "r,Q>,m")))] + (match_operand:QI 1 "nonimmediate_operand" "r,Q>,m"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "movu.b %1,%0" [(set_attr "slottable" "yes,yes,no")]) -;; All kinds of arithmetic and logical instructions. -;; -;; First, anonymous patterns to match addressing modes with -;; side-effects. -;; -;; op.S [rx=ry+I],rz; (add, sub, or, and, bound). -;; -;; [rx=ry+rz.S] - -(define_insn "*op_side<mode>_biap" - [(set (match_operand:BWD 0 "register_operand" "=r,r") - (match_operator:BWD - 6 "cris_orthogonal_operator" - [(match_operand:BWD 1 "register_operand" "0,0") - (mem:BWD (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "const_int_operand" "n,n")) - (match_operand:SI 4 "register_operand" "r,r")))])) - (set (match_operand:SI 5 "register_operand" "=*4,r") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))] - "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)" - "@ - # - %x6<m> [%5=%4+%2%T3],%0") - -;; [rx=ry+i] ([%4=%2+%3]) - -(define_insn "*op_side<mode>" - [(set (match_operand:BWD 0 "register_operand" "=r,r,r,r,r") - (match_operator:BWD - 5 "cris_orthogonal_operator" - [(match_operand:BWD 1 "register_operand" "0,0,0,0,0") - (mem:BWD (plus:SI - (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])) - (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r") - (plus:SI (match_dup 2) - (match_dup 3)))] - "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[3]) - || INTVAL (operands[3]) > 127 - || INTVAL (operands[3]) < -128 - || satisfies_constraint_N (operands[3]) - || satisfies_constraint_J (operands[3]))) - return "#"; - if (which_alternative == 4) - return "%x5.%s0 [%4=%3%S2],%0"; - return "%x5<m> [%4=%2%S3],%0"; -}) - -;; To match all cases for commutative operations we may have to have the -;; following pattern for add, or & and. I do not know really, but it does -;; not break anything. -;; -;; FIXME: This really ought to be checked. -;; -;; op.S [rx=ry+I],rz; -;; -;; [rx=ry+rz.S] - -(define_insn "*op_swap_side<mode>_biap" - [(set (match_operand:BWD 0 "register_operand" "=r,r") - (match_operator:BWD - 6 "cris_commutative_orth_op" - [(mem:BWD (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "const_int_operand" "n,n")) - (match_operand:SI 4 "register_operand" "r,r"))) - (match_operand:BWD 1 "register_operand" "0,0")])) - (set (match_operand:SI 5 "register_operand" "=*4,r") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))] - "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)" - "@ - # - %x6<m> [%5=%4+%2%T3],%0") - -;; [rx=ry+i] ([%4=%2+%3]) -;; FIXME: These could have anonymous mode for operand 0. - -;; QImode - -(define_insn "*op_swap_side<mode>" - [(set (match_operand:BWD 0 "register_operand" "=r,r,r,r,r") - (match_operator:BWD - 5 "cris_commutative_orth_op" - [(mem:BWD - (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r"))) - (match_operand:BWD 1 "register_operand" "0,0,0,0,0")])) - (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r") - (plus:SI (match_dup 2) - (match_dup 3)))] - "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[3]) - || INTVAL (operands[3]) > 127 - || INTVAL (operands[3]) < -128 - || satisfies_constraint_N (operands[3]) - || satisfies_constraint_J (operands[3]))) - return "#"; - if (which_alternative == 4) - return "%x5<m> [%4=%3%S2],%0"; - return "%x5<m> [%4=%2%S3],%0"; -}) - ;; Add operations, standard names. ;; Note that for the 'P' constraint, the high part can be -1 or 0. We ;; output the insn through the 'A' output modifier as "adds.w" and "addq", ;; respectively. (define_expand "adddi3" - [(set (match_operand:DI 0 "register_operand") - (plus:DI (match_operand:DI 1 "register_operand") - (match_operand:DI 2 "general_operand")))] + [(parallel + [(set (match_operand:DI 0 "register_operand") + (plus:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") (define_insn "*adddi3" [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r") (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,r") - (match_operand:DI 2 "general_operand" "J,N,P,g,!To")))] + (match_operand:DI 2 "general_operand" "J,N,P,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ addq %2,%M0\;ax\;addq 0,%H0 @@ -1303,10 +772,12 @@ add.d %M2,%M1,%M0\;ax\;add.d %H2,%H1,%H0") (define_expand "add<mode>3" - [(set (match_operand:BWD 0 "register_operand") - (plus:BWD - (match_operand:BWD 1 "register_operand") - (match_operand:BWD 2 "general_operand")))] + [(parallel + [(set (match_operand:BWD 0 "register_operand") + (plus:BWD + (match_operand:BWD 1 "register_operand") + (match_operand:BWD 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") @@ -1314,7 +785,8 @@ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r, r") (plus:SI (match_operand:SI 1 "register_operand" "%0,0, 0,0,0,0,r, r") - (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,g,!To,0")))] + (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,g,!To,0"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] ;; The last constraint is due to that after reload, the '%' is not ;; honored, and canonicalization doesn't care about keeping the same @@ -1365,7 +837,8 @@ (define_insn "*addhi3" [(set (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r") (plus:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r") - (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))] + (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ add.w %2,%0 @@ -1380,7 +853,8 @@ (define_insn "*addqi3" [(set (match_operand:QI 0 "register_operand" "=r,r, r,r,r,r,r") (plus:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,0,0,r") - (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To")))] + (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ add.b %2,%0 @@ -1402,16 +876,19 @@ ;; output the insn through the 'D' output modifier as "subs.w" and "subq", ;; respectively. (define_expand "subdi3" - [(set (match_operand:DI 0 "register_operand") - (minus:DI (match_operand:DI 1 "register_operand") - (match_operand:DI 2 "general_operand")))] + [(parallel + [(set (match_operand:DI 0 "register_operand") + (minus:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") (define_insn "*subdi3" [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r") (minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0,r") - (match_operand:DI 2 "general_operand" "J,N,P,g,!To")))] + (match_operand:DI 2 "general_operand" "J,N,P,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ subq %2,%M0\;ax\;subq 0,%H0 @@ -1421,10 +898,12 @@ sub.d %M2,%M1,%M0\;ax\;sub.d %H2,%H1,%H0") (define_expand "sub<mode>3" - [(set (match_operand:BWD 0 "register_operand") - (minus:BWD - (match_operand:BWD 1 "register_operand") - (match_operand:BWD 2 "general_operand")))] + [(parallel + [(set (match_operand:BWD 0 "register_operand") + (minus:BWD + (match_operand:BWD 1 "register_operand") + (match_operand:BWD 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") @@ -1432,7 +911,8 @@ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r,r") (minus:SI (match_operand:SI 1 "register_operand" "0,0, 0,0,0,0,0,r") - (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To")))] + (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" ;; This does not do the optimal: "addu.w 65535,r0" when %2 is negative. @@ -1452,7 +932,8 @@ (define_insn "*sub<mode>3" [(set (match_operand:BW 0 "register_operand" "=r,r, r,r,r,r") (minus:BW (match_operand:BW 1 "register_operand" "0,0, 0,0,0,r") - (match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To")))] + (match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ sub<m> %2,%0 @@ -1464,314 +945,6 @@ [(set_attr "slottable" "yes,yes,yes,yes,no,no") (set_attr "cc" "normal,normal,clobber,clobber,normal,normal")]) -;; CRIS has some add/sub-with-sign/zero-extend instructions. -;; Although these perform sign/zero-extension to SImode, they are -;; equally applicable for the HImode case. -;; FIXME: Check; GCC should handle the widening. -;; Note that these must be located after the normal add/sub patterns, -;; so not to get constants into any less specific operands. -;; -;; Extend with add/sub and side-effect. -;; -;; ADDS/SUBS/ADDU/SUBU and BOUND, which needs a check for zero_extend -;; -;; adds/subs/addu/subu bound [rx=ry+rz.S] - -;; QImode to HImode -;; FIXME: GCC should widen. - -(define_insn "*extopqihi_side_biap" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI - 6 "cris_additive_operand_extend_operator" - [(match_operand:HI 1 "register_operand" "0,0") - (match_operator:HI - 7 "cris_extend_operator" - [(mem:QI (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "const_int_operand" "n,n")) - (match_operand:SI 4 "register_operand" "r,r")))])])) - (set (match_operand:SI 5 "register_operand" "=*4,r") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))] - "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)" - "@ - # - %x6%e7.%m7 [%5=%4+%2%T3],%0") - -(define_insn "*extop<mode>si_side_biap" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI - 6 "cris_operand_extend_operator" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operator:SI - 7 "cris_extend_operator" - [(mem:BW (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "const_int_operand" "n,n")) - (match_operand:SI 4 "register_operand" "r,r")))])])) - (set (match_operand:SI 5 "register_operand" "=*4,r") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))] - "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND) - && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)" - "@ - # - %x6%e7<m> [%5=%4+%2%T3],%0") - - -;; [rx=ry+i] - -;; QImode to HImode - -(define_insn "*extopqihi_side" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") - (match_operator:HI - 5 "cris_additive_operand_extend_operator" - [(match_operand:HI 1 "register_operand" "0,0,0,0,0") - (match_operator:HI - 6 "cris_extend_operator" - [(mem:QI - (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r") - ))])])) - (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r") - (plus:SI (match_dup 2) - (match_dup 3)))] - "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[3]) - || INTVAL (operands[3]) > 127 - || INTVAL (operands[3]) < -128 - || satisfies_constraint_N (operands[3]) - || satisfies_constraint_J (operands[3]))) - return "#"; - if (which_alternative == 4) - return "%x5%E6.%m6 [%4=%3%S2],%0"; - return "%x5%E6.%m6 [%4=%2%S3],%0"; -}) - -(define_insn "*extop<mode>si_side" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (match_operator:SI - 5 "cris_operand_extend_operator" - [(match_operand:SI 1 "register_operand" "0,0,0,0,0") - (match_operator:SI - 6 "cris_extend_operator" - [(mem:BW - (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r") - ))])])) - (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r") - (plus:SI (match_dup 2) - (match_dup 3)))] - "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND) - && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[3]) - || INTVAL (operands[3]) > 127 - || INTVAL (operands[3]) < -128 - || satisfies_constraint_N (operands[3]) - || satisfies_constraint_J (operands[3]))) - return "#"; - if (which_alternative == 4) - return "%x5%E6<m> [%4=%3%S2],%0"; - return "%x5%E6<m> [%4=%2%S3],%0"; -}) - - -;; As with op.S we may have to add special pattern to match commuted -;; operands to adds/addu and bound -;; -;; adds/addu/bound [rx=ry+rz.S] - -;; QImode to HImode -;; FIXME: GCC should widen. - -(define_insn "*extopqihi_swap_side_biap" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (plus:HI - (match_operator:HI - 6 "cris_extend_operator" - [(mem:QI (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "const_int_operand" "n,n")) - (match_operand:SI 4 "register_operand" "r,r")))]) - (match_operand:HI 1 "register_operand" "0,0"))) - (set (match_operand:SI 5 "register_operand" "=*4,r") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))] - "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)" - "@ - # - add%e6.b [%5=%4+%2%T3],%0") - -(define_insn "*extop<mode>si_swap_side_biap" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI - 7 "cris_plus_or_bound_operator" - [(match_operator:SI - 6 "cris_extend_operator" - [(mem:BW (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "const_int_operand" "n,n")) - (match_operand:SI 4 "register_operand" "r,r")))]) - (match_operand:SI 1 "register_operand" "0,0")])) - (set (match_operand:SI 5 "register_operand" "=*4,r") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))] - "(GET_CODE (operands[7]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND) - && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)" - "@ - # - %x7%E6<m> [%5=%4+%2%T3],%0") - -;; [rx=ry+i] -;; FIXME: GCC should widen. - -;; QImode to HImode - -(define_insn "*extopqihi_swap_side" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") - (plus:HI - (match_operator:HI - 5 "cris_extend_operator" - [(mem:QI (plus:SI - (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]) - (match_operand:HI 1 "register_operand" "0,0,0,0,0"))) - (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r") - (plus:SI (match_dup 2) - (match_dup 3)))] - "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[3]) - || INTVAL (operands[3]) > 127 - || INTVAL (operands[3]) < -128 - || satisfies_constraint_N (operands[3]) - || satisfies_constraint_J (operands[3]))) - return "#"; - if (which_alternative == 4) - return "add%e5.b [%4=%3%S2],%0"; - return "add%e5.b [%4=%2%S3],%0"; -}) - -(define_insn "*extop<mode>si_swap_side" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (match_operator:SI - 6 "cris_plus_or_bound_operator" - [(match_operator:SI - 5 "cris_extend_operator" - [(mem:BW (plus:SI - (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R") - (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]) - (match_operand:SI 1 "register_operand" "0,0,0,0,0")])) - (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r") - (plus:SI (match_dup 2) - (match_dup 3)))] - "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[5]) == ZERO_EXTEND) - && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)" -{ - if ((which_alternative == 0 || which_alternative == 3) - && (!CONST_INT_P (operands[3]) - || INTVAL (operands[3]) > 127 - || INTVAL (operands[3]) < -128 - || satisfies_constraint_N (operands[3]) - || satisfies_constraint_J (operands[3]))) - return "#"; - if (which_alternative == 4) - return \"%x6%E5.%m5 [%4=%3%S2],%0\"; - return "%x6%E5<m> [%4=%2%S3],%0"; -}) - -;; Extend versions (zero/sign) of normal add/sub (no side-effects). - -;; QImode to HImode -;; FIXME: GCC should widen. - -(define_insn "*extopqihi" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (match_operator:HI - 3 "cris_additive_operand_extend_operator" - [(match_operand:HI 1 "register_operand" "0,0,0,r") - (match_operator:HI - 4 "cris_extend_operator" - [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))] - "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)" - "@ - %x3%E4.%m4 %2,%0 - %x3%E4.%m4 %2,%0 - %x3%E4.%m4 %2,%0 - %x3%E4.%m4 %2,%1,%0" - [(set_attr "slottable" "yes,yes,no,no") - (set_attr "cc" "clobber")]) - -;; QImode to SImode - -(define_insn "*extop<mode>si" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (match_operator:SI - 3 "cris_operand_extend_operator" - [(match_operand:SI 1 "register_operand" "0,0,0,r") - (match_operator:SI - 4 "cris_extend_operator" - [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))] - "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)" - "@ - %x3%E4<m> %2,%0 - %x3%E4<m> %2,%0 - %x3%E4<m> %2,%0 - %x3%E4<m> %2,%1,%0" - [(set_attr "slottable" "yes,yes,no,no")]) - -;; As with the side-effect patterns, may have to have swapped operands for add. -;; For commutative operands, these are the canonical forms. - -;; QImode to HImode - -(define_insn "*addxqihi_swap" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (plus:HI - (match_operator:HI - 3 "cris_extend_operator" - [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")]) - (match_operand:HI 1 "register_operand" "0,0,0,r")))] - "operands[1] != frame_pointer_rtx" - "@ - add%e3.b %2,%0 - add%e3.b %2,%0 - add%e3.b %2,%0 - add%e3.b %2,%1,%0" - [(set_attr "slottable" "yes,yes,no,no") - (set_attr "cc" "clobber")]) - -(define_insn "*extop<mode>si" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (match_operator:SI - 4 "cris_plus_or_bound_operator" - [(match_operator:SI - 3 "cris_extend_operator" - [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")]) - (match_operand:SI 1 "register_operand" "0,0,0,r")]))] - "(GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND) - && operands[1] != frame_pointer_rtx" - "@ - %x4%E3<m> %2,%0 - %x4%E3<m> %2,%0 - %x4%E3<m> %2,%0 - %x4%E3<m> %2,%1,%0" - [(set_attr "slottable" "yes,yes,no,no")]) - ;; This is the special case when we use what corresponds to the ;; instruction above in "casesi". Do *not* change it to use the generic ;; pattern and "REG 15" as pc; I did that and it led to madness and @@ -1803,7 +976,8 @@ (pc)))) (pc)) (label_ref (match_operand 2 "" "")))) - (use (label_ref (match_operand 3 "" "")))] + (use (label_ref (match_operand 3 "" ""))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "operands[0] != frame_pointer_rtx" "adds.w [$pc+%0.w],$pc" [(set_attr "cc" "clobber")]) @@ -1821,7 +995,8 @@ [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "const_int_operand" "n")))] + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "operands[0] != frame_pointer_rtx && operands[1] != frame_pointer_rtx && CONST_INT_P (operands[2]) @@ -1861,50 +1036,13 @@ [(set_attr "slottable" "yes") (set_attr "cc" "none")]) -;; The mstep instruction. Probably not useful by itself; it's to -;; non-linear wrt. the other insns. We used to expand to it, so at least -;; it's correct. - -(define_insn "mstep_shift" - [(set (match_operand:SI 0 "register_operand" "=r") - (if_then_else:SI - (lt:SI (cc0) (const_int 0)) - (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") - (const_int 1)) - (match_operand:SI 2 "register_operand" "r")) - (ashift:SI (match_operand:SI 3 "register_operand" "0") - (const_int 1))))] - "" - "mstep %2,%0" - [(set_attr "slottable" "yes")]) - -;; When illegitimate addresses are legitimized, sometimes gcc forgets -;; to canonicalize the multiplications. -;; -;; FIXME: Check gcc > 2.7.2, remove and possibly fix in gcc. - -(define_insn "mstep_mul" - [(set (match_operand:SI 0 "register_operand" "=r") - (if_then_else:SI - (lt:SI (cc0) (const_int 0)) - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "0") - (const_int 2)) - (match_operand:SI 2 "register_operand" "r")) - (mult:SI (match_operand:SI 3 "register_operand" "0") - (const_int 2))))] - "operands[0] != frame_pointer_rtx - && operands[1] != frame_pointer_rtx - && operands[2] != frame_pointer_rtx - && operands[3] != frame_pointer_rtx" - "mstep %2,%0" - [(set_attr "slottable" "yes")]) - (define_insn "<u>mul<s><mode>3" [(set (match_operand:WD 0 "register_operand" "=r") (mult:WD (szext:WD (match_operand:<S> 1 "register_operand" "%0")) (szext:WD (match_operand:<S> 2 "register_operand" "r")))) - (clobber (match_scratch:SI 3 "=h"))] + (clobber (match_scratch:SI 3 "=h")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_MUL_INSNS" "%!mul<su><mm> %2,%0" [(set (attr "slottable") @@ -1927,7 +1065,8 @@ [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "r"))) - (clobber (match_scratch:SI 3 "=h"))] + (clobber (match_scratch:SI 3 "=h")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_MUL_INSNS" "%!muls.d %2,%0" [(set (attr "slottable") @@ -1941,16 +1080,14 @@ ;; When needed, we can get the high 32 bits from the overflow ;; register. We don't care to split and optimize these. -;; -;; Note that cc0 is still valid after the move-from-overflow-register -;; insn; no special precaution need to be taken in cris_notice_update_cc. (define_insn "<u>mulsidi3" [(set (match_operand:DI 0 "register_operand" "=r") (mult:DI (szext:DI (match_operand:SI 1 "register_operand" "%0")) (szext:DI (match_operand:SI 2 "register_operand" "r")))) - (clobber (match_scratch:SI 3 "=h"))] + (clobber (match_scratch:SI 3 "=h")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_MUL_INSNS" "%!mul<su>.d %2,%M0\;move $mof,%H0") @@ -1976,7 +1113,8 @@ (szext:DI (match_operand:SI 1 "register_operand" "r,r,0,r")) (szext:DI (match_operand:SI 2 "register_operand" "r,r,r,0"))) (const_int 32)))) - (clobber (match_scratch:SI 3 "=1,2,h,h"))] + (clobber (match_scratch:SI 3 "=1,2,h,h")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_MUL_INSNS" "@ %!mul<su>.d %2,%1 @@ -1998,7 +1136,8 @@ (const_int 1)) (match_operand:SI 4 "register_operand" "2")) (ashift:SI (match_operand:SI 5 "register_operand" "0") - (const_int 1))))] + (const_int 1)))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "dstep %2,%0" [(set_attr "slottable" "yes")]) @@ -2017,7 +1156,8 @@ (const_int 2)) (match_operand:SI 4 "register_operand" "2")) (mult:SI (match_operand:SI 5 "register_operand" "0") - (const_int 2))))] + (const_int 2)))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "operands[0] != frame_pointer_rtx && operands[1] != frame_pointer_rtx && operands[2] != frame_pointer_rtx @@ -2041,9 +1181,11 @@ ;; FIXME: This should be made obsolete. (define_expand "andsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (and:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] + [(parallel + [(set (match_operand:SI 0 "nonimmediate_operand") + (and:SI (match_operand:SI 1 "nonimmediate_operand") + (match_operand:SI 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { if (! (CONST_INT_P (operands[2]) @@ -2072,7 +1214,8 @@ reg1 = reg0; } - emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (SImode, reg1, operands[2]))); + cris_emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (SImode, reg1, + operands[2]))); /* Make sure we get the right *final* destination. */ if (! REG_P (operands[0])) @@ -2087,16 +1230,20 @@ (define_insn "*andsi_movu" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (and:SI (match_operand:SI 1 "nonimmediate_operand" "%r,Q,To") - (match_operand:SI 2 "const_int_operand" "n,n,n")))] + (match_operand:SI 2 "const_int_operand" "n,n,n"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "(INTVAL (operands[2]) == 255 || INTVAL (operands[2]) == 65535) && !side_effects_p (operands[1])" "movu.%z2 %1,%0" [(set_attr "slottable" "yes,yes,no")]) +;; FIXME: Remember, this does *not* actually affect condition codes; +;; get rid of the clobber. (define_insn "*andsi_clear" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,Q,Q,To,To") (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0") - (match_operand:SI 2 "const_int_operand" "P,n,P,n,P,n")))] + (match_operand:SI 2 "const_int_operand" "P,n,P,n,P,n"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "(INTVAL (operands[2]) == -65536 || INTVAL (operands[2]) == -256) && !side_effects_p (operands[0])" "@ @@ -2120,7 +1267,8 @@ (define_insn "*expanded_andsi" [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,r") - (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To")))] + (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ andq %2,%0 @@ -2132,15 +1280,17 @@ ;; For both QI and HI we may use the quick patterns. This results in ;; useless condition codes, but that is used rarely enough for it to -;; normally be a win (could check ahead for use of cc0, but seems to be -;; more pain than win). +;; normally be a win (could check ahead for use of CRIS_CC0_REGNUM, but +;; seems to be more pain than win). ;; FIXME: See note for andsi3 (define_expand "andhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (and:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] + [(parallel + [(set (match_operand:HI 0 "nonimmediate_operand") + (and:HI (match_operand:HI 1 "nonimmediate_operand") + (match_operand:HI 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { if (! (CONST_INT_P (operands[2]) @@ -2160,7 +1310,8 @@ reg1 = reg0; } - emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (HImode, reg1, operands[2]))); + cris_emit_insn (gen_rtx_SET (reg0, gen_rtx_AND (HImode, reg1, + operands[2]))); /* Make sure we get the right destination. */ if (! REG_P (operands[0])) @@ -2175,7 +1326,8 @@ (define_insn "*andhi_movu" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (and:HI (match_operand:HI 1 "nonimmediate_operand" "r,Q,To") - (const_int 255)))] + (const_int 255))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "!side_effects_p (operands[1])" "mOvu.b %1,%0" [(set_attr "slottable" "yes,yes,no")]) @@ -2183,7 +1335,8 @@ (define_insn "*andhi_clear" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q,To") (and:HI (match_operand:HI 1 "nonimmediate_operand" "0,0,0") - (const_int -256)))] + (const_int -256))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "!side_effects_p (operands[0])" "cLear.b %0" [(set_attr "slottable" "yes,yes,no") @@ -2194,7 +1347,8 @@ (define_insn "*expanded_andhi" [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r") (and:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r") - (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))] + (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] ;; Sidenote: the tightening from "general_operand" to ;; "register_operand" for operand 1 actually increased the register @@ -2241,7 +1395,8 @@ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r,r,r")) (and:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "r,Q>,g")))] + (match_operand:HI 1 "general_operand" "r,Q>,g"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ and.w %1,%0 @@ -2250,16 +1405,19 @@ [(set_attr "slottable" "yes,yes,no")]) (define_expand "andqi3" - [(set (match_operand:QI 0 "register_operand") - (and:QI (match_operand:QI 1 "register_operand") - (match_operand:QI 2 "general_operand")))] + [(parallel + [(set (match_operand:QI 0 "register_operand") + (and:QI (match_operand:QI 1 "register_operand") + (match_operand:QI 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") (define_insn "*andqi3" [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r") (and:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r") - (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))] + (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ andq %2,%0 @@ -2275,7 +1433,8 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r,r,r")) (and:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "r,Q>,g")))] + (match_operand:QI 1 "general_operand" "r,Q>,g"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ and.b %1,%0 @@ -2291,16 +1450,19 @@ ;; with andsi3. (define_expand "ior<mode>3" - [(set (match_operand:BWD 0 "register_operand") - (ior:BWD (match_operand:BWD 1 "register_operand") - (match_operand:BWD 2 "general_operand")))] + [(parallel + [(set (match_operand:BWD 0 "register_operand") + (ior:BWD (match_operand:BWD 1 "register_operand") + (match_operand:BWD 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") (define_insn "*iorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,0,r") - (match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To")))] + (match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ orq %2,%0 @@ -2315,7 +1477,8 @@ (define_insn "*iorhi3" [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r") (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r") - (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))] + (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ orq %2,%0 @@ -2331,7 +1494,8 @@ (define_insn "*iorqi3" [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r") (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r") - (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))] + (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "@ orq %2,%0 @@ -2351,7 +1515,8 @@ (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r") (xor:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "r")))] + (match_operand:SI 2 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "xor %2,%0" [(set_attr "slottable" "yes")]) @@ -2359,7 +1524,8 @@ (define_insn "xor<mode>3" [(set (match_operand:BW 0 "register_operand" "=r") (xor:BW (match_operand:BW 1 "register_operand" "%0") - (match_operand:BW 2 "register_operand" "r")))] + (match_operand:BW 2 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "xor %2,%0" [(set_attr "slottable" "yes") @@ -2371,12 +1537,13 @@ ;; example. (define_expand "negsf2" - [(set (match_dup 2) - (match_dup 3)) - (parallel [(set (match_operand:SF 0 "register_operand" "=r") - (neg:SF (match_operand:SF 1 - "register_operand" "0"))) - (use (match_dup 2))])] + [(parallel + [(set (match_dup 2) (match_dup 3)) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel [(set (match_operand:SF 0 "register_operand") + (neg:SF (match_operand:SF 1 "register_operand"))) + (use (match_dup 2)) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { operands[2] = gen_reg_rtx (SImode); @@ -2386,7 +1553,8 @@ (define_insn "*expanded_negsf2" [(set (match_operand:SF 0 "register_operand" "=r") (neg:SF (match_operand:SF 1 "register_operand" "0"))) - (use (match_operand:SI 2 "register_operand" "r"))] + (use (match_operand:SI 2 "register_operand" "r")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "xor %2,%0" [(set_attr "slottable" "yes")]) @@ -2396,7 +1564,8 @@ (define_insn "neg<mode>2" [(set (match_operand:BWD 0 "register_operand" "=r") - (neg:BWD (match_operand:BWD 1 "register_operand" "r")))] + (neg:BWD (match_operand:BWD 1 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "neg<m> %1,%0" [(set_attr "slottable" "yes")]) @@ -2408,14 +1577,16 @@ (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "0")))] + (not:SI (match_operand:SI 1 "register_operand" "0"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "not %0" [(set_attr "slottable" "yes")]) (define_insn "one_cmpl<mode>2" [(set (match_operand:BW 0 "register_operand" "=r") - (not:BW (match_operand:BW 1 "register_operand" "0")))] + (not:BW (match_operand:BW 1 "register_operand" "0"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "not %0" [(set_attr "slottable" "yes") @@ -2426,7 +1597,8 @@ (define_insn "<shlr>si3" [(set (match_operand:SI 0 "register_operand" "=r") (shift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "Kcr")))] + (match_operand:SI 2 "nonmemory_operand" "Kcr"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" { if (REG_S_P (operands[2])) @@ -2447,13 +1619,21 @@ ;; FIXME: Can't parametrize sign_extend and zero_extend (before ;; mentioning "shiftrt"), so we need two patterns. (define_expand "ashr<mode>3" - [(set (match_dup 3) - (sign_extend:SI (match_operand:BW 1 "nonimmediate_operand" ""))) - (set (match_dup 4) - (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" ""))) - (set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4))) - (set (match_operand:BW 0 "general_operand" "") - (subreg:BW (match_dup 5) 0))] + [(parallel + [(set (match_dup 3) + (sign_extend:SI (match_operand:BW 1 "nonimmediate_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 4) + (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_operand:BW 0 "general_operand") + (subreg:BW (match_dup 5) 0)) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { int i; @@ -2463,13 +1643,21 @@ }) (define_expand "lshr<mode>3" - [(set (match_dup 3) - (zero_extend:SI (match_operand:BW 1 "nonimmediate_operand" ""))) - (set (match_dup 4) - (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" ""))) - (set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4))) - (set (match_operand:BW 0 "general_operand" "") - (subreg:BW (match_dup 5) 0))] + [(parallel + [(set (match_dup 3) + (zero_extend:SI (match_operand:BW 1 "nonimmediate_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 4) + (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_operand:BW 0 "general_operand") + (subreg:BW (match_dup 5) 0)) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { int i; @@ -2481,7 +1669,8 @@ (define_insn "*expanded_<shlr><mode>" [(set (match_operand:BW 0 "register_operand" "=r") (shiftrt:BW (match_operand:BW 1 "register_operand" "0") - (match_operand:BW 2 "register_operand" "r")))] + (match_operand:BW 2 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "<slr><m> %2,%0" [(set_attr "slottable" "yes")]) @@ -2489,7 +1678,8 @@ (define_insn "*<shlr><mode>_lowpart" [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r")) (shiftrt:BW (match_dup 0) - (match_operand:BW 1 "register_operand" "r")))] + (match_operand:BW 1 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "<slr><m> %1,%0" [(set_attr "slottable" "yes")]) @@ -2503,7 +1693,8 @@ (define_insn "ashl<mode>3" [(set (match_operand:BW 0 "register_operand" "=r,r") (ashift:BW (match_operand:BW 1 "register_operand" "0,0") - (match_operand:BW 2 "nonmemory_operand" "r,Kc")))] + (match_operand:BW 2 "nonmemory_operand" "r,Kc"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" { return @@ -2520,7 +1711,8 @@ (define_insn "*ashl<mode>_lowpart" [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r")) (ashift:BW (match_dup 0) - (match_operand:HI 1 "register_operand" "r")))] + (match_operand:HI 1 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "lsl<m> %1,%0" [(set_attr "slottable" "yes")]) @@ -2532,13 +1724,15 @@ (define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=r") - (abs:SF (match_operand:SF 1 "register_operand" "0")))] + (abs:SF (match_operand:SF 1 "register_operand" "0"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "lslq 1,%0\;lsrq 1,%0") (define_insn "abssi2" [(set (match_operand:SI 0 "register_operand" "=r") - (abs:SI (match_operand:SI 1 "register_operand" "r")))] + (abs:SI (match_operand:SI 1 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" "abs %1,%0" [(set_attr "slottable" "yes")]) @@ -2546,24 +1740,32 @@ ;; FIXME: GCC should be able to do these expansions itself. (define_expand "abs<mode>2" - [(set (match_dup 2) - (sign_extend:SI (match_operand:BW 1 "general_operand" ""))) - (set (match_dup 3) (abs:SI (match_dup 2))) - (set (match_operand:BW 0 "register_operand" "") - (subreg:BW (match_dup 3) 0))] + [(parallel + [(set (match_dup 2) + (sign_extend:SI (match_operand:BW 1 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 3) (abs:SI (match_dup 2))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_operand:BW 0 "register_operand") + (subreg:BW (match_dup 3) 0)) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);") (define_insn "clzsi2" [(set (match_operand:SI 0 "register_operand" "=r") - (clz:SI (match_operand:SI 1 "register_operand" "r")))] + (clz:SI (match_operand:SI 1 "register_operand" "r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_LZ" "lz %1,%0" [(set_attr "slottable" "yes")]) (define_insn "bswapsi2" [(set (match_operand:SI 0 "register_operand" "=r") - (bswap:SI (match_operand:SI 1 "register_operand" "0")))] + (bswap:SI (match_operand:SI 1 "register_operand" "0"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_SWAP" "swapwb %0" [(set_attr "slottable" "yes")]) @@ -2575,7 +1777,8 @@ (define_insn "cris_swap_bits" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "0")] - CRIS_UNSPEC_SWAP_BITS))] + CRIS_UNSPEC_SWAP_BITS)) + (clobber (reg:CC CRIS_CC0_REGNUM))] "TARGET_HAS_SWAP" "swapwbr %0" [(set_attr "slottable" "yes")]) @@ -2584,12 +1787,18 @@ ;; Defines a scratch register to avoid clobbering input. (define_expand "ctzsi2" - [(set (match_dup 2) - (match_operand:SI 1 "register_operand")) - (set (match_dup 2) - (unspec:SI [(match_dup 2)] CRIS_UNSPEC_SWAP_BITS)) - (set (match_operand:SI 0 "register_operand") - (clz:SI (match_dup 2)))] + [(parallel + [(set (match_dup 2) + (match_operand:SI 1 "register_operand")) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 2) + (unspec:SI [(match_dup 2)] CRIS_UNSPEC_SWAP_BITS)) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_operand:SI 0 "register_operand") + (clz:SI (match_dup 2))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "TARGET_HAS_LZ && TARGET_HAS_SWAP" "operands[2] = gen_reg_rtx (SImode);") @@ -2598,16 +1807,19 @@ ;; normal code too. (define_expand "uminsi3" - [(set (match_operand:SI 0 "register_operand" "") - (umin:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "general_operand" "")))] + [(parallel + [(set (match_operand:SI 0 "register_operand") + (umin:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "general_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "") (define_insn "*uminsi3" [(set (match_operand:SI 0 "register_operand" "=r,r, r,r") (umin:SI (match_operand:SI 1 "register_operand" "%0,0, 0,r") - (match_operand:SI 2 "general_operand" "r,Q>,g,!To")))] + (match_operand:SI 2 "general_operand" "r,Q>,g,!To"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" { if (CONST_INT_P (operands[2])) @@ -2691,28 +1903,36 @@ ;; Conditional branches. (define_expand "cbranch<mode>4" - [(set (cc0) (compare - (match_operand:BWD 1 "nonimmediate_operand") - (match_operand:BWD 2 "general_operand"))) - (set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] + [(parallel + [(set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_operand:BWDD 1 "nonimmediate_operand") + (match_operand:BWDD 2 "general_operand")]) + (label_ref (match_operand 3 "")) + (pc))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "cris_reduce_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cbranchdi4" - [(set (cc0) - (compare (match_operand:DI 1 "nonimmediate_operand" "") - (match_operand:DI 2 "general_operand" ""))) +(define_insn_and_split "*cbranch<mode>4" + [(set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_operand:BWDD 1 "nonimmediate_operand" "<cmp_op1c>") + (match_operand:BWDD 2 "general_operand" "<cmp_op2c>")]) + (label_ref (match_operand 3 "")) + (pc))) + (clobber (reg:CC CRIS_CC0_REGNUM))] + "" + "#" + "&& reload_completed" + [(set (reg:CC CRIS_CC0_REGNUM) (compare:CC (match_dup 1) (match_dup 2))) (set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) + (if_then_else (match_op_dup 0 [(reg:CC CRIS_CC0_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) (pc)))] - "" - "cris_reduce_compare (&operands[0], &operands[1], &operands[2]);") + "") ;; We suffer from the same overflow-bit-gets-in-the-way problem as @@ -2721,136 +1941,123 @@ (define_insn "b<ncond:code>" [(set (pc) - (if_then_else (ncond (cc0) + (if_then_else (ncond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] - "" + "reload_completed" "b<CC> %l0%#" [(set_attr "slottable" "has_slot")]) (define_insn "b<ocond:code>" [(set (pc) - (if_then_else (ocond (cc0) + (if_then_else (ocond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] - "" -{ - return - (cc_prev_status.flags & CC_NO_OVERFLOW) - ? 0 : "b<CC> %l0%#"; -} + "reload_completed" + ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW. + "b<CC> %l0%#" [(set_attr "slottable" "has_slot")]) (define_insn "b<rcond:code>" [(set (pc) - (if_then_else (rcond (cc0) + (if_then_else (rcond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] - "" -{ - return - (cc_prev_status.flags & CC_NO_OVERFLOW) - ? "b<oCC> %l0%#" : "b<CC> %l0%#"; -} + "reload_completed" + ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW. + "b<CC> %l0%#" [(set_attr "slottable" "has_slot")]) ;; Reversed anonymous patterns to the ones above, as mandated. (define_insn "*b<ncond:code>_reversed" [(set (pc) - (if_then_else (ncond (cc0) + (if_then_else (ncond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] - "" + "reload_completed" "b<rCC> %l0%#" [(set_attr "slottable" "has_slot")]) (define_insn "*b<ocond:code>_reversed" [(set (pc) - (if_then_else (ocond (cc0) + (if_then_else (ocond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] - "" -{ - return - (cc_prev_status.flags & CC_NO_OVERFLOW) - ? 0 : "b<rCC> %l0%#"; -} + "reload_completed" + ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW. + "b<rCC> %l0%#" [(set_attr "slottable" "has_slot")]) (define_insn "*b<rcond:code>_reversed" [(set (pc) - (if_then_else (rcond (cc0) + (if_then_else (rcond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] - "" -{ - return - (cc_prev_status.flags & CC_NO_OVERFLOW) - ? "b<roCC> %l0%#" : "b<rCC> %l0%#"; -} + "reload_completed" + ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW. + "b<rCC> %l0%#" [(set_attr "slottable" "has_slot")]) ;; Set on condition: sCC. -(define_expand "cstoredi4" - [(set (cc0) (compare - (match_operand:DI 2 "nonimmediate_operand") - (match_operand:DI 3 "general_operand"))) - (set (match_operand:SI 0 "register_operand") - (match_operator:SI 1 "ordered_comparison_operator" - [(cc0) (const_int 0)]))] +(define_expand "cstore<mode>4" + [(parallel + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:BWDD 2 "nonimmediate_operand") + (match_operand:BWDD 3 "general_operand")])) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" "cris_reduce_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "cstore<mode>4" - [(set (cc0) (compare - (match_operand:BWD 2 "nonimmediate_operand") - (match_operand:BWD 3 "general_operand"))) - (set (match_operand:SI 0 "register_operand") +(define_insn_and_split "*cstore<mode>4" + [(set (match_operand:SI 0 "register_operand" "=<sCC_destc>") (match_operator:SI 1 "ordered_comparison_operator" - [(cc0) (const_int 0)]))] + [(match_operand:BWDD 2 "nonimmediate_operand" "<cmp_op1c>") + (match_operand:BWDD 3 "general_operand" "<cmp_op2c>")])) + (clobber (reg:CC CRIS_CC0_REGNUM))] "" - "cris_reduce_compare (&operands[1], &operands[2], &operands[3]);") + "#" + "&& reload_completed" + [(set (reg:CC CRIS_CC0_REGNUM) (compare:CC (match_dup 2) (match_dup 3))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(reg:CC CRIS_CC0_REGNUM) (const_int 0)]))] + "") ;; Like bCC, we have to check the overflow bit for ;; signed conditions. -(define_insn "s<ncond:code>" +(define_insn "*s<ncond:code>" [(set (match_operand:SI 0 "register_operand" "=r") - (ncond:SI (cc0) (const_int 0)))] - "" + (ncond:SI (reg:CC CRIS_CC0_REGNUM) (const_int 0)))] + "reload_completed" "s<CC> %0" [(set_attr "slottable" "yes") (set_attr "cc" "none")]) -(define_insn "s<rcond:code>" +(define_insn "*s<rcond:code>" [(set (match_operand:SI 0 "register_operand" "=r") - (rcond:SI (cc0) (const_int 0)))] - "" -{ - return - (cc_prev_status.flags & CC_NO_OVERFLOW) - ? "s<oCC> %0" : "s<CC> %0"; -} + (rcond:SI (reg:CC CRIS_CC0_REGNUM) (const_int 0)))] + "reload_completed" + ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW. + "s<CC> %0" [(set_attr "slottable" "yes") (set_attr "cc" "none")]) -(define_insn "s<ocond:code>" +(define_insn "*s<ocond:code>" [(set (match_operand:SI 0 "register_operand" "=r") - (ocond:SI (cc0) (const_int 0)))] - "" -{ - return - (cc_prev_status.flags & CC_NO_OVERFLOW) - ? 0 : "s<CC> %0"; -} + (ocond:SI (reg:CC CRIS_CC0_REGNUM) (const_int 0)))] + "reload_completed" + ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW. + "s<CC> %0" [(set_attr "slottable" "yes") (set_attr "cc" "none")]) @@ -2945,13 +2152,19 @@ ;; accordingly, to add the default case at the end of the jump-table. (define_expand "casesi" - [(set (match_dup 5) (match_operand:SI 0 "general_operand" "")) - (set (match_dup 6) - (minus:SI (match_dup 5) - (match_operand:SI 1 "const_int_operand" "n"))) - (set (match_dup 7) - (umin:SI (match_dup 6) - (match_operand:SI 2 "const_int_operand" "n"))) + [(parallel + [(set (match_dup 5) (match_operand:SI 0 "general_operand")) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 6) + (minus:SI (match_dup 5) + (match_operand:SI 1 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 7) + (umin:SI (match_dup 6) + (match_operand:SI 2 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) (parallel [(set (pc) (if_then_else @@ -2961,8 +2174,9 @@ (plus:SI (mult:SI (match_dup 7) (const_int 2)) (pc)))) (pc)) - (label_ref (match_operand 4 "" "")))) - (use (label_ref (match_operand 3 "" "")))])] + (label_ref (match_operand 4 "")))) + (use (label_ref (match_operand 3 ""))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { operands[2] = plus_constant (SImode, operands[2], 1); @@ -2970,658 +2184,11 @@ operands[6] = gen_reg_rtx (SImode); operands[7] = gen_reg_rtx (SImode); }) - -;; Split-patterns. Some of them have modes unspecified. This -;; should always be ok; if for no other reason sparc.md has it as -;; well. -;; -;; When register_operand is specified for an operand, we can get a -;; subreg as well (Axis-990331), so don't just assume that REG_P is true -;; for a register_operand and that REGNO can be used as is. It is best to -;; guard with REG_P, unless it is worth it to adjust for the subreg case. - -;; op [rx + 0],ry,rz -;; The index to rx is optimized into zero, and gone. - -;; First, recognize bound [rx],ry,rz; where [rx] is zero-extended, -;; and add/sub [rx],ry,rz, with zero or sign-extend on [rx]. -;; Split this into: -;; move ry,rz -;; op [rx],rz -;; Lose if rz=ry or rx=rz. -;; Call this op-extend-split. - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 4 "cris_operand_extend_operator" - [(match_operand 1 "register_operand" "") - (match_operator - 3 "cris_extend_operator" - [(match_operand 2 "memory_operand" "")])]))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])" - [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 0) - (match_op_dup - 4 [(match_dup 0) - (match_op_dup 3 [(match_dup 2)])]))] - "") - -;; As op-extend-split, but recognize and split op [rz],ry,rz into -;; ext [rz],rz -;; op ry,rz -;; Do this for plus or bound only, being commutative operations, since we -;; have swapped the operands. -;; Call this op-extend-split-rx=rz - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 4 "cris_plus_or_bound_operator" - [(match_operand 1 "register_operand" "") - (match_operator - 3 "cris_extend_operator" - [(match_operand 2 "memory_operand" "")])]))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])" - [(set (match_dup 0) - (match_op_dup 3 [(match_dup 2)])) - (set (match_dup 0) - (match_op_dup - 4 [(match_dup 0) - (match_dup 1)]))] - "") - -;; As the op-extend-split, but swapped operands, and only for -;; plus or bound, being the commutative extend-operators. FIXME: Why is -;; this needed? Is it? -;; Call this op-extend-split-swapped - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 4 "cris_plus_or_bound_operator" - [(match_operator - 3 "cris_extend_operator" - [(match_operand 2 "memory_operand" "")]) - (match_operand 1 "register_operand" "")]))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])" - [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 0) - (match_op_dup - 4 [(match_dup 0) - (match_op_dup 3 [(match_dup 2)])]))] - "") - -;; As op-extend-split-rx=rz, but swapped operands, only for plus or -;; bound. Call this op-extend-split-swapped-rx=rz. - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 4 "cris_plus_or_bound_operator" - [(match_operator - 3 "cris_extend_operator" - [(match_operand 2 "memory_operand" "")]) - (match_operand 1 "register_operand" "")]))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])" - [(set (match_dup 0) - (match_op_dup 3 [(match_dup 2)])) - (set (match_dup 0) - (match_op_dup - 4 [(match_dup 0) - (match_dup 1)]))] - "") - -;; As op-extend-split, but the mem operand is not extended. -;; -;; op [rx],ry,rz changed into -;; move ry,rz -;; op [rx],rz -;; lose if ry=rz or rx=rz -;; Call this op-extend. - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 3 "cris_orthogonal_operator" - [(match_operand 1 "register_operand" "") - (match_operand 2 "memory_operand" "")]))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])" - [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 0) - (match_op_dup - 3 [(match_dup 0) - (match_dup 2)]))] - "") - -;; As op-extend-split-rx=rz, non-extended. -;; Call this op-split-rx=rz - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 3 "cris_commutative_orth_op" - [(match_operand 2 "memory_operand" "") - (match_operand 1 "register_operand" "")]))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) != REGNO (operands[0])" - [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 0) - (match_op_dup - 3 [(match_dup 0) - (match_dup 2)]))] - "") - -;; As op-extend-split-swapped, nonextended. -;; Call this op-split-swapped. - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 3 "cris_commutative_orth_op" - [(match_operand 1 "register_operand" "") - (match_operand 2 "memory_operand" "")]))] - "REG_P (operands[0]) && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])" - [(set (match_dup 0) - (match_dup 2)) - (set (match_dup 0) - (match_op_dup - 3 [(match_dup 0) - (match_dup 1)]))] - "") - -;; As op-extend-split-swapped-rx=rz, non-extended. -;; Call this op-split-swapped-rx=rz. - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 3 "cris_orthogonal_operator" - [(match_operand 2 "memory_operand" "") - (match_operand 1 "register_operand" "")]))] - "REG_P (operands[0]) && REG_P (operands[1]) - && REGNO (operands[1]) != REGNO (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && REG_P (XEXP (operands[2], 0)) - && REGNO (XEXP (operands[2], 0)) == REGNO (operands[0])" - [(set (match_dup 0) - (match_dup 2)) - (set (match_dup 0) - (match_op_dup - 3 [(match_dup 0) - (match_dup 1)]))] - "") (include "sync.md") -;; Splits for all cases in side-effect insns where (possibly after reload -;; and register allocation) rx and ry in [rx=ry+i] are equal. - -;; move.S1 [rx=rx+rz.S2],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 6 "cris_mem_op" - [(plus:SI - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")) - (match_operand:SI 3 "register_operand" ""))])) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 3)))])] - "REG_P (operands[3]) && REG_P (operands[4]) - && REGNO (operands[3]) == REGNO (operands[4])" - [(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2)) - (match_dup 3))) - (set (match_dup 0) (match_dup 5))] - "operands[5] = replace_equiv_address (operands[6], operands[3]);") - -;; move.S1 [rx=rx+i],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 5 "cris_mem_op" - [(plus:SI (match_operand:SI 1 "cris_bdap_operand" "") - (match_operand:SI 2 "cris_bdap_operand" ""))])) - (set (match_operand:SI 3 "register_operand" "") - (plus:SI (match_dup 1) - (match_dup 2)))])] - "(rtx_equal_p (operands[3], operands[1]) - || rtx_equal_p (operands[3], operands[2]))" - [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (match_dup 4))] -{ - operands[4] = replace_equiv_address (operands[5], operands[3]); - cris_order_for_addsi3 (operands, 1); -}) - -;; move.S1 ry,[rx=rx+rz.S2] - -(define_split - [(parallel - [(set (match_operator - 6 "cris_mem_op" - [(plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" "")) - (match_operand:SI 2 "register_operand" ""))]) - (match_operand 3 "register_operand" "")) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 2)))])] - "REG_P (operands[2]) && REG_P (operands[4]) - && REGNO (operands[4]) == REGNO (operands[2])" - [(set (match_dup 4) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) - (match_dup 2))) - (set (match_dup 5) (match_dup 3))] - "operands[5] = replace_equiv_address (operands[6], operands[4]);") - -;; move.S1 ry,[rx=rx+i] - -(define_split - [(parallel - [(set (match_operator - 6 "cris_mem_op" - [(plus:SI (match_operand:SI 0 "cris_bdap_operand" "") - (match_operand:SI 1 "cris_bdap_operand" ""))]) - (match_operand 2 "register_operand" "")) - (set (match_operand:SI 3 "register_operand" "") - (plus:SI (match_dup 0) - (match_dup 1)))])] - "(rtx_equal_p (operands[3], operands[0]) - || rtx_equal_p (operands[3], operands[1]))" - [(set (match_dup 3) (plus:SI (match_dup 0) (match_dup 1))) - (set (match_dup 5) (match_dup 2))] -{ - operands[5] = replace_equiv_address (operands[6], operands[3]); - cris_order_for_addsi3 (operands, 0); -}) - -;; clear.[bwd] [rx=rx+rz.S2] - -(define_split - [(parallel - [(set (mem:BWD (plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" "")) - (match_operand:SI 2 "register_operand" ""))) - (const_int 0)) - (set (match_operand:SI 3 "register_operand" "") - (plus:SI (mult:SI (match_dup 0) - (match_dup 1)) - (match_dup 2)))])] - "REG_P (operands[2]) && REG_P (operands[3]) - && REGNO (operands[3]) == REGNO (operands[2])" - [(set (match_dup 3) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) - (match_dup 2))) - (set (mem:BWD (match_dup 3)) (const_int 0))] - "") - -;; clear.[bwd] [rx=rx+i] - -(define_split - [(parallel - [(set (mem:BWD - (plus:SI (match_operand:SI 0 "cris_bdap_operand" "") - (match_operand:SI 1 "cris_bdap_operand" ""))) - (const_int 0)) - (set (match_operand:SI 2 "register_operand" "") - (plus:SI (match_dup 0) - (match_dup 1)))])] - "(rtx_equal_p (operands[0], operands[2]) - || rtx_equal_p (operands[2], operands[1]))" - [(set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1))) - (set (mem:BWD (match_dup 2)) (const_int 0))] - "cris_order_for_addsi3 (operands, 0);") - -;; mov(s|u).S1 [rx=rx+rz.S2],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 5 "cris_extend_operator" - [(mem (plus:SI - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")) - (match_operand:SI 3 "register_operand" "")))])) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 3)))])] - "REG_P (operands[3]) - && REG_P (operands[4]) - && REGNO (operands[3]) == REGNO (operands[4])" - [(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2)) - (match_dup 3))) - (set (match_dup 0) (match_op_dup 5 [(match_dup 6)]))] - "operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);") - -;; mov(s|u).S1 [rx=rx+i],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 4 "cris_extend_operator" - [(mem (plus:SI - (match_operand:SI 1 "cris_bdap_operand" "") - (match_operand:SI 2 "cris_bdap_operand" "")))])) - (set (match_operand:SI 3 "register_operand" "") - (plus:SI (match_dup 1) - (match_dup 2)))])] - "(rtx_equal_p (operands[1], operands[3]) - || rtx_equal_p (operands[2], operands[3]))" - [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (match_op_dup 4 [(match_dup 5)]))] -{ - operands[5] = replace_equiv_address (XEXP (operands[4], 0), operands[3]); - cris_order_for_addsi3 (operands, 1); -}) - -;; op.S1 [rx=rx+i],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 5 "cris_orthogonal_operator" - [(match_operand 1 "register_operand" "") - (mem (plus:SI - (match_operand:SI 2 "cris_bdap_operand" "") - (match_operand:SI 3 "cris_bdap_operand" "")))])) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (match_dup 2) - (match_dup 3)))])] - "(rtx_equal_p (operands[4], operands[2]) - || rtx_equal_p (operands[4], operands[3]))" - [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3))) - (set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 6)]))] -{ - operands[6] = replace_equiv_address (XEXP (operands[5], 1), operands[4]); - cris_order_for_addsi3 (operands, 2); -}) - -;; op.S1 [rx=rx+rz.S2],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 6 "cris_orthogonal_operator" - [(match_operand 1 "register_operand" "") - (mem (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")) - (match_operand:SI 4 "register_operand" "")))])) - (set (match_operand:SI 5 "register_operand" "") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))])] - "REG_P (operands[4]) - && REG_P (operands[5]) - && REGNO (operands[5]) == REGNO (operands[4])" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3)) - (match_dup 4))) - (set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 7)]))] - "operands[7] = replace_equiv_address (XEXP (operands[6], 1), operands[5]);") - -;; op.S1 [rx=rx+rz.S2],ry (swapped) - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 6 "cris_commutative_orth_op" - [(mem (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")) - (match_operand:SI 4 "register_operand" ""))) - (match_operand 1 "register_operand" "")])) - (set (match_operand:SI 5 "register_operand" "") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))])] - "REG_P (operands[4]) - && REG_P (operands[5]) - && REGNO (operands[5]) == REGNO (operands[4])" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3)) - (match_dup 4))) - (set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))] - "operands[7] = replace_equiv_address (XEXP (operands[6], 0), operands[5]);") - -;; op.S1 [rx=rx+i],ry (swapped) - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 5 "cris_commutative_orth_op" - [(mem - (plus:SI (match_operand:SI 2 "cris_bdap_operand" "") - (match_operand:SI 3 "cris_bdap_operand" ""))) - (match_operand 1 "register_operand" "")])) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (match_dup 2) - (match_dup 3)))])] - "(rtx_equal_p (operands[4], operands[2]) - || rtx_equal_p (operands[4], operands[3]))" - [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3))) - (set (match_dup 0) (match_op_dup 5 [(match_dup 6) (match_dup 1)]))] -{ - operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]); - cris_order_for_addsi3 (operands, 2); -}) - -;; op(s|u).S1 [rx=rx+rz.S2],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 6 "cris_operand_extend_operator" - [(match_operand 1 "register_operand" "") - (match_operator - 7 "cris_extend_operator" - [(mem (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")) - (match_operand:SI 4 "register_operand" "")))])])) - (set (match_operand:SI 5 "register_operand" "") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))])] - "REG_P (operands[4]) - && REG_P (operands[5]) - && REGNO (operands[5]) == REGNO (operands[4])" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3)) - (match_dup 4))) - (set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 8)]))] - "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[7]), GET_MODE (operands[7]), - replace_equiv_address (XEXP (operands[7], 0), - operands[5]));") - -;; op(s|u).S1 [rx=rx+i],ry - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 5 "cris_operand_extend_operator" - [(match_operand 1 "register_operand" "") - (match_operator - 6 "cris_extend_operator" - [(mem - (plus:SI (match_operand:SI 2 "cris_bdap_operand" "") - (match_operand:SI 3 "cris_bdap_operand" "") - ))])])) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (match_dup 2) - (match_dup 3)))])] - "(rtx_equal_p (operands[4], operands[2]) - || rtx_equal_p (operands[4], operands[3]))" - [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3))) - (set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 7)]))] -{ - operands[7] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]), - replace_equiv_address (XEXP (operands[6], 0), - operands[4])); - cris_order_for_addsi3 (operands, 2); -}) - -;; op(s|u).S1 [rx=rx+rz.S2],ry (swapped, plus or bound) - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 7 "cris_plus_or_bound_operator" - [(match_operator - 6 "cris_extend_operator" - [(mem (plus:SI - (mult:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")) - (match_operand:SI 4 "register_operand" "")))]) - (match_operand 1 "register_operand" "")])) - (set (match_operand:SI 5 "register_operand" "") - (plus:SI (mult:SI (match_dup 2) - (match_dup 3)) - (match_dup 4)))])] - "REG_P (operands[4]) && REG_P (operands[5]) - && REGNO (operands[5]) == REGNO (operands[4])" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3)) - (match_dup 4))) - (set (match_dup 0) (match_op_dup 6 [(match_dup 8) (match_dup 1)]))] - "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]), - replace_equiv_address (XEXP (operands[6], 0), - operands[5]));") - -;; op(s|u).S1 [rx=rx+i],ry (swapped, plus or bound) - -(define_split - [(parallel - [(set (match_operand 0 "register_operand" "") - (match_operator - 6 "cris_plus_or_bound_operator" - [(match_operator - 5 "cris_extend_operator" - [(mem (plus:SI - (match_operand:SI 2 "cris_bdap_operand" "") - (match_operand:SI 3 "cris_bdap_operand" "")))]) - (match_operand 1 "register_operand" "")])) - (set (match_operand:SI 4 "register_operand" "") - (plus:SI (match_dup 2) - (match_dup 3)))])] - "(rtx_equal_p (operands[4], operands[2]) - || rtx_equal_p (operands[4], operands[3]))" - [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3))) - (set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))] -{ - operands[7] = gen_rtx_fmt_e (GET_CODE (operands[5]), GET_MODE (operands[5]), - replace_equiv_address (XEXP (operands[5], 0), - operands[4])); - cris_order_for_addsi3 (operands, 2); -}) - -;; Splits for addressing prefixes that have no side-effects, so we can -;; fill a delay slot. Never split if we lose something, though. - -;; If we have a -;; move [indirect_ref],rx -;; where indirect ref = {const, [r+], [r]}, it costs as much as -;; move indirect_ref,rx -;; move [rx],rx -;; Take care not to allow indirect_ref = register. - -;; We're not allowed to generate copies of registers with different mode -;; until after reload; copying pseudos upsets reload. CVS as of -;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in -;; cselib_invalidate_regno. Also, don't do this for the stack-pointer, -;; as we don't want it set temporarily to an invalid value. - -(define_split ; indir_to_reg_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operand 1 "indirect_operand" ""))] - "reload_completed - && REG_P (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && (MEM_P (XEXP (operands[1], 0)) || CONSTANT_P (XEXP (operands[1], 0))) - && REGNO (operands[0]) < CRIS_LAST_GENERAL_REGISTER" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 0) (match_dup 3))] - "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0])); - operands[3] = replace_equiv_address (operands[1], operands[2]); - operands[4] = XEXP (operands[1], 0);") - -;; As the above, but MOVS and MOVU. - -(define_split - [(set (match_operand 0 "cris_nonsp_register_operand" "") - (match_operator - 4 "cris_extend_operator" - [(match_operand 1 "indirect_operand" "")]))] - "reload_completed - && REG_P (operands[0]) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD - && (MEM_P (XEXP (operands[1], 0)) - || CONSTANT_P (XEXP (operands[1], 0)))" - [(set (match_dup 2) (match_dup 5)) - (set (match_dup 0) (match_op_dup 4 [(match_dup 3)]))] - "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0])); - operands[3] = replace_equiv_address (XEXP (operands[4], 0), operands[2]); - operands[5] = XEXP (operands[1], 0);") - ;; Various peephole optimizations. ;; -;; Watch out: when you exchange one set of instructions for another, the -;; condition codes setting must be the same, or you have to CC_INIT or -;; whatever is appropriate, in the pattern before you emit the -;; assembly text. This is best done here, not in cris_notice_update_cc, -;; to keep changes local to their cause. -;; ;; Do not add patterns that you do not know will be matched. ;; Please also add a self-contained testcase. @@ -3630,13 +2197,17 @@ ;; suboptimal when not having extzv insns. ;; Testcase for the following four peepholes: gcc.dg/cris-peep2-xsrand.c -(define_peephole2 ; asrandb (peephole casesi+31) - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))) - (set (match_dup 0) +(define_peephole2 ; asrandb + [(parallel + [(set (match_operand:SI 0 "register_operand") + (ashiftrt:SI (match_dup 0) + (match_operand:SI 1 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 0) (and:SI (match_dup 0) - (match_operand 2 "const_int_operand" "")))] + (match_operand 2 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 255 && INTVAL (operands[1]) > 23 @@ -3644,20 +2215,27 @@ && (INTVAL (operands[2]) & ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U << (32 - INTVAL (operands[1]))))) == 0" - [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) - (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))] - ;; FIXME: CC0 is valid except for the M bit. + [(parallel + [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 3) (and:QI (match_dup 3) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] { operands[3] = gen_rtx_REG (QImode, REGNO (operands[0])); operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode)); }) -(define_peephole2 ; asrandw (peephole casesi+32) - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))) - (set (match_dup 0) - (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))] +(define_peephole2 ; asrandw + [(parallel + [(set (match_operand:SI 0 "register_operand") + (ashiftrt:SI (match_dup 0) + (match_operand:SI 1 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 0) + (and:SI (match_dup 0) (match_operand 2 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535 && INTVAL (operands[2]) != 255 @@ -3666,311 +2244,64 @@ && (INTVAL (operands[2]) & ((HOST_WIDE_INT) (HOST_WIDE_INT_M1U << (32 - INTVAL (operands[1]))))) == 0" - [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) - (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))] - ;; FIXME: CC0 is valid except for the M bit. + [(parallel + [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 3) (and:HI (match_dup 3) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode)); }) -(define_peephole2 ; lsrandb (peephole casesi+33) - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))) - (set (match_dup 0) - (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))] +(define_peephole2 ; lsrandb + [(parallel + [(set (match_operand:SI 0 "register_operand") + (lshiftrt:SI (match_dup 0) + (match_operand:SI 1 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 0) + (and:SI (match_dup 0) (match_operand 2 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 255 && INTVAL (operands[1]) > 23" - [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) - (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))] - ;; FIXME: CC0 is valid except for the M bit. + [(parallel + [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 3) (and:QI (match_dup 3) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] { operands[3] = gen_rtx_REG (QImode, REGNO (operands[0])); operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode)); }) -(define_peephole2 ; lsrandw (peephole casesi+34) - [(set (match_operand:SI 0 "register_operand" "") +(define_peephole2 ; lsrandw + [(parallel + [(set (match_operand:SI 0 "register_operand") (lshiftrt:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))) - (set (match_dup 0) - (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))] + (match_operand:SI 1 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 0) + (and:SI (match_dup 0) (match_operand 2 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] "INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535 && INTVAL (operands[2]) != 255 && INTVAL (operands[1]) > 15" - [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) - (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))] - ;; FIXME: CC0 is valid except for the M bit. + [(parallel + [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 3) (and:HI (match_dup 3) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode)); }) - - -;; Change -;; add.d n,rx -;; move [rx],ry -;; into -;; move [rx=rx+n],ry -;; when -128 <= n <= 127. -;; This will reduce the size of the assembler code for n = [-128..127], -;; and speed up accordingly. Don't match if the previous insn is -;; (set rx rz) because that combination is matched by another peephole. -;; No stable test-case. - -(define_peephole2 ; moversideqi (peephole casesi+35) - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" ""))) - (set (match_operand 3 "register_operand" "") - (match_operator 4 "cris_mem_op" [(match_dup 0)]))] - "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD - && REGNO (operands[3]) != REGNO (operands[0]) - && (cris_base_p (operands[1], true) || cris_base_p (operands[2], true)) - && !satisfies_constraint_J (operands[2]) - && !satisfies_constraint_N (operands[2]) - && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128) - && TARGET_SIDE_EFFECT_PREFIXES" - [(parallel - [(set (match_dup 3) (match_dup 5)) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])] - ;; Checking the previous insn is a bit too awkward for the condition. -{ - rtx_insn *prev = prev_nonnote_insn (curr_insn); - if (prev != NULL_RTX) - { - rtx set = single_set (prev); - if (set != NULL_RTX - && REG_S_P (SET_DEST (set)) - && REGNO (SET_DEST (set)) == REGNO (operands[0]) - && REG_S_P (SET_SRC (set))) - FAIL; - } - operands[5] - = replace_equiv_address (operands[4], - gen_rtx_PLUS (SImode, - operands[1], operands[2])); -}) - -;; Vice versa: move ry,[rx=rx+n] - -(define_peephole2 ; movemsideqi (peephole casesi+36) - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" ""))) - (set (match_operator 3 "cris_mem_op" [(match_dup 0)]) - (match_operand 4 "register_operand" ""))] - "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD - && REGNO (operands[4]) != REGNO (operands[0]) - && (cris_base_p (operands[1], true) || cris_base_p (operands[2], true)) - && !satisfies_constraint_J (operands[2]) - && !satisfies_constraint_N (operands[2]) - && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128) - && TARGET_SIDE_EFFECT_PREFIXES" - [(parallel - [(set (match_dup 5) (match_dup 4)) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])] - "operands[5] - = replace_equiv_address (operands[3], - gen_rtx_PLUS (SImode, - operands[1], operands[2]));") - -;; As above, change: -;; add.d n,rx -;; op.d [rx],ry -;; into: -;; op.d [rx=rx+n],ry -;; Saves when n = [-128..127]. -;; -;; Splitting and joining combinations for side-effect modes are slightly -;; out of hand. They probably will not save the time they take typing in, -;; not to mention the bugs that creep in. FIXME: Get rid of as many of -;; the splits and peepholes as possible. -;; No stable test-case. - -(define_peephole2 ; mover2side (peephole casesi+37) - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" ""))) - (set (match_operand 3 "register_operand" "") - (match_operator 4 "cris_orthogonal_operator" - [(match_dup 3) - (match_operator - 5 "cris_mem_op" [(match_dup 0)])]))] - ;; FIXME: What about DFmode? - ;; Change to GET_MODE_SIZE (GET_MODE (operands[3])) <= UNITS_PER_WORD? - "GET_MODE (operands[3]) != DImode - && REGNO (operands[0]) != REGNO (operands[3]) - && !satisfies_constraint_J (operands[2]) - && !satisfies_constraint_N (operands[2]) - && INTVAL (operands[2]) >= -128 - && INTVAL (operands[2]) <= 127 - && TARGET_SIDE_EFFECT_PREFIXES" - [(parallel - [(set (match_dup 3) (match_op_dup 4 [(match_dup 3) (match_dup 6)])) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])] - "operands[6] - = replace_equiv_address (operands[5], - gen_rtx_PLUS (SImode, - operands[1], operands[2]));") - -;; Sometimes, for some reason the pattern -;; move x,rx -;; add y,rx -;; move [rx],rz -;; will occur. Solve this, and likewise for to-memory. -;; No stable test-case. - -(define_peephole2 ; moverside (peephole casesi+38) - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "cris_bdap_biap_operand" "")) - (set (match_dup 0) - (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "") - (match_operand:SI 3 "cris_bdap_biap_operand" ""))) - (set (match_operand 4 "register_operand" "") - (match_operator 5 "cris_mem_op" [(match_dup 0)]))] - "(rtx_equal_p (operands[2], operands[0]) - || rtx_equal_p (operands[3], operands[0])) - && cris_side_effect_mode_ok (PLUS, operands, 0, - (REG_S_P (operands[1]) - ? 1 - : (rtx_equal_p (operands[2], operands[0]) - ? 3 : 2)), - (! REG_S_P (operands[1]) - ? 1 - : (rtx_equal_p (operands[2], operands[0]) - ? 3 : 2)), - -1, 4)" - [(parallel - [(set (match_dup 4) (match_dup 6)) - (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])] -{ - rtx otherop - = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2]; - - /* Make sure we have canonical RTX so we match the insn pattern - - not a constant in the first operand. We also require the order - (plus reg mem) to match the final pattern. */ - if (CONSTANT_P (otherop) || MEM_P (otherop)) - { - operands[7] = operands[1]; - operands[8] = otherop; - } - else - { - operands[7] = otherop; - operands[8] = operands[1]; - } - operands[6] - = replace_equiv_address (operands[5], - gen_rtx_PLUS (SImode, - operands[7], operands[8])); -}) - -;; As above but to memory. -;; FIXME: Split movemside and moverside into variants and prune -;; the ones that don't trig. -;; No stable test-case. - -(define_peephole2 ; movemside (peephole casesi+39) - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "cris_bdap_biap_operand" "")) - (set (match_dup 0) - (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "") - (match_operand:SI 3 "cris_bdap_biap_operand" ""))) - (set (match_operator 4 "cris_mem_op" [(match_dup 0)]) - (match_operand 5 "register_operand" ""))] - "(rtx_equal_p (operands[2], operands[0]) - || rtx_equal_p (operands[3], operands[0])) - && cris_side_effect_mode_ok (PLUS, operands, 0, - (REG_S_P (operands[1]) - ? 1 - : (rtx_equal_p (operands[2], operands[0]) - ? 3 : 2)), - (! REG_S_P (operands[1]) - ? 1 - : (rtx_equal_p (operands[2], operands[0]) - ? 3 : 2)), - -1, 5)" - [(parallel - [(set (match_dup 6) (match_dup 5)) - (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])] -{ - rtx otherop - = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2]; - - /* Make sure we have canonical RTX so we match the insn pattern - - not a constant in the first operand. We also require the order - (plus reg mem) to match the final pattern. */ - if (CONSTANT_P (otherop) || MEM_P (otherop)) - { - operands[7] = operands[1]; - operands[8] = otherop; - } - else - { - operands[7] = otherop; - operands[8] = operands[1]; - } - operands[6] - = replace_equiv_address (operands[4], - gen_rtx_PLUS (SImode, - operands[7], operands[8])); -}) - -;; Another spotted bad code: -;; move rx,ry -;; move [ry],ry -;; No stable test-case. - -(define_peephole2 ; movei (peephole casesi+42) - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "register_operand" "")) - (set (match_operand 2 "register_operand" "") - (match_operator 3 "cris_mem_op" [(match_dup 0)]))] - "REGNO (operands[0]) == REGNO (operands[2]) - && (REGNO_REG_CLASS (REGNO (operands[0])) - == REGNO_REG_CLASS (REGNO (operands[1]))) - && GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD" - [(set (match_dup 2) (match_dup 4))] - "operands[4] = replace_equiv_address (operands[3], operands[1]);") - -;; move.d [r10+16],r9 -;; and.d r12,r9 -;; change to -;; and.d [r10+16],r12,r9 -;; With generalization of the operation, the size and the addressing mode. -;; This seems to be the result of a quirk in register allocation -;; missing the three-operand cases when having different predicates. -;; Maybe that it matters that it is a commutative operation. -;; This pattern helps that situation, but there's still the increased -;; register pressure. -;; Note that adding the noncommutative variant did not show any matches -;; in ipps and cc1, so it's not here. -;; No stable test-case. - -(define_peephole2 ; op3 (peephole casesi+44) - [(set (match_operand 0 "register_operand" "") - (match_operator - 6 "cris_mem_op" - [(plus:SI - (match_operand:SI 1 "cris_bdap_biap_operand" "") - (match_operand:SI 2 "cris_bdap_biap_operand" ""))])) - (set (match_dup 0) - (match_operator - 5 "cris_commutative_orth_op" - [(match_operand 3 "register_operand" "") - (match_operand 4 "register_operand" "")]))] - "(rtx_equal_p (operands[3], operands[0]) - || rtx_equal_p (operands[4], operands[0])) - && ! rtx_equal_p (operands[3], operands[4]) - && (REG_S_P (operands[1]) || REG_S_P (operands[2])) - && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD" - [(set (match_dup 0) (match_op_dup 5 [(match_dup 7) (match_dup 6)]))] - "operands[7] - = rtx_equal_p (operands[3], operands[0]) ? operands[4] : operands[3];") ;; There seems to be no other way to make GCC (including 4.8/trunk at ;; r186932) optimally reload an instruction that looks like @@ -3985,12 +2316,16 @@ ;; Fix it with these two peephole2's. ;; Testcases: gcc.dg/cris-peep2-andu1.c gcc.dg/cris-peep2-andu2.c -(define_peephole2 ; andu (casesi+45) - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonimmediate_operand" "")) - (set (match_operand:SI 2 "register_operand" "") - (and:SI (match_dup 0) - (match_operand:SI 3 "const_int_operand" "")))] +(define_peephole2 ; andu + [(parallel + [(set (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "nonimmediate_operand")) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_operand:SI 2 "register_operand") + (and:SI (match_dup 0) + (match_operand:SI 3 "const_int_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] ;; Since the size of the memory access could be made different here, ;; don't do this for a mem-volatile access. "REGNO (operands[2]) == REGNO (operands[0]) @@ -3999,9 +2334,12 @@ && !side_effects_p (operands[1]) && (!REG_P (operands[1]) || REGNO (operands[1]) <= CRIS_LAST_GENERAL_REGISTER)" - ;; FIXME: CC0 valid except for M (i.e. CC_NOT_NEGATIVE). - [(set (match_dup 0) (match_dup 4)) - (set (match_dup 5) (match_dup 6))] + [(parallel + [(set (match_dup 0) (match_dup 4)) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 5) (match_dup 6)) + (clobber (reg:CC CRIS_CC0_REGNUM))])] { machine_mode zmode = INTVAL (operands[3]) <= 255 ? QImode : HImode; machine_mode amode @@ -4028,18 +2366,26 @@ ;; movu.b $r10,$r9 ;; andq -2,$r9. ;; Only do this for values fitting the quick immediate operand. -(define_peephole2 ; andqu (casesi+46) - [(set (match_operand:SI 0 "register_operand") - (match_operand:SI 1 "const_int_operand")) - (set (match_dup 0) - (and:SI (match_dup 0) (match_operand:SI 2 "nonimmediate_operand")))] +(define_peephole2 ; andqu + [(parallel + [(set (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "const_int_operand")) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 0) + (and:SI (match_dup 0) (match_operand:SI 2 "nonimmediate_operand"))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] ;; Since the size of the memory access will be made different here, ;; don't do this for a volatile access or a post-incremented address. "satisfies_constraint_O (operands[1]) && !side_effects_p (operands[2]) && !reg_overlap_mentioned_p (operands[0], operands[2])" - [(set (match_dup 0) (match_dup 3)) - (set (match_dup 0) (and:SI (match_dup 0) (match_dup 4)))] + [(parallel + [(set (match_dup 0) (match_dup 3)) + (clobber (reg:CC CRIS_CC0_REGNUM))]) + (parallel + [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) + (clobber (reg:CC CRIS_CC0_REGNUM))])] { machine_mode zmode = INTVAL (operands[1]) <= 255 ? QImode : HImode; rtx op1 diff --git a/gcc/config/cris/predicates.md b/gcc/config/cris/predicates.md index 1fa22cda466..2b55c05931b 100644 --- a/gcc/config/cris/predicates.md +++ b/gcc/config/cris/predicates.md @@ -51,7 +51,7 @@ (define_predicate "cris_load_multiple_op" (and (match_code "parallel") - (match_test "cris_movem_load_rest_p (op, 0)"))) + (match_test "cris_movem_load_rest_p (op)"))) (define_predicate "cris_store_multiple_op" (and (match_code "parallel") diff --git a/gcc/config/cris/sync.md b/gcc/config/cris/sync.md index d5bb11ddbcf..30b5ea075af 100644 --- a/gcc/config/cris/sync.md +++ b/gcc/config/cris/sync.md @@ -123,7 +123,8 @@ (match_operand:BWD 2 "<atomic_op_op_pred>" "<atomic_op_op_cnstr>"))) (set (match_operand:BWD 0 "register_operand" "=&r") (match_dup 1)) - (clobber (match_scratch:SI 3 "=&r"))] + (clobber (match_scratch:SI 3 "=&r")) + (clobber (reg:CC CRIS_CC0_REGNUM))] "<MODE>mode == QImode || !TARGET_ATOMICS_MAY_CALL_LIBFUNCS" { /* Can't be too sure; better ICE if this happens. */ @@ -226,7 +227,8 @@ [(match_dup 2) (match_dup 3) (match_operand:BWD 4 "register_operand" "r")] - CRIS_UNSPEC_ATOMIC_SWAP_MEM))] + CRIS_UNSPEC_ATOMIC_SWAP_MEM)) + (clobber (reg:CC CRIS_CC0_REGNUM))] "<MODE>mode == QImode || !TARGET_ATOMICS_MAY_CALL_LIBFUNCS" { if (cris_cpu_version == 10) |