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 ]
|
||||
[ handle-sync-point ] bi ;
|
||||
|
||||
: live-interval-or-sync-point ( intervals sync-points -- live-interval )
|
||||
2array [ heap-empty? not ] filter [ heap-peek nip ] infimum-by
|
||||
heap-pop drop ;
|
||||
|
||||
: (allocate-registers) ( unhandled-intervals unhandled-sync-points -- )
|
||||
2dup [ heap-empty? ] both? [ 2drop ] [
|
||||
[ live-interval-or-sync-point handle ]
|
||||
[ (allocate-registers) ]
|
||||
2bi
|
||||
! TODO: use slurp-heap
|
||||
: (allocate-registers) ( unhandled-min-heap -- )
|
||||
dup heap-empty? [ drop ] [
|
||||
[ heap-pop drop handle ] keep (allocate-registers)
|
||||
] if ;
|
||||
|
||||
: finish-allocation ( -- )
|
||||
|
@ -76,6 +71,6 @@ M: sync-point handle ( sync-point -- )
|
|||
|
||||
: allocate-registers ( live-intervals sync-point machine-registers -- live-intervals )
|
||||
init-allocator
|
||||
unhandled-intervals get unhandled-sync-points get (allocate-registers)
|
||||
unhandled-min-heap get (allocate-registers)
|
||||
finish-allocation
|
||||
handled-intervals get ;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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
|
||||
|
||||
{
|
||||
|
@ -12,3 +13,46 @@ IN: compiler.cfg.linear-scan.allocation.state.tests
|
|||
[ 8 next-spill-slot ] twice
|
||||
cfg get
|
||||
] 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.
|
||||
! 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.linear-scan.live-intervals compiler.cfg.registers
|
||||
cpu.architecture fry heaps kernel layouts linked-assocs math
|
||||
math.order namespaces sequences ;
|
||||
compiler.cfg.linear-scan.live-intervals linked-assocs slots.syntax ;
|
||||
FROM: assocs => change-at ;
|
||||
IN: compiler.cfg.linear-scan.allocation.state
|
||||
|
||||
|
@ -22,11 +22,20 @@ SYMBOL: progress
|
|||
: check-handled ( live-interval -- )
|
||||
end>> progress get > [ "check-handled" throw ] when ; inline
|
||||
|
||||
: live-intervals>min-heap ( live-intervals -- min-heap )
|
||||
[ [ start>> ] map ] keep zip >min-heap ;
|
||||
SYMBOL: unhandled-min-heap
|
||||
|
||||
: sync-points>min-heap ( sync-points -- min-heap )
|
||||
[ [ n>> ] map ] keep zip >min-heap ;
|
||||
: live-interval-key ( live-interval -- key )
|
||||
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
|
||||
SYMBOL: registers
|
||||
|
@ -112,12 +121,11 @@ ERROR: register-already-used live-interval ;
|
|||
[ don't-change ]
|
||||
} process-intervals ;
|
||||
|
||||
SYMBOL: unhandled-intervals
|
||||
|
||||
: add-unhandled ( live-interval -- )
|
||||
[ 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-classes ] dip { } map>assoc ; inline
|
||||
|
@ -130,8 +138,6 @@ SYMBOL: unhandled-intervals
|
|||
: align-spill-area ( align -- )
|
||||
cfg get [ max ] change-spill-area-align drop ;
|
||||
|
||||
SYMBOL: unhandled-sync-points
|
||||
|
||||
SYMBOL: spill-slots
|
||||
|
||||
: assign-spill-slot ( coalesced-vreg rep -- spill-slot )
|
||||
|
@ -145,9 +151,7 @@ SYMBOL: spill-slots
|
|||
|
||||
: init-allocator ( live-intervals sync-points registers -- )
|
||||
registers set
|
||||
[ live-intervals>min-heap unhandled-intervals set ]
|
||||
[ sync-points>min-heap unhandled-sync-points set ] bi*
|
||||
|
||||
>unhandled-min-heap unhandled-min-heap set
|
||||
[ V{ } clone ] reg-class-assoc active-intervals set
|
||||
[ V{ } clone ] reg-class-assoc inactive-intervals set
|
||||
V{ } clone handled-intervals set
|
||||
|
|
Loading…
Reference in New Issue