1 (* Copyright (C) 2009 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 RemoveUnused2 (S: SSA2_TRANSFORM_STRUCTS): SSA2_TRANSFORM =
14 open Exp Statement Transfer
18 structure L = TwoPointLattice (val bottom = "unused"
23 val whenUsed = addHandler
28 structure L = TwoPointLattice (val bottom = "not coned"
33 val whenConed = addHandler
38 structure L = TwoPointLattice (val bottom = "not deconed"
47 structure L = TwoPointLattice (val bottom = "does not return"
48 val top = "may return")
52 val whenReturns = addHandler
57 structure L = TwoPointLattice (val bottom = "does not raise"
58 val top = "may raise")
62 val whenRaises = addHandler
68 datatype t = T of {ty: Type.t,
71 fun layout (T {used, ...}) = Used.layout used
74 fun make f (T r) = f r
80 fun new (ty : Type.t): t = T {ty = ty,
83 val use = Used.use o used
84 val isUsed = Used.isUsed o used
85 fun whenUsed (vi, th) = Used.whenUsed (used vi, th)
90 datatype t = T of {args: (VarInfo.t * Type.t) Prod.t,
93 dummy: {con: Con.t, args: Type.t Prod.t,
94 ty: Type.t, exp: Exp.t},
97 fun layout (T {args, coned, deconed, used, ...}) =
98 Layout.record [("args", Prod.layout (args, VarInfo.layout o #1)),
99 ("coned", Coned.layout coned),
100 ("deconed", Deconed.layout deconed),
101 ("used", Used.layout used)]
104 fun make f (T r) = f r
106 val args = make #args
107 val coned = make #coned
108 val deconed = make #deconed
109 val dummy = make #dummy
110 val used = make #used
113 val con = Coned.con o coned
114 val isConed = Coned.isConed o coned
115 fun whenConed (ci, th) = Coned.whenConed (coned ci, th)
117 val decon = Deconed.decon o deconed
118 val isDeconed = Deconed.isDeconed o deconed
120 val use = Used.use o used
121 val isUsed = Used.isUsed o used
122 fun whenUsed (vi, th) = Used.whenUsed (used vi, th)
124 fun new {args: Type.t Prod.t,
125 dummy: {con: Con.t, args: Type.t Prod.t,
126 ty: Type.t, exp: Exp.t}}: t =
127 T {args = Prod.map (args, fn ty => (VarInfo.new ty, ty)),
128 coned = Coned.new (),
129 deconed = Deconed.new (),
134 structure TyconInfo =
136 datatype t = T of {cons: Con.t vector,
137 dummy: {con: Con.t, args: Type.t Prod.t},
141 fun layout (T {used, ...}) =
142 Layout.record [("used", Used.layout used)]
145 fun make f (T r) = f r
146 fun make' f = (make f, ! o (make f))
148 val cons = make #cons
149 val dummy = make #dummy
150 val (numCons', numCons) = make' #numCons
151 val used = make #used
154 fun new {cons: Con.t vector,
155 dummy: {con: Con.t, args: Type.t Prod.t}}: t =
164 datatype t = T of {deconed: bool ref,
165 simplify: Type.t option ref,
169 fun make f (T r) = f r
170 fun make' f = (make f, ! o (make f))
172 val (deconed', _) = make' #deconed
173 val (simplify', _) = make' #simplify
174 val (used', _) = make' #used
177 fun new (): t = T {deconed = ref false,
184 datatype t = T of {args: (VarInfo.t * Type.t) vector,
185 bugLabel: Label.t option ref,
186 mayRaise: MayRaise.t,
187 mayReturn: MayReturn.t,
188 raiseLabel: Label.t option ref,
189 raises: (VarInfo.t * Type.t) vector option,
190 returnLabel: Label.t option ref,
191 returns: (VarInfo.t * Type.t) vector option,
193 wrappers: Block.t list ref}
200 Layout.record [("args", Vector.layout
201 (Layout.tuple2 (VarInfo.layout, Type.layout))
203 ("mayRaise", MayRaise.layout mayRaise),
204 ("mayReturn", MayReturn.layout mayReturn),
205 ("raises", Option.layout
207 (Layout.tuple2 (VarInfo.layout, Type.layout)))
209 ("returns", Option.layout
211 (Layout.tuple2 (VarInfo.layout, Type.layout)))
213 ("used", Used.layout used)]
216 fun make f (T r) = f r
217 fun make' f = (make f, ! o (make f))
219 val args = make #args
220 val mayRaise' = make #mayRaise
221 val mayReturn' = make #mayReturn
222 val raiseLabel = make #raiseLabel
223 val raises = make #raises
224 val returnLabel = make #returnLabel
225 val returns = make #returns
226 val used = make #used
227 val (wrappers', wrappers) = make' #wrappers
230 val raisee = MayRaise.raisee o mayRaise'
231 val mayRaise = MayRaise.mayRaise o mayRaise'
232 fun whenRaises (fi, th) = MayRaise.whenRaises (mayRaise' fi, th)
233 fun flowRaises (fi, fi') = MayRaise.<= (mayRaise' fi, mayRaise' fi')
235 val return = MayReturn.return o mayReturn'
236 fun whenReturns (fi, th) = MayReturn.whenReturns (mayReturn' fi, th)
237 val mayReturn = MayReturn.mayReturn o mayReturn'
238 fun flowReturns (fi, fi') = MayReturn.<= (mayReturn' fi, mayReturn' fi')
240 val use = Used.use o used
241 val isUsed = Used.isUsed o used
242 fun whenUsed (fi, th) = Used.whenUsed (used fi, th)
244 fun new {args: (VarInfo.t * Type.t) vector,
245 raises: (VarInfo.t * Type.t) vector option,
246 returns: (VarInfo.t * Type.t) vector option}: t =
249 mayRaise = MayRaise.new (),
250 mayReturn = MayReturn.new (),
251 raiseLabel = ref NONE,
253 returnLabel = ref NONE,
259 structure LabelInfo =
261 datatype t = T of {args: (VarInfo.t * Type.t) vector,
264 wrappers: (Type.t vector * Label.t) list ref}
266 fun layout (T {args, used, ...}) =
267 Layout.record [("args", Vector.layout (VarInfo.layout o #1) args),
268 ("used", Used.layout used)]
270 fun new {args: (VarInfo.t * Type.t) vector, func: FuncInfo.t}: t =
277 fun make f (T r) = f r
278 fun make' f = (make f, ! o (make f))
280 val args = make #args
281 val func = make #func
282 val used = make #used
283 val (wrappers', wrappers) = make' #wrappers
286 val use = Used.use o used
287 val isUsed = Used.isUsed o used
288 fun whenUsed (li, th) = Used.whenUsed (used li, th)
292 fun transform2 (Program.T {datatypes, globals, functions, main}) =
294 val {get = conInfo: Con.t -> ConInfo.t,
295 set = setConInfo, ...} =
298 Property.initRaise ("RemoveUnused2.conInfo", Con.layout))
299 fun newConInfo (con, args, dummy) =
300 setConInfo (con, ConInfo.new {args = args, dummy = dummy})
302 val {get = tyconInfo: Tycon.t -> TyconInfo.t,
303 set = setTyconInfo, ...} =
306 Property.initRaise ("RemoveUnused2.tyconInfo", Tycon.layout))
307 fun newTyconInfo (tycon, cons, dummy) =
308 setTyconInfo (tycon, TyconInfo.new {cons = cons, dummy = dummy})
310 val {get = typeInfo: Type.t -> TypeInfo.t,
314 Property.initFun (fn _ => TypeInfo.new ()))
316 val {get = varInfo: Var.t -> VarInfo.t,
317 set = setVarInfo, ...} =
320 Property.initRaise ("RemoveUnused2.varInfo", Var.layout))
321 fun newVarInfo (var, ty) =
322 setVarInfo (var, VarInfo.new ty)
324 val {get = labelInfo: Label.t -> LabelInfo.t,
325 set = setLabelInfo, ...} =
328 Property.initRaise ("RemoveUnused2.labelInfo", Label.layout))
330 val {get = funcInfo: Func.t -> FuncInfo.t,
331 set = setFuncInfo, ...} =
334 Property.initRaise ("RemoveUnused2.funcInfo", Func.layout))
337 val usedCon = ConInfo.used o conInfo
338 val useCon = Used.use o usedCon
339 fun visitCon (con: Con.t) = useCon con
340 val whenUsedCon = fn (con, th) => ConInfo.whenUsed (conInfo con, th)
342 val usedTycon = TyconInfo.used o tyconInfo
343 val useTycon = Used.use o usedTycon
344 fun visitTycon (tycon: Tycon.t) = useTycon tycon
345 val isUsedTycon = Used.isUsed o usedTycon
347 fun visitType (ty: Type.t) =
350 val used = TypeInfo.used' ti
355 val () = used := true
356 datatype z = datatype Type.dest
357 datatype z = datatype ObjectCon.t
360 Datatype tycon => visitTycon tycon
361 | Object {args, con} =>
363 val () = Prod.foreach (args, visitType)
366 Con con => visitCon con
372 | Weak ty => visitType ty
378 val visitTypeTh = fn ty => fn () => visitType ty
380 val tyVar = VarInfo.ty o varInfo
381 val usedVar = VarInfo.used o varInfo
382 val useVar = Used.use o usedVar
383 val isUsedVar = Used.isUsed o usedVar
384 val whenUsedVar = fn (var, th) => VarInfo.whenUsed (varInfo var, th)
385 fun flowVarInfoTyVarInfoTy ((vi, _), (vi', _)) =
386 Used.<= (VarInfo.used vi, VarInfo.used vi')
387 fun flowVarInfoTysVarInfoTys (xs, ys) =
388 Vector.foreach2 (xs, ys, flowVarInfoTyVarInfoTy)
389 fun flowVarInfoTyVar ((vi, _), x) =
390 Used.<= (VarInfo.used vi, usedVar x)
391 fun flowVarInfoTysVars (xs, ys) =
392 Vector.foreach2 (xs, ys, flowVarInfoTyVar)
394 val newVarInfo = fn (var, ty) =>
395 (newVarInfo (var, ty)
396 ; whenUsedVar (var, visitTypeTh ty))
398 val visitLabelInfo = LabelInfo.use
399 val visitLabelInfoTh = fn li => fn () => visitLabelInfo li
400 val visitLabel = visitLabelInfo o labelInfo
401 val visitLabelTh = fn l => fn () => visitLabel l
402 val visitFuncInfo = FuncInfo.use
403 val visitFunc = visitFuncInfo o funcInfo
405 fun visitVar (x: Var.t) = useVar x
406 fun visitVars (xs: Var.t Vector.t) = Vector.foreach (xs, visitVar)
407 fun visitExp (e: Exp.t) =
410 | Inject {sum, variant} =>
413 | Object {args, con} =>
417 NONE => visitVars args
421 val () = ConInfo.con ci
424 (Prod.dest (ConInfo.args ci), #elt)
425 val () = flowVarInfoTysVars (ciArgs, args)
432 | PrimApp {prim, args, ...} =>
434 val () = visitVars args
435 datatype z = datatype Type.dest
436 datatype z = datatype ObjectCon.t
437 fun deconType (ty: Type.t) =
440 val deconed = TypeInfo.deconed' ti
445 val () = deconed := true
450 (TyconInfo.cons (tyconInfo t),
451 fn con => deconCon con)
452 | Object {args, con} =>
456 (Prod.dest args, fn {elt, isMutable} =>
462 Con con => deconCon con
463 | Tuple => default ()
464 | Vector => default ()
476 val () = ConInfo.decon ci
479 (Prod.dest (ConInfo.args ci), fn {elt = (x, t), isMutable} =>
481 ; if isMutable then () else deconType t))
486 case Prim.name prim of
487 Prim.Name.MLton_eq =>
488 (* MLton_eq may be used on datatypes used as enums. *)
489 deconType (tyVar (Vector.first args))
490 | Prim.Name.MLton_equal =>
491 (* MLton_equal will be expanded by poly-equal into uses
492 * of constructors as patterns.
494 deconType (tyVar (Vector.first args))
495 | Prim.Name.MLton_hash =>
496 (* MLton_hash will be expanded by poly-hash into uses
497 * of constructors as patterns.
499 deconType (tyVar (Vector.first args))
501 | Prim.Name.MLton_size =>
502 deconType (tyVar (Vector.first args))
508 | Select {base, offset} =>
510 datatype z = datatype Base.t
511 datatype z = datatype ObjectCon.t
516 val () = visitVar base
518 case Type.dest (tyVar base) of
519 Type.Object {con, ...} =>
524 val ciArgs = ConInfo.args ci
525 val {elt = (vi, _), ...} =
526 Prod.sub (ciArgs, offset)
528 val () = ConInfo.decon ci
529 val () = VarInfo.use vi
534 | Vector => Error.bug "RemoveUnused2.visitExp: Select:non-Con|Tuple")
535 | _ => Error.bug "RemovUnused2.visitExp: Select:non-Object"
539 | VectorSub {index, vector} =>
543 | Var x => visitVar x
544 val visitExpTh = fn e => fn () => visitExp e
545 fun maybeVisitVarExp (var, exp) =
546 Option.app (var, fn var =>
547 VarInfo.whenUsed (varInfo var, visitExpTh exp))
548 fun visitStatement s =
550 Bind {exp, ty, var} =>
551 (Option.app (var, fn var => newVarInfo (var, ty))
552 ; if Exp.maySideEffect exp
555 else maybeVisitVarExp (var, exp))
557 | Update {base, offset, value} =>
559 datatype z = datatype Base.t
560 datatype z = datatype ObjectCon.t
564 (case Type.dest (tyVar base) of
565 Type.Object {con, ...} =>
570 val ciArgs = ConInfo.args ci
571 val {elt = (vi, _), ...} =
572 Prod.sub (ciArgs, offset)
583 | Vector => Error.bug "RemoveUnused2.visitStatement: Update:non-Con|Tuple")
584 | _ => Error.bug "RemoveUnused2.visitStatement: Update:non-Object")
585 | VectorSub {index, vector} =>
590 fun visitTransfer (t: Transfer.t, fi: FuncInfo.t) =
592 Arith {args, overflow, success, ty, ...} =>
594 ; visitLabel overflow
598 | Call {args, func, return} =>
603 val (cont, handler) =
605 Return.Dead => (None, None)
606 | Return.NonTail {cont, handler} =>
609 Handler.Caller => Caller
610 | Handler.Dead => None
611 | Handler.Handle h => Some h)
612 | Return.Tail => (Caller, Caller)
613 val fi' = funcInfo func
615 val () = flowVarInfoTysVars (FuncInfo.args fi', args)
622 case (FuncInfo.returns fi,
623 FuncInfo.returns fi') of
624 (SOME xts, SOME xts') =>
625 flowVarInfoTysVarInfoTys (xts, xts')
627 val () = FuncInfo.flowReturns (fi', fi)
636 (FuncInfo.returns fi', fn xts =>
637 flowVarInfoTysVarInfoTys
638 (LabelInfo.args li, xts))
641 (fi', visitLabelInfoTh li)
651 case (FuncInfo.raises fi,
652 FuncInfo.raises fi') of
653 (SOME xts, SOME xts') =>
654 flowVarInfoTysVarInfoTys (xts, xts')
656 val () = FuncInfo.flowRaises (fi', fi)
665 (FuncInfo.raises fi', fn xts =>
666 flowVarInfoTysVarInfoTys
667 (LabelInfo.args li, xts))
669 FuncInfo.whenRaises (fi', visitLabelInfoTh li)
673 val () = visitFuncInfo fi'
677 | Case {test, cases, default} =>
679 val () = visitVar test
682 Cases.Word (_, cs) =>
683 (Vector.foreach (cs, visitLabel o #2)
684 ; Option.app (default, visitLabel))
686 if Vector.isEmpty cases
687 then Option.app (default, visitLabel)
691 (cases, fn (con, l) =>
694 val () = ConInfo.decon ci
702 case Type.dest (tyVar test) of
703 Type.Datatype tycon => tycon
704 | _ => Error.bug "RemoveUnused2.visitTransfer: Case:non-Datatype"
705 val cons = TyconInfo.cons (tyconInfo tycon)
718 (conInfo con, visitLabelTh l))
721 | Goto {dst, args} =>
723 val li = labelInfo dst
724 val () = flowVarInfoTysVars (LabelInfo.args li, args)
725 val () = visitLabelInfo li
731 ; flowVarInfoTysVars (valOf (FuncInfo.raises fi), xs))
734 ; flowVarInfoTysVars (valOf (FuncInfo.returns fi), xs))
735 | Runtime {args, return, ...} =>
738 fun visitBlock (Block.T {statements, transfer, ...}, fi: FuncInfo.t) =
739 (Vector.foreach (statements, visitStatement)
740 ; visitTransfer (transfer, fi))
741 val visitBlockTh = fn (b, fi) => fn () => visitBlock (b, fi)
742 (* Visit all reachable expressions. *)
745 (datatypes, fn Datatype.T {tycon, cons} =>
747 val dummyCon = Con.newString "dummy"
748 val dummyArgs = Prod.empty ()
749 val dummy = {con = dummyCon, args = dummyArgs}
752 (tycon, Vector.map (cons, fn {con, ...} => con), dummy)
753 val dummyTy = Type.conApp (dummyCon, dummyArgs)
754 val dummyExp = Object {args = Vector.new0 (),
756 val dummy = {con = dummyCon, args = dummyArgs,
757 ty = dummyTy, exp = dummyExp}
760 (cons, fn {con, args} =>
761 (newConInfo (con, args, dummy)
762 ; whenUsedCon (con, fn () => useTycon tycon)))
782 Vector.foreach (globals, visitStatement)
785 (functions, fn function =>
787 val {name, args, raises, returns, start, blocks, ...} =
788 Function.dest function
789 val () = Vector.foreach (args, newVarInfo)
792 Vector.map (vts, fn (x, t) => (varInfo x, t))
794 Vector.map (ts, fn t => (VarInfo.new t, t))
796 Option.map (ts, doitTys)
800 {args = doitVarTys args,
801 raises = doitTys' raises,
802 returns = doitTys' returns}
804 val () = setFuncInfo (name, fi)
805 val () = FuncInfo.whenUsed (fi, visitLabelTh start)
808 (blocks, fn block as Block.T {label, args, ...} =>
810 val () = Vector.foreach (args, newVarInfo)
813 Vector.map (vts, fn (x, t) => (varInfo x, t))
817 {args = doitVarTys args,
820 val () = setLabelInfo (label, li)
821 val () = LabelInfo.whenUsed (li, visitBlockTh (block, fi))
828 val () = visitFunc main
837 (datatypes, fn Datatype.T {tycon, cons} =>
838 display (seq [Tycon.layout tycon,
840 TyconInfo.layout (tyconInfo tycon),
846 ConInfo.layout (conInfo con)])
852 val {name, blocks, ...} = Function.dest f
854 display (seq [Func.layout name,
856 FuncInfo.layout (funcInfo name)]);
858 (blocks, fn Block.T {label, ...} =>
859 display (seq [Label.layout label,
861 LabelInfo.layout (labelInfo label)]));
866 (* Analysis is done, Now build the resulting program. *)
867 fun getWrapperLabel (l: Label.t,
868 args: (VarInfo.t * Type.t) vector) =
872 if Vector.forall2 (args, LabelInfo.args li, fn ((x, _), (y, _)) =>
873 VarInfo.isUsed x = VarInfo.isUsed y)
877 Vector.keepAllMap (args, fn (x, ty) =>
883 (LabelInfo.wrappers li, fn (args', _) =>
884 Vector.length args' = Vector.length tys
886 Vector.forall2 (args', tys, fn (ty', ty) =>
887 Type.equals (ty', ty))) of
890 val liArgs = LabelInfo.args li
891 val l' = Label.newNoname ()
892 val (args', args'') =
895 (args, liArgs, fn ((x, ty), (y, _)) =>
897 val z = Var.newNoname ()
900 then SOME (z, ty) else NONE,
902 then SOME z else NONE)
905 Vector.keepAllMap (args', fn x => x)
906 val (_, tys') = Vector.unzip args'
908 Vector.keepAllMap (args'', fn x => x)
912 statements = Vector.new0 (),
913 transfer = Goto {dst = l,
916 List.push (LabelInfo.wrappers' li,
919 List.push (FuncInfo.wrappers' (LabelInfo.func li),
927 val getContWrapperLabel = getWrapperLabel
928 val getHandlerWrapperLabel = getWrapperLabel
929 fun getOriginalWrapperLabel l =
931 (l, Vector.map (LabelInfo.args (labelInfo l), fn (_, t) =>
933 val x = VarInfo.new t
934 val () = VarInfo.use x
938 val getArithOverflowWrapperLabel = getOriginalWrapperLabel
939 val getArithSuccessWrapperLabel = getOriginalWrapperLabel
940 val getRuntimeWrapperLabel = getOriginalWrapperLabel
941 fun getBugFunc (fi: FuncInfo.t): Label.t =
942 (* Can't share the Bug block across different places because the
943 * profile sourceInfo stack might be different.
946 val l = Label.newNoname ()
947 val block = Block.T {label = l,
948 args = Vector.new0 (),
949 statements = Vector.new0 (),
951 val () = List.push (FuncInfo.wrappers' fi, block)
955 fun getReturnFunc (fi: FuncInfo.t): Label.t =
957 val r = FuncInfo.returnLabel fi
962 val l = Label.newNoname ()
963 val returns = valOf (FuncInfo.returns fi)
966 (returns, fn (vi, ty) =>
968 then SOME (Var.newNoname (), ty)
970 val xs = Vector.map (args, #1)
971 val block = Block.T {label = l,
973 statements = Vector.new0 (),
974 transfer = Return xs}
976 val () = List.push (FuncInfo.wrappers' fi, block)
977 val () = setLabelInfo (l, LabelInfo.new {func = fi,
984 fun getReturnContFunc (fi, args) =
985 getWrapperLabel (getReturnFunc fi, args)
986 fun getRaiseFunc (fi: FuncInfo.t): Label.t =
988 val r = FuncInfo.raiseLabel fi
993 val l = Label.newNoname ()
994 val raises = valOf (FuncInfo.raises fi)
997 (raises, fn (vi, ty) =>
999 then SOME (Var.newNoname (), ty)
1001 val xs = Vector.map (args, #1)
1002 val block = Block.T {label = l,
1004 statements = Vector.new0 (),
1005 transfer = Raise xs}
1006 val () = r := SOME l
1007 val () = List.push (FuncInfo.wrappers' fi, block)
1008 val () = setLabelInfo (l, LabelInfo.new {func = fi,
1015 fun getRaiseHandlerFunc (fi, args) =
1016 getWrapperLabel (getRaiseFunc fi, args)
1018 fun simplifyType (ty: Type.t): Type.t =
1020 val ti = typeInfo ty
1021 val simplify = TypeInfo.simplify' ti
1025 datatype z = datatype Type.dest
1026 datatype z = datatype ObjectCon.t
1028 case Type.dest ty of
1029 Object {args, con} =>
1033 val ci = conInfo con
1035 case (ConInfo.isConed ci,
1036 ConInfo.isDeconed ci) of
1038 #ty (ConInfo.dummy ci)
1041 {args = Prod.keepAllMap
1042 (ConInfo.args ci, fn (x,t) =>
1044 then SOME (simplifyType t)
1048 #ty (ConInfo.dummy ci)
1052 {args = Prod.map (args, simplifyType),
1054 | Weak ty => Type.weak (simplifyType ty)
1065 (datatypes, fn Datatype.T {tycon, cons} =>
1066 if isUsedTycon tycon
1068 val needsDummy : bool ref = ref false
1071 (cons, fn {con, ...} =>
1073 val ci = conInfo con
1078 val () = needsDummy := true
1080 SOME (TyconInfo.dummy (tyconInfo tycon))
1083 case (ConInfo.isConed ci,
1084 ConInfo.isDeconed ci) of
1086 if ConInfo.isUsed ci
1091 args = Prod.keepAllMap
1092 (ConInfo.args ci, fn (x, ty) =>
1094 then SOME (simplifyType ty)
1099 val num = Vector.length cons
1100 val () = TyconInfo.numCons' (tyconInfo tycon) := num
1102 SOME (Datatype.T {tycon = tycon, cons = cons})
1106 fun simplifyExp (e: Exp.t): Exp.t =
1108 Object {con, args} =>
1113 val ci = conInfo con
1115 if ConInfo.isDeconed ci
1119 (Prod.dest (ConInfo.args ci), #elt)
1121 Object {con = SOME con,
1122 args = (Vector.keepAllMap2
1129 else #exp (ConInfo.dummy ci)
1131 | Select {base, offset} =>
1133 datatype z = datatype Base.t
1138 datatype z = datatype ObjectCon.t
1139 datatype z = datatype Type.dest
1141 case Type.dest (tyVar base) of
1142 Object {con, ...} =>
1146 val ci = conInfo con
1147 val ciArgs = ConInfo.args ci
1150 (0, offset, 0, fn (i, offset) =>
1151 if (VarInfo.isUsed o #1 o #elt)
1152 (Prod.sub (ciArgs, i))
1156 Select {base = Base.Object base,
1160 | Vector => Error.bug "RemoveUnused2.simplifyExp: Update:non-Con|Tuple")
1161 | _ => Error.bug "RemoveUnused2.simplifyExp:Select:non-Object"
1166 fun simplifyStatement (s : Statement.t) : Statement.t option =
1168 Bind {exp, ty, var} =>
1171 SOME (Statement.Bind
1173 ty = simplifyType ty,
1174 exp = simplifyExp exp})
1176 if Exp.maySideEffect exp
1183 SOME var => if isUsedVar var
1184 then doit (SOME var)
1188 | Profile _ => SOME s
1189 | Update {base, offset, value} =>
1191 datatype z = datatype Base.t
1196 datatype z = datatype ObjectCon.t
1197 datatype z = datatype Type.dest
1199 case Type.dest (tyVar base) of
1200 Object {con, ...} =>
1204 val ci = conInfo con
1205 val ciArgs = ConInfo.args ci
1208 (#1 (#elt (Prod.sub (ciArgs, i))))
1223 {base = Base.Object base,
1230 | Vector => Error.bug "RemoveUnused2.simplifyStatement: Update:non-Con|Tuple")
1231 | _ => Error.bug "RemoveUnused2.simplifyStatement: Select:non-Object"
1235 fun simplifyStatements (ss: Statement.t Vector.t) : Statement.t Vector.t =
1236 Vector.keepAllMap (ss, simplifyStatement)
1237 fun simplifyTransfer (t: Transfer.t, fi: FuncInfo.t): Transfer.t =
1239 Arith {prim, args, overflow, success, ty} =>
1242 overflow = getArithOverflowWrapperLabel overflow,
1243 success = getArithSuccessWrapperLabel success,
1244 ty = simplifyType ty}
1246 | Call {func, args, return} =>
1248 val fi' = funcInfo func
1252 val (cont, handler) =
1254 Return.Dead => (None, None)
1255 | Return.NonTail {cont, handler} =>
1258 Handler.Caller => Caller
1259 | Handler.Dead => None
1260 | Handler.Handle h => Some h)
1261 | Return.Tail => (Caller, Caller)
1263 if FuncInfo.mayReturn fi'
1266 Error.bug "RemoveUnused2.simplifyTransfer: cont:None"
1268 (if (case (FuncInfo.returns fi,
1269 FuncInfo.returns fi') of
1270 (SOME xts, SOME yts) =>
1272 (xts, yts, fn ((x, _), (y, _)) =>
1273 VarInfo.isUsed x = VarInfo.isUsed y)
1274 | _ => Error.bug "RemoveUnused2.simplifyTransfer: cont:Caller")
1276 else Some (getReturnContFunc
1277 (fi, valOf (FuncInfo.returns fi'))))
1279 Some (getContWrapperLabel
1280 (l, valOf (FuncInfo.returns fi')))
1283 if FuncInfo.mayRaise fi'
1284 then (case handler of
1286 Error.bug "RemoveUnused2.simplifyTransfer: handler:None"
1288 (if (case (FuncInfo.raises fi,
1289 FuncInfo.raises fi') of
1290 (SOME xts, SOME yts) =>
1292 (xts, yts, fn ((x, _), (y, _)) =>
1293 VarInfo.isUsed x = VarInfo.isUsed y)
1294 | _ => Error.bug "RemoveUnused2.simplifyTransfer: handler:Caller")
1296 else Some (getRaiseHandlerFunc
1297 (fi, valOf (FuncInfo.raises fi'))))
1299 Some (getHandlerWrapperLabel
1300 (l, valOf (FuncInfo.raises fi'))))
1303 case (cont, handler) of
1304 (None, None) => Return.Dead
1305 | (None, Caller) => Return.Tail
1308 {cont = getBugFunc fi,
1309 handler = Handler.Handle h}
1310 | (Caller, None) => Return.Tail
1311 | (Caller, Caller) => Return.Tail
1312 | (Caller, Some h) =>
1314 {cont = getReturnContFunc
1315 (fi, valOf (FuncInfo.returns fi')),
1316 handler = Handler.Handle h}
1320 handler = Handler.Dead}
1321 | (Some c, Caller) =>
1324 handler = Handler.Caller}
1325 | (Some c, Some h) =>
1328 handler = Handler.Handle h}
1332 (args, FuncInfo.args fi', fn (x, (y, _)) =>
1341 | Case {test, cases = Cases.Con cases, default} =>
1345 (cases, fn (con, l) =>
1347 val ci = conInfo con
1349 if ConInfo.isConed ci
1353 fun keep default = Case {test = test,
1354 cases = Cases.Con cases,
1356 fun none () = keep NONE
1360 | SOME l => if Vector.isEmpty cases
1361 then if LabelInfo.isUsed (labelInfo l)
1362 then Goto {dst = l, args = Vector.new0 ()}
1366 case Type.dest (tyVar test) of
1367 Type.Datatype tycon => tycon
1368 | _ => Error.bug "RemoveUnused2.simplifyTransfer: Case:non-Datatype"
1369 val numCons = TyconInfo.numCons (tyconInfo tycon)
1371 if Vector.length cases = numCons
1376 | Case {test, cases, default} =>
1380 | Goto {dst, args} =>
1382 args = (Vector.keepAllMap2
1383 (args, LabelInfo.args (labelInfo dst),
1384 fn (x, (y, _)) => if VarInfo.isUsed y
1388 Raise (Vector.keepAllMap2
1389 (xs, valOf (FuncInfo.raises fi),
1390 fn (x, (y, _)) => if VarInfo.isUsed y
1394 Return (Vector.keepAllMap2
1395 (xs, valOf (FuncInfo.returns fi),
1396 fn (x, (y, _)) => if VarInfo.isUsed y
1399 | Runtime {prim, args, return} =>
1400 Runtime {prim = prim,
1402 return = getRuntimeWrapperLabel return}
1403 val simplifyTransfer =
1405 ("RemoveUnused2.simplifyTransfer",
1406 Layout.tuple2 (Transfer.layout, FuncInfo.layout), Transfer.layout)
1408 fun simplifyBlock (Block.T {label, args, statements, transfer}): Block.t option =
1410 val li = labelInfo label
1412 if LabelInfo.isUsed li
1416 (LabelInfo.args li, args, fn ((vi, _), (x, ty)) =>
1417 if VarInfo.isUsed vi
1418 then SOME (x, simplifyType ty)
1420 val statements = simplifyStatements statements
1422 simplifyTransfer (transfer, LabelInfo.func li)
1424 SOME (Block.T {label = label,
1426 statements = statements,
1427 transfer = transfer})
1431 fun simplifyBlocks (bs: Block.t Vector.t): Block.t Vector.t =
1432 Vector.keepAllMap (bs, simplifyBlock)
1433 val globals = simplifyStatements globals
1434 val shrink = shrinkFunction {globals = globals}
1435 fun simplifyFunction (f: Function.t): Function.t option =
1437 val {args, blocks, mayInline, name, start, ...} = Function.dest f
1438 val fi = funcInfo name
1440 if FuncInfo.isUsed fi
1444 (FuncInfo.args fi, args, fn ((vi, _), (x, ty)) =>
1445 if VarInfo.isUsed vi
1446 then SOME (x, simplifyType ty)
1448 val blocks = simplifyBlocks blocks
1449 val wrappers = Vector.fromList (FuncInfo.wrappers fi)
1450 val blocks = Vector.concat [wrappers, blocks]
1452 case FuncInfo.returns fi of
1455 if FuncInfo.mayReturn fi
1456 then SOME (Vector.keepAllMap
1459 then SOME (simplifyType ty)
1463 case FuncInfo.raises fi of
1466 if FuncInfo.mayRaise fi
1467 then SOME (Vector.keepAllMap
1470 then SOME (simplifyType ty)
1474 SOME (shrink (Function.new {args = args,
1476 mayInline = mayInline,
1484 fun simplifyFunctions (fs: Function.t List.t): Function.t List.t =
1485 List.keepAllMap (fs, simplifyFunction)
1486 val functions = simplifyFunctions functions
1487 val program = Program.T {datatypes = datatypes,
1489 functions = functions,
1492 val () = Program.clearTop program