compiler.cfg.coalescing: precompute live intervals, add support for instructions where output cannot equal an input, split critical edges
							parent
							
								
									e8cf50ac3e
								
							
						
					
					
						commit
						3cc71a1934
					
				| 
						 | 
					@ -7,10 +7,12 @@ compiler.cfg.def-use
 | 
				
			||||||
compiler.cfg.utilities
 | 
					compiler.cfg.utilities
 | 
				
			||||||
compiler.cfg.dominance
 | 
					compiler.cfg.dominance
 | 
				
			||||||
compiler.cfg.instructions
 | 
					compiler.cfg.instructions
 | 
				
			||||||
 | 
					compiler.cfg.critical-edges
 | 
				
			||||||
compiler.cfg.coalescing.state
 | 
					compiler.cfg.coalescing.state
 | 
				
			||||||
compiler.cfg.coalescing.forest
 | 
					compiler.cfg.coalescing.forest
 | 
				
			||||||
compiler.cfg.coalescing.copies
 | 
					compiler.cfg.coalescing.copies
 | 
				
			||||||
compiler.cfg.coalescing.renaming
 | 
					compiler.cfg.coalescing.renaming
 | 
				
			||||||
 | 
					compiler.cfg.coalescing.live-ranges
 | 
				
			||||||
compiler.cfg.coalescing.process-blocks ;
 | 
					compiler.cfg.coalescing.process-blocks ;
 | 
				
			||||||
IN: compiler.cfg.coalescing
 | 
					IN: compiler.cfg.coalescing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,9 +51,11 @@ SYMBOL: seen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
: coalesce ( cfg -- cfg' )
 | 
					: coalesce ( cfg -- cfg' )
 | 
				
			||||||
    init-coalescing
 | 
					    init-coalescing
 | 
				
			||||||
 | 
					    dup split-critical-edges
 | 
				
			||||||
    dup compute-def-use
 | 
					    dup compute-def-use
 | 
				
			||||||
    dup compute-dominance
 | 
					    dup compute-dominance
 | 
				
			||||||
    dup compute-dfs
 | 
					    dup compute-dfs
 | 
				
			||||||
 | 
					    dup compute-live-ranges
 | 
				
			||||||
    dup process-blocks
 | 
					    dup process-blocks
 | 
				
			||||||
    break-interferences
 | 
					    break-interferences
 | 
				
			||||||
    dup perform-renaming
 | 
					    dup perform-renaming
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ IN: compiler.cfg.coalescing.copies
 | 
				
			||||||
: compute-copies ( assoc -- assoc' )
 | 
					: compute-copies ( assoc -- assoc' )
 | 
				
			||||||
    dup assoc-size <hashtable> [
 | 
					    dup assoc-size <hashtable> [
 | 
				
			||||||
        '[
 | 
					        '[
 | 
				
			||||||
            [ _ 2dup key? [ "OOPS" throw ] [ set-at ] if ] with each
 | 
					            [ 2dup eq? [ 2drop ] [ _ 2dup key? [ "OOPS" throw ] [ set-at ] if ] if ] with each
 | 
				
			||||||
        ] assoc-each
 | 
					        ] assoc-each
 | 
				
			||||||
    ] keep ;
 | 
					    ] keep ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,48 +2,32 @@
 | 
				
			||||||
! See http://factorcode.org/license.txt for BSD license.
 | 
					! See http://factorcode.org/license.txt for BSD license.
 | 
				
			||||||
USING: accessors assocs combinators combinators.short-circuit
 | 
					USING: accessors assocs combinators combinators.short-circuit
 | 
				
			||||||
kernel math namespaces sequences locals compiler.cfg.def-use
 | 
					kernel math namespaces sequences locals compiler.cfg.def-use
 | 
				
			||||||
compiler.cfg.liveness compiler.cfg.dominance ;
 | 
					compiler.cfg.dominance compiler.cfg.coalescing.live-ranges ;
 | 
				
			||||||
IN: compiler.cfg.coalescing.interference
 | 
					IN: compiler.cfg.coalescing.interference
 | 
				
			||||||
 | 
					
 | 
				
			||||||
! Local interference testing. Requires live-out information
 | 
					 | 
				
			||||||
<PRIVATE
 | 
					<PRIVATE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SYMBOLS: def-index kill-index ;
 | 
					: kill-after-def? ( vreg1 vreg2 bb -- ? )
 | 
				
			||||||
 | 
					 | 
				
			||||||
: compute-local-live-ranges ( bb -- )
 | 
					 | 
				
			||||||
    H{ } clone def-index set
 | 
					 | 
				
			||||||
    H{ } clone kill-index set
 | 
					 | 
				
			||||||
    [
 | 
					 | 
				
			||||||
        instructions>> [
 | 
					 | 
				
			||||||
            [ swap defs-vregs [ def-index get set-at ] with each ]
 | 
					 | 
				
			||||||
            [ swap uses-vregs [ kill-index get set-at ] with each ]
 | 
					 | 
				
			||||||
            2bi
 | 
					 | 
				
			||||||
        ] each-index
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
    [ live-out keys [ [ 1/0. ] dip kill-index get set-at ] each ]
 | 
					 | 
				
			||||||
    bi ;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
: kill-after-def? ( vreg1 vreg2 -- ? )
 | 
					 | 
				
			||||||
    ! If first register is killed after second one is defined, they interfere
 | 
					    ! If first register is killed after second one is defined, they interfere
 | 
				
			||||||
    [ kill-index get at ] [ def-index get at ] bi* >= ;
 | 
					    [ kill-index ] [ def-index ] bi-curry bi* >= ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
: interferes-same-block? ( vreg1 vreg2 bb1 bb2 -- ? )
 | 
					: interferes-same-block? ( vreg1 vreg2 bb1 bb2 -- ? )
 | 
				
			||||||
    ! If both are defined in the same basic block, they interfere if their
 | 
					    ! If both are defined in the same basic block, they interfere if their
 | 
				
			||||||
    ! local live ranges intersect.
 | 
					    ! local live ranges intersect.
 | 
				
			||||||
    drop compute-local-live-ranges
 | 
					    drop
 | 
				
			||||||
    { [ kill-after-def? ] [ swap kill-after-def? ] } 2|| ;
 | 
					    { [ kill-after-def? ] [ swapd kill-after-def? ] } 3|| ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
: interferes-first-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
 | 
					: interferes-first-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
 | 
				
			||||||
    ! If vreg1 dominates vreg2, then they interfere if vreg2's definition
 | 
					    ! If vreg1 dominates vreg2, then they interfere if vreg2's definition
 | 
				
			||||||
    ! occurs before vreg1 is killed.
 | 
					    ! occurs before vreg1 is killed.
 | 
				
			||||||
    nip compute-local-live-ranges
 | 
					    nip
 | 
				
			||||||
    kill-after-def? ;
 | 
					    kill-after-def? ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
: interferes-second-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
 | 
					: interferes-second-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
 | 
				
			||||||
    ! If vreg2 dominates vreg1, then they interfere if vreg1's definition
 | 
					    ! If vreg2 dominates vreg1, then they interfere if vreg1's definition
 | 
				
			||||||
    ! occurs before vreg2 is killed.
 | 
					    ! occurs before vreg2 is killed.
 | 
				
			||||||
    drop compute-local-live-ranges
 | 
					    drop
 | 
				
			||||||
    swap kill-after-def? ;
 | 
					    swapd kill-after-def? ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PRIVATE>
 | 
					PRIVATE>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					! Copyright (C) 2009 Slava Pestov.
 | 
				
			||||||
 | 
					! See http://factorcode.org/license.txt for BSD license.
 | 
				
			||||||
 | 
					USING: accessors assocs fry kernel namespaces sequences
 | 
				
			||||||
 | 
					compiler.cfg.def-use compiler.cfg.instructions
 | 
				
			||||||
 | 
					compiler.cfg.liveness compiler.cfg.rpo ;
 | 
				
			||||||
 | 
					IN: compiler.cfg.coalescing.live-ranges
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					! Live ranges for interference testing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<PRIVATE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SYMBOLS: local-def-indices local-kill-indices ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: record-defs ( n vregs -- )
 | 
				
			||||||
 | 
					    local-def-indices get '[ _ set-at ] with each ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: record-uses ( n vregs -- )
 | 
				
			||||||
 | 
					    local-kill-indices get '[ _ set-at ] with each ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: visit-insn ( insn n -- )
 | 
				
			||||||
 | 
					    [ swap defs-vregs record-defs ]
 | 
				
			||||||
 | 
					    [ swap uses-vregs record-uses ]
 | 
				
			||||||
 | 
					    [ over def-is-use-insn? [ swap defs-vregs record-uses ] [ 2drop ] if ]
 | 
				
			||||||
 | 
					    2tri ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SYMBOLS: def-indices kill-indices ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: compute-local-live-ranges ( bb -- )
 | 
				
			||||||
 | 
					    H{ } clone local-def-indices set
 | 
				
			||||||
 | 
					    H{ } clone local-kill-indices set
 | 
				
			||||||
 | 
					    instructions>> [ visit-insn ] each-index ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PRIVATE>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: compute-live-ranges ( cfg -- )
 | 
				
			||||||
 | 
					    [ compute-local-live-ranges ] each-basic-block ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: def-index ( vreg bb -- n )
 | 
				
			||||||
 | 
					    def-indices get at at ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: kill-index ( vreg bb -- n )
 | 
				
			||||||
 | 
					    2dup live-out key? [ 2drop 1/0. ] [ kill-indices get at at ] if ;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					! Copyright (C) 2009 Slava Pestov.
 | 
				
			||||||
 | 
					! See http://factorcode.org/license.txt for BSD license.
 | 
				
			||||||
 | 
					USING: kernel math accessors sequences
 | 
				
			||||||
 | 
					compiler.cfg compiler.cfg.rpo compiler.cfg.utilities ;
 | 
				
			||||||
 | 
					IN: compiler.cfg.critical-edges
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: critical-edge? ( from to -- ? )
 | 
				
			||||||
 | 
					    [ successors>> length 1 > ] [ predecessors>> length 1 > ] bi* and ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: split-critical-edge ( from to -- )
 | 
				
			||||||
 | 
					    f <simple-block> insert-basic-block ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					: split-critical-edges ( cfg -- )
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					        dup successors>> [
 | 
				
			||||||
 | 
					            2dup critical-edge?
 | 
				
			||||||
 | 
					            [ split-critical-edge ] [ 2drop ] if
 | 
				
			||||||
 | 
					        ] with each
 | 
				
			||||||
 | 
					    ] each-basic-block ;
 | 
				
			||||||
| 
						 | 
					@ -251,3 +251,10 @@ UNION: kill-vreg-insn
 | 
				
			||||||
    ##alien-invoke
 | 
					    ##alien-invoke
 | 
				
			||||||
    ##alien-indirect
 | 
					    ##alien-indirect
 | 
				
			||||||
    ##alien-callback ;
 | 
					    ##alien-callback ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					! Instructions that have complex expansions and require that the
 | 
				
			||||||
 | 
					! output registers are not equal to any of the input registers
 | 
				
			||||||
 | 
					UNION: def-is-use-insn
 | 
				
			||||||
 | 
					    ##integer>bignum
 | 
				
			||||||
 | 
					    ##bignum>integer
 | 
				
			||||||
 | 
					    ##unbox-any-c-ptr ;
 | 
				
			||||||
		Loading…
	
		Reference in New Issue