684 lines
16 KiB
Factor
684 lines
16 KiB
Factor
USING: tools.test random sorting sequences sets hashtables assocs
|
|
kernel fry arrays splitting namespaces math accessors vectors locals
|
|
math.order grouping strings strings.private classes layouts
|
|
cpu.architecture
|
|
compiler.cfg
|
|
compiler.cfg.optimizer
|
|
compiler.cfg.instructions
|
|
compiler.cfg.registers
|
|
compiler.cfg.predecessors
|
|
compiler.cfg.rpo
|
|
compiler.cfg.debugger
|
|
compiler.cfg.def-use
|
|
compiler.cfg.comparisons
|
|
compiler.cfg.ssa.destruction.leaders
|
|
compiler.cfg.linear-scan
|
|
compiler.cfg.linear-scan.allocation
|
|
compiler.cfg.linear-scan.allocation.state
|
|
compiler.cfg.linear-scan.allocation.splitting
|
|
compiler.cfg.linear-scan.allocation.spilling
|
|
compiler.cfg.linear-scan.live-intervals
|
|
compiler.cfg.linear-scan.numbering
|
|
compiler.cfg.linear-scan.ranges
|
|
compiler.cfg.linear-scan.debugger
|
|
compiler.cfg.utilities ;
|
|
IN: compiler.cfg.linear-scan.tests
|
|
|
|
check-allocation? on
|
|
check-numbering? on
|
|
|
|
! Live interval calculation
|
|
|
|
! A value is defined and never used; make sure it has the right
|
|
! live range
|
|
V{
|
|
T{ ##load-integer f 1 0 }
|
|
T{ ##replace-imm f D: 0 "hi" }
|
|
T{ ##branch }
|
|
} 0 test-bb
|
|
|
|
: test-live-intervals ( -- )
|
|
0 get block>cfg
|
|
[ cfg set ] [ number-instructions ] [ compute-live-intervals ] tri
|
|
drop ;
|
|
|
|
{ } [
|
|
H{
|
|
{ 1 int-rep }
|
|
} representations set
|
|
H{
|
|
{ 1 1 }
|
|
} leader-map set
|
|
test-live-intervals
|
|
] unit-test
|
|
|
|
{ 0 0 } [
|
|
1 live-intervals get at [ start>> ] [ end>> ] bi
|
|
] unit-test
|
|
|
|
! Live interval splitting
|
|
|
|
cfg new 0 >>spill-area-size 4 >>spill-area-align cfg set
|
|
H{ } spill-slots set
|
|
|
|
H{
|
|
{ 1 float-rep }
|
|
{ 2 float-rep }
|
|
{ 3 float-rep }
|
|
} representations set
|
|
|
|
: clean-up-split ( a b -- a b )
|
|
[ dup [ [ >vector ] change-uses [ >vector ] change-ranges ] when ] bi@ ;
|
|
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 2 }
|
|
{ uses V{ T{ vreg-use f 0 float-rep f } T{ vreg-use f 1 f float-rep } } }
|
|
{ ranges V{ { 0 2 } } }
|
|
{ spill-to T{ spill-slot f 0 } }
|
|
{ spill-rep float-rep }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 5 }
|
|
{ end 5 }
|
|
{ uses V{ T{ vreg-use f 5 f float-rep } } }
|
|
{ ranges V{ { 5 5 } } }
|
|
{ reload-from T{ spill-slot f 0 } }
|
|
{ reload-rep float-rep }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 5 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 float-rep f }
|
|
T{ vreg-use f 1 f float-rep }
|
|
T{ vreg-use f 5 f float-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 5 } } }
|
|
} 2 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
{
|
|
f
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 1 }
|
|
{ end 5 }
|
|
{ uses V{ T{ vreg-use f 1 f float-rep } T{ vreg-use f 5 f float-rep } } }
|
|
{ ranges V{ { 1 5 } } }
|
|
{ reload-from T{ spill-slot f 4 } }
|
|
{ reload-rep float-rep }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 0 }
|
|
{ end 5 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 float-rep f }
|
|
T{ vreg-use f 1 f float-rep }
|
|
T{ vreg-use f 5 f float-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 5 } } }
|
|
} 0 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 3 }
|
|
{ start 0 }
|
|
{ end 2 }
|
|
{ uses V{ T{ vreg-use f 0 float-rep f } T{ vreg-use f 1 f float-rep } } }
|
|
{ ranges V{ { 0 2 } } }
|
|
{ spill-to T{ spill-slot f 8 } }
|
|
{ spill-rep float-rep }
|
|
}
|
|
f
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 3 }
|
|
{ start 0 }
|
|
{ end 5 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 float-rep f }
|
|
T{ vreg-use f 1 f float-rep }
|
|
T{ vreg-use f 5 f float-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 5 } } }
|
|
} 5 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 4 }
|
|
{ start 0 }
|
|
{ end 1 }
|
|
{ uses V{ T{ vreg-use f 0 float-rep f } } }
|
|
{ ranges V{ { 0 1 } } }
|
|
{ spill-to T{ spill-slot f 12 } }
|
|
{ spill-rep float-rep }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 4 }
|
|
{ start 20 }
|
|
{ end 30 }
|
|
{ uses V{ T{ vreg-use f 20 f float-rep } T{ vreg-use f 30 f float-rep } } }
|
|
{ ranges V{ { 20 30 } } }
|
|
{ reload-from T{ spill-slot f 12 } }
|
|
{ reload-rep float-rep }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 4 }
|
|
{ start 0 }
|
|
{ end 30 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 float-rep f }
|
|
T{ vreg-use f 20 f float-rep }
|
|
T{ vreg-use f 30 f float-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 8 } { 10 18 } { 20 30 } } }
|
|
} 10 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
! Don't insert reload if first usage is a def
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 5 }
|
|
{ start 0 }
|
|
{ end 1 }
|
|
{ uses V{ T{ vreg-use f 0 float-rep f } } }
|
|
{ ranges V{ { 0 1 } } }
|
|
{ spill-to T{ spill-slot f 16 } }
|
|
{ spill-rep float-rep }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 5 }
|
|
{ start 20 }
|
|
{ end 30 }
|
|
{ uses V{ T{ vreg-use f 20 float-rep f } T{ vreg-use f 30 f float-rep } } }
|
|
{ ranges V{ { 20 30 } } }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 5 }
|
|
{ start 0 }
|
|
{ end 30 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 float-rep f }
|
|
T{ vreg-use f 20 float-rep f }
|
|
T{ vreg-use f 30 f float-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 8 } { 10 18 } { 20 30 } } }
|
|
} 10 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
! Multiple representations
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 6 }
|
|
{ start 0 }
|
|
{ end 11 }
|
|
{ uses V{ T{ vreg-use f 0 float-rep f } T{ vreg-use f 10 double-rep float-rep } } }
|
|
{ ranges V{ { 0 11 } } }
|
|
{ spill-to T{ spill-slot f 24 } }
|
|
{ spill-rep double-rep }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 6 }
|
|
{ start 20 }
|
|
{ end 20 }
|
|
{ uses V{ T{ vreg-use f 20 f double-rep } } }
|
|
{ ranges V{ { 20 20 } } }
|
|
{ reload-from T{ spill-slot f 24 } }
|
|
{ reload-rep double-rep }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 6 }
|
|
{ start 0 }
|
|
{ end 20 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 float-rep f }
|
|
T{ vreg-use f 10 double-rep float-rep }
|
|
T{ vreg-use f 20 f double-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 20 } } }
|
|
} 15 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
{
|
|
f
|
|
T{ live-interval-state
|
|
{ vreg 7 }
|
|
{ start 8 }
|
|
{ end 8 }
|
|
{ ranges V{ { 8 8 } } }
|
|
{ uses V{ T{ vreg-use f 8 int-rep } } }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 7 }
|
|
{ start 4 }
|
|
{ end 8 }
|
|
{ ranges V{ { 4 8 } } }
|
|
{ uses V{ T{ vreg-use f 8 int-rep } } }
|
|
} 4 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
! trim-before-ranges, trim-after-ranges
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 8 }
|
|
{ start 0 }
|
|
{ end 3 }
|
|
{ ranges V{ { 0 3 } } }
|
|
{ uses V{ T{ vreg-use f 0 f int-rep } T{ vreg-use f 2 f int-rep } } }
|
|
{ spill-to T{ spill-slot f 32 } }
|
|
{ spill-rep int-rep }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 8 }
|
|
{ start 14 }
|
|
{ end 16 }
|
|
{ ranges V{ { 14 16 } } }
|
|
{ uses V{ T{ vreg-use f 14 f int-rep } } }
|
|
{ reload-from T{ spill-slot f 32 } }
|
|
{ reload-rep int-rep }
|
|
}
|
|
} [
|
|
T{ live-interval-state
|
|
{ vreg 8 }
|
|
{ start 0 }
|
|
{ end 16 }
|
|
{ ranges V{ { 0 4 } { 6 10 } { 12 16 } } }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 f int-rep }
|
|
T{ vreg-use f 2 f int-rep }
|
|
T{ vreg-use f 14 f int-rep } }
|
|
}
|
|
} 8 split-for-spill
|
|
clean-up-split
|
|
] unit-test
|
|
|
|
H{
|
|
{ 1 int-rep }
|
|
{ 2 int-rep }
|
|
{ 3 int-rep }
|
|
} representations set
|
|
|
|
{
|
|
{
|
|
3
|
|
10
|
|
}
|
|
} [
|
|
H{
|
|
{ int-regs
|
|
V{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ reg 1 }
|
|
{ start 1 }
|
|
{ end 15 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 1 int-rep f }
|
|
T{ vreg-use f 3 f int-rep }
|
|
T{ vreg-use f 7 f int-rep }
|
|
T{ vreg-use f 10 f int-rep }
|
|
T{ vreg-use f 15 f int-rep }
|
|
}
|
|
}
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ reg 2 }
|
|
{ start 3 }
|
|
{ end 8 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 3 int-rep f }
|
|
T{ vreg-use f 4 f int-rep }
|
|
T{ vreg-use f 8 f int-rep }
|
|
}
|
|
}
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 3 }
|
|
{ reg 3 }
|
|
{ start 3 }
|
|
{ end 10 }
|
|
{ uses V{ T{ vreg-use f 3 int-rep f } T{ vreg-use f 10 f int-rep } } }
|
|
}
|
|
}
|
|
}
|
|
} active-intervals set
|
|
H{ } inactive-intervals set
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 5 }
|
|
{ end 5 }
|
|
{ uses V{ T{ vreg-use f 5 int-rep f } } }
|
|
}
|
|
spill-status
|
|
] unit-test
|
|
|
|
{
|
|
{
|
|
1
|
|
1/0.
|
|
}
|
|
} [
|
|
H{
|
|
{ int-regs
|
|
V{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ reg 1 }
|
|
{ start 1 }
|
|
{ end 15 }
|
|
{ uses V{ T{ vreg-use f 1 int-rep f } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ reg 2 }
|
|
{ start 3 }
|
|
{ end 8 }
|
|
{ uses V{ T{ vreg-use f 3 int-rep f } T{ vreg-use f 8 f int-rep } } }
|
|
}
|
|
}
|
|
}
|
|
} active-intervals set
|
|
H{ } inactive-intervals set
|
|
T{ live-interval-state
|
|
{ vreg 3 }
|
|
{ start 5 }
|
|
{ end 5 }
|
|
{ uses V{ T{ vreg-use f 5 int-rep f } } }
|
|
}
|
|
spill-status
|
|
] unit-test
|
|
|
|
H{ { 1 int-rep } { 2 int-rep } } representations set
|
|
|
|
{ } [
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 100 }
|
|
{ uses V{ T{ vreg-use f 0 int-rep f } T{ vreg-use f 100 f int-rep } } }
|
|
{ ranges V{ { 0 100 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" } } }
|
|
check-linear-scan
|
|
] unit-test
|
|
|
|
{ } [
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 10 }
|
|
{ uses V{ T{ vreg-use f 0 int-rep f } T{ vreg-use f 10 f int-rep } } }
|
|
{ ranges V{ { 0 10 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 11 }
|
|
{ end 20 }
|
|
{ uses V{ T{ vreg-use f 11 int-rep f } T{ vreg-use f 20 f int-rep } } }
|
|
{ ranges V{ { 11 20 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" } } }
|
|
check-linear-scan
|
|
] unit-test
|
|
|
|
{ } [
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 100 }
|
|
{ uses V{ T{ vreg-use f 0 int-rep f } T{ vreg-use f 100 f int-rep } } }
|
|
{ ranges V{ { 0 100 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 30 }
|
|
{ end 60 }
|
|
{ uses V{ T{ vreg-use f 30 int-rep f } T{ vreg-use f 60 f int-rep } } }
|
|
{ ranges V{ { 30 60 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" } } }
|
|
check-linear-scan
|
|
] unit-test
|
|
|
|
{ } [
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 100 }
|
|
{ uses V{ T{ vreg-use f 0 int-rep f } T{ vreg-use f 100 f int-rep } } }
|
|
{ ranges V{ { 0 100 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 30 }
|
|
{ end 200 }
|
|
{ uses V{ T{ vreg-use f 30 int-rep f } T{ vreg-use f 200 f int-rep } } }
|
|
{ ranges V{ { 30 200 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" } } }
|
|
check-linear-scan
|
|
] unit-test
|
|
|
|
[
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 100 }
|
|
{ uses V{ T{ vreg-use f 0 int-rep f } T{ vreg-use f 100 f int-rep } } }
|
|
{ ranges V{ { 0 100 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 30 }
|
|
{ end 100 }
|
|
{ uses V{ T{ vreg-use f 30 int-rep f } T{ vreg-use f 100 f int-rep } } }
|
|
{ ranges V{ { 30 100 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" } } }
|
|
check-linear-scan
|
|
] must-fail
|
|
|
|
! Problem with spilling intervals with no more usages after the spill location
|
|
H{
|
|
{ 1 int-rep }
|
|
{ 2 int-rep }
|
|
{ 3 int-rep }
|
|
{ 4 int-rep }
|
|
{ 5 int-rep }
|
|
} representations set
|
|
|
|
{ } [
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 20 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 int-rep f }
|
|
T{ vreg-use f 10 f int-rep }
|
|
T{ vreg-use f 20 f int-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 2 } { 10 20 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 0 }
|
|
{ end 20 }
|
|
{ uses
|
|
V{
|
|
T{ vreg-use f 0 int-rep f }
|
|
T{ vreg-use f 10 f int-rep }
|
|
T{ vreg-use f 20 f int-rep }
|
|
}
|
|
}
|
|
{ ranges V{ { 0 2 } { 10 20 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 3 }
|
|
{ start 4 }
|
|
{ end 8 }
|
|
{ uses V{ T{ vreg-use f 6 int-rep f } } }
|
|
{ ranges V{ { 4 8 } } }
|
|
}
|
|
T{ live-interval-state
|
|
{ vreg 4 }
|
|
{ start 4 }
|
|
{ end 8 }
|
|
{ uses V{ T{ vreg-use f 8 int-rep f } } }
|
|
{ ranges V{ { 4 8 } } }
|
|
}
|
|
|
|
! This guy will invoke the 'spill partially available' code path
|
|
T{ live-interval-state
|
|
{ vreg 5 }
|
|
{ start 4 }
|
|
{ end 8 }
|
|
{ uses V{ T{ vreg-use f 8 int-rep f } } }
|
|
{ ranges V{ { 4 8 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" "B" } } }
|
|
check-linear-scan
|
|
] unit-test
|
|
|
|
! Test spill-new code path
|
|
|
|
{ } [
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 10 }
|
|
{ uses V{ T{ vreg-use f 0 int-rep f } T{ vreg-use f 6 f int-rep } T{ vreg-use f 10 f int-rep } } }
|
|
{ ranges V{ { 0 10 } } }
|
|
}
|
|
|
|
! This guy will invoke the 'spill new' code path
|
|
T{ live-interval-state
|
|
{ vreg 5 }
|
|
{ start 2 }
|
|
{ end 8 }
|
|
{ uses V{ T{ vreg-use f 8 int-rep f } } }
|
|
{ ranges V{ { 2 8 } } }
|
|
}
|
|
}
|
|
H{ { int-regs { "A" } } }
|
|
check-linear-scan
|
|
] unit-test
|
|
|
|
! register-status had problems because it used map>assoc where the sequence
|
|
! had multiple keys
|
|
H{
|
|
{ 1 int-rep }
|
|
{ 2 int-rep }
|
|
{ 3 int-rep }
|
|
{ 4 int-rep }
|
|
} representations set
|
|
|
|
{ { 0 10 } } [
|
|
H{
|
|
{ int-regs
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 1 }
|
|
{ start 0 }
|
|
{ end 20 }
|
|
{ reg 0 }
|
|
{ ranges V{ { 0 2 } { 10 20 } } }
|
|
{ uses V{ 0 2 10 20 } }
|
|
}
|
|
|
|
T{ live-interval-state
|
|
{ vreg 2 }
|
|
{ start 4 }
|
|
{ end 40 }
|
|
{ reg 0 }
|
|
{ ranges V{ { 4 6 } { 30 40 } } }
|
|
{ uses V{ 4 6 30 40 } }
|
|
}
|
|
}
|
|
}
|
|
} inactive-intervals set
|
|
H{
|
|
{ int-regs
|
|
{
|
|
T{ live-interval-state
|
|
{ vreg 3 }
|
|
{ start 0 }
|
|
{ end 40 }
|
|
{ reg 1 }
|
|
{ ranges V{ { 0 40 } } }
|
|
{ uses V{ 0 40 } }
|
|
}
|
|
}
|
|
}
|
|
} active-intervals set
|
|
|
|
T{ live-interval-state
|
|
{ vreg 4 }
|
|
{ start 8 }
|
|
{ end 10 }
|
|
{ ranges V{ { 8 10 } } }
|
|
{ uses V{ T{ vreg-use f 8 int-rep f } T{ vreg-use f 10 f int-rep } } }
|
|
}
|
|
H{ { int-regs { 0 1 } } } register-status
|
|
] unit-test
|
|
|
|
{ t } [
|
|
T{ cfg { frame-pointer? f } } admissible-registers machine-registers =
|
|
] unit-test
|
|
|
|
{ f } [
|
|
T{ cfg { frame-pointer? t } } admissible-registers
|
|
int-regs of frame-reg swap member?
|
|
] unit-test
|