Annotation of researchv10no/cmd/sml/src/cps/spill.sml, revision 1.1.1.1

1.1       root        1: (* Copyright 1989 by AT&T Bell Laboratories *)
                      2: signature SPILL =
                      3:   sig val spill : (CPS.function * bool) list * (CPS.lvar -> bool)
                      4:                                 * (int * int * CPS.cexp -> CPS.cexp) ->
                      5:                        (CPS.function * bool) list
                      6:   end
                      7: 
                      8: functor Spill(val maxfree : int) : SPILL =
                      9: struct
                     10: open FreeMap Access SortedList CPS
                     11: val error = ErrorMsg.impossible
                     12: fun sublist test =
                     13:   let fun subl(a::r) = if test a then a::(subl r) else subl r
                     14:         | subl [] = []
                     15:   in  subl
                     16:   end
                     17: 
                     18: local val spillname = Symbol.symbol "spillrec"
                     19: in    fun spillLvar() = namedLvar spillname
                     20: end
                     21: 
                     22: val ilist = PrintUtil.printClosedSequence ("[",",","]") Integer.print
                     23: 
                     24: fun cut(0,_) = []
                     25:   | cut(i,a::x) = a::cut(i-1,x)
                     26:   | cut(_,[]) = []
                     27: 
                     28: fun nextuse x =
                     29:  let fun xin[] = false | xin(y::r) = x=y orelse xin r
                     30:      fun g(level,a) =
                     31:      let val rec f =
                     32:       fn ([],[]) => level
                     33:        | ([],next) => g(level+1,next)
                     34:        | (SWITCH(v,l)::r,next) => if x=v then level else f(r,l@next)
                     35:        | (RECORD(l,w,c)::r,next) =>
                     36:         if xin(map #1 l) then level else f(r,c::next)
                     37:        | (SELECT(i,v,w,c)::r,next) => if x=v then level else f(r,c::next)
                     38:        | (OFFSET(i,v,w,c)::r,next) => if x=v then level else f(r,c::next)
                     39:        | (PRIMOP(i,a,w,cl)::r,next) => if xin a then level else f(r,cl@next)
                     40:        | (APP(v,vl)::r,next) => if xin(v::vl) then level else f(r,next)
                     41:      in f(a,[])
                     42:      end
                     43:      fun h y = g(0,[y])
                     44:  in h
                     45:  end
                     46: 
                     47: local val sort = Sort.sort (fn ((i:int,_),(j,_)) => i>j)
                     48: in fun sortdups(cexp,dups) =
                     49:        map #2 (sort (map (fn dup as (v,w) => (nextuse v cexp, dup)) dups))
                     50: end
                     51: 
                     52: (* should do the first n and then only go 
                     53:    deep enough to prove that it is not needed *)
                     54: 
                     55: fun next_n_dups(0,cexp,dups) = []
                     56:   | next_n_dups(n,cexp,dups) =
                     57:     if n >= length dups
                     58:     then dups
                     59:     else cut(n,sortdups(cexp,dups))
                     60: 
                     61: fun show (SWITCH(v,l)) = (print "SWITCH "; print v; print "\n")
                     62:   | show (RECORD(_,w,_)) = (print "RECORD "; print w; print "\n")
                     63:   | show (SELECT(_,_,w,_)) = (print "SELECT "; print w; print "\n")
                     64:   | show (OFFSET(_,_,w,_)) = (print "OFFSET "; print w; print "\n")
                     65:   | show (PRIMOP(_,_,w::_,_)) = (print "PRIMOP "; print w; print "\n")
                     66:   | show (PRIMOP(_,vl,_,_)) = (print "PRIMOP "; ilist vl; print "\n")
                     67:   | show (APP(f,vl)) = (print "APP "; print f; ilist vl; print "\n")
                     68: 
                     69: nonfix before
                     70: val \/ = merge and /\ = intersect
                     71: infix 6 \/   infix 7 /\
                     72: fun mash (constant,freevars,spillmem) =
                     73: let fun f(results : lvar list,
                     74:          uniques : lvar list,
                     75:           dups : (lvar*lvar) list,
                     76:          spill : (lvar list * lvar) option,
                     77:          cexp : cexp) =
                     78:     let fun prepare l = sublist (fn x => not(constant x)) (uniq l)
                     79:         val (before,after) =  (* variables free in this operation, and after
                     80:                                  not including the newly-bound variables *)
                     81:         let val rec free =
                     82:              fn SWITCH(v,l) => foldmerge(prepare[v] :: map free l)
                     83:               | RECORD(l,w,c) =>  prepare (map #1 l) \/ freevars w
                     84:               | SELECT(i,v,w,c) => prepare[v] \/ freevars w
                     85:               | OFFSET(i,v,w,c) => prepare[v] \/ freevars w
                     86:               | PRIMOP(i,a,[],cl) => foldmerge(prepare a :: map free cl)
                     87:               | PRIMOP(i,a,[res],cl) => prepare a \/ freevars res
                     88:               | APP(f,vl) => prepare(f::vl)
                     89:             fun here(vl,wl) = (prepare vl, wl)
                     90:           in case cexp
                     91:              of SWITCH(v,l) => here([v],foldmerge(map free l))
                     92:               | RECORD(l,w,c) =>  here(map #1 l,freevars w)
                     93:               | SELECT(i,v,w,c) => here([v],freevars w)
                     94:               | OFFSET(i,v,w,c) => here([v],freevars w)
                     95:               | PRIMOP(i,a,[],cl) => here(a,foldmerge(map free cl))
                     96:               | PRIMOP(i,a,[res],cl) => here(a,freevars res)
                     97:               | APP(f,vl) => here(f::vl,[])
                     98:         end
                     99: 
                    100:         val uniques = uniques \/ results
                    101:        val uniques_after = uniques /\ after
                    102:         val uniques_before = (uniques /\ before) \/ uniques_after
                    103:         val spill_after = 
                    104:            case spill of
                    105:              NONE => NONE
                    106:            | SOME(contents,_) =>
                    107:              case uniq contents /\ after of
                    108:                [] => NONE
                    109:              | _ => spill
                    110:        val maxfree' = case spill of NONE => maxfree | SOME _ => maxfree-1
                    111:        val maxfreeafter = case spill_after of
                    112:                             NONE => maxfree | SOME _ => maxfree-1
                    113:        val avail = maxfree' - length(uniques_before \/ results)
                    114:        val dups = next_n_dups(avail,cexp,dups)
                    115: 
                    116:         fun getpath p v =
                    117:          if constant v orelse member uniques_before v
                    118:          then (v, OFFp 0)
                    119:          else let fun try((w,x)::l) = if v=w then (x,OFFp 0) else try l
                    120:                     | try [] = let val SOME (l,sv) = spill
                    121:                                    fun find(i,w::l) = 
                    122:                                        if v=w
                    123:                                        then ((* if p
                    124:                                              then (print "Retching ";
                    125:                                                    print v;
                    126:                                                    print "\n")
                    127:                                              else (); *)
                    128:                                              (sv,SELp(i,OFFp 0)))
                    129:                                        else find(i+1,l)
                    130:                                      | find(_,[]) = error "not found in spill"
                    131:                                in find(0,l)
                    132:                                end
                    133:               in try dups
                    134:               end
                    135: 
                    136:        fun makeSpillRec args =
                    137:            let val contents = prepare args \/ after
                    138:                val spillrec = map (getpath true) contents
                    139:                val sv = spillLvar()
                    140:                val dups' = map (fn x => (x,x)) uniques_before @ dups
                    141:             in (* ilist contents; print "\n"; *)
                    142:                RECORD(spillrec,sv,f([],[],dups',SOME(contents,sv),cexp))
                    143:            end
                    144: 
                    145:         fun g(args,res,conts,gen) = 
                    146:        if length(prepare args \/ uniques_after) > maxfreeafter orelse
                    147:           length res + length uniques_after > maxfreeafter
                    148:        then makeSpillRec args
                    149:        else let val paths = map (fn x => (x, getpath false x)) (uniq args)
                    150:                 fun fetchit (_,(_,OFFp 0)) = false | fetchit _ = true
                    151:             in case sublist fetchit paths of
                    152:                  [(v,(w,SELp(i,OFFp 0)))] =>
                    153:                  let val x = dupLvar v
                    154:                  in (* print "Fetching ";
                    155:                     print v;
                    156:                     print "\n"; *)
                    157:                     SELECT(i,w,x,f([],uniques_before,(v,x)::dups,
                    158:                                    spill_after,cexp))
                    159:                  end
                    160:                | (v,(w,SELp(i,OFFp 0)))::_ =>
                    161:                  let val x = dupLvar v
                    162:                  in (* print "fetching ";
                    163:                     print v;
                    164:                     print "\n"; *)
                    165:                     SELECT(i,w,x,f([],uniques_before,(v,x)::dups,spill,cexp))
                    166:                  end
                    167:                | [] => let fun f' cexp = f(uniq res,uniques_after,
                    168:                                            dups,spill_after,cexp)
                    169:                        in gen(map (#1 o (getpath false)) args,res,map f' conts)
                    170:                        end
                    171:             end
                    172: 
                    173:      in case ((*show cexp;*) cexp)
                    174:          of SWITCH(v,l) => g([v],[],l,fn([v],[],l)=>SWITCH(v,l))
                    175:           | RECORD(l,w,c) =>
                    176:            if 1+length uniques_after > maxfreeafter
                    177:            then makeSpillRec (map #1 l)
                    178:            else let val paths = map (fn (v,p) =>
                    179:                                         let val (v',p') = getpath true v 
                    180:                                         in (v', combinepaths(p',p))
                    181:                                         end)
                    182:                                     l
                    183:                 in RECORD(paths,w,f([w],uniques_after,dups,spill_after,c))
                    184:                 end
                    185:           | SELECT(i,v,w,c) => g([v],[w],[c], fn([v],[w],[c])=>SELECT(i,v,w,c))
                    186:          | OFFSET(i,v,w,c) => g([v],[w],[c], fn([v],[w],[c])=>OFFSET(i,v,w,c))
                    187:          | PRIMOP(i,a,r,cl) => g(a,r,cl, fn(a,r,cl)=>PRIMOP(i,a,r,cl))
                    188:          | APP(f,vl) => g(f::vl,[],[],fn(f::vl,[],[])=>APP(f,vl))
                    189:    end
                    190:  in f
                    191: end
                    192: 
                    193: fun spill(carg,constant,prof) =
                    194: let 
                    195: exception SpillCall
                    196: val callmap = Intmap.new(64,SpillCall) : (lvar list * lvar list) Intmap.intmap
                    197: val callinfo = Intmap.map callmap
                    198: val note = Intmap.add callmap
                    199: val t = Intset.new()
                    200: val spillarg = Intset.add t
                    201: val spillmem = Intset.mem t
                    202: 
                    203: fun spill_call(arg as ((f,vl,body),k)) =
                    204:     if length vl < maxfree
                    205:     then (arg,uniq vl,[],NONE)
                    206:     else let val dups = map (fn x => (x,x)) vl
                    207:             val dups' = next_n_dups(maxfree-2,body,dups)
                    208:             val sv = spillLvar()
                    209:             val new = map #1 dups'
                    210:             val new_vl = sv :: new
                    211:             val spill = SOME(vl,sv)
                    212:          in note(f,(new,vl));
                    213:            (((f,new_vl,body),k),[],dups',spill)
                    214:         end
                    215: 
                    216: val rec fixApp =
                    217:     fn e as APP(f,vl) =>
                    218:        (let val (new,old) = callinfo f
                    219:            val sv = spillLvar()
                    220:            val sr = map (fn x => (x,OFFp 0)) vl
                    221:            fun find [] = []
                    222:              | find(x::r) =
                    223:                let fun loop(a::b,c::d) =
                    224:                        if x=a then c :: find r else loop(b,d)
                    225:                      | loop _ = error "fixApp in spill"
                    226:                in loop(old,vl)
                    227:                end
                    228:         in spillarg sv;
                    229:           RECORD(sr,sv,APP(f,sv :: find new))
                    230:         end handle SpillCall => e)
                    231:      | SWITCH(v,l) => SWITCH(v,map fixApp l)
                    232:      | RECORD(l,w,c) => RECORD(l,w,fixApp c)
                    233:      | SELECT(i,v,w,c) => SELECT(i,v,w,fixApp c)
                    234:      | OFFSET(i,v,w,c) => OFFSET(i,v,w,fixApp c)
                    235:      | PRIMOP(i,a,w,l) => PRIMOP(i,a,w,map fixApp l)
                    236:     val carg' = map spill_call carg
                    237:     val carg'' = map (fn (((f,vl,b),k),uniq,dups,spill) =>
                    238:                          (((f,vl,fixApp b),k),uniq,dups,spill)) carg'
                    239:     val freevars = 
                    240:        let exception SpillFreemap
                    241:            val m = Intmap.new(32, SpillFreemap) : lvar list Intmap.intmap
                    242:            val _ = app (freemap constant (Intmap.add m) o #3 o #1 o #1) carg''
                    243:          in Intmap.map m
                    244:         end
                    245:     exception TooMany
                    246:     fun checkv w = if length(freevars w) >= maxfree then raise TooMany else ()
                    247:     val rec check =
                    248:      fn FIX _ => error "FIX in cps/spill"
                    249:       | APP(l,args) => ()
                    250:       | SWITCH(v,l) => app check l
                    251:       | RECORD(l,w,c) => (checkv w; check c)
                    252:       | SELECT(i,v,w,c) => (checkv w; check c)
                    253:       | OFFSET(i,v,w,c) => (checkv w; check c)
                    254:       | PRIMOP(i,args,[],l) => app check l
                    255:       | PRIMOP(i,args,w::_, l) => (checkv w; app check l)
                    256:     val masher = mash(constant,freevars,spillmem)
                    257: 
                    258: in map
                    259:    (fn (((f,vl,body),k),uniq,dups,spill as SOME _) =>
                    260:        ((f,vl,masher([],uniq,dups,spill,body)), k)
                    261:      | (arg as ((f,vl,body),k),uniq,dups,NONE) =>
                    262:        ((check body; arg)
                    263:         handle TooMany => ((f,vl,masher([],uniq,dups,NONE,body)), k)))
                    264:    carg''
                    265: end
                    266: 
                    267: end (* structure Spill *)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.