@@ -3568,6 +3568,7 @@ function optimize(me::InferenceState)
3568
3568
alloc_elim_pass! (opt)
3569
3569
getfield_elim_pass! (opt)
3570
3570
copy_duplicated_expr_pass! (opt)
3571
+ linearize_pass! (opt)
3571
3572
# Clean up for `alloc_elim_pass!` and `getfield_elim_pass!`
3572
3573
void_use_elim_pass! (opt)
3573
3574
# Pop metadata before label reindexing
@@ -6167,6 +6168,120 @@ function replace_getfield!(e::Expr, tupname, vals, field_names, sv::Optimization
6167
6168
end
6168
6169
end
6169
6170
6171
+ function is_ccall_static (e:: Expr , sv:: OptimizationState )
6172
+ if e. head === :call
6173
+ is_known_call (e, tuple, sv. src, sv. mod) || return false
6174
+ length (e. args) == 3 || return false
6175
+ for i in 2 : 3
6176
+ a = e. args[i]
6177
+ (isa (a, Expr) || isa (a, Slot) || isa (a, SSAValue)) && return false
6178
+ end
6179
+ return true
6180
+ elseif e. head === :static_parameter
6181
+ return true
6182
+ end
6183
+ return false
6184
+ end
6185
+
6186
+ function linearize_arg! (args, i, stmts, sv:: OptimizationState )
6187
+ a = args[i]
6188
+ if isa (a, Symbol)
6189
+ a = a:: Symbol
6190
+ isdefined (sv. mod, a) && isconst (sv. mod, a) && return
6191
+ typ = Any
6192
+ elseif isa (a, GlobalRef)
6193
+ a = a:: GlobalRef
6194
+ isdefined (a. mod, a. name) && isconst (a. mod, a. name) && return
6195
+ typ = Any
6196
+ elseif isa (a, Expr)
6197
+ if a. head === :boundscheck
6198
+ # Allow `Expr(:boundscheck)` to be nested, this affects DCE
6199
+ # TODO : make the DCE/alloc_elim smarter to not need this hack
6200
+ return
6201
+ end
6202
+ typ = (a:: Expr ). typ
6203
+ else
6204
+ return
6205
+ end
6206
+ ssa = newvar! (sv, typ)
6207
+ push! (stmts, :($ ssa = $ a))
6208
+ args[i] = ssa
6209
+ return
6210
+ end
6211
+
6212
+ # Temporary pass to linearize the IR before `alloc_elim_pass!` before we do so in lowering
6213
+ function linearize_pass! (sv:: OptimizationState )
6214
+ body = sv. src. code
6215
+ len = length (body)
6216
+ next_i = 1
6217
+ stmts = []
6218
+ while next_i <= len
6219
+ i = next_i
6220
+ next_i += 1
6221
+ ex = body[i]
6222
+ isa (ex, Expr) || continue
6223
+ ex = ex:: Expr
6224
+ head = ex. head
6225
+ is_meta_expr_head (head) && continue
6226
+ if head === :(= )
6227
+ ex = ex. args[2 ]
6228
+ isa (ex, Expr) || continue
6229
+ ex = ex:: Expr
6230
+ head = ex. head
6231
+ end
6232
+ args = ex. args
6233
+ if head === :foreigncall
6234
+ if isa (args[1 ], Expr) && ! is_ccall_static (args[1 ]:: Expr , sv)
6235
+ linearize_arg! (args, 1 , stmts, sv)
6236
+ end
6237
+ for j in 2 : length (args)
6238
+ a = args[j]
6239
+ isa (a, Expr) || continue
6240
+ if a. head === :&
6241
+ linearize_arg! (a. args, 1 , stmts, sv)
6242
+ else
6243
+ linearize_arg! (args, j, stmts, sv)
6244
+ end
6245
+ end
6246
+ elseif (head === :import || head === :using || head === :importall || head === :export ||
6247
+ head === :isdefined || head === :const || is_meta_expr_head (head))
6248
+ continue
6249
+ elseif head === :call
6250
+ if is_known_call (ex, Intrinsics. llvmcall, sv. src, sv. mod)
6251
+ for j in 5 : length (args)
6252
+ linearize_arg! (args, j, stmts, sv)
6253
+ end
6254
+ elseif is_known_call (ex, Intrinsics. cglobal, sv. src, sv. mod)
6255
+ if isa (args[2 ], Expr) && ! is_ccall_static (args[2 ]:: Expr , sv)
6256
+ linearize_arg! (args, 2 , stmts, sv)
6257
+ end
6258
+ for j in 3 : length (args)
6259
+ linearize_arg! (args, j, stmts, sv)
6260
+ end
6261
+ else
6262
+ for j in 1 : length (args)
6263
+ linearize_arg! (args, j, stmts, sv)
6264
+ end
6265
+ end
6266
+ else
6267
+ for j in 1 : length (args)
6268
+ if j == 1 && head === :method
6269
+ argj = args[j]
6270
+ if isa (argj, Slot) || isa (argj, Symbol) || isa (argj, GlobalRef)
6271
+ continue
6272
+ end
6273
+ end
6274
+ linearize_arg! (args, j, stmts, sv)
6275
+ end
6276
+ end
6277
+ isempty (stmts) && continue
6278
+ next_i = i
6279
+ splice! (body, i: (i - 1 ), stmts)
6280
+ len += length (stmts)
6281
+ empty! (stmts)
6282
+ end
6283
+ end
6284
+
6170
6285
const meta_pop_loc = Expr (:meta , :pop_loc )
6171
6286
6172
6287
function copy_expr_in_array! (ary, seen)
0 commit comments