diff options
author | Ian Lance Taylor <iant@golang.org> | 2022-02-11 15:02:44 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2022-02-11 15:02:44 -0800 |
commit | 9a510fb0970d3d9a4201bce8965cabe67850386b (patch) | |
tree | 43d7fd2bbfd7ad8c9625a718a5e8718889351994 /gcc/tree-ssanames.c | |
parent | a6d3012b274f38b20e2a57162106f625746af6c6 (diff) | |
parent | 8dc2499aa62f768c6395c9754b8cabc1ce25c494 (diff) | |
download | gcc-9a510fb0970d3d9a4201bce8965cabe67850386b.zip gcc-9a510fb0970d3d9a4201bce8965cabe67850386b.tar.gz gcc-9a510fb0970d3d9a4201bce8965cabe67850386b.tar.bz2 |
Merge from trunk revision 8dc2499aa62f768c6395c9754b8cabc1ce25c494
Diffstat (limited to 'gcc/tree-ssanames.c')
-rw-r--r-- | gcc/tree-ssanames.c | 923 |
1 files changed, 0 insertions, 923 deletions
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c deleted file mode 100644 index f427c5a..0000000 --- a/gcc/tree-ssanames.c +++ /dev/null @@ -1,923 +0,0 @@ -/* Generic routines for manipulating SSA_NAME expressions - Copyright (C) 2003-2021 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "backend.h" -#include "tree.h" -#include "gimple.h" -#include "tree-pass.h" -#include "ssa.h" -#include "gimple-iterator.h" -#include "stor-layout.h" -#include "tree-into-ssa.h" -#include "tree-ssa.h" -#include "cfgloop.h" -#include "tree-scalar-evolution.h" -#include "value-query.h" - -/* Rewriting a function into SSA form can create a huge number of SSA_NAMEs, - many of which may be thrown away shortly after their creation if jumps - were threaded through PHI nodes. - - While our garbage collection mechanisms will handle this situation, it - is extremely wasteful to create nodes and throw them away, especially - when the nodes can be reused. - - For PR 8361, we can significantly reduce the number of nodes allocated - and thus the total amount of memory allocated by managing SSA_NAMEs a - little. This additionally helps reduce the amount of work done by the - garbage collector. Similar results have been seen on a wider variety - of tests (such as the compiler itself). - - Right now we maintain our free list on a per-function basis. It may - or may not make sense to maintain the free list for the duration of - a compilation unit. - - External code should rely solely upon HIGHEST_SSA_VERSION and the - externally defined functions. External code should not know about - the details of the free list management. - - External code should also not assume the version number on nodes is - monotonically increasing. We reuse the version number when we - reuse an SSA_NAME expression. This helps keep arrays and bitmaps - more compact. */ - - -/* Version numbers with special meanings. We start allocating new version - numbers after the special ones. */ -#define UNUSED_NAME_VERSION 0 - -unsigned int ssa_name_nodes_reused; -unsigned int ssa_name_nodes_created; - -#define FREE_SSANAMES(fun) (fun)->gimple_df->free_ssanames -#define FREE_SSANAMES_QUEUE(fun) (fun)->gimple_df->free_ssanames_queue - - -/* Initialize management of SSA_NAMEs to default SIZE. If SIZE is - zero use default. */ - -void -init_ssanames (struct function *fn, int size) -{ - if (!size) - vec_alloc (SSANAMES (fn), 50); - else - vec_safe_reserve (SSANAMES (fn), size, true); - - /* Version 0 is special, so reserve the first slot in the table. Though - currently unused, we may use version 0 in alias analysis as part of - the heuristics used to group aliases when the alias sets are too - large. - - We use vec::quick_push here because we know that SSA_NAMES has at - least 50 elements reserved in it. */ - SSANAMES (fn)->quick_push (NULL_TREE); - FREE_SSANAMES (fn) = NULL; - FREE_SSANAMES_QUEUE (fn) = NULL; - - fn->gimple_df->ssa_renaming_needed = 0; - fn->gimple_df->rename_vops = 0; -} - -/* Finalize management of SSA_NAMEs. */ - -void -fini_ssanames (struct function *fn) -{ - unsigned i; - tree name; - /* Some SSA names leak into global tree data structures so we can't simply - ggc_free them. But make sure to clear references to stmts since we now - ggc_free the CFG itself. */ - FOR_EACH_VEC_SAFE_ELT (SSANAMES (fn), i, name) - if (name) - SSA_NAME_DEF_STMT (name) = NULL; - vec_free (SSANAMES (fn)); - vec_free (FREE_SSANAMES (fn)); - vec_free (FREE_SSANAMES_QUEUE (fn)); -} - -/* Dump some simple statistics regarding the re-use of SSA_NAME nodes. */ - -void -ssanames_print_statistics (void) -{ - fprintf (stderr, "%-32s" PRsa (11) "\n", "SSA_NAME nodes allocated:", - SIZE_AMOUNT (ssa_name_nodes_created)); - fprintf (stderr, "%-32s" PRsa (11) "\n", "SSA_NAME nodes reused:", - SIZE_AMOUNT (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) -{ - if (!gimple_in_ssa_p (fun)) - return; - - auto_bitmap names_in_il; - - /* Walk the entire IL noting every SSA_NAME we see. */ - basic_block bb; - 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) - 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. */ - auto_bitmap names_in_freelists; - 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 pretending 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; - auto_bitmap all_names; - 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)); -} - -/* 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 - lists. In particular at this point every name must be in the IL, - on the free list or in the queue. Anything else is an error. */ - -void -flush_ssaname_freelist (void) -{ - /* If there were any SSA names released reset the SCEV cache. */ - if (! vec_safe_is_empty (FREE_SSANAMES_QUEUE (cfun))) - scev_reset_htab (); - vec_safe_splice (FREE_SSANAMES (cfun), FREE_SSANAMES_QUEUE (cfun)); - vec_safe_truncate (FREE_SSANAMES_QUEUE (cfun), 0); -} - -/* Initialize SSA_NAME_IMM_USE_NODE of a SSA NAME. */ - -void -init_ssa_name_imm_use (tree name) -{ - use_operand_p imm; - imm = &(SSA_NAME_IMM_USE_NODE (name)); - imm->use = NULL; - imm->prev = imm; - imm->next = imm; - imm->loc.ssa_name = name; -} - -/* Return an SSA_NAME node for variable VAR defined in statement STMT - in function FN. STMT may be an empty statement for artificial - references (e.g., default definitions created when a variable is - used without a preceding definition). If VERISON is not zero then - allocate the SSA name with that version. */ - -tree -make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, - unsigned int version) -{ - tree t; - gcc_assert (VAR_P (var) - || TREE_CODE (var) == PARM_DECL - || TREE_CODE (var) == RESULT_DECL - || (TYPE_P (var) && is_gimple_reg_type (var))); - - /* Get the specified SSA name version. */ - if (version != 0) - { - t = make_node (SSA_NAME); - SSA_NAME_VERSION (t) = version; - if (version >= SSANAMES (fn)->length ()) - vec_safe_grow_cleared (SSANAMES (fn), version + 1, true); - gcc_assert ((*SSANAMES (fn))[version] == NULL); - (*SSANAMES (fn))[version] = t; - ssa_name_nodes_created++; - } - /* If our free list has an element, then use it. */ - else if (!vec_safe_is_empty (FREE_SSANAMES (fn))) - { - t = FREE_SSANAMES (fn)->pop (); - ssa_name_nodes_reused++; - - /* The node was cleared out when we put it on the free list, so - there is no need to do so again here. */ - gcc_assert ((*SSANAMES (fn))[SSA_NAME_VERSION (t)] == NULL); - (*SSANAMES (fn))[SSA_NAME_VERSION (t)] = t; - } - else - { - t = make_node (SSA_NAME); - SSA_NAME_VERSION (t) = SSANAMES (fn)->length (); - vec_safe_push (SSANAMES (fn), t); - ssa_name_nodes_created++; - } - - if (TYPE_P (var)) - { - TREE_TYPE (t) = TYPE_MAIN_VARIANT (var); - SET_SSA_NAME_VAR_OR_IDENTIFIER (t, NULL_TREE); - } - else - { - TREE_TYPE (t) = TREE_TYPE (var); - SET_SSA_NAME_VAR_OR_IDENTIFIER (t, var); - } - SSA_NAME_DEF_STMT (t) = stmt; - if (POINTER_TYPE_P (TREE_TYPE (t))) - SSA_NAME_PTR_INFO (t) = NULL; - else - SSA_NAME_RANGE_INFO (t) = NULL; - - SSA_NAME_IN_FREE_LIST (t) = 0; - SSA_NAME_IS_DEFAULT_DEF (t) = 0; - init_ssa_name_imm_use (t); - - return t; -} - -/* Helper function for set_range_info. - - Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name - NAME. */ - -void -set_range_info_raw (tree name, enum value_range_kind range_type, - const wide_int_ref &min, const wide_int_ref &max) -{ - gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); - gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); - - /* Allocate if not available. */ - if (ri == NULL) - { - size_t size = (sizeof (range_info_def) - + trailing_wide_ints <3>::extra_size (precision)); - ri = static_cast<range_info_def *> (ggc_internal_alloc (size)); - ri->ints.set_precision (precision); - SSA_NAME_RANGE_INFO (name) = ri; - ri->set_nonzero_bits (wi::shwi (-1, precision)); - } - - /* Record the range type. */ - if (SSA_NAME_RANGE_TYPE (name) != range_type) - SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); - - /* Set the values. */ - ri->set_min (min); - ri->set_max (max); - - /* If it is a range, try to improve nonzero_bits from the min/max. */ - if (range_type == VR_RANGE) - { - wide_int xorv = ri->get_min () ^ ri->get_max (); - if (xorv != 0) - xorv = wi::mask (precision - wi::clz (xorv), false, precision); - ri->set_nonzero_bits (ri->get_nonzero_bits () & (ri->get_min () | xorv)); - } -} - -/* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name - NAME while making sure we don't store useless range info. */ - -void -set_range_info (tree name, enum value_range_kind range_type, - const wide_int_ref &min, const wide_int_ref &max) -{ - gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); - - /* A range of the entire domain is really no range at all. */ - tree type = TREE_TYPE (name); - if (min == wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)) - && max == wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type))) - { - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - if (ri == NULL) - return; - if (ri->get_nonzero_bits () == -1) - { - ggc_free (ri); - SSA_NAME_RANGE_INFO (name) = NULL; - return; - } - } - - set_range_info_raw (name, range_type, min, max); -} - -/* Store range information for NAME from a value_range. */ - -void -set_range_info (tree name, const value_range &vr) -{ - wide_int min = wi::to_wide (vr.min ()); - wide_int max = wi::to_wide (vr.max ()); - set_range_info (name, vr.kind (), min, max); -} - -/* Set nonnull attribute to pointer NAME. */ - -void -set_ptr_nonnull (tree name) -{ - gcc_assert (POINTER_TYPE_P (TREE_TYPE (name))); - struct ptr_info_def *pi = get_ptr_info (name); - pi->pt.null = 0; -} - -/* Change non-zero bits bitmask of NAME. */ - -void -set_nonzero_bits (tree name, const wide_int_ref &mask) -{ - gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); - if (SSA_NAME_RANGE_INFO (name) == NULL) - { - if (mask == -1) - return; - set_range_info_raw (name, VR_RANGE, - wi::to_wide (TYPE_MIN_VALUE (TREE_TYPE (name))), - wi::to_wide (TYPE_MAX_VALUE (TREE_TYPE (name)))); - } - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - ri->set_nonzero_bits (mask); -} - -/* Return a widest_int with potentially non-zero bits in SSA_NAME - NAME, the constant for INTEGER_CST, or -1 if unknown. */ - -wide_int -get_nonzero_bits (const_tree name) -{ - if (TREE_CODE (name) == INTEGER_CST) - return wi::to_wide (name); - - /* Use element_precision instead of TYPE_PRECISION so complex and - vector types get a non-zero precision. */ - unsigned int precision = element_precision (TREE_TYPE (name)); - if (POINTER_TYPE_P (TREE_TYPE (name))) - { - struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name); - if (pi && pi->align) - return wi::shwi (-(HOST_WIDE_INT) pi->align - | (HOST_WIDE_INT) pi->misalign, precision); - return wi::shwi (-1, precision); - } - - range_info_def *ri = SSA_NAME_RANGE_INFO (name); - if (!ri) - return wi::shwi (-1, precision); - - return ri->get_nonzero_bits (); -} - -/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false - otherwise. - - This can be because it is a boolean type, any unsigned integral - type with a single bit of precision, or has known range of [0..1] - via range analysis. */ - -bool -ssa_name_has_boolean_range (tree op) -{ - gcc_assert (TREE_CODE (op) == SSA_NAME); - - /* Boolean types always have a range [0..1]. */ - if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE) - return true; - - /* An integral type with a single bit of precision. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (op)) - && TYPE_UNSIGNED (TREE_TYPE (op)) - && TYPE_PRECISION (TREE_TYPE (op)) == 1) - return true; - - /* An integral type with more precision, but the object - only takes on values [0..1] as determined by range - analysis. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (op)) - && (TYPE_PRECISION (TREE_TYPE (op)) > 1)) - { - int_range<2> onezero (build_zero_cst (TREE_TYPE (op)), - build_one_cst (TREE_TYPE (op))); - int_range<2> r; - if (get_range_query (cfun)->range_of_expr (r, op) && r == onezero) - return true; - - if (wi::eq_p (get_nonzero_bits (op), 1)) - return true; - } - - return false; -} - -/* We no longer need the SSA_NAME expression VAR, release it so that - it may be reused. - - Note it is assumed that no calls to make_ssa_name will be made - until all uses of the ssa name are released and that the only - use of the SSA_NAME expression is to check its SSA_NAME_VAR. All - other fields must be assumed clobbered. */ - -void -release_ssa_name_fn (struct function *fn, tree var) -{ - if (!var) - return; - - /* Never release the default definition for a symbol. It's a - special SSA name that should always exist once it's created. */ - if (SSA_NAME_IS_DEFAULT_DEF (var)) - return; - - /* If VAR has been registered for SSA updating, don't remove it. - After update_ssa has run, the name will be released. */ - if (name_registered_for_update_p (var)) - { - release_ssa_name_after_update_ssa (var); - return; - } - - /* release_ssa_name can be called multiple times on a single SSA_NAME. - However, it should only end up on our free list one time. We - keep a status bit in the SSA_NAME node itself to indicate it has - been put on the free list. - - Note that once on the freelist you cannot reference the SSA_NAME's - defining statement. */ - if (! SSA_NAME_IN_FREE_LIST (var)) - { - int saved_ssa_name_version = SSA_NAME_VERSION (var); - use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var)); - - if (MAY_HAVE_DEBUG_BIND_STMTS) - insert_debug_temp_for_var_def (NULL, var); - - if (flag_checking) - verify_imm_links (stderr, var); - while (imm->next != imm) - delink_imm_use (imm->next); - - (*SSANAMES (fn))[SSA_NAME_VERSION (var)] = NULL_TREE; - memset (var, 0, tree_size (var)); - - imm->prev = imm; - imm->next = imm; - imm->loc.ssa_name = var; - - /* First put back the right tree node so that the tree checking - macros do not complain. */ - TREE_SET_CODE (var, SSA_NAME); - - /* Restore the version number. */ - SSA_NAME_VERSION (var) = saved_ssa_name_version; - - /* Note this SSA_NAME is now in the first list. */ - SSA_NAME_IN_FREE_LIST (var) = 1; - - /* Put in a non-NULL TREE_TYPE so dumping code will not ICE - if it happens to come along a released SSA name and tries - to inspect its type. */ - TREE_TYPE (var) = error_mark_node; - - /* And finally queue it so that it will be put on the free list. */ - vec_safe_push (FREE_SSANAMES_QUEUE (fn), var); - } -} - -/* If the alignment of the pointer described by PI is known, return true and - store the alignment and the deviation from it into *ALIGNP and *MISALIGNP - respectively. Otherwise return false. */ - -bool -get_ptr_info_alignment (struct ptr_info_def *pi, unsigned int *alignp, - unsigned int *misalignp) -{ - if (pi->align) - { - *alignp = pi->align; - *misalignp = pi->misalign; - return true; - } - else - return false; -} - -/* State that the pointer described by PI has unknown alignment. */ - -void -mark_ptr_info_alignment_unknown (struct ptr_info_def *pi) -{ - pi->align = 0; - pi->misalign = 0; -} - -/* Store the power-of-two byte alignment and the deviation from that - alignment of pointer described by PI to ALIOGN and MISALIGN - respectively. */ - -void -set_ptr_info_alignment (struct ptr_info_def *pi, unsigned int align, - unsigned int misalign) -{ - gcc_checking_assert (align != 0); - gcc_assert ((align & (align - 1)) == 0); - gcc_assert ((misalign & ~(align - 1)) == 0); - - pi->align = align; - pi->misalign = misalign; -} - -/* If pointer described by PI has known alignment, increase its known - misalignment by INCREMENT modulo its current alignment. */ - -void -adjust_ptr_info_misalignment (struct ptr_info_def *pi, poly_uint64 increment) -{ - if (pi->align != 0) - { - increment += pi->misalign; - if (!known_misalignment (increment, pi->align, &pi->misalign)) - { - pi->align = known_alignment (increment); - pi->misalign = 0; - } - } -} - -/* Return the alias information associated with pointer T. It creates a - new instance if none existed. */ - -struct ptr_info_def * -get_ptr_info (tree t) -{ - struct ptr_info_def *pi; - - gcc_assert (POINTER_TYPE_P (TREE_TYPE (t))); - - pi = SSA_NAME_PTR_INFO (t); - if (pi == NULL) - { - pi = ggc_cleared_alloc<ptr_info_def> (); - pt_solution_reset (&pi->pt); - mark_ptr_info_alignment_unknown (pi); - SSA_NAME_PTR_INFO (t) = pi; - } - - return pi; -} - - -/* Creates a new SSA name using the template NAME tobe defined by - statement STMT in function FN. */ - -tree -copy_ssa_name_fn (struct function *fn, tree name, gimple *stmt) -{ - tree new_name; - - if (SSA_NAME_VAR (name)) - new_name = make_ssa_name_fn (fn, SSA_NAME_VAR (name), stmt); - else - { - new_name = make_ssa_name_fn (fn, TREE_TYPE (name), stmt); - SET_SSA_NAME_VAR_OR_IDENTIFIER (new_name, SSA_NAME_IDENTIFIER (name)); - } - - return new_name; -} - - -/* Creates a duplicate of the ptr_info_def at PTR_INFO for use by - the SSA name NAME. */ - -void -duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info) -{ - struct ptr_info_def *new_ptr_info; - - gcc_assert (POINTER_TYPE_P (TREE_TYPE (name))); - gcc_assert (!SSA_NAME_PTR_INFO (name)); - - if (!ptr_info) - return; - - new_ptr_info = ggc_alloc<ptr_info_def> (); - *new_ptr_info = *ptr_info; - - SSA_NAME_PTR_INFO (name) = new_ptr_info; -} - -/* Creates a duplicate of the range_info_def at RANGE_INFO of type - RANGE_TYPE for use by the SSA name NAME. */ -void -duplicate_ssa_name_range_info (tree name, enum value_range_kind range_type, - struct range_info_def *range_info) -{ - struct range_info_def *new_range_info; - - gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); - gcc_assert (!SSA_NAME_RANGE_INFO (name)); - - if (!range_info) - return; - - unsigned int precision = TYPE_PRECISION (TREE_TYPE (name)); - size_t size = (sizeof (range_info_def) - + trailing_wide_ints <3>::extra_size (precision)); - new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size)); - memcpy (new_range_info, range_info, size); - - gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE); - SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE); - SSA_NAME_RANGE_INFO (name) = new_range_info; -} - - - -/* Creates a duplicate of a ssa name NAME tobe defined by statement STMT - in function FN. */ - -tree -duplicate_ssa_name_fn (struct function *fn, tree name, gimple *stmt) -{ - tree new_name = copy_ssa_name_fn (fn, name, stmt); - if (POINTER_TYPE_P (TREE_TYPE (name))) - { - struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name); - - if (old_ptr_info) - duplicate_ssa_name_ptr_info (new_name, old_ptr_info); - } - else - { - struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name); - - if (old_range_info) - duplicate_ssa_name_range_info (new_name, SSA_NAME_RANGE_TYPE (name), - old_range_info); - } - - return new_name; -} - - -/* Reset all flow sensitive data on NAME such as range-info, nonzero - bits and alignment. */ - -void -reset_flow_sensitive_info (tree name) -{ - if (POINTER_TYPE_P (TREE_TYPE (name))) - { - /* points-to info is not flow-sensitive. */ - if (SSA_NAME_PTR_INFO (name)) - { - /* [E]VRP can derive context sensitive alignment info and - non-nullness properties. We must reset both. */ - mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name)); - SSA_NAME_PTR_INFO (name)->pt.null = 1; - } - } - else - SSA_NAME_RANGE_INFO (name) = NULL; -} - -/* Clear all flow sensitive data from all statements and PHI definitions - in BB. */ - -void -reset_flow_sensitive_info_in_bb (basic_block bb) -{ - for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); - gsi_next (&gsi)) - { - gimple *stmt = gsi_stmt (gsi); - ssa_op_iter i; - tree op; - FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_DEF) - reset_flow_sensitive_info (op); - } - - for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); - gsi_next (&gsi)) - { - tree phi_def = gimple_phi_result (gsi.phi ()); - reset_flow_sensitive_info (phi_def); - } -} - -/* Release all the SSA_NAMEs created by STMT. */ - -void -release_defs (gimple *stmt) -{ - tree def; - ssa_op_iter iter; - - FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS) - if (TREE_CODE (def) == SSA_NAME) - release_ssa_name (def); -} - - -/* Replace the symbol associated with SSA_NAME with SYM. */ - -void -replace_ssa_name_symbol (tree ssa_name, tree sym) -{ - SET_SSA_NAME_VAR_OR_IDENTIFIER (ssa_name, sym); - TREE_TYPE (ssa_name) = TREE_TYPE (sym); -} - -/* Release the vector of free SSA_NAMEs and compact 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. */ - -namespace { - -const pass_data pass_data_release_ssa_names = -{ - GIMPLE_PASS, /* type */ - "release_ssa", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_TREE_SSA_OTHER, /* tv_id */ - PROP_ssa, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - TODO_remove_unused_locals, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_release_ssa_names : public gimple_opt_pass -{ -public: - pass_release_ssa_names (gcc::context *ctxt) - : gimple_opt_pass (pass_data_release_ssa_names, ctxt) - {} - - /* opt_pass methods: */ - virtual unsigned int execute (function *); - -}; // class pass_release_ssa_names - -unsigned int -pass_release_ssa_names::execute (function *fun) -{ - release_free_names_and_compact_live_names (fun); - return 0; -} - -} // anon namespace - -gimple_opt_pass * -make_pass_release_ssa_names (gcc::context *ctxt) -{ - return new pass_release_ssa_names (ctxt); -} |