summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cc/cc_int/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cc/cc_int/sched.c')
-rw-r--r--gnu/usr.bin/cc/cc_int/sched.c96
1 files changed, 78 insertions, 18 deletions
diff --git a/gnu/usr.bin/cc/cc_int/sched.c b/gnu/usr.bin/cc/cc_int/sched.c
index 9870967..0f08b65 100644
--- a/gnu/usr.bin/cc/cc_int/sched.c
+++ b/gnu/usr.bin/cc/cc_int/sched.c
@@ -315,7 +315,7 @@ static void add_insn_mem_dependence PROTO((rtx *, rtx *, rtx, rtx));
static void flush_pending_lists PROTO((rtx));
static void sched_analyze_1 PROTO((rtx, rtx));
static void sched_analyze_2 PROTO((rtx, rtx));
-static void sched_analyze_insn PROTO((rtx, rtx));
+static void sched_analyze_insn PROTO((rtx, rtx, rtx));
static int sched_analyze PROTO((rtx, rtx));
static void sched_note_set PROTO((int, rtx, int));
static int rank_for_schedule PROTO((rtx *, rtx *));
@@ -2013,8 +2013,9 @@ sched_analyze_2 (x, insn)
/* Analyze an INSN with pattern X to find all dependencies. */
static void
-sched_analyze_insn (x, insn)
+sched_analyze_insn (x, insn, loop_notes)
rtx x, insn;
+ rtx loop_notes;
{
register RTX_CODE code = GET_CODE (x);
rtx link;
@@ -2048,6 +2049,36 @@ sched_analyze_insn (x, insn)
sched_analyze_2 (XEXP (link, 0), insn);
}
+ /* If there is a LOOP_{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 max_reg = max_reg_num ();
+ rtx link;
+
+ for (i = 0; i < max_reg; i++)
+ {
+ rtx u;
+ for (u = reg_last_uses[i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
+ reg_last_uses[i] = 0;
+ if (reg_last_sets[i])
+ add_dependence (insn, reg_last_sets[i], 0);
+ }
+ reg_pending_sets_all = 1;
+
+ flush_pending_lists (insn);
+
+ link = loop_notes;
+ while (XEXP (link, 1))
+ link = XEXP (link, 1);
+ XEXP (link, 1) = REG_NOTES (insn);
+ REG_NOTES (insn) = loop_notes;
+ }
+
/* After reload, it is possible for an instruction to have a REG_DEAD note
for a register that actually dies a few instructions earlier. For
example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
@@ -2107,7 +2138,8 @@ sched_analyze_insn (x, insn)
prev_dep_insn = insn;
dep_insn = PREV_INSN (insn);
while (GET_CODE (dep_insn) == INSN
- && GET_CODE (PATTERN (dep_insn)) == USE)
+ && GET_CODE (PATTERN (dep_insn)) == USE
+ && GET_CODE (XEXP (PATTERN (dep_insn), 0)) == REG)
{
SCHED_GROUP_P (prev_dep_insn) = 1;
@@ -2135,6 +2167,7 @@ sched_analyze (head, tail)
register int n_insns = 0;
register rtx u;
register int luid = 0;
+ rtx loop_notes = 0;
for (insn = head; ; insn = NEXT_INSN (insn))
{
@@ -2142,7 +2175,8 @@ sched_analyze (head, tail)
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{
- sched_analyze_insn (PATTERN (insn), insn);
+ sched_analyze_insn (PATTERN (insn), insn, loop_notes);
+ loop_notes = 0;
n_insns += 1;
}
else if (GET_CODE (insn) == CALL_INSN)
@@ -2179,7 +2213,8 @@ sched_analyze (head, tail)
/* Add a fake REG_NOTE which we will later convert
back into a NOTE_INSN_SETJMP note. */
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD, constm1_rtx,
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
+ GEN_INT (NOTE_INSN_SETJMP),
REG_NOTES (insn));
}
else
@@ -2207,7 +2242,8 @@ sched_analyze (head, tail)
}
LOG_LINKS (sched_before_next_call) = 0;
- sched_analyze_insn (PATTERN (insn), insn);
+ sched_analyze_insn (PATTERN (insn), insn, loop_notes);
+ loop_notes = 0;
/* We don't need to flush memory for a function call which does
not involve memory. */
@@ -2224,6 +2260,11 @@ sched_analyze (head, tail)
last_function_call = insn;
n_insns += 1;
}
+ else if (GET_CODE (insn) == NOTE
+ && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
+ loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
+ GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
if (insn == tail)
return n_insns;
@@ -2825,6 +2866,16 @@ attach_deaths (x, insn, set_p)
{
if (! all_needed && ! dead_or_set_p (insn, x))
{
+ /* Check for the case where the register dying partially
+ overlaps the register set by this insn. */
+ if (regno < FIRST_PSEUDO_REGISTER
+ && HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1)
+ {
+ int n = HARD_REGNO_NREGS (regno, GET_MODE (x));
+ while (--n >= 0)
+ some_needed |= dead_or_set_regno_p (insn, regno + n);
+ }
+
/* If none of the words in X is needed, make a REG_DEAD
note. Otherwise, we must make partial REG_DEAD
notes. */
@@ -2985,8 +3036,11 @@ unlink_notes (insn, tail)
/* Don't save away NOTE_INSN_SETJMPs, because they must remain
immediately after the call they follow. We use a fake
- (REG_DEAD (const_int -1)) note to remember them. */
- else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP)
+ (REG_DEAD (const_int -1)) note to remember them.
+ Likewise with NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END. */
+ else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END)
{
/* Insert the note at the end of the notes list. */
PREV_INSN (insn) = note_list;
@@ -3803,17 +3857,23 @@ schedule_block (b, file)
PREV_INSN (last) = insn;
last = insn;
- /* Check to see if we need to re-emit a NOTE_INSN_SETJMP here. */
- if (GET_CODE (insn) == CALL_INSN)
- {
- rtx note = find_reg_note (insn, REG_DEAD, constm1_rtx);
+ /* Check to see if we need to re-emit any notes here. */
+ {
+ rtx note;
- if (note)
- {
- emit_note_after (NOTE_INSN_SETJMP, insn);
- remove_note (insn, note);
- }
- }
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ {
+ if (REG_NOTE_KIND (note) == REG_DEAD
+ && GET_CODE (XEXP (note, 0)) == CONST_INT)
+ {
+ if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
+ emit_note_after (INTVAL (XEXP (note, 0)), insn);
+ else
+ last = emit_note_before (INTVAL (XEXP (note, 0)), last);
+ remove_note (insn, note);
+ }
+ }
+ }
/* Everything that precedes INSN now either becomes "ready", if
it can execute immediately before INSN, or "pending", if
OpenPOWER on IntegriCloud