]> gitweb.factorcode.org Git - factor.git/commitdiff
compiler.cfg.linear-scan: Re-implement spilling, add some additional runtime assertio...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 7 Jul 2009 08:28:55 +0000 (03:28 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Tue, 7 Jul 2009 08:28:55 +0000 (03:28 -0500)
basis/compiler/cfg/linear-scan/allocation/allocation.factor
basis/compiler/cfg/linear-scan/allocation/coalescing/coalescing.factor
basis/compiler/cfg/linear-scan/allocation/spilling/spilling.factor
basis/compiler/cfg/linear-scan/allocation/splitting/splitting.factor
basis/compiler/cfg/linear-scan/allocation/state/state.factor
basis/compiler/cfg/linear-scan/assignment/assignment.factor
basis/compiler/cfg/linear-scan/debugger/debugger.factor
basis/compiler/cfg/linear-scan/linear-scan-tests.factor
basis/compiler/cfg/linear-scan/live-intervals/live-intervals.factor

index 4a58064582160b0ef1529d65d387551ab2b0fac5..7dd39776050c459ee08ff5e3231a8a0fb6f0f0a6 100644 (file)
@@ -9,11 +9,6 @@ compiler.cfg.linear-scan.allocation.splitting
 compiler.cfg.linear-scan.allocation.state ;
 IN: compiler.cfg.linear-scan.allocation
 
-: free-positions ( new -- assoc )
-    vreg>> reg-class>> registers get at [ 1/0. ] H{ } map>assoc ;
-
-: add-use-position ( n reg assoc -- ) [ [ min ] when* ] change-at ;
-
 : active-positions ( new assoc -- )
     [ vreg>> active-intervals-for ] dip
     '[ [ 0 ] dip reg>> _ add-use-position ] each ;
@@ -21,7 +16,7 @@ IN: compiler.cfg.linear-scan.allocation
 : inactive-positions ( new assoc -- )
     [ [ vreg>> inactive-intervals-for ] keep ] dip
     '[
-        [ _ relevant-ranges intersect-live-ranges ] [ reg>> ] bi
+        [ _ relevant-ranges intersect-live-ranges 1/0. or ] [ reg>> ] bi
         _ add-use-position
     ] each ;
 
@@ -33,12 +28,6 @@ IN: compiler.cfg.linear-scan.allocation
 : no-free-registers? ( result -- ? )
     second 0 = ; inline
 
-: register-available? ( new result -- ? )
-    [ end>> ] [ second ] bi* < ; inline
-
-: register-available ( new result -- )
-    first >>reg add-active ;
-
 : register-partially-available ( new result -- )
     [ second split-before-use ] keep
     '[ _ register-available ] [ add-unhandled ] bi* ;
index b2b9202204099d9672282eb253856483c41330d3..e99c2ba710cbcc658c900b315fda731d04bc177a 100644 (file)
@@ -9,15 +9,15 @@ IN: compiler.cfg.linear-scan.allocation.coalescing
 : active-interval ( vreg -- live-interval )
     dup [ dup active-intervals-for [ vreg>> = ] with find nip ] when ;
 
-: intersects-inactive-intervals? ( live-interval -- ? )
+: avoids-inactive-intervals? ( live-interval -- ? )
     dup vreg>> inactive-intervals-for
-    [ relevant-ranges intersect-live-ranges 1/0. = ] with all? ;
+    [ intervals-intersect? not ] with all? ;
 
 : coalesce? ( live-interval -- ? )
     {
         [ copy-from>> active-interval ]
         [ [ start>> ] [ copy-from>> active-interval end>> ] bi = ]
-        [ intersects-inactive-intervals? ]
+        [ avoids-inactive-intervals? ]
     } 1&& ;
 
 : coalesce ( live-interval -- )
index e5c4b1002104144e36e41b6d3cfc1068c5bd5274..9be80b0775e7946badcf9fbea8ad21841649be09 100644 (file)
@@ -1,23 +1,13 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators fry hints kernel locals
-math sequences sets sorting splitting compiler.utilities namespaces
+math sequences sets sorting splitting namespaces
+combinators.short-circuit compiler.utilities
 compiler.cfg.linear-scan.allocation.state
 compiler.cfg.linear-scan.allocation.splitting
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.spilling
 
