(* census-fn.sml * * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu) * All rights reserved. * * Compute use counts for IL variables and initialize their bindings. *) functor CensusFn (IL : SSA) : sig structure IL : SSA val init : IL.program -> unit val inc : IL.var -> unit val dec : IL.var -> unit end = struct structure IL = IL fun inc (IL.V{useCnt, ...}) = (useCnt := !useCnt + 1) fun dec (IL.V{useCnt, ...}) = (useCnt := !useCnt - 1) fun init (IL.Program{globalInit, initially, strands, ...}) = let fun clearVar (IL.V{useCnt, ...}) = useCnt := 0 (* clear the counts of the variables defined in a node *) fun clearNode (IL.ND{kind, ...}) = (case kind of IL.JOIN{phis, ...} => List.app (fn (x, _) => clearVar x) (!phis) | IL.ASSIGN{stm=(x, _), ...} => clearVar x | IL.MASSIGN{stm=(xs, _, _), ...} => List.app clearVar xs | _ => () (* end case *)) (* clear the counts of the initially code *) fun clearInitially (IL.Initially{rangeInit, iters, create, ...}) = let fun clearIter (param, lo, hi) = clearVar param in IL.CFG.apply clearNode rangeInit; List.app clearIter iters; IL.CFG.apply clearNode (#1 create) end (* clear the counts of the variables defined in an strand *) fun clearStrand (IL.Strand{params, state, stateInit, methods, ...}) = let fun clearMethod (IL.Method{body, ...}) = IL.CFG.apply clearNode body in List.app clearVar params; IL.CFG.apply clearNode stateInit; List.app clearMethod methods end (* increment the use counts of a list of variables *) val incList = List.app inc (* increment the counts of the variables used in a node. The exitCount function * is used to count the live variables at exits, since the context affects the * treatment of these. *) fun incNode exitCount (IL.ND{kind, ...}) = (case kind of IL.JOIN{phis, ...} => let fun f (y, xs) = incList xs in List.app f (!phis) end | IL.COND{cond, ...} => inc cond | IL.ASSIGN{stm = (y, rhs), ...} => IL.RHS.app inc rhs | IL.MASSIGN{stm = (ys, rator, xs), ...} => List.app inc xs | IL.NEW{args, ...} => incList args | IL.SAVE{rhs, ...} => inc rhs | IL.EXIT{live, ...} => exitCount live | _ => () (* end case *)) (* increment the counts of variables used in the initially code *) fun incInitially (IL.Initially{create, rangeInit, iters, ...}) = let fun incIter (param, lo, hi) = (inc lo; inc hi) in IL.CFG.apply (incNode (fn live => incList live)) rangeInit; List.app incIter iters; IL.CFG.apply (incNode (fn _ => ())) (#1 create); List.app inc (#3 create) end (* increment the counts of the variables used in a strand *) fun incStrand (IL.Strand{params, state, stateInit, methods, ...}) = let fun incMethod (IL.Method{body, ...}) = IL.CFG.apply (incNode (fn live => incList live)) body in IL.CFG.apply (incNode (fn live => incList live)) stateInit; List.app incMethod methods end in (* first clear the counts of all variables *) IL.CFG.apply clearNode globalInit; clearInitially initially; List.app clearStrand strands; (* then count uses *) IL.CFG.apply (incNode (fn _ => ())) globalInit; incInitially initially; List.app incStrand strands end end