RFA: Enable multi-step transformation in peephole2
diff mbox

Message ID 20111030183151.w3ow66cmjwo40cc4-nzlynne@webmail.spamcop.net
State New
Headers show

Commit Message

Joern Rennecke Oct. 30, 2011, 10:31 p.m. UTC
Where there can be multiple things wrong with a pattern sequence,
performance-wise, and multiple things might be fixed up, depending
on factors like available registers, providing patterns for every
combination leads to combinatorial explosion.
It is simpler to describe the available transformations in simpler steps
that can be chained.  However, the peephole2 pass currently makes only a
single pass over a basic block.  With the attached patch, a peephole2 pattern
can set a new variable, peep2_rescan, to request that the current basic block
is re-scanned.
Bootstrapped and regtested on i686-pc-linux-gnu.

I've been using this mechanism for the Epiphany port to transform add
instructions generated by reload or later passes, which require expensive
flag register save/restore operations, and often have an unnecessary constant
load, into variants which are cheaper.
2011-10-30  Joern Rennecke <joern.rennecke@embecosm.com>

	* recog.c (peep2_rescan): New variable.
	(peephole2_optimize): Clear peep2_rescan at the start of each block.
	Loop if peep2_rescan is set at the end of processing a block.
	* recog.h (peep2_rescan): Declare.
	* doc/md.texi: Document peep2_rescan.

Patch
diff mbox

Index: doc/md.texi
===================================================================
--- doc/md.texi	(revision 180683)
+++ doc/md.texi	(working copy)
@@ -6872,6 +6872,20 @@  If we had not added the @code{(match_dup
 sequence, it might have been the case that the register we chose at the
 beginning of the sequence is killed by the first or second @code{set}.
 
+The @code{peephole2} pass usually scans each basic block only once.  If you
+have a @code{peephole2} pattern that, once applied, might enable other
+@code{peephole2} patterns to be matched, you can request to re-run the
+scan over the current basic block by setting the variable
+@code{peep2_rescan} to @code{true} in the @var{preparation-statements}
+of the @code{peephole2} pattern.
+You should be careful not to create infinite loops by doing this.
+E.g.  one technique to avoid loops is to have a cost function (as a concept
+to describe the pattern sequences, not necessarily actual code - although
+for complex designs, implementing it as actual code might help debugging
+ and/or implementation), and make sure that any @code{peephole2} pattern
+that sets @code{peep2_rescan} lowers this cost function, and no
+@code{peephole2} pattern increases this cost function.
+
 @end ifset
 @ifset INTERNALS
 @node Insn Attributes
Index: recog.c
===================================================================
--- recog.c	(revision 180683)
+++ recog.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* Subroutines used by or related to instruction recognition.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -3467,6 +3467,8 @@  peep2_fill_buffer (basic_block bb, rtx i
   return true;
 }
 
+bool peep2_rescan;
+
 /* Perform the peephole2 optimization pass.  */
 
 static void
@@ -3491,9 +3493,14 @@  peephole2_optimize (void)
 
   FOR_EACH_BB_REVERSE (bb)
     {
-      bool past_end = false;
+      bool past_end;
       int pos;
 
+    rescan_block:
+      peep2_rescan = false;
+
+      past_end = false;
+
       rtl_profile_for_bb (bb);
 
       /* Start up propagation.  */
@@ -3546,6 +3553,8 @@  peephole2_optimize (void)
 	  peep2_current = peep2_buf_position (peep2_current + 1);
 	  peep2_current_count--;
 	}
+      if (peep2_rescan)
+	goto rescan_block;
     }
 
   default_rtl_profile ();
Index: recog.h
===================================================================
--- recog.h	(revision 180683)
+++ recog.h	(working copy)
@@ -1,6 +1,6 @@ 
 /* Declarations for interface to insn recognizer and insn-output.c.
    Copyright (C) 1987, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -311,5 +311,6 @@  struct insn_data_d
 
 extern const struct insn_data_d insn_data[];
 extern int peep2_current_count;
+extern bool peep2_rescan;
 
 #endif /* GCC_RECOG_H */