-: find-use ( live-interval n quot -- elt )
-    [ uses>> ] 2dip curry find nip ; inline
-
-: interval-to-spill ( active-intervals current -- live-interval )
-    #! We spill the interval with the most distant use location.
-    #! If an active interval has no more use positions, find-use
-    #! returns f. This occurs if the interval is a split. In
-    #! this case, we prefer to spill this interval always.
-    start>> '[ dup _ [ >= ] find-use 1/0. or ] { } map>assoc
-    alist-max first ;
-
 ERROR: bad-live-ranges interval ;
 
 : check-ranges ( live-interval -- )
@@ -47,52 +37,106 @@ ERROR: bad-live-ranges interval ;
         [ ]
     } 2cleave ;
 
-: assign-spill ( live-interval -- live-interval )
-    dup vreg>> assign-spill-slot >>spill-to ;
+: assign-spill ( live-interval -- )
+    dup vreg>> assign-spill-slot >>spill-to drop ;
 
-: assign-reload ( before after -- before after )
-    over spill-to>> >>reload-from ;
+: assign-reload ( live-interval -- )
+    dup vreg>> assign-spill-slot >>reload-from drop ;
 
-: split-and-spill ( new existing -- before after )
-    swap start>> split-for-spill [ assign-spill ] dip assign-reload ;
+: split-and-spill ( live-interval n -- before after )
+    split-for-spill
+    [ [ assign-spill ] [ assign-reload ] bi* ]
+    [ [ t >>record-spill? ] [ t >>record-reload? ] bi* ] 2bi ;
 
