SCM Repository
View of /sml/branches/SMLNJ/src/compiler/FLINT/cpsopt/expandNEW.sml
Parent Directory
|
Revision Log
Revision 67 -
(download)
(annotate)
Fri Apr 3 00:06:42 1998 UTC (24 years, 3 months ago)
File size: 25982 byte(s)
Fri Apr 3 00:06:42 1998 UTC (24 years, 3 months ago)
File size: 25982 byte(s)
This commit was manufactured by cvs2svn to create branch 'SMLNJ'.
(* Copyright 1996 by Bell Laboratories *) (* expand.sml *) functor ExpandNEW (MachSpec : MACH_SPEC) : EXPAND = struct local open CPS structure CG = Control.CG structure LV = LambdaVar in fun inc r = (r := !r + 1) fun dec r = (r := !r - 1) fun map1 f (a,b) = (f a, b) fun sum f = let fun h [] = 0 | h (a::r) = f a + h r in h end fun split pred (a::rest) = let val (t,f) = split pred rest in if pred a then (a::t,f) else (t,a::f) end | split pred nil = (nil,nil) fun muldiv(a,b,c) = (* a*b/c, approximately, but guaranteed no overflow *) (a*b) div c handle Overflow => if a>b then muldiv(a div 2,b,c div 2) else muldiv(a,b div 2,c div 2) fun sameName(x,VAR y) = LV.sameName(x,y) | sameName(x,LABEL y) = LV.sameName(x,y) | sameName _ = () datatype mode = ALL | NO_UNROLL | UNROLL of int | HEADERS fun expand{function=(fkind,fvar,fargs,ctyl,cexp),unroll,bodysize,click, afterClosure,table=typtable,do_headers} = let val clicked_any = ref false val debug = !CG.debugcps (* false *) val debugprint = if debug then Control.Print.say else fn _ => () val debugflush = if debug then Control.Print.flush else fn _ => () val click = fn z => (debugprint z; (* temporary *) click z; clicked_any := true) val CGinvariant = !CG.invariant fun label v = if afterClosure then LABEL v else VAR v datatype info = Fun of {escape: int ref, (* how many non-call uses *) call: int ref, (* how many calls to this func *) size: int ref, (* size of function body *) args: lvar list, (* formal parameters *) body: cexp, (* function body *) invariant: bool list ref, (* one for each arg *) sibling_call: int ref, (* how many of calls are from other functions defined in same FIX *) unroll_call: int ref, (* how many calls are from within this func's body *) level: int, (* loop-nesting level of this function *) within: bool ref,(* are we currently doing pass1 within this function's body? *) within_sibling: bool ref (* are we currently doing passw within the body of this function or any of the other functions defined in the same FIX? *) } | Arg of {escape: int ref, savings: int ref, record: (int * lvar) list ref} | Sel of {savings: int ref} | Rec of {escape: int ref, size: int, vars: (value * accesspath) list} | Real | Const | Other val rep_flag = MachSpec.representations val type_flag = (!Control.CG.checkcps1) andalso (!Control.CG.checkcps1) andalso rep_flag local exception NEXPAND fun getty v = if type_flag then (Intmap.map typtable v) handle _ => (Control.Print.say ("NEXPAND: Can't find the variable "^ (Int.toString v)^" in the typtable ***** \n"); raise NEXPAND) else LtyExtern.ltc_void fun addty(f,t) = Intmap.add typtable (f,t) in fun mkv(t) = let val v = LV.mkLvar() val _ = if type_flag then addty(v,t) else () in v end fun copyLvar v = let val x = LV.dupLvar(v) val _ = if type_flag then addty(x,getty v) else () in x end end (* local *) local exception Expand val m : info Intmap.intmap = Intmap.new(128,Expand) val get' = Intmap.map m in val note = Intmap.add m fun get i = get' i handle Expand => Other fun discard_pass1_info() = Intmap.clear m end fun getval(VAR v) = get v | getval(LABEL v) = get v | getval(INT _) = Const (* | getval(REAL _) = Real*) | getval _ = Other fun call(v, args) = case getval v of Fun{call,within=ref false, within_sibling=ref false,...} => inc call | Fun{call,within=ref false,within_sibling=ref true, sibling_call,...} => (inc call; inc sibling_call) | Fun{call,within=ref true,unroll_call, args=vl,invariant,...} => let fun g(VAR x :: args, x' :: vl, i::inv) = (i andalso x=x') :: g(args,vl,inv) | g( _ :: args, _ :: vl, i::inv) = false :: g(args,vl,inv) | g _ = nil in inc call; inc unroll_call; invariant := g(args,vl,!invariant) end | Arg{savings,...} => inc savings | Sel{savings} => inc savings | _ => () fun escape v = case getval v of Fun{escape,...} => inc escape | Arg{escape,...} => inc escape | Rec{escape,...} => inc escape | _ => () fun escapeargs v = case getval v of Fun{escape,...} => inc escape | Arg{escape,savings, ...} => (inc escape; inc savings) | Sel{savings} => inc savings | Rec{escape,...} => inc escape | _ => () fun unescapeargs v = case getval v of Fun{escape,...} => dec escape | Arg{escape,savings, ...} => (dec escape; dec savings) | Sel{savings} => dec savings | Rec{escape,...} => dec escape | _ => () fun notearg v = (note (v,Arg{escape=ref 0,savings=ref 0, record=ref []})) fun noteother v = () (* note (v,Other) *) fun notereal v = noteother v (* note (v,Real) *) fun enter level (_,f,vl,_,e) = (note(f,Fun{escape=ref 0, call=ref 0, size=ref 0, args=vl, body=e, within=ref false, within_sibling=ref false, unroll_call = ref 0, sibling_call=ref 0, invariant = ref(map (fn _ => CGinvariant) vl), level=level}); app notearg vl) fun noterec(w, vl, size) = note (w,Rec{size=size,escape=ref 0,vars=vl}) fun notesel(i,v,w) = (note (w, Sel{savings=ref 0}); case getval v of Arg{savings,record,...} => (inc savings; record := (i,w)::(!record)) | _ => ()) fun setsize(f,n) = case get f of Fun{size,...} => (size := n; n) fun incsave(v,k) = case getval v of Arg{savings,...} => savings := !savings + k | Sel{savings} => savings := !savings + k | _ => () fun setsave(v,k) = case getval v of Arg{savings,...} => savings := k | Sel{savings} => savings := k | _ => () fun savesofar v = case getval v of Arg{savings,...} => !savings | Sel{savings} => !savings | _ => 0 fun within_sibling fundefs func arg = (app (fn (_,f,_,_,_) => case get f of Fun{within_sibling=w,...} => w := true) fundefs; func arg before (app (fn (_,f,_,_,_) => case get f of Fun{within_sibling=w,...} => w := false) fundefs)) fun within f func arg = case get f of Fun{within=w,...} => (w := true; func arg before (w := false)) val rec prim = fn (level,vl,e) => let fun vbl(VAR v) = (case get v of Rec _ => 0 | _ => 1) | vbl _ = 0 val nonconst = sum vbl vl val sl = map savesofar vl val afterwards = pass1 level e val zl = map savesofar vl val overhead = length vl + 1 val potential = overhead val savings = case nonconst of 1 => potential | 2 => potential div 4 | _ => 0 fun app3 f = let fun loop (a::b,c::d,e::r) = (f(a,c,e); loop(b,d,r)) | loop _ = () in loop end in app3(fn (v,s,z)=> setsave(v,s + savings + (z-s))) (vl,sl,zl); overhead+afterwards end and primreal = fn (level,(_,vl,w,_,e)) => (notereal w; app (fn v => incsave(v,1)) vl; 2*(length vl + 1) + pass1 level e) (*******************************************************************) (* pass1: gather info on code. *) (*******************************************************************) and pass1 : int -> cexp -> int= fn level => fn RECORD(_,vl,w,e) => let val len = length vl in app (escape o #1) vl; noterec(w,vl,len); 2 + len + pass1 level e end | SELECT (i,v,w,_,e) => (notesel(i,v,w); 1 + pass1 level e) | OFFSET (i,v,w,e) => (noteother w; 1 + pass1 level e) | APP(f,vl) => (call(f,vl); app escapeargs vl; 1 + ((length vl + 1) div 2)) | FIX(l, e) => (app (enter level) l; within_sibling l (fn () => (sum (fn (_,f,_,_,e) => setsize(f, within f (pass1 (level+1)) e)) l + length l + pass1 level e)) ()) | SWITCH(v,_,el) => let val len = length el val jumps = 4 + len val branches = sum (pass1 level) el in incsave(v, muldiv(branches,len-1,len) + jumps); jumps+branches end | BRANCH(_,vl,c,e1,e2) => let fun vbl(VAR v) = (case get v of Rec _ => 0 | _ => 1) | vbl _ = 0 val nonconst = sum vbl vl val sl = map savesofar vl val branches = pass1 level e1 + pass1 level e2 val zl = map savesofar vl val overhead = length vl val potential = overhead + branches div 2 val savings = case nonconst of 1 => potential | 2 => potential div 4 | _ => 0 fun app3 f = let fun loop (a::b,c::d,e::r) = (f(a,c,e); loop(b,d,r)) | loop _ = () in loop end in app3(fn (v,s,z)=> setsave(v,s + savings + (z-s) div 2)) (vl,sl,zl); overhead+branches end | LOOKER(_,vl,w,_,e) => (noteother w; prim(level,vl,e)) | SETTER(_,vl,e) => prim(level,vl,e) | ARITH(args as (P.arith{kind=P.FLOAT 64,...},_,_,_,_)) => primreal (level,args) | ARITH(args as (P.round _, _,_,_,_)) => primreal (level,args) | ARITH(_,vl,w,_,e) => (noteother w; prim(level,vl,e)) | PURE(P.pure_arith{kind=P.FLOAT 64,...},[v],w,_,e) => (notereal w; incsave(v,1); 4+(pass1 level e)) | PURE(P.real{tokind=P.FLOAT 64,...},vl,w,_,e) => (notereal w; prim(level,vl,e)) | PURE(_,vl,w,_,e) => (noteother w; prim(level,vl,e)) (*********************************************************************) (* substitute(args,wl,e,alpha) : substitute args for wl in e. *) (* If alpha=true, also rename all bindings. *) (*********************************************************************) fun substitute(args,wl,e,alpha) = let exception Alpha val vm : value Intmap.intmap = Intmap.new(16, Alpha) fun look (v,default) = Intmap.map vm v handle Alpha => default val enter = Intmap.add vm fun use(v0 as VAR v) = look(v,v0) | use(v0 as LABEL v) = look(v,v0) | use x = x fun def v = if alpha then let val w = copyLvar v in enter (v, VAR w); w end else v fun defl v = if alpha then let val w = copyLvar v in enter (v, label w); w end else v fun bind(a::args,w::wl) = (sameName(w,a); enter (w,a); bind(args,wl)) | bind _ = () val rec g = fn RECORD(k,vl,w,ce) => RECORD(k,map (map1 use) vl, def w, g ce) | SELECT(i,v,w,t,ce) => SELECT(i, use v, def w, t, g ce) | OFFSET(i,v,w,ce) => OFFSET(i, use v, def w, g ce) | APP(v,vl) => APP(use v, map use vl) | FIX(l,ce) => let (* Careful: order of evaluation is important here. *) fun h1(fk,f,vl,cl,e) = (fk,defl f,vl,cl,e) fun h2(fk,f',vl,cl,e) = let val vl' = map def vl val e'= g e in (fk,f',vl',cl,e') end in FIX(map h2(map h1 l), g ce) end | SWITCH(v,c,l) => SWITCH(use v, def c, map g l) | LOOKER(i,vl,w,t,e) => LOOKER(i, map use vl, def w, t, g e) | ARITH(i,vl,w,t,e) => ARITH(i, map use vl, def w, t, g e) | PURE(i,vl,w,t,e) => PURE(i, map use vl, def w, t, g e) | SETTER(i,vl,e) => SETTER(i, map use vl, g e) | BRANCH(i,vl,c,e1,e2) => BRANCH(i, map use vl, def c, g e1, g e2) in bind(args,wl); g e end fun whatsave(acc, size, (v:value)::vl, a::al) = if acc>=size then acc else (case get a of Arg{escape=ref esc,savings=ref save,record=ref rl} => let val (this, nvl: value list, nal) = case getval v of Fun{escape=ref 1,...} => (if esc>0 then save else 6+save,vl,al) | Fun _ => (save,vl,al) | Rec{escape=ref ex,vars,size} => let exception Chase fun chasepath(v,OFFp 0) = v | chasepath(v, SELp(i,p)) = (case getval v of Rec{vars,...} => chasepath(chasepath(List.nth(vars,i)),p) | _ => raise Chase) | chasepath _ = raise Chase fun loop([],nvl,nal) = (if ex>1 orelse esc>0 then save else save+size+2,nvl,nal) | loop((i,w)::rl,nvl,nal) = loop(rl, chasepath(List.nth(vars,i))::nvl, w::nal) in loop(rl,vl,al) handle Chase => (0,vl,al) | Subscript => (0,vl,al) end (* | Real => (save,vl,al)*) | Const => (save,vl,al) | _ => (0,vl,al) in whatsave(acc+this - muldiv(acc,this,size), size, nvl,nal) end | Sel{savings=ref save} => let val this = case v of VAR v' => (case get v' of Fun _ => save | Rec _ => save | _ => 0) | _ => save in whatsave(acc + this - muldiv(acc,this,size),size, vl,al) end) | whatsave(acc,size,_,_) = acc (************************************************************* * should_expand: should a function application be inlined? * *************************************************************) fun should_expand(d, (* path length from entry to current function *) u, (* unroll level *) e as APP(v,vl), Fun{escape,call,unroll_call,size=ref size,args,body, level,within=ref within,...}) = if !call + !escape = 1 then false else let val stupidloop = (* prevent infinite loops at compile time *) case (v,body) of (VAR vv, APP(VAR v',_)) => vv=v' | (LABEL vv, APP(LABEL v',_)) => vv=v' | _ => false val calls = case u of UNROLL _ => !unroll_call | _ => !call val small_fun_size = case u of UNROLL _ => 0 | _ => 50 val savings = whatsave(0,size,vl,args) val predicted = let val real_increase = size-savings-(1+length vl) in real_increase * calls - (* don't subtract off the original body if the original body is huge (because we might have guessed wrong and the consequences are too nasty for big functions); or if we're in unroll mode *) (if size < small_fun_size then size else 0) end val depth = 2 and max = 2 in if false andalso debug then (PPCps.prcps e; debugprint(Int.toString predicted); debugprint " "; debugprint(Int.toString bodysize); debugprint "\n") else (); not stupidloop andalso case u of UNROLL lev => (* Unroll if: the loop body doesn't make function calls orelse "unroll_recur" is turned on; andalso we are within the definition of the function; andalso it looks like things won't grow too much. *) (!CG.unroll_recur orelse level >= lev) andalso within andalso predicted <= bodysize | NO_UNROLL => !unroll_call = 0 andalso not within andalso (predicted <= bodysize orelse (!escape=0 andalso calls = 1)) | HEADERS => false (* shouldn't get here *) | ALL => (predicted <= bodysize orelse (!escape=0 andalso calls = 1)) end datatype decision = YES of {formals: lvar list, body: cexp} | NO of int (* how many no's in a row *) (* There is really no point in making decisions a ref. This should be changed one day. *) val decisions : decision list ref = ref nil fun decide_yes x = decisions := YES x :: !decisions fun decide_no () = decisions := (case !decisions of NO n :: rest => NO(n+1) :: rest | d => NO 1 :: d) (*********************************************************************) (* pass2: mark function applications to be inlined. *) (*********************************************************************) fun pass2(d, (* path length from start of current function *) u, (* unroll-info *) e (* expression to traverse *) ) = case e of RECORD(k,vl,w,ce) => pass2(d+2+length vl,u,ce) | SELECT(i,v,w,t,ce) => pass2(d+1,u,ce) | OFFSET(i,v,w,ce) => pass2(d+1,u,ce) | APP(v,vl) => (case getval v of info as Fun{args,body,...} => if should_expand(d,u,e,info) then decide_yes{formals=args,body=body} else decide_no() | _ => decide_no()) | FIX(l,ce) => let fun fundef (NO_INLINE_INTO,_,_,_,_) = () | fundef (fk,f,vl,cl,e) = let val Fun{level,within,escape=ref escape,...} = get f val u' = case u of UNROLL _ => UNROLL level | _ => u fun conform((VAR x)::r,z::l) = (x=z) andalso conform(r,l) | conform(_::r,_::l) = false | conform([],[]) = true | conform _ = false in within := true; pass2(0,u',e) before within := false end in app fundef l; pass2(d+length l,u,ce) end | SWITCH(v,c,l) => app (fn e => pass2(d+2,u,e)) l | LOOKER(i,vl,w,t,e) => pass2(d+2,u,e) | ARITH(i,vl,w,t,e) => pass2(d+2,u,e) | PURE(i,vl,w,t,e) => pass2(d+2,u,e) | SETTER(i,vl,e) => pass2(d+2,u,e) | BRANCH(i,vl,c,e1,e2) => (pass2(d+2,u,e1); pass2(d+2,u,e2)) (* Do loop-header optimizations, elimination of invariant loop arguments, hoisting of invariant computations. *) fun from_outside (_,f,_,_,_) = case get f of Fun{escape,call,unroll_call,sibling_call,...} => !escape > 0 orelse !call > !unroll_call + !sibling_call fun loop_opt(bigexp) = let exception Gamma_Levmap (* For each variable, tell what level of loop nesting at its definition*) val levmap : int Intmap.intmap = Intmap.new(16,Gamma_Levmap) val level_of' = Intmap.map levmap fun level_of(VAR v) = (level_of' v handle Gamma_Levmap => 0 ) (* ^^^ clean this up *) | level_of(LABEL v) = level_of (VAR v) | level_of _ = 0 val note_level = Intmap.add levmap val _ = app (fn v => note_level(v,0)) fargs exception Gamma_Hoistmap (* For each level, tell what expressions are hoisted there *) val hoistmap : (cexp->cexp) Intmap.intmap = Intmap.new(16,Gamma_Hoistmap) fun hoisted_here (lev) = Intmap.map hoistmap lev handle Gamma_Hoistmap => (fn e=>e) fun any_hoisted_here (lev) = (Intmap.map hoistmap lev; true) handle Gamma_Hoistmap => false fun reset_hoist(lev) = Intmap.rmv hoistmap lev fun add_hoist(lev,f) = let val h = hoisted_here lev in Intmap.add hoistmap (lev, h o f) end fun gamma_lev(level,e) = let fun def w = note_level(w,level) fun formaldef wl = app (fn w => note_level(w,level+1)) wl fun gamma e = gamma_lev(level,e) fun tryhoist(vl,w,e,f) = let val minlev = foldr Int.min 1000000000 (map level_of vl) in if minlev < level then (add_hoist(minlev, f); note_level(w, minlev); click "#"; gamma e) else (def w; f(gamma e)) end in case e of RECORD(k,vl,w,ce) => tryhoist(map #1 vl, w, ce, fn e => RECORD(k,vl, w, e)) | SELECT(i,v,w,t,ce) => tryhoist([v],w,ce, fn e=>SELECT(i, v, w, t,e)) | OFFSET(i,v,w,ce) => tryhoist([v],w,ce, fn e=>OFFSET(i, v, w, e)) | e as APP(v,vl) => e | SWITCH(v,c,l) => (def c; SWITCH(v, c, map gamma l)) | LOOKER(i,vl,w,t,e) => (def w; LOOKER(i, vl, w, t, gamma e)) | ARITH(i,vl,w,t,e) => (def w; ARITH(i, vl, w, t, gamma e)) | PURE(i,vl,w,t,e) => tryhoist(vl,w,e, fn e=>PURE(i,vl,w,t,e)) | SETTER(i,vl,e) => SETTER(i, vl, gamma e) | BRANCH(i,vl,c,e1,e2) => (def c; BRANCH(i, vl, c,gamma e1, gamma e2)) | FIX(l,ce) => let fun fundef (z as (NO_INLINE_INTO,_,_,_,_)) = z | fundef (fk,f,vl,cl,e) = let val Fun{escape=ref escape,call,unroll_call, invariant=ref inv,...} = get f val _ = app def vl (* A "loop" is a function called from inside itself. Here we will ensure that any loop has a unique entry point; that is, any loop has only one call from outside itself. We do this by making a "header" and "pre-header". Also, any argument passed around the loop but never used is hoisted out. See also: Loop Headers in Lambda-calculus or CPS. Andrew W. Appel. CS-TR-460-94, Princeton University, June 15, 1994. To appear in _Lisp and Symbolic Computation_ 7, 337-343 (1994). ftp://ftp.cs.princeton.edu/reports/1994/460.ps.Z *) in if escape = 0 andalso !unroll_call > 0 then let val e' = gamma_lev(level+1,e) in if (!call - !unroll_call > 1 orelse List.exists (fn t=>t) inv orelse any_hoisted_here(level)) then let val f'::vl' = map copyLvar (f::vl) fun drop(false::r,a::s) = a::drop(r,s) | drop(true::r,_::s) = drop(r,s) | drop _ = nil val newformals=label f' :: map VAR (drop(inv,vl')) val e'' =substitute(newformals, f :: drop(inv,vl), e', false) val hoisted = hoisted_here level in click "!"; debugprint(Int.toString f); reset_hoist level; (* app def (f'::vl'); Unnecessary *) enter 0 (fk,f',vl',cl,e''); (fk,f,vl,cl, hoisted(FIX([(fk,f',vl',cl,e'')], APP(label f', map VAR vl)))) end else (fk,f,vl,cl,e') end else (fk,f,vl,cl,gamma e) end in case split from_outside l of ([(fk,f,vl,cl,e)], others as _::_) => (* for any FIX containing more than one function, but only one of them called from the body of the FIX itself, split into two levels to hide the "auxiliary" functions inside the externally called function. *) let val Fun{sibling_call as ref sib, unroll_call as ref unr,...} = get f in sibling_call := 0; unroll_call := unr + sib; def f; click "`"; (* temporary: *) print "`"; app (fn (_,ff,_,_,_) => let val Fun{sibling_call,...} = get ff in sibling_call := 0 (* this is a conservative estimate, I hope. *) end) others; gamma(FIX([(fk,f,vl,cl, FIX(others,e))], ce)) end (* for any other kind of FIX, proceed with loop detection on each function individually*) | _ => (app (def o #2) l; FIX(map fundef l, gamma ce)) end end val bigexp' = gamma_lev(1,bigexp) in hoisted_here 0 bigexp' end val rec beta = fn RECORD(k,vl,w,ce) => RECORD(k,vl,w,beta ce) | SELECT(i,v,w,t,ce) => SELECT(i,v,w,t,beta ce) | OFFSET(i,v,w,ce) => OFFSET(i,v,w,beta ce) | e as APP(v,vl) => (case !decisions of YES{formals,body}::rest => (click "^"; case v of VAR vv => debugprint(Int.toString vv) | _ => (); debugflush(); decisions := rest; substitute(vl,formals,body,true)) | NO 1::rest => (decisions := rest; e) | NO n :: rest => (decisions := NO(n-1)::rest; e)) | FIX(l,ce) => let fun fundef (z as (NO_INLINE_INTO,_,_,_,_)) = z | fundef (fk,f,vl,cl,e) = (fk,f,vl,cl,beta e) in FIX(map fundef l, beta ce) end | SWITCH(v,c,l) => SWITCH(v,c,map beta l) | LOOKER(i,vl,w,t,e) => LOOKER(i,vl,w,t,beta e) | ARITH(i,vl,w,t,e) => ARITH(i,vl,w,t,beta e) | PURE(i,vl,w,t,e) => PURE(i,vl,w,t,beta e) | SETTER(i,vl,e) => SETTER(i,vl,beta e) | BRANCH(i,vl,c,e1,e2) => BRANCH(i,vl,c,beta e1,beta e2) fun pass2_beta(mode,e) = (pass2(0,mode,e); discard_pass1_info(); debugprint "Expand: finishing pass2\n"; debugflush(); case !decisions of [NO _] => (debugprint "No expansions to do.\n"; debugflush(); e) | _ => (decisions := rev(!decisions); debugprint "Beta: "; beta e before (debugprint "\n"; debugflush()))) fun prCexp cexp = PPCps.printcps0(fkind,fvar,fargs,ctyl,cexp) val gamma = fn c => (print "Before Gamma:\n"; prCexp c; debugprint "Gamma: "; let val c' = loop_opt c in print "After Gamma:\n"; prCexp c'; c' end before (debugprint "\n"; debugflush())) in (* body of expand *) notearg fvar; app notearg fargs; (***> if !CG.printit then CPSprint.show Control.Print.say cexp else (); <***) debugprint("Expand: pass1: "); debugprint(Int.toString(pass1 0 cexp)); debugprint "\n"; debugflush(); if unroll then let val _ = (debugprint(" (unroll)\n"); debugflush()); val e' = pass2_beta(UNROLL 0,cexp) in if !clicked_any then expand{function=(fkind,fvar,fargs,ctyl,e'), table=typtable, bodysize=bodysize,click=click,unroll=unroll, afterClosure=afterClosure, do_headers=do_headers} else ((*debugprint("\nExpand\n"); debugflush(); (fkind,fvar,fargs,ctyl,pass2_beta(ALL,cexp)) *) (fkind,fvar,fargs,ctyl,e')) end else if !CG.unroll then let val _ = (debugprint(" (headers)\n"); debugflush()) val e' = if do_headers then gamma cexp else cexp in if !clicked_any then expand{function=(fkind,fvar,fargs,ctyl,e'), table=typtable,bodysize=bodysize,click=click, unroll=unroll,afterClosure=afterClosure, do_headers=false} else (debugprint(" (non-unroll 1)\n"); debugflush(); (fkind,fvar,fargs,ctyl,pass2_beta(NO_UNROLL,e'))) end else (debugprint(" (non-unroll 2)\n"); debugflush(); (fkind,fvar,fargs,ctyl,pass2_beta(ALL,cexp))) end end (* local *) end (* functor Expand *) (* * $Log: expandNEW.sml,v $ * Revision 1.1.1.1 1997/01/14 01:38:31 george * Version 109.24 * *)
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |