1 ! Copyright (C) 2008, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel math accessors sequences namespaces make
4 combinators assocs arrays locals cpu.architecture
7 compiler.cfg.comparisons
8 compiler.cfg.stack-frame
9 compiler.cfg.instructions
10 compiler.cfg.utilities ;
11 IN: compiler.cfg.linearization
13 ! Convert CFG IR to machine IR.
14 GENERIC: linearize-insn ( basic-block insn -- )
16 : linearize-basic-block ( bb -- )
18 [ dup instructions>> [ linearize-insn ] with each ]
21 M: insn linearize-insn , drop ;
23 : useless-branch? ( basic-block successor -- ? )
24 #! If our successor immediately follows us in RPO, then we
25 #! don't need to branch.
26 [ number>> ] bi@ 1 - = ; inline
28 : emit-loop-entry? ( bb successor -- ? )
30 [ nip dup predecessors>> [ swap back-edge? ] with any? ] 2bi and ;
32 : emit-branch ( bb successor -- )
33 2dup emit-loop-entry? [ _loop-entry ] when
34 2dup useless-branch? [ 2drop ] [ nip number>> _branch ] if ;
36 M: ##branch linearize-insn
37 drop dup successors>> first emit-branch ;
39 : successors ( bb -- first second ) successors>> first2 ; inline
41 : (binary-conditional) ( bb insn -- bb successor1 successor2 src1 src2 cc )
43 [ [ src1>> ] [ src2>> ] [ cc>> ] tri ] bi* ; inline
45 : binary-conditional ( bb insn -- bb successor label2 src1 src2 cc )
46 [ (binary-conditional) ]
47 [ drop dup successors>> second useless-branch? ] 2bi
48 [ [ swap number>> ] 3dip ] [ [ number>> ] 3dip negate-cc ] if ;
50 : with-regs ( insn quot -- )
51 over regs>> [ call ] dip building get last (>>regs) ; inline
53 M: ##compare-branch linearize-insn
54 [ binary-conditional _compare-branch ] with-regs emit-branch ;
56 M: ##compare-imm-branch linearize-insn
57 [ binary-conditional _compare-imm-branch ] with-regs emit-branch ;
59 M: ##compare-float-branch linearize-insn
60 [ binary-conditional _compare-float-branch ] with-regs emit-branch ;
62 : overflow-conditional ( bb insn -- bb successor label2 dst src1 src2 )
63 [ dup successors number>> ]
64 [ [ dst>> ] [ src1>> ] [ src2>> ] tri ] bi* ; inline
66 M: ##fixnum-add linearize-insn
67 [ overflow-conditional _fixnum-add ] with-regs emit-branch ;
69 M: ##fixnum-sub linearize-insn
70 [ overflow-conditional _fixnum-sub ] with-regs emit-branch ;
72 M: ##fixnum-mul linearize-insn
73 [ overflow-conditional _fixnum-mul ] with-regs emit-branch ;
75 M: ##dispatch linearize-insn
77 [ [ [ src>> ] [ temp>> ] bi _dispatch ] with-regs ]
78 [ successors>> [ number>> _dispatch-label ] each ]
81 : (compute-gc-roots) ( n live-values -- n )
84 [ drop reg-class>> reg-size + ]
88 : oop-values ( regs -- regs' )
89 [ drop reg-class>> int-regs eq? ] assoc-filter ;
91 : data-values ( regs -- regs' )
92 [ drop reg-class>> double-float-regs eq? ] assoc-filter ;
94 : compute-gc-roots ( live-values -- alist )
97 ! we put float registers last; the GC doesn't actually scan them
98 [ oop-values (compute-gc-roots) ]
99 [ data-values (compute-gc-roots) ] bi
103 : count-gc-roots ( live-values -- n )
104 ! Size of GC root area, minus the float registers
105 oop-values assoc-size ;
107 M: ##gc linearize-insn
122 : linearize-basic-blocks ( cfg -- insns )
124 [ [ linearize-basic-block ] each-basic-block ]
125 [ spill-counts>> _spill-counts ]
129 : flatten-cfg ( cfg -- mr )
130 [ linearize-basic-blocks ] [ word>> ] [ label>> ] tri