-: reuse-register ( new existing -- )
-    [ nip delete-active ]
-    [ reg>> >>reg add-active ] 2bi ;
+: find-use-position ( live-interval new -- n )
+    [ uses>> ] [ start>> '[ _ >= ] ] bi* find nip 1/0. or ;
 
-: spill-existing? ( new existing -- ? )
-    #! Test if 'new' will be used before 'existing'.
-    over start>> '[ _ [ > ] find-use -1 or ] bi@ < ;
+: find-use-positions ( live-intervals new assoc -- )
+    '[ [ _ find-use-position ] [ reg>> ] bi _ add-use-position ] each ;
 
-: spill-existing ( new existing -- )
-    #! Our new interval will be used before the active interval
-    #! with the most distant use location. Spill the existing
-    #! interval, then process the new interval and the tail end
-    #! of the existing interval again.
-    [ reuse-register ]
-    [ split-and-spill [ add-handled ] [ add-unhandled ] bi* ] 2bi ;
+: active-positions ( new assoc -- )
+    [ [ vreg>> active-intervals-for ] keep ] dip
+    find-use-positions ;
 
-: spill-live-out? ( new existing -- ? )
-    [ start>> ] [ uses>> last ] bi* > ;
+: inactive-positions ( new assoc -- )
+    [
+        [ vreg>> inactive-intervals-for ] keep
+        [ '[ _ intervals-intersect? ] filter ] keep
+    ] dip
+    find-use-positions ;
 
-: spill-live-out ( new existing -- )
-    #! The existing interval is never used again. Spill it and
-    #! re-use the register.
-    assign-spill
-    [ reuse-register ]
-    [ nip add-handled ] 2bi ;
+: spill-status ( new -- use-pos )
+    H{ } clone
+    [ inactive-positions ] [ active-positions ] [ nip ] 2tri
+    >alist alist-max ;
 
-: spill-new ( new existing -- )
-    #! Our new interval will be used after the active interval
-    #! with the most distant use location. Split the new
-    #! interval, then process both parts of the new interval
-    #! again.
-    [ dup split-and-spill add-unhandled ] dip spill-existing ;
+: spill-new? ( new pair -- ? )
+    [ uses>> first ] [ second ] bi* > ;
 
-: assign-blocked-register ( new -- )
-    [ dup vreg>> active-intervals-for ] keep interval-to-spill {
-        { [ 2dup spill-live-out? ] [ spill-live-out ] }
-        { [ 2dup spill-existing? ] [ spill-existing ] }
-        [ spill-new ]
+: spill-new ( new pair -- )
+    "not sure what to do yet" throw ;
+
+: split-intersecting? ( live-interval new reg -- ? )
+    { [ [ drop reg>> ] dip = ] [ drop intervals-intersect? ] } 3&& ;
+
+: split-live-out ( live-interval -- )
+    f >>record-spill?
+    {
+        [ trim-before-ranges ]
+        [ compute-start/end ]
+        [ assign-spill ]
+        [ add-handled ]
+    } cleave ;
+
+: split-live-in ( live-interval -- )
+    f >>record-reload?
+    {
+        [ trim-after-ranges ]
+        [ compute-start/end ]
+        ! [ assign-reload ]
+        [ add-handled ]
+    } cleave ;
+
+: (split-intersecting) ( live-interval new -- )
+    start>> {
+        { [ 2dup [ uses>> last ] dip < ] [ drop split-live-out ] }
+        { [ 2dup [ uses>> first ] dip > ] [ drop split-live-in ] }
+        [ split-and-spill [ add-handled ] [ add-unhandled ] bi* ]
     } cond ;
 
+: (split-intersecting-active) ( active new -- )
+    [ drop delete-active ]
+    [ (split-intersecting) ] 2bi ;
+
+: split-intersecting-active ( new reg -- )
+    [ [ vreg>> active-intervals-for ] keep ] dip
+    [ '[ _ _ split-intersecting? ] filter ] 2keep drop
+    '[ _ (split-intersecting-active) ] each ;
+
+: (split-intersecting-inactive) ( inactive new -- )
+    [ drop delete-inactive ]
+    [ (split-intersecting) ] 2bi ;
+
+: split-intersecting-inactive ( new reg -- )
+    [ [ vreg>> inactive-intervals-for ] keep ] dip
+    [ '[ _ _ split-intersecting? ] filter ] 2keep drop
+    '[ _ (split-intersecting-inactive) ] each ;
+
+: split-intersecting ( new reg -- )
+    [ split-intersecting-active ]
+    [ split-intersecting-inactive ]
+    2bi ;
+
+: spill-available ( new pair -- )
+    [ first split-intersecting ] [ register-available ] 2bi ;
+
+: spill-partially-available ( new pair -- )
+    [ second 1 - split-and-spill add-unhandled ] keep
+    spill-available ;
+
+: assign-blocked-register ( new -- )
+    dup spill-status {
+        { [ 2dup spill-new? ] [ spill-new ] }
+        { [ 2dup register-available? ] [ spill-available ] }
+        [ spill-partially-available ]
+    } cond ;
\ No newline at end of file
index b2872ace14f53d1b034bc536f05f5bc6223363aa..71d3d56285c7a48fe56ba9fc8a149e6c28c2c435 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators fry hints kernel locals
-math sequences sets sorting splitting
+math sequences sets sorting splitting namespaces
 compiler.cfg.linear-scan.allocation.state
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.splitting
@@ -32,12 +32,17 @@ IN: compiler.cfg.linear-scan.allocation.splitting
 
 ERROR: splitting-too-early ;
 
+ERROR: splitting-too-late ;
+
 ERROR: splitting-atomic-interval ;
 
 : check-split ( live-interval n -- )
-    [ [ start>> ] dip > [ splitting-too-early ] when ]
-    [ drop [ end>> ] [ start>> ] bi - 0 = [ splitting-atomic-interval ] when ]
-    2bi ; inline
+    check-allocation? get [
+        [ [ start>> ] dip > [ splitting-too-early ] when ]
+        [ [ end>> ] dip <= [ splitting-too-late ] when ]
+        [ drop [ end>> ] [ start>> ] bi = [ splitting-atomic-interval ] when ]
+        2tri
+    ] [ 2drop ] if ; inline
 
 : split-before ( before -- before' )
     f >>spill-to ; inline
index a17a1181b56c374f889d959384480e3d0e4a513c..a08e3e37bd0f1508c7af126d9468691bb3c539b3 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs combinators cpu.architecture fry heaps
-kernel math namespaces sequences vectors
+kernel math math.order namespaces sequences vectors
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.state
 
@@ -32,6 +32,9 @@ SYMBOL: inactive-intervals
 : add-inactive ( live-interval -- )
     dup vreg>> inactive-intervals-for push ;
 
+: delete-inactive ( live-interval -- )
+    dup vreg>> inactive-intervals-for delq ;
+
 ! Vector of handled live intervals
 SYMBOL: handled-intervals
 
@@ -133,4 +136,16 @@ SYMBOL: spill-slots
 
 : init-unhandled ( live-intervals -- )
     [ [ start>> ] keep ] { } map>assoc
-    unhandled-intervals get heap-push-all ;
\ No newline at end of file
+    unhandled-intervals get heap-push-all ;
+
+! A utility used by register-status and spill-status words
+: free-positions ( new -- assoc )
+    vreg>> reg-class>> registers get at [ 1/0. ] H{ } map>assoc ;
+
+: add-use-position ( n reg assoc -- ) [ [ min ] when* ] change-at ;
+
+: register-available? ( new result -- ? )
+    [ end>> ] [ second ] bi* < ; inline
+
+: register-available ( new result -- )
+    first >>reg add-active ;
index 8a9bfa02db43621c30987b0165c24e1494f29255..bc565c6cbba1b9b95e745103ec724ee3a086dd9b 100644 (file)
@@ -3,7 +3,9 @@
 USING: accessors kernel math assocs namespaces sequences heaps
 fry make combinators sets locals
 cpu.architecture
+compiler.cfg
 compiler.cfg.def-use
+compiler.cfg.liveness
 compiler.cfg.registers
 compiler.cfg.instructions
 compiler.cfg.linear-scan.allocation
@@ -27,12 +29,6 @@ SYMBOL: unhandled-intervals
 : init-unhandled ( live-intervals -- )
     [ add-unhandled ] each ;
 
-! Mapping spill slots to vregs
-SYMBOL: spill-slots
-
-: spill-slots-for ( vreg -- assoc )
-    reg-class>> spill-slots get at ;
-
 ! Mapping from basic blocks to values which are live at the start
 SYMBOL: register-live-ins
 
@@ -42,17 +38,10 @@ SYMBOL: register-live-outs
 : init-assignment ( live-intervals -- )
     V{ } clone pending-intervals set
     <min-heap> unhandled-intervals set
-    [ H{ } clone ] reg-class-assoc spill-slots set
     H{ } clone register-live-ins set
     H{ } clone register-live-outs set
     init-unhandled ;
 
-ERROR: already-spilled ;
-
-: record-spill ( live-interval -- )
-    [ dup spill-to>> ] [ vreg>> spill-slots-for ] bi
-    2dup key? drop set-at ; ! [ already-spilled ] [ set-at ] if ;
-
 : insert-spill ( live-interval -- )
     {
         [ reg>> ]
@@ -62,7 +51,7 @@ ERROR: already-spilled ;
     } cleave f swap \ _spill boa , ;
 
 : handle-spill ( live-interval -- )
-    dup spill-to>> [ [ record-spill ] [ insert-spill ] bi ] [ drop ] if ;
+    dup spill-to>> [ insert-spill ] [ drop ] if ;
 
 : first-split ( live-interval -- live-interval' )
     dup split-before>> [ first-split ] [ ] ?if ;
@@ -88,12 +77,6 @@ ERROR: already-spilled ;
         [ [ handle-spill ] [ handle-copy ] bi f ] [ drop t ] if
     ] filter-here ;
 
-ERROR: already-reloaded ;
-
-: record-reload ( live-interval -- )
-    [ reload-from>> ] [ vreg>> spill-slots-for ] bi
-    2dup key? [ delete-at ] [ already-reloaded ] if ;
-
 : insert-reload ( live-interval -- )
     {
         [ reg>> ]
@@ -103,7 +86,7 @@ ERROR: already-reloaded ;
     } cleave f swap \ _reload boa , ;
 
 : handle-reload ( live-interval -- )
-    dup reload-from>> [ [ record-reload ] [ insert-reload ] bi ] [ drop ] if ;
+    dup reload-from>> [ insert-reload ] [ drop ] if ;
 
 : activate-new-intervals ( n -- )
     #! Any live intervals which start on the current instruction
@@ -145,35 +128,43 @@ M: vreg-insn assign-registers-in-insn
     register-mapping
     >>regs drop ;
 
-: compute-live-registers ( n -- assoc )
-    active-intervals register-mapping ;
-
-: compute-live-spill-slots ( -- assocs )
-    spill-slots get values first2
-    [ [ vreg>> swap <spill-slot> ] H{ } assoc-map-as ] bi@
-    assoc-union ;
-
-: compute-live-values ( n -- assoc )
-    [ compute-live-spill-slots ] dip compute-live-registers
-    assoc-union ;
-
-: compute-live-gc-values ( insn -- assoc )
-    [ insn#>> compute-live-values ] [ temp-vregs ] bi
-    '[ drop _ memq? not ] assoc-filter ;
-
 M: ##gc assign-registers-in-insn
+    ! This works because ##gc is always the first instruction
+    ! in a block.
     dup call-next-method
-    dup compute-live-gc-values >>live-values
+    basic-block get register-live-ins get at >>live-values
     drop ;
 
 M: insn assign-registers-in-insn drop ;
 
+: compute-live-spill-slots ( vregs -- assoc )
+    spill-slots get '[ _ at dup [ <spill-slot> ] when ] assoc-map ;
+
+: compute-live-registers ( n -- assoc )
+    active-intervals register-mapping ;
+
+ERROR: bad-live-values live-values ;
+
+: check-live-values ( assoc -- assoc )
+    check-assignment? get [
+        dup values [ not ] any? [ bad-live-values ] when
+    ] when ;
+
+: compute-live-values ( vregs n -- assoc )
+    ! If a live vreg is not in active or inactive, then it must have been
+    ! spilled.
+    [ compute-live-spill-slots ] [ compute-live-registers ] bi*
+    assoc-union check-live-values ;
+
 : begin-block ( bb -- )
+    dup basic-block set
     dup block-from prepare-insn
-    [ block-from compute-live-values ] keep register-live-ins get set-at ;
+    [ [ live-in ] [ block-from ] bi compute-live-values ] keep
+    register-live-ins get set-at ;
 
 : end-block ( bb -- )
-    [ block-to compute-live-values ] keep register-live-outs get set-at ;
+    [ [ live-out ] [ block-to ] bi compute-live-values ] keep
+    register-live-outs get set-at ;
 
 ERROR: bad-vreg vreg ;
 
index be3fb2bea8fde22de2ec00dca80b9bc9fc6b789c..a350ee5f43b5b42a542673a00bbe52e94042c4fd 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel sequences sets arrays math strings fry
 namespaces prettyprint compiler.cfg.linear-scan.live-intervals
-compiler.cfg.linear-scan.allocation compiler.cfg ;
+compiler.cfg.linear-scan.allocation compiler.cfg assocs ;
 IN: compiler.cfg.linear-scan.debugger
 
 : check-assigned ( live-intervals -- )
@@ -19,7 +19,10 @@ IN: compiler.cfg.linear-scan.debugger
     ] [ 1array ] if ;
 
 : check-linear-scan ( live-intervals machine-registers -- )
-    [ [ clone ] map ] dip allocate-registers
+    [
+        [ clone ] map dup [ [ vreg>> ] keep ] H{ } map>assoc
+        live-intervals set
+    ] dip allocate-registers
     [ split-children ] map concat check-assigned ;
 
 : picture ( uses -- str )
index e3cd9e105f5fb15293f8d3136f5abde82a9eabd5..59e6190b633dbb777bb6d1dcf2c30767d4d2f5ce 100644 (file)
@@ -76,36 +76,6 @@ check-assignment? on
     { T{ live-range f 0 5 } } 0 split-ranges
 ] unit-test
 
-[ 7 ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-        { start 0 }
-        { end 10 }
-        { uses V{ 0 1 3 7 10 } }
-    }
-    4 [ >= ] find-use
-] unit-test
-
-[ 4 ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-        { start 0 }
-        { end 10 }
-        { uses V{ 0 1 3 4 10 } }
-    }
-    4 [ >= ] find-use
-] unit-test
-
-[ f ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-        { start 0 }
-        { end 10 }
-        { uses V{ 0 1 3 4 10 } }
-    }
-    100 [ >= ] find-use
-] unit-test
-
 [
     T{ live-interval
        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@@ -257,88 +227,82 @@ check-assignment? on
 ] unit-test
 
 [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 3 }
-        { end 10 }
-        { uses V{ 3 10 } }
+    {
+        3
+        10
     }
 ] [
-    {
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 1 }
-            { end 15 }
-            { uses V{ 1 3 7 10 15 } }
-        }
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 3 }
-            { end 8 }
-            { uses V{ 3 4 8 } }
-        }
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 3 }
-            { end 10 }
-            { uses V{ 3 10 } }
+    H{
+        { int-regs
+          V{
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+                 { reg 1 }
+                 { start 1 }
+                 { end 15 }
+                 { uses V{ 1 3 7 10 15 } }
+              }
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 2 } } }
+                 { reg 2 }
+                 { start 3 }
+                 { end 8 }
+                 { uses V{ 3 4 8 } }
+              }
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 3 } } }
+                 { reg 3 }
+                 { start 3 }
+                 { end 10 }
+                 { uses V{ 3 10 } }
+              }
+          }
         }
