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

SCM Repository

[diderot] Annotation of /branches/vis15/src/compiler/cfg-ir/promote-fn.sml
ViewVC logotype

Annotation of /branches/vis15/src/compiler/cfg-ir/promote-fn.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3937 - (view) (download)

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

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