compiler.cfg.linear-scan.allocation.*: maybe a fix for #1227
The register allocator pops from the unhandled-intervals and unhandled-sync-points heaps. If two live intervals share the same start slot, then they can be popped in either order leading to differently generated code. So instead use one heap (unhandled-min-heap) and both the start and end slot as the heap key to resolve tie-breakersdb4
parent
fd0b0cbf9e
commit
35d00da765
|
@ -59,15 +59,10 @@ M: sync-point handle ( sync-point -- )
|
||||||
[ n>> [ deactivate-intervals ] [ activate-intervals ] bi ]
|
[ n>> [ deactivate-intervals ] [ activate-intervals ] bi ]
|
||||||
[ handle-sync-point ] bi ;
|
[ handle-sync-point ] bi ;
|
||||||
|
|
||||||
: live-interval-or-sync-point ( intervals sync-points -- live-interval )
|
! TODO: use slurp-heap
|
||||||
2array [ heap-empty? not ] filter [ heap-peek nip ] infimum-by
|
: (allocate-registers) ( unhandled-min-heap -- )
|
||||||
heap-pop drop ;
|
dup heap-empty? [ drop ] [
|
||||||
|
[ heap-pop drop handle ] keep (allocate-registers)
|
||||||
: (allocate-registers) ( unhandled-intervals unhandled-sync-points -- )
|
|
||||||
2dup [ heap-empty? ] both? [ 2drop ] [
|
|
||||||
[ live-interval-or-sync-point handle ]
|
|
||||||
[ (allocate-registers) ]
|
|
||||||
2bi
|
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
: finish-allocation ( -- )
|
: finish-allocation ( -- )
|
||||||
|
@ -76,6 +71,6 @@ M: sync-point handle ( sync-point -- )
|
||||||
|
|
||||||
: allocate-registers ( live-intervals sync-point machine-registers -- live-intervals )
|
: allocate-registers ( live-intervals sync-point machine-registers -- live-intervals )
|
||||||
init-allocator
|
init-allocator
|
||||||
unhandled-intervals get unhandled-sync-points get (allocate-registers)
|
unhandled-min-heap get (allocate-registers)
|
||||||
finish-allocation
|
finish-allocation
|
||||||
handled-intervals get ;
|
handled-intervals get ;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
USING: combinators.extras compiler.cfg compiler.cfg.instructions
|
USING: combinators.extras compiler.cfg compiler.cfg.instructions
|
||||||
compiler.cfg.linear-scan.allocation.state kernel namespaces tools.test ;
|
compiler.cfg.linear-scan.allocation.state
|
||||||
|
compiler.cfg.linear-scan.live-intervals heaps kernel namespaces tools.test ;
|
||||||
IN: compiler.cfg.linear-scan.allocation.state.tests
|
IN: compiler.cfg.linear-scan.allocation.state.tests
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -12,3 +13,46 @@ IN: compiler.cfg.linear-scan.allocation.state.tests
|
||||||
[ 8 next-spill-slot ] twice
|
[ 8 next-spill-slot ] twice
|
||||||
cfg get
|
cfg get
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
{ { 33 1/0.0 } } [
|
||||||
|
T{ sync-point { n 33 } } sync-point-key
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{ { 5 1/0. } T{ sync-point { n 5 } } }
|
||||||
|
{
|
||||||
|
{ 20 28 }
|
||||||
|
T{ live-interval-state { start 20 } { end 28 } }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
{ 20 30 }
|
||||||
|
T{ live-interval-state { start 20 } { end 30 } }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
{ 33 999 }
|
||||||
|
T{ live-interval-state { start 33 } { end 999 } }
|
||||||
|
}
|
||||||
|
{ { 33 1/0. } T{ sync-point { n 33 } } }
|
||||||
|
{ { 100 1/0. } T{ sync-point { n 100 } } }
|
||||||
|
}
|
||||||
|
} [
|
||||||
|
{
|
||||||
|
T{ live-interval-state { start 20 } { end 30 } }
|
||||||
|
T{ live-interval-state { start 20 } { end 28 } }
|
||||||
|
T{ live-interval-state { start 33 } { end 999 } }
|
||||||
|
}
|
||||||
|
{
|
||||||
|
T{ sync-point { n 5 } }
|
||||||
|
T{ sync-point { n 33 } }
|
||||||
|
T{ sync-point { n 100 } }
|
||||||
|
}
|
||||||
|
>unhandled-min-heap heap-pop-all
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ 2 } [
|
||||||
|
{
|
||||||
|
T{ live-interval-state { start 20 } { end 30 } }
|
||||||
|
T{ live-interval-state { start 20 } { end 30 } }
|
||||||
|
} { } >unhandled-min-heap heap-size
|
||||||
|
] unit-test
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
! Copyright (C) 2009, 2010 Slava Pestov.
|
! Copyright (C) 2009, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors arrays assocs combinators compiler.cfg
|
USING: arrays accessors assocs combinators cpu.architecture fry
|
||||||
|
heaps kernel math math.order namespaces layouts sequences vectors
|
||||||
|
compiler.cfg compiler.cfg.registers
|
||||||
compiler.cfg.instructions
|
compiler.cfg.instructions
|
||||||
compiler.cfg.linear-scan.live-intervals compiler.cfg.registers
|
compiler.cfg.linear-scan.live-intervals linked-assocs slots.syntax ;
|
||||||
cpu.architecture fry heaps kernel layouts linked-assocs math
|
|
||||||
math.order namespaces sequences ;
|
|
||||||
FROM: assocs => change-at ;
|
FROM: assocs => change-at ;
|
||||||
IN: compiler.cfg.linear-scan.allocation.state
|
IN: compiler.cfg.linear-scan.allocation.state
|
||||||
|
|
||||||
|
@ -22,11 +22,20 @@ SYMBOL: progress
|
||||||
: check-handled ( live-interval -- )
|
: check-handled ( live-interval -- )
|
||||||
end>> progress get > [ "check-handled" throw ] when ; inline
|
end>> progress get > [ "check-handled" throw ] when ; inline
|
||||||
|
|
||||||
: live-intervals>min-heap ( live-intervals -- min-heap )
|
SYMBOL: unhandled-min-heap
|
||||||
[ [ start>> ] map ] keep zip >min-heap ;
|
|
||||||
|
|
||||||
: sync-points>min-heap ( sync-points -- min-heap )
|
: live-interval-key ( live-interval -- key )
|
||||||
[ [ n>> ] map ] keep zip >min-heap ;
|
get{ start end } ;
|
||||||
|
|
||||||
|
: sync-point-key ( sync-point -- key )
|
||||||
|
n>> 1/0.0 2array ;
|
||||||
|
|
||||||
|
: zip-keyed ( seq quot: ( elt -- key ) -- assoc )
|
||||||
|
dupd map swap zip ; inline
|
||||||
|
|
||||||
|
: >unhandled-min-heap ( live-intervals sync-points -- min-heap )
|
||||||
|
[ [ live-interval-key ] zip-keyed ]
|
||||||
|
[ [ sync-point-key ] zip-keyed ] bi* append >min-heap ;
|
||||||
|
|
||||||
! Mapping from register classes to sequences of machine registers
|
! Mapping from register classes to sequences of machine registers
|
||||||
SYMBOL: registers
|
SYMBOL: registers
|
||||||
|
@ -112,12 +121,11 @@ ERROR: register-already-used live-interval ;
|
||||||
[ don't-change ]
|
[ don't-change ]
|
||||||
} process-intervals ;
|
} process-intervals ;
|
||||||
|
|
||||||
SYMBOL: unhandled-intervals
|
|
||||||
|
|
||||||
: add-unhandled ( live-interval -- )
|
: add-unhandled ( live-interval -- )
|
||||||
[ check-unhandled ]
|
[ check-unhandled ]
|
||||||
[ dup start>> unhandled-intervals get heap-push ]
|
[
|
||||||
bi ;
|
dup live-interval-key unhandled-min-heap get heap-push
|
||||||
|
] bi ;
|
||||||
|
|
||||||
: reg-class-assoc ( quot -- assoc )
|
: reg-class-assoc ( quot -- assoc )
|
||||||
[ reg-classes ] dip { } map>assoc ; inline
|
[ reg-classes ] dip { } map>assoc ; inline
|
||||||
|
@ -130,8 +138,6 @@ SYMBOL: unhandled-intervals
|
||||||
: align-spill-area ( align -- )
|
: align-spill-area ( align -- )
|
||||||
cfg get [ max ] change-spill-area-align drop ;
|
cfg get [ max ] change-spill-area-align drop ;
|
||||||
|
|
||||||
SYMBOL: unhandled-sync-points
|
|
||||||
|
|
||||||
SYMBOL: spill-slots
|
SYMBOL: spill-slots
|
||||||
|
|
||||||
: assign-spill-slot ( coalesced-vreg rep -- spill-slot )
|
: assign-spill-slot ( coalesced-vreg rep -- spill-slot )
|
||||||
|
@ -145,9 +151,7 @@ SYMBOL: spill-slots
|
||||||
|
|
||||||
: init-allocator ( live-intervals sync-points registers -- )
|
: init-allocator ( live-intervals sync-points registers -- )
|
||||||
registers set
|
registers set
|
||||||
[ live-intervals>min-heap unhandled-intervals set ]
|
>unhandled-min-heap unhandled-min-heap set
|
||||||
[ sync-points>min-heap unhandled-sync-points set ] bi*
|
|
||||||
|
|
||||||
[ V{ } clone ] reg-class-assoc active-intervals set
|
[ V{ } clone ] reg-class-assoc active-intervals set
|
||||||
[ V{ } clone ] reg-class-assoc inactive-intervals set
|
[ V{ } clone ] reg-class-assoc inactive-intervals set
|
||||||
V{ } clone handled-intervals set
|
V{ } clone handled-intervals set
|
||||||
|
|
Loading…
Reference in New Issue