1 (* Copyright (C) 2009,2017 Matthew Fluet.
2 * Copyright (C) 2005-2007 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
9 functor PrePasses (S: PREPASSES_STRUCTS): PREPASSES =
16 (* A critical edge is one that connects a block with two or more
17 * succesors to one with two or more predecessors.
18 * This prepass breaks all critical edges by inserting an eta-block.
19 * For some analyses and transformations, simply ensuring the unique
20 * successor or predecessor property is sufficient. (For example, see
21 * the comments at the end of "Conditional Constant Propagation" in
22 * Section 19.3 of Appel's "Modern Compiler Implementation in ML".)
23 * However, passes that require critical edges to be broken in order
24 * to accomodate code motion (for example, PRE), should also break an
25 * edge that connects a block with non-goto transfer to one with two
26 * or more predecessors.
28 structure CriticalEdges =
33 datatype t = T of {args: (Var.t * Type.t) vector,
39 fun make f (T r) = f r
40 fun make' f = (make f, ! o (make f))
43 val (inDeg', inDeg) = make' #inDeg
44 val mustBreak = make #mustBreak
45 val (outDeg', outDeg) = make' #outDeg
48 fun new (args, mustBreak): t = T {args = args,
50 mustBreak = mustBreak,
54 fun breakFunction (f, {codeMotion: bool}) =
56 val {get = labelInfo: Label.t -> LabelInfo.t,
57 set = setLabelInfo, ...} =
59 (Label.plist, Property.initRaise ("CriticalEdges.labelInfo", Label.layout))
60 val argsLabel = LabelInfo.args o labelInfo
61 val inDeg = LabelInfo.inDeg o labelInfo
62 val inDeg' = LabelInfo.inDeg' o labelInfo
63 val mustBreak = LabelInfo.mustBreak o labelInfo
64 val outDeg = LabelInfo.outDeg o labelInfo
65 val outDeg' = LabelInfo.outDeg' o labelInfo
67 val {args, blocks, mayInline,
68 name, raises, returns, start} = Function.dest f
72 (blocks, fn Block.T {args, label, transfer, ...} =>
76 Bug => false (* no successors *)
78 | Raise _ => false (* no successors *)
79 | Return _ => false (* no successors *)
82 setLabelInfo (label, LabelInfo.new (args, mustBreak))
86 (blocks, fn Block.T {label, transfer, ...} =>
88 val outDeg' = outDeg' label
97 val newBlocks = ref []
100 val l' = Label.newString "L_crit"
103 (argsLabel l, fn (x, ty) =>
108 Block.T {args = args,
110 statements = Vector.new0 (),
111 transfer = Goto {dst = l,
112 args = Vector.map(args, #1)}})
118 (blocks, fn b as Block.T {args, label, statements, transfer} =>
119 if (codeMotion andalso mustBreak label)
120 orelse outDeg label >= 2
123 Transfer.replaceLabel
129 Block.T {args = args,
131 statements = statements,
132 transfer = doit transfer}
136 Function.new {args = args,
137 blocks = Vector.concat [blocks, Vector.fromList (!newBlocks)],
138 mayInline = mayInline,
145 fun break (Program.T {datatypes, globals, functions, main}, codeMotion) =
148 List.revMap (functions, fn f =>
149 breakFunction (f, codeMotion))
151 Program.T {datatypes = datatypes,
153 functions = functions,
158 val breakCriticalEdgesFunction = CriticalEdges.breakFunction
159 (* quell unused warning *)
160 val _ = breakCriticalEdgesFunction
161 val breakCriticalEdges = CriticalEdges.break
163 structure DeadBlocks =
166 fun eliminateFunction f =
168 val {args, blocks, mayInline, name, raises, returns, start} =
170 val {get = isLive, set = setLive, rem} =
171 Property.getSetOnce (Label.plist, Property.initConst false)
172 val _ = Function.dfs (f, fn Block.T {label, ...} =>
173 (setLive (label, true)
176 if Vector.forall (blocks, isLive o Block.label)
182 (blocks, isLive o Block.label)
184 Function.new {args = args,
186 mayInline = mayInline,
192 val _ = Vector.foreach (blocks, rem o Block.label)
197 fun eliminate (Program.T {datatypes, globals, functions, main}) =
198 Program.T {datatypes = datatypes,
200 functions = List.revMap (functions, eliminateFunction),
204 val eliminateDeadBlocksFunction = DeadBlocks.eliminateFunction
205 val eliminateDeadBlocks = DeadBlocks.eliminate
211 fun orderFunctions (p as Program.T {globals, datatypes, main, ...}) =
213 val functions = ref []
218 val {args, mayInline, name, raises, returns, start, ...} =
224 (List.push (blocks, b)
226 val f = Function.new {args = args,
227 blocks = Vector.fromListRev (!blocks),
228 mayInline = mayInline,
234 List.push (functions, f)
238 Program.T {datatypes = datatypes,
240 functions = List.rev (!functions),
246 val orderFunctions = Order.orderFunctions
252 fun reverseFunctions (Program.T {globals, datatypes, functions, main}) =
253 Program.T {datatypes = datatypes,
255 functions = List.rev functions,
259 val reverseFunctions = Reverse.reverseFunctions