GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Instruction reorganization pass.
epilogue has filled delay-slots; we would have to try and
move the delay-slot fillers to the delay-slots for the new
return insn or in front of the new return insn. */
- if (current_function_epilogue_delay_list == NULL
+ if (crtl->epilogue_delay_list == NULL
&& HAVE_return)
{
/* The return we make may have delay slots too. */
INSN_DELETED_P (delay_insn) = 0;
PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
+ INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);
+
for (li = list; li; li = XEXP (li, 1), i++)
{
rtx tem = XEXP (li, 0);
remove_note (tem, note);
break;
- case REG_LABEL:
+ case REG_LABEL_OPERAND:
+ case REG_LABEL_TARGET:
/* Keep the label reference count up to date. */
if (LABEL_P (XEXP (note, 0)))
LABEL_NUSES (XEXP (note, 0)) ++;
In both of these cases, inverting the jump and annulling the delay
slot give the same effect in fewer insns. */
if ((next_trial == next_active_insn (JUMP_LABEL (insn))
- && ! (next_trial == 0 && current_function_epilogue_delay_list != 0))
+ && ! (next_trial == 0 && crtl->epilogue_delay_list != 0))
|| (next_trial != 0
&& JUMP_P (next_trial)
&& JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
{
if (! annul_p)
{
- rtx new;
+ rtx new_rtx;
update_block (dtrial, thread);
- new = delete_from_delay_slot (dtrial);
+ new_rtx = delete_from_delay_slot (dtrial);
if (INSN_DELETED_P (thread))
- thread = new;
+ thread = new_rtx;
INSN_FROM_TARGET_P (next_to_match) = 0;
}
else
{
if (GET_MODE (merged_insns) == SImode)
{
- rtx new;
+ rtx new_rtx;
update_block (XEXP (merged_insns, 0), thread);
- new = delete_from_delay_slot (XEXP (merged_insns, 0));
+ new_rtx = delete_from_delay_slot (XEXP (merged_insns, 0));
if (INSN_DELETED_P (thread))
- thread = new;
+ thread = new_rtx;
}
else
{
The only thing we can do is scan backwards from the end of the
function. If we did this in a previous pass, it is incorrect to do it
again. */
- if (current_function_epilogue_delay_list)
+ if (crtl->epilogue_delay_list)
return;
slots_to_fill = DELAY_SLOTS_FOR_EPILOGUE;
/* Here as well we are searching backward, so put the
insns we find on the head of the list. */
- current_function_epilogue_delay_list
+ crtl->epilogue_delay_list
= gen_rtx_INSN_LIST (VOIDmode, trial,
- current_function_epilogue_delay_list);
+ crtl->epilogue_delay_list);
mark_end_of_function_resources (trial, 1);
update_block (trial, trial);
delete_related_insns (trial);
/* We are moving this insn, not deleting it. We must
temporarily increment the use count on any referenced
label lest it be deleted by delete_related_insns. */
- note = find_reg_note (trial, REG_LABEL, 0);
- /* REG_LABEL could be NOTE_INSN_DELETED_LABEL too. */
- if (note && LABEL_P (XEXP (note, 0)))
- LABEL_NUSES (XEXP (note, 0))++;
+ for (note = REG_NOTES (trial);
+ note != NULL_RTX;
+ note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
+ || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
+ {
+ /* REG_LABEL_OPERAND could be
+ NOTE_INSN_DELETED_LABEL too. */
+ if (LABEL_P (XEXP (note, 0)))
+ LABEL_NUSES (XEXP (note, 0))++;
+ else
+ gcc_assert (REG_NOTE_KIND (note)
+ == REG_LABEL_OPERAND);
+ }
+ if (JUMP_P (trial) && JUMP_LABEL (trial))
+ LABEL_NUSES (JUMP_LABEL (trial))++;
delete_related_insns (trial);
- if (note && LABEL_P (XEXP (note, 0)))
- LABEL_NUSES (XEXP (note, 0))--;
+ for (note = REG_NOTES (trial);
+ note != NULL_RTX;
+ note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
+ || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
+ {
+ /* REG_LABEL_OPERAND could be
+ NOTE_INSN_DELETED_LABEL too. */
+ if (LABEL_P (XEXP (note, 0)))
+ LABEL_NUSES (XEXP (note, 0))--;
+ else
+ gcc_assert (REG_NOTE_KIND (note)
+ == REG_LABEL_OPERAND);
+ }
+ if (JUMP_P (trial) && JUMP_LABEL (trial))
+ LABEL_NUSES (JUMP_LABEL (trial))--;
}
else
new_thread = next_active_insn (trial);
/* If we reach a CALL which is not calling a const function
or the callee pops the arguments, then give up. */
if (CALL_P (our_prev)
- && (! CONST_OR_PURE_CALL_P (our_prev)
+ && (! RTL_CONST_CALL_P (our_prev)
|| GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
break;
{
int i;
- REG_NOTES (our_prev)
- = gen_rtx_EXPR_LIST (REG_UNUSED, reg,
- REG_NOTES (our_prev));
+ add_reg_note (our_prev, REG_UNUSED, reg);
for (i = dest_regno; i < dest_endregno; i++)
if (! find_regno_note (our_prev, REG_UNUSED, i))
delete_computation (prev);
else
/* Otherwise, show that cc0 won't be used. */
- REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED,
- cc0_rtx, REG_NOTES (prev));
+ add_reg_note (prev, REG_UNUSED, cc0_rtx);
}
}
#endif
Only do so if optimizing for size since this results in slower, but
smaller code. */
- if (optimize_size
+ if (optimize_function_for_size_p (cfun)
&& GET_CODE (PATTERN (delay_insn)) == RETURN
&& next
&& JUMP_P (next)
delay slot filler insns. It is also unknown whether such a
transformation would actually be profitable. Note that the existing
code only cares for branches with (some) filled delay slots. */
- if (current_function_epilogue_delay_list != NULL)
+ if (crtl->epilogue_delay_list != NULL)
return;
#endif
epilogue_insn = insn;
}
- uid_to_ruid = xmalloc ((max_uid + 1) * sizeof (int));
+ uid_to_ruid = XNEWVEC (int, max_uid + 1);
for (i = 0, insn = first; insn; i++, insn = NEXT_INSN (insn))
uid_to_ruid[INSN_UID (insn)] = i;
if (unfilled_firstobj == 0)
{
gcc_obstack_init (&unfilled_slots_obstack);
- unfilled_firstobj = obstack_alloc (&unfilled_slots_obstack, 0);
+ unfilled_firstobj = XOBNEWVAR (&unfilled_slots_obstack, rtx, 0);
}
for (insn = next_active_insn (first); insn; insn = next_active_insn (insn))
relax_delay_slots (first);
}
- /* Delete any USE insns made by update_block; subsequent passes don't need
- them or know how to deal with them. */
- for (insn = first; insn; insn = next)
- {
- next = NEXT_INSN (insn);
-
- if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
- && INSN_P (XEXP (PATTERN (insn), 0)))
- next = delete_related_insns (insn);
- }
-
/* If we made an end of function label, indicate that it is now
safe to delete it by undoing our prior adjustment to LABEL_NUSES.
If it is now unused, delete it. */
make_return_insns (first);
#endif
+ /* Delete any USE insns made by update_block; subsequent passes don't need
+ them or know how to deal with them. */
+ for (insn = first; insn; insn = next)
+ {
+ next = NEXT_INSN (insn);
+
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
+ && INSN_P (XEXP (PATTERN (insn), 0)))
+ next = delete_related_insns (insn);
+ }
+
obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
/* It is not clear why the line below is needed, but it does seem to be. */
- unfilled_firstobj = obstack_alloc (&unfilled_slots_obstack, 0);
+ unfilled_firstobj = XOBNEWVAR (&unfilled_slots_obstack, rtx, 0);
if (dump_file)
{
continue;
pred_flags = get_jump_flags (insn, JUMP_LABEL (insn));
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_BR_PRED,
- GEN_INT (pred_flags),
- REG_NOTES (insn));
+ add_reg_note (insn, REG_BR_PRED, GEN_INT (pred_flags));
}
free_resource_info ();
free (uid_to_ruid);
{
rtx link;
- for (link = current_function_epilogue_delay_list;
+ for (link = crtl->epilogue_delay_list;
link;
link = XEXP (link, 1))
INSN_LOCATOR (XEXP (link, 0)) = 0;
}
#endif
+ crtl->dbr_scheduled_p = true;
}
#endif /* DELAY_SLOTS */
\f
gate_handle_delay_slots (void)
{
#ifdef DELAY_SLOTS
- return flag_delayed_branch;
+ return flag_delayed_branch && !crtl->dbr_scheduled_p;
#else
return 0;
#endif
return 0;
}
-struct tree_opt_pass pass_delay_slots =
+struct rtl_opt_pass pass_delay_slots =
{
+ {
+ RTL_PASS,
"dbr", /* name */
gate_handle_delay_slots, /* gate */
rest_of_handle_delay_slots, /* execute */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
- TODO_ggc_collect, /* todo_flags_finish */
- 'd' /* letter */
+ TODO_ggc_collect /* todo_flags_finish */
+ }
};
/* Machine dependent reorg pass. */
return 0;
}
-struct tree_opt_pass pass_machine_reorg =
+struct rtl_opt_pass pass_machine_reorg =
{
+ {
+ RTL_PASS,
"mach", /* name */
gate_handle_machine_reorg, /* gate */
rest_of_handle_machine_reorg, /* execute */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
- TODO_ggc_collect, /* todo_flags_finish */
- 'M' /* letter */
+ TODO_ggc_collect /* todo_flags_finish */
+ }
};