@@ -3282,24 +3282,7 @@ static bool local_var_occurs(jl_value_t *e, int sl)
32823282 return false ;
32833283}
32843284
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)
33033286{
33043287 size_t slength = jl_array_dim0 (stmts);
33053288 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>
33083291 int last = jl_enternode_catch_dest (st);
33093292 if (last == 0 )
33103293 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 );
33213317 }
33223318 }
33233319 }
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+ }
33243326 }
33253327}
33263328
@@ -8439,7 +8441,6 @@ static jl_llvm_functions_t
84398441 ctx.code = src->code ;
84408442 ctx.source = src;
84418443
8442- std::map<int , BasicBlock*> labels;
84438444 ctx.module = jl_is_method (lam->def .method ) ? lam->def .method ->module : lam->def .module ;
84448445 ctx.linfo = lam;
84458446 ctx.name = name_from_method_instance (lam);
@@ -8499,6 +8500,49 @@ static jl_llvm_functions_t
84998500 if (dbgFuncName.empty ()) // Should never happen anymore?
85008501 debug_enabled = false ;
85018502
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+
85028546 // step 2. process var-info lists to see what vars need boxing
85038547 int n_ssavalues = jl_is_long (src->ssavaluetypes ) ? jl_unbox_long (src->ssavaluetypes ) : jl_array_nrows (src->ssavaluetypes );
85048548 size_t vinfoslen = jl_array_dim0 (src->slotflags );
@@ -8559,7 +8603,7 @@ static jl_llvm_functions_t
85598603 simple_use_analysis (ctx, jl_array_ptr_ref (stmts, i));
85608604
85618605 // determine which vars need to be volatile
8562- mark_volatile_vars (stmts, ctx.slots );
8606+ mark_volatile_vars (stmts, ctx.slots , branch_targets );
85638607
85648608 // step 4. determine function signature
85658609 if (!specsig)
@@ -9310,8 +9354,8 @@ static jl_llvm_functions_t
93109354
93119355 // step 11b. Do codegen in control flow order
93129356 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;
93159359 int cursor = 0 ;
93169360 int current_label = 0 ;
93179361 auto find_next_stmt = [&] (int seq_next) {
@@ -9430,47 +9474,6 @@ static jl_llvm_functions_t
94309474
94319475 come_from_bb[0 ] = ctx.builder .GetInsertBlock ();
94329476
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-
94749477 for (int label : branch_targets) {
94759478 BasicBlock *bb = BasicBlock::Create (ctx.builder .getContext (),
94769479 " L" + std::to_string (label), f);
0 commit comments