* RE: [Patch] bfin: move loop invariants out of loop
@ 2011-03-31 14:28 Henderson, Stuart
2011-03-31 15:31 ` Bernd Schmidt
0 siblings, 1 reply; 4+ messages in thread
From: Henderson, Stuart @ 2011-03-31 14:28 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 614 bytes --]
New version of previous patch. Apologies.
Stu
-----Original Message-----
From: Henderson, Stuart
Sent: 31 March 2011 12:20
To: gcc-patches@gcc.gnu.org
Subject: [Patch] bfin: move loop invariants out of loop
The attached patch attempts to move loop invariants out of loops for Blackfin.
2011-03-31 Stuart Henderson <stuart.henderson@analog.com>
From Bernd Schmidt
* config/bfin/bfin.c (bfin_gen_bundles): Don't try to bundle a jump.
(bfin_optimize_loops_1, move_loop_constants): New static functions.
(bfin_reorg): Call bfin_optimize_loops_1 if optimizing.
Thanks,
Stu
[-- Attachment #2: upstream.patch --]
[-- Type: application/octet-stream, Size: 4877 bytes --]
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c (revision 171215)
+++ gcc/config/bfin/bfin.c (working copy)
@@ -53,6 +53,8 @@
#include "gt-bfin.h"
#include "basic-block.h"
#include "cfglayout.h"
+#include "cfgloop.h"
+#include "sched-int.h"
#include "timevar.h"
#include "df.h"
#include "sel-sched.h"
@@ -4794,6 +4796,150 @@
}
splitting_loops = 0;
}
+
+/* Subroutine of move_loop_constants, called through note_stores. */
+static void
+forget_known_values (rtx x, const_rtx pat, void *data)
+{
+ rtx *known_value = (rtx *)data;
+ int nregs;
+ if (!REG_P (x))
+ return;
+ nregs = HARD_REGNO_NREGS (REGNO (x), GET_MODE (x));
+ while (nregs-- > 0)
+ known_value[REGNO (x) + nregs] = const0_rtx;
+}
+
+/* For LOOP, whose body is recorded in BODY, try to move loop invariants
+ out of the loop. */
+static void
+move_loop_constants (struct loop *loop, basic_block *body)
+{
+ unsigned i;
+ rtx known_value[FIRST_PSEUDO_REGISTER];
+ edge ph_edge;
+ edge_iterator ei;
+
+ if (EDGE_COUNT (loop->header->preds) != 2)
+ return;
+
+ FOR_EACH_EDGE (ph_edge, ei, loop->header->preds)
+ if (ph_edge->src != loop->latch)
+ break;
+
+ memset (known_value, 0, sizeof known_value);
+
+ for (i = 0; i < loop->num_nodes; i++)
+ {
+ basic_block bb = body[i];
+ rtx insn;
+
+ for (insn = BB_HEAD (bb);
+ insn != NEXT_INSN (BB_END (bb));
+ insn = NEXT_INSN (insn))
+ {
+ rtx set, note;
+
+ if (CALL_P (insn))
+ {
+ rtx link, reg, op;
+ unsigned j;
+ note_stores (PATTERN (insn), forget_known_values, known_value);
+
+ for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+ if (call_used_regs[j])
+ known_value[j] = const0_rtx;
+
+ for (link = CALL_INSN_FUNCTION_USAGE (insn);
+ link;
+ link = XEXP (link, 1))
+ {
+ if (GET_CODE (op = XEXP (link, 0)) == CLOBBER
+ && REG_P (reg = XEXP (op, 0)))
+ known_value[REGNO (reg)] = const0_rtx;
+ }
+ continue;
+ }
+
+ if (!INSN_P (insn))
+ continue;
+
+ set = single_set (insn);
+ if (!set || !REG_P (SET_DEST (set))
+ || GET_MODE_SIZE (GET_MODE (SET_DEST (set))) > UNITS_PER_WORD)
+ note_stores (PATTERN (insn), forget_known_values, known_value);
+ else
+ {
+ unsigned regno = REGNO (SET_DEST (set));
+ if (known_value[regno] != NULL_RTX)
+ known_value[regno] = const0_rtx;
+ else
+ known_value[regno] = insn;
+ }
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0)))
+ {
+ known_value[REGNO (XEXP (note, 0))] = const0_rtx;
+ }
+ }
+ }
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ rtx insn, src;
+
+ insn = known_value[i];
+ if (insn == NULL_RTX || insn == const0_rtx)
+ continue;
+
+ src = SET_SRC (single_set (insn));
+ if (!CONSTANT_P (src))
+ continue;
+ if (REGNO_REG_SET_P (df_get_live_in (loop->header), i))
+ continue;
+
+ insert_insn_on_edge (PATTERN (insn), ph_edge);
+ delete_insn (insn);
+ }
+}
+
+/* First set of loop optimizations performed during the machine_reorg pass.
+ This tries to move constant loads generated by reload out of loops. */
+static void
+bfin_optimize_loops_1 (FILE *dump_file)
+{
+ struct loop * loop;
+ loop_iterator li;
+
+ if (current_function_calls_setjmp)
+ return;
+
+ /* Without LOOPS_MAY_HAVE_MULTIPLE_LATCHES, extra unnecessary jumps are
+ created which we'd have to clean up again later. */
+ loop_optimizer_init (LOOPS_HAVE_RECORDED_EXITS
+ | LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+ if (number_of_loops () <= 1)
+ {
+ loop_optimizer_finalize ();
+ return; /* There are no loops to schedule. */
+ }
+
+ df_analyze ();
+
+ FOR_EACH_LOOP (li, loop, 0)
+ {
+ basic_block *body = get_loop_body (loop);
+
+ move_loop_constants (loop, body);
+
+ free (body);
+ }
+
+ commit_edge_insertions ();
+
+ loop_optimizer_finalize ();
+ free_dominance_info (CDI_DOMINATORS);
+}
\f
/* Possibly generate a SEQUENCE out of three insns found in SLOT.
Returns true if we modified the insn chain, false otherwise. */
@@ -4911,7 +5057,8 @@
/* BB_END can change due to emitting extra NOPs, so check here. */
at_end = insn == BB_END (bb);
- if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
+ if (delete_this == NULL_RTX
+ && (at_end || GET_MODE (next) == TImode || JUMP_P (next)))
{
if ((n_filled < 2
|| !gen_one_bundle (slot))
@@ -5502,6 +5649,9 @@
with old MDEP_REORGS that are not CFG based. Recompute it now. */
compute_bb_for_insn ();
+ if (optimize)
+ bfin_optimize_loops_1 (dump_file);
+
if (bfin_flag_schedule_insns2)
{
splitting_for_sched = 1;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch] bfin: move loop invariants out of loop
2011-03-31 14:28 [Patch] bfin: move loop invariants out of loop Henderson, Stuart
@ 2011-03-31 15:31 ` Bernd Schmidt
2011-04-04 10:20 ` Henderson, Stuart
0 siblings, 1 reply; 4+ messages in thread
From: Bernd Schmidt @ 2011-03-31 15:31 UTC (permalink / raw)
To: Henderson, Stuart; +Cc: gcc-patches
On 03/31/2011 04:16 PM, Henderson, Stuart wrote:
> The attached patch attempts to move loop invariants out of loops for Blackfin.
>
>
> 2011-03-31 Stuart Henderson <stuart.henderson@analog.com>
>
> From Bernd Schmidt
> * config/bfin/bfin.c (bfin_gen_bundles): Don't try to bundle a jump.
> (bfin_optimize_loops_1, move_loop_constants): New static functions.
> (bfin_reorg): Call bfin_optimize_loops_1 if optimizing.
I kind of want to do this kind of thing as part of postreload,
especially since I recently discovered that we have a cprop pass after
loop_invariant that tends to undo all the loop invariant motion.
Bernd
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [Patch] bfin: move loop invariants out of loop
2011-03-31 15:31 ` Bernd Schmidt
@ 2011-04-04 10:20 ` Henderson, Stuart
0 siblings, 0 replies; 4+ messages in thread
From: Henderson, Stuart @ 2011-04-04 10:20 UTC (permalink / raw)
To: Bernd Schmidt; +Cc: gcc-patches
Do you mean you plan to implement a generic solution in postreload?
I have no objections to dropping this in that case. I'll carry on using the patch in our local 4.5 release (for what it's worth).
-----Original Message-----
From: Bernd Schmidt [mailto:bernds@codesourcery.com]
Sent: 31 March 2011 16:21
To: Henderson, Stuart
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [Patch] bfin: move loop invariants out of loop
On 03/31/2011 04:16 PM, Henderson, Stuart wrote:
> The attached patch attempts to move loop invariants out of loops for Blackfin.
>
>
> 2011-03-31 Stuart Henderson <stuart.henderson@analog.com>
>
> From Bernd Schmidt
> * config/bfin/bfin.c (bfin_gen_bundles): Don't try to bundle a jump.
> (bfin_optimize_loops_1, move_loop_constants): New static functions.
> (bfin_reorg): Call bfin_optimize_loops_1 if optimizing.
I kind of want to do this kind of thing as part of postreload,
especially since I recently discovered that we have a cprop pass after
loop_invariant that tends to undo all the loop invariant motion.
Bernd
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Patch] bfin: move loop invariants out of loop
@ 2011-03-31 11:39 Henderson, Stuart
0 siblings, 0 replies; 4+ messages in thread
From: Henderson, Stuart @ 2011-03-31 11:39 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 393 bytes --]
The attached patch attempts to move loop invariants out of loops for Blackfin.
2011-03-31 Stuart Henderson <stuart.henderson@analog.com>
From Bernd Schmidt
* config/bfin/bfin.c (bfin_gen_bundles): Don't try to bundle a jump.
(bfin_optimize_loops_1, move_loop_constants): New static functions.
(bfin_reorg): Call bfin_optimize_loops_1 if optimizing.
Thanks,
Stu
[-- Attachment #2: upstream.patch --]
[-- Type: application/octet-stream, Size: 4824 bytes --]
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c (revision 171215)
+++ gcc/config/bfin/bfin.c (working copy)
@@ -53,6 +53,8 @@
#include "gt-bfin.h"
#include "basic-block.h"
#include "cfglayout.h"
+#include "cfgloop.h"
+#include "sched-int.h"
#include "timevar.h"
#include "df.h"
#include "sel-sched.h"
@@ -4794,6 +4796,147 @@
}
splitting_loops = 0;
}
+
+/* Subroutine of move_loop_constants, called through note_stores. */
+static void
+forget_known_values (rtx x, const_rtx pat, void *data)
+{
+ rtx *known_value = (rtx *)data;
+ int nregs;
+ if (!REG_P (x))
+ return;
+ nregs = HARD_REGNO_NREGS (REGNO (x), GET_MODE (x));
+ while (nregs-- > 0)
+ known_value[REGNO (x) + nregs] = const0_rtx;
+}
+
+/* For LOOP, whose body is recorded in BODY, try to move loop invariants
+ out of the loop. */
+static void
+move_loop_constants (struct loop *loop, basic_block *body)
+{
+ unsigned i;
+ rtx known_value[FIRST_PSEUDO_REGISTER];
+ edge ph_edge;
+ edge_iterator ei;
+
+ if (EDGE_COUNT (loop->header->preds) != 2)
+ return;
+
+ FOR_EACH_EDGE (ph_edge, ei, loop->header->preds)
+ if (ph_edge->src != loop->latch)
+ break;
+
+ memset (known_value, 0, sizeof known_value);
+
+ for (i = 0; i < loop->num_nodes; i++)
+ {
+ basic_block bb = body[i];
+ rtx insn;
+
+ for (insn = BB_HEAD (bb);
+ insn != NEXT_INSN (BB_END (bb));
+ insn = NEXT_INSN (insn))
+ {
+ rtx set, note;
+
+ if (CALL_P (insn))
+ {
+ rtx link, reg, op;
+ unsigned j;
+ note_stores (PATTERN (insn), forget_known_values, known_value);
+
+ for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+ if (call_used_regs[j])
+ known_value[j] = const0_rtx;
+
+ for (link = CALL_INSN_FUNCTION_USAGE (insn);
+ link;
+ link = XEXP (link, 1))
+ {
+ if (GET_CODE (op = XEXP (link, 0)) == CLOBBER
+ && REG_P (reg = XEXP (op, 0)))
+ known_value[REGNO (reg)] = const0_rtx;
+ }
+ continue;
+ }
+
+ if (!INSN_P (insn))
+ continue;
+
+ set = single_set (insn);
+ if (!set || !REG_P (SET_DEST (set))
+ || GET_MODE_SIZE (GET_MODE (SET_DEST (set))) > UNITS_PER_WORD)
+ note_stores (PATTERN (insn), forget_known_values, known_value);
+ else
+ {
+ unsigned regno = REGNO (SET_DEST (set));
+ if (known_value[regno] != NULL_RTX)
+ known_value[regno] = const0_rtx;
+ else
+ known_value[regno] = insn;
+ }
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0)))
+ {
+ known_value[REGNO (XEXP (note, 0))] = const0_rtx;
+ }
+ }
+ }
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ rtx insn, src;
+
+ insn = known_value[i];
+ if (insn == NULL_RTX || insn == const0_rtx)
+ continue;
+
+ src = SET_SRC (single_set (insn));
+ if (!CONSTANT_P (src))
+ continue;
+ if (REGNO_REG_SET_P (df_get_live_in (loop->header), i))
+ continue;
+
+ insert_insn_on_edge (PATTERN (insn), ph_edge);
+ delete_insn (insn);
+ }
+}
+
+/* First set of loop optimizations performed during the machine_reorg pass.
+ This tries to move constant loads generated by reload out of loops. */
+static void
+bfin_optimize_loops_1 (FILE *dump_file)
+{
+ struct loop * loop;
+ loop_iterator li;
+
+ /* Without LOOPS_MAY_HAVE_MULTIPLE_LATCHES, extra unnecessary jumps are
+ created which we'd have to clean up again later. */
+ loop_optimizer_init (LOOPS_HAVE_RECORDED_EXITS
+ | LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+ if (number_of_loops () <= 1)
+ {
+ loop_optimizer_finalize ();
+ return; /* There are no loops to schedule. */
+ }
+
+ df_analyze ();
+
+ FOR_EACH_LOOP (li, loop, 0)
+ {
+ basic_block *body = get_loop_body (loop);
+
+ move_loop_constants (loop, body);
+
+ free (body);
+ }
+
+ commit_edge_insertions ();
+
+ loop_optimizer_finalize ();
+ free_dominance_info (CDI_DOMINATORS);
+}
\f
/* Possibly generate a SEQUENCE out of three insns found in SLOT.
Returns true if we modified the insn chain, false otherwise. */
@@ -4911,7 +5054,8 @@
/* BB_END can change due to emitting extra NOPs, so check here. */
at_end = insn == BB_END (bb);
- if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
+ if (delete_this == NULL_RTX
+ && (at_end || GET_MODE (next) == TImode || JUMP_P (next)))
{
if ((n_filled < 2
|| !gen_one_bundle (slot))
@@ -5502,6 +5646,9 @@
with old MDEP_REORGS that are not CFG based. Recompute it now. */
compute_bb_for_insn ();
+ if (optimize)
+ bfin_optimize_loops_1 (dump_file);
+
if (bfin_flag_schedule_insns2)
{
splitting_for_sched = 1;
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-04-04 10:20 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-31 14:28 [Patch] bfin: move loop invariants out of loop Henderson, Stuart
2011-03-31 15:31 ` Bernd Schmidt
2011-04-04 10:20 ` Henderson, Stuart
-- strict thread matches above, loose matches on Subject: below --
2011-03-31 11:39 Henderson, Stuart
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).