@@ -35,7 +35,8 @@ object Normalizer { normal =>
35
35
exprs : Map [Id , Expr ],
36
36
decls : DeclarationContext , // for field selection
37
37
usage : mutable.Map [Id , Usage ], // mutable in order to add new information after renaming
38
- maxInlineSize : Int // to control inlining and avoid code bloat
38
+ maxInlineSize : Int , // to control inlining and avoid code bloat
39
+ preserveBoxing : Boolean // for LLVM, prevents some optimizations
39
40
) {
40
41
def bind (id : Id , expr : Expr ): Context = copy(exprs = exprs + (id -> expr))
41
42
def bind (id : Id , block : Block ): Context = copy(blocks = blocks + (id -> block))
@@ -65,14 +66,14 @@ object Normalizer { normal =>
65
66
case None => false
66
67
}
67
68
68
- def normalize (entrypoints : Set [Id ], m : ModuleDecl , maxInlineSize : Int ): ModuleDecl = {
69
+ def normalize (entrypoints : Set [Id ], m : ModuleDecl , maxInlineSize : Int , preserveBoxing : Boolean ): ModuleDecl = {
69
70
// usage information is used to detect recursive functions (and not inline them)
70
71
val usage = Reachable (entrypoints, m)
71
72
72
73
val defs = m.definitions.collect {
73
74
case Toplevel .Def (id, block) => id -> block
74
75
}.toMap
75
- val context = Context (defs, Map .empty, DeclarationContext (m.declarations, m.externs), mutable.Map .from(usage), maxInlineSize)
76
+ val context = Context (defs, Map .empty, DeclarationContext (m.declarations, m.externs), mutable.Map .from(usage), maxInlineSize, preserveBoxing )
76
77
77
78
val (normalizedDefs, _) = normalizeToplevel(m.definitions)(using context)
78
79
m.copy(definitions = normalizedDefs)
@@ -138,10 +139,10 @@ object Normalizer { normal =>
138
139
139
140
// TODO for `New` we should track how often each operation is used, not the object itself
140
141
// to decide inlining.
141
- private def shouldInline (b : BlockLit , boundBy : Option [BlockVar ])(using C : Context ): Boolean = boundBy match {
142
+ private def shouldInline (b : BlockLit , boundBy : Option [BlockVar ], blockArgs : List [ Block ] )(using C : Context ): Boolean = boundBy match {
142
143
case Some (id) if isRecursive(id.id) => false
143
144
case Some (id) => isOnce(id.id) || b.body.size <= C .maxInlineSize
144
- case None => true
145
+ case _ => blockArgs.exists { b => b. isInstanceOf [ BlockLit ] } // higher-order function with known arg
145
146
}
146
147
147
148
private def active (e : Expr )(using Context ): Expr =
@@ -171,7 +172,7 @@ object Normalizer { normal =>
171
172
// -------
172
173
case Stmt .App (b, targs, vargs, bargs) =>
173
174
active(b) match {
174
- case NormalizedBlock .Known (b : BlockLit , boundBy) if shouldInline(b, boundBy) =>
175
+ case NormalizedBlock .Known (b : BlockLit , boundBy) if shouldInline(b, boundBy, bargs ) =>
175
176
reduce(b, targs, vargs.map(normalize), bargs.map(normalize))
176
177
case normalized =>
177
178
Stmt .App (normalized.shared, targs, vargs.map(normalize), bargs.map(normalize))
@@ -181,7 +182,7 @@ object Normalizer { normal =>
181
182
active(b) match {
182
183
case n @ NormalizedBlock .Known (Block .New (impl), boundBy) =>
183
184
selectOperation(impl, method) match {
184
- case b : BlockLit if shouldInline(b, boundBy) => reduce(b, targs, vargs.map(normalize), bargs.map(normalize))
185
+ case b : BlockLit if shouldInline(b, boundBy, bargs ) => reduce(b, targs, vargs.map(normalize), bargs.map(normalize))
185
186
case _ => Stmt .Invoke (n.shared, method, methodTpe, targs, vargs.map(normalize), bargs.map(normalize))
186
187
}
187
188
@@ -213,6 +214,14 @@ object Normalizer { normal =>
213
214
214
215
def normalizeVal (id : Id , tpe : ValueType , binding : Stmt , body : Stmt ): Stmt = normalize(binding) match {
215
216
217
+ // [[ val x = ABORT; body ]] = ABORT
218
+ case abort if ! C .preserveBoxing && abort.tpe == Type .TBottom =>
219
+ abort
220
+
221
+ case abort @ Stmt .Shift (p, BlockLit (tparams, cparams, vparams, List (k), body))
222
+ if ! C .preserveBoxing && ! Variables .free(body).containsBlock(k.id) =>
223
+ abort
224
+
216
225
// [[ val x = sc match { case id(ps) => body2 }; body ]] = sc match { case id(ps) => val x = body2; body }
217
226
case Stmt .Match (sc, List ((id2, BlockLit (tparams2, cparams2, vparams2, bparams2, body2))), None ) =>
218
227
Stmt .Match (sc, List ((id2, BlockLit (tparams2, cparams2, vparams2, bparams2,
0 commit comments