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

1.1       root        1: (* Copyright 1989 by AT&T Bell Laboratories *)
                      2: (* All record paths must be "OFFp 0" in cpsopt.sml *)
                      3: 
                      4: functor CPSopt(val maxfree : int) :
                      5:        sig val reduce : (CPS.const Intmap.intmap) -> CPS.cexp -> CPS.cexp
                      6:         end =
                      7: struct
                      8: 
                      9:  open Access CPS SortedList
                     10: 
                     11:  fun map1 f (a,b) = (f a, b)
                     12: 
                     13:  fun member(i : int, a::b) = i=a orelse member(i,b)
                     14:    | member(i,[]) = false
                     15: 
                     16:  fun choose(a::b,true::d) = a::choose(b,d)
                     17:    | choose(a::b,false::d) = choose(b,d)
                     18:    | choose _ = []
                     19: 
                     20:  fun sum f = let fun h [] = 0 
                     21:                   | h (a::r) = f a + h r
                     22:             in h
                     23:             end
                     24: 
                     25:  val debug = false
                     26:  fun debugprint s = if debug then print(s:string) else ()
                     27:  fun debugflush() = if debug then flush_out std_out else ()
                     28: 
                     29: fun reduce ctab cexp =
                     30: let
                     31:  val clicked = ref 0
                     32:  fun click (s:string) = (debugprint s; inc clicked)
                     33: 
                     34:  fun eta cexp =
                     35:   let exception M2
                     36:       val m : lvar Intmap.intmap = Intmap.new(32, M2)
                     37:       val name = Intmap.map m
                     38:       fun rename v = rename(name v) handle M2 => v
                     39:       fun newname x = (Access.sameName x; Intmap.add m x)
                     40:       val rec eta = 
                     41:        fn RECORD(vl,w,e) => RECORD(map (map1 rename) vl, w, eta e)
                     42:         | SELECT(i,v,w,e) => SELECT(i, v, w, eta e)
                     43:         | APP(f,vl) => APP(rename f, map rename vl)
                     44:         | SWITCH(v,el) => SWITCH(v, map eta el)
                     45:         | PRIMOP(i,vl,wl,el) => PRIMOP(i, map rename vl, wl, map eta el)
                     46:         | FIX(l,e) =>
                     47:             let fun h((f,vl,body as APP(g,wl))::r) =
                     48:                     if wl=vl andalso not (member(g, f::vl))
                     49:                     then (newname(f,rename g); h r)
                     50:                     else let val vl' = map dupLvar vl 
                     51:                              and f' = dupLvar f
                     52:                          in (f,vl',APP(f',vl'))::(f',vl,body) :: h r
                     53:                          end
                     54:                   | h((f,vl,body)::r) =
                     55:                     let val vl' = map dupLvar vl 
                     56:                         and f' = dupLvar f
                     57:                     in (f,vl',APP(f',vl'))::(f',vl,body) :: h r
                     58:                     end
                     59:                   | h [] = []
                     60:              in case h l of
                     61:                  [] => eta e
                     62:                | l' => FIX(map (fn(f,vl,e)=>(f,vl,eta e)) l', eta e)
                     63:             end
                     64:   in eta cexp
                     65:   end
                     66: 
                     67:  val hoist = Hoist.hoist click
                     68: fun contract last cexp =
                     69:  let val mkconst = Intmap.add ctab
                     70:      datatype cv = CO of const | VA of lvar
                     71:      fun ctable v = CO(Intmap.map ctab v) handle Ctable => VA v
                     72:      fun isconst v = case ctable v of CO _ => true | VA _ => false
                     73:      datatype arity = BOT | COUNT of int | TOP | NOTUSED
                     74:      val botlist = map (fn _ => BOT)
                     75:      datatype info = FNinfo of {arity: arity list ref,
                     76:                                args: lvar list,
                     77:                                body : cexp,
                     78:                                reduce_ok : bool ref}
                     79:                   | RECinfo of (lvar * accesspath) list * (lvar * int) list ref
                     80:                   | MISCinfo
                     81: 
                     82:      exception Escapemap
                     83:      val m : {info: info, used : int ref, escape : int ref} Intmap.intmap =
                     84:                     Intmap.new(128, Escapemap)
                     85:      val get = Intmap.map m
                     86:      val enter = Intmap.add m
                     87:      fun use v = inc(#used(get v)) handle Escapemap => ()
                     88:      fun used v = !(#used(get v)) > 0 handle Escapemap => true
                     89:      fun escape v = let val {escape,used,...} = get v
                     90:                    in inc escape; inc used
                     91:                    end handle Escapemap => ()
                     92:      fun escapes r = !(#escape(get r)) handle Escapemap => 0
                     93:      fun flatfun(f,n) =
                     94:         (case get f of
                     95:            {info=FNinfo{arity=ref al,reduce_ok=ref false,...},escape=ref 0,...} =>
                     96:            (case nth(al,n) of
                     97:                COUNT i => 1
                     98:             | _ => 0)
                     99:          | _ => 0) handle Escapemap => 0
                    100:      fun selectonly r = 0 = !(#escape(get r)) handle Escapemap => false
                    101:      fun enterREC(w,vl) = enter(w,{info=RECinfo(vl,ref[]),escape=ref 0,used=ref 0})
                    102:      fun enterMISC w = enter(w,{info=MISCinfo, escape=ref 0, used = ref 0})
                    103:      fun enterFN (f,vl,cexp) =
                    104:                (enter(f,{escape=ref 0,used=ref 0,
                    105:                         info=FNinfo{arity=ref(botlist vl), args=vl, body=cexp,
                    106:                         reduce_ok=ref true}});
                    107:                 app enterMISC vl)
                    108: 
                    109:      fun checkreduce(f,vl,body) =
                    110:         case get f of
                    111:           {escape=ref 0,used=ref i,
                    112:            info=FNinfo{reduce_ok,arity as ref al,...},...} =>
                    113:                if i>1
                    114:                then
                    115:                  let fun loop(v::vl,a::al) =
                    116:                          if used v
                    117:                          then if selectonly v
                    118:                               then a::loop(vl,al)
                    119:                               else TOP::loop(vl,al)
                    120:                          else NOTUSED::loop(vl,al)
                    121:                        | loop _ = []
                    122:                  in reduce_ok := false;
                    123:                     arity := loop(vl,al)
                    124:                  end
                    125:                else ()
                    126:              | {info=FNinfo{reduce_ok,...},...} =>
                    127:                    (reduce_ok := false;
                    128:                     if last
                    129:                     then ()
                    130:                     else (case body of
                    131:                             APP(g,_) =>
                    132:                             (case get g of
                    133:                                {info=FNinfo{reduce_ok,...},...} => 
                    134:                                reduce_ok := false
                    135:                              | _ => ())
                    136:                           | _ => ()))
                    137: 
                    138:      exception ConstFold
                    139: 
                    140:      val rec pass1 = 
                    141:       fn RECORD(vl,w,e) => (enterREC(w,vl); app (escape o #1) vl; pass1 e)
                    142:        | SELECT (i,v,w,e) => (enterMISC w; use v; pass1 e)
                    143:        | APP(f,vl) =>
                    144:         ((case get f of
                    145:             {info=FNinfo{arity as ref al,...},...} =>
                    146:             let fun loop(TOP::r,v::vl,n) = TOP::loop(r,vl,n+1)
                    147:                   | loop(BOT::r,v::vl,n) =
                    148:                     ((case get v of
                    149:                         {info=RECinfo(wl,flr as ref fl), ...} =>
                    150:                         (flr := (f,n)::fl; COUNT(length wl)::loop(r,vl,n+1))
                    151:                       | _ => raise Escapemap)
                    152:                      handle Escapemap => TOP::loop(r,vl,n+1))
                    153:                   | loop((cnt as COUNT a)::r,v::vl,n) = 
                    154:                     ((case get v of
                    155:                         {info=RECinfo(wl,flr as ref fl), ...} =>
                    156:                         if a = length wl
                    157:                         then (flr := (f,n)::fl; cnt::loop(r,vl,n+1))
                    158:                         else TOP::loop(r,vl,n+1)
                    159:                       | _ => raise Escapemap)
                    160:                      handle Escapemap => TOP::loop(r,vl,n+1))
                    161:                   | loop _ = []
                    162:             in arity := loop(al,vl,0)
                    163:             end
                    164:           | _ => ())
                    165:          handle Escapemap => ();
                    166:          use f; app escape vl)
                    167:        | FIX(l, e) => (app enterFN l;
                    168:                       app (fn(* (f,vl,APP(g,wl)) => (use g; app escape wl)
                    169:                             |*) (f,vl,body) => pass1 body) l;
                    170:                       pass1 e;
                    171:                       app checkreduce l)
                    172:        | SWITCH(v,el) => (use v; app pass1 el)
                    173:        | PRIMOP(i,vl,wl,el) =>
                    174:         (case i of
                    175:            P.:= => app escape vl
                    176:          | P.makeref => app escape vl
                    177:          | P.sethdlr => app escape vl
                    178:          | P.store => app escape vl
                    179:          | P.unboxedassign => app escape vl
                    180:          | P.unboxedupdate => app escape vl
                    181:          | P.update => app escape vl
                    182:          | _ => app use vl;
                    183:          app enterMISC wl;
                    184:          app pass1 el)
                    185:        | OFFSET _ => ErrorMsg.impossible "OFFSET in cpsopt"
                    186: 
                    187:      exception Beta
                    188:      val m2 : lvar Intmap.intmap = Intmap.new(32, Beta)
                    189:      fun ren v = ren(Intmap.map m2 v) handle Beta => v
                    190:      fun newname x = (Access.sameName x; Intmap.add m2 x)
                    191:      fun newnames(v::vl, w::wl) = (newname(v,w); newnames(vl,wl))
                    192:        | newnames _ = ()
                    193:      val one = let val x = mkLvar() in mkconst(x, INTconst 1); x end
                    194:      
                    195:      val rec reduce = fn cexp => g NONE cexp
                    196:      and g = fn hdlr =>
                    197:      let val rec g' =
                    198:        fn RECORD (vl,w,e) =>
                    199:          let val {info=RECinfo(_,ref fl),escape=ref esc,...} = get w
                    200:          in if esc = sum flatfun fl
                    201:             then (click "rec "; g' e)
                    202:             else RECORD(map (map1 ren) vl, w, g' e)
                    203:          end
                    204:         | SELECT(i,v,w,e) =>
                    205:          if not(used w)
                    206:           then (click "Sel "; g' e)
                    207:          else let val v' = ren v
                    208:               in (case get v' of
                    209:                     {info=RECinfo(vl,_),...} =>
                    210:                     let val (x,OFFp 0) = nth(vl,i)
                    211:                     in click "sel ";
                    212:                        newname(w,ren x);
                    213:                        g' e
                    214:                     end
                    215:                   | _ => raise Escapemap)
                    216:                  handle Escapemap => SELECT(i,v',w,g' e)
                    217:               end
                    218:        | OFFSET _ => ErrorMsg.impossible "OFFSET in cpsopt"
                    219:        | APP(f,vl) =>
                    220:          ((case get(ren f) of
                    221:               {info=FNinfo{args,body,reduce_ok=ref true,...},...} =>
                    222:                (newnames(args, map ren vl); g' body)
                    223:              | {info=FNinfo{arity=ref al,...},escape=ref 0,...} =>
                    224:               let fun loop(COUNT _ :: r,v::vl) =
                    225:                       let val {info=RECinfo(wl,_),...} = get(ren v)
                    226:                           val wl' = map (fn (x,OFFp 0) => ren x) wl
                    227:                       in wl' @ loop(r,vl)
                    228:                       end
                    229:                     | loop(NOTUSED::r,v::vl) = loop(r,vl)
                    230:                     | loop(_::r,v::vl) = (ren v)::loop(r,vl)
                    231:                     | loop _ = []
                    232:               in APP(ren f,loop(al,vl))
                    233:               end
                    234:             | _ => raise Escapemap)
                    235:           handle Escapemap => APP(ren f, map ren vl))
                    236:        | FIX(l,e) =>
                    237:          let fun h((f,vl,body)::r) = 
                    238:                 (case get f
                    239:                  of {info=FNinfo{reduce_ok=ref true,...},...} =>
                    240:                     (click "fn  "; h r)
                    241:                   | {info=FNinfo{arity=ref al,...},escape=ref 0,...} =>
                    242:                          let fun vars 0 = []
                    243:                                | vars i = mkLvar()::vars(i-1)
                    244:                              fun newargs(COUNT j :: r,v::vl) =
                    245:                                  let val new = vars j
                    246:                                  in enterREC(v, map (fn x =>(x,OFFp 0)) new);
                    247:                                     click "flt ";
                    248:                                     new @ newargs(r,vl)
                    249:                                  end
                    250:                                | newargs(NOTUSED::r,v::vl) =
                    251:                                     (click "drp "; newargs(r,vl))
                    252:                                | newargs(TOP::r,v::vl) = v::newargs(r,vl)
                    253:                                | newargs _ = []
                    254:                          in (f, newargs(al,vl), reduce body) :: h r
                    255:                          end
                    256:                   | _ => (f, vl, reduce body) :: h r)
                    257:                | h [] = []
                    258:           in case h l of [] => g' e | l' => FIX(l', g' e)
                    259:          end
                    260:         | SWITCH(v,el) => 
                    261:                (case ctable (ren v)
                    262:                  of CO(INTconst i) => (click "swt "; g' (nth(el,i)))
                    263:                   | VA v' => SWITCH(v', map g' el)
                    264:                   | _ => ErrorMsg.impossible "3121 in cpsopt")
                    265:        | PRIMOP(P.gethdlr,vl,wl as [w],[e]) =>
                    266:          (case hdlr of
                    267:             NONE => if used w then PRIMOP(P.gethdlr,vl,wl,[g (SOME w) e])
                    268:                     else (click "gth "; g' e)
                    269:           | SOME w' => (click "gth "; newname(w,w'); g' e))
                    270:        | PRIMOP(P.sethdlr,[v],wl,[e]) =>
                    271:          let val v' = ren v
                    272:              val e' = g (SOME v') e
                    273:          in case hdlr of
                    274:               NONE => PRIMOP(P.sethdlr,[v'],wl,[e'])
                    275:             | SOME v'' => if v'=v'' then (click "sth "; e')
                    276:                           else PRIMOP(P.sethdlr,[v'],wl,[e'])
                    277:          end
                    278:        | PRIMOP(i, vl, wl, el as [e1,e2]) => 
                    279:              if e1 = e2
                    280:              then (click "tst "; g' e1)
                    281:              else let val vl' = map ren vl
                    282:                   in g' (primops(i,map ctable vl', wl, el))
                    283:                      handle ConstFold => PRIMOP(i, vl', wl, map g' el)
                    284:                   end
                    285:         | PRIMOP(i, vl, wl as [w], el as [e]) =>
                    286:          if not(used w) andalso Prim.pure i
                    287:            then (click "prm "; g' e)
                    288:            else let val vl' = map ren vl
                    289:                  in g' (primops(i,map ctable vl', wl, el))
                    290:                     handle ConstFold => PRIMOP(i, vl', wl, map g' el)
                    291:                 end
                    292:         | PRIMOP(i,vl,wl,el) =>
                    293:                 let val vl' = map ren vl
                    294:                  in g' (primops(i,map ctable vl', wl, el))
                    295:                     handle ConstFold => PRIMOP(i, vl', wl, map g' el)
                    296:                 end
                    297:       in g'
                    298:      end
                    299: 
                    300:      and primops =
                    301:        fn (P.boxed, CO(INTconst _)::_,_,_::b::_) => (click "A"; b)
                    302:         | (P.boxed, CO(STRINGconst s)::_,_,a::b::_) =>
                    303:                            (click "A"; if size s = 1 then b else a)
                    304:         | (P.boxed, VA v :: _,_,a::_) => 
                    305:             ((case get v of
                    306:                  {info=RECinfo _, ...} => (click "A"; a)
                    307:              | _ => raise ConstFold)
                    308:             handle Escapemap => raise ConstFold)
                    309:          | (P.<, [CO(INTconst i),CO(INTconst j)],_,[a,b]) =>
                    310:                      (click "B"; if Integer.<(i,j) then a else b)
                    311:          | (P.<=, [CO(INTconst i),CO(INTconst j)],_,[a,b]) =>
                    312:                   (click "C"; if Integer.<=(i,j) then a else b)
                    313:         | (P.> , [CO(INTconst i),CO(INTconst j)],_,[a,b]) =>
                    314:                   (click "D"; if Integer.>(i,j) then a else b)
                    315:          | (P.>=, [CO(INTconst i),CO(INTconst j)],_,[a,b]) =>
                    316:                   (click "E"; if Integer.>=(i,j) then a else b)
                    317:          | (P.ieql, [CO(INTconst i),CO(INTconst j)],_,[a,b]) =>
                    318:                     (click "F"; if i=j then a else b)
                    319:          | (P.ineq, [CO(INTconst i),CO(INTconst j)],_,[a,b]) =>
                    320:                     (click "G"; if i=j then b else a)
                    321:          | (P.*, [CO(INTconst 1), VA(v)],[w],[c]) =>
                    322:                      (click "H"; newname(w,v); c)
                    323:         | (P.*, [VA(v), CO(INTconst 1)],[w],[c]) =>
                    324:                      (click "H"; newname(w,v); c)
                    325:         | (P.*, [CO(INTconst 0), _],[w],[c]) =>
                    326:                   (click "H"; mkconst(w,INTconst 0); c)
                    327:         | (P.*, [_, CO(INTconst 0)],[w],[c]) =>
                    328:                      (click "H"; mkconst(w,INTconst 0); c)
                    329:         | (P.*, [CO(INTconst i),CO(INTconst j)], [w], [c]) =>
                    330:                   (let val x = i*j
                    331:                    in x+x; mkconst(w,INTconst x); click "H"; c
                    332:                    end handle Overflow => raise ConstFold)
                    333:         | (P.div, [VA(v), CO(INTconst 1)],[w],[c]) =>
                    334:                      (click "I"; newname(w,v); c)
                    335:         | (P.div, [CO(INTconst i),CO(INTconst j)],[w],[c]) =>
                    336:                   (let val x = i div j
                    337:                    in click "I"; mkconst(w,INTconst x); c
                    338:                    end handle Div => raise ConstFold)
                    339:          | (P.+, [CO(INTconst 0), VA(v)],[w],[c]) =>
                    340:                   (click "J"; newname(w,v); c)
                    341:         | (P.+, [VA(v), CO(INTconst 0)],[w],[c]) =>
                    342:                   (click "J"; newname(w,v); c)
                    343:         | (P.+, [CO(INTconst i),CO(INTconst j)], [w], [c]) =>
                    344:                   (let val x = i+j
                    345:                    in x+x; mkconst(w,INTconst x); click "J"; c
                    346:                    end handle Overflow => raise ConstFold)
                    347:          | (P.-, [VA(v), CO(INTconst 0)],[w],[c]) =>
                    348:                      (click "K";newname(w,v); c)
                    349:         | (P.-, [CO(INTconst i),CO(INTconst j)], [w], [c]) =>
                    350:                  (let val x = i-j
                    351:                   in x+x; mkconst(w,INTconst x); click "K"; c
                    352:                   end handle Overflow => raise ConstFold)
                    353:         | (P.rshift, [CO(INTconst i),CO(INTconst j)],[w],[c]) =>
                    354:                           (click "L"; mkconst(w,INTconst(Bits.rshift(i,j))); c)
                    355:         | (P.rshift, [CO(INTconst 0), VA v],[w],[c]) =>
                    356:                           (click "L"; mkconst(w,INTconst 0); c)
                    357:         | (P.rshift, [VA v, CO(INTconst 0)],[w],[c]) =>
                    358:                           (click "L"; newname(w,v); c)
                    359:          | (P.slength, [CO(INTconst _)],[w],[c]) =>
                    360:                         (click "M"; mkconst(w, INTconst 1); c)
                    361:         | (P.slength, [CO(STRINGconst s)], [w],[c]) =>
                    362:                         (click "M"; mkconst(w, INTconst(size s)); c)
                    363:          | (P.ordof, [CO(STRINGconst s), CO(INTconst i)],[w],[c]) =>
                    364:                         (click "N"; mkconst(w, INTconst (ordof(s,i))); c)
                    365:          | (P.~, [CO(INTconst i)], [w], [c]) =>
                    366:                     (let val x = ~i
                    367:                      in x+x; mkconst(w,INTconst x); click "O"; c
                    368:                      end handle Overflow => raise ConstFold)
                    369:         | (P.lshift, [CO(INTconst i),CO(INTconst j)],[w],[c]) =>
                    370:                           (let val x = Bits.lshift(i,j)
                    371:                            in x+x; mkconst(w,INTconst x); click "P"; c
                    372:                            end handle Overflow => raise ConstFold)
                    373:         | (P.lshift, [CO(INTconst 0), VA v],[w],[c]) =>
                    374:                           (click "P"; mkconst(w,INTconst 0); c)
                    375:         | (P.lshift, [VA v, CO(INTconst 0)],[w],[c]) =>
                    376:                           (click "P"; newname(w,v); c)
                    377:         | (P.orb, [CO(INTconst i),CO(INTconst j)],[w],[c]) =>
                    378:                        (click "Q"; mkconst(w,INTconst(Bits.orb(i,j))); c)
                    379:         | (P.orb, [CO(INTconst 0),VA v],[w],[c]) =>
                    380:                        (click "Q"; newname(w,v); c)
                    381:         | (P.orb, [VA v, CO(INTconst 0)],[w],[c]) =>
                    382:                        (click "Q"; newname(w,v); c)
                    383:         | (P.xorb, [CO(INTconst i),CO(INTconst j)],[w],[c]) =>
                    384:                         (click "R"; mkconst(w,INTconst(Bits.xorb(i,j))); c)
                    385:         | (P.xorb, [CO(INTconst 0),VA v],[w],[c]) =>
                    386:                        (click "R"; newname(w,v); c)
                    387:         | (P.xorb, [VA v, CO(INTconst 0)],[w],[c]) =>
                    388:                        (click "R"; newname(w,v); c)
                    389:         | (P.notb, [CO(INTconst i)], [w], [c]) =>
                    390:                         (mkconst(w,INTconst(Bits.notb i)); click "S"; c)
                    391:         | (P.andb, [CO(INTconst i),CO(INTconst j)],[w],[c]) =>
                    392:                         (click "T"; mkconst(w,INTconst(Bits.andb(i,j))); c)
                    393:         | (P.andb, [CO(INTconst 0),VA v],[w],[c]) =>
                    394:                        (click "T"; mkconst(w,INTconst 0); c)
                    395:         | (P.andb, [VA v, CO(INTconst 0)],[w],[c]) =>
                    396:                        (click "T"; mkconst(w,INTconst 0); c)
                    397:          | _ => raise ConstFold
                    398: 
                    399:     val _ = (debugprint "\nContract: "; debugflush())
                    400:   in (pass1 cexp; reduce cexp)
                    401:   end
                    402: 
                    403: fun expand(cexp,bodysize) =
                    404:    let
                    405:      datatype info = Fun of {escape: int ref, call: int ref, size: int ref,
                    406:                         args: lvar list, body: cexp}
                    407:                   | Arg of {escape: int ref, savings: int ref,
                    408:                             record: (int * lvar) list ref}
                    409:                   | Sel of {savings: int ref}
                    410:                   | Rec of {escape: int ref, size: int,
                    411:                             vars: (lvar * accesspath) list}
                    412: 
                    413:      exception Expand
                    414:      val m : info Intmap.intmap = Intmap.new(128,Expand)
                    415:      val get = Intmap.map m
                    416:      fun call(v,args) = (case get v
                    417:                    of Fun{call,...} => inc call
                    418:                     | Arg{savings,...} => savings := !savings+1
                    419:                     | Sel{savings} => savings := !savings+1
                    420:                     | Rec _ => ()  (* impossible *)
                    421:                  ) handle Expand => ()
                    422:      fun escape v = (case get v
                    423:                    of Fun{escape,...} => inc escape
                    424:                     | Arg{escape,...} => inc escape
                    425:                     | Sel _ => ()
                    426:                     | Rec{escape,...} => inc escape
                    427:                  ) handle Expand => ()
                    428:      fun escapeargs v = (case get v
                    429:                         of Fun{escape,...} => inc escape
                    430:                       | Arg{escape,savings, ...} =>
                    431:                             (inc escape; savings := !savings + 1)
                    432:                       | Sel{savings} => savings := !savings + 1
                    433:                       | Rec{escape,...} => inc escape)
                    434:                         handle Expand => ()
                    435:      fun unescapeargs v = (case get v
                    436:                         of Fun{escape,...} => dec escape
                    437:                       | Arg{escape,savings, ...} =>
                    438:                             (dec escape; savings := !savings - 1)
                    439:                       | Sel{savings} => savings := !savings - 1
                    440:                       | Rec{escape,...} => dec escape)
                    441:                         handle Expand => ()
                    442:      fun setsize(f,n) = case get f of Fun{size,...} => (size := n; n)
                    443:      fun enter (f,vl,e) = (Intmap.add m(f,Fun{escape=ref 0, call=ref 0, size=ref 0,
                    444:                                              args=vl, body=e});
                    445:                           app (fn v => Intmap.add m (v,
                    446:                                        Arg{escape=ref 0,savings=ref 0,
                    447:                                            record=ref []})) vl)
                    448:      fun noterec(w, vl, size) = Intmap.add m (w,Rec{size=size,escape=ref 0,vars=vl})
                    449:      fun notesel(i,v,w) = (Intmap.add m (w, Sel{savings=ref 0});
                    450:                     (case get v of
                    451:                         Arg{savings,record,...} => (inc savings;
                    452:                                                    record := (i,w)::(!record))
                    453:                       | _ => ()) handle Expand => ())
                    454:      fun save(v,k) = (case get v
                    455:                       of Arg{savings,...} => savings := !savings + k
                    456:                        | Sel{savings} => savings := !savings + k
                    457:                        | _ => ()
                    458:                     ) handle Expand => ()
                    459:      fun nsave(v,k) = (case get v
                    460:                       of Arg{savings,...} => savings := k
                    461:                        | Sel{savings} => savings := k
                    462:                        | _ => ()
                    463:                     ) handle Expand => ()
                    464:      fun savesofar v = (case get v 
                    465:                       of Arg{savings,...} => !savings
                    466:                        | Sel{savings} => !savings
                    467:                        | _ => 0
                    468:                     ) handle Expand => 0
                    469:      val rec prim = fn (_,vl,wl,el) =>
                    470:         let fun vbl v = (Intmap.map ctab v; 0)
                    471:                          handle Ctable =>
                    472:                            ((case get v of
                    473:                                 Rec _ => 0
                    474:                              | _ => 1) handle Expand => 1)
                    475:             val nonconst = sum vbl vl
                    476:             val len = length el
                    477:             val sl = map savesofar vl
                    478:             val branches = sum pass1 el
                    479:             val zl = map savesofar vl
                    480:             val overhead = length vl + length wl
                    481:             val potential = overhead + (branches*(len-1)) div len
                    482:             val savings = case nonconst of
                    483:                             1 => potential
                    484:                           | 2 => potential div 4
                    485:                           | _ => 0
                    486:             fun app3 f = let fun loop (a::b,c::d,e::r) = (f(a,c,e); loop(b,d,r))
                    487:                                | loop _ = ()
                    488:                          in loop
                    489:                          end
                    490:         in app3(fn (v,s,z)=> nsave(v,s + savings + (z-s) div len)) (vl,sl,zl);
                    491:            overhead+branches
                    492:         end
                    493: 
                    494:      and pass1 = 
                    495:       fn RECORD(vl,w,e) =>
                    496:          (app (escape o #1) vl;
                    497:           noterec(w,vl,length vl);
                    498:           2 + length vl + pass1 e)
                    499:        | SELECT (i,v,w,e) => (notesel(i,v,w); 1 + pass1 e)
                    500:        | APP(f,vl) => (call(f,length vl); app escapeargs vl; 1 + length vl)
                    501:        | FIX(l, e) => 
                    502:            (app enter l; 
                    503:              sum (fn (f,_,e) => setsize(f, pass1 e)) l + length l + pass1 e)
                    504:        | SWITCH(v,el) => let val len = length el
                    505:                             val jumps = 4 + len
                    506:                             val branches = sum pass1 el
                    507:                          in save(v, (branches*(len-1)) div len + jumps);
                    508:                             jumps+branches
                    509:                         end
                    510:        | PRIMOP(args as (P.boxed,_,_,_)) => prim args
                    511:        | PRIMOP(args as (P.<,_,_,_)) => prim args
                    512:        | PRIMOP(args as (P.<=,_,_,_)) => prim args
                    513:        | PRIMOP(args as (P.>,_,_,_)) => prim args
                    514:        | PRIMOP(args as (P.>=,_,_,_)) => prim args
                    515:        | PRIMOP(args as (P.ieql,_,_,_)) => prim args
                    516:        | PRIMOP(args as (P.ineq,_,_,_)) => prim args
                    517:        | PRIMOP(args as (P.*,_,_,_)) => prim args
                    518:        | PRIMOP(args as (P.div,_,_,_)) => prim args
                    519:        | PRIMOP(args as (P.+,_,_,_)) => prim args
                    520:        | PRIMOP(args as (P.-,_,_,_)) => prim args
                    521:        | PRIMOP(args as (P.rshift,_,_,_)) => prim args
                    522:        | PRIMOP(args as (P.slength,_,_,_)) => prim args
                    523:        | PRIMOP(args as (P.ordof,_,_,_)) => prim args
                    524:        | PRIMOP(args as (P.~,_,_,_)) => prim args
                    525:        | PRIMOP(args as (P.lshift,_,_,_)) => prim args
                    526:        | PRIMOP(args as (P.orb,_,_,_)) => prim args
                    527:        | PRIMOP(args as (P.xorb,_,_,_)) => prim args
                    528:        | PRIMOP(args as (P.notb,_,_,_)) => prim args
                    529:        | PRIMOP(args as (P.andb,_,_,_)) => prim args
                    530:        | PRIMOP(_,vl,wl,el) =>
                    531:         (app escape vl; length vl + length wl + sum pass1 el)
                    532: 
                    533:      fun substitute(args,wl,e) =
                    534:       let exception Alpha
                    535:           val vm : lvar Intmap.intmap = Intmap.new(16, Alpha)
                    536:           fun use v = Intmap.map vm v handle Alpha => v
                    537:           fun def v = let val w = dupLvar v 
                    538:                      in Intmap.add vm (v,w); w
                    539:                      end
                    540:          fun bind(a::args,w::wl) = (Intmap.add vm (w,a); bind(args,wl))
                    541:            | bind _ = ()
                    542:           val rec g =
                    543:          fn RECORD(vl,w,ce) => RECORD(map (map1 use) vl, def w, g ce)
                    544:           | SELECT(i,v,w,ce) => SELECT(i, use v, def w, g ce)
                    545:           | APP(v,vl) => APP(use v, map use vl)
                    546:           | FIX(l,ce) => 
                    547:            let fun h1(f,vl,e) = (f,def f, vl, e)
                    548:                fun h2(f,f',vl,e) =
                    549:                    let val vl' = map def vl
                    550:                        val e'= g e
                    551:                    in (f', vl', e')
                    552:                    end
                    553:             in FIX(map h2(map h1 l), g ce)
                    554:            end
                    555:           | SWITCH(v,l) => SWITCH(use v, map g l)
                    556:           | PRIMOP(i,vl,wl,ce) => PRIMOP(i, map use vl, map def wl, map g ce)
                    557:       val cexp = (bind(args,wl); g e)
                    558:       in debugprint(makestring(pass1 cexp)); debugprint " "; cexp
                    559:       end
                    560:                
                    561:      fun beta(n, d, e) = case e
                    562:       of RECORD(vl,w,ce) => RECORD(vl, w, beta(n,d+2+length vl, ce))
                    563:        | SELECT(i,v,w,ce) => SELECT(i, v, w, beta(n,d+1, ce))
                    564:        | APP(v,vl) => 
                    565:           ((case get v
                    566:             of Fun{escape,call as ref calls,size,args,body} =>
                    567:                let val size = !size
                    568:                    fun whatsave(acc, v::vl, a::al) =
                    569:                        if acc>=size
                    570:                        then acc
                    571:                        else
                    572:                        (case get a of
                    573:                           Arg{escape=ref esc,savings=ref save,record=ref rl} =>
                    574:                            let val (this,nvl,nal) =
                    575:                               if (Intmap.map ctab v; true) handle Ctable => false
                    576:                               then (save,vl,al)
                    577:                               else (case get v of
                    578:                                       Fun{escape=ref 1,...} =>
                    579:                                          (if esc>0 then save else 6+save,vl,al)
                    580:                                     | Fun _ => (save,vl,al)
                    581:                                     | Rec{escape=ref ex,vars,size} =>
                    582:                                       let fun loop([],nvl,nal) = 
                    583:                                               (if ex>1 orelse esc>0
                    584:                                                then save
                    585:                                                else save+size+2,nvl,nal)
                    586:                                             | loop((i,w)::rl,nvl,nal) =
                    587:                                               let val (v,OFFp 0) = nth(vars,i)
                    588:                                               in loop(rl,v::nvl,w::nal)
                    589:                                               end
                    590:                                       in loop(rl,vl,al)
                    591:                                       end
                    592:                                      | _ => (0,vl,al)) handle Expand => (0,vl,al)
                    593:                           in whatsave(acc + this - (acc*this) div size, nvl,nal)
                    594:                           end
                    595:                         | Sel{savings=ref save} =>
                    596:                            let val this =
                    597:                               if (Intmap.map ctab v; true) handle Ctable => false
                    598:                               then save
                    599:                               else (case get v of
                    600:                                       Fun _ => save
                    601:                                     | Rec _ => save
                    602:                                      | _ => 0) handle Expand => 0
                    603:                           in whatsave(acc + this - (acc*this) div size, vl,al)
                    604:                           end)
                    605:                      | whatsave(acc,_,_) = acc
                    606:                  val predicted = calls*((size-whatsave(0,vl,args))-(1+length vl))
                    607:                   val depth = 2
                    608:                  val max = 5
                    609:                  val increase = (bodysize*(depth - n)) div depth
                    610:             in if (predicted <= increase
                    611:                    orelse (!escape=0 andalso
                    612:                            (calls = 1
                    613:                    orelse (case vl of
                    614:                              [_] => calls = 2 andalso
                    615:                                     predicted - (size+1) <= increase
                    616:                            | _ => false))))
                    617:                    andalso (n <= max orelse (debugprint "n>";
                    618:                                              debugprint(makestring max);
                    619:                                              debugprint "\n"; false))
                    620:                then let val new = beta(n+1, d+1, substitute(vl,args,body))
                    621:                     in click "";
                    622:                        call := calls-1;
                    623:                        app unescapeargs vl;
                    624:                        new
                    625:                     end
                    626:                else e
                    627:            end
                    628:            | _ => e) handle Expand => e)
                    629:        | FIX(l,ce) => let fun h(f,vl,e) = 
                    630:                             case get f
                    631:                              of Fun{escape=ref 0,...} => (f,vl, beta(n,0,e))
                    632:                               | _ => (f,vl,e)
                    633:                       in FIX(if n<1 then map h l else l, 
                    634:                              beta(n,d+length l, ce))
                    635:                      end
                    636:        | SWITCH(v,l) => SWITCH(v, map (fn e => beta(n,d+2,e)) l)
                    637:        | PRIMOP(i,vl,wl,ce) => PRIMOP(i, vl, wl, map (fn e => beta(n,d+2,e)) ce)
                    638: 
                    639:     in debugprint("\nExpand ("); debugprint(makestring(pass1 cexp));
                    640:        debugprint("): "); debugflush();
                    641:        beta(0,0,cexp)
                    642:    end
                    643: 
                    644:   val bodysize = !System.Control.CG.bodysize
                    645:   val rounds = !System.Control.CG.rounds
                    646:   val reducemore = !System.Control.CG.reducemore
                    647: 
                    648:   fun contracter last cexp =
                    649:         let val cexp = (clicked := 0; contract false cexp)
                    650:          in if !clicked <= reducemore
                    651:             then if last
                    652:                  then contract last cexp
                    653:                  else cexp
                    654:             else contracter last cexp
                    655:         end
                    656: 
                    657:   fun cycle(0,cexp) = contract true cexp
                    658:     | cycle(1,cexp) = 
                    659:        let val _ = debugprint "\nHoist: "
                    660:            val cexp = hoist cexp
                    661:            val _ = clicked := 0
                    662:            val cexp = expand(cexp,bodysize div rounds)
                    663:            val cl = !clicked before clicked := 0
                    664:         in if cl <= reducemore
                    665:           then contract true cexp
                    666:           else contracter true cexp
                    667:        end
                    668:     | cycle(k,cexp) = 
                    669:        let val _ = debugprint "\nHoist: "
                    670:            val cexp = hoist cexp
                    671:            val _ = clicked := 0
                    672:            val cexp = expand(cexp,(bodysize * k) div rounds)
                    673:            val cl = !clicked before clicked := 0
                    674:         in if cl <= reducemore
                    675:           then contract true cexp
                    676:           else cycle(k-1, contract false cexp)
                    677:        end
                    678: in cycle(rounds,contracter false (eta cexp))
                    679:    before (debugprint "\n"; debugflush())
                    680: end
                    681: end

unix.superglobalmegacorp.com

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