From: Steven Bosscher <stevenb.gcc@gmail.com>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Cc: Eric Botcazou <ebotcazou@adacore.com>, Jakub Jelinek <jakub@redhat.com>
Subject: [patch][sparc] remove sparc machine_reorg, add machine specifc pass after delayed-branch scheduling
Date: Thu, 04 Apr 2013 19:54:00 -0000 [thread overview]
Message-ID: <CABu31nODCigYMtUsynY-3U_EmnkSLAWDK_vZA+acrGtFo70kgQ@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 742 bytes --]
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
[-- Attachment #2: sparc_errata_as_machine_pass.diff.txt --]
[-- Type: text/plain, Size: 8884 bytes --]
* 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);
}
\f
/* 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 *
next reply other threads:[~2013-04-04 16:31 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-04 19:54 Steven Bosscher [this message]
2013-04-09 10:45 ` Eric Botcazou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CABu31nODCigYMtUsynY-3U_EmnkSLAWDK_vZA+acrGtFo70kgQ@mail.gmail.com \
--to=stevenb.gcc@gmail.com \
--cc=ebotcazou@adacore.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).