This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ia64 eh, part 14
- To: gcc-patches at gcc dot gnu dot org
- Subject: ia64 eh, part 14
- From: Richard Henderson <rth at redhat dot com>
- Date: Tue, 27 Mar 2001 23:44:41 -0800
If non-call instructions that throw exceptions that are caught within
the function are modeled properly, that is, actually force the basic
block to end, then we cannot move them without moving the basic block
boundary. Letting that happen confuses the scheduler immensely.
r~
* sched-deps.c (sched_analyze_insn): Consolidate scheduling
barrier code. Add a scheduling barrier if a non-call insn
can throw internally.
Index: sched-deps.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/sched-deps.c,v
retrieving revision 1.9
diff -c -p -d -r1.9 sched-deps.c
*** sched-deps.c 2001/01/19 18:28:58 1.9
--- sched-deps.c 2001/03/28 07:38:03
*************** sched_analyze_insn (deps, x, insn, loop_
*** 972,977 ****
--- 972,978 ----
rtx loop_notes;
{
register RTX_CODE code = GET_CODE (x);
+ int schedule_barrier_found = 0;
rtx link;
int i;
*************** sched_analyze_insn (deps, x, insn, loop_
*** 1021,1042 ****
if (GET_CODE (insn) == JUMP_INSN)
{
! rtx next, u, pending, pending_mem;
next = next_nonnote_insn (insn);
if (next && GET_CODE (next) == BARRIER)
! {
! for (i = 0; i < deps->max_reg; i++)
! {
! struct deps_reg *reg_last = &deps->reg_last[i];
!
! for (u = reg_last->uses; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
! for (u = reg_last->sets; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
! for (u = reg_last->clobbers; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
! }
! }
else
{
regset_head tmp;
--- 1022,1031 ----
if (GET_CODE (insn) == JUMP_INSN)
{
! rtx next, u;
next = next_nonnote_insn (insn);
if (next && GET_CODE (next) == BARRIER)
! schedule_barrier_found = 1;
else
{
regset_head tmp;
*************** sched_analyze_insn (deps, x, insn, loop_
*** 1054,1086 ****
CLEAR_REG_SET (&tmp);
}
- pending = deps->pending_write_insns;
- pending_mem = deps->pending_write_mems;
- while (pending)
- {
- add_dependence (insn, XEXP (pending, 0), 0);
-
- pending = XEXP (pending, 1);
- pending_mem = XEXP (pending_mem, 1);
- }
-
- for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
- add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
}
/* If there is a {LOOP,EHREGION}_{BEG,END} note in the middle of a basic
block, then we must be sure that no instructions are scheduled across it.
Otherwise, the reg_n_refs info (which depends on loop_depth) would
become incorrect. */
-
if (loop_notes)
{
- int schedule_barrier_found = 0;
rtx link;
/* Update loop_notes with any notes from this insn. Also determine
if any of the notes on the list correspond to instruction scheduling
! barriers (loop, eh & setjmp notes, but not range notes. */
link = loop_notes;
while (XEXP (link, 1))
{
--- 1043,1061 ----
CLEAR_REG_SET (&tmp);
}
}
/* If there is a {LOOP,EHREGION}_{BEG,END} note in the middle of a basic
block, then we must be sure that no instructions are scheduled across it.
Otherwise, the reg_n_refs info (which depends on loop_depth) would
become incorrect. */
if (loop_notes)
{
rtx link;
/* Update loop_notes with any notes from this insn. Also determine
if any of the notes on the list correspond to instruction scheduling
! barriers (loop, eh & setjmp notes, but not range notes). */
link = loop_notes;
while (XEXP (link, 1))
{
*************** sched_analyze_insn (deps, x, insn, loop_
*** 1095,1124 ****
}
XEXP (link, 1) = REG_NOTES (insn);
REG_NOTES (insn) = loop_notes;
! /* Add dependencies if a scheduling barrier was found. */
! if (schedule_barrier_found)
{
! for (i = 0; i < deps->max_reg; i++)
! {
! struct deps_reg *reg_last = &deps->reg_last[i];
! rtx u;
! for (u = reg_last->uses; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
! for (u = reg_last->sets; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), 0);
! for (u = reg_last->clobbers; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), 0);
! if (GET_CODE (PATTERN (insn)) != COND_EXEC)
! free_INSN_LIST_list (®_last->uses);
! }
! reg_pending_sets_all = 1;
! flush_pending_lists (deps, insn, 0);
}
}
/* Accumulate clobbers until the next set so that it will be output
--- 1070,1117 ----
}
XEXP (link, 1) = REG_NOTES (insn);
REG_NOTES (insn) = loop_notes;
+ }
! /* If this instruction can throw an exception, then moving it changes
! where block boundaries fall. This is mighty confusing elsewhere.
! Therefore, prevent such an instruction from being moved. */
! if (flag_non_call_exceptions && can_throw_internal (insn))
! schedule_barrier_found = 1;
!
! /* Add dependencies if a scheduling barrier was found. */
! if (schedule_barrier_found)
! {
! rtx u, pending, pending_mem;
!
! for (i = 0; i < deps->max_reg; i++)
{
! struct deps_reg *reg_last = &deps->reg_last[i];
! for (u = reg_last->uses; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
! for (u = reg_last->sets; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), 0);
! for (u = reg_last->clobbers; u; u = XEXP (u, 1))
! add_dependence (insn, XEXP (u, 0), 0);
! if (GET_CODE (PATTERN (insn)) != COND_EXEC)
! free_INSN_LIST_list (®_last->uses);
! }
! flush_pending_lists (deps, insn, 0);
! pending = deps->pending_write_insns;
! pending_mem = deps->pending_write_mems;
! while (pending)
! {
! add_dependence (insn, XEXP (pending, 0), 0);
! pending = XEXP (pending, 1);
! pending_mem = XEXP (pending_mem, 1);
}
+ for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
+
+ reg_pending_sets_all = 1;
}
/* Accumulate clobbers until the next set so that it will be output