-    }
+    } active-intervals set
+    H{ } inactive-intervals set
     T{ live-interval
         { vreg T{ vreg { reg-class int-regs } { n 1 } } }
         { start 5 }
         { end 5 }
         { uses V{ 5 } }
     }
-    interval-to-spill
+    spill-status
 ] unit-test
 
-[ t ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 5 }
-        { end 15 }
-        { uses V{ 5 10 15 } }
-    }
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 1 }
-        { end 20 }
-        { uses V{ 1 20 } }
-    }
-    spill-existing?
-] unit-test
-
-[ f ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 5 }
-        { end 15 }
-        { uses V{ 5 10 15 } }
-    }
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 1 }
-        { end 20 }
-        { uses V{ 1 7 20 } }
+[
+    {
+        1
+        1/0.
     }
-    spill-existing?
-] unit-test
-
-[ t ] [
+] [
+    H{
+        { int-regs
+          V{
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+                 { reg 1 }
+                 { start 1 }
+                 { end 15 }
+                 { uses V{ 1 } }
+              }
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 2 } } }
+                 { reg 2 }
+                 { start 3 }
+                 { end 8 }
+                 { uses V{ 3 8 } }
+              }
+          }
+        }
+    } active-intervals set
+    H{ } inactive-intervals set
     T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+        { vreg T{ vreg { reg-class int-regs } { n 3 } } }
         { start 5 }
         { end 5 }
         { uses V{ 5 } }
     }
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 1 }
-        { end 20 }
-        { uses V{ 1 7 20 } }
-    }
-    spill-existing?
+    spill-status
 ] unit-test
 
 [ ] [
@@ -1477,6 +1441,20 @@ USING: math.private ;
     intersect-live-ranges
 ] unit-test
 
