public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* 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).