compiler.cfg.linear-scan: debugging spilling, add more assertions

db4
Slava Pestov 2009-07-07 13:01:27 -05:00
parent 516ce0c71d
commit e2044602aa
6 changed files with 251 additions and 25 deletions

View File

@ -72,7 +72,13 @@ ERROR: bad-live-ranges interval ;
[ uses>> first ] [ second ] bi* > ; [ uses>> first ] [ second ] bi* > ;
: spill-new ( new pair -- ) : spill-new ( new pair -- )
"not sure what to do yet" throw ; drop
{
[ trim-after-ranges ]
[ compute-start/end ]
[ assign-reload ]
[ add-unhandled ]
} cleave ;
: split-intersecting? ( live-interval new reg -- ? ) : split-intersecting? ( live-interval new reg -- ? )
{ [ [ drop reg>> ] dip = ] [ drop intervals-intersect? ] } 3&& ; { [ [ drop reg>> ] dip = ] [ drop intervals-intersect? ] } 3&& ;
@ -90,7 +96,7 @@ ERROR: bad-live-ranges interval ;
[ trim-after-ranges ] [ trim-after-ranges ]
[ compute-start/end ] [ compute-start/end ]
[ assign-reload ] [ assign-reload ]
[ add-handled ] [ add-unhandled ]
} cleave ; } cleave ;
: (split-intersecting) ( live-interval new -- ) : (split-intersecting) ( live-interval new -- )

View File

@ -5,6 +5,20 @@ kernel math math.order namespaces sequences vectors
compiler.cfg.linear-scan.live-intervals ; compiler.cfg.linear-scan.live-intervals ;
IN: compiler.cfg.linear-scan.allocation.state IN: compiler.cfg.linear-scan.allocation.state
! Start index of current live interval. We ensure that all
! live intervals added to the unhandled set have a start index
! strictly greater than this one. This ensures that we can catch
! infinite loop situations. We also ensure that all live
! intervals added to the handled set have an end index strictly
! smaller than this one. This helps catch bugs.
SYMBOL: progress
: check-unhandled ( live-interval -- )
start>> progress get <= [ "check-unhandled" throw ] when ; inline
: check-handled ( live-interval -- )
end>> progress get > [ "check-handled" throw ] when ; inline
! Mapping from register classes to sequences of machine registers ! Mapping from register classes to sequences of machine registers
SYMBOL: registers SYMBOL: registers
@ -39,7 +53,7 @@ SYMBOL: inactive-intervals
SYMBOL: handled-intervals SYMBOL: handled-intervals
: add-handled ( live-interval -- ) : add-handled ( live-interval -- )
handled-intervals get push ; [ check-handled ] [ handled-intervals get push ] bi ;
: finished? ( n live-interval -- ? ) end>> swap < ; : finished? ( n live-interval -- ? ) end>> swap < ;
@ -93,17 +107,8 @@ ERROR: register-already-used live-interval ;
! Minheap of live intervals which still need a register allocation ! Minheap of live intervals which still need a register allocation
SYMBOL: unhandled-intervals SYMBOL: unhandled-intervals
! Start index of current live interval. We ensure that all
! live intervals added to the unhandled set have a start index
! strictly greater than ths one. This ensures that we can catch
! infinite loop situations.
SYMBOL: progress
: check-progress ( live-interval -- )
start>> progress get <= [ "No progress" throw ] when ; inline
: add-unhandled ( live-interval -- ) : add-unhandled ( live-interval -- )
[ check-progress ] [ check-unhandled ]
[ dup start>> unhandled-intervals get heap-push ] [ dup start>> unhandled-intervals get heap-push ]
bi ; bi ;

View File

