p->must_stay = true;
}
-/* Encapsulate the block starting at FIRST and ending with LAST, which is
- logically equivalent to EQUIV, so it gets manipulated as a unit if it
- is possible to do so. */
-
-void
-maybe_encapsulate_block (rtx first, rtx last, rtx equiv)
-{
- if (!flag_non_call_exceptions || !may_trap_p (equiv))
- {
- /* We can't attach the REG_LIBCALL and REG_RETVAL notes when the
- encapsulated region would not be in one basic block, i.e. when
- there is a control_flow_insn_p insn between FIRST and LAST. */
- bool attach_libcall_retval_notes = true;
- rtx insn, next = NEXT_INSN (last);
-
- for (insn = first; insn != next; insn = NEXT_INSN (insn))
- if (control_flow_insn_p (insn))
- {
- attach_libcall_retval_notes = false;
- break;
- }
-
- if (attach_libcall_retval_notes)
- {
- REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
- REG_NOTES (first));
- REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
- REG_NOTES (last));
- }
- }
-}
-
\f
/* Emit code to make a call to a constant function or a library call.
loading constants into registers; doing so allows them to be safely cse'ed
between blocks. Then we emit all the other insns in the block, followed by
an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
- note with an operand of EQUIV.
-
- Moving assignments to pseudos outside of the block is done to improve
- the generated code, but is not required to generate correct code,
- hence being unable to move an assignment is not grounds for not making
- a libcall block. There are two reasons why it is safe to leave these
- insns inside the block: First, we know that these pseudos cannot be
- used in generated RTL outside the block since they are created for
- temporary purposes within the block. Second, CSE will not record the
- values of anything set inside a libcall block, so we know they must
- be dead at the end of the block.
-
- Except for the first group of insns (the ones setting pseudos), the
- block is delimited by REG_RETVAL and REG_LIBCALL notes. */
+ note with an operand of EQUIV. */
+
void
emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
{
rtx final_dest = target;
- rtx prev, next, first, last, insn;
+ rtx prev, next, last, insn;
/* If this is a reg with REG_USERVAR_P set, then it could possibly turn
into a MEM later. Protect the libcall block from this change. */
for (insn = insns; insn; insn = next)
{
rtx set = single_set (insn);
- rtx note;
-
- /* Some ports (cris) create a libcall regions at their own. We must
- avoid any potential nesting of LIBCALLs. */
- if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
- remove_note (insn, note);
- if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
- remove_note (insn, note);
next = NEXT_INSN (insn);
if (optab_handler (mov_optab, GET_MODE (target))->insn_code
!= CODE_FOR_nothing)
set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
- else
- {
- /* Remove any existing REG_EQUAL note from "last", or else it will
- be mistaken for a note referring to the full contents of the
- libcall value when found together with the REG_RETVAL note added
- below. An existing note can come from an insn expansion at
- "last". */
- remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
- }
if (final_dest != target)
emit_move_insn (final_dest, target);
-
- if (prev == 0)
- first = get_insns ();
- else
- first = NEXT_INSN (prev);
-
- maybe_encapsulate_block (first, last, equiv);
}
\f
/* Nonzero if we can perform a comparison of mode MODE straightforwardly.