120 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Factor
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Factor
		
	
	
		
			Executable File
		
	
| ! Copyright (C) 2004, 2008 Slava Pestov.
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| USING: arrays generic assocs inference inference.class
 | |
| inference.dataflow inference.backend inference.state io kernel
 | |
| math namespaces sequences vectors words quotations hashtables
 | |
| combinators classes optimizer.def-use ;
 | |
| IN: optimizer.backend
 | |
| 
 | |
| SYMBOL: class-substitutions
 | |
| 
 | |
| SYMBOL: literal-substitutions
 | |
| 
 | |
| SYMBOL: value-substitutions
 | |
| 
 | |
| SYMBOL: optimizer-changed
 | |
| 
 | |
| GENERIC: optimize-node* ( node -- node/t changed? )
 | |
| 
 | |
| : ?union ( assoc/f assoc -- hash )
 | |
|     over [ union ] [ nip ] if ;
 | |
| 
 | |
| : add-node-literals ( assoc node -- )
 | |
|     over assoc-empty? [
 | |
|         2drop
 | |
|     ] [
 | |
|         [ node-literals ?union ] keep set-node-literals
 | |
|     ] if ;
 | |
| 
 | |
| : add-node-classes ( assoc node -- )
 | |
|     over assoc-empty? [
 | |
|         2drop
 | |
|     ] [
 | |
|         [ node-classes ?union ] keep set-node-classes
 | |
|     ] if ;
 | |
| 
 | |
| : substitute-values ( assoc node -- )
 | |
|     over assoc-empty? [
 | |
|         2drop
 | |
|     ] [
 | |
|         2dup node-in-d swap substitute-here
 | |
|         2dup node-in-r swap substitute-here
 | |
|         2dup node-out-d swap substitute-here
 | |
|         node-out-r swap substitute-here
 | |
|     ] if ;
 | |
| 
 | |
| : perform-substitutions ( node -- )
 | |
|     class-substitutions get over add-node-classes
 | |
|     literal-substitutions get over add-node-literals
 | |
|     value-substitutions get swap substitute-values ;
 | |
| 
 | |
| DEFER: optimize-nodes
 | |
| 
 | |
| : optimize-children ( node -- )
 | |
|     [ optimize-nodes ] change-children ;
 | |
| 
 | |
| : optimize-node ( node -- node )
 | |
|     dup [
 | |
|         dup perform-substitutions
 | |
|         dup optimize-node* [
 | |
|             nip optimizer-changed on optimize-node
 | |
|         ] [
 | |
|             dup t eq? [
 | |
|                 drop dup optimize-children
 | |
|             ] [
 | |
|                 nip optimize-node
 | |
|             ] if
 | |
|         ] if
 | |
|     ] when ;
 | |
| 
 | |
| : optimize-nodes ( node -- newnode )
 | |
|     [
 | |
|         class-substitutions [ clone ] change
 | |
|         literal-substitutions [ clone ] change
 | |
|         [ optimize-node ] transform-nodes
 | |
|         optimizer-changed get
 | |
|     ] with-scope optimizer-changed set ;
 | |
| 
 | |
| M: node optimize-node* drop t f ;
 | |
| 
 | |
| ! Post-inlining cleanup
 | |
| : follow ( key assoc -- value )
 | |
|     2dup at* [ swap follow nip ] [ 2drop ] if ;
 | |
| 
 | |
| : union* ( assoc1 assoc2 -- assoc )
 | |
|     union [ keys ] keep
 | |
|     [ dupd follow ] curry
 | |
|     H{ } map>assoc ;
 | |
| 
 | |
| : update* ( assoc1 assoc2 -- )
 | |
|     #! Not very efficient.
 | |
|     dupd union* update ;
 | |
| 
 | |
| : compute-value-substitutions ( #return/#values #call/#merge -- assoc )
 | |
|     node-out-d swap node-in-d 2array unify-lengths flip
 | |
|     [ = not ] assoc-subset >hashtable ;
 | |
| 
 | |
| : cleanup-inlining ( #return/#values -- newnode changed? )
 | |
|     dup node-successor dup [
 | |
|         class-substitutions get pick node-classes update
 | |
|         literal-substitutions get pick node-literals update
 | |
|         tuck compute-value-substitutions value-substitutions get swap update*
 | |
|         node-successor t
 | |
|     ] [
 | |
|         2drop t f
 | |
|     ] if ;
 | |
| 
 | |
| ! #return
 | |
| M: #return optimize-node* cleanup-inlining ;
 | |
| 
 | |
| ! #values
 | |
| M: #values optimize-node* cleanup-inlining ;
 | |
| 
 | |
| M: f set-node-successor 2drop ;
 | |
| 
 | |
| : splice-node ( old new -- )
 | |
|     dup splice-def-use last-node set-node-successor ;
 | |
| 
 | |
| : drop-inputs ( node -- #shuffle )
 | |
|     node-in-d clone \ #shuffle in-node ;
 |