From patchwork Thu Mar 24 13:19:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 88197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 865E4B6F8D for ; Fri, 25 Mar 2011 00:20:53 +1100 (EST) Received: (qmail 13164 invoked by alias); 24 Mar 2011 13:20:52 -0000 Received: (qmail 13153 invoked by uid 22791); 24 Mar 2011 13:20:51 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, TW_CP, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 24 Mar 2011 13:20:44 +0000 Received: (qmail 851 invoked from network); 24 Mar 2011 13:20:43 -0000 Received: from unknown (HELO ?84.152.193.230?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 24 Mar 2011 13:20:43 -0000 Message-ID: <4D8B44E9.7070908@codesourcery.com> Date: Thu, 24 Mar 2011 14:19:37 +0100 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.15) Gecko/20110309 Lightning/1.0b3pre Thunderbird/3.1.9 MIME-Version: 1.0 To: GCC Patches Subject: Scheduler cleanups, 5/5 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org We can currently select an insn to be scheduled, only to find out that it's not actually valid at the current time, either due to state conflicts or being an asm with something else already scheduled in the same cycle. Not only is this pointless, it causes problem with the sched_reorder logic in the TI C6X port (which will be submitted later). The solution is to prune the ready list earlier. More code is moved out of the schedule_block main loop, which is IMO always a good thing. Bootstrapped and tested (a slightly earlier version with an unused variable) on i686-linux; I also verified that there are no changes in code generation on any of my testcases. Bernd * haifa-sched.c (prune_ready_list): New function, broken out of schedule_block. (schedule_block): Use it. Index: gcc/haifa-sched.c =================================================================== --- gcc/haifa-sched.c.orig +++ gcc/haifa-sched.c @@ -2614,8 +2614,8 @@ max_issue (struct ready_list *ready, int { if (state_dead_lock_p (state) || insn_finishes_cycle_p (insn)) - /* We won't issue any more instructions in the next - choice_state. */ + /* We won't issue any more instructions in the next + choice_state. */ top->rest = 0; else top->rest--; @@ -2863,6 +2863,52 @@ commit_schedule (rtx prev_head, rtx tail VEC_truncate (rtx, scheduled_insns, 0); } +/* 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. */ + +static void +prune_ready_list (state_t temp_state, bool first_cycle_insn_p) +{ + int i; + + restart: + for (i = 0; i < ready.n_ready; i++) + { + rtx insn = ready_element (&ready, i); + int cost = 0; + const char *reason = "resource conflict"; + + if (recog_memoized (insn) < 0) + { + if (!first_cycle_insn_p + && (GET_CODE (PATTERN (insn)) == ASM_INPUT + || asm_noperands (PATTERN (insn)) >= 0)) + cost = 1; + reason = "asm"; + } + else if (flag_sched_pressure) + 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) + { + ready_remove (&ready, i); + queue_insn (insn, cost, reason); + goto restart; + } + } +} + /* Use forward list scheduling to rearrange insns of block pointed to by TARGET_BB, possibly bringing insns from subsequent blocks in the same region. */ @@ -3014,6 +3060,10 @@ schedule_block (basic_block *target_bb) } while (advance > 0); + prune_ready_list (temp_state, true); + if (ready.n_ready == 0) + continue; + if (sort_p) { /* Sort the ready list based on priority. */ @@ -3144,44 +3194,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, "resource conflict"); - 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)) @@ -3202,14 +3214,20 @@ schedule_block (basic_block *target_bb) /* Update counters, etc in the scheduler's front end. */ (*current_sched_info->begin_schedule_ready) (insn); - VEC_safe_push (rtx, heap, scheduled_insns, insn); + VEC_safe_push (rtx, heap, scheduled_insns, 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) + { + cost = state_transition (curr_state, insn); + if (!flag_sched_pressure) + gcc_assert (cost < 0); + cycle_issued_insns++; + asm_p = false; + } + else + asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT + || asm_noperands (PATTERN (insn)) >= 0); if (targetm.sched.variable_issue) can_issue_more = @@ -3230,6 +3248,9 @@ schedule_block (basic_block *target_bb) first_cycle_insn_p = false; + if (ready.n_ready > 0) + prune_ready_list (temp_state, false); + /* 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. */ @@ -3241,7 +3262,7 @@ schedule_block (basic_block *target_bb) if (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)) && (*current_sched_info->schedule_more_p) ()) { - while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0))) + while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0))) { insn = ready_remove_first (&ready); gcc_assert (DEBUG_INSN_P (insn));