1 ! Copyright (C) 2009 Slava Pestov.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators combinators.short-circuit
4 compiler.cfg compiler.cfg.instructions compiler.cfg.rpo
5 compiler.cfg.utilities compiler.utilities kernel math namespaces
9 ! Tail call optimization.
15 [ first ##safepoint? ]
16 [ second ##epilogue? ]
20 : tail-call? ( bb -- ? )
22 [ instructions>> { [ length 2 >= ] [ last ##branch? ] } 1&& ]
23 [ successors>> first return? ]
26 : word-tail-call? ( bb -- ? )
27 instructions>> penultimate ##call? ;
29 : convert-tail-call ( ..a bb quot: ( ..a insn -- ..a tail-insn ) -- ..b )
32 [ pop* ] [ pop ] [ ] tri
33 [ [ ##safepoint new-insn ] dip push ]
34 [ [ ##epilogue new-insn ] dip push ]
37 [ successors>> delete-all ]
40 : convert-word-tail-call ( bb -- )
41 [ word>> ##jump new-insn ] convert-tail-call ;
43 : loop-tail-call? ( bb -- ? )
44 instructions>> penultimate
45 { [ ##call? ] [ word>> cfg get label>> eq? ] } 1&& ;
47 : convert-loop-tail-call ( bb -- )
48 ! If a word calls itself, this becomes a loop in the CFG.
53 [ [ ##safepoint new-insn ] dip push ]
54 [ [ ##branch new-insn ] dip push ]
57 [ successors>> delete-all ]
58 [ [ cfg get entry>> successors>> first ] dip successors>> push ]
61 : optimize-tail-call ( bb -- )
64 { [ dup loop-tail-call? ] [ convert-loop-tail-call ] }
65 { [ dup word-tail-call? ] [ convert-word-tail-call ] }
70 : optimize-tail-calls ( cfg -- )
71 [ [ optimize-tail-call ] each-basic-block ]
73 [ predecessors-changed ] tri ;