| 
									
										
										
										
											2009-08-08 01:24:46 -04:00
										 |  |  | ! Copyright (C) 2009 Slava Pestov. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: accessors assocs combinators deques dlists fry kernel | 
					
						
							| 
									
										
										
										
											2009-08-08 21:02:56 -04:00
										 |  |  | namespaces sequences sets compiler.cfg compiler.cfg.predecessors ;
 | 
					
						
							| 
									
										
										
										
											2010-02-26 16:01:01 -05:00
										 |  |  | FROM: namespaces => set ;
 | 
					
						
							| 
									
										
										
										
											2009-08-08 01:24:46 -04:00
										 |  |  | IN: compiler.cfg.loop-detection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: natural-loop header index ends blocks ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: loops | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-13 21:26:44 -04:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-08 01:24:46 -04:00
										 |  |  | : <natural-loop> ( header index -- loop )
 | 
					
						
							|  |  |  |     H{ } clone H{ } clone natural-loop boa ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : lookup-header ( header -- loop )
 | 
					
						
							|  |  |  |     loops get [ | 
					
						
							|  |  |  |         loops get assoc-size <natural-loop> | 
					
						
							|  |  |  |     ] cache ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOLS: visited active ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : record-back-edge ( from to -- )
 | 
					
						
							|  |  |  |     lookup-header ends>> conjoin ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFER: find-loop-headers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : visit-edge ( from to -- )
 | 
					
						
							|  |  |  |     dup active get key?
 | 
					
						
							|  |  |  |     [ record-back-edge ] | 
					
						
							|  |  |  |     [ nip find-loop-headers ] | 
					
						
							|  |  |  |     if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : find-loop-headers ( bb -- )
 | 
					
						
							|  |  |  |     dup visited get key? [ drop ] [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             [ visited get conjoin ] | 
					
						
							|  |  |  |             [ active get conjoin ] | 
					
						
							|  |  |  |             [ dup successors>> [ visit-edge ] with each ] | 
					
						
							|  |  |  |             [ active get delete-at ] | 
					
						
							|  |  |  |         } cleave
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: work-list | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : process-loop-block ( bb loop -- )
 | 
					
						
							|  |  |  |     2dup blocks>> key? [ 2drop ] [ | 
					
						
							|  |  |  |         [ blocks>> conjoin ] [ | 
					
						
							|  |  |  |             2dup header>> eq? [ 2drop ] [ | 
					
						
							|  |  |  |                 drop predecessors>> work-list get push-all-front | 
					
						
							|  |  |  |             ] if
 | 
					
						
							|  |  |  |         ] 2bi
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : process-loop-ends ( loop -- )
 | 
					
						
							|  |  |  |     [ ends>> keys <dlist> [ push-all-front ] [ work-list set ] [ ] tri ] keep
 | 
					
						
							|  |  |  |     '[ _ process-loop-block ] slurp-deque ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : process-loop-headers ( -- )
 | 
					
						
							|  |  |  |     loops get values [ process-loop-ends ] each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: loop-nesting | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compute-loop-nesting ( -- )
 | 
					
						
							|  |  |  |     loops get H{ } clone [ | 
					
						
							|  |  |  |         [ values ] dip '[ blocks>> values [ _ inc-at ] each ] each
 | 
					
						
							|  |  |  |     ] keep loop-nesting set ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : detect-loops ( cfg -- cfg' )
 | 
					
						
							| 
									
										
										
										
											2009-08-08 21:02:56 -04:00
										 |  |  |     needs-predecessors | 
					
						
							| 
									
										
										
										
											2009-08-08 01:24:46 -04:00
										 |  |  |     H{ } clone loops set
 | 
					
						
							|  |  |  |     H{ } clone visited set
 | 
					
						
							|  |  |  |     H{ } clone active set
 | 
					
						
							|  |  |  |     H{ } clone loop-nesting set
 | 
					
						
							| 
									
										
										
										
											2009-08-08 21:02:56 -04:00
										 |  |  |     dup entry>> find-loop-headers process-loop-headers compute-loop-nesting ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : loop-nesting-at ( bb -- n ) loop-nesting get at 0 or ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-24 20:05:52 -04:00
										 |  |  | : current-loop-nesting ( -- n ) basic-block get loop-nesting-at ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-08 21:02:56 -04:00
										 |  |  | : needs-loops ( cfg -- cfg' )
 | 
					
						
							|  |  |  |     needs-predecessors | 
					
						
							| 
									
										
										
										
											2009-08-13 21:26:44 -04:00
										 |  |  |     dup loops-valid?>> [ detect-loops t >>loops-valid? ] unless ;
 |