===================================================================
@@ -2761,6 +2762,59 @@ choose_ready (struct ready_list *ready,
}
}
+/* Examine all insns on the ready list and queue those which can't be
+ issued in this cycle. TEMP_STATE is temporary scheduler state we
+ can use as scratch space. If FIRST_CYCLE_INSN_P is true, no insns
+ have been issued for the current cycle, which means it is valid to
+ issue an asm statement. Return the number of cycles we must
+ advance to find the next ready instruction, or zero if there remain
+ insns on the ready list. */
+
+static int
+delay_ready_insns_with_resource_conflict (state_t temp_state,
+ bool first_cycle_insn_p)
+{
+ int min_cost = INT_MAX;
+ int i;
+
+ restart:
+ for (i = 0; i < ready.n_ready; i++)
+ {
+ rtx insn = ready_element (&ready, i);
+ int cost = 0;
+
+ if (recog_memoized (insn) < 0)
+ {
+ if (!first_cycle_insn_p
+ && (GET_CODE (PATTERN (insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (insn)) >= 0))
+ cost = 1;
+ }
+ else if (sched_pressure_p)
+ cost = 0;
+ else
+ {
+ memcpy (temp_state, curr_state, dfa_state_size);
+ cost = state_transition (temp_state, insn);
+ if (cost < 0)
+ cost = 0;
+ else if (cost == 0)
+ cost = 1;
+ }
+ if (cost >= 1)
+ {
+ if (cost < min_cost)
+ min_cost = cost;
+ ready_remove (&ready, i);
+ queue_insn (insn, cost);
+ goto restart;
+ }
+ }
+ if (ready.n_ready == 0)
+ return min_cost;
+ return 0;
+}
+
/* Use forward list scheduling to rearrange insns of block pointed to by
TARGET_BB, possibly bringing insns from subsequent blocks in the same
region. */
@@ -2768,7 +2822,7 @@ choose_ready (struct ready_list *ready,
void
schedule_block (basic_block *target_bb)
{
- int i, first_cycle_insn_p;
+ int i;
int can_issue_more;
state_t temp_state = NULL; /* It is used for multipass scheduling. */
int sort_p, advance, start_clock_var;
@@ -2907,6 +2961,10 @@ schedule_block (basic_block *target_bb)
debug_ready_list (&ready);
}
advance -= clock_var - start_clock_var;
+
+ if (advance <= 0)
+ advance = delay_ready_insns_with_resource_conflict (temp_state,
+ true);
}
while (advance > 0);
@@ -2974,7 +3032,6 @@ schedule_block (basic_block *target_bb)
else
can_issue_more = issue_rate;
- first_cycle_insn_p = 1;
cycle_issued_insns = 0;
for (;;)
{
@@ -3059,44 +3116,6 @@ schedule_block (basic_block *target_bb)
}
sort_p = TRUE;
- memcpy (temp_state, curr_state, dfa_state_size);
- if (recog_memoized (insn) < 0)
- {
- asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
- || asm_noperands (PATTERN (insn)) >= 0);
- if (!first_cycle_insn_p && asm_p)
- /* This is asm insn which is tried to be issued on the
- cycle not first. Issue it on the next cycle. */
- cost = 1;
- else
- /* A USE insn, or something else we don't need to
- understand. We can't pass these directly to
- state_transition because it will trigger a
- fatal error for unrecognizable insns. */
- cost = 0;
- }
- else if (sched_pressure_p)
- cost = 0;
- else
- {
- cost = state_transition (temp_state, insn);
- if (cost < 0)
- cost = 0;
- else if (cost == 0)
- cost = 1;
- }
-
- if (cost >= 1)
- {
- queue_insn (insn, cost);
- if (SCHED_GROUP_P (insn))
- {
- advance = cost;
- break;
- }
-
- continue;
- }
if (current_sched_info->can_schedule_ready_p
&& ! (*current_sched_info->can_schedule_ready_p) (insn))
@@ -3143,11 +3162,18 @@ schedule_block (basic_block *target_bb)
reemit_notes (insn);
last_scheduled_insn = insn;
- if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
- {
- cycle_issued_insns++;
- memcpy (curr_state, temp_state, dfa_state_size);
+ if (recog_memoized (insn) >= 0)
+ {
+ if (!sched_pressure_p)
+ {
+ cost = state_transition (curr_state, insn);
+ gcc_assert (cost < 0);
+ cycle_issued_insns++;
+ }
}
+ else
+ asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (insn)) >= 0);
if (targetm.sched.variable_issue)
can_issue_more =
@@ -3163,11 +3189,12 @@ schedule_block (basic_block *target_bb)
/* After issuing an asm insn we should start a new cycle. */
if (advance == 0 && asm_p)
advance = 1;
+ else if (advance == 0 && ready.n_ready > 0)
+ advance = delay_ready_insns_with_resource_conflict (temp_state, false);
+
if (advance != 0)
break;
- first_cycle_insn_p = 0;
-
/* Sort the ready list based on priority. This must be
redone here, as schedule_insn may have readied additional
insns that will not be sorted correctly. */