static inline void remove_from_partition_kill_list (temp_expr_table_p tab, int p, int version) { #ifdef ENABLE_CHECKING gcc_assert (tab->kill_list[p]); #endif bitmap_clear_bit (tab->kill_list[p], version); if (bitmap_empty_p (tab->kill_list[p])) { bitmap_clear_bit (tab->partition_in_use, p); BITMAP_FREE (tab->kill_list[p]); } }
/* Set up USED_PSEUDOS_BITMAP, and update LR_BITMAP (a BB live info bitmap). */ static void update_live_info (bitmap lr_bitmap) { unsigned int j; bitmap_iterator bi; bitmap_clear (&used_pseudos_bitmap); EXECUTE_IF_AND_IN_BITMAP (&coalesced_pseudos_bitmap, lr_bitmap, FIRST_PSEUDO_REGISTER, j, bi) bitmap_set_bit (&used_pseudos_bitmap, first_coalesced_pseudo[j]); if (! bitmap_empty_p (&used_pseudos_bitmap)) { bitmap_and_compl_into (lr_bitmap, &coalesced_pseudos_bitmap); bitmap_ior_into (lr_bitmap, &used_pseudos_bitmap); } }
static void add_dependence (temp_expr_table_p tab, int version, tree var) { int i; bitmap_iterator bi; unsigned x; i = SSA_NAME_VERSION (var); if (version_to_be_replaced_p (tab, i)) { if (!bitmap_empty_p (tab->new_replaceable_dependencies)) { /* Version will now be killed by a write to any partition the substituted expression would have been killed by. */ EXECUTE_IF_SET_IN_BITMAP (tab->new_replaceable_dependencies, 0, x, bi) add_to_partition_kill_list (tab, x, version); /* 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); bitmap_ior_into (tab->partition_dependencies[version], tab->new_replaceable_dependencies); bitmap_ior_into (tab->partition_in_use, tab->new_replaceable_dependencies); /* It is only necessary to add these once. */ bitmap_clear (tab->new_replaceable_dependencies); } } else { i = var_to_partition (tab->map, var); #ifdef ENABLE_CHECKING gcc_assert (i != NO_PARTITION); gcc_assert (tab->num_in_part[i] != 0); #endif /* Only dependencies on ssa_names which are coalesced with something need to be tracked. Partitions with containing only a single SSA_NAME *cannot* have their value changed. */ if (tab->num_in_part[i] > 1) { add_to_partition_kill_list (tab, i, version); make_dependent_on_partition (tab, version, i); } } }
unsigned HOST_WIDE_INT compute_builtin_object_size (tree ptr, int object_size_type) { gcc_assert (object_size_type >= 0 && object_size_type <= 3); if (! offset_limit) init_offset_limit (); if (TREE_CODE (ptr) == ADDR_EXPR) return addr_object_size (ptr, object_size_type); else if (TREE_CODE (ptr) == CALL_EXPR) { tree arg = pass_through_call (ptr); if (arg) return compute_builtin_object_size (arg, object_size_type); else return alloc_object_size (ptr, object_size_type); } else if (TREE_CODE (ptr) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (ptr)) && object_sizes[object_size_type] != NULL) { if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr))) { struct object_size_info osi; bitmap_iterator bi; unsigned int i; if (dump_file) { fprintf (dump_file, "Computing %s %sobject size for ", (object_size_type & 2) ? "minimum" : "maximum", (object_size_type & 1) ? "sub" : ""); print_generic_expr (dump_file, ptr, dump_flags); fprintf (dump_file, ":\n"); } osi.visited = BITMAP_ALLOC (NULL); osi.reexamine = BITMAP_ALLOC (NULL); osi.object_size_type = object_size_type; osi.depths = NULL; osi.stack = NULL; osi.tos = NULL; /* First pass: walk UD chains, compute object sizes that can be computed. osi.reexamine bitmap at the end will contain what variables were found in dependency cycles and therefore need to be reexamined. */ osi.pass = 0; osi.changed = false; collect_object_sizes_for (&osi, ptr); /* Second pass: keep recomputing object sizes of variables that need reexamination, until no object sizes are increased or all object sizes are computed. */ if (! bitmap_empty_p (osi.reexamine)) { bitmap reexamine = BITMAP_ALLOC (NULL); /* If looking for minimum instead of maximum object size, detect cases where a pointer is increased in a loop. Although even without this detection pass 2 would eventually terminate, it could take a long time. If a pointer is increasing this way, we need to assume 0 object size. E.g. p = &buf[0]; while (cond) p = p + 4; */ if (object_size_type & 2) { osi.depths = xcalloc (num_ssa_names, sizeof (unsigned int)); osi.stack = xmalloc (num_ssa_names * sizeof (unsigned int)); osi.tos = osi.stack; osi.pass = 1; /* collect_object_sizes_for is changing osi.reexamine bitmap, so iterate over a copy. */ bitmap_copy (reexamine, osi.reexamine); EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) if (bitmap_bit_p (osi.reexamine, i)) check_for_plus_in_loops (&osi, ssa_name (i)); free (osi.depths); osi.depths = NULL; free (osi.stack); osi.stack = NULL; osi.tos = NULL; } do { osi.pass = 2; osi.changed = false; /* collect_object_sizes_for is changing osi.reexamine bitmap, so iterate over a copy. */ bitmap_copy (reexamine, osi.reexamine); EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) if (bitmap_bit_p (osi.reexamine, i)) { collect_object_sizes_for (&osi, ssa_name (i)); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Reexamining "); print_generic_expr (dump_file, ssa_name (i), dump_flags); fprintf (dump_file, "\n"); } } } while (osi.changed); BITMAP_FREE (reexamine); } EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi) bitmap_set_bit (computed[object_size_type], i); /* Debugging dumps. */ if (dump_file) { EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi) if (object_sizes[object_size_type][i] != unknown[object_size_type]) { print_generic_expr (dump_file, ssa_name (i), dump_flags); fprintf (dump_file, ": %s %sobject size " HOST_WIDE_INT_PRINT_UNSIGNED "\n", (object_size_type & 2) ? "minimum" : "maximum", (object_size_type & 1) ? "sub" : "", object_sizes[object_size_type][i]); } } BITMAP_FREE (osi.reexamine); BITMAP_FREE (osi.visited); }
bool compute_builtin_object_size (tree ptr, int object_size_type, unsigned HOST_WIDE_INT *psize) { gcc_assert (object_size_type >= 0 && object_size_type <= 3); /* Set to unknown and overwrite just before returning if the size could be determined. */ *psize = unknown[object_size_type]; if (! offset_limit) init_offset_limit (); if (TREE_CODE (ptr) == ADDR_EXPR) return addr_object_size (NULL, ptr, object_size_type, psize); if (TREE_CODE (ptr) != SSA_NAME || !POINTER_TYPE_P (TREE_TYPE (ptr))) return false; if (computed[object_size_type] == NULL) { if (optimize || object_size_type & 1) return false; /* When not optimizing, rather than failing, make a small effort to determine the object size without the full benefit of the (costly) computation below. */ gimple *def = SSA_NAME_DEF_STMT (ptr); if (gimple_code (def) == GIMPLE_ASSIGN) { tree_code code = gimple_assign_rhs_code (def); if (code == POINTER_PLUS_EXPR) { tree offset = gimple_assign_rhs2 (def); ptr = gimple_assign_rhs1 (def); if (tree_fits_shwi_p (offset) && compute_builtin_object_size (ptr, object_size_type, psize)) { /* Return zero when the offset is out of bounds. */ unsigned HOST_WIDE_INT off = tree_to_shwi (offset); *psize = off < *psize ? *psize - off : 0; return true; } } } return false; } if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr))) { struct object_size_info osi; bitmap_iterator bi; unsigned int i; if (num_ssa_names > object_sizes[object_size_type].length ()) object_sizes[object_size_type].safe_grow (num_ssa_names); if (dump_file) { fprintf (dump_file, "Computing %s %sobject size for ", (object_size_type & 2) ? "minimum" : "maximum", (object_size_type & 1) ? "sub" : ""); print_generic_expr (dump_file, ptr, dump_flags); fprintf (dump_file, ":\n"); } osi.visited = BITMAP_ALLOC (NULL); osi.reexamine = BITMAP_ALLOC (NULL); osi.object_size_type = object_size_type; osi.depths = NULL; osi.stack = NULL; osi.tos = NULL; /* First pass: walk UD chains, compute object sizes that can be computed. osi.reexamine bitmap at the end will contain what variables were found in dependency cycles and therefore need to be reexamined. */ osi.pass = 0; osi.changed = false; collect_object_sizes_for (&osi, ptr); /* Second pass: keep recomputing object sizes of variables that need reexamination, until no object sizes are increased or all object sizes are computed. */ if (! bitmap_empty_p (osi.reexamine)) { bitmap reexamine = BITMAP_ALLOC (NULL); /* If looking for minimum instead of maximum object size, detect cases where a pointer is increased in a loop. Although even without this detection pass 2 would eventually terminate, it could take a long time. If a pointer is increasing this way, we need to assume 0 object size. E.g. p = &buf[0]; while (cond) p = p + 4; */ if (object_size_type & 2) { osi.depths = XCNEWVEC (unsigned int, num_ssa_names); osi.stack = XNEWVEC (unsigned int, num_ssa_names); osi.tos = osi.stack; osi.pass = 1; /* collect_object_sizes_for is changing osi.reexamine bitmap, so iterate over a copy. */ bitmap_copy (reexamine, osi.reexamine); EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) if (bitmap_bit_p (osi.reexamine, i)) check_for_plus_in_loops (&osi, ssa_name (i)); free (osi.depths); osi.depths = NULL; free (osi.stack); osi.stack = NULL; osi.tos = NULL; } do { osi.pass = 2; osi.changed = false; /* collect_object_sizes_for is changing osi.reexamine bitmap, so iterate over a copy. */ bitmap_copy (reexamine, osi.reexamine); EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi) if (bitmap_bit_p (osi.reexamine, i)) { collect_object_sizes_for (&osi, ssa_name (i)); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Reexamining "); print_generic_expr (dump_file, ssa_name (i), dump_flags); fprintf (dump_file, "\n"); } } } while (osi.changed); BITMAP_FREE (reexamine); }