@@ -324,8 +324,8 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
324
324
if is_opaque
325
325
# Replace the first argument by a load of the capture environment
326
326
argexprs[1 ] = insert_node_here! (compact,
327
- Expr (:call , GlobalRef (Core, :getfield ), argexprs[1 ], :captures ),
328
- spec. ir. argtypes[1 ], compact. result[idx][:line ])
327
+ NewInstruction ( Expr (:call , GlobalRef (Core, :getfield ), argexprs[1 ], QuoteNode ( :captures ) ),
328
+ spec. ir. argtypes[1 ], compact. result[idx][:line ]))
329
329
end
330
330
flag = compact. result[idx][:flag ]
331
331
boundscheck_idx = boundscheck
@@ -386,8 +386,8 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
386
386
inline_compact. result[idx′][:type ] = (isa (val, Argument) || isa (val, Expr)) ?
387
387
compact_exprtype (compact, val) :
388
388
compact_exprtype (inline_compact, val)
389
- insert_node_here! (inline_compact, GotoNode (post_bb_id),
390
- Any, compact. result[idx′][:line ],
389
+ insert_node_here! (inline_compact, NewInstruction ( GotoNode (post_bb_id),
390
+ Any, compact. result[idx′][:line ]) ,
391
391
true )
392
392
push! (pn. values, SSAValue (idx′))
393
393
else
@@ -419,7 +419,8 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
419
419
if length (pn. edges) == 1
420
420
return_value = pn. values[1 ]
421
421
else
422
- return_value = insert_node_here! (compact, pn, compact_exprtype (compact, SSAValue (idx)), compact. result[idx][:line ])
422
+ return_value = insert_node_here! (compact,
423
+ NewInstruction (pn, compact_exprtype (compact, SSAValue (idx)), compact. result[idx][:line ]))
423
424
end
424
425
end
425
426
return_value
@@ -448,15 +449,15 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int,
448
449
a <: m && continue
449
450
# Generate isa check
450
451
isa_expr = Expr (:call , isa, argexprs[i], m)
451
- ssa = insert_node_here! (compact, isa_expr, Bool, line)
452
+ ssa = insert_node_here! (compact, NewInstruction ( isa_expr, Bool, line) )
452
453
if cond === true
453
454
cond = ssa
454
455
else
455
456
and_expr = Expr (:call , and_int, cond, ssa)
456
- cond = insert_node_here! (compact, and_expr, Bool, line)
457
+ cond = insert_node_here! (compact, NewInstruction ( and_expr, Bool, line) )
457
458
end
458
459
end
459
- insert_node_here! (compact, GotoIfNot (cond, next_cond_bb), Union{}, line)
460
+ insert_node_here! (compact, NewInstruction ( GotoIfNot (cond, next_cond_bb), Union{}, line) )
460
461
bb = next_cond_bb - 1
461
462
finish_current_bb! (compact, 0 )
462
463
argexprs′ = argexprs
@@ -466,45 +467,49 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int,
466
467
a, m = atype. parameters[i], metharg. parameters[i]
467
468
(isa (argexprs[i], SSAValue) || isa (argexprs[i], Argument)) || continue
468
469
if ! (a <: m )
469
- argexprs′[i] = insert_node_here! (compact, PiNode (argexprs′[i], m),
470
- m, line)
470
+ argexprs′[i] = insert_node_here! (compact,
471
+ NewInstruction ( PiNode (argexprs′[i], m), m, line) )
471
472
end
472
473
end
473
474
end
474
475
if isa (case, InliningTodo)
475
476
val = ir_inline_item! (compact, idx, argexprs′, linetable, case, boundscheck, todo_bbs)
476
477
elseif isa (case, MethodInstance)
477
- val = insert_node_here! (compact, Expr (:invoke , case, argexprs′... ), typ, line)
478
+ val = insert_node_here! (compact,
479
+ NewInstruction (Expr (:invoke , case, argexprs′... ), typ, line))
478
480
else
479
481
case = case:: ConstantCase
480
482
val = case. val
481
483
end
482
484
if ! isempty (compact. result_bbs[bb]. preds)
483
485
push! (pn. edges, bb)
484
486
push! (pn. values, val)
485
- insert_node_here! (compact, GotoNode (join_bb), Union{}, line)
487
+ insert_node_here! (compact,
488
+ NewInstruction (GotoNode (join_bb), Union{}, line))
486
489
else
487
- insert_node_here! (compact, ReturnNode (), Union{}, line)
490
+ insert_node_here! (compact,
491
+ NewInstruction (ReturnNode (), Union{}, line))
488
492
end
489
493
finish_current_bb! (compact, 0 )
490
494
end
491
495
bb += 1
492
496
# We're now in the fall through block, decide what to do
493
497
if item. fully_covered
494
498
e = Expr (:call , GlobalRef (Core, :throw ), fatal_type_bound_error)
495
- insert_node_here! (compact, e, Union{}, line)
496
- insert_node_here! (compact, ReturnNode (), Union{}, line)
499
+ insert_node_here! (compact, NewInstruction ( e, Union{}, line) )
500
+ insert_node_here! (compact, NewInstruction ( ReturnNode (), Union{}, line) )
497
501
finish_current_bb! (compact, 0 )
498
502
else
499
- ssa = insert_node_here! (compact, stmt, typ, line)
503
+ ssa = insert_node_here! (compact, NewInstruction ( stmt, typ, line) )
500
504
push! (pn. edges, bb)
501
505
push! (pn. values, ssa)
502
- insert_node_here! (compact, GotoNode (join_bb), Union{}, line)
506
+ insert_node_here! (compact, NewInstruction ( GotoNode (join_bb), Union{}, line) )
503
507
finish_current_bb! (compact, 0 )
504
508
end
505
509
506
510
# We're now in the join block.
507
- compact. ssa_rename[compact. idx- 1 ] = insert_node_here! (compact, pn, typ, line)
511
+ compact. ssa_rename[compact. idx- 1 ] = insert_node_here! (compact,
512
+ NewInstruction (pn, typ, line))
508
513
nothing
509
514
end
510
515
@@ -553,8 +558,9 @@ function batch_inline!(todo::Vector{Pair{Int, Any}}, ir::IRCode, linetable::Vect
553
558
# At the moment we will allow globalrefs in argument position, turn those into ssa values
554
559
for aidx in 1 : length (argexprs)
555
560
aexpr = argexprs[aidx]
556
- if isa (aexpr, GlobalRef) || isa (aexpr, Expr)
557
- argexprs[aidx] = insert_node_here! (compact, aexpr, compact_exprtype (compact, aexpr), compact. result[idx][:line ])
561
+ if isa (aexpr, Expr)
562
+ argexprs[aidx] = insert_node_here! (compact,
563
+ NewInstruction (aexpr, compact_exprtype (compact, aexpr), compact. result[idx][:line ]))
558
564
end
559
565
end
560
566
if isa (item, InliningTodo)
@@ -630,7 +636,7 @@ function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::
630
636
new_argexpr = quoted (def_atype. val)
631
637
else
632
638
new_call = Expr (:call , GlobalRef (Core, :getfield ), def, j)
633
- new_argexpr = insert_node! (ir, idx, def_atype, new_call )
639
+ new_argexpr = insert_node! (ir, idx, NewInstruction (new_call, def_atype) )
634
640
end
635
641
push! (new_argexprs, new_argexpr)
636
642
push! (new_atypes, def_atype)
@@ -640,7 +646,7 @@ function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::
640
646
for i = 1 : length (thisarginfo. each)
641
647
call = thisarginfo. each[i]
642
648
new_stmt = Expr (:call , argexprs[2 ], def, state... )
643
- state1 = insert_node! (ir, idx, call. rt, new_stmt )
649
+ state1 = insert_node! (ir, idx, NewInstruction (new_stmt, call. rt) )
644
650
new_sig = with_atype (call_sig (ir, new_stmt):: Signature )
645
651
info = call. info
646
652
handled = false
@@ -661,12 +667,14 @@ function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::
661
667
end
662
668
if i != length (thisarginfo. each)
663
669
valT = getfield_tfunc (call. rt, Const (1 ))
664
- val_extracted = insert_node! (ir, idx, valT,
665
- Expr (:call , GlobalRef (Core, :getfield ), state1, 1 ))
670
+ val_extracted = insert_node! (ir, idx, NewInstruction (
671
+ Expr (:call , GlobalRef (Core, :getfield ), state1, 1 ),
672
+ valT))
666
673
push! (new_argexprs, val_extracted)
667
674
push! (new_atypes, valT)
668
- state_extracted = insert_node! (ir, idx, getfield_tfunc (call. rt, Const (2 )),
669
- Expr (:call , GlobalRef (Core, :getfield ), state1, 2 ))
675
+ state_extracted = insert_node! (ir, idx, NewInstruction (
676
+ Expr (:call , GlobalRef (Core, :getfield ), state1, 2 ),
677
+ getfield_tfunc (call. rt, Const (2 ))))
670
678
state = Core. svec (state_extracted)
671
679
end
672
680
end
@@ -933,7 +941,7 @@ function inline_splatnew!(ir::IRCode, idx::Int)
933
941
for j = 1 : n
934
942
atype = getfield_tfunc (tt, Const (j))
935
943
new_call = Expr (:call , Core. getfield, tup, j)
936
- new_argexpr = insert_node! (ir, idx, atype, new_call )
944
+ new_argexpr = insert_node! (ir, idx, NewInstruction (new_call, atype) )
937
945
push! (new_argexprs, new_argexpr)
938
946
end
939
947
stmt. head = :new
@@ -1081,17 +1089,32 @@ function narrow_opaque_closure!(ir::IRCode, stmt::Expr, @nospecialize(info), sta
1081
1089
end
1082
1090
end
1083
1091
1092
+ # As a matter of convenience, this pass also computes effect-freenes.
1093
+ # For primitives, we do that right here. For proper calls, we will
1094
+ # discover this when we consult the caches.
1095
+ function check_effect_free! (ir:: IRCode , @nospecialize (stmt), @nospecialize (calltype), idx:: Int )
1096
+ if stmt_effect_free (stmt, calltype, ir, ir. sptypes)
1097
+ ir. stmts[idx][:flag ] |= IR_FLAG_EFFECT_FREE
1098
+ end
1099
+ end
1100
+
1084
1101
# Handles all analysis and inlining of intrinsics and builtins. In particular,
1085
1102
# this method does not access the method table or otherwise process generic
1086
1103
# functions.
1087
1104
function process_simple! (ir:: IRCode , todo:: Vector{Pair{Int, Any}} , idx:: Int , state:: InliningState )
1088
1105
stmt = ir. stmts[idx][:inst ]
1089
- stmt isa Expr || return nothing
1090
- if stmt. head === :splatnew
1091
- inline_splatnew ! (ir, idx)
1106
+ calltype = ir . stmts[idx][ :type ]
1107
+ if ! ( stmt isa Expr)
1108
+ check_effect_free ! (ir, stmt, calltype , idx)
1092
1109
return nothing
1093
- elseif stmt. head === :new_opaque_closure
1094
- narrow_opaque_closure! (ir, stmt, ir. stmts[idx][:info ], state)
1110
+ end
1111
+ if stmt. head != = :call
1112
+ if stmt. head === :splatnew
1113
+ inline_splatnew! (ir, idx)
1114
+ elseif stmt. head === :new_opaque_closure
1115
+ narrow_opaque_closure! (ir, stmt, ir. stmts[idx][:info ], state)
1116
+ end
1117
+ check_effect_free! (ir, stmt, calltype, idx)
1095
1118
return nothing
1096
1119
end
1097
1120
@@ -1105,13 +1128,14 @@ function process_simple!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int, sta
1105
1128
sig === nothing && return nothing
1106
1129
1107
1130
# Check if we match any of the early inliners
1108
- calltype = ir. stmts[idx][:type ]
1109
1131
res = early_inline_special_case (ir, sig, stmt, state. params, calltype)
1110
1132
if res != = nothing
1111
1133
ir. stmts[idx][:inst ] = res
1112
1134
return nothing
1113
1135
end
1114
1136
1137
+ check_effect_free! (ir, stmt, calltype, idx)
1138
+
1115
1139
if sig. f != = Core. invoke && is_builtin (sig)
1116
1140
# No inlining for builtins (other invoke/apply)
1117
1141
return nothing
@@ -1121,8 +1145,10 @@ function process_simple!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int, sta
1121
1145
1122
1146
# Special case inliners for regular functions
1123
1147
if late_inline_special_case! (ir, sig, idx, stmt, state. params) || is_return_type (sig. f)
1148
+ check_effect_free! (ir, ir. stmts[idx][:inst ], calltype, idx)
1124
1149
return nothing
1125
1150
end
1151
+
1126
1152
return sig
1127
1153
end
1128
1154
@@ -1256,6 +1282,7 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
1256
1282
ir. stmts[idx][:inst ] = quoted (calltype. val)
1257
1283
continue
1258
1284
end
1285
+ ir. stmts[idx][:flag ] |= IR_FLAG_EFFECT_FREE
1259
1286
info = info. info
1260
1287
end
1261
1288
@@ -1306,7 +1333,7 @@ end
1306
1333
function mk_tuplecall! (compact:: IncrementalCompact , args:: Vector{Any} , line_idx:: Int32 )
1307
1334
e = Expr (:call , TOP_TUPLE, args... )
1308
1335
etyp = tuple_tfunc (Any[compact_exprtype (compact, args[i]) for i in 1 : length (args)])
1309
- return insert_node_here! (compact, e, etyp, line_idx)
1336
+ return insert_node_here! (compact, NewInstruction ( e, etyp, line_idx) )
1310
1337
end
1311
1338
1312
1339
function linear_inline_eligible (ir:: IRCode )
@@ -1371,7 +1398,7 @@ function late_inline_special_case!(ir::IRCode, sig::Signature, idx::Int, stmt::E
1371
1398
return true
1372
1399
end
1373
1400
cmp_call = Expr (:call , GlobalRef (Core, :(=== )), stmt. args[2 ], stmt. args[3 ])
1374
- cmp_call_ssa = insert_node! (ir, idx, Bool, cmp_call )
1401
+ cmp_call_ssa = insert_node! (ir, idx, effect_free ( NewInstruction (cmp_call, Bool)) )
1375
1402
not_call = Expr (:call , GlobalRef (Core. Intrinsics, :not_int ), cmp_call_ssa)
1376
1403
ir[SSAValue (idx)] = not_call
1377
1404
return true
0 commit comments