diff options
Diffstat (limited to 'gcc/tree-ssanames.c')
-rw-r--r-- | gcc/tree-ssanames.c | 192 |
1 files changed, 164 insertions, 28 deletions
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 12235f6a902..096b75b10e0 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -114,6 +114,133 @@ ssanames_print_statistics (void) fprintf (stderr, "SSA_NAME nodes reused: %u\n", ssa_name_nodes_reused); } +/* Verify the state of the SSA_NAME lists. + + There must be no duplicates on the free list. + Every name on the free list must be marked as on the free list. + Any name on the free list must not appear in the IL. + No names can be leaked. */ + +DEBUG_FUNCTION void +verify_ssaname_freelists (struct function *fun) +{ + /* Do nothing if we are in RTL format. */ + basic_block bb; + FOR_EACH_BB_FN (bb, fun) + { + if (bb->flags & BB_RTL) + return; + } + + bitmap names_in_il = BITMAP_ALLOC (NULL); + + /* Walk the entire IL noting every SSA_NAME we see. */ + FOR_EACH_BB_FN (bb, fun) + { + tree t; + /* First note the result and arguments of PHI nodes. */ + for (gphi_iterator gsi = gsi_start_phis (bb); + !gsi_end_p (gsi); + gsi_next (&gsi)) + { + gphi *phi = gsi.phi (); + t = gimple_phi_result (phi); + bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t)); + + for (unsigned int i = 0; i < gimple_phi_num_args (phi); i++) + { + t = gimple_phi_arg_def (phi, i); + if (TREE_CODE (t) == SSA_NAME) + bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t)); + } + } + + /* Then note the operands of each statement. */ + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); + !gsi_end_p (gsi); + gsi_next (&gsi)) + { + ssa_op_iter iter; + gimple *stmt = gsi_stmt (gsi); + FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, SSA_OP_ALL_OPERANDS) + if (TREE_CODE (t) == SSA_NAME) + bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t)); + } + } + + /* Now walk the free list noting what we find there and verifying + there are no duplicates. */ + bitmap names_in_freelists = BITMAP_ALLOC (NULL); + if (FREE_SSANAMES (fun)) + { + for (unsigned int i = 0; i < FREE_SSANAMES (fun)->length (); i++) + { + tree t = (*FREE_SSANAMES (fun))[i]; + + /* Verify that the name is marked as being in the free list. */ + gcc_assert (SSA_NAME_IN_FREE_LIST (t)); + + /* Verify the name has not already appeared in the free list and + note it in the list of names found in the free list. */ + gcc_assert (!bitmap_bit_p (names_in_freelists, SSA_NAME_VERSION (t))); + bitmap_set_bit (names_in_freelists, SSA_NAME_VERSION (t)); + } + } + + /* Similarly for the names in the pending free list. */ + if (FREE_SSANAMES_QUEUE (fun)) + { + for (unsigned int i = 0; i < FREE_SSANAMES_QUEUE (fun)->length (); i++) + { + tree t = (*FREE_SSANAMES_QUEUE (fun))[i]; + + /* Verify that the name is marked as being in the free list. */ + gcc_assert (SSA_NAME_IN_FREE_LIST (t)); + + /* Verify the name has not already appeared in the free list and + note it in the list of names found in the free list. */ + gcc_assert (!bitmap_bit_p (names_in_freelists, SSA_NAME_VERSION (t))); + bitmap_set_bit (names_in_freelists, SSA_NAME_VERSION (t)); + } + } + + /* If any name appears in both the IL and the freelists, then + something horrible has happened. */ + bool intersect_p = bitmap_intersect_p (names_in_il, names_in_freelists); + gcc_assert (!intersect_p); + + /* Names can be queued up for release if there is an ssa update + pending. Pretend we saw them in the IL. */ + if (names_to_release) + bitmap_ior_into (names_in_il, names_to_release); + + /* Function splitting can "lose" SSA_NAMEs in an effort to ensure that + debug/non-debug compilations have the same SSA_NAMEs. So for each + lost SSA_NAME, see if it's likely one from that wart. These will always + be marked as default definitions. So we loosely assume that anything + marked as a default definition isn't leaked by pretening they are + in the IL. */ + for (unsigned int i = UNUSED_NAME_VERSION + 1; i < num_ssa_names; i++) + if (ssa_name (i) && SSA_NAME_IS_DEFAULT_DEF (ssa_name (i))) + bitmap_set_bit (names_in_il, i); + + unsigned int i; + bitmap_iterator bi; + bitmap all_names = BITMAP_ALLOC (NULL); + bitmap_set_range (all_names, UNUSED_NAME_VERSION + 1, num_ssa_names - 1); + bitmap_ior_into (names_in_il, names_in_freelists); + + /* Any name not mentioned in the IL and not in the feelists + has been leaked. */ + EXECUTE_IF_AND_COMPL_IN_BITMAP(all_names, names_in_il, + UNUSED_NAME_VERSION + 1, i, bi) + gcc_assert (!ssa_name (i)); + + BITMAP_FREE (all_names); + BITMAP_FREE (names_in_freelists); + BITMAP_FREE (names_in_il); +} + /* Move all SSA_NAMEs from FREE_SSA_NAMES_QUEUE to FREE_SSA_NAMES. We do not, but should have a mode to verify the state of the SSA_NAMEs @@ -604,6 +731,42 @@ replace_ssa_name_symbol (tree ssa_name, tree sym) TREE_TYPE (ssa_name) = TREE_TYPE (sym); } +/* Release the vector of free SSA_NAMEs and compact the the + vector of SSA_NAMEs that are live. */ + +static void +release_free_names_and_compact_live_names (function *fun) +{ + unsigned i, j; + int n = vec_safe_length (FREE_SSANAMES (fun)); + + /* Now release the freelist. */ + vec_free (FREE_SSANAMES (fun)); + + /* And compact the SSA number space. We make sure to not change the + relative order of SSA versions. */ + for (i = 1, j = 1; i < fun->gimple_df->ssa_names->length (); ++i) + { + tree name = ssa_name (i); + if (name) + { + if (i != j) + { + SSA_NAME_VERSION (name) = j; + (*fun->gimple_df->ssa_names)[j] = name; + } + j++; + } + } + fun->gimple_df->ssa_names->truncate (j); + + statistics_counter_event (fun, "SSA names released", n); + statistics_counter_event (fun, "SSA name holes removed", i - j); + if (dump_file) + fprintf (dump_file, "Released %i names, %.2f%%, removed %i holes\n", + n, n * 100.0 / num_ssa_names, i - j); +} + /* Return SSA names that are unused to GGC memory and compact the SSA version namespace. This is used to keep footprint of compiler during interprocedural optimization. */ @@ -638,34 +801,7 @@ public: unsigned int pass_release_ssa_names::execute (function *fun) { - unsigned i, j; - int n = vec_safe_length (FREE_SSANAMES (fun)); - - /* Now release the freelist. */ - vec_free (FREE_SSANAMES (fun)); - - /* And compact the SSA number space. We make sure to not change the - relative order of SSA versions. */ - for (i = 1, j = 1; i < fun->gimple_df->ssa_names->length (); ++i) - { - tree name = ssa_name (i); - if (name) - { - if (i != j) - { - SSA_NAME_VERSION (name) = j; - (*fun->gimple_df->ssa_names)[j] = name; - } - j++; - } - } - fun->gimple_df->ssa_names->truncate (j); - - statistics_counter_event (fun, "SSA names released", n); - statistics_counter_event (fun, "SSA name holes removed", i - j); - if (dump_file) - fprintf (dump_file, "Released %i names, %.2f%%, removed %i holes\n", - n, n * 100.0 / num_ssa_names, i - j); + release_free_names_and_compact_live_names (fun); return 0; } |