[proposed backport for PR54146 fixes to 4.7 ] From: Steven Bosscher Date: Wed, 22 Aug 2012 00:57:09 +0200 Subject: [patch] Backport fixes for PR54146 to GCC 4.7 List-Archive: Hello, This patch back-ports most of the changes made to resolve the worst of PR54146 on trunk to GCC 4.7. This PR is basically an accumulation of various compiler speed and memory usage regressions, and all fixes are almost trivial, so I think it's fair and safe to back-port these changes. Bootstrapped&tested (gcc-4_7-branch, of course) on x86_64-unknown-linux-gnu, and on powerpc64-unknown-linux-gnu. OK? Ciao! Steven gcc/ 2012-08-25 Steven Bosscher Backport from trunk PR middle-end/54146 * tree-ssa-loop-im.c (lim_bitmap_obstack): New bitmap_obstack. (memref_free): Don't free the bitmaps individually here. (mem_ref_alloc): Allocate the bitmaps on the new bitmap obstack. (analyze_memory_references): Likewise. (tree_ssa_lim_initialize): Initialize the new bitmap obstack. (tree_ssa_lim_finalize): Release it. * dse.c (dse_bitmap_obstack): New bitmap obstack. (dse_obstack): New obstack. (get_group_info): Allocate the bitmaps on the new bitmap obstack. (dse_step0): Allocate the scratch bitmap on reg_obstack. Initialize the new bitmap obstack and normal obstack. Use XNEWVEC for bb_table. (record_store): Allocate regs_set on reg_obstack. (dse_step1): Allocate regs_live on reg_obstack. (dse_step2_init): Allocate offset_map_n and offset_map_p on the new obstack. (dse_step3_scan): Allocate bitmaps on the new bitmap obstack. (dse_step3): Likewise. (dse_confluence_0): Likewise. (dse_confluence_n): Likewise. (dse_transfer_function): Likewise. (dse_step7): Destroy the new obstacks, and everything allocated on them, in one big sweep. (rest_of_handle_dse): Update. * cfgexpand.c (stack_var_bitmap_obstack): New bitmap obstack. (add_stack_var_conflict): Allocate bitmaps on it. (add_scope_conflicts_1): Likewise. (add_scope_conflicts): Likewise. (update_alias_info_with_stack_vars): Likewise. (init_vars_expansion): Move TREE_USED fiddling expand_used_vars. Initialize the new bitmap obstack. (fini_vars_expansion): Release it. (estimated_stack_frame_size): Use init_vars_expansion to set things up and always clean up at the end. (expand_used_vars): Do the TREE_USED trickery here. Always call fini_vars_expansion. * tree-ssa-live.h (struct tree_live_info_d): Make livein and liveout arrays of bitmap_head to avoid one indirection per bitmap access. (live_on_entry, live_on_exit, live_var_map, live_merge_and_clear, make_live_on_entry): Update. * tree-ssa-live.c (partition_view_bitmap): Don't double-free 'used'. (liveness_bitmap_obstack): New bitmap obstack. (remove_unused_locals): Use it to allocate all bitmaps on. Update for livein/liveout changes in tree-ssa-live.h. (delete_tree_live_info): Release the bitmap obstack. (loe_visit_block, live_worklist, set_var_live_on_entry, calculate_live_on_exit, dump_live_info): Update. (calculate_live_ranges): Initialize the bitmap. * tree-ssa-ter.c (ter_bitmap_obstack): New bitmap obstack. (new_temp_expr_table): Allocate bitmap on it. (make_dependent_on_partition, add_to_partition_kill_list, add_dependence, process_replaceable): Likewise. (find_replaceable_exprs): Initialize and release the new obstack here. * df-problems.c (df_lr_add_problem): Allocate persistent bitmap for out_of_date_transfer_functions on df_bitmap_obstack. (df_live_add_problem): Likewise. (df_chain_add_problem): Likewise. (df_word_lr_add_problem): Likewise. PR tree-optimization/54146 * cfgexpand.c (add_scope_conflicts_1): Use bitmap_ior_into. (add_scope_conflicts): Iterate in RPO order. (add_stack_protection_conflicts): Iterate over the other triangle. (fini_vars_expansion): Clear stack_vars_sorted. PR tree-optimization/54146 * ifcvt.c: Include pointer-set.h. (cond_move_process_if_block): Change type of then_regs and else_regs from alloca'd array to pointer_sets. (check_cond_move_block): Update for this change. (cond_move_convert_if_block): Likewise. * Makefile.in: Fix dependencies for ifcvt.o. PR middle-end/54146 * tree-flow.h (compute_global_livein): Remove prototype. * tree-into-ssa.c (compute_global_livein): Remove function. * tree-ssa-loop-manip.c: Include gimple-pretty-print.h. (find_sibling_superloop): New function. (compute_live_loop_exits): New function. (add_exit_phis_edge): Rename to add_exit_phi. Do not allow inserting a PHI in a block that is not a loop exit for VAR. Add dumping if TDF_DETAILS. (add_exit_phis_var): Rewrite. (add_exit_phis): Update. (get_loops_exits): Rewrite to return an array of per-loop exits rather than one bitmap with all loop exits. (find_uses_to_rename_bb): Ignore virtual PHI nodes. (rewrite_into_loop_closed_ssa): Update. PR middle-end/54146 * sbitmap.h (SBITMAP_SIZE): New macro. * ira.c (init_live_subregs): Take live_subregs_used as a bitmap. (build_insn_chain): Make live_subregs_used a bitmap. Use SBITMAP_SIZE to ignore the paradoxical bytes of subregs. Use sbitmap_free to free the live_subreg sbitmaps. * tree-ssa-loop-manip.c (loop_renamer_obstack): New static obstack for all bitmaps used for rewriting into loop-closed SSA form. (add_exit_phis_var): Allocate the def bitmap on it. Clear the livein bitmap at the end to release a lot of memory. (add_exit_phis): Allocate the exits bitmap on the new obstack. (get_loops_exits): Allocate the exits bitmap on the new obstack. (find_uses_to_rename_use): Allocate a use_blocks bitmap if ver is seen for the first time. (find_uses_to_rename): Add "???" for why the whole function must be re-scanned if changed_bbs is empty. (rewrite_into_loop_closed_ssa): Allocate bitmaps on the new obstack. Use XNEWVEC to allocate the use_blocks array. Initialize the new obstack, and free it at the end. Remove loop over all SSA names. (check_loop_closed_ssa_stmt): Look only at SSA_OP_USE operands. --- gcc-4.7-20120825/gcc/Makefile.in.~1~ 2012-08-06 16:34:27.000000000 +0200 +++ gcc-4.7-20120825/gcc/Makefile.in 2012-09-01 14:35:11.000000000 +0200 @@ -3417,7 +3417,7 @@ regrename.o : regrename.c $(CONFIG_H) $( ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \ $(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \ - $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h $(TIMEVAR_H) \ + $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h pointer-set.h $(TIMEVAR_H) \ $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) params.o : params.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(COMMON_TARGET_H) \ $(PARAMS_H) $(DIAGNOSTIC_CORE_H) --- gcc-4.7-20120825/gcc/cfgexpand.c.~1~ 2012-01-26 16:50:33.000000000 +0100 +++ gcc-4.7-20120825/gcc/cfgexpand.c 2012-09-01 14:35:11.000000000 +0200 @@ -186,6 +186,10 @@ static size_t stack_vars_alloc; static size_t stack_vars_num; static struct pointer_map_t *decl_to_stack_part; +/* Conflict bitmaps go on this obstack. This allows us to destroy + all of them in one big sweep. */ +static bitmap_obstack stack_var_bitmap_obstack; + /* An array of indices such that stack_vars[stack_vars_sorted[i]].size is non-decreasing. */ static size_t *stack_vars_sorted; @@ -300,9 +304,9 @@ add_stack_var_conflict (size_t x, size_t struct stack_var *a = &stack_vars[x]; struct stack_var *b = &stack_vars[y]; if (!a->conflicts) - a->conflicts = BITMAP_ALLOC (NULL); + a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); if (!b->conflicts) - b->conflicts = BITMAP_ALLOC (NULL); + b->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); bitmap_set_bit (a->conflicts, y); bitmap_set_bit (b->conflicts, x); } @@ -494,10 +498,10 @@ add_scope_conflicts_1 (basic_block bb, b unsigned i; EXECUTE_IF_SET_IN_BITMAP (work, 0, i, bi) { - unsigned j; - bitmap_iterator bj; - EXECUTE_IF_SET_IN_BITMAP (work, i + 1, j, bj) - add_stack_var_conflict (i, j); + struct stack_var *a = &stack_vars[i]; + if (!a->conflicts) + a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); + bitmap_ior_into (a->conflicts, work); } visit = visit_conflict; } @@ -515,6 +519,8 @@ add_scope_conflicts (void) basic_block bb; bool changed; bitmap work = BITMAP_ALLOC (NULL); + int *rpo; + int n_bbs; /* We approximate the live range of a stack variable by taking the first mention of its name as starting point(s), and by the end-of-scope @@ -527,15 +533,21 @@ add_scope_conflicts (void) We then do a mostly classical bitmap liveness algorithm. */ FOR_ALL_BB (bb) - bb->aux = BITMAP_ALLOC (NULL); + bb->aux = BITMAP_ALLOC (&stack_var_bitmap_obstack); + + rpo = XNEWVEC (int, last_basic_block); + n_bbs = pre_and_rev_post_order_compute (NULL, rpo, false); changed = true; while (changed) { + int i; changed = false; - FOR_EACH_BB (bb) + for (i = 0; i < n_bbs; i++) { - bitmap active = (bitmap)bb->aux; + bitmap active; + bb = BASIC_BLOCK (rpo[i]); + active = (bitmap)bb->aux; add_scope_conflicts_1 (bb, work, false); if (bitmap_ior_into (active, work)) changed = true; @@ -545,6 +557,7 @@ add_scope_conflicts (void) FOR_EACH_BB (bb) add_scope_conflicts_1 (bb, work, true); + free (rpo); BITMAP_FREE (work); FOR_ALL_BB (bb) BITMAP_FREE (bb->aux); @@ -710,7 +723,7 @@ update_alias_info_with_stack_vars (void) { unsigned i; struct pointer_set_t *visited = pointer_set_create (); - bitmap temp = BITMAP_ALLOC (NULL); + bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack); for (i = 1; i < num_ssa_names; i++) { @@ -1415,7 +1428,7 @@ add_stack_protection_conflicts (void) for (i = 0; i < n; ++i) { unsigned char ph_i = phase[i]; - for (j = 0; j < i; ++j) + for (j = i + 1; j < n; ++j) if (ph_i != phase[j]) add_stack_var_conflict (i, j); } @@ -1440,14 +1453,11 @@ create_stack_guard (void) static void init_vars_expansion (void) { - tree t; - unsigned ix; - /* Set TREE_USED on all variables in the local_decls. */ - FOR_EACH_LOCAL_DECL (cfun, ix, t) - TREE_USED (t) = 1; + /* Conflict bitmaps, and a few related temporary bitmaps, go here. */ + bitmap_obstack_initialize (&stack_var_bitmap_obstack); - /* Clear TREE_USED on all variables associated with a block scope. */ - clear_tree_used (DECL_INITIAL (current_function_decl)); + /* A map from decl to stack partition. */ + decl_to_stack_part = pointer_map_create (); /* Initialize local stack smashing state. */ has_protected_decls = false; @@ -1458,12 +1468,13 @@ init_vars_expansion (void) static void fini_vars_expansion (void) { - size_t i, n = stack_vars_num; - for (i = 0; i < n; i++) - BITMAP_FREE (stack_vars[i].conflicts); - XDELETEVEC (stack_vars); - XDELETEVEC (stack_vars_sorted); + bitmap_obstack_release (&stack_var_bitmap_obstack); + if (stack_vars) + XDELETEVEC (stack_vars); + if (stack_vars_sorted) + XDELETEVEC (stack_vars_sorted); stack_vars = NULL; + stack_vars_sorted = NULL; stack_vars_alloc = stack_vars_num = 0; pointer_map_destroy (decl_to_stack_part); decl_to_stack_part = NULL; @@ -1490,6 +1501,8 @@ estimated_stack_frame_size (struct cgrap current_function_decl = node->decl; push_cfun (fn); + init_vars_expansion (); + gcc_checking_assert (gimple_referenced_vars (fn)); FOR_EACH_REFERENCED_VAR (fn, var, rvi) size += expand_one_var (var, true, false); @@ -1501,8 +1514,9 @@ estimated_stack_frame_size (struct cgrap for (i = 0; i < stack_vars_num; ++i) stack_vars_sorted[i] = i; size += account_stack_vars (); - fini_vars_expansion (); } + + fini_vars_expansion (); pop_cfun (); current_function_decl = old_cur_fun_decl; return size; @@ -1525,6 +1539,12 @@ expand_used_vars (void) frame_phase = off ? align - off : 0; } + /* Set TREE_USED on all variables in the local_decls. */ + FOR_EACH_LOCAL_DECL (cfun, i, var) + TREE_USED (var) = 1; + /* Clear TREE_USED on all variables associated with a block scope. */ + clear_tree_used (DECL_INITIAL (current_function_decl)); + init_vars_expansion (); for (i = 0; i < SA.map->num_partitions; i++) @@ -1665,10 +1685,10 @@ expand_used_vars (void) } expand_stack_vars (NULL); - - fini_vars_expansion (); } + fini_vars_expansion (); + /* If there were any artificial non-ignored vars without rtl found earlier, see if deferred stack allocation hasn't assigned rtl to them. */ --- gcc-4.7-20120825/gcc/df-problems.c.~1~ 2012-07-13 19:21:41.000000000 +0200 +++ gcc-4.7-20120825/gcc/df-problems.c 2012-09-01 14:35:11.000000000 +0200 @@ -1229,7 +1229,7 @@ df_lr_add_problem (void) df_add_problem (&problem_LR); /* These will be initialized when df_scan_blocks processes each block. */ - df_lr->out_of_date_transfer_functions = BITMAP_ALLOC (NULL); + df_lr->out_of_date_transfer_functions = BITMAP_ALLOC (&df_bitmap_obstack); } @@ -1758,7 +1758,7 @@ df_live_add_problem (void) df_add_problem (&problem_LIVE); /* These will be initialized when df_scan_blocks processes each block. */ - df_live->out_of_date_transfer_functions = BITMAP_ALLOC (NULL); + df_live->out_of_date_transfer_functions = BITMAP_ALLOC (&df_bitmap_obstack); } @@ -2284,7 +2284,7 @@ df_chain_add_problem (unsigned int chain { df_add_problem (&problem_CHAIN); df_chain->local_flags = chain_flags; - df_chain->out_of_date_transfer_functions = BITMAP_ALLOC (NULL); + df_chain->out_of_date_transfer_functions = BITMAP_ALLOC (&df_bitmap_obstack); } #undef df_chain_problem_p @@ -2663,7 +2663,7 @@ df_word_lr_add_problem (void) df_add_problem (&problem_WORD_LR); /* These will be initialized when df_scan_blocks processes each block. */ - df_word_lr->out_of_date_transfer_functions = BITMAP_ALLOC (NULL); + df_word_lr->out_of_date_transfer_functions = BITMAP_ALLOC (&df_bitmap_obstack); } --- gcc-4.7-20120825/gcc/dse.c.~1~ 2012-01-24 20:03:33.000000000 +0100 +++ gcc-4.7-20120825/gcc/dse.c 2012-09-01 14:35:11.000000000 +0200 @@ -202,8 +202,21 @@ along with GCC; see the file COPYING3. that really have constant offsets this size. */ #define MAX_OFFSET (64 * 1024) +/* Obstack for the DSE dataflow bitmaps. We don't want to put these + on the default obstack because these bitmaps can grow quite large + (~2GB for the small (!) test case of PR54146) and we'll hold on to + all that memory until the end of the compiler run. + As a bonus, delete_tree_live_info can destroy all the bitmaps by just + releasing the whole obstack. */ +static bitmap_obstack dse_bitmap_obstack; + +/* Obstack for other data. As for above: Kinda nice to be able to + throw it all away at the end in one big sweep. */ +static struct obstack dse_obstack; +/* Scratch bitmap for cselib's cselib_expand_value_rtx. */ static bitmap scratch = NULL; + struct insn_info; /* This structure holds information about a candidate store. */ @@ -710,13 +723,13 @@ get_group_info (rtx base) (group_info_t) pool_alloc (rtx_group_info_pool); memset (gi, 0, sizeof (struct group_info)); gi->id = rtx_group_next_id++; - gi->store1_n = BITMAP_ALLOC (NULL); - gi->store1_p = BITMAP_ALLOC (NULL); - gi->store2_n = BITMAP_ALLOC (NULL); - gi->store2_p = BITMAP_ALLOC (NULL); - gi->escaped_p = BITMAP_ALLOC (NULL); - gi->escaped_n = BITMAP_ALLOC (NULL); - gi->group_kill = BITMAP_ALLOC (NULL); + gi->store1_n = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->store1_p = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->store2_n = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->store2_p = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->escaped_p = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->escaped_n = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->group_kill = BITMAP_ALLOC (&dse_bitmap_obstack); gi->process_globally = false; gi->offset_map_size_n = 0; gi->offset_map_size_p = 0; @@ -734,13 +747,13 @@ get_group_info (rtx base) gi->id = rtx_group_next_id++; gi->base_mem = gen_rtx_MEM (BLKmode, base); gi->canon_base_addr = canon_rtx (base); - gi->store1_n = BITMAP_ALLOC (NULL); - gi->store1_p = BITMAP_ALLOC (NULL); - gi->store2_n = BITMAP_ALLOC (NULL); - gi->store2_p = BITMAP_ALLOC (NULL); - gi->escaped_p = BITMAP_ALLOC (NULL); - gi->escaped_n = BITMAP_ALLOC (NULL); - gi->group_kill = BITMAP_ALLOC (NULL); + gi->store1_n = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->store1_p = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->store2_n = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->store2_p = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->escaped_p = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->escaped_n = BITMAP_ALLOC (&dse_bitmap_obstack); + gi->group_kill = BITMAP_ALLOC (&dse_bitmap_obstack); gi->process_globally = false; gi->frame_related = (base == frame_pointer_rtx) || (base == hard_frame_pointer_rtx); @@ -764,8 +777,11 @@ dse_step0 (void) globally_deleted = 0; spill_deleted = 0; - scratch = BITMAP_ALLOC (NULL); - kill_on_calls = BITMAP_ALLOC (NULL); + bitmap_obstack_initialize (&dse_bitmap_obstack); + gcc_obstack_init (&dse_obstack); + + scratch = BITMAP_ALLOC (®_obstack); + kill_on_calls = BITMAP_ALLOC (&dse_bitmap_obstack); rtx_store_info_pool = create_alloc_pool ("rtx_store_info_pool", @@ -789,7 +805,7 @@ dse_step0 (void) rtx_group_table = htab_create (11, invariant_group_base_hash, invariant_group_base_eq, NULL); - bb_table = XCNEWVEC (bb_info_t, last_basic_block); + bb_table = XNEWVEC (bb_info_t, last_basic_block); rtx_group_next_id = 0; stores_off_frame_dead_at_return = !cfun->stdarg; @@ -1724,7 +1740,7 @@ record_store (rtx body, bb_info_t bb_inf { store_info->is_large = true; store_info->positions_needed.large.count = 0; - store_info->positions_needed.large.bmap = BITMAP_ALLOC (NULL); + store_info->positions_needed.large.bmap = BITMAP_ALLOC (&dse_bitmap_obstack); } else { @@ -2050,7 +2066,7 @@ replace_read (store_info_t store_info, i live at this point. For instance, this can happen if one of the insns sets the CC and the CC happened to be live at that point. This does occasionally happen, see PR 37922. */ - bitmap regs_set = BITMAP_ALLOC (NULL); + bitmap regs_set = BITMAP_ALLOC (®_obstack); for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn)) note_stores (PATTERN (this_insn), look_for_hardregs, regs_set); @@ -2748,7 +2764,7 @@ static void dse_step1 (void) { basic_block bb; - bitmap regs_live = BITMAP_ALLOC (NULL); + bitmap regs_live = BITMAP_ALLOC (®_obstack); cselib_init (0); all_blocks = BITMAP_ALLOC (NULL); @@ -2936,9 +2952,11 @@ dse_step2_init (void) } group->offset_map_size_n++; - group->offset_map_n = XNEWVEC (int, group->offset_map_size_n); + group->offset_map_n = XOBNEWVEC (&dse_obstack, int, + group->offset_map_size_n); group->offset_map_size_p++; - group->offset_map_p = XNEWVEC (int, group->offset_map_size_p); + group->offset_map_p = XOBNEWVEC (&dse_obstack, int, + group->offset_map_size_p); group->process_globally = false; if (dump_file) { @@ -3370,7 +3388,7 @@ dse_step3_scan (bool for_spills, basic_b if (bb_info->kill) bitmap_clear (bb_info->kill); else - bb_info->kill = BITMAP_ALLOC (NULL); + bb_info->kill = BITMAP_ALLOC (&dse_bitmap_obstack); } else if (bb_info->kill) @@ -3463,7 +3481,7 @@ dse_step3 (bool for_spills) if (bb_info->gen) bitmap_clear (bb_info->gen); else - bb_info->gen = BITMAP_ALLOC (NULL); + bb_info->gen = BITMAP_ALLOC (&dse_bitmap_obstack); if (bb->index == ENTRY_BLOCK) ; @@ -3495,13 +3513,13 @@ dse_step3 (bool for_spills) unsigned int j; group_info_t group; - all_ones = BITMAP_ALLOC (NULL); + all_ones = BITMAP_ALLOC (&dse_bitmap_obstack); FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, j, group) bitmap_ior_into (all_ones, group->group_kill); } if (!bb_info->out) { - bb_info->out = BITMAP_ALLOC (NULL); + bb_info->out = BITMAP_ALLOC (&dse_bitmap_obstack); bitmap_copy (bb_info->out, all_ones); } } @@ -3537,7 +3555,7 @@ dse_confluence_0 (basic_block bb) if (!bb_info->out) { - bb_info->out = BITMAP_ALLOC (NULL); + bb_info->out = BITMAP_ALLOC (&dse_bitmap_obstack); bitmap_copy (bb_info->out, bb_table[EXIT_BLOCK]->gen); } } @@ -3558,7 +3576,7 @@ dse_confluence_n (edge e) bitmap_and_into (src_info->out, dest_info->in); else { - src_info->out = BITMAP_ALLOC (NULL); + src_info->out = BITMAP_ALLOC (&dse_bitmap_obstack); bitmap_copy (src_info->out, dest_info->in); } } @@ -3597,7 +3615,7 @@ dse_transfer_function (int bb_index) bb_info->out, bb_info->kill); else { - bb_info->in = BITMAP_ALLOC (NULL); + bb_info->in = BITMAP_ALLOC (&dse_bitmap_obstack); bitmap_ior_and_compl (bb_info->in, bb_info->gen, bb_info->out, bb_info->kill); return true; @@ -3615,7 +3633,7 @@ dse_transfer_function (int bb_index) return false; else { - bb_info->in = BITMAP_ALLOC (NULL); + bb_info->in = BITMAP_ALLOC (&dse_bitmap_obstack); bitmap_copy (bb_info->in, bb_info->gen); return true; } @@ -3895,37 +3913,10 @@ dse_step6 (void) ----------------------------------------------------------------------------*/ static void -dse_step7 (bool global_done) +dse_step7 (void) { - unsigned int i; - group_info_t group; - basic_block bb; - - FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group) - { - free (group->offset_map_n); - free (group->offset_map_p); - BITMAP_FREE (group->store1_n); - BITMAP_FREE (group->store1_p); - BITMAP_FREE (group->store2_n); - BITMAP_FREE (group->store2_p); - BITMAP_FREE (group->escaped_n); - BITMAP_FREE (group->escaped_p); - BITMAP_FREE (group->group_kill); - } - - if (global_done) - FOR_ALL_BB (bb) - { - bb_info_t bb_info = bb_table[bb->index]; - BITMAP_FREE (bb_info->gen); - if (bb_info->kill) - BITMAP_FREE (bb_info->kill); - if (bb_info->in) - BITMAP_FREE (bb_info->in); - if (bb_info->out) - BITMAP_FREE (bb_info->out); - } + bitmap_obstack_release (&dse_bitmap_obstack); + obstack_free (&dse_obstack, NULL); if (clear_alias_sets) { @@ -3941,7 +3932,6 @@ dse_step7 (bool global_done) VEC_free (group_info_t, heap, rtx_group_vec); BITMAP_FREE (all_blocks); BITMAP_FREE (scratch); - BITMAP_FREE (kill_on_calls); free_alloc_pool (rtx_store_info_pool); free_alloc_pool (read_info_pool); @@ -4006,7 +3996,7 @@ rest_of_handle_dse (void) } dse_step6 (); - dse_step7 (did_global); + dse_step7 (); if (dump_file) fprintf (dump_file, "dse: local deletions = %d, global deletions = %d, spill deletions = %d\n", --- gcc-4.7-20120825/gcc/ifcvt.c.~1~ 2012-02-27 15:30:44.000000000 +0100 +++ gcc-4.7-20120825/gcc/ifcvt.c 2012-09-01 14:35:11.000000000 +0200 @@ -44,6 +44,7 @@ #include "tree-pass.h" #include "df.h" #include "vec.h" +#include "pointer-set.h" #include "vecprim.h" #include "dbgcnt.h" @@ -2689,12 +2690,14 @@ noce_process_if_block (struct noce_if_in /* Check whether a block is suitable for conditional move conversion. Every insn must be a simple set of a register to a constant or a - register. For each assignment, store the value in the array VALS, - indexed by register number, then store the register number in - REGS. COND is the condition we will test. */ + register. For each assignment, store the value in the pointer map + VALS, keyed indexed by register pointer, then store the register + pointer in REGS. COND is the condition we will test. */ static int -check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs, +check_cond_move_block (basic_block bb, + struct pointer_map_t *vals, + VEC (rtx, heap) **regs, rtx cond) { rtx insn; @@ -2708,6 +2711,7 @@ check_cond_move_block (basic_block bb, r FOR_BB_INSNS (bb, insn) { rtx set, dest, src; + void **slot; if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn)) continue; @@ -2734,14 +2738,14 @@ check_cond_move_block (basic_block bb, r /* Don't try to handle this if the source register was modified earlier in the block. */ if ((REG_P (src) - && vals[REGNO (src)] != NULL) + && pointer_map_contains (vals, src)) || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src)) - && vals[REGNO (SUBREG_REG (src))] != NULL)) + && pointer_map_contains (vals, SUBREG_REG (src)))) return FALSE; /* Don't try to handle this if the destination register was modified earlier in the block. */ - if (vals[REGNO (dest)] != NULL) + if (pointer_map_contains (vals, dest)) return FALSE; /* Don't try to handle this if the condition uses the @@ -2755,17 +2759,18 @@ check_cond_move_block (basic_block bb, r && modified_between_p (src, insn, NEXT_INSN (BB_END (bb)))) return FALSE; - vals[REGNO (dest)] = src; + slot = pointer_map_insert (vals, (void *) dest); + *slot = (void *) src; - VEC_safe_push (int, heap, *regs, REGNO (dest)); + VEC_safe_push (rtx, heap, *regs, dest); } return TRUE; } /* Given a basic block BB suitable for conditional move conversion, - a condition COND, and arrays THEN_VALS and ELSE_VALS containing the - register values depending on COND, emit the insns in the block as + a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing + the register values depending on COND, emit the insns in the block as conditional moves. If ELSE_BLOCK is true, THEN_BB was already processed. The caller has started a sequence for the conversion. Return true if successful, false if something goes wrong. */ @@ -2773,7 +2778,8 @@ check_cond_move_block (basic_block bb, r static bool cond_move_convert_if_block (struct noce_if_info *if_infop, basic_block bb, rtx cond, - rtx *then_vals, rtx *else_vals, + struct pointer_map_t *then_vals, + struct pointer_map_t *else_vals, bool else_block_p) { enum rtx_code code; @@ -2786,7 +2792,7 @@ cond_move_convert_if_block (struct noce_ FOR_BB_INSNS (bb, insn) { rtx set, target, dest, t, e; - unsigned int regno; + void **then_slot, **else_slot; /* ??? Maybe emit conditional debug insn? */ if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn)) @@ -2795,10 +2801,11 @@ cond_move_convert_if_block (struct noce_ gcc_assert (set && REG_P (SET_DEST (set))); dest = SET_DEST (set); - regno = REGNO (dest); - t = then_vals[regno]; - e = else_vals[regno]; + then_slot = pointer_map_contains (then_vals, dest); + else_slot = pointer_map_contains (else_vals, dest); + t = then_slot ? (rtx) *then_slot : NULL_RTX; + e = else_slot ? (rtx) *else_slot : NULL_RTX; if (else_block_p) { @@ -2842,31 +2849,25 @@ cond_move_process_if_block (struct noce_ rtx jump = if_info->jump; rtx cond = if_info->cond; rtx seq, loc_insn; - int max_reg, size, c, reg; - rtx *then_vals; - rtx *else_vals; - VEC (int, heap) *then_regs = NULL; - VEC (int, heap) *else_regs = NULL; + rtx reg; + int c; + struct pointer_map_t *then_vals; + struct pointer_map_t *else_vals; + VEC (rtx, heap) *then_regs = NULL; + VEC (rtx, heap) *else_regs = NULL; unsigned int i; + int success_p = FALSE; /* Build a mapping for each block to the value used for each register. */ - max_reg = max_reg_num (); - size = (max_reg + 1) * sizeof (rtx); - then_vals = (rtx *) alloca (size); - else_vals = (rtx *) alloca (size); - memset (then_vals, 0, size); - memset (else_vals, 0, size); + then_vals = pointer_map_create (); + else_vals = pointer_map_create (); /* Make sure the blocks are suitable. */ if (!check_cond_move_block (then_bb, then_vals, &then_regs, cond) || (else_bb && !check_cond_move_block (else_bb, else_vals, &else_regs, cond))) - { - VEC_free (int, heap, then_regs); - VEC_free (int, heap, else_regs); - return FALSE; - } + goto done; /* Make sure the blocks can be used together. If the same register is set in both blocks, and is not set to a constant in both @@ -2875,41 +2876,38 @@ cond_move_process_if_block (struct noce_ source register does not change after the assignment. Also count the number of registers set in only one of the blocks. */ c = 0; - FOR_EACH_VEC_ELT (int, then_regs, i, reg) + FOR_EACH_VEC_ELT (rtx, then_regs, i, reg) { - if (!then_vals[reg] && !else_vals[reg]) - continue; + void **then_slot = pointer_map_contains (then_vals, reg); + void **else_slot = pointer_map_contains (else_vals, reg); - if (!else_vals[reg]) + gcc_checking_assert (then_slot); + if (!else_slot) ++c; else { - if (!CONSTANT_P (then_vals[reg]) - && !CONSTANT_P (else_vals[reg]) - && !rtx_equal_p (then_vals[reg], else_vals[reg])) - { - VEC_free (int, heap, then_regs); - VEC_free (int, heap, else_regs); - return FALSE; - } + rtx then_val = (rtx) *then_slot; + rtx else_val = (rtx) *else_slot; + if (!CONSTANT_P (then_val) && !CONSTANT_P (else_val) + && !rtx_equal_p (then_val, else_val)) + goto done; } } /* Finish off c for MAX_CONDITIONAL_EXECUTE. */ - FOR_EACH_VEC_ELT (int, else_regs, i, reg) - if (!then_vals[reg]) - ++c; + FOR_EACH_VEC_ELT (rtx, else_regs, i, reg) + { + gcc_checking_assert (pointer_map_contains (else_vals, reg)); + if (!pointer_map_contains (then_vals, reg)) + ++c; + } /* Make sure it is reasonable to convert this block. What matters is the number of assignments currently made in only one of the branches, since if we convert we are going to always execute them. */ if (c > MAX_CONDITIONAL_EXECUTE) - { - VEC_free (int, heap, then_regs); - VEC_free (int, heap, else_regs); - return FALSE; - } + goto done; /* Try to emit the conditional moves. First do the then block, then do anything left in the else blocks. */ @@ -2921,17 +2919,11 @@ cond_move_process_if_block (struct noce_ then_vals, else_vals, true))) { end_sequence (); - VEC_free (int, heap, then_regs); - VEC_free (int, heap, else_regs); - return FALSE; + goto done; } seq = end_ifcvt_sequence (if_info); if (!seq) - { - VEC_free (int, heap, then_regs); - VEC_free (int, heap, else_regs); - return FALSE; - } + goto done; loc_insn = first_active_insn (then_bb); if (!loc_insn) @@ -2962,9 +2954,14 @@ cond_move_process_if_block (struct noce_ num_updated_if_blocks++; - VEC_free (int, heap, then_regs); - VEC_free (int, heap, else_regs); - return TRUE; + success_p = TRUE; + +done: + pointer_map_destroy (then_vals); + pointer_map_destroy (else_vals); + VEC_free (rtx, heap, then_regs); + VEC_free (rtx, heap, else_regs); + return success_p; } --- gcc-4.7-20120825/gcc/ira.c.~1~ 2012-02-22 00:27:59.000000000 +0100 +++ gcc-4.7-20120825/gcc/ira.c 2012-09-01 14:35:11.000000000 +0200 @@ -3213,7 +3213,7 @@ pseudo_for_reload_consideration_p (int r initialization. ALLOCNUM need not be the regno of REG. */ static void init_live_subregs (bool init_value, sbitmap *live_subregs, - int *live_subregs_used, int allocnum, rtx reg) + bitmap live_subregs_used, int allocnum, rtx reg) { unsigned int regno = REGNO (SUBREG_REG (reg)); int size = GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno])); @@ -3221,10 +3221,10 @@ init_live_subregs (bool init_value, sbit gcc_assert (size > 0); /* Been there, done that. */ - if (live_subregs_used[allocnum]) + if (bitmap_bit_p (live_subregs_used, allocnum)) return; - /* Create a new one with zeros. */ + /* Create a new one. */ if (live_subregs[allocnum] == NULL) live_subregs[allocnum] = sbitmap_alloc (size); @@ -3235,8 +3235,7 @@ init_live_subregs (bool init_value, sbit else sbitmap_zero (live_subregs[allocnum]); - /* Set the number of bits that we really want. */ - live_subregs_used[allocnum] = size; + bitmap_set_bit (live_subregs_used, allocnum); } /* Walk the insns of the current function and build reload_insn_chain, @@ -3255,11 +3254,11 @@ build_insn_chain (void) which hardregs are live in multiword pseudos. live_subregs and live_subregs_used are indexed by pseudo number. The live_subreg entry for a particular pseudo is only used if the corresponding - element is non zero in live_subregs_used. The value in - live_subregs_used is number of bytes that the pseudo can + element is non zero in live_subregs_used. The sbitmap size of + live_subreg[allocno] is number of bytes that the pseudo can occupy. */ sbitmap *live_subregs = XCNEWVEC (sbitmap, max_regno); - int *live_subregs_used = XNEWVEC (int, max_regno); + bitmap live_subregs_used = BITMAP_ALLOC (NULL); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (eliminable_regset, i)) @@ -3270,7 +3269,7 @@ build_insn_chain (void) rtx insn; CLEAR_REG_SET (live_relevant_regs); - memset (live_subregs_used, 0, max_regno * sizeof (int)); + bitmap_clear (live_subregs_used); EXECUTE_IF_SET_IN_BITMAP (DF_LR_OUT (bb), 0, i, bi) { @@ -3355,8 +3354,8 @@ build_insn_chain (void) } /* Ignore the paradoxical bits. */ - if ((int)last > live_subregs_used[regno]) - last = live_subregs_used[regno]; + if (last > SBITMAP_SIZE (live_subregs[regno])) + last = SBITMAP_SIZE (live_subregs[regno]); while (start < last) { @@ -3366,7 +3365,7 @@ build_insn_chain (void) if (sbitmap_empty_p (live_subregs[regno])) { - live_subregs_used[regno] = 0; + bitmap_clear_bit (live_subregs_used, regno); bitmap_clear_bit (live_relevant_regs, regno); } else @@ -3384,8 +3383,8 @@ build_insn_chain (void) modeling the def as a killing def. */ if (!DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL)) { + bitmap_clear_bit (live_subregs_used, regno); bitmap_clear_bit (live_relevant_regs, regno); - live_subregs_used[regno] = 0; } } } @@ -3441,8 +3440,8 @@ build_insn_chain (void) live_subregs, live_subregs_used, regno, reg); /* Ignore the paradoxical bits. */ - if ((int)last > live_subregs_used[regno]) - last = live_subregs_used[regno]; + if (last > SBITMAP_SIZE (live_subregs[regno])) + last = SBITMAP_SIZE (live_subregs[regno]); while (start < last) { @@ -3455,7 +3454,7 @@ build_insn_chain (void) effectively saying do not use the subregs because we are reading the whole pseudo. */ - live_subregs_used[regno] = 0; + bitmap_clear_bit (live_subregs_used, regno); bitmap_set_bit (live_relevant_regs, regno); } } @@ -3498,14 +3497,14 @@ build_insn_chain (void) } } - for (i = 0; i < (unsigned int) max_regno; i++) - free (live_subregs[i]); - reload_insn_chain = c; *p = NULL; + for (i = 0; i < (unsigned int) max_regno; i++) + if (live_subregs[i] != NULL) + sbitmap_free (live_subregs[i]); free (live_subregs); - free (live_subregs_used); + BITMAP_FREE (live_subregs_used); BITMAP_FREE (live_relevant_regs); BITMAP_FREE (elim_regset); --- gcc-4.7-20120825/gcc/sbitmap.h.~1~ 2011-01-03 21:52:22.000000000 +0100 +++ gcc-4.7-20120825/gcc/sbitmap.h 2012-09-01 14:35:11.000000000 +0200 @@ -1,5 +1,5 @@ /* Simple bitmaps. - Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2010 + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GCC. @@ -48,6 +48,9 @@ struct simple_bitmap_def #define SBITMAP_SET_SIZE(N) (((N) + SBITMAP_ELT_BITS - 1) / SBITMAP_ELT_BITS) #define SBITMAP_SIZE_BYTES(BITMAP) ((BITMAP)->size * sizeof (SBITMAP_ELT_TYPE)) +/* Return the number of bits in BITMAP. */ +#define SBITMAP_SIZE(BITMAP) ((BITMAP)->n_bits) + /* Test if bit number bitno in the bitmap is set. */ #define TEST_BIT(BITMAP, BITNO) \ ((BITMAP)->elms [(BITNO) / SBITMAP_ELT_BITS] >> (BITNO) % SBITMAP_ELT_BITS & 1) --- gcc-4.7-20120825/gcc/tree-flow.h.~1~ 2012-02-24 10:40:27.000000000 +0100 +++ gcc-4.7-20120825/gcc/tree-flow.h 2012-09-01 14:35:11.000000000 +0200 @@ -577,7 +577,6 @@ bool name_mappings_registered_p (void); bool name_registered_for_update_p (tree); bitmap ssa_names_to_replace (void); void release_ssa_name_after_update_ssa (tree); -void compute_global_livein (bitmap, bitmap); void mark_sym_for_renaming (tree); void mark_set_for_renaming (bitmap); bool symbol_marked_for_renaming (tree); --- gcc-4.7-20120825/gcc/tree-into-ssa.c.~1~ 2012-02-24 10:39:38.000000000 +0100 +++ gcc-4.7-20120825/gcc/tree-into-ssa.c 2012-09-01 14:35:11.000000000 +0200 @@ -366,57 +366,6 @@ set_current_def (tree var, tree def) } -/* Compute global livein information given the set of blocks where - an object is locally live at the start of the block (LIVEIN) - and the set of blocks where the object is defined (DEF_BLOCKS). - - Note: This routine augments the existing local livein information - to include global livein (i.e., it modifies the underlying bitmap - for LIVEIN). */ - -void -compute_global_livein (bitmap livein ATTRIBUTE_UNUSED, bitmap def_blocks ATTRIBUTE_UNUSED) -{ - basic_block bb, *worklist, *tos; - unsigned i; - bitmap_iterator bi; - - tos = worklist - = (basic_block *) xmalloc (sizeof (basic_block) * (last_basic_block + 1)); - - EXECUTE_IF_SET_IN_BITMAP (livein, 0, i, bi) - *tos++ = BASIC_BLOCK (i); - - /* Iterate until the worklist is empty. */ - while (tos != worklist) - { - edge e; - edge_iterator ei; - - /* Pull a block off the worklist. */ - bb = *--tos; - - /* For each predecessor block. */ - FOR_EACH_EDGE (e, ei, bb->preds) - { - basic_block pred = e->src; - int pred_index = pred->index; - - /* None of this is necessary for the entry block. */ - if (pred != ENTRY_BLOCK_PTR - && ! bitmap_bit_p (livein, pred_index) - && ! bitmap_bit_p (def_blocks, pred_index)) - { - *tos++ = pred; - bitmap_set_bit (livein, pred_index); - } - } - } - - free (worklist); -} - - /* Cleans up the REWRITE_THIS_STMT and REGISTER_DEFS_IN_THIS_STMT flags for all statements in basic block BB. */ --- gcc-4.7-20120825/gcc/tree-ssa-live.c.~1~ 2012-08-06 16:34:27.000000000 +0200 +++ gcc-4.7-20120825/gcc/tree-ssa-live.c 2012-09-01 14:35:11.000000000 +0200 @@ -297,7 +297,7 @@ partition_view_fini (var_map map, bitmap /* Create a partition view which includes all the used partitions in MAP. If WANT_BASES is true, create the base variable map as well. */ -extern void +void partition_view_normal (var_map map, bool want_bases) { bitmap used; @@ -316,7 +316,7 @@ partition_view_normal (var_map map, bool the bitmap ONLY. If WANT_BASES is true, create the base variable map as well. */ -extern void +void partition_view_bitmap (var_map map, bitmap only, bool want_bases) { bitmap used; @@ -333,7 +333,6 @@ partition_view_bitmap (var_map map, bitm } partition_view_fini (map, new_partitions); - BITMAP_FREE (used); if (want_bases) var_map_base_init (map); else @@ -873,6 +872,12 @@ remove_unused_locals (void) timevar_pop (TV_REMOVE_UNUSED); } +/* Obstack for globale liveness info bitmaps. We don't want to put these + on the default obstack because these bitmaps can grow quite large and + we'll hold on to all that memory until the end of the compiler run. + As a bonus, delete_tree_live_info can destroy all the bitmaps by just + releasing the whole obstack. */ +static bitmap_obstack liveness_bitmap_obstack; /* Allocate and return a new live range information object base on MAP. */ @@ -880,24 +885,24 @@ static tree_live_info_p new_tree_live_info (var_map map) { tree_live_info_p live; - unsigned x; + basic_block bb; - live = (tree_live_info_p) xmalloc (sizeof (struct tree_live_info_d)); + live = XNEW (struct tree_live_info_d); live->map = map; live->num_blocks = last_basic_block; - live->livein = (bitmap *)xmalloc (last_basic_block * sizeof (bitmap)); - for (x = 0; x < (unsigned)last_basic_block; x++) - live->livein[x] = BITMAP_ALLOC (NULL); - - live->liveout = (bitmap *)xmalloc (last_basic_block * sizeof (bitmap)); - for (x = 0; x < (unsigned)last_basic_block; x++) - live->liveout[x] = BITMAP_ALLOC (NULL); + live->livein = XNEWVEC (bitmap_head, last_basic_block); + FOR_EACH_BB (bb) + bitmap_initialize (&live->livein[bb->index], &liveness_bitmap_obstack); + + live->liveout = XNEWVEC (bitmap_head, last_basic_block); + FOR_EACH_BB (bb) + bitmap_initialize (&live->liveout[bb->index], &liveness_bitmap_obstack); live->work_stack = XNEWVEC (int, last_basic_block); live->stack_top = live->work_stack; - live->global = BITMAP_ALLOC (NULL); + live->global = BITMAP_ALLOC (&liveness_bitmap_obstack); return live; } @@ -907,19 +912,10 @@ new_tree_live_info (var_map map) void delete_tree_live_info (tree_live_info_p live) { - int x; - - BITMAP_FREE (live->global); + bitmap_obstack_release (&liveness_bitmap_obstack); free (live->work_stack); - - for (x = live->num_blocks - 1; x >= 0; x--) - BITMAP_FREE (live->liveout[x]); free (live->liveout); - - for (x = live->num_blocks - 1; x >= 0; x--) - BITMAP_FREE (live->livein[x]); free (live->livein); - free (live); } @@ -952,7 +948,7 @@ loe_visit_block (tree_live_info_p live, predecessor block. This should be the live on entry vars to pred. Note that liveout is the DEFs in a block while live on entry is being calculated. */ - bitmap_and_compl (tmp, loe, live->liveout[pred_bb->index]); + bitmap_and_compl (tmp, loe, &live->liveout[pred_bb->index]); /* Add these bits to live-on-entry for the pred. if there are any changes, and pred_bb has been visited already, add it to the @@ -976,7 +972,7 @@ live_worklist (tree_live_info_p live) unsigned b; basic_block bb; sbitmap visited = sbitmap_alloc (last_basic_block + 1); - bitmap tmp = BITMAP_ALLOC (NULL); + bitmap tmp = BITMAP_ALLOC (&liveness_bitmap_obstack); sbitmap_zero (visited); @@ -1021,7 +1017,7 @@ set_var_live_on_entry (tree ssa_name, tr def_bb = gimple_bb (stmt); /* Mark defs in liveout bitmap temporarily. */ if (def_bb) - bitmap_set_bit (live->liveout[def_bb->index], p); + bitmap_set_bit (&live->liveout[def_bb->index], p); } else def_bb = ENTRY_BLOCK_PTR; @@ -1060,7 +1056,7 @@ set_var_live_on_entry (tree ssa_name, tr if (add_block) { global = true; - bitmap_set_bit (live->livein[add_block->index], p); + bitmap_set_bit (&live->livein[add_block->index], p); } } @@ -1082,7 +1078,7 @@ calculate_live_on_exit (tree_live_info_p /* live on entry calculations used liveout vectors for defs, clear them. */ FOR_EACH_BB (bb) - bitmap_clear (liveinfo->liveout[bb->index]); + bitmap_clear (&liveinfo->liveout[bb->index]); /* Set all the live-on-exit bits for uses in PHIs. */ FOR_EACH_BB (bb) @@ -1107,14 +1103,14 @@ calculate_live_on_exit (tree_live_info_p continue; e = gimple_phi_arg_edge (phi, i); if (e->src != ENTRY_BLOCK_PTR) - bitmap_set_bit (liveinfo->liveout[e->src->index], p); + bitmap_set_bit (&liveinfo->liveout[e->src->index], p); } } /* Add each successors live on entry to this bock live on exit. */ FOR_EACH_EDGE (e, ei, bb->succs) if (e->dest != EXIT_BLOCK_PTR) - bitmap_ior_into (liveinfo->liveout[bb->index], + bitmap_ior_into (&liveinfo->liveout[bb->index], live_on_entry (liveinfo, e->dest)); } } @@ -1130,6 +1126,7 @@ calculate_live_ranges (var_map map) unsigned i; tree_live_info_p live; + bitmap_obstack_initialize (&liveness_bitmap_obstack); live = new_tree_live_info (map); for (i = 0; i < num_var_partitions (map); i++) { @@ -1209,7 +1206,7 @@ dump_live_info (FILE *f, tree_live_info_ FOR_EACH_BB (bb) { fprintf (f, "\nLive on entry to BB%d : ", bb->index); - EXECUTE_IF_SET_IN_BITMAP (live->livein[bb->index], 0, i, bi) + EXECUTE_IF_SET_IN_BITMAP (&live->livein[bb->index], 0, i, bi) { print_generic_expr (f, partition_to_var (map, i), TDF_SLIM); fprintf (f, " "); @@ -1223,7 +1220,7 @@ dump_live_info (FILE *f, tree_live_info_ FOR_EACH_BB (bb) { fprintf (f, "\nLive on exit from BB%d : ", bb->index); - EXECUTE_IF_SET_IN_BITMAP (live->liveout[bb->index], 0, i, bi) + EXECUTE_IF_SET_IN_BITMAP (&live->liveout[bb->index], 0, i, bi) { print_generic_expr (f, partition_to_var (map, i), TDF_SLIM); fprintf (f, " "); --- gcc-4.7-20120825/gcc/tree-ssa-live.h.~1~ 2011-01-03 21:52:22.000000000 +0100 +++ gcc-4.7-20120825/gcc/tree-ssa-live.h 2012-09-01 14:35:11.000000000 +0200 @@ -239,8 +239,11 @@ typedef struct tree_live_info_d /* Bitmap indicating which partitions are global. */ bitmap global; - /* Bitmap of live on entry blocks for partition elements. */ - bitmap *livein; + /* Bitmaps of live on entry blocks for partition elements. */ + bitmap_head *livein; + + /* Bitmaps of what variables are live on exit for a basic blocks. */ + bitmap_head *liveout; /* Number of basic blocks when live on exit calculated. */ int num_blocks; @@ -250,9 +253,6 @@ typedef struct tree_live_info_d /* Top of workstack. */ int *stack_top; - - /* Bitmap of what variables are live on exit for a basic blocks. */ - bitmap *liveout; } *tree_live_info_p; @@ -286,7 +286,7 @@ live_on_entry (tree_live_info_p live, ba && bb != ENTRY_BLOCK_PTR && bb != EXIT_BLOCK_PTR); - return live->livein[bb->index]; + return &live->livein[bb->index]; } @@ -300,7 +300,7 @@ live_on_exit (tree_live_info_p live, bas && bb != ENTRY_BLOCK_PTR && bb != EXIT_BLOCK_PTR); - return live->liveout[bb->index]; + return &live->liveout[bb->index]; } @@ -319,9 +319,9 @@ live_var_map (tree_live_info_p live) static inline void live_merge_and_clear (tree_live_info_p live, int p1, int p2) { - gcc_checking_assert (live->livein[p1] && live->livein[p2]); - bitmap_ior_into (live->livein[p1], live->livein[p2]); - bitmap_zero (live->livein[p2]); + gcc_checking_assert (&live->livein[p1] && &live->livein[p2]); + bitmap_ior_into (&live->livein[p1], &live->livein[p2]); + bitmap_zero (&live->livein[p2]); } @@ -330,7 +330,7 @@ live_merge_and_clear (tree_live_info_p l static inline void make_live_on_entry (tree_live_info_p live, basic_block bb , int p) { - bitmap_set_bit (live->livein[bb->index], p); + bitmap_set_bit (&live->livein[bb->index], p); bitmap_set_bit (live->global, p); } --- gcc-4.7-20120825/gcc/tree-ssa-loop-im.c.~1~ 2012-08-21 15:34:19.000000000 +0200 +++ gcc-4.7-20120825/gcc/tree-ssa-loop-im.c 2012-09-01 14:35:11.000000000 +0200 @@ -187,6 +187,9 @@ static struct struct pointer_map_t *ttae_cache; } memory_accesses; +/* Obstack for the bitmaps in the above data structures. */ +static bitmap_obstack lim_bitmap_obstack; + static bool ref_indep_loop_p (struct loop *, mem_ref_p); /* Minimum cost of an expensive expression. */ @@ -1485,12 +1488,6 @@ memref_free (struct mem_ref *mem) unsigned i; mem_ref_locs_p accs; - BITMAP_FREE (mem->stored); - BITMAP_FREE (mem->indep_loop); - BITMAP_FREE (mem->dep_loop); - BITMAP_FREE (mem->indep_ref); - BITMAP_FREE (mem->dep_ref); - FOR_EACH_VEC_ELT (mem_ref_locs_p, mem->accesses_in_loop, i, accs) free_mem_ref_locs (accs); VEC_free (mem_ref_locs_p, heap, mem->accesses_in_loop); @@ -1508,11 +1505,11 @@ mem_ref_alloc (tree mem, unsigned hash, ref->mem = mem; ref->id = id; ref->hash = hash; - ref->stored = BITMAP_ALLOC (NULL); - ref->indep_loop = BITMAP_ALLOC (NULL); - ref->dep_loop = BITMAP_ALLOC (NULL); - ref->indep_ref = BITMAP_ALLOC (NULL); - ref->dep_ref = BITMAP_ALLOC (NULL); + ref->stored = BITMAP_ALLOC (&lim_bitmap_obstack); + ref->indep_loop = BITMAP_ALLOC (&lim_bitmap_obstack); + ref->dep_loop = BITMAP_ALLOC (&lim_bitmap_obstack); + ref->indep_ref = BITMAP_ALLOC (&lim_bitmap_obstack); + ref->dep_ref = BITMAP_ALLOC (&lim_bitmap_obstack); ref->accesses_in_loop = NULL; return ref; @@ -1732,11 +1729,11 @@ analyze_memory_references (void) for (i = 0; i < number_of_loops (); i++) { - empty = BITMAP_ALLOC (NULL); + empty = BITMAP_ALLOC (&lim_bitmap_obstack); VEC_quick_push (bitmap, memory_accesses.refs_in_loop, empty); - empty = BITMAP_ALLOC (NULL); + empty = BITMAP_ALLOC (&lim_bitmap_obstack); VEC_quick_push (bitmap, memory_accesses.all_refs_in_loop, empty); - empty = BITMAP_ALLOC (NULL); + empty = BITMAP_ALLOC (&lim_bitmap_obstack); VEC_quick_push (bitmap, memory_accesses.all_refs_stored_in_loop, empty); } @@ -2579,6 +2576,8 @@ tree_ssa_lim_initialize (void) struct loop *loop; basic_block bb; + bitmap_obstack_initialize (&lim_bitmap_obstack); + sbitmap_zero (contains_call); FOR_EACH_BB (bb) { @@ -2612,7 +2611,6 @@ tree_ssa_lim_finalize (void) { basic_block bb; unsigned i; - bitmap b; mem_ref_p ref; free_aux_for_edges (); @@ -2620,6 +2618,7 @@ tree_ssa_lim_finalize (void) FOR_EACH_BB (bb) SET_ALWAYS_EXECUTED_IN (bb, NULL); + bitmap_obstack_release (&lim_bitmap_obstack); pointer_map_destroy (lim_aux_data_map); htab_delete (memory_accesses.refs); @@ -2628,16 +2627,8 @@ tree_ssa_lim_finalize (void) memref_free (ref); VEC_free (mem_ref_p, heap, memory_accesses.refs_list); - FOR_EACH_VEC_ELT (bitmap, memory_accesses.refs_in_loop, i, b) - BITMAP_FREE (b); VEC_free (bitmap, heap, memory_accesses.refs_in_loop); - - FOR_EACH_VEC_ELT (bitmap, memory_accesses.all_refs_in_loop, i, b) - BITMAP_FREE (b); VEC_free (bitmap, heap, memory_accesses.all_refs_in_loop); - - FOR_EACH_VEC_ELT (bitmap, memory_accesses.all_refs_stored_in_loop, i, b) - BITMAP_FREE (b); VEC_free (bitmap, heap, memory_accesses.all_refs_stored_in_loop); if (memory_accesses.ttae_cache) --- gcc-4.7-20120825/gcc/tree-ssa-loop-manip.c.~1~ 2011-08-17 14:00:35.000000000 +0200 +++ gcc-4.7-20120825/gcc/tree-ssa-loop-manip.c 2012-09-01 14:35:11.000000000 +0200 @@ -31,12 +31,17 @@ along with GCC; see the file COPYING3. #include "timevar.h" #include "cfgloop.h" #include "tree-pass.h" +#include "gimple-pretty-print.h" #include "cfglayout.h" #include "tree-scalar-evolution.h" #include "params.h" #include "tree-inline.h" #include "langhooks.h" +/* All bitmaps for rewriting into loop-closed SSA go on this obstack, + so that we can free them all at once. */ +static bitmap_obstack loop_renamer_obstack; + /* Creates an induction variable with value BASE + STEP * iteration in LOOP. It is expected that neither BASE nor STEP are shared with other expressions (unless the sharing rules allow this). Use VAR as a base var_decl for it @@ -127,61 +132,190 @@ create_iv (tree base, tree step, tree va add_phi_arg (stmt, va, loop_latch_edge (loop), UNKNOWN_LOCATION); } -/* Add exit phis for the USE on EXIT. */ +/* Return the innermost superloop LOOP of USE_LOOP that is a superloop of + both DEF_LOOP and USE_LOOP. */ + +static inline struct loop * +find_sibling_superloop (struct loop *use_loop, struct loop *def_loop) +{ + unsigned ud = loop_depth (use_loop); + unsigned dd = loop_depth (def_loop); + gcc_assert (ud > 0 && dd > 0); + if (ud > dd) + use_loop = superloop_at_depth (use_loop, dd); + if (ud < dd) + def_loop = superloop_at_depth (def_loop, ud); + while (loop_outer (use_loop) != loop_outer (def_loop)) + { + use_loop = loop_outer (use_loop); + def_loop = loop_outer (def_loop); + gcc_assert (use_loop && def_loop); + } + return use_loop; +} + +/* DEF_BB is a basic block containing a DEF that needs rewriting into + loop-closed SSA form. USE_BLOCKS is the set of basic blocks containing + uses of DEF that "escape" from the loop containing DEF_BB (i.e. blocks in + USE_BLOCKS are dominated by DEF_BB but not in the loop father of DEF_B). + ALL_EXITS[I] is the set of all basic blocks that exit loop I. + + Compute the subset of LOOP_EXITS that exit the loop containing DEF_BB + or one of its loop fathers, in which DEF is live. This set is returned + in the bitmap LIVE_EXITS. + + Instead of computing the complete livein set of the def, we use the loop + nesting tree as a form of poor man's structure analysis. This greatly + speeds up the analysis, which is important because this function may be + called on all SSA names that need rewriting, one at a time. */ static void -add_exit_phis_edge (basic_block exit, tree use) +compute_live_loop_exits (bitmap live_exits, bitmap use_blocks, + bitmap *loop_exits, basic_block def_bb) { - gimple phi, def_stmt = SSA_NAME_DEF_STMT (use); - basic_block def_bb = gimple_bb (def_stmt); - struct loop *def_loop; + unsigned i; + bitmap_iterator bi; + VEC (basic_block, heap) *worklist; + struct loop *loop, *def_loop = def_bb->loop_father; + unsigned def_loop_depth = loop_depth (def_loop); + bitmap def_loop_exits; + + /* Normally the work list size is bounded by the number of basic + blocks in the largest loop. We don't know this number, but we + can be fairly sure that it will be relatively small. */ + worklist = VEC_alloc (basic_block, heap, MAX (8, n_basic_blocks / 128)); + + EXECUTE_IF_SET_IN_BITMAP (use_blocks, 0, i, bi) + { + basic_block use_bb = BASIC_BLOCK (i); + struct loop *use_loop = use_bb->loop_father; + gcc_checking_assert (def_loop != use_loop + && ! flow_loop_nested_p (def_loop, use_loop)); + if (! flow_loop_nested_p (use_loop, def_loop)) + use_bb = find_sibling_superloop (use_loop, def_loop)->header; + if (bitmap_set_bit (live_exits, use_bb->index)) + VEC_safe_push (basic_block, heap, worklist, use_bb); + } + + /* Iterate until the worklist is empty. */ + while (! VEC_empty (basic_block, worklist)) + { + edge e; + edge_iterator ei; + + /* Pull a block off the worklist. */ + basic_block bb = VEC_pop (basic_block, worklist); + + /* Make sure we have at least enough room in the work list + for all predecessors of this block. */ + VEC_reserve (basic_block, heap, worklist, EDGE_COUNT (bb->preds)); + + /* For each predecessor block. */ + FOR_EACH_EDGE (e, ei, bb->preds) + { + basic_block pred = e->src; + struct loop *pred_loop = pred->loop_father; + unsigned pred_loop_depth = loop_depth (pred_loop); + bool pred_visited; + + /* We should have met DEF_BB along the way. */ + gcc_assert (pred != ENTRY_BLOCK_PTR); + + if (pred_loop_depth >= def_loop_depth) + { + if (pred_loop_depth > def_loop_depth) + pred_loop = superloop_at_depth (pred_loop, def_loop_depth); + /* If we've reached DEF_LOOP, our train ends here. */ + if (pred_loop == def_loop) + continue; + } + else if (! flow_loop_nested_p (pred_loop, def_loop)) + pred = find_sibling_superloop (pred_loop, def_loop)->header; + + /* Add PRED to the LIVEIN set. PRED_VISITED is true if + we had already added PRED to LIVEIN before. */ + pred_visited = !bitmap_set_bit (live_exits, pred->index); + + /* If we have visited PRED before, don't add it to the worklist. + If BB dominates PRED, then we're probably looking at a loop. + We're only interested in looking up in the dominance tree + because DEF_BB dominates all the uses. */ + if (pred_visited || dominated_by_p (CDI_DOMINATORS, pred, bb)) + continue; + + VEC_quick_push (basic_block, worklist, pred); + } + } + VEC_free (basic_block, heap, worklist); + + def_loop_exits = BITMAP_ALLOC (&loop_renamer_obstack); + for (loop = def_loop; + loop != current_loops->tree_root; + loop = loop_outer (loop)) + bitmap_ior_into (def_loop_exits, loop_exits[loop->num]); + bitmap_and_into (live_exits, def_loop_exits); + BITMAP_FREE (def_loop_exits); +} + +/* Add a loop-closing PHI for VAR in basic block EXIT. */ + +static void +add_exit_phi (basic_block exit, tree var) +{ + gimple phi; edge e; edge_iterator ei; - /* Check that some of the edges entering the EXIT block exits a loop in - that USE is defined. */ +#ifdef ENABLE_CHECKING + /* Check that at least one of the edges entering the EXIT block exits + the loop, or a superloop of that loop, that VAR is defined in. */ + gimple def_stmt = SSA_NAME_DEF_STMT (var); + basic_block def_bb = gimple_bb (def_stmt); FOR_EACH_EDGE (e, ei, exit->preds) { - def_loop = find_common_loop (def_bb->loop_father, e->src->loop_father); - if (!flow_bb_inside_loop_p (def_loop, e->dest)) + struct loop *aloop = find_common_loop (def_bb->loop_father, + e->src->loop_father); + if (!flow_bb_inside_loop_p (aloop, e->dest)) break; } - if (!e) - return; + gcc_checking_assert (e); +#endif - phi = create_phi_node (use, exit); - create_new_def_for (gimple_phi_result (phi), phi, - gimple_phi_result_ptr (phi)); + phi = create_phi_node (var, exit); + create_new_def_for (var, phi, gimple_phi_result_ptr (phi)); FOR_EACH_EDGE (e, ei, exit->preds) - add_phi_arg (phi, use, e, UNKNOWN_LOCATION); + add_phi_arg (phi, var, e, UNKNOWN_LOCATION); + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, ";; Created LCSSA PHI: "); + print_gimple_stmt (dump_file, phi, 0, dump_flags); + } } /* Add exit phis for VAR that is used in LIVEIN. - Exits of the loops are stored in EXITS. */ + Exits of the loops are stored in LOOP_EXITS. */ static void -add_exit_phis_var (tree var, bitmap livein, bitmap exits) +add_exit_phis_var (tree var, bitmap use_blocks, bitmap *loop_exits) { - bitmap def; unsigned index; - basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (var)); bitmap_iterator bi; + basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (var)); + bitmap live_exits = BITMAP_ALLOC (&loop_renamer_obstack); - if (is_gimple_reg (var)) - bitmap_clear_bit (livein, def_bb->index); - else - bitmap_set_bit (livein, def_bb->index); + gcc_checking_assert (is_gimple_reg (var)); + gcc_checking_assert (! bitmap_bit_p (use_blocks, def_bb->index)); - def = BITMAP_ALLOC (NULL); - bitmap_set_bit (def, def_bb->index); - compute_global_livein (livein, def); - BITMAP_FREE (def); + compute_live_loop_exits (live_exits, use_blocks, loop_exits, def_bb); - EXECUTE_IF_AND_IN_BITMAP (exits, livein, 0, index, bi) + EXECUTE_IF_SET_IN_BITMAP (live_exits, 0, index, bi) { - add_exit_phis_edge (BASIC_BLOCK (index), var); + add_exit_phi (BASIC_BLOCK (index), var); } + + BITMAP_FREE (live_exits); } /* Add exit phis for the names marked in NAMES_TO_RENAME. @@ -189,7 +323,7 @@ add_exit_phis_var (tree var, bitmap live names are used are stored in USE_BLOCKS. */ static void -add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap loop_exits) +add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap *loop_exits) { unsigned i; bitmap_iterator bi; @@ -200,28 +334,24 @@ add_exit_phis (bitmap names_to_rename, b } } -/* Returns a bitmap of all loop exit edge targets. */ +/* Fill the array of bitmaps LOOP_EXITS with all loop exit edge targets. */ -static bitmap -get_loops_exits (void) +static void +get_loops_exits (bitmap *loop_exits) { - bitmap exits = BITMAP_ALLOC (NULL); - basic_block bb; + loop_iterator li; + struct loop *loop; + unsigned j; edge e; - edge_iterator ei; - FOR_EACH_BB (bb) + FOR_EACH_LOOP (li, loop, 0) { - FOR_EACH_EDGE (e, ei, bb->preds) - if (e->src != ENTRY_BLOCK_PTR - && !flow_bb_inside_loop_p (e->src->loop_father, bb)) - { - bitmap_set_bit (exits, bb->index); - break; - } + VEC(edge, heap) *exit_edges = get_loop_exit_edges (loop); + loop_exits[loop->num] = BITMAP_ALLOC (&loop_renamer_obstack); + FOR_EACH_VEC_ELT (edge, exit_edges, j, e) + bitmap_set_bit (loop_exits[loop->num], e->dest->index); + VEC_free (edge, heap, exit_edges); } - - return exits; } /* For USE in BB, if it is used outside of the loop it is defined in, @@ -258,11 +388,11 @@ find_uses_to_rename_use (basic_block bb, if (flow_bb_inside_loop_p (def_loop, bb)) return; - if (!use_blocks[ver]) - use_blocks[ver] = BITMAP_ALLOC (NULL); + /* If we're seeing VER for the first time, we still have to allocate + a bitmap for its uses. */ + if (bitmap_set_bit (need_phis, ver)) + use_blocks[ver] = BITMAP_ALLOC (&loop_renamer_obstack); bitmap_set_bit (use_blocks[ver], bb->index); - - bitmap_set_bit (need_phis, ver); } /* For uses in STMT, mark names that are used outside of the loop they are @@ -280,7 +410,7 @@ find_uses_to_rename_stmt (gimple stmt, b if (is_gimple_debug (stmt)) return; - FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES) + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE) find_uses_to_rename_use (bb, var, use_blocks, need_phis); } @@ -298,8 +428,12 @@ find_uses_to_rename_bb (basic_block bb, FOR_EACH_EDGE (e, ei, bb->succs) for (bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); gsi_next (&bsi)) - find_uses_to_rename_use (bb, PHI_ARG_DEF_FROM_EDGE (gsi_stmt (bsi), e), - use_blocks, need_phis); + { + gimple phi = gsi_stmt (bsi); + if (is_gimple_reg (gimple_phi_result (phi))) + find_uses_to_rename_use (bb, PHI_ARG_DEF_FROM_EDGE (phi, e), + use_blocks, need_phis); + } for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) find_uses_to_rename_stmt (gsi_stmt (bsi), use_blocks, need_phis); @@ -317,6 +451,7 @@ find_uses_to_rename (bitmap changed_bbs, unsigned index; bitmap_iterator bi; + /* ??? If CHANGED_BBS is empty we rewrite the whole function -- why? */ if (changed_bbs && !bitmap_empty_p (changed_bbs)) { EXECUTE_IF_SET_IN_BITMAP (changed_bbs, 0, index, bi) @@ -368,24 +503,31 @@ find_uses_to_rename (bitmap changed_bbs, void rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) { - bitmap loop_exits; + bitmap *loop_exits; bitmap *use_blocks; - unsigned i, old_num_ssa_names; bitmap names_to_rename; loops_state_set (LOOP_CLOSED_SSA); if (number_of_loops () <= 1) return; - loop_exits = get_loops_exits (); - names_to_rename = BITMAP_ALLOC (NULL); - /* If the pass has caused the SSA form to be out-of-date, update it now. */ update_ssa (update_flag); - old_num_ssa_names = num_ssa_names; - use_blocks = XCNEWVEC (bitmap, old_num_ssa_names); + bitmap_obstack_initialize (&loop_renamer_obstack); + + names_to_rename = BITMAP_ALLOC (&loop_renamer_obstack); + + /* An array of bitmaps where LOOP_EXITS[I] is the set of basic blocks + that are the destination of an edge exiting loop number I. */ + loop_exits = XNEWVEC (bitmap, number_of_loops ()); + get_loops_exits (loop_exits); + + /* Uses of names to rename. We don't have to initialize this array, + because we know that we will only have entries for the SSA names + in NAMES_TO_RENAME. */ + use_blocks = XCNEWVEC (bitmap, num_ssa_names); /* Find the uses outside loops. */ find_uses_to_rename (changed_bbs, use_blocks, names_to_rename); @@ -394,11 +536,9 @@ rewrite_into_loop_closed_ssa (bitmap cha rewrite. */ add_exit_phis (names_to_rename, use_blocks, loop_exits); - for (i = 0; i < old_num_ssa_names; i++) - BITMAP_FREE (use_blocks[i]); + bitmap_obstack_release (&loop_renamer_obstack); free (use_blocks); - BITMAP_FREE (loop_exits); - BITMAP_FREE (names_to_rename); + free (loop_exits); /* Fix up all the names found to be used outside their original loops. */ @@ -433,7 +573,7 @@ check_loop_closed_ssa_stmt (basic_block if (is_gimple_debug (stmt)) return; - FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES) + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE) check_loop_closed_ssa_use (bb, var); } --- gcc-4.7-20120825/gcc/tree-ssa-ter.c.~1~ 2011-02-04 16:50:51.000000000 +0100 +++ gcc-4.7-20120825/gcc/tree-ssa-ter.c 2012-09-01 14:35:11.000000000 +0200 @@ -173,6 +173,9 @@ typedef struct temp_expr_table_d /* Used to indicate a dependency on VDEFs. */ #define VIRTUAL_PARTITION(table) (table->virtual_partition) +/* A place for the many, many bitmaps we create. */ +static bitmap_obstack ter_bitmap_obstack; + #ifdef ENABLE_CHECKING extern void debug_ter (FILE *, temp_expr_table_p); #endif @@ -193,10 +196,10 @@ new_temp_expr_table (var_map map) t->expr_decl_uids = XCNEWVEC (bitmap, num_ssa_names + 1); t->kill_list = XCNEWVEC (bitmap, num_var_partitions (map) + 1); - t->partition_in_use = BITMAP_ALLOC (NULL); + t->partition_in_use = BITMAP_ALLOC (&ter_bitmap_obstack); t->virtual_partition = num_var_partitions (map); - t->new_replaceable_dependencies = BITMAP_ALLOC (NULL); + t->new_replaceable_dependencies = BITMAP_ALLOC (&ter_bitmap_obstack); t->replaceable_expressions = NULL; t->num_in_part = XCNEWVEC (int, num_var_partitions (map)); @@ -270,7 +273,7 @@ static inline void make_dependent_on_partition (temp_expr_table_p tab, int version, int p) { if (!tab->partition_dependencies[version]) - tab->partition_dependencies[version] = BITMAP_ALLOC (NULL); + tab->partition_dependencies[version] = BITMAP_ALLOC (&ter_bitmap_obstack); bitmap_set_bit (tab->partition_dependencies[version], p); } @@ -283,7 +286,7 @@ add_to_partition_kill_list (temp_expr_ta { if (!tab->kill_list[p]) { - tab->kill_list[p] = BITMAP_ALLOC (NULL); + tab->kill_list[p] = BITMAP_ALLOC (&ter_bitmap_obstack); bitmap_set_bit (tab->partition_in_use, p); } bitmap_set_bit (tab->kill_list[p], ver); @@ -331,7 +334,8 @@ add_dependence (temp_expr_table_p tab, i /* Rather than set partition_dependencies and in_use lists bit by bit, simply OR in the new_replaceable_dependencies bits. */ if (!tab->partition_dependencies[version]) - tab->partition_dependencies[version] = BITMAP_ALLOC (NULL); + tab->partition_dependencies[version] = + BITMAP_ALLOC (&ter_bitmap_obstack); bitmap_ior_into (tab->partition_dependencies[version], tab->new_replaceable_dependencies); bitmap_ior_into (tab->partition_in_use, @@ -500,7 +504,7 @@ process_replaceable (temp_expr_table_p t def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF); version = SSA_NAME_VERSION (def); basevar = SSA_NAME_VAR (def); - def_vars = BITMAP_ALLOC (NULL); + def_vars = BITMAP_ALLOC (&ter_bitmap_obstack); bitmap_set_bit (def_vars, DECL_UID (basevar)); @@ -578,7 +582,9 @@ mark_replaceable (temp_expr_table_p tab, finished_with_expr (tab, version, !more_replacing); - /* Set the replaceable expression. */ + /* Set the replaceable expression. + The bitmap for this "escapes" from this file so it's allocated + on the default obstack. */ if (!tab->replaceable_expressions) tab->replaceable_expressions = BITMAP_ALLOC (NULL); bitmap_set_bit (tab->replaceable_expressions, version); @@ -705,21 +711,22 @@ find_replaceable_in_bb (temp_expr_table_ NULL is returned by the function, otherwise an expression vector indexed by SSA_NAME version numbers. */ -extern bitmap +bitmap find_replaceable_exprs (var_map map) { basic_block bb; temp_expr_table_p table; bitmap ret; + bitmap_obstack_initialize (&ter_bitmap_obstack); table = new_temp_expr_table (map); FOR_EACH_BB (bb) { find_replaceable_in_bb (table, bb); gcc_checking_assert (bitmap_empty_p (table->partition_in_use)); } - ret = free_temp_expr_table (table); + bitmap_obstack_release (&ter_bitmap_obstack); return ret; }