1 (* Copyright (C) 2009,2011,2017 Matthew Fluet.
2 * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
10 functor Shrink (S: SHRINK_STRUCTS): SHRINK =
28 fun isProfile (T {exp, ...}) = Exp.isProfile exp
35 fun inc (a: int t, i: int): unit = update (a, i, 1 + sub (a, i))
36 fun dec (a: int t, i: int): unit = update (a, i, sub (a, i) - 1)
39 datatype z = datatype Exp.t
40 datatype z = datatype Transfer.t
44 datatype t = T of {isUsed: bool ref,
45 numOccurrences: int ref,
47 value: value option ref,
53 | Select of {tuple: t, offset: int}
56 fun equals (T {var = x, ...}, T {var = y, ...}) = Var.equals (x, y)
58 fun layout (T {isUsed, numOccurrences, ty, value, var}) =
60 in record [("isUsed", Bool.layout (!isUsed)),
61 ("numOccurrences", Int.layout (!numOccurrences)),
62 ("ty", Option.layout Type.layout ty),
63 ("value", Option.layout layoutValue (!value)),
64 ("var", Var.layout var)]
69 Con {con, args} => seq [Con.layout con,
70 Vector.layout layout args]
71 | Const c => Const.layout c
72 | Select {tuple, offset} => seq [str "#", Int.layout (offset + 1),
73 str " ", layout tuple]
74 | Tuple vis => Vector.layout layout vis
77 fun new (x: Var.t, ty: Type.t option) = T {isUsed = ref false,
78 numOccurrences = ref 0,
83 fun setValue (T {value, ...}, v) =
84 (Assert.assert ("Ssa.Shrink.VarInfo.setValue", fn () => Option.isNone (!value))
88 fun numOccurrences (T {numOccurrences = r, ...}) = r
89 fun ty (T {ty, ...}): Type.t option = ty
90 fun value (T {value, ...}): value option = !value
91 fun var (T {var, ...}): Var.t = var
96 datatype t = datatype VarInfo.value
107 Formal i => Int.layout i
108 | Free x => Var.layout x
111 fn (Formal i, Formal i') => i = i'
112 | (Free x, Free x') => Var.equals (x, x')
116 structure Positions = MonoVector (Position)
118 structure LabelMeaning =
120 datatype t = T of {aux: aux,
121 blockIndex: int, (* The index of the block *)
122 label: Label.t} (* redundant, the label of the block *)
127 | Case of {canMove: Statement.t list,
129 default: Label.t option}
130 | Goto of {canMove: Statement.t list,
133 | Raise of {args: Positions.t,
134 canMove: Statement.t list}
135 | Return of {args: Positions.t,
136 canMove: Statement.t list}
139 fun make f (T r) = f r
142 val blockIndex = make #blockIndex
145 fun layout (T {aux, label, ...}) =
149 seq [Label.layout label,
152 Block => str "Block "
154 | Case _ => str "Case"
155 | Goto {dst, args, ...} =>
157 tuple [layout dst, Positions.layout args]]
158 | Raise {args, ...} =>
159 seq [str "Raise ", Positions.layout args]
160 | Return {args, ...} =>
161 seq [str "Return ", Positions.layout args]]
169 | Visited of LabelMeaning.t
176 fn Unvisited => str "Unvisited"
177 | Visited m => LabelMeaning.layout m
178 | Visiting => str "Visiting"
182 val traceApplyInfo = Trace.info "Ssa.Shrink.Prim.apply"
184 fun shrinkFunction {globals: Statement.t vector} =
186 fun use (VarInfo.T {isUsed, var, ...}): Var.t =
189 fun uses (vis: VarInfo.t vector): Var.t vector = Vector.map (vis, use)
190 (* varInfo can't be getSetOnce because of setReplacement. *)
191 val {get = varInfo: Var.t -> VarInfo.t, set = setVarInfo, ...} =
192 Property.getSet (Var.plist,
193 Property.initFun (fn x => VarInfo.new (x, NONE)))
194 (* Property.getSet (Var.plist, Property.initFun VarInfo.new) *)
196 Trace.trace2 ("Ssa.Shrink.setVarInfo",
197 Var.layout, VarInfo.layout, Unit.layout)
199 fun varInfos xs = Vector.map (xs, varInfo)
200 fun simplifyVar (x: Var.t) = use (varInfo x)
202 Trace.trace ("Ssa.Shrink.simplifyVar", Var.layout, Var.layout) simplifyVar
203 fun simplifyVars xs = Vector.map (xs, simplifyVar)
204 fun incVarInfo (x: VarInfo.t): unit =
205 Int.inc (VarInfo.numOccurrences x)
206 fun incVar (x: Var.t): unit = incVarInfo (varInfo x)
207 fun incVars xs = Vector.foreach (xs, incVar)
208 fun numVarOccurrences (x: Var.t): int =
209 ! (VarInfo.numOccurrences (varInfo x))
212 (globals, fn Statement.T {var, exp, ty} =>
216 setVarInfo (x, VarInfo.new (x, SOME ty)))
218 Option.app (var, fn x => VarInfo.setValue (varInfo x, v))
220 ConApp {con, args} =>
221 construct (Value.Con {con = con,
222 args = Vector.map (args, varInfo)})
223 | Const c => construct (Value.Const c)
224 | Select {tuple, offset} =>
225 construct (Value.Select {tuple = varInfo tuple,
227 | Tuple xs => construct (Value.Tuple (Vector.map (xs, varInfo)))
228 | Var y => Option.app (var, fn x => setVarInfo (x, varInfo y))
234 val _ = Function.clear f
235 val {args, blocks, mayInline, name, raises, returns, start, ...} =
237 val _ = Vector.foreach
239 setVarInfo (x, VarInfo.new (x, SOME ty)))
240 (* Index the labels by their defining block in blocks. *)
241 val {get = labelIndex, set = setLabelIndex, ...} =
242 Property.getSetOnce (Label.plist,
243 Property.initRaise ("index", Label.layout))
244 val _ = Vector.foreachi (blocks, fn (i, Block.T {label, ...}) =>
245 setLabelIndex (label, i))
246 val numBlocks = Vector.length blocks
247 (* Do a DFS to compute occurrence counts and set label meanings *)
248 val states = Array.array (numBlocks, State.Unvisited)
249 val inDegree = Array.array (numBlocks, 0)
250 fun addLabelIndex i = Array.inc (inDegree, i)
251 val isHeader = Array.array (numBlocks, false)
252 val numHandlerUses = Array.array (numBlocks, 0)
253 fun layoutLabel (l: Label.t): Layout.t =
257 Layout.record [("label", Label.layout l),
258 ("inDegree", Int.layout (Array.sub (inDegree, i)))]
262 LabelMeaning.Goto {dst, ...} =>
263 addLabelIndex (LabelMeaning.blockIndex dst)
265 fun incLabel (l: Label.t): unit =
266 incLabelMeaning (labelMeaning l)
267 and incLabelMeaning (LabelMeaning.T {aux, blockIndex, ...}): unit =
270 val n = Array.sub (inDegree, i)
271 val _ = Array.update (inDegree, i, 1 + n)
277 and labelMeaning (l: Label.t): LabelMeaning.t =
281 case Array.sub (states, i) of
284 (Array.update (isHeader, i, true)
286 {aux = LabelMeaning.Block,
288 label = Block.label (Vector.sub (blocks, i))}))
291 val _ = Array.update (states, i, State.Visiting)
292 val m = computeMeaning i
293 val _ = Array.update (states, i, State.Visited m)
298 and computeMeaning (i: int): LabelMeaning.t =
300 val Block.T {args, statements, transfer, ...} =
301 Vector.sub (blocks, i)
303 Vector.foreach (args, fn (x, ty) =>
304 setVarInfo (x, VarInfo.new (x, SOME ty)))
307 (statements, fn s => Exp.foreachVar (Statement.exp s, incVar))
308 fun extract (actuals: Var.t vector): Positions.t =
310 val {get: Var.t -> Position.t, set, destroy} =
311 Property.destGetSetOnce
312 (Var.plist, Property.initFun Position.Free)
313 val _ = Vector.foreachi (args, fn (i, (x, _)) =>
314 set (x, Position.Formal i))
315 val ps = Vector.map (actuals, get)
320 LabelMeaning.T {aux = aux,
322 label = Block.label (Vector.sub (blocks, i))}
323 fun normal () = doit LabelMeaning.Block
326 (statements, fn Statement.T {exp, ty, ...} =>
327 Statement.T {exp = exp, ty = ty, var = NONE})
328 fun rr (xs: Var.t vector, make) =
332 val n = Vector.length statements
336 if 0 = Vector.length xs
337 orelse 0 < Vector.length args
338 then doit (make {args = extract xs,
343 val Statement.T {exp, ty, ...} =
344 Vector.sub (statements, i)
348 Statement.T {exp = exp,
358 if Vector.forall (statements, Statement.isProfile)
359 andalso (0 = Vector.length xs
360 orelse 0 < Vector.length args)
361 then doit (make {args = extract xs,
362 canMove = canMove ()})
367 Arith {args, overflow, success, ...} =>
373 if Vector.forall (statements, Statement.isProfile)
374 andalso (case returns of
378 (ts, args, fn (t, (_, t')) =>
379 Type.equals (t, t')))
380 then doit LabelMeaning.Bug
382 | Call {args, return, ...} =>
386 Return.foreachHandler
388 Array.inc (numHandlerUses, labelIndex l))
389 val _ = Return.foreachLabel (return, incLabel)
393 | Case {test, cases, default} =>
396 val _ = Cases.foreach (cases, incLabel)
397 val _ = Option.app (default, incLabel)
399 if Vector.forall (statements, Statement.isProfile)
400 andalso not (Array.sub (isHeader, i))
401 andalso 1 = Vector.length args
402 andalso 1 = numVarOccurrences test
403 andalso Var.equals (test, #1 (Vector.first args))
405 doit (LabelMeaning.Case {canMove = canMove (),
411 | Goto {dst, args = actuals} =>
413 val _ = incVars actuals
414 val m = labelMeaning dst
416 if Vector.exists (statements, not o Statement.isProfile)
417 orelse Array.sub (isHeader, i)
418 then (incLabelMeaning m
421 if Vector.isEmpty statements
423 Vector.equals (args, actuals, fn ((x, _), x') =>
425 andalso 1 = numVarOccurrences x)
426 then m (* It's an eta. *)
429 val ps = extract actuals
431 Vector.fold (args, 0, fn ((x, _), n) =>
432 n + numVarOccurrences x)
434 Vector.fold (ps, 0, fn (p, n) =>
436 Position.Formal _ => n + 1
438 datatype z = datatype LabelMeaning.aux
441 then (incLabelMeaning m
445 fun extract (ps': Positions.t)
450 datatype z = datatype Position.t
454 | Formal i => Vector.sub (ps, i)
456 val canMove' = canMove ()
458 case LabelMeaning.aux m of
460 Goto {canMove = canMove',
468 (ts, args, fn (t, (_, t')) =>
469 Type.equals (t, t')))
471 else Goto {canMove = canMove',
475 Goto {canMove = canMove',
478 | Goto {canMove, dst, args} =>
479 Goto {canMove = canMove' @ canMove,
482 | Raise {args, canMove} =>
483 Raise {args = extract args,
484 canMove = canMove' @ canMove}
485 | Return {args, canMove} =>
486 Return {args = extract args,
487 canMove = canMove' @ canMove}
493 | Raise xs => rr (xs, LabelMeaning.Raise)
494 | Return xs => rr (xs, LabelMeaning.Return)
495 | Runtime {args, return, ...} =>
500 val _ = incLabel start
502 case Array.sub (states, i) of
504 | _ => Error.bug "Ssa.Shrink.indexMeaning: not computed"
506 Trace.trace ("Ssa.Shrink.indexMeaning", Int.layout, LabelMeaning.layout)
508 val labelMeaning = indexMeaning o labelIndex
510 Trace.trace ("Ssa.Shrink.labelMeaning",
511 Label.layout, LabelMeaning.layout)
514 Block.label (Vector.sub (blocks, LabelMeaning.blockIndex m))
516 Block.args (Vector.sub (blocks, labelIndex l))
518 Block.args (Vector.sub (blocks, LabelMeaning.blockIndex m))
521 val {destroy, controlFlowGraph, ...} =
522 Function.layoutDot (f, Var.layout)
525 (concat ["/tmp/", Func.toString (Function.name f),
527 fn out => Layout.outputl (controlFlowGraph, out))
530 val _ = if true then () else save (f, "pre")
541 Label.layout (Block.label (Vector.sub (blocks, i)))),
542 ("inDegree", Int.layout (Array.sub (inDegree, i))),
543 ("state", State.layout (Array.sub (states, i)))]))
544 (Vector.tabulate (numBlocks, fn i => i)),
548 ("Ssa.Shrink.labelMeanings", fn () =>
550 val inDegree' = Array.array (numBlocks, 0)
551 fun bumpIndex i = Array.inc (inDegree', i)
552 fun bumpMeaning m = bumpIndex (LabelMeaning.blockIndex m)
553 val bumpLabel = bumpMeaning o labelMeaning
554 fun doit (LabelMeaning.T {aux, blockIndex, ...}) =
556 datatype z = datatype LabelMeaning.aux
560 Transfer.foreachLabel
561 (Block.transfer (Vector.sub (blocks, blockIndex)),
564 | Case {cases, default, ...} =>
565 (Cases.foreach (cases, bumpLabel)
566 ; Option.app (default, bumpLabel))
567 | Goto {dst, ...} => bumpMeaning dst
573 (states, fn (i, s) =>
574 if Array.sub (inDegree, i) > 0
577 State.Visited m => doit m
580 val _ = bumpMeaning (labelMeaning start)
582 Array.equals (inDegree, inDegree', Int.equals)
591 Label.layout (Block.label (Vector.sub (blocks, i)))),
592 ("inDegree", Int.layout (Array.sub (inDegree, i))),
593 ("inDegree'", Int.layout (Array.sub (inDegree', i))),
594 ("state", State.layout (Array.sub (states, i)))]))
595 (Vector.tabulate (numBlocks, fn i => i)),
601 val isBlock = Array.array (numBlocks, false)
602 (* Functions for maintaining inDegree. *)
605 (Assert.assert ("Ssa.Shrink.addLabelIndex", fn () =>
606 Array.sub (inDegree, i) > 0)
608 val addLabelMeaning = addLabelIndex o LabelMeaning.blockIndex
609 fun layoutLabelMeaning m =
611 [("inDegree", Int.layout (Array.sub
612 (inDegree, LabelMeaning.blockIndex m))),
613 ("meaning", LabelMeaning.layout m)]
614 val traceDeleteLabelMeaning =
615 Trace.trace ("SSa.Shrink.deleteLabelMeaning",
616 layoutLabelMeaning, Unit.layout)
617 fun deleteLabel l = deleteLabelMeaning (labelMeaning l)
618 and deleteLabelMeaning arg: unit =
619 traceDeleteLabelMeaning
620 (fn (m: LabelMeaning.t) =>
622 val i = LabelMeaning.blockIndex m
623 val n = Array.sub (inDegree, i) - 1
624 val _ = Array.update (inDegree, i, n)
625 val _ = Assert.assert ("Ssa.Shrink.deleteLabelMeaning", fn () => n >= 0)
627 if n = 0 (* andalso not (Array.sub (isBlock, i)) *)
630 datatype z = datatype LabelMeaning.aux
632 case LabelMeaning.aux m of
635 val t = Block.transfer (Vector.sub (blocks, i))
636 val _ = Transfer.foreachLabel (t, deleteLabel)
639 Transfer.Call {return, ...} =>
640 Return.foreachHandler
642 Array.dec (numHandlerUses,
643 (LabelMeaning.blockIndex
650 | Case {cases, default, ...} =>
651 (Cases.foreach (cases, deleteLabel)
652 ; Option.app (default, deleteLabel))
653 | Goto {dst, ...} => deleteLabelMeaning dst
659 fun primApp (prim: Type.t Prim.t, args: VarInfo.t vector)
660 : (Type.t, VarInfo.t) Prim.ApplyResult.t =
666 VarInfo.T {value = ref (SOME v), ...} =>
668 Value.Con {con, args} =>
669 if Vector.isEmpty args
670 then Prim.ApplyArg.Con {con = con,
672 else Prim.ApplyArg.Var vi
673 | Value.Const c => Prim.ApplyArg.Const c
674 | _ => Prim.ApplyArg.Var vi)
675 | _ => Prim.ApplyArg.Var vi)
683 seq [Prim.layout p, str " ",
684 List.layout (Prim.ApplyArg.layout
685 (Var.layout o VarInfo.var)) args]
687 Prim.ApplyResult.layout (Var.layout o VarInfo.var))
689 (prim, Vector.toList args', VarInfo.equals)
691 (* Another DFS, this time accumulating the new blocks. *)
692 val traceForceMeaningBlock =
693 Trace.trace ("Ssa.Shrink.forceMeaningBlock",
694 layoutLabelMeaning, Unit.layout)
695 val traceSimplifyBlock =
696 Trace.trace2 ("Ssa.Shrink.simplifyBlock",
697 List.layout Statement.layout,
698 layoutLabel o Block.label,
699 Layout.tuple2 (List.layout Statement.layout,
701 val traceGotoMeaning =
703 ("Ssa.Shrink.gotoMeaning",
704 List.layout Statement.layout,
706 Vector.layout VarInfo.layout,
707 Layout.tuple2 (List.layout Statement.layout, Transfer.layout))
708 val traceEvalStatement =
710 ("Ssa.Shrink.evalStatement",
712 Layout.ignore: (Statement.t list -> Statement.t list) -> Layout.t)
713 val traceSimplifyTransfer =
714 Trace.trace ("Ssa.Shrink.simplifyTransfer",
716 Layout.tuple2 (List.layout Statement.layout,
718 val traceSimplifyCase =
720 ("Ssa.Shrink2.simplifyCase",
721 fn {canMove, cases, default, test, ...} =>
722 Layout.record [("canMove", List.layout Statement.layout canMove),
723 ("cantSimplify", Layout.str "fn () => ..."),
724 ("gone", Layout.str "fn () => ..."),
725 ("test", VarInfo.layout test),
727 (Transfer.layout o Transfer.Case)
730 test = VarInfo.var test})],
731 Layout.tuple2 (List.layout Statement.layout, Transfer.layout))
732 val newBlocks = ref []
733 fun simplifyLabel l =
735 val m = labelMeaning l
736 val _ = forceMeaningBlock m
740 and forceMeaningBlock arg =
741 traceForceMeaningBlock
742 (fn (LabelMeaning.T {aux, blockIndex = i, ...}) =>
743 if Array.sub (isBlock, i)
747 val _ = Array.update (isBlock, i, true)
748 val block as Block.T {label, args, ...} =
749 Vector.sub (blocks, i)
750 fun extract (p: Position.t): VarInfo.t =
752 Position.Formal n => #1 (Vector.sub (args, n))
753 | Position.Free x => x)
754 val (statements, transfer) =
756 fun rr ({args, canMove}, make) =
758 make (Vector.map (args, use o extract)))
759 datatype z = datatype LabelMeaning.aux
762 Block => simplifyBlock ([], block)
763 | Bug => ([], Transfer.Bug)
764 | Case _ => simplifyBlock ([], block)
765 | Goto {canMove, dst, args} =>
769 Vector.map (args, extract))
770 | Raise z => rr (z, Transfer.Raise)
771 | Return z => rr (z, Transfer.Return)
776 Block.T {label = label,
778 statements = Vector.fromList statements,
779 transfer = transfer})
783 and simplifyBlock arg : Statement.t list * Transfer.t =
785 (fn (canMoveIn, Block.T {statements, transfer, ...}) =>
787 val f = evalStatements statements
788 val (ss, transfer) = simplifyTransfer transfer
790 (canMoveIn @ (f ss), transfer)
792 and evalStatements (ss: Statement.t vector)
793 : Statement.t list -> Statement.t list =
795 val fs = Vector.map (ss, evalStatement)
797 fn ss => Vector.foldr (fs, ss, fn (f, ss) => f ss)
799 and simplifyTransfer arg : Statement.t list * Transfer.t =
800 traceSimplifyTransfer
801 (fn (t: Transfer.t) =>
803 Arith {prim, args, overflow, success, ty} =>
805 val args = varInfos args
807 case primApp (prim, args) of
808 Prim.ApplyResult.Const c =>
810 val _ = deleteLabel overflow
811 val x = Var.newNoname ()
812 val isUsed = ref false
814 VarInfo.T {isUsed = isUsed,
815 numOccurrences = ref 0,
817 value = ref (SOME (Value.Const c)),
819 val (ss, t) = goto (success, Vector.new1 vi)
822 then Statement.T {var = SOME x,
830 | Prim.ApplyResult.Var x =>
832 val _ = deleteLabel overflow
834 goto (success, Vector.new1 x)
836 | Prim.ApplyResult.Overflow =>
838 val _ = deleteLabel success
840 goto (overflow, Vector.new0 ())
842 | Prim.ApplyResult.Apply (prim, args) =>
843 let val args = Vector.fromList args
845 ([], Arith {prim = prim,
847 overflow = simplifyLabel overflow,
848 success = simplifyLabel success,
852 ([], Arith {prim = prim,
854 overflow = simplifyLabel overflow,
855 success = simplifyLabel success,
859 | Call {func, args, return} =>
861 val (statements, return) =
863 Return.NonTail {cont, handler} =>
865 fun isEta (m: LabelMeaning.t,
866 ps: Position.t vector): bool =
867 Vector.length ps = Vector.length (meaningArgs m)
871 fn (i, Position.Formal i') => i = i'
873 val m = labelMeaning cont
876 val _ = forceMeaningBlock m
881 val m = labelMeaning l
882 val _ = forceMeaningBlock m
888 Return.NonTail {cont = meaningLabel m,
891 fun tail statements =
892 (deleteLabelMeaning m
893 ; (statements, Return.Tail))
894 fun cont handlerEta =
895 case LabelMeaning.aux m of
899 | SOME canMove => tail canMove)
900 | LabelMeaning.Return {args, canMove} =>
908 Handler.Caller => cont NONE
909 | Handler.Dead => cont NONE
910 | Handler.Handle l =>
912 val m = labelMeaning l
914 case LabelMeaning.aux m of
915 LabelMeaning.Bug => cont NONE
916 | LabelMeaning.Raise {args, canMove} =>
918 then cont (SOME canMove)
927 args = simplifyVars args,
930 | Case {test, cases, default} =>
932 val test = varInfo test
933 fun cantSimplify () =
935 Case {test = use test,
936 cases = Cases.map (cases, simplifyLabel),
937 default = Option.map (default, simplifyLabel)})
941 cantSimplify = cantSimplify,
944 gone = fn () => (Cases.foreach (cases, deleteLabel)
945 ; Option.app (default, deleteLabel)),
948 | Goto {dst, args} => goto (dst, varInfos args)
949 | Raise xs => ([], Raise (simplifyVars xs))
950 | Return xs => ([], Return (simplifyVars xs))
951 | Runtime {prim, args, return} =>
952 ([], Runtime {prim = prim,
953 args = simplifyVars args,
954 return = simplifyLabel return})
956 and simplifyCase arg : Statement.t list * Transfer.t =
958 (fn {canMove, cantSimplify,
959 cases, default, gone, test: VarInfo.t} =>
961 (* tryToEliminate makes sure that the destination meaning
962 * hasn't already been simplified. If it has, then we can't
965 fun tryToEliminate m =
967 val i = LabelMeaning.blockIndex m
969 if Array.sub (inDegree, i) = 0
973 val _ = addLabelIndex i
976 gotoMeaning (canMove, m, Vector.new0 ())
980 if Cases.isEmpty cases
981 then (case default of
982 NONE => (canMove, Bug)
983 | SOME l => tryToEliminate (labelMeaning l))
986 val l = Cases.hd cases
987 fun isOk (l': Label.t): bool = Label.equals (l, l')
989 if Vector.isEmpty (labelArgs l)
990 andalso Cases.forall (cases, isOk)
991 andalso (case default of
995 (* All cases the same -- eliminate the case. *)
996 tryToEliminate (labelMeaning l)
999 fun findCase (cases, isCon, args) =
1001 val n = Vector.length cases
1002 fun doit (l, args) =
1004 val m = labelMeaning l
1005 val _ = addLabelMeaning m
1008 gotoMeaning (canMove, m, args)
1014 NONE => (gone (); ([], Bug))
1015 | SOME l => doit (l, Vector.new0 ()))
1018 val (con, l) = Vector.sub (cases, k)
1028 case (VarInfo.value test, cases) of
1029 (SOME (Value.Const c), _) =>
1031 (Cases.Word (_, cs), Const.Word w) =>
1033 fn w' => WordX.equals (w, w'),
1036 Error.bug "Ssa.Shrink.simplifyCases: strange constant")
1037 | (SOME (Value.Con {con, args}), Cases.Con cases) =>
1039 fn c => Con.equals (con, c),
1041 | _ => cantSimplify ()
1045 and goto (dst: Label.t, args: VarInfo.t vector)
1046 : Statement.t list * Transfer.t =
1047 gotoMeaning ([], labelMeaning dst, args)
1048 and gotoMeaning arg : Statement.t list * Transfer.t =
1051 m as LabelMeaning.T {aux, blockIndex = i, ...},
1052 args: VarInfo.t vector) =>
1054 val n = Array.sub (inDegree, i)
1055 val _ = Assert.assert ("Ssa.Shrink.gotoMeaning", fn () => n >= 1)
1060 val _ = Array.update (inDegree, i, 0)
1061 val b = Vector.sub (blocks, i)
1064 (Block.args b, args, fn ((x, _), vi) =>
1067 simplifyBlock (canMoveIn, b)
1071 val _ = forceMeaningBlock m
1074 Goto {dst = Block.label (Vector.sub (blocks, i)),
1079 Position.Formal n => Vector.sub (args, n)
1080 | Position.Free x => varInfo x
1081 fun rr ({args, canMove}, make) =
1082 (canMoveIn @ canMove,
1083 make (Vector.map (args, use o extract)))
1084 datatype z = datatype LabelMeaning.aux
1088 | Bug => ((*canMoveIn*)[], Transfer.Bug)
1089 | Case {canMove, cases, default} =>
1090 simplifyCase {canMove = canMoveIn @ canMove,
1091 cantSimplify = normal,
1094 gone = fn () => deleteLabelMeaning m,
1095 test = Vector.first args}
1096 | Goto {canMove, dst, args} =>
1097 if Array.sub (isHeader, i)
1098 orelse Array.sub (isBlock, i)
1103 val _ = Array.update (inDegree, i, n')
1106 then addLabelMeaning dst
1109 gotoMeaning (canMoveIn @ canMove,
1111 Vector.map (args, extract))
1113 | Raise z => rr (z, Transfer.Raise)
1114 | Return z => rr (z, Transfer.Return)
1116 and evalStatement arg : Statement.t list -> Statement.t list =
1118 (fn (Statement.T {var, ty, exp}) =>
1122 setVarInfo (x, VarInfo.new (x, SOME ty)))
1124 fun doit {makeExp: unit -> Exp.t,
1126 value: Value.t option} =
1129 Statement.T {var = var,
1136 then (fn ss => make NONE :: ss)
1140 val VarInfo.T {isUsed, value = r, ...} = varInfo x
1145 then make (SOME x) :: ss
1147 then make NONE :: ss
1152 (Option.app (var, fn x => setVarInfo (x, vi))
1154 fun construct (v: Value.t, makeExp) =
1155 doit {makeExp = makeExp,
1160 ConApp {con, args} =>
1162 val args = varInfos args
1164 construct (Value.Con {con = con, args = args},
1165 fn () => ConApp {con = con,
1168 | Const c => construct (Value.Const c, fn () => exp)
1169 | PrimApp {prim, targs, args} =>
1171 val args = varInfos args
1172 fun apply {prim, targs, args} =
1173 doit {sideEffect = Prim.maySideEffect prim,
1174 makeExp = fn () => PrimApp {prim = prim,
1178 datatype z = datatype Prim.ApplyResult.t
1180 case primApp (prim, args) of
1181 Apply (prim, args) =>
1182 apply {prim = prim, targs = Vector.new0 (),
1183 args = Vector.fromList args}
1186 val con = Con.fromBool b
1188 construct (Value.Con {con = con,
1189 args = Vector.new0 ()},
1192 args = Vector.new0 ()})
1194 | Const c => construct (Value.Const c,
1195 fn () => Exp.Const c)
1196 | Var vi => setVar vi
1197 | _ => apply {prim = prim,
1201 | Select {tuple, offset} =>
1203 val tuple as VarInfo.T {value, ...} = varInfo tuple
1206 SOME (Value.Tuple vs) =>
1207 setVar (Vector.sub (vs, offset))
1209 construct (Value.Select {tuple = tuple,
1211 fn () => Select {tuple = use tuple,
1216 val xs = varInfos xs
1222 fn (i, VarInfo.T {value, ...}, tuple') =>
1224 SOME (Value.Select {offset, tuple}) =>
1228 (case VarInfo.ty tuple of
1230 (case Type.deTupleOpt ty of
1232 if Vector.length xs =
1236 | NONE => escape NONE)
1237 | NONE => escape NONE)
1239 if VarInfo.equals (tuple'', tuple)
1243 | _ => escape NONE)) of
1244 SOME tuple => setVar tuple
1245 | NONE => construct (Value.Tuple xs,
1246 fn () => Tuple (uses xs))
1248 | Var x => setVar (varInfo x)
1249 | _ => doit {makeExp = fn () => exp,
1253 val start = labelMeaning start
1254 val _ = forceMeaningBlock start
1256 Function.new {args = args,
1257 blocks = Vector.fromList (!newBlocks),
1258 mayInline = mayInline,
1262 start = meaningLabel start}
1263 val _ = if true then () else save (f, "post")
1264 val _ = Function.clear f
1270 fun eliminateUselessProfile (f: Function.t): Function.t =
1271 if !Control.profile = Control.ProfileNone
1275 fun eliminateInBlock (b as Block.T {args, label, statements, transfer})
1277 if not (Vector.exists (statements, Statement.isProfile))
1281 datatype z = datatype Exp.t
1282 datatype z = datatype ProfileExp.t
1285 (statements, [], fn (s as Statement.T {exp, ...}, stack) =>
1287 Profile (Leave si) =>
1289 Statement.T {exp = Profile (Enter si'), ...}
1291 if SourceInfo.equals (si, si')
1293 else Error.bug "Ssa.Shrink.eliminateUselessProfile: mismatched Leave"
1296 val statements = Vector.fromListRev stack
1298 Block.T {args = args,
1300 statements = statements,
1301 transfer = transfer}
1303 val {args, blocks, mayInline, name, raises, returns, start} =
1305 val blocks = Vector.map (blocks, eliminateInBlock)
1307 Function.new {args = args,
1309 mayInline = mayInline,
1316 val traceShrinkFunction =
1317 Trace.trace ("Ssa.Shrink.shrinkFunction", Function.layout, Function.layout)
1319 val shrinkFunction =
1322 val s = shrinkFunction g
1324 fn f => traceShrinkFunction s (eliminateUselessProfile f)
1327 fun shrink (Program.T {datatypes, globals, functions, main})
1329 val s = shrinkFunction {globals = globals}
1331 Program.T {datatypes = datatypes,
1333 functions = List.revMap (functions, s),