From patchwork Thu Apr 4 16:30:51 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Bosscher X-Patchwork-Id: 233873 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 2F2E02C00A7 for ; Fri, 5 Apr 2013 03:31:50 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:cc:content-type; q=dns; s=default; b=ESqt0jO6aX642B1fTibnThijPn1vq1L9GH5r/vJGwor V45a950LQe0QjO2cNwl1FCk5PzzY+EInXzbgJiyeVVePZ0dxOdZMJPwENuCTQg7C Bnqqcp1BmGCDpFdMJqUyix7eNz9wBhwhMMAM8TuHLa0lKK0EJNr/HaSybse9Qn4w = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:cc:content-type; s=default; bh=uV7QqZGzaJd7pruf/iVYn33715Q=; b=SR77T7roW5x8gMsIo xPkHEs2zscKDhQifrs3zpe60hU1GDg+OukIIkVwLgdB7gIzyyllx+ZU79VnNz5D/ ySrbTNuUgdWGWcd0B63GBxHiCxCCswLWhd5KNylgPYZB4KXZ9abgpA8sKMPCWFKL dvkAaARuNOhFtXsLEnVC5sv2jo= Received: (qmail 25427 invoked by alias); 4 Apr 2013 16:31:39 -0000 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 Received: (qmail 25418 invoked by uid 89); 4 Apr 2013 16:31:39 -0000 X-Spam-SWARE-Status: No, score=-4.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, TW_FN autolearn=ham version=3.3.1 Received: from mail-ve0-f180.google.com (HELO mail-ve0-f180.google.com) (209.85.128.180) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 04 Apr 2013 16:31:33 +0000 Received: by mail-ve0-f180.google.com with SMTP id c13so2762264vea.25 for ; Thu, 04 Apr 2013 09:31:32 -0700 (PDT) X-Received: by 10.52.164.166 with SMTP id yr6mr4582034vdb.37.1365093091866; Thu, 04 Apr 2013 09:31:31 -0700 (PDT) MIME-Version: 1.0 Received: by 10.58.68.228 with HTTP; Thu, 4 Apr 2013 09:30:51 -0700 (PDT) From: Steven Bosscher Date: Thu, 4 Apr 2013 18:30:51 +0200 Message-ID: Subject: [patch][sparc] remove sparc machine_reorg, add machine specifc pass after delayed-branch scheduling To: GCC Patches Cc: Eric Botcazou , Jakub Jelinek X-Virus-Found: No Hello, This patch removes a dbr_schedule() call from the sparc back end, and plugs in a sparc-specific pass that needs the insn chain in delayed-branch scheduled form after pass_delay_slots. This is essentially the same patch as the one I posted yesterday (http://gcc.gnu.org/ml/gcc-patches/2013-04/msg00197.html) but with a few fixes so that bootstrap+regtest actually passes :-) The purpose of this patch is to make a step towards passing verify_flow_info after pass_machine_reorg. Currently bug middle-end/43631 is a blocker for this, but with a few hacks around that bug, a few ports already can run and pass verify_flow_info after their machine reorg. Bootstrapped and tested on sparc64-unknown-linux-gnu. OK for trunk? Ciao! Steven * config/sparc/sparc.c: Include tree-pass.h. (TARGET_MACHINE_DEPENDENT_REORG): Do not redefine. (sparc_reorg): Rename to sparc_do_work_around_errata. Move to head of file. Change return type. Split off gate function. (sparc_gate_work_around_errata): New function. (pass_work_around_errata): New pass definition. (insert_pass_work_around_errata) New pass insert definition to insert pass_work_around_errata just after delayed-branch scheduling. (sparc_option_override): Insert the pass. Index: config/sparc/sparc.c =================================================================== --- config/sparc/sparc.c (revision 197452) +++ config/sparc/sparc.c (working copy) @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "df.h" #include "opts.h" +#include "tree-pass.h" /* Processor costs */ @@ -538,7 +539,6 @@ static void sparc_output_mi_thunk (FILE *, tree, H HOST_WIDE_INT, tree); static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT, const_tree); -static void sparc_reorg (void); static struct machine_function * sparc_init_machine_status (void); static bool sparc_cannot_force_const_mem (enum machine_mode, rtx); static rtx sparc_tls_get_addr (void); @@ -680,9 +680,6 @@ char sparc_hard_reg_printed[8]; #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg - #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS sparc_rtx_costs #undef TARGET_ADDRESS_COST @@ -804,6 +801,136 @@ char sparc_hard_reg_printed[8]; struct gcc_target targetm = TARGET_INITIALIZER; +/* We use the machine specific reorg pass to enable workarounds for errata. + We need to have the (essentially) final form of the insn stream in order + to properly detect the various hazards. Therefore, this machine specific + pass runs as late as possible. The pass is inserted in the pass pipeline + at the end of sparc_options_override(). */ + +static bool +sparc_gate_work_around_errata (void) +{ + /* The only erratum we handle for now is that of the AT697F processor. */ + return sparc_fix_at697f != 0; +} + +static unsigned int +sparc_do_work_around_errata (void) +{ + rtx insn, next; + + /* Now look for specific patterns in the insn stream. */ + for (insn = get_insns (); insn; insn = next) + { + bool insert_nop = false; + rtx set; + + /* Look for a single-word load into an odd-numbered FP register. */ + if (NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 + && MEM_P (SET_SRC (set)) + && REG_P (SET_DEST (set)) + && REGNO (SET_DEST (set)) > 31 + && REGNO (SET_DEST (set)) % 2 != 0) + { + /* The wrong dependency is on the enclosing double register. */ + unsigned int x = REGNO (SET_DEST (set)) - 1; + unsigned int src1, src2, dest; + int code; + + /* If the insn has a delay slot, then it cannot be problematic. */ + next = next_active_insn (insn); + if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE) + code = -1; + else + { + extract_insn (next); + code = INSN_CODE (next); + } + + switch (code) + { + case CODE_FOR_adddf3: + case CODE_FOR_subdf3: + case CODE_FOR_muldf3: + case CODE_FOR_divdf3: + dest = REGNO (recog_data.operand[0]); + src1 = REGNO (recog_data.operand[1]); + src2 = REGNO (recog_data.operand[2]); + if (src1 != src2) + { + /* Case [1-4]: + ld [address], %fx+1 + FPOPd %f{x,y}, %f{y,x}, %f{x,y} */ + if ((src1 == x || src2 == x) + && (dest == src1 || dest == src2)) + insert_nop = true; + } + else + { + /* Case 5: + ld [address], %fx+1 + FPOPd %fx, %fx, %fx */ + if (src1 == x + && dest == src1 + && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3)) + insert_nop = true; + } + break; + + case CODE_FOR_sqrtdf2: + dest = REGNO (recog_data.operand[0]); + src1 = REGNO (recog_data.operand[1]); + /* Case 6: + ld [address], %fx+1 + fsqrtd %fx, %fx */ + if (src1 == x && dest == src1) + insert_nop = true; + break; + + default: + break; + } + } + else + next = NEXT_INSN (insn); + + if (insert_nop) + emit_insn_after (gen_nop (), insn); + } + return 0; +} + +struct rtl_opt_pass pass_work_around_errata = +{ + { + RTL_PASS, + "errata", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + sparc_gate_work_around_errata, /* gate */ + sparc_do_work_around_errata, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_MACH_DEP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_verify_rtl_sharing, /* todo_flags_finish */ + } +}; + +struct register_pass_info insert_pass_work_around_errata = +{ + &pass_work_around_errata.pass, /* pass */ + "dbr", /* reference_pass_name */ + 1, /* ref_pass_instance_number */ + PASS_POS_INSERT_AFTER /* po_op */ +}; + +/* Helpers for TARGET_DEBUG_OPTIONS. */ static void dump_target_flag_bits (const int flags) { @@ -1241,6 +1368,13 @@ sparc_option_override (void) pessimizes for double floating-point registers. */ if (!global_options_set.x_flag_ira_share_save_slots) flag_ira_share_save_slots = 0; + + /* We register a machine specific pass to work around errata, if any. + The pass mut be scheduled as late as possible so that we have the + (essentially) final form of the insn stream to work on. + Registering the pass must be done at start up. It's convenient to + do it here. */ + register_pass (&insert_pass_work_around_errata); } /* Miscellaneous utilities. */ @@ -10894,107 +11028,6 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl return (vcall_offset >= -32768 || ! fixed_regs[5]); } -/* We use the machine specific reorg pass to enable workarounds for errata. */ - -static void -sparc_reorg (void) -{ - rtx insn, next; - - /* The only erratum we handle for now is that of the AT697F processor. */ - if (!sparc_fix_at697f) - return; - - /* We need to have the (essentially) final form of the insn stream in order - to properly detect the various hazards. Run delay slot scheduling. */ - if (optimize > 0 && flag_delayed_branch) - { - cleanup_barriers (); - dbr_schedule (get_insns ()); - } - - /* Now look for specific patterns in the insn stream. */ - for (insn = get_insns (); insn; insn = next) - { - bool insert_nop = false; - rtx set; - - /* Look for a single-word load into an odd-numbered FP register. */ - if (NONJUMP_INSN_P (insn) - && (set = single_set (insn)) != NULL_RTX - && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4 - && MEM_P (SET_SRC (set)) - && REG_P (SET_DEST (set)) - && REGNO (SET_DEST (set)) > 31 - && REGNO (SET_DEST (set)) % 2 != 0) - { - /* The wrong dependency is on the enclosing double register. */ - unsigned int x = REGNO (SET_DEST (set)) - 1; - unsigned int src1, src2, dest; - int code; - - /* If the insn has a delay slot, then it cannot be problematic. */ - next = next_active_insn (insn); - if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE) - code = -1; - else - { - extract_insn (next); - code = INSN_CODE (next); - } - - switch (code) - { - case CODE_FOR_adddf3: - case CODE_FOR_subdf3: - case CODE_FOR_muldf3: - case CODE_FOR_divdf3: - dest = REGNO (recog_data.operand[0]); - src1 = REGNO (recog_data.operand[1]); - src2 = REGNO (recog_data.operand[2]); - if (src1 != src2) - { - /* Case [1-4]: - ld [address], %fx+1 - FPOPd %f{x,y}, %f{y,x}, %f{x,y} */ - if ((src1 == x || src2 == x) - && (dest == src1 || dest == src2)) - insert_nop = true; - } - else - { - /* Case 5: - ld [address], %fx+1 - FPOPd %fx, %fx, %fx */ - if (src1 == x - && dest == src1 - && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3)) - insert_nop = true; - } - break; - - case CODE_FOR_sqrtdf2: - dest = REGNO (recog_data.operand[0]); - src1 = REGNO (recog_data.operand[1]); - /* Case 6: - ld [address], %fx+1 - fsqrtd %fx, %fx */ - if (src1 == x && dest == src1) - insert_nop = true; - break; - - default: - break; - } - } - else - next = NEXT_INSN (insn); - - if (insert_nop) - emit_insn_after (gen_nop (), insn); - } -} - /* How to allocate a 'struct machine_function'. */ static struct machine_function *