1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators.short-circuit kernel math
4 namespaces sequences fry combinators
9 compiler.cfg.instructions
10 compiler.cfg.utilities ;
13 ! Tail call optimization.
23 : tail-call? ( bb -- ? )
25 [ instructions>> { [ length 2 >= ] [ last ##branch? ] } 1&& ]
26 [ successors>> first return? ]
29 : word-tail-call? ( bb -- ? )
30 instructions>> penultimate ##call? ;
32 : convert-tail-call ( ..a bb quot: ( ..a insn -- ..a tail-insn ) -- ..b )
35 [ pop* ] [ pop ] [ ] tri
36 [ [ \ ##epilogue new-insn ] dip push ]
39 [ successors>> delete-all ]
42 : convert-word-tail-call ( bb -- )
43 [ word>> \ ##jump new-insn ] convert-tail-call ;
45 : loop-tail-call? ( bb -- ? )
46 instructions>> penultimate
47 { [ ##call? ] [ word>> cfg get label>> eq? ] } 1&& ;
49 : convert-loop-tail-call ( bb -- )
50 ! If a word calls itself, this becomes a loop in the CFG.
51 [ instructions>> [ pop* ] [ pop* ] [ [ \ ##branch new-insn ] dip push ] tri ]
52 [ successors>> delete-all ]
53 [ [ cfg get entry>> successors>> first ] dip successors>> push ]
56 : optimize-tail-call ( bb -- )
59 { [ dup loop-tail-call? ] [ convert-loop-tail-call ] }
60 { [ dup word-tail-call? ] [ convert-word-tail-call ] }
65 : optimize-tail-calls ( cfg -- cfg' )
66 dup [ optimize-tail-call ] each-basic-block
68 cfg-changed predecessors-changed ;