aboutsummaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@redhat.com>2002-06-11 05:22:48 -0700
committerDavid S. Miller <davem@gcc.gnu.org>2002-06-11 05:22:48 -0700
commit2f937369fa50dfd2f5af11b18d30c5489451072c (patch)
tree5f5a5da6b9ff25b136d9c1acd1a495af48658efb /gcc/emit-rtl.c
parent43cf10b56ceb4bb309c6aac698845eebf734d351 (diff)
downloadgcc-2f937369fa50dfd2f5af11b18d30c5489451072c.zip
gcc-2f937369fa50dfd2f5af11b18d30c5489451072c.tar.gz
gcc-2f937369fa50dfd2f5af11b18d30c5489451072c.tar.bz2
Delete SEQUENCE rtl usage outside of reorg and ssa passes.
2002-06-05 David S. Miller <davem@redhat.com> Delete SEQUENCE rtl usage outside of reorg and ssa passes. * rtl.h (gen_sequence, emit_insns, emit_insns_before, emit_insns_before_scope, emit_insns_after, emit_insns_after_scope): Delete declaration. * ada/misc.c (insert_code_for): Use emit_insn* instead of emit_insns_foo. * config/alpha/alpha.c (alpha_set_memflags_1): Abort on SEQUENCE. (alpha_set_memflags): Fix comment. (set_frame_related_p): Use get_insns instead of gen_sequence. * config/alpha/alpha.md (setjmp receiver splitter): Avoid emitting no insns. * config/arm/arm.c (arm_finalize_pic): Use get_insns instead of gen_sequence. (arm_gen_load_multiple, arm_gen_store_multiple): Likewise. * config/fr30/fr30.c (fr30_move_double): Likewise. * config/i386/i386.c (ix86_expand_int_movcc, ix86_expand_movstr): Likewise. * config/ia64/ia64.c (spill_restore_mem): Likewise. * config/ia64/ia64.md (conditional move spliiter): Avoid emitting no insns. * config/m32r/m32r.c (gen_split_move_double): Use get_insns instead of gen_sequence. * config/mips/mips.c (embedded_pic_fnaddr_reg): Likewise. (mips_expand_prologue, mips16_gp_pseudo_reg): Likewise. * config/sh/sh.c (sh_need_epilogue): Likewise. * config/sparc/sparc.md (current_function_calls_alloca, flat): New attributes. (setjmp pattern and split): Use them to avoid splitter which emits no RTL. * genattrtab.c (main): Emit include of function.h * config/stormy16/stormy16.c (xstormy16_split_cbranch): Use get_insns instead of gen_sequence. * config/cris/cris.c (cris_split_movdx): Likewise. * emit-rtl.c (emit_insns*): Kill. (try_split): Expect insn list instead of SEQUENCE. (make_jump_insn_raw, make_call_insn_raw): Fix comments. (emit_*insn*): Reimplement to work with INSN lists and PATTERNs. Make them abort if a SEQUENCE is given and RTL checking is enabled. (emit_*_scope): Don't forget to set scope on final insn. (gen_sequence): Move from here... * ssa.c (gen_sequence): To here as private function. * builtins.c (expand_builtin_apply_args): Use emit_insn_foo, fix comments. (expand_builtin_return, expand_builtin_mathfn): Likewise. (expand_builtin_strlen): Use get_insns instead of gen_sequence. (expand_builtin_saveregs): Use emit_insn_foo, fix comments. (expand_builtin_expect_jump): Use get_insns and fix comments. * calls.c (try_to_integrate): Use emit_insn_foo. (expand_call, emit_library_call_value_1): Likewise. * expr.c (emit_queue): Handle insn lists instead of SEQUENCE. (emit_move_insn_1): Use get_insns instead of gen_sequence. (expand_expr): Use emit_insn_foo. * cfgrtl.c (commit_one_edge_insertion): Use emit_insn_foo. * except.c (build_post_landing_pads): Likewise. * flow.c (attempt_auto_inc): Likewise. * stmt.c (expand_fixup, fixup_gotos, expand_nl_handler_label, expand_nl_goto_receivers, expand_decl_cleanup): Likewise. * function.c (fixup_var_refs_insn): Use get_insns instead of gen_sequence. (fixup_var_refs_1): Likewise and expect insn list from gen_foo. (fixup_memory_subreg): Use get_insns instead of gen_sequence. (fixup_stack_1, purge_addressof_1, expand_main_function, get_arg_pointer_save_area): Likewise. (optimize_bit_field, instantiate_virtual_regs_1, assign_parms, expand_function_end): Use emit_insn_foo. (record_insns, keep_stack_depressed): Work with insn list instead of SEQUENCE, fix comments. * ifcvt.c (noce_emit_store_flag, noce_try_store_flag, noce_try_store_flag_constants, noce_try_store_flag_inc, noce_try_store_flag_mask, noce_emit_cmove, noce_try_cmove_arith, noce_try_minmax, noce_try_abs): Use emit_insn_foo. (noce_process_if_block): Use get_insns instead of gen_sequence. * optabs.c (add_equal_note): Work with insn list, fix comments. (expand_binop): Expect insn list from GEN_FCN(), use emit_insn_foo. (expand_unop, expand_complex_abs, expand_unop_insn, expand_no_conflict_block): Likewise. (gen_move_insn): Use get_insns instead of gen_sequence. (gen_cond_trap): Likewise. * integrate.c (copy_rtx_and_substitute): Likewise. (emit_initial_value_sets): Use emit_insn_foo. * reload1.c (emit_output_reload_insns, emit_reload_insns): Likewise. (fixup_abnormal_edges): Avoid losing REG_NOTES more intelligently now that RTL generators give insn lists. * sibcall.c (replace_call_placeholder): Use emit_insn_foo. * doloop.c (doloop_modify, doloop_modify_runtime): Use get_insns instead of gen_sequence. (doloop_optimize): Work with insn lists instead of SEQUENCE rtl. * explow.c (emit_stack_save, emit_stack_restore): Use get_insns instead of gen_sequence. * loop.c (move_movables, emit_prefetch_instructions, gen_add_mult, check_dbra_loop, gen_load_of_final_value): Likewise. (loop_regs_update): Work with insn list instead of SEQUENCE rtl. (product_cheap_p): Likewise, and add commentary about RTL wastage here. * lcm.c (optimize_mode_switching): Use get_insns instead of gen_sequence. * profile.c (gen_edge_profiler): Likewise. * regmove.c (copy_src_to_dest): Likewise. * reg-stack.c (compensate_edge): Likewise and fix comment. * gcse.c (process_insert_insn): Likewise. (insert_insn_end_bb): Work with insn list instead of SEQUENCE rtl. * jump.c (delete_prior_computation): Update comment. * genemit.c (gen_expand, gen_split, main): Use get_insns instead of gen_sequence, update comments to match. * recog.c (peephole2_optimize): Work with insn lists instead of SEQUENCE rtl. * sched-vis.c (print_pattern): Abort on SEQUENCE. * unroll.c (unroll_loop, find_splittable_givs, final_giv_value): Use get_insns instead of gen_sequence. (copy_loop_body): Likewise and don't emit dummy NOTE. * genrecog.c: Don't mention SEQUENCE rtl in comments. * combine.c (try_combine): Expect insn lists from split generator. * reorg.c (relax_delay_slots): Emit SEQUENCE into insn list by hand. From-SVN: r54497
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c807
1 files changed, 480 insertions, 327 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 7df9f23..a78a574 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -3101,52 +3101,72 @@ try_split (pat, trial, last)
if (seq)
{
- /* SEQ can either be a SEQUENCE or the pattern of a single insn.
- The latter case will normally arise only when being done so that
- it, in turn, will be split (SFmode on the 29k is an example). */
- if (GET_CODE (seq) == SEQUENCE)
+ /* SEQ can only be a list of insns. */
+ if (! INSN_P (seq))
+ abort ();
+
+ /* Sometimes there will be only one insn in that list, this case will
+ normally arise only when we want it in turn to be split (SFmode on
+ the 29k is an example). */
+ if (NEXT_INSN (seq) != NULL_RTX)
{
- int i, njumps = 0;
+ rtx insn_last, insn;
+ int njumps = 0;
/* Avoid infinite loop if any insn of the result matches
the original pattern. */
- for (i = 0; i < XVECLEN (seq, 0); i++)
- if (GET_CODE (XVECEXP (seq, 0, i)) == INSN
- && rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat))
- return trial;
+ insn_last = seq;
+ while (1)
+ {
+ if (rtx_equal_p (PATTERN (insn_last), pat))
+ return trial;
+ if (NEXT_INSN (insn_last) == NULL_RTX)
+ break;
+ insn_last = NEXT_INSN (insn_last);
+ }
/* Mark labels. */
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
- {
- rtx insn = XVECEXP (seq, 0, i);
- mark_jump_label (PATTERN (insn),
- XVECEXP (seq, 0, i), 0);
- njumps++;
- if (probability != -1
- && any_condjump_p (insn)
- && !find_reg_note (insn, REG_BR_PROB, 0))
- {
- /* We can preserve the REG_BR_PROB notes only if exactly
- one jump is created, otherwise the machine description
- is responsible for this step using
- split_branch_probability variable. */
- if (njumps != 1)
- abort ();
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_BR_PROB,
- GEN_INT (probability),
- REG_NOTES (insn));
- }
- }
+ insn = insn_last;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ mark_jump_label (PATTERN (insn), insn, 0);
+ njumps++;
+ if (probability != -1
+ && any_condjump_p (insn)
+ && !find_reg_note (insn, REG_BR_PROB, 0))
+ {
+ /* We can preserve the REG_BR_PROB notes only if exactly
+ one jump is created, otherwise the machine description
+ is responsible for this step using
+ split_branch_probability variable. */
+ if (njumps != 1)
+ abort ();
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (probability),
+ REG_NOTES (insn));
+ }
+ }
+
+ insn = PREV_INSN (insn);
+ }
/* If we are splitting a CALL_INSN, look for the CALL_INSN
in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
if (GET_CODE (trial) == CALL_INSN)
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (seq, 0, i)) == CALL_INSN)
- CALL_INSN_FUNCTION_USAGE (XVECEXP (seq, 0, i))
- = CALL_INSN_FUNCTION_USAGE (trial);
+ {
+ insn = insn_last;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == CALL_INSN)
+ CALL_INSN_FUNCTION_USAGE (insn)
+ = CALL_INSN_FUNCTION_USAGE (trial);
+
+ insn = PREV_INSN (insn);
+ }
+ }
/* Copy notes, particularly those related to the CFG. */
for (note = REG_NOTES (trial); note; note = XEXP (note, 1))
@@ -3154,9 +3174,9 @@ try_split (pat, trial, last)
switch (REG_NOTE_KIND (note))
{
case REG_EH_REGION:
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+ insn = insn_last;
+ while (insn != NULL_RTX)
{
- rtx insn = XVECEXP (seq, 0, i);
if (GET_CODE (insn) == CALL_INSN
|| (flag_non_call_exceptions
&& may_trap_p (PATTERN (insn))))
@@ -3164,32 +3184,35 @@ try_split (pat, trial, last)
= gen_rtx_EXPR_LIST (REG_EH_REGION,
XEXP (note, 0),
REG_NOTES (insn));
+ insn = PREV_INSN (insn);
}
break;
case REG_NORETURN:
case REG_SETJMP:
case REG_ALWAYS_RETURN:
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+ insn = insn_last;
+ while (insn != NULL_RTX)
{
- rtx insn = XVECEXP (seq, 0, i);
if (GET_CODE (insn) == CALL_INSN)
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
XEXP (note, 0),
REG_NOTES (insn));
+ insn = PREV_INSN (insn);
}
break;
case REG_NON_LOCAL_GOTO:
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
+ insn = insn_last;
+ while (insn != NULL_RTX)
{
- rtx insn = XVECEXP (seq, 0, i);
if (GET_CODE (insn) == JUMP_INSN)
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
XEXP (note, 0),
REG_NOTES (insn));
+ insn = PREV_INSN (insn);
}
break;
@@ -3201,9 +3224,16 @@ try_split (pat, trial, last)
/* If there are LABELS inside the split insns increment the
usage count so we don't delete the label. */
if (GET_CODE (trial) == INSN)
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (seq, 0, i)) == INSN)
- mark_label_nuses (PATTERN (XVECEXP (seq, 0, i)));
+ {
+ insn = last_insn;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == INSN)
+ mark_label_nuses (PATTERN (insn));
+
+ insn = PREV_INSN (insn);
+ }
+ }
tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial));
@@ -3221,13 +3251,13 @@ try_split (pat, trial, last)
tem = try_split (PATTERN (tem), tem, 1);
}
/* Avoid infinite loop if the result matches the original pattern. */
- else if (rtx_equal_p (seq, pat))
+ else if (rtx_equal_p (PATTERN (seq), pat))
return trial;
else
{
- PATTERN (trial) = seq;
+ PATTERN (trial) = PATTERN (seq);
INSN_CODE (trial) = -1;
- try_split (seq, trial, last);
+ try_split (PATTERN (trial), trial, last);
}
/* Return either the first or the last insn, depending on which was
@@ -3274,7 +3304,7 @@ make_insn_raw (pattern)
return insn;
}
-/* Like `make_insn' but make a JUMP_INSN instead of an insn. */
+/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */
static rtx
make_jump_insn_raw (pattern)
@@ -3296,7 +3326,7 @@ make_jump_insn_raw (pattern)
return insn;
}
-/* Like `make_insn' but make a CALL_INSN instead of an insn. */
+/* Like `make_insn_raw' but make a CALL_INSN instead of an insn. */
static rtx
make_call_insn_raw (pattern)
@@ -3782,97 +3812,173 @@ remove_unnecessary_notes ()
}
-/* Emit an insn of given code and pattern
- at a specified place within the doubly-linked list. */
+/* Emit insn(s) of given code and pattern
+ at a specified place within the doubly-linked list.
-/* Make an instruction with body PATTERN
- and output it before the instruction BEFORE. */
+ All of the emit_foo global entry points accept an object
+ X which is either an insn list or a PATTERN of a single
+ instruction.
-rtx
-emit_insn_before (pattern, before)
- rtx pattern, before;
-{
- rtx insn = before;
+ There are thus a few canonical ways to generate code and
+ emit it at a specific place in the instruction stream. For
+ example, consider the instruction named SPOT and the fact that
+ we would like to emit some instructions before SPOT. We might
+ do it like this:
- if (GET_CODE (pattern) == SEQUENCE)
- {
- int i;
+ start_sequence ();
+ ... emit the new instructions ...
+ insns_head = get_insns ();
+ end_sequence ();
- for (i = 0; i < XVECLEN (pattern, 0); i++)
- {
- insn = XVECEXP (pattern, 0, i);
- add_insn_before (insn, before);
- }
- }
- else
- {
- insn = make_insn_raw (pattern);
- add_insn_before (insn, before);
- }
+ emit_insn_before (insns_head, SPOT);
- return insn;
-}
+ It used to be common to generate SEQUENCE rtl instead, but that
+ is a relic of the past which no longer occurs. The reason is that
+ SEQUENCE rtl results in much fragmented RTL memory since the SEQUENCE
+ generated would almost certainly die right after it was created. */
-/* Make an instruction with body PATTERN and code JUMP_INSN
- and output it before the instruction BEFORE. */
+/* Make X be output before the instruction BEFORE. */
rtx
-emit_jump_insn_before (pattern, before)
- rtx pattern, before;
+emit_insn_before (x, before)
+ rtx x, before;
{
+ rtx last = before;
rtx insn;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_before (pattern, before);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (before == NULL_RTX)
+ abort ();
+#endif
+
+ if (x == NULL_RTX)
+ return last;
+
+ switch (GET_CODE (x))
{
- insn = make_jump_insn_raw (pattern);
- add_insn_before (insn, before);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn_before (insn, before);
+ last = insn;
+ insn = next;
+ }
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_insn_raw (x);
+ add_insn_before (last, before);
+ break;
}
- return insn;
+ return last;
}
-/* Make an instruction with body PATTERN and code CALL_INSN
+/* Make an instruction with body X and code JUMP_INSN
and output it before the instruction BEFORE. */
rtx
-emit_call_insn_before (pattern, before)
- rtx pattern, before;
+emit_jump_insn_before (x, before)
+ rtx x, before;
{
- rtx insn;
+ rtx insn, last;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_before (pattern, before);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (before == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
{
- insn = make_call_insn_raw (pattern);
- add_insn_before (insn, before);
- PUT_CODE (insn, CALL_INSN);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn_before (insn, before);
+ last = insn;
+ insn = next;
+ }
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_jump_insn_raw (x);
+ add_insn_before (last, before);
+ break;
}
- return insn;
+ return last;
}
-/* Make an instruction with body PATTERN and code CALL_INSN
+/* Make an instruction with body X and code CALL_INSN
and output it before the instruction BEFORE. */
rtx
-emit_call_insn_after (pattern, before)
- rtx pattern, before;
+emit_call_insn_before (x, before)
+ rtx x, before;
{
- rtx insn;
+ rtx last, insn;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_after (pattern, before);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (before == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
{
- insn = make_call_insn_raw (pattern);
- add_insn_after (insn, before);
- PUT_CODE (insn, CALL_INSN);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn_before (insn, before);
+ last = insn;
+ insn = next;
+ }
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_call_insn_raw (x);
+ add_insn_before (last, before);
+ break;
}
- return insn;
+ return last;
}
/* Make an insn of code BARRIER
@@ -3924,45 +4030,100 @@ emit_note_before (subtype, before)
return note;
}
-/* Make an insn of code INSN with body PATTERN
- and output it after the insn AFTER. */
+/* Helper for emit_insn_after, handles lists of instructions
+ efficiently. */
-rtx
-emit_insn_after (pattern, after)
- rtx pattern, after;
+static rtx emit_insn_after_1 PARAMS ((rtx, rtx));
+
+static rtx
+emit_insn_after_1 (first, after)
+ rtx first, after;
{
- rtx insn = after;
+ rtx last;
+ rtx after_after;
+ basic_block bb;
- if (GET_CODE (pattern) == SEQUENCE)
+ if (GET_CODE (after) != BARRIER
+ && (bb = BLOCK_FOR_INSN (after)))
{
- int i;
-
- for (i = 0; i < XVECLEN (pattern, 0); i++)
- {
- insn = XVECEXP (pattern, 0, i);
- add_insn_after (insn, after);
- after = insn;
- }
+ bb->flags |= BB_DIRTY;
+ for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+ if (GET_CODE (last) != BARRIER)
+ set_block_for_insn (last, bb);
+ if (GET_CODE (last) != BARRIER)
+ set_block_for_insn (last, bb);
+ if (bb->end == after)
+ bb->end = last;
}
else
+ for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+ continue;
+
+ after_after = NEXT_INSN (after);
+
+ NEXT_INSN (after) = first;
+ PREV_INSN (first) = after;
+ NEXT_INSN (last) = after_after;
+ if (after_after)
+ PREV_INSN (after_after) = last;
+
+ if (after == last_insn)
+ last_insn = last;
+ return last;
+}
+
+/* Make X be output after the insn AFTER. */
+
+rtx
+emit_insn_after (x, after)
+ rtx x, after;
+{
+ rtx last = after;
+
+#ifdef ENABLE_RTL_CHECKING
+ if (after == NULL_RTX)
+ abort ();
+#endif
+
+ if (x == NULL_RTX)
+ return last;
+
+ switch (GET_CODE (x))
{
- insn = make_insn_raw (pattern);
- add_insn_after (insn, after);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ last = emit_insn_after_1 (x, after);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_insn_raw (x);
+ add_insn_after (last, after);
+ break;
}
- return insn;
+ return last;
}
/* Similar to emit_insn_after, except that line notes are to be inserted so
as to act as if this insn were at FROM. */
void
-emit_insn_after_with_line_notes (pattern, after, from)
- rtx pattern, after, from;
+emit_insn_after_with_line_notes (x, after, from)
+ rtx x, after, from;
{
rtx from_line = find_line_note (from);
rtx after_line = find_line_note (after);
- rtx insn = emit_insn_after (pattern, after);
+ rtx insn = emit_insn_after (x, after);
if (from_line)
emit_line_note_after (NOTE_SOURCE_FILE (from_line),
@@ -3975,24 +4136,84 @@ emit_insn_after_with_line_notes (pattern, after, from)
insn);
}
-/* Make an insn of code JUMP_INSN with body PATTERN
+/* Make an insn of code JUMP_INSN with body X
and output it after the insn AFTER. */
rtx
-emit_jump_insn_after (pattern, after)
- rtx pattern, after;
+emit_jump_insn_after (x, after)
+ rtx x, after;
{
- rtx insn;
+ rtx last;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_after (pattern, after);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (after == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
{
- insn = make_jump_insn_raw (pattern);
- add_insn_after (insn, after);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ last = emit_insn_after_1 (x, after);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_jump_insn_raw (x);
+ add_insn_after (last, after);
+ break;
}
- return insn;
+ return last;
+}
+
+/* Make an instruction with body X and code CALL_INSN
+ and output it after the instruction AFTER. */
+
+rtx
+emit_call_insn_after (x, after)
+ rtx x, after;
+{
+ rtx last;
+
+#ifdef ENABLE_RTL_CHECKING
+ if (after == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
+ {
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ last = emit_insn_after_1 (x, after);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_call_insn_raw (x);
+ add_insn_after (last, after);
+ break;
+ }
+
+ return last;
}
/* Make an insn of code BARRIER
@@ -4076,20 +4297,15 @@ emit_insn_after_scope (pattern, after, scope)
tree scope;
{
rtx last = emit_insn_after (pattern, after);
- for (after = NEXT_INSN (after); after != last; after = NEXT_INSN (after))
- INSN_SCOPE (after) = scope;
- return last;
-}
-/* Like emit_insns_after, but set INSN_SCOPE according to SCOPE. */
-rtx
-emit_insns_after_scope (pattern, after, scope)
- rtx pattern, after;
- tree scope;
-{
- rtx last = emit_insns_after (pattern, after);
- for (after = NEXT_INSN (after); after != last; after = NEXT_INSN (after))
- INSN_SCOPE (after) = scope;
+ after = NEXT_INSN (after);
+ while (1)
+ {
+ INSN_SCOPE (after) = scope;
+ if (after == last)
+ break;
+ after = NEXT_INSN (after);
+ }
return last;
}
@@ -4100,8 +4316,15 @@ emit_jump_insn_after_scope (pattern, after, scope)
tree scope;
{
rtx last = emit_jump_insn_after (pattern, after);
- for (after = NEXT_INSN (after); after != last; after = NEXT_INSN (after))
- INSN_SCOPE (after) = scope;
+
+ after = NEXT_INSN (after);
+ while (1)
+ {
+ INSN_SCOPE (after) = scope;
+ if (after == last)
+ break;
+ after = NEXT_INSN (after);
+ }
return last;
}
@@ -4112,8 +4335,15 @@ emit_call_insn_after_scope (pattern, after, scope)
tree scope;
{
rtx last = emit_call_insn_after (pattern, after);
- for (after = NEXT_INSN (after); after != last; after = NEXT_INSN (after))
- INSN_SCOPE (after) = scope;
+
+ after = NEXT_INSN (after);
+ while (1)
+ {
+ INSN_SCOPE (after) = scope;
+ if (after == last)
+ break;
+ after = NEXT_INSN (after);
+ }
return last;
}
@@ -4126,178 +4356,140 @@ emit_insn_before_scope (pattern, before, scope)
rtx first = PREV_INSN (before);
rtx last = emit_insn_before (pattern, before);
- for (first = NEXT_INSN (first); first != last; first = NEXT_INSN (first))
- INSN_SCOPE (first) = scope;
- return last;
-}
-
-/* Like emit_insns_before, but set INSN_SCOPE according to SCOPE. */
-rtx
-emit_insns_before_scope (pattern, before, scope)
- rtx pattern, before;
- tree scope;
-{
- rtx first = PREV_INSN (before);
- rtx last = emit_insns_before (pattern, before);
-
- for (first = NEXT_INSN (first); first != last; first = NEXT_INSN (first))
- INSN_SCOPE (first) = scope;
+ first = NEXT_INSN (first);
+ while (1)
+ {
+ INSN_SCOPE (first) = scope;
+ if (first == last)
+ break;
+ first = NEXT_INSN (first);
+ }
return last;
}
-/* Make an insn of code INSN with pattern PATTERN
- and add it to the end of the doubly-linked list.
- If PATTERN is a SEQUENCE, take the elements of it
- and emit an insn for each element.
+/* Take X and emit it at the end of the doubly-linked
+ INSN list.
Returns the last insn emitted. */
rtx
-emit_insn (pattern)
- rtx pattern;
+emit_insn (x)
+ rtx x;
{
- rtx insn = last_insn;
+ rtx last = last_insn;
+ rtx insn;
- if (GET_CODE (pattern) == SEQUENCE)
- {
- int i;
+ if (x == NULL_RTX)
+ return last;
- for (i = 0; i < XVECLEN (pattern, 0); i++)
+ switch (GET_CODE (x))
+ {
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
{
- insn = XVECEXP (pattern, 0, i);
+ rtx next = NEXT_INSN (insn);
add_insn (insn);
+ last = insn;
+ insn = next;
}
- }
- else
- {
- insn = make_insn_raw (pattern);
- add_insn (insn);
- }
-
- return insn;
-}
-
-/* Emit the insns in a chain starting with INSN.
- Return the last insn emitted. */
+ break;
-rtx
-emit_insns (insn)
- rtx insn;
-{
- rtx last = 0;
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
- while (insn)
- {
- rtx next = NEXT_INSN (insn);
- add_insn (insn);
- last = insn;
- insn = next;
+ default:
+ last = make_insn_raw (x);
+ add_insn (last);
+ break;
}
return last;
}
-/* Emit the insns in a chain starting with INSN and place them in front of
- the insn BEFORE. Return the last insn emitted. */
+/* Make an insn of code JUMP_INSN with pattern X
+ and add it to the end of the doubly-linked list. */
rtx
-emit_insns_before (insn, before)
- rtx insn;
- rtx before;
+emit_jump_insn (x)
+ rtx x;
{
- rtx last = 0;
+ rtx last, insn;
- while (insn)
+ switch (GET_CODE (x))
{
- rtx next = NEXT_INSN (insn);
- add_insn_before (insn, before);
- last = insn;
- insn = next;
- }
-
- return last;
-}
-
-/* Emit the insns in a chain starting with FIRST and place them in back of
- the insn AFTER. Return the last insn emitted. */
-
-rtx
-emit_insns_after (first, after)
- rtx first;
- rtx after;
-{
- rtx last;
- rtx after_after;
- basic_block bb;
-
- if (!after)
- abort ();
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn (insn);
+ last = insn;
+ insn = next;
+ }
+ break;
- if (!first)
- return after;
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
- if (GET_CODE (after) != BARRIER
- && (bb = BLOCK_FOR_INSN (after)))
- {
- bb->flags |= BB_DIRTY;
- for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
- if (GET_CODE (last) != BARRIER)
- set_block_for_insn (last, bb);
- if (GET_CODE (last) != BARRIER)
- set_block_for_insn (last, bb);
- if (bb->end == after)
- bb->end = last;
+ default:
+ last = make_jump_insn_raw (x);
+ add_insn (last);
+ break;
}
- else
- for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
- continue;
-
- after_after = NEXT_INSN (after);
-
- NEXT_INSN (after) = first;
- PREV_INSN (first) = after;
- NEXT_INSN (last) = after_after;
- if (after_after)
- PREV_INSN (after_after) = last;
- if (after == last_insn)
- last_insn = last;
return last;
}
-/* Make an insn of code JUMP_INSN with pattern PATTERN
+/* Make an insn of code CALL_INSN with pattern X
and add it to the end of the doubly-linked list. */
rtx
-emit_jump_insn (pattern)
- rtx pattern;
+emit_call_insn (x)
+ rtx x;
{
- if (GET_CODE (pattern) == SEQUENCE)
- return emit_insn (pattern);
- else
+ rtx insn;
+
+ switch (GET_CODE (x))
{
- rtx insn = make_jump_insn_raw (pattern);
- add_insn (insn);
- return insn;
- }
-}
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = emit_insn (x);
+ break;
-/* Make an insn of code CALL_INSN with pattern PATTERN
- and add it to the end of the doubly-linked list. */
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
-rtx
-emit_call_insn (pattern)
- rtx pattern;
-{
- if (GET_CODE (pattern) == SEQUENCE)
- return emit_insn (pattern);
- else
- {
- rtx insn = make_call_insn_raw (pattern);
+ default:
+ insn = make_call_insn_raw (x);
add_insn (insn);
- PUT_CODE (insn, CALL_INSN);
- return insn;
+ break;
}
+
+ return insn;
}
/* Add the label LABEL to the end of the doubly-linked list. */
@@ -4634,12 +4826,12 @@ pop_topmost_sequence ()
/* After emitting to a sequence, restore previous saved state.
To get the contents of the sequence just made, you must call
- `gen_sequence' *before* calling here.
+ `get_insns' *before* calling here.
If the compiler might have deferred popping arguments while
generating this sequence, and this sequence will not be immediately
inserted into the instruction stream, use do_pending_stack_adjust
- before calling gen_sequence. That will ensure that the deferred
+ before calling get_insns. That will ensure that the deferred
pops are inserted into this sequence, and not into some random
location in the instruction stream. See INHIBIT_DEFER_POP for more
information about deferred popping of arguments. */
@@ -4678,45 +4870,6 @@ in_sequence_p ()
{
return seq_stack != 0;
}
-
-/* Generate a SEQUENCE rtx containing the insns already emitted
- to the current sequence.
-
- This is how the gen_... function from a DEFINE_EXPAND
- constructs the SEQUENCE that it returns. */
-
-rtx
-gen_sequence ()
-{
- rtx result;
- rtx tem;
- int i;
- int len;
-
- /* Count the insns in the chain. */
- len = 0;
- for (tem = first_insn; tem; tem = NEXT_INSN (tem))
- len++;
-
- /* If only one insn, return it rather than a SEQUENCE.
- (Now that we cache SEQUENCE expressions, it isn't worth special-casing
- the case of an empty list.)
- We only return the pattern of an insn if its code is INSN and it
- has no notes. This ensures that no information gets lost. */
- if (len == 1
- && GET_CODE (first_insn) == INSN
- && ! RTX_FRAME_RELATED_P (first_insn)
- /* Don't throw away any reg notes. */
- && REG_NOTES (first_insn) == 0)
- return PATTERN (first_insn);
-
- result = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (len));
-
- for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++)
- XVECEXP (result, 0, i) = tem;
-
- return result;
-}
/* Put the various virtual registers into REGNO_REG_RTX. */