@ -68,8 +68,7 @@ SYMBOL: register-live-outs
} cleave f swap \ _copy boa , ; } cleave f swap \ _copy boa , ;
: handle-copy ( live-interval -- ) : handle-copy ( live-interval -- )
dup [ spill-to>> not ] [ split-next>> ] bi and dup split-next>> [ insert-copy ] [ drop ] if ;
[ insert-copy ] [ drop ] if ;
: expire-old-intervals ( n -- ) : expire-old-intervals ( n -- )
[ pending-intervals get ] dip '[ [ pending-intervals get ] dip '[
@ -82,7 +81,7 @@ SYMBOL: register-live-outs
[ reg>> ] [ reg>> ]
[ vreg>> reg-class>> ] [ vreg>> reg-class>> ]
[ reload-from>> ] [ reload-from>> ]
[ end>> ] [ start>> ]
} cleave f swap \ _reload boa , ; } cleave f swap \ _reload boa , ;
: handle-reload ( live-interval -- ) : handle-reload ( live-interval -- )
@ -92,7 +91,7 @@ SYMBOL: register-live-outs
#! Any live intervals which start on the current instruction #! Any live intervals which start on the current instruction
#! are added to the active set. #! are added to the active set.
unhandled-intervals get dup heap-empty? [ 2drop ] [ unhandled-intervals get dup heap-empty? [ 2drop ] [
2dup heap-peek drop start>> >= [ 2dup heap-peek drop start>> = [
heap-pop drop heap-pop drop
[ add-active ] [ handle-reload ] bi [ add-active ] [ handle-reload ] bi
activate-new-intervals activate-new-intervals
@ -179,10 +178,12 @@ ERROR: bad-vreg vreg ;
[ [
bb begin-block bb begin-block
[ [
{
[ insn#>> 1 - prepare-insn ]
[ insn#>> prepare-insn ] [ insn#>> prepare-insn ]
[ assign-registers-in-insn ] [ assign-registers-in-insn ]
[ , ] [ , ]
tri } cleave
] each ] each
bb end-block bb end-block
] V{ } make ] V{ } make

View File

@ -1,7 +1,7 @@
IN: compiler.cfg.linear-scan.tests IN: compiler.cfg.linear-scan.tests
USING: tools.test random sorting sequences sets hashtables assocs USING: tools.test random sorting sequences sets hashtables assocs
kernel fry arrays splitting namespaces math accessors vectors locals kernel fry arrays splitting namespaces math accessors vectors locals
math.order grouping math.order grouping strings strings.private
cpu.architecture cpu.architecture
compiler.cfg compiler.cfg
compiler.cfg.optimizer compiler.cfg.optimizer
@ -13,6 +13,7 @@ compiler.cfg.rpo
compiler.cfg.linearization compiler.cfg.linearization
compiler.cfg.debugger compiler.cfg.debugger
compiler.cfg.linear-scan compiler.cfg.linear-scan
compiler.cfg.linear-scan.numbering
compiler.cfg.linear-scan.live-intervals compiler.cfg.linear-scan.live-intervals
compiler.cfg.linear-scan.allocation compiler.cfg.linear-scan.allocation
compiler.cfg.linear-scan.allocation.state compiler.cfg.linear-scan.allocation.state
@ -24,6 +25,7 @@ FROM: compiler.cfg.linear-scan.assignment => check-assignment? ;
check-allocation? on check-allocation? on
check-assignment? on check-assignment? on
check-numbering? on
[ [
{ T{ live-range f 1 10 } T{ live-range f 15 15 } } { T{ live-range f 1 10 } T{ live-range f 15 15 } }
@ -2333,3 +2335,203 @@ V{
5 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 [ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
! Another push-all reduction to demonstrate numbering anamoly
V{ T{ ##prologue } T{ ##branch } }
0 test-bb
V{
T{ ##peek { dst V int-regs 1 } { loc D 0 } }
T{ ##slot-imm
{ dst V int-regs 5 }
{ obj V int-regs 1 }
{ slot 3 }
{ tag 7 }
}
T{ ##peek { dst V int-regs 7 } { loc D 1 } }
T{ ##slot-imm
{ dst V int-regs 12 }
{ obj V int-regs 7 }
{ slot 1 }
{ tag 6 }
}
T{ ##add
{ dst V int-regs 25 }
{ src1 V int-regs 5 }
{ src2 V int-regs 12 }
}
T{ ##compare-branch
{ src1 V int-regs 25 }
{ src2 V int-regs 5 }
{ cc cc> }
}
}
1 test-bb
V{
T{ ##slot-imm
{ dst V int-regs 41 }
{ obj V int-regs 1 }
{ slot 2 }
{ tag 7 }
}
T{ ##slot-imm
{ dst V int-regs 44 }
{ obj V int-regs 41 }
{ slot 1 }
{ tag 6 }
}
T{ ##compare-branch
{ src1 V int-regs 25 }
{ src2 V int-regs 44 }
{ cc cc> }
}
}
2 test-bb
V{
T{ ##add-imm
{ dst V int-regs 54 }
{ src1 V int-regs 25 }
{ src2 8 }
}
T{ ##load-immediate { dst V int-regs 55 } { val 24 } }
T{ ##inc-d { n 4 } }
T{ ##inc-r { n 1 } }
T{ ##replace { src V int-regs 25 } { loc D 2 } }
T{ ##replace { src V int-regs 1 } { loc D 3 } }
T{ ##replace { src V int-regs 5 } { loc D 4 } }
T{ ##replace { src V int-regs 1 } { loc D 1 } }
T{ ##replace { src V int-regs 54 } { loc D 0 } }
T{ ##replace { src V int-regs 12 } { loc R 0 } }
T{ ##fixnum-mul
{ src1 V int-regs 54 }
{ src2 V int-regs 55 }
{ temp1 V int-regs 58 }
{ temp2 V int-regs 59 }
}
T{ ##branch }
}
3 test-bb
V{
T{ ##peek { dst V int-regs 60 } { loc D 1 } }
T{ ##slot-imm
{ dst V int-regs 66 }
{ obj V int-regs 60 }
{ slot 2 }
{ tag 7 }
}
T{ ##inc-d { n 1 } }
T{ ##inc-r { n 1 } }
T{ ##replace { src V int-regs 66 } { loc D 0 } }
T{ ##replace { src V int-regs 60 } { loc R 0 } }
T{ ##call { word resize-string } }
T{ ##branch }
}
4 test-bb
V{
T{ ##peek { dst V int-regs 67 } { loc R 0 } }
T{ ##peek { dst V int-regs 68 } { loc D 0 } }
T{ ##set-slot-imm
{ src V int-regs 68 }
{ obj V int-regs 67 }
{ slot 2 }
{ tag 7 }
}
T{ ##write-barrier
{ src V int-regs 67 }
{ card# V int-regs 75 }
{ table V int-regs 76 }
}
T{ ##inc-d { n -1 } }
T{ ##inc-r { n -1 } }
T{ ##peek { dst V int-regs 94 } { loc D 0 } }
T{ ##peek { dst V int-regs 96 } { loc D 1 } }
T{ ##peek { dst V int-regs 98 } { loc D 2 } }
T{ ##peek { dst V int-regs 100 } { loc D 3 } }
T{ ##peek { dst V int-regs 102 } { loc D 4 } }
T{ ##peek { dst V int-regs 106 } { loc R 0 } }
T{ ##copy { dst V int-regs 95 } { src V int-regs 94 } }
T{ ##copy { dst V int-regs 97 } { src V int-regs 96 } }
T{ ##copy { dst V int-regs 99 } { src V int-regs 98 } }
T{ ##copy { dst V int-regs 101 } { src V int-regs 100 } }
T{ ##copy { dst V int-regs 103 } { src V int-regs 102 } }
T{ ##copy { dst V int-regs 107 } { src V int-regs 106 } }
T{ ##branch }
}
5 test-bb
V{
T{ ##inc-d { n 3 } }
T{ ##inc-r { n 1 } }
T{ ##copy { dst V int-regs 95 } { src V int-regs 1 } }
T{ ##copy { dst V int-regs 97 } { src V int-regs 25 } }
T{ ##copy { dst V int-regs 99 } { src V int-regs 1 } }
T{ ##copy { dst V int-regs 101 } { src V int-regs 5 } }
T{ ##copy { dst V int-regs 103 } { src V int-regs 7 } }
T{ ##copy { dst V int-regs 107 } { src V int-regs 12 } }
T{ ##branch }
}
6 test-bb
V{
T{ ##load-immediate
{ dst V int-regs 78 }
{ val 4611686018427387896 }
}
T{ ##and
{ dst V int-regs 81 }
{ src1 V int-regs 97 }
{ src2 V int-regs 78 }
}
T{ ##set-slot-imm
{ src V int-regs 81 }
{ obj V int-regs 95 }
{ slot 3 }
{ tag 7 }
}
T{ ##inc-d { n -2 } }
T{ ##copy { dst V int-regs 110 } { src V int-regs 99 } }
T{ ##copy { dst V int-regs 111 } { src V int-regs 101 } }
T{ ##copy { dst V int-regs 112 } { src V int-regs 103 } }
T{ ##copy { dst V int-regs 117 } { src V int-regs 107 } }
T{ ##branch }
}
7 test-bb
V{
T{ ##inc-d { n 1 } }
T{ ##inc-r { n 1 } }
T{ ##copy { dst V int-regs 110 } { src V int-regs 1 } }
T{ ##copy { dst V int-regs 111 } { src V int-regs 5 } }
T{ ##copy { dst V int-regs 112 } { src V int-regs 7 } }
T{ ##copy { dst V int-regs 117 } { src V int-regs 12 } }
T{ ##branch }
}
8 test-bb
V{
T{ ##inc-d { n 1 } }
T{ ##inc-r { n -1 } }
T{ ##replace { src V int-regs 117 } { loc D 0 } }
T{ ##replace { src V int-regs 110 } { loc D 1 } }
T{ ##replace { src V int-regs 111 } { loc D 2 } }
T{ ##replace { src V int-regs 112 } { loc D 3 } }
T{ ##epilogue }
T{ ##return }
}
9 test-bb
0 get 1 get 1vector >>successors drop
1 get 2 get 8 get V{ } 2sequence >>successors drop
2 get 3 get 6 get V{ } 2sequence >>successors drop
3 get 4 get 1vector >>successors drop
4 get 5 get 1vector >>successors drop
5 get 7 get 1vector >>successors drop
6 get 7 get 1vector >>successors drop
7 get 9 get 1vector >>successors drop
8 get 9 get 1vector >>successors drop
[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test

View File

@ -31,7 +31,8 @@ IN: compiler.cfg.linear-scan
rpo number-instructions rpo number-instructions
rpo compute-live-intervals machine-registers allocate-registers rpo compute-live-intervals machine-registers allocate-registers
rpo assign-registers rpo assign-registers
rpo resolve-data-flow ; rpo resolve-data-flow
rpo check-numbering ;
: linear-scan ( cfg -- cfg' ) : linear-scan ( cfg -- cfg' )
[ [

View File

@ -1,6 +1,6 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors math sequences ; USING: kernel accessors math sequences grouping namespaces ;
IN: compiler.cfg.linear-scan.numbering IN: compiler.cfg.linear-scan.numbering
: number-instructions ( rpo -- ) : number-instructions ( rpo -- )
@ -9,3 +9,14 @@ IN: compiler.cfg.linear-scan.numbering
[ (>>insn#) ] [ drop 2 + ] 2bi [ (>>insn#) ] [ drop 2 + ] 2bi
] each ] each
] each drop ; ] each drop ;
SYMBOL: check-numbering?
ERROR: bad-numbering bb ;
: check-block-numbering ( bb -- )
dup instructions>> [ insn#>> ] map sift [ <= ] monotonic?
[ drop ] [ bad-numbering ] if ;
: check-numbering ( rpo -- )
check-numbering? get [ [ check-block-numbering ] each ] [ drop ] if ;