| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | ! Copyright (C) 2009, 2010 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2014-12-13 19:10:21 -05:00
										 |  |  | USING: accessors arrays combinators combinators.short-circuit | 
					
						
							|  |  |  | compiler.cfg.dominance compiler.cfg.ssa.interference.live-ranges | 
					
						
							|  |  |  | kernel locals math math.order sequences sorting.slots ;
 | 
					
						
							| 
									
										
										
										
											2009-08-02 09:15:36 -04:00
										 |  |  | IN: compiler.cfg.ssa.interference | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | ! Interference testing using SSA properties. | 
					
						
							|  |  |  | !
 | 
					
						
							|  |  |  | ! Based on: | 
					
						
							|  |  |  | !
 | 
					
						
							|  |  |  | ! Revisiting Out-of-SSA Translation for Correctness, Code Quality, and Efficiency | 
					
						
							|  |  |  | ! http://hal.archives-ouvertes.fr/docs/00/34/99/25/PDF/OutSSA-RR.pdf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: vreg-info vreg value def-index bb pre-of color equal-anc-in equal-anc-out ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: <vreg-info> ( vreg value bb -- info )
 | 
					
						
							|  |  |  |     vreg-info new
 | 
					
						
							|  |  |  |         vreg >>vreg | 
					
						
							|  |  |  |         bb >>bb | 
					
						
							|  |  |  |         value >>value | 
					
						
							|  |  |  |         bb pre-of >>pre-of | 
					
						
							|  |  |  |         vreg bb def-index >>def-index ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | ! Our dominance pass computes dominance information on a | 
					
						
							|  |  |  | ! per-basic block level. Rig up a more fine-grained dominance | 
					
						
							|  |  |  | ! test here. | 
					
						
							|  |  |  | : locally-dominates? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     [ def-index>> ] bi@ < ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: vreg-dominates? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     vreg1 bb>> :> bb1 | 
					
						
							|  |  |  |     vreg2 bb>> :> bb2 | 
					
						
							|  |  |  |     bb1 bb2 eq?
 | 
					
						
							|  |  |  |     [ vreg1 vreg2 locally-dominates? ] [ bb1 bb2 dominates? ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Testing individual vregs for live range intersection. | 
					
						
							|  |  |  | : kill-after-def? ( vreg1 vreg2 bb -- ? )
 | 
					
						
							| 
									
										
										
										
											2009-07-28 07:48:20 -04:00
										 |  |  |     ! If first register is used after second one is defined, they interfere. | 
					
						
							|  |  |  |     ! If they are used in the same instruction, no interference. If the | 
					
						
							|  |  |  |     ! instruction is a def-is-use-insn, then there will be a use at +1 | 
					
						
							|  |  |  |     ! (instructions are 2 apart) and so outputs will interfere with | 
					
						
							|  |  |  |     ! inputs. | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  |     [ kill-index ] [ def-index ] bi-curry bi* > ;
 | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : interferes-first-dominates? ( vreg1 vreg2 -- ? )
 | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  |     ! If vreg1 dominates vreg2, then they interfere if vreg2's definition | 
					
						
							|  |  |  |     ! occurs before vreg1 is killed. | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  |     [ [ vreg>> ] bi@ ] [ nip bb>> ] 2bi kill-after-def? ;
 | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : interferes-second-dominates? ( vreg1 vreg2 -- ? )
 | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  |     ! If vreg2 dominates vreg1, then they interfere if vreg1's definition | 
					
						
							|  |  |  |     ! occurs before vreg2 is killed. | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  |     swap interferes-first-dominates? ;
 | 
					
						
							| 
									
										
										
										
											2009-07-26 22:11:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : interferes-same-block? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     ! If both are defined in the same basic block, they interfere if their | 
					
						
							|  |  |  |     ! local live ranges intersect. | 
					
						
							|  |  |  |     2dup locally-dominates? [ swap ] unless
 | 
					
						
							|  |  |  |     interferes-first-dominates? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: vregs-intersect? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     vreg1 bb>> :> bb1 | 
					
						
							|  |  |  |     vreg2 bb>> :> bb2 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         { [ bb1 bb2 eq? ] [ vreg1 vreg2 interferes-same-block? ] } | 
					
						
							|  |  |  |         { [ bb1 bb2 dominates? ] [ vreg1 vreg2 interferes-first-dominates? ] } | 
					
						
							|  |  |  |         { [ bb2 bb1 dominates? ] [ vreg1 vreg2 interferes-second-dominates? ] } | 
					
						
							|  |  |  |         [ f ] | 
					
						
							| 
									
										
										
										
											2009-07-27 01:31:21 -04:00
										 |  |  |     } cond ;
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | ! Value-based interference test. | 
					
						
							|  |  |  | : chain-intersect ( vreg1 vreg2 -- vreg )
 | 
					
						
							|  |  |  |     [ 2dup { [ nip ] [ vregs-intersect? not ] } 2&& ] | 
					
						
							|  |  |  |     [ equal-anc-in>> ] | 
					
						
							|  |  |  |     while nip ;
 | 
					
						
							| 
									
										
										
										
											2009-08-05 19:57:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : update-equal-anc-out ( vreg1 vreg2 -- )
 | 
					
						
							|  |  |  |     dupd chain-intersect >>equal-anc-out drop ;
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : same-sets? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     [ color>> ] bi@ eq? ;
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : same-values? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     [ value>> ] bi@ eq? ;
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : vregs-interfere? ( vreg1 vreg2 -- ? )
 | 
					
						
							|  |  |  |     [ f >>equal-anc-out ] dip
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     2dup same-sets? [ equal-anc-out>> ] when
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     2dup same-values? | 
					
						
							|  |  |  |     [ update-equal-anc-out f ] [ chain-intersect >boolean ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Merging lists of vregs sorted by dominance. | 
					
						
							|  |  |  | M: vreg-info <=> ( vreg1 vreg2 -- <=> )
 | 
					
						
							|  |  |  |     { { pre-of>> <=> } { def-index>> <=> } } compare-slots ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOLS: blue red ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: iterator seq n ;
 | 
					
						
							|  |  |  | : <iterator> ( seq -- iterator ) 0 iterator boa ; inline
 | 
					
						
							|  |  |  | : done? ( iterator -- ? ) [ seq>> length ] [ n>> ] bi = ; inline
 | 
					
						
							|  |  |  | : this ( iterator -- obj ) [ n>> ] [ seq>> ] bi nth ; inline
 | 
					
						
							|  |  |  | : ++ ( iterator -- ) [ 1 + ] change-n drop ; inline
 | 
					
						
							|  |  |  | : take ( iterator -- obj ) [ this ] [ ++ ] bi ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : blue-smaller? ( blue red -- ? )
 | 
					
						
							|  |  |  |     [ this ] bi@ before? ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : take-blue? ( blue red -- ? )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         [ nip done? ] | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 [ drop done? not ] | 
					
						
							|  |  |  |                 [ blue-smaller? ] | 
					
						
							|  |  |  |             } 2&& | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     } 2|| ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : merge-sets ( blue red -- seq )
 | 
					
						
							|  |  |  |     [ <iterator> ] bi@
 | 
					
						
							|  |  |  |     [ 2dup [ done? ] both? not ] | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         2dup take-blue? | 
					
						
							|  |  |  |         [ over take blue >>color ] | 
					
						
							|  |  |  |         [ dup take red >>color ] | 
					
						
							|  |  |  |         if
 | 
					
						
							|  |  |  |     ] produce 2nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : update-for-merge ( seq -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         dup [ equal-anc-in>> ] [ equal-anc-out>> ] bi
 | 
					
						
							|  |  |  |         2dup and [ [ vreg-dominates? ] most ] [ or ] if
 | 
					
						
							|  |  |  |         >>equal-anc-in | 
					
						
							|  |  |  |         drop
 | 
					
						
							|  |  |  |     ] each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Linear-time live range intersection test in a merged set. | 
					
						
							|  |  |  | : find-parent ( dom current -- vreg )
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  |     over empty? [ 2drop f ] [ | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  |         over last over vreg-dominates? | 
					
						
							|  |  |  |         [ drop last ] [ over pop* find-parent ] if
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | :: linear-interference-test ( seq -- ? )
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  |     V{ } clone :> dom | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  |     seq [| vreg | | 
					
						
							|  |  |  |         dom vreg find-parent | 
					
						
							|  |  |  |         { [ ] [ vreg same-sets? not ] [ vreg swap vregs-interfere? ] } 1&& | 
					
						
							|  |  |  |         [ t ] [ vreg dom push f ] if
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:26:52 -04:00
										 |  |  |     ] any? ;
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:35:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : sets-interfere-1? ( seq1 seq2 -- merged/f ? )
 | 
					
						
							|  |  |  |     [ first ] bi@
 | 
					
						
							|  |  |  |     2dup before? [ swap ] unless
 | 
					
						
							|  |  |  |     2dup same-values? [ | 
					
						
							|  |  |  |         2dup equal-anc-in<< | 
					
						
							|  |  |  |         2array f
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         2dup vregs-intersect? | 
					
						
							|  |  |  |         [ 2drop f t ] [ 2array f ] if
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-02 11:35:02 -04:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 05:49:41 -04:00
										 |  |  | : sets-interfere? ( seq1 seq2 -- merged/f ? )
 | 
					
						
							|  |  |  |     2dup [ length 1 = ] both? [ sets-interfere-1? ] [ | 
					
						
							|  |  |  |         merge-sets dup linear-interference-test | 
					
						
							|  |  |  |         [ drop f t ] [ dup update-for-merge f ] if
 | 
					
						
							| 
									
										
										
										
											2014-12-13 19:10:21 -05:00
										 |  |  |     ] if ;
 |