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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 0 8 } T{ live-range f 10 18 } T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 0 8 } T{ live-range f 10 18 } T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 0 20 } } } } 15 split-for-spill clean-up-split ] unit-test { f T{ live-interval-state { vreg 7 } { start 8 } { end 8 } { ranges V{ T{ live-range f 8 8 } } } { uses V{ T{ vreg-use f 8 int-rep } } } } } [ T{ live-interval-state { vreg 7 } { start 4 } { end 8 } { ranges V{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 0 4 } T{ live-range f 6 10 } T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 0 2 } T{ live-range f 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{ T{ live-range f 0 2 } T{ live-range f 10 20 } } } } T{ live-interval-state { vreg 3 } { start 4 } { end 8 } { uses V{ T{ vreg-use f 6 int-rep f } } } { ranges V{ T{ live-range f 4 8 } } } } T{ live-interval-state { vreg 4 } { start 4 } { end 8 } { uses V{ T{ vreg-use f 8 int-rep f } } } { ranges V{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 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{ T{ live-range f 0 2 } T{ live-range f 10 20 } } } { uses V{ 0 2 10 20 } } } T{ live-interval-state { vreg 2 } { start 4 } { end 40 } { reg 0 } { ranges V{ T{ live-range f 4 6 } T{ live-range f 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{ T{ live-range f 0 40 } } } { uses V{ 0 40 } } } } } } active-intervals set T{ live-interval-state { vreg 4 } { start 8 } { end 10 } { ranges V{ T{ live-range f 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