Annotation of researchv10no/cmd/sml/src/cps/cpsopt.sml, revision 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.