|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.