@@ -3282,24 +3282,7 @@ static bool local_var_occurs(jl_value_t *e, int sl)
3282
3282
return false ;
3283
3283
}
3284
3284
3285
- static std::set<int > assigned_in_try (jl_array_t *stmts, int s, long l)
3286
- {
3287
- std::set<int > av;
3288
- for (int i=s; i < l; i++) {
3289
- jl_value_t *st = jl_array_ptr_ref (stmts,i);
3290
- if (jl_is_expr (st)) {
3291
- if (((jl_expr_t *)st)->head == jl_assign_sym) {
3292
- jl_value_t *ar = jl_exprarg (st, 0 );
3293
- if (jl_is_slotnumber (ar)) {
3294
- av.insert (jl_slot_number (ar)-1 );
3295
- }
3296
- }
3297
- }
3298
- }
3299
- return av;
3300
- }
3301
-
3302
- static void mark_volatile_vars (jl_array_t *stmts, SmallVectorImpl<jl_varinfo_t > &slots)
3285
+ static bool have_try_block (jl_array_t *stmts)
3303
3286
{
3304
3287
size_t slength = jl_array_dim0 (stmts);
3305
3288
for (int i = 0 ; i < (int )slength; i++) {
@@ -3308,19 +3291,38 @@ static void mark_volatile_vars(jl_array_t *stmts, SmallVectorImpl<jl_varinfo_t>
3308
3291
int last = jl_enternode_catch_dest (st);
3309
3292
if (last == 0 )
3310
3293
continue ;
3311
- std::set<int > as = assigned_in_try (stmts, i + 1 , last - 1 );
3312
- for (int j = 0 ; j < (int )slength; j++) {
3313
- if (j < i || j > last) {
3314
- std::set<int >::iterator it = as.begin ();
3315
- for (; it != as.end (); it++) {
3316
- if (local_var_occurs (jl_array_ptr_ref (stmts, j), *it)) {
3317
- jl_varinfo_t &vi = slots[*it];
3318
- vi.isVolatile = true ;
3319
- }
3320
- }
3294
+ return 1 ;
3295
+ }
3296
+ }
3297
+ return 0 ;
3298
+ }
3299
+
3300
+ // conservative marking of all variables potentially used after a catch block that were assigned before it
3301
+ static void mark_volatile_vars (jl_array_t *stmts, SmallVectorImpl<jl_varinfo_t > &slots, const std::set<int > &bbstarts)
3302
+ {
3303
+ if (!have_try_block (stmts))
3304
+ return ;
3305
+ size_t slength = jl_array_dim0 (stmts);
3306
+ BitVector assigned_in_block (slots.size ()); // conservatively only ignore slots assigned in the same basic block
3307
+ for (int j = 0 ; j < (int )slength; j++) {
3308
+ if (bbstarts.count (j + 1 ))
3309
+ assigned_in_block.reset ();
3310
+ jl_value_t *stmt = jl_array_ptr_ref (stmts, j);
3311
+ if (jl_is_expr (stmt)) {
3312
+ jl_expr_t *e = (jl_expr_t *)stmt;
3313
+ if (e->head == jl_assign_sym) {
3314
+ jl_value_t *l = jl_exprarg (e, 0 );
3315
+ if (jl_is_slotnumber (l)) {
3316
+ assigned_in_block.set (jl_slot_number (l)-1 );
3321
3317
}
3322
3318
}
3323
3319
}
3320
+ for (int slot = 0 ; slot < (int )slots.size (); slot++) {
3321
+ if (!assigned_in_block.test (slot) && local_var_occurs (stmt, slot)) {
3322
+ jl_varinfo_t &vi = slots[slot];
3323
+ vi.isVolatile = true ;
3324
+ }
3325
+ }
3324
3326
}
3325
3327
}
3326
3328
@@ -8439,7 +8441,6 @@ static jl_llvm_functions_t
8439
8441
ctx.code = src->code ;
8440
8442
ctx.source = src;
8441
8443
8442
- std::map<int , BasicBlock*> labels;
8443
8444
ctx.module = jl_is_method (lam->def .method ) ? lam->def .method ->module : lam->def .module ;
8444
8445
ctx.linfo = lam;
8445
8446
ctx.name = name_from_method_instance (lam);
@@ -8499,6 +8500,49 @@ static jl_llvm_functions_t
8499
8500
if (dbgFuncName.empty ()) // Should never happen anymore?
8500
8501
debug_enabled = false ;
8501
8502
8503
+ // First go through and collect all branch targets, so we know where to
8504
+ // split basic blocks.
8505
+ std::set<int > branch_targets; // 1-indexed, sorted
8506
+ for (size_t i = 0 ; i < stmtslen; ++i) {
8507
+ jl_value_t *stmt = jl_array_ptr_ref (stmts, i);
8508
+ if (jl_is_gotoifnot (stmt)) {
8509
+ int dest = jl_gotoifnot_label (stmt);
8510
+ branch_targets.insert (dest);
8511
+ // The next 1-indexed statement
8512
+ branch_targets.insert (i + 2 );
8513
+ }
8514
+ else if (jl_is_returnnode (stmt)) {
8515
+ // We don't do dead branch elimination before codegen
8516
+ // so we need to make sure to start a BB after any
8517
+ // return node, even if they aren't otherwise branch
8518
+ // targets.
8519
+ if (i + 2 <= stmtslen)
8520
+ branch_targets.insert (i + 2 );
8521
+ }
8522
+ else if (jl_is_enternode (stmt)) {
8523
+ branch_targets.insert (i + 1 );
8524
+ if (i + 2 <= stmtslen)
8525
+ branch_targets.insert (i + 2 );
8526
+ size_t catch_dest = jl_enternode_catch_dest (stmt);
8527
+ if (catch_dest)
8528
+ branch_targets.insert (catch_dest);
8529
+ }
8530
+ else if (jl_is_gotonode (stmt)) {
8531
+ int dest = jl_gotonode_label (stmt);
8532
+ branch_targets.insert (dest);
8533
+ if (i + 2 <= stmtslen)
8534
+ branch_targets.insert (i + 2 );
8535
+ }
8536
+ else if (jl_is_phinode (stmt)) {
8537
+ jl_array_t *edges = (jl_array_t *)jl_fieldref_noalloc (stmt, 0 );
8538
+ for (size_t j = 0 ; j < jl_array_nrows (edges); ++j) {
8539
+ size_t edge = jl_array_data (edges, int32_t )[j];
8540
+ if (edge == i)
8541
+ branch_targets.insert (i + 1 );
8542
+ }
8543
+ }
8544
+ }
8545
+
8502
8546
// step 2. process var-info lists to see what vars need boxing
8503
8547
int n_ssavalues = jl_is_long (src->ssavaluetypes ) ? jl_unbox_long (src->ssavaluetypes ) : jl_array_nrows (src->ssavaluetypes );
8504
8548
size_t vinfoslen = jl_array_dim0 (src->slotflags );
@@ -8559,7 +8603,7 @@ static jl_llvm_functions_t
8559
8603
simple_use_analysis (ctx, jl_array_ptr_ref (stmts, i));
8560
8604
8561
8605
// determine which vars need to be volatile
8562
- mark_volatile_vars (stmts, ctx.slots );
8606
+ mark_volatile_vars (stmts, ctx.slots , branch_targets );
8563
8607
8564
8608
// step 4. determine function signature
8565
8609
if (!specsig)
@@ -9310,8 +9354,8 @@ static jl_llvm_functions_t
9310
9354
9311
9355
// step 11b. Do codegen in control flow order
9312
9356
SmallVector<int , 0 > workstack;
9313
- std::map< int , BasicBlock*> BB;
9314
- std::map <size_t , BasicBlock*> come_from_bb;
9357
+ DenseMap< size_t , BasicBlock*> BB;
9358
+ DenseMap <size_t , BasicBlock*> come_from_bb;
9315
9359
int cursor = 0 ;
9316
9360
int current_label = 0 ;
9317
9361
auto find_next_stmt = [&] (int seq_next) {
@@ -9430,47 +9474,6 @@ static jl_llvm_functions_t
9430
9474
9431
9475
come_from_bb[0 ] = ctx.builder .GetInsertBlock ();
9432
9476
9433
- // First go through and collect all branch targets, so we know where to
9434
- // split basic blocks.
9435
- std::set<int > branch_targets; // 1-indexed
9436
- {
9437
- for (size_t i = 0 ; i < stmtslen; ++i) {
9438
- jl_value_t *stmt = jl_array_ptr_ref (stmts, i);
9439
- if (jl_is_gotoifnot (stmt)) {
9440
- int dest = jl_gotoifnot_label (stmt);
9441
- branch_targets.insert (dest);
9442
- // The next 1-indexed statement
9443
- branch_targets.insert (i + 2 );
9444
- } else if (jl_is_returnnode (stmt)) {
9445
- // We don't do dead branch elimination before codegen
9446
- // so we need to make sure to start a BB after any
9447
- // return node, even if they aren't otherwise branch
9448
- // targets.
9449
- if (i + 2 <= stmtslen)
9450
- branch_targets.insert (i + 2 );
9451
- } else if (jl_is_enternode (stmt)) {
9452
- branch_targets.insert (i + 1 );
9453
- if (i + 2 <= stmtslen)
9454
- branch_targets.insert (i + 2 );
9455
- size_t catch_dest = jl_enternode_catch_dest (stmt);
9456
- if (catch_dest)
9457
- branch_targets.insert (catch_dest);
9458
- } else if (jl_is_gotonode (stmt)) {
9459
- int dest = jl_gotonode_label (stmt);
9460
- branch_targets.insert (dest);
9461
- if (i + 2 <= stmtslen)
9462
- branch_targets.insert (i + 2 );
9463
- } else if (jl_is_phinode (stmt)) {
9464
- jl_array_t *edges = (jl_array_t *)jl_fieldref_noalloc (stmt, 0 );
9465
- for (size_t j = 0 ; j < jl_array_nrows (edges); ++j) {
9466
- size_t edge = jl_array_data (edges, int32_t )[j];
9467
- if (edge == i)
9468
- branch_targets.insert (i + 1 );
9469
- }
9470
- }
9471
- }
9472
- }
9473
-
9474
9477
for (int label : branch_targets) {
9475
9478
BasicBlock *bb = BasicBlock::Create (ctx.builder .getContext (),
9476
9479
" L" + std::to_string (label), f);
0 commit comments