1 ! Copyright (C) 2009 Slava Pestov.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs combinators.short-circuit compiler.cfg
4 compiler.cfg.predecessors compiler.cfg.utilities deques dlists
5 kernel namespaces sequences sets ;
6 IN: compiler.cfg.loop-detection
8 TUPLE: natural-loop header index ends blocks ;
14 : <natural-loop> ( header index -- loop )
15 HS{ } clone HS{ } clone natural-loop boa ;
17 : lookup-header ( header -- loop )
18 loops get dup '[ _ assoc-size <natural-loop> ] cache ;
20 SYMBOLS: visited active ;
22 : record-back-edge ( from to -- )
23 lookup-header ends>> adjoin ;
25 DEFER: find-loop-headers
27 : visit-edge ( from to active -- )
30 [ nip find-loop-headers ]
33 : find-loop-headers ( bb -- )
34 dup visited get ?adjoin [
37 [ [ dup successors>> ] dip '[ _ visit-edge ] with each ]
42 : process-loop-block ( bb loop -- bbs )
43 dupd { [ blocks>> ?adjoin ] [ header>> eq? not ] } 2&&
44 swap predecessors>> { } ? ;
46 : process-loop-ends ( loop -- )
47 dup ends>> members <dlist> [ push-all-front ] keep
48 swap '[ _ process-loop-block ] slurp/replenish-deque ;
50 : process-loop-headers ( -- )
51 loops get values [ process-loop-ends ] each ;
55 : compute-loop-nesting ( -- )
56 loops get H{ } clone [
57 [ values ] dip '[ blocks>> members [ _ inc-at ] each ] each
58 ] keep loop-nesting namespaces:set ;
60 : detect-loops ( cfg -- cfg' )
61 H{ } clone loops namespaces:set
62 HS{ } clone visited namespaces:set
63 HS{ } clone active namespaces:set
64 H{ } clone loop-nesting namespaces:set
65 [ needs-predecessors ]
66 [ entry>> find-loop-headers process-loop-headers compute-loop-nesting ]
71 : loop-nesting-at ( bb -- n ) loop-nesting get at 0 or ;
73 : current-loop-nesting ( -- n ) basic-block get loop-nesting-at ;
75 : needs-loops ( cfg -- )
76 dup needs-predecessors
77 dup loops-valid?>> [ detect-loops t >>loops-valid? ] unless