+[ f ] [
+    {
+        T{ live-range f 0 10 }
+        T{ live-range f 20 30 }
+        T{ live-range f 40 50 }
+    }
+    {
+        T{ live-range f 11 15 }
+        T{ live-range f 31 36 }
+        T{ live-range f 51 55 }
+    }
+    intersect-live-ranges
+] unit-test
+
 [ 5 ] [
     T{ live-interval
        { start 0 }
@@ -1605,12 +1583,14 @@ V{
 SYMBOL: linear-scan-result
 
 :: test-linear-scan-on-cfg ( regs -- )
-    cfg new 0 get >>entry
-    compute-predecessors
-    compute-liveness
-    dup reverse-post-order
-    { { int-regs regs } } (linear-scan)
-    flatten-cfg 1array mr. ;
+    [
+        cfg new 0 get >>entry
+        compute-predecessors
+        compute-liveness
+        dup reverse-post-order
+        { { int-regs regs } } (linear-scan)
+        flatten-cfg 1array mr.
+    ] with-scope ;
 
 ! This test has a critical edge -- do we care about these?
 
@@ -2101,3 +2081,255 @@ V{
 5 get 1vector 3 get (>>successors)
 
 [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
+
+! Reduction of push-all regression, x86-32
+V{ T{ ##prologue } T{ ##branch } } 0 test-bb
+
+V{
+    T{ ##load-immediate { dst V int-regs 61 } }
+    T{ ##peek { dst V int-regs 62 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 64 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 69 }
+        { obj V int-regs 64 }
+        { slot 1 }
+        { tag 2 }
+    }
+    T{ ##copy { dst V int-regs 79 } { src V int-regs 69 } }
+    T{ ##slot-imm
+        { dst V int-regs 85 }
+        { obj V int-regs 62 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##compare-branch
+        { src1 V int-regs 69 }
+        { src2 V int-regs 85 }
+        { cc cc> }
+    }
+} 1 test-bb
+
+V{
+    T{ ##slot-imm
+        { dst V int-regs 97 }
+        { obj V int-regs 62 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##replace { src V int-regs 79 } { loc D 3 } }
+    T{ ##replace { src V int-regs 62 } { loc D 4 } }
+    T{ ##replace { src V int-regs 79 } { loc D 1 } }
+    T{ ##replace { src V int-regs 62 } { loc D 2 } }
+    T{ ##replace { src V int-regs 61 } { loc D 5 } }
+    T{ ##replace { src V int-regs 62 } { loc R 0 } }
+    T{ ##replace { src V int-regs 69 } { loc R 1 } }
+    T{ ##replace { src V int-regs 97 } { loc D 0 } }
+    T{ ##call { word resize-array } }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 98 } { loc R 0 } }
+    T{ ##peek { dst V int-regs 100 } { loc D 0 } }
+    T{ ##set-slot-imm
+        { src V int-regs 100 }
+        { obj V int-regs 98 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##peek { dst V int-regs 108 } { loc D 2 } }
+    T{ ##peek { dst V int-regs 110 } { loc D 3 } }
+    T{ ##peek { dst V int-regs 112 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 114 } { loc D 1 } }
+    T{ ##peek { dst V int-regs 116 } { loc D 4 } }
+    T{ ##peek { dst V int-regs 119 } { loc R 0 } }
+    T{ ##copy { dst V int-regs 109 } { src V int-regs 108 } }
+    T{ ##copy { dst V int-regs 111 } { src V int-regs 110 } }
+    T{ ##copy { dst V int-regs 113 } { src V int-regs 112 } }
+    T{ ##copy { dst V int-regs 115 } { src V int-regs 114 } }
+    T{ ##copy { dst V int-regs 117 } { src V int-regs 116 } }
+    T{ ##copy { dst V int-regs 120 } { src V int-regs 119 } }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##copy { dst V int-regs 109 } { src V int-regs 62 } }
+    T{ ##copy { dst V int-regs 111 } { src V int-regs 61 } }
+    T{ ##copy { dst V int-regs 113 } { src V int-regs 62 } }
+    T{ ##copy { dst V int-regs 115 } { src V int-regs 79 } }
+    T{ ##copy { dst V int-regs 117 } { src V int-regs 64 } }
+    T{ ##copy { dst V int-regs 120 } { src V int-regs 69 } }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##replace { src V int-regs 120 } { loc D 0 } }
+    T{ ##replace { src V int-regs 109 } { loc D 3 } }
+    T{ ##replace { src V int-regs 111 } { loc D 4 } }
+    T{ ##replace { src V int-regs 113 } { loc D 1 } }
+    T{ ##replace { src V int-regs 115 } { loc D 2 } }
+    T{ ##replace { src V int-regs 117 } { loc D 5 } }
+    T{ ##epilogue }
+    T{ ##return }
+} 5 test-bb
+
+0 get 1 get 1vector >>successors drop
+1 get 2 get 4 get V{ } 2sequence >>successors drop
+2 get 3 get 1vector >>successors drop
+3 get 5 get 1vector >>successors drop
+4 get 5 get 1vector >>successors drop
+
+[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
+
+! Another reduction of push-all
+V{ T{ ##prologue } T{ ##branch } } 0 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 85 } { loc D 0 } }
+    T{ ##slot-imm
+        { dst V int-regs 89 }
+        { obj V int-regs 85 }
+        { slot 3 }
+        { tag 7 }
+    }
+    T{ ##peek { dst V int-regs 91 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 96 }
+        { obj V int-regs 91 }
+        { slot 1 }
+        { tag 2 }
+    }
+    T{ ##add
+        { dst V int-regs 109 }
+        { src1 V int-regs 89 }
+        { src2 V int-regs 96 }
+    }
+    T{ ##slot-imm
+        { dst V int-regs 115 }
+        { obj V int-regs 85 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##slot-imm
+        { dst V int-regs 118 }
+        { obj V int-regs 115 }
+        { slot 1 }
+        { tag 2 }
+    }
+    T{ ##compare-branch
+        { src1 V int-regs 109 }
+        { src2 V int-regs 118 }
+        { cc cc> }
+    }
+} 1 test-bb
+
+V{
+    T{ ##add-imm
+        { dst V int-regs 128 }
+        { src1 V int-regs 109 }
+        { src2 8 }
+    }
+    T{ ##load-immediate { dst V int-regs 129 } { val 24 } }
+    T{ ##inc-d { n 4 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##replace { src V int-regs 109 } { loc D 2 } }
+    T{ ##replace { src V int-regs 85 } { loc D 3 } }
+    T{ ##replace { src V int-regs 128 } { loc D 0 } }
+    T{ ##replace { src V int-regs 85 } { loc D 1 } }
+    T{ ##replace { src V int-regs 89 } { loc D 4 } }
+    T{ ##replace { src V int-regs 96 } { loc R 0 } }
+    T{ ##fixnum-mul
+        { src1 V int-regs 128 }
+        { src2 V int-regs 129 }
+        { temp1 V int-regs 132 }
+        { temp2 V int-regs 133 }
+    }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 134 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 140 }
+        { obj V int-regs 134 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##replace { src V int-regs 140 } { loc D 0 } }
+    T{ ##replace { src V int-regs 134 } { loc R 0 } }
+    T{ ##call { word resize-array } }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 141 } { loc R 0 } }
+    T{ ##peek { dst V int-regs 143 } { loc D 0 } }
+    T{ ##set-slot-imm
+        { src V int-regs 143 }
+        { obj V int-regs 141 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##write-barrier
+        { src V int-regs 141 }
+        { card# V int-regs 145 }
+        { table V int-regs 146 }
+    }
+    T{ ##inc-d { n -1 } }
+    T{ ##inc-r { n -1 } }
+    T{ ##peek { dst V int-regs 156 } { loc D 2 } }
+    T{ ##peek { dst V int-regs 158 } { loc D 3 } }
+    T{ ##peek { dst V int-regs 160 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 162 } { loc D 1 } }
+    T{ ##peek { dst V int-regs 164 } { loc D 4 } }
+    T{ ##peek { dst V int-regs 167 } { loc R 0 } }
+    T{ ##copy { dst V int-regs 157 } { src V int-regs 156 } }
+    T{ ##copy { dst V int-regs 159 } { src V int-regs 158 } }
+    T{ ##copy { dst V int-regs 161 } { src V int-regs 160 } }
+    T{ ##copy { dst V int-regs 163 } { src V int-regs 162 } }
+    T{ ##copy { dst V int-regs 165 } { src V int-regs 164 } }
+    T{ ##copy { dst V int-regs 168 } { src V int-regs 167 } }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##inc-d { n 3 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##copy { dst V int-regs 157 } { src V int-regs 85 } }
+    T{ ##copy { dst V int-regs 159 } { src V int-regs 89 } }
+    T{ ##copy { dst V int-regs 161 } { src V int-regs 85 } }
+    T{ ##copy { dst V int-regs 163 } { src V int-regs 109 } }
+    T{ ##copy { dst V int-regs 165 } { src V int-regs 91 } }
+    T{ ##copy { dst V int-regs 168 } { src V int-regs 96 } }
+    T{ ##branch }
+} 5 test-bb
+
+V{
+    T{ ##set-slot-imm
+        { src V int-regs 163 }
+        { obj V int-regs 161 }
+        { slot 3 }
+        { tag 7 }
+    }
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n -1 } }
+    T{ ##replace { src V int-regs 168 } { loc D 0 } }
+    T{ ##replace { src V int-regs 157 } { loc D 3 } }
+    T{ ##replace { src V int-regs 159 } { loc D 4 } }
+    T{ ##replace { src V int-regs 161 } { loc D 1 } }
+    T{ ##replace { src V int-regs 163 } { loc D 2 } }
+    T{ ##replace { src V int-regs 165 } { loc D 5 } }
+    T{ ##epilogue }
+    T{ ##return }
+} 6 test-bb
+
+0 get 1 get 1vector >>successors drop
+1 get 2 get 5 get V{ } 2sequence >>successors drop
+2 get 3 get 1vector >>successors drop
+3 get 4 get 1vector >>successors drop
+4 get 6 get 1vector >>successors drop
+5 get 6 get 1vector >>successors drop
+
+[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
\ No newline at end of file
index 61432eefdfd7b8ea81945e4a4f686d89ee96eada..e735640b1055834dfb980867a4cf32e4744af477 100644 (file)
@@ -11,7 +11,7 @@ C: <live-range> live-range
 
 TUPLE: live-interval
 vreg
-reg spill-to reload-from
+reg spill-to record-spill? reload-from record-reload?
 split-before split-after split-next
 start end ranges uses
 copy-from ;
@@ -145,8 +145,7 @@ M: ##copy-float compute-live-intervals*
         <reversed> [ compute-live-intervals-step ] each
     ] keep values dup finish-live-intervals ;
 
-: relevant-ranges ( new inactive -- new' inactive' )
-    ! Slice off all ranges of 'inactive' that precede the start of 'new'
+: relevant-ranges ( interval1 interval2 -- ranges1 ranges2 )
     [ [ ranges>> ] bi@ ] [ nip start>> ] 2bi '[ to>> _ >= ] filter ;
 
 : intersect-live-range ( range1 range2 -- n/f )
@@ -155,8 +154,8 @@ M: ##copy-float compute-live-intervals*
 
 : intersect-live-ranges ( ranges1 ranges2 -- n )
     {
-        { [ over empty? ] [ 2drop 1/0. ] }
-        { [ dup empty? ] [ 2drop 1/0. ] }
+        { [ over empty? ] [ 2drop f ] }
+        { [ dup empty? ] [ 2drop f ] }
         [
             2dup [ first ] bi@ intersect-live-range dup [ 2nip ] [
                 drop
@@ -166,3 +165,6 @@ M: ##copy-float compute-live-intervals*
             ] if
         ]
     } cond ;
+
+: intervals-intersect? ( interval1 interval2 -- ? )
+    relevant-ranges intersect-live-ranges >boolean ; inline
\ No newline at end of file