Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /branches/vis12/src/compiler/IL/promote-fn.sml
ViewVC logotype

Annotation of /branches/vis12/src/compiler/IL/promote-fn.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2799 - (view) (download)

1 : jhr 2796 (* promote-fn.sml
2 :     *
3 :     * COPYRIGHT (c) 2014 The Diderot Project (http://diderot-language.cs.uchicago.edu)
4 :     * All rights reserved.
5 :     *
6 :     * Transformations, such as normalization, can create references to variables defined
7 :     * in the global initialization section from nested scopes (e.g., inside strands).
8 :     * This functor implements a pass that promotes such variables to be globals.
9 :     *)
10 :    
11 :     functor PromoteFn (IL : SSA) : sig
12 :    
13 :     val transform : IL.program -> IL.program
14 :    
15 :     end = struct
16 :    
17 :     structure V = IL.Var
18 :     structure VTbl = V.Tbl
19 :     structure VMap = V.Map
20 :    
21 :     (* adjust a variable's use count *)
22 :     fun incUse (IL.V{useCnt, ...}) = (useCnt := !useCnt + 1)
23 :     fun decUse (IL.V{useCnt, ...}) = (useCnt := !useCnt - 1)
24 :     fun incGlobal (IL.GV{useCnt, ...}) = (useCnt := !useCnt + 1)
25 :    
26 :     (* variables in the global initialization section are either just used locally
27 :     * or used to define a global (via GASSIGN).
28 :     *)
29 :     datatype info = LOCAL | GLOBAL of IL.global_var
30 :    
31 : jhr 2799 fun initTbl (inputInit, globalInit) = let
32 : jhr 2796 val tbl = VTbl.mkTable (64, Fail "promote")
33 :     val insert = VTbl.insert tbl
34 :     fun doNode nd = (case IL.Node.kind nd
35 :     of IL.GASSIGN{lhs, rhs, ...} => insert (rhs, GLOBAL lhs)
36 :     | _ => List.app (fn x => insert (x, LOCAL)) (IL.Node.defs nd)
37 :     (* end case *))
38 :     in
39 : jhr 2799 IL.CFG.apply doNode inputInit;
40 :     IL.CFG.apply doNode globalInit;
41 : jhr 2796 tbl
42 :     end
43 :    
44 :     fun transform (prog as IL.Program{globals=[], ...}) = prog
45 : jhr 2799 | transform (IL.Program{props, globals, inputInit, globalInit, initially, strands}) = let
46 : jhr 2796 (* table mapping locals in the globalInit to info *)
47 : jhr 2799 val promoteTbl = initTbl (inputInit, globalInit)
48 : jhr 2796 (* newly defined globals paired with their globalInit local definition *)
49 :     val newGlobs : (IL.global_var * IL.var) list ref = ref []
50 :     (* update a CFG as necessary to references to globalInit locals with references to new
51 :     * globals.
52 :     *)
53 :     fun doCFG cfg = let
54 :     (* assignment statements to load local copies of the new globals; these get put
55 :     * at the beginning of the block.
56 :     *)
57 :     val initStms = ref []
58 :     fun doNode (nd as IL.ND{id, props, kind}, env) = let
59 :     fun doUse (false, [], _, env, _) = env
60 :     | doUse (true, [], ys, env, mkNode) = (
61 :     IL.CFG.replaceNode (nd, mkNode(List.rev ys));
62 :     env)
63 :     | doUse (changed, x::xs, ys, env, mkNode) = (case VTbl.find promoteTbl x
64 :     of SOME LOCAL => let
65 :     val x' = V.copy x
66 :     val gx = IL.GlobalVar.new(false, V.name x, V.ty x)
67 :     in
68 :     decUse x; incUse x'; incGlobal gx;
69 :     initStms := IL.ASSGN(x', IL.GLOBAL gx) :: !initStms;
70 :     newGlobs := (gx, x) :: !newGlobs;
71 :     VTbl.insert promoteTbl (x, GLOBAL gx);
72 :     doUse (true, xs, x'::ys, VMap.insert(env, x, x'), mkNode)
73 :     end
74 :     | SOME(GLOBAL gx) => (case VMap.find(env, x)
75 :     of SOME x' => (
76 :     decUse x; incUse x';
77 :     doUse (true, xs, x'::ys, env, mkNode))
78 :     | NONE => let (* no previous use of g in this CFG *)
79 :     val x' = V.copy x
80 :     in
81 :     decUse x; incUse x'; incGlobal gx;
82 :     initStms := IL.ASSGN(x', IL.GLOBAL gx) :: !initStms;
83 :     doUse (true, xs, x'::ys, VMap.insert(env, x, x'), mkNode)
84 :     end
85 :     (* end case *))
86 :     | NONE => doUse (changed, xs, x::ys, env, mkNode)
87 :     (* end case *))
88 :     fun doArgs (args, mkNode) = doUse (false, args, [], env, mkNode)
89 :     in
90 :     case kind
91 :     of IL.NULL => env
92 :     | IL.ENTRY _ => env
93 :     | IL.JOIN _ => env
94 :     | IL.COND _ => env
95 :     | IL.COM _ => env
96 :     | IL.ASSIGN{stm=(lhs, rhs), ...} => (case rhs
97 :     of IL.GLOBAL _ => env
98 :     | IL.STATE _ => env
99 :     | IL.VAR x => doArgs ([x], fn [x] => IL.Node.mkASSIGN(lhs, IL.VAR x))
100 :     | IL.LIT _ => env
101 :     | IL.OP(rator, args) =>
102 :     doArgs (args, fn args => IL.Node.mkASSIGN(lhs, IL.OP(rator, args)))
103 :     | IL.APPLY(f, args) =>
104 :     doArgs (args, fn args => IL.Node.mkASSIGN(lhs, IL.APPLY(f, args)))
105 :     | IL.CONS(ty, args) =>
106 :     doArgs (args, fn args => IL.Node.mkASSIGN(lhs, IL.CONS(ty, args)))
107 :     (* end case *))
108 :     | IL.MASSIGN{stm=(lhs, rator, rhs), ...} =>
109 :     doArgs (rhs, fn rhs => IL.Node.mkMASSIGN(lhs, rator, rhs))
110 :     | IL.GASSIGN _ => raise Fail "unexpected GASSIGN"
111 :     | IL.NEW{strand, args, ...} =>
112 :     doArgs (args, fn args => IL.Node.mkNEW{strand=strand, args=args})
113 :     | IL.SAVE{lhs, rhs, ...} =>
114 :     doArgs ([rhs], fn [rhs] => IL.Node.mkSAVE(lhs, rhs))
115 :     | IL.EXIT{live=[], ...} => env
116 :     | IL.EXIT{kind, live, ...} =>
117 :     doArgs (live, fn live => IL.Node.mkEXIT(kind, live))
118 :     (* end case *)
119 :     end
120 :     in
121 :     List.foldl doNode VMap.empty (IL.CFG.sort cfg);
122 :     case !initStms
123 :     of [] => cfg
124 :     | stms => IL.CFG.prependBlock(List.rev stms, cfg)
125 :     (* end case *)
126 :     end
127 :     (* process the initially code *)
128 :     val initially' = let
129 :     val IL.Initially{isArray, rangeInit, iters, create=(cfg, strand, args)} = initially
130 :     in
131 :     IL.Initially{
132 :     isArray = isArray,
133 :     rangeInit = doCFG rangeInit,
134 :     iters = iters,
135 :     create = (doCFG cfg, strand, args)
136 :     }
137 :     end
138 :     (* process a strand method *)
139 :     fun doMeth (IL.Method{name, body}) = IL.Method{name = name, body = doCFG body}
140 :     (* process a strand *)
141 :     fun doStrand (IL.Strand{name, params, state, stateInit, methods}) = IL.Strand{
142 :     name = name, params = params, state = state,
143 :     stateInit = doCFG stateInit,
144 :     methods = List.map doMeth methods
145 :     }
146 :     val strands' = List.map doStrand strands
147 :     (* check to see if we have created new globals and thus need to update the globalInit block *)
148 :     val (globals', globalInit') = (case !newGlobs
149 :     of [] => (globals, globalInit)
150 :     | globs => let
151 :     fun f ([], globals, stms) = (globals, stms)
152 :     | f ((gx, x)::globs, globals, stms) = (
153 :     incUse x;
154 :     f (globs, gx::globals, IL.GASSGN(gx, x)::stms))
155 :     val (globals', stms) = f (globs, [], [])
156 :     in
157 :     (globals @ globals', IL.CFG.appendBlock (globalInit, stms))
158 :     end
159 :     (* end case *))
160 :     in
161 :     IL.Program{
162 :     props = props,
163 :     globals = globals',
164 : jhr 2799 inputInit = inputInit,
165 : jhr 2796 globalInit = globalInit',
166 :     initially = initially',
167 :     strands = strands'
168 :     }
169 :     end
170 :    
171 :     end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0