GCC Middle and Back End API Reference
|
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "predict.h"
#include "alloc-pool.h"
#include "tree-pass.h"
#include "ssa.h"
#include "cgraph.h"
#include "gimple-pretty-print.h"
#include "alias.h"
#include "fold-const.h"
#include "tree-eh.h"
#include "stor-layout.h"
#include "gimplify.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "gimple-walk.h"
#include "tree-cfg.h"
#include "tree-dfa.h"
#include "tree-ssa.h"
#include "dbgcnt.h"
#include "builtins.h"
#include "tree-sra.h"
#include "opts.h"
Data Structures | |
struct | access |
struct | assign_link |
struct | uid_decl_hasher |
class | sra_padding_collecting |
struct | subreplacement_assignment_data |
Typedefs | |
typedef struct access * | access_p |
Enumerations | |
enum | sra_mode { SRA_MODE_EARLY_IPA , SRA_MODE_EARLY_INTRA , SRA_MODE_INTRA } |
enum | out_edge_check { SRA_OUTGOING_EDGES_UNCHECKED , SRA_OUTGOING_EDGES_OK , SRA_OUTGOING_EDGES_FAIL } |
enum | total_sra_field_state { TOTAL_FLD_CREATE , TOTAL_FLD_DONE , TOTAL_FLD_FAILED } |
enum | unscalarized_data_handling { SRA_UDH_NONE , SRA_UDH_RIGHT , SRA_UDH_LEFT } |
enum | assignment_mod_result { SRA_AM_NONE , SRA_AM_MODIFIED , SRA_AM_REMOVED } |
Variables | |
static enum sra_mode | sra_mode |
static object_allocator< struct access > | access_pool ("SRA accesses") |
static object_allocator< assign_link > | assign_link_pool ("SRA links") |
static hash_map< tree, auto_vec< access_p > > * | base_access_vec |
static hash_map< tree, unsigned > * | propagation_budget |
static bitmap | candidate_bitmap |
static hash_table< uid_decl_hasher > * | candidates |
static bitmap | should_scalarize_away_bitmap |
static bitmap | cannot_scalarize_away_bitmap |
static bitmap | disqualified_constants |
static bitmap | passed_by_ref_in_call |
static struct obstack | name_obstack |
static struct access * | rhs_work_queue_head |
static struct access * | lhs_work_queue_head |
static struct { ... } | sra_stats |
enum out_edge_check |
enum sra_mode |
Scalar Replacement of Aggregates (SRA) converts some structure references into scalar references, exposing them to the scalar optimizers. Copyright (C) 2008-2025 Free Software Foundation, Inc. Contributed by Martin Jambor <mjambor@suse.cz> 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/>.
This file implements Scalar Reduction of Aggregates (SRA). SRA is run twice, once in the early stages of compilation (early SRA) and once in the late stages (late SRA). The aim of both is to turn references to scalar parts of aggregates into uses of independent scalar variables. The two passes are nearly identical, the only difference is that early SRA does not scalarize unions which are used as the result in a GIMPLE_RETURN statement because together with inlining this can lead to weird type conversions. Both passes operate in four stages: 1. The declarations that have properties which make them candidates for scalarization are identified in function find_var_candidates(). The candidates are stored in candidate_bitmap. 2. The function body is scanned. In the process, declarations which are used in a manner that prevent their scalarization are removed from the candidate bitmap. More importantly, for every access into an aggregate, an access structure (struct access) is created by create_access() and stored in a vector associated with the aggregate. Among other information, the aggregate declaration, the offset and size of the access and its type are stored in the structure. On a related note, assign_link structures are created for every assign statement between candidate aggregates and attached to the related accesses. 3. The vectors of accesses are analyzed. They are first sorted according to their offset and size and then scanned for partially overlapping accesses (i.e. those which overlap but one is not entirely within another). Such an access disqualifies the whole aggregate from being scalarized. If there is no such inhibiting overlap, a representative access structure is chosen for every unique combination of offset and size. Afterwards, the pass builds a set of trees from these structures, in which children of an access are within their parent (in terms of offset and size). Then accesses are propagated whenever possible (i.e. in cases when it does not create a partially overlapping access) across assign_links from the right hand side to the left hand side. Then the set of trees for each declaration is traversed again and those accesses which should be replaced by a scalar are identified. 4. The function is traversed again, and for every reference into an aggregate that has some component which is about to be scalarized, statements are amended and new statements are created as necessary. Finally, if a parameter got scalarized, the scalar replacements are initialized with values from respective parameter aggregates.
Enumeration of all aggregate reductions we can do.
Enumerator | |
---|---|
SRA_MODE_EARLY_IPA | |
SRA_MODE_EARLY_INTRA | |
SRA_MODE_INTRA |
|
static |
Return true if STMT terminates BB and there is an abnormal edge going out of the BB and remember the decision in OE_CHECK.
References FOR_EACH_EDGE, gimple_bb(), SRA_OUTGOING_EDGES_FAIL, SRA_OUTGOING_EDGES_OK, access::stmt, and stmt_ends_bb_p().
Referenced by build_access_from_call_arg().
Return true if INNER is either the same type as OUTER or if it is the type of a record field in OUTER at offset zero, possibly in nested sub-records.
References DECL_CHAIN, DECL_FIELD_OFFSET, TREE_CODE, TREE_TYPE, TYPE_FIELDS, TYPE_MAIN_VARIANT, and zerop().
Referenced by total_should_skip_creating_access().
Return true iff ACC is non-NULL and has subaccesses.
References access::first_child.
Referenced by sra_modify_assign(), and sra_modify_constructor_assign().
Return true iff ACC is (partly) covered by at least one replacement.
References access_has_replacements_p(), access::first_child, access::grp_to_be_replaced, and access::next_sibling.
Referenced by access_has_replacements_p(), and sra_modify_assign().
Return true if ACC or any of its subaccesses has grp_child set.
References access_or_its_child_written(), access::first_child, and access::grp_write.
Referenced by access_or_its_child_written(), and propagate_subaccesses_from_rhs().
|
static |
Add ACCESS to the work to queue for propagation of subaccesses from LHS to RHS (which is actually a stack).
References access::first_lhs_link, gcc_assert, access::grp_lhs_queued, lhs_work_queue_head, and access::next_lhs_queued.
Referenced by build_accesses_from_assign(), propagate_all_subaccesses(), and propagate_subaccesses_from_lhs().
|
static |
Add ACCESS to the work to queue for propagation of subaccesses from RHS to LHS (which is actually a stack).
References access::first_rhs_link, gcc_assert, access::grp_rhs_queued, access::next_rhs_queued, and rhs_work_queue_head.
Referenced by build_accesses_from_assign(), propagate_all_subaccesses(), propagate_subaccesses_from_rhs(), and subtree_mark_written_and_rhs_enqueue().
|
static |
Add LINK to the linked list of lhs assign links of LACC.
References access::first_lhs_link, gcc_assert, access::last_lhs_link, assign_link::next_lhs, and NULL.
Referenced by build_accesses_from_assign().
|
static |
Add LINK to the linked list of assign links of RACC.
References access::first_rhs_link, gcc_assert, access::last_rhs_link, assign_link::next_rhs, and NULL.
Referenced by build_accesses_from_assign().
|
static |
Analyze the subtree of accesses rooted in ROOT, scheduling replacements when both seeming beneficial and when ALLOW_REPLACEMENTS allows it. If TOTALLY is set, we are totally scalarizing the aggregate. Also set all sorts of access flags appropriately along the way, notably always set grp_read and grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is true. Creating a replacement for a scalar access is considered beneficial if its grp_hint ot TOTALLY is set (this means either that there is more than one direct read access or that we are attempting total scalarization) or according to the following table: Access written to through a scalar type (once or more times) | | Written to in an assignment statement | | | | Access read as scalar _once_ | | | | | | Read in an assignment statement | | | | | | | | Scalarize Comment ----------------------------------------------------------------------------- 0 0 0 0 No access for the scalar 0 0 0 1 No access for the scalar 0 0 1 0 No Single read - won't help 0 0 1 1 No The same case 0 1 0 0 No access for the scalar 0 1 0 1 No access for the scalar 0 1 1 0 Yes s = *g; return s.i; 0 1 1 1 Yes The same case as above 1 0 0 0 No Won't help 1 0 0 1 Yes s.i = 1; *g = s; 1 0 1 0 Yes s.i = 5; g = s.i; 1 0 1 1 Yes The same case as above 1 1 0 0 No Won't help. 1 1 0 1 Yes s.i = 1; *g = s; 1 1 1 0 Yes s = *g; return s.i; 1 1 1 1 Yes Any of the above yeses
References analyze_access_subtree(), access::base, bitmap_bit_p, build_bitint_type(), build_nonstandard_integer_type(), build_ref_for_offset(), cannot_scalarize_away_bitmap, comes_initialized_p(), create_access_replacement(), DECL_BIT_FIELD, DECL_UID, dump_file, dump_flags, access::expr, expr_with_var_bounded_array_refs_p(), access::first_child, gcc_assert, gcc_checking_assert, access::grp_assignment_read, access::grp_assignment_write, access::grp_covered, access::grp_hint, access::grp_partial_lhs, access::grp_read, access::grp_result_of_prop_from_lhs, access::grp_same_access_path, access::grp_scalar_read, access::grp_scalar_write, access::grp_to_be_debug_replaced, access::grp_to_be_replaced, access::grp_total_scalarization, access::grp_unscalarizable_region, access::grp_unscalarized_data, access::grp_write, INTEGRAL_TYPE_P, is_gimple_reg_type(), MAY_HAVE_DEBUG_BIND_STMTS, access::next_sibling, NULL, access::offset, access::parent, print_generic_expr(), access::replacement_decl, access::reverse, access::size, TDF_DETAILS, TREE_CODE, TREE_OPERAND, access::type, TYPE_PRECISION, TYPE_UNSIGNED, and UNKNOWN_LOCATION.
Referenced by analyze_access_subtree(), and analyze_access_trees().
Analyze all access trees linked by next_grp by the means of analyze_access_subtree.
References analyze_access_subtree(), access::grp_total_scalarization, access::next_grp, and NULL.
Referenced by analyze_all_variable_accesses().
|
static |
Go through all accesses collected throughout the (intraprocedural) analysis stage, exclude overlapping ones, identify representatives and build trees out of them, making decisions about scalarization on the way. Return true iff there are any to-be-scalarized variables after this stage.
References analyze_access_trees(), BITMAP_ALLOC, bitmap_bit_p, bitmap_copy(), BITMAP_FREE, build_access_trees(), can_totally_scalarize_forest_p(), candidate(), candidate_bitmap, cannot_scalarize_away_bitmap, cfun, constant_decl_p(), DECL_UID, disqualify_candidate(), dump_access_tree(), dump_file, dump_flags, EXECUTE_IF_SET_IN_BITMAP, get_first_repr_for_decl(), access::grp_total_scalarization, i, is_gimple_reg_type(), access::next_grp, NULL, print_generic_expr(), propagate_all_subaccesses(), should_scalarize_away_bitmap, sort_and_splice_var_accesses(), sra_get_max_scalarization_size(), statistics_counter_event(), TDF_DETAILS, totally_scalarizable_type_p(), totally_scalarize_subtree(), tree_to_uhwi(), TREE_TYPE, access::type, TYPE_SIZE, VAR_P, and verify_all_sra_access_forests().
Referenced by perform_intra_sra().
If there is still budget to create a propagation access for DECL, return true and decrement the budget. Otherwise return false.
References b, DECL_UID, dump_file, dump_flags, print_generic_expr(), propagation_budget, and TDF_DETAILS.
Referenced by propagate_subaccesses_from_lhs(), and propagate_subaccesses_from_rhs().
|
static |
Scan expression EXPR which is an argument of a call and create access structures for all accesses to candidates for scalarization. Return true if any access has been inserted. STMT must be the statement from which the expression is taken. CAN_BE_RETURNED must be true if call argument flags do not rule out that the argument is directly returned. OE_CHECK is used to remember result of a test for abnormal outgoing edges after this statement.
References abnormal_edge_after_stmt_p(), access::base, bitmap_set_bit, build_access_from_expr(), DECL_UID, disqualify_base_of_expr(), dump_file, dump_flags, ECF_RETURNS_TWICE, get_base_address(), gimple_call_flags(), passed_by_ref_in_call, print_generic_expr(), print_gimple_stmt(), access::stmt, TDF_DETAILS, TREE_CODE, TREE_OPERAND, and access::write.
Referenced by scan_function().
Scan expression EXPR and create access structures for all accesses to candidates for scalarization. Return true if any access has been inserted. STMT must be the statement from which the expression is taken, WRITE must be true if the expression is a store and false otherwise.
References access::base, bitmap_set_bit, build_access_from_expr_1(), cannot_scalarize_away_bitmap, DECL_UID, access::stmt, and access::write.
Referenced by build_access_from_call_arg(), and scan_function().
Scan expression EXPR and create access structures for all accesses to candidates for scalarization. Return the created access or NULL if none is created.
References access::base, bitmap_bit_p, candidate_bitmap, contains_view_convert_expr_p(), create_access(), DECL_P, DECL_UID, disqualify_base_of_expr(), gcc_assert, get_base_address(), access::grp_partial_lhs, NULL, sra_handled_bf_read_p(), access::stmt, storage_order_barrier_p(), TREE_CODE, TREE_OPERAND, TREE_THIS_VOLATILE, and access::write.
Referenced by build_access_from_expr(), build_accesses_from_assign(), and scan_function().
Build a subtree of accesses rooted in *ACCESS, and move the pointer in the linked list along the way. Stop when *ACCESS is NULL or the access pointed to it is not "within" the root. Return false iff some accesses partially overlap.
References build_access_subtree(), access::first_child, access::grp_write, access::next_grp, access::next_sibling, NULL, access::offset, access::parent, and access::size.
Referenced by build_access_subtree(), and build_access_trees().
Build a tree of access representatives, ACCESS is the pointer to the first one, others are linked in a list by the next_grp field. Return false iff some accesses partially overlap.
References build_access_subtree(), and access::next_grp.
Referenced by analyze_all_variable_accesses().
Scan expressions occurring in STMT, create access structures for all accesses to candidates for scalarization and remove those candidates which occur in statements or expressions that prevent them from being split apart. Return true if any access has been inserted.
References add_access_to_lhs_work_queue(), add_access_to_rhs_work_queue(), add_link_to_lhs(), add_link_to_rhs(), AGGREGATE_TYPE_P, assign_link_pool, access::base, bitmap_set_bit, build_access_from_expr_1(), cannot_scalarize_away_bitmap, comes_initialized_p(), contains_vce_or_bfcref_p(), DECL_UID, disqualify_if_bad_bb_terminating_stmt(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_clobber_p(), gimple_has_volatile_ops(), access::grp_assignment_read, access::grp_assignment_write, access::grp_unscalarizable_region, is_gimple_reg_type(), assign_link::lacc, assign_link::racc, should_scalarize_away_bitmap, access::size, SRA_MODE_EARLY_INTRA, SRA_MODE_INTRA, access::stmt, storage_order_barrier_p(), TREE_TYPE, access::type, useless_type_conversion_p(), and access::write.
Referenced by scan_function().
|
static |
Attempt to build a memory reference that we could but into a gimple debug_bind statement. Similar to build_ref_for_model but punts if it has to create statements and return s NULL instead. This function also ignores alignment issues and so its results should never end up in non-debug statements.
References build_fold_addr_expr, build_int_cst(), DECL_BIT_FIELD, access::expr, fold_build2_loc(), get_addr_base_and_unit_offset(), int_const_binop(), NULL_TREE, reference_alias_ptr_type(), TREE_CODE, TREE_OPERAND, TREE_TYPE, access::type, and unshare_expr().
Referenced by generate_subtree_copies(), load_assign_lhs_subreplacements(), and sra_modify_assign().
Construct and return a memory reference that is equal to a portion of MODEL->expr but is based on BASE. If this cannot be done, return NULL.
References access::expr, handled_component_p(), NULL_TREE, TREE_CODE, TREE_OPERAND, TREE_TYPE, types_compatible_p(), and unshare_expr().
Referenced by build_ref_for_model().
|
static |
Construct a memory reference to a part of an aggregate BASE at the given OFFSET and of the same type as MODEL. In case this is a reference to a bit-field, the function will replicate the last component_ref of model's expr to access it. INSERT_AFTER and GSI have the same meaning as in build_ref_for_offset, furthermore, when GSI is NULL, the function expects that it re-builds the entire reference from a DECL to the final access and so will create a MEM_REF when OFFSET does not exactly match offset of MODEL.
References build_reconstructed_reference(), build_ref_for_offset(), DECL_BIT_FIELD, access::expr, fold_build3_loc(), gcc_assert, access::grp_same_access_path, int_bit_position(), NULL_TREE, access::offset, REF_REVERSE_STORAGE_ORDER, access::reverse, TREE_CODE, TREE_OPERAND, TREE_THIS_VOLATILE, TREE_TYPE, access::type, and TYPE_ADDR_SPACE.
Referenced by create_artificial_child_access(), generate_subtree_copies(), load_assign_lhs_subreplacements(), propagate_subaccesses_from_rhs(), sra_modify_assign(), and sra_modify_expr().
tree build_ref_for_offset | ( | location_t | loc, |
tree | base, | ||
poly_int64 | offset, | ||
bool | reverse, | ||
tree | exp_type, | ||
gimple_stmt_iterator * | gsi, | ||
bool | insert_after ) |
Construct a MEM_REF that would reference a part of aggregate BASE of type EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is something for which get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used to insert new statements either before or below the current one as specified by INSERT_AFTER. This function is not capable of handling bitfields.
References build_aligned_type(), build_fold_addr_expr, build_int_cst(), build_pointer_type(), build_qualified_type(), ENCODE_QUAL_ADDR_SPACE, fold_build2_loc(), gcc_checking_assert, get_addr_base_and_unit_offset(), get_object_alignment_1(), gimple_build_assign(), gimple_set_location(), gsi_insert_after(), gsi_insert_before(), GSI_NEW_STMT, GSI_SAME_STMT, int_const_binop(), make_ssa_name(), MIN, REF_REVERSE_STORAGE_ORDER, reference_alias_ptr_type(), STRIP_USELESS_TYPE_CONVERSION, TREE_CODE, TREE_OPERAND, TREE_SIDE_EFFECTS, TREE_THIS_VOLATILE, TREE_TYPE, TYPE_ADDR_SPACE, TYPE_ALIGN, TYPE_QUALS, and unshare_expr().
Referenced by analyze_access_subtree(), and build_ref_for_model().
|
static |
Construct a memory reference consisting of component_refs and array_refs to a part of an aggregate *RES (which is of type TYPE). The requested part should have type EXP_TYPE at be the given OFFSET. This function might not succeed, it returns true when it does and only then *RES points to something meaningful. This function should be used only to build expressions that we might need to present to user (e.g. in warnings). In all other situations, build_ref_for_model or build_ref_for_offset should be used instead.
References bit_position(), build3(), build4(), build_int_cst(), build_user_friendly_ref_for_offset(), DECL_CHAIN, DECL_SIZE, gcc_assert, int_const_binop(), integer_zerop(), NULL_TREE, TREE_CODE, tree_fits_uhwi_p(), tree_to_uhwi(), TREE_TYPE, TYPE_DOMAIN, TYPE_FIELDS, TYPE_MIN_VALUE, TYPE_SIZE, and types_compatible_p().
Referenced by build_user_friendly_ref_for_offset(), create_artificial_child_access(), and propagate_subaccesses_from_rhs().
Return true if the forest beginning with ROOT does not contain unscalarizable regions or non-byte aligned accesses.
References access::first_child, gcc_assert, access::grp_unscalarizable_region, is_gimple_reg_type(), access::next_grp, access::next_sibling, access::offset, access::parent, access::size, and access::type.
Referenced by analyze_all_variable_accesses().
|
inlinestatic |
For a candidate UID return the candidates decl.
References candidates.
Referenced by analyze_all_variable_accesses(), candidates_list_and_hint(), best_match< GOAL_TYPE, CANDIDATE_TYPE >::consider(), dead_debug_insert_temp(), bst_traits::equal(), default_hash_traits< scalar_cond_masked_key >::equal(), int_hash_base< int >::equal(), member_function_hash_traits< Type >::equal(), pod_hash_traits< Type >::equal(), pod_hash_traits< function_point >::equal(), pointer_hash< Type >::equal(), pointer_hash< action_record >::equal(), sinfo_hashmap_traits::equal_keys(), expand_omp_metadirective(), find_closest_string(), gen_memset_value_from_prev(), option_proposer::get_completions(), get_name_for_bit_test(), pointer_hash< Type >::hash(), initialize_constant_pool_replacements(), omp_check_context_selector(), omp_declare_variant_candidates(), omp_metadirective_candidates(), redundant_insn(), op_by_pieces_d::smallest_fixed_size_mode_for_size(), vec_init_loop_exit_info(), verify_all_sra_access_forests(), and widest_fixed_size_mode_for_size().
|
static |
If type T cannot be totally scalarized, return false. Otherwise return true and push to the vector within PC offsets and lengths of all padding in the type as total scalarization would encounter it.
References sra_padding_collecting::record_padding(), totally_scalarizable_type_p(), tree_to_shwi(), and TYPE_SIZE.
Referenced by sra_total_scalarization_would_copy_same_data_p().
|
static |
Return true iff a potential new child of ACC at offset OFFSET and with size SIZE would conflict with an already existing one. If exactly such a child already exists in ACC, store a pointer to it in EXACT_MATCH.
References access::first_child, access::next_sibling, access::offset, and access::size.
Referenced by propagate_subaccesses_from_lhs(), and propagate_subaccesses_from_rhs().
|
static |
Clobber all scalar replacements in an access subtree. ACCESS is the root of the subtree to be processed. GSI is the statement iterator used for inserting statements which are added after the current statement if INSERT_AFTER is true or before it otherwise.
References build_clobber(), clobber_subtree(), access::first_child, get_access_replacement(), gimple_build_assign(), gimple_set_location(), access::grp_to_be_replaced, gsi_insert_after(), gsi_insert_before(), GSI_NEW_STMT, GSI_SAME_STMT, access::next_sibling, access::stmt, access::type, and update_stmt().
Referenced by clobber_subtree(), and sra_modify_constructor_assign().
Return true if the nature of BASE is such that it contains data even if there is no write to it in the function.
References access::base, constant_decl_p(), and TREE_CODE.
Referenced by analyze_access_subtree(), build_accesses_from_assign(), and propagate_subaccesses_from_rhs().
|
static |
Helper of QSORT function. There are pointers to accesses in the array. An access is considered smaller than another if it has smaller offset or if the offsets are the same but is size is bigger.
References a, b, f1, f2, INTEGRAL_TYPE_P, is_gimple_reg_type(), TREE_CODE, TYPE_PRECISION, TYPE_UID, and VECTOR_TYPE_P.
Referenced by sort_and_splice_var_accesses().
Return true if DECL is a VAR_DECL in the constant pool, false otherwise.
References DECL_IN_CONSTANT_POOL, and VAR_P.
Referenced by analyze_all_variable_accesses(), comes_initialized_p(), create_access(), disqualify_candidate(), generate_subtree_copies(), initialize_constant_pool_replacements(), load_assign_lhs_subreplacements(), maybe_add_sra_candidate(), and sort_and_splice_var_accesses().
|
static |
Return true if REF contains a VIEW_CONVERT_EXPR or a COMPONENT_REF with a bit-field field declaration. If TYPE_CHANGING_P is non-NULL, set the bool it points to will be set if REF contains any of the above or a MEM_REF expression that effectively performs type conversion.
References DECL_BIT_FIELD, handled_component_p(), NULL, TREE_CODE, TREE_OPERAND, TREE_TYPE, and TYPE_MAIN_VARIANT.
Referenced by build_accesses_from_assign(), and sra_modify_assign().
|
inlinestatic |
Return true if REF has an VIEW_CONVERT_EXPR somewhere in it.
References handled_component_p(), TREE_CODE, and TREE_OPERAND.
Referenced by build_access_from_expr_1().
Create and insert access for EXPR. Return created access, or NULL if it is not possible. Also scan for uses of constant pool as we go along and add to candidates.
References access::base, bitmap_bit_p, candidate_bitmap, constant_decl_p(), create_access_1(), DECL_P, DECL_SIZE, DECL_UID, disqualified_constants, disqualify_candidate(), dump_file, dump_flags, access::expr, get_ref_base_and_extent(), access::grp_unscalarizable_region, poly_int< N, C >::is_constant(), is_gimple_reg_type(), maybe_add_sra_candidate(), NULL, access::offset, print_generic_expr(), access::reverse, access::size, access::stmt, TDF_DETAILS, TREE_CODE, TREE_READONLY, tree_to_shwi(), TREE_TYPE, access::type, WIDE_INT_MAX_PRECISION, and access::write.
Referenced by build_access_from_expr_1().
|
static |
Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in the three fields. Also add it to the vector of accesses corresponding to the base. Finally, return the new access.
References access_pool, access::base, base_access_vec, access::offset, and access::size.
Referenced by create_access().
Create a variable for the given ACCESS which determines the type, name and a few other properties. Return the variable declaration and store it also to ACCESS->replacement. REG_TREE is used when creating a declaration to base a default-definition SSA name on in order to facilitate an uninitialized warning. It is used instead of the actual ACCESS type if that is not of a gimple register type.
References access::base, build_qualified_type(), copy_warning(), create_tmp_var, create_tmp_var_raw(), current_function_decl, debug_expr(), DECL_ARTIFICIAL, DECL_CONTEXT, DECL_HAS_DEBUG_EXPR_P, DECL_IGNORED_P, DECL_NAME, DECL_NAMELESS, DECL_NOT_GIMPLE_REG_P, DECL_SOURCE_LOCATION, dump_file, access::expr, get_identifier(), access::grp_no_warning, access::grp_partial_lhs, access::grp_to_be_debug_replaced, handled_component_p(), is_gimple_reg_type(), make_fancy_name(), name_obstack, NULL_TREE, access::offset, print_generic_expr(), SET_DECL_DEBUG_EXPR, access::size, sra_stats, suppress_warning(), TDF_UID, TREE_CODE, TREE_OPERAND, access::type, TYPE_MAIN_VARIANT, TYPE_QUALS, and unshare_expr_without_location().
Referenced by analyze_access_subtree(), and get_repl_default_def_ssa_name().
|
static |
Create a new child access of PARENT, with all properties just like MODEL except for its offset and with its grp_write false and grp_read true. Return the new access or NULL if it cannot be created. Note that this access is created long after all splicing and sorting, it's not located in any access vector and is automatically a representative of its group. Set the gpr_write flag of the new accesss if SET_GRP_WRITE is true.
References access_pool, access::base, build_ref_for_model(), build_user_friendly_ref_for_offset(), access::expr, EXPR_LOCATION, access::first_child, gcc_assert, access::grp_no_warning, access::grp_read, access::grp_unscalarizable_region, access::grp_write, access::next_sibling, NULL, access::offset, access::parent, access::reverse, access::size, TREE_TYPE, and access::type.
Referenced by propagate_subaccesses_from_lhs(), and propagate_subaccesses_from_rhs().
|
static |
Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and reference EXPR for total scalarization purposes and mark it as such, link it at *PTR and reshape the tree so that those elements at *PTR and their siblings which fall within the part described by POS and SIZE are moved to be children of the new access. If a partial overlap is detected, return NULL.
References a, create_total_scalarization_access(), access::first_child, access::next_sibling, NULL, access::offset, access::parent, and access::size.
Referenced by totally_scalarize_subtree().
|
static |
Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and reference EXPR for total scalarization purposes and mark it as such. Within the children of PARENT, link it in between PTR and NEXT_SIBLING.
References access_pool, access::base, access::expr, access::grp_hint, access::grp_same_access_path, access::grp_total_scalarization, access::grp_write, access::next_sibling, access::offset, access::parent, path_comparable_for_same_access(), access::reverse, reverse_storage_order_for_component_p(), access::size, and access::type.
Referenced by create_total_access_and_reshape().
|
static |
Search the given tree for a declaration by skipping handled components and exclude it from the candidates.
References DECL_P, disqualify_candidate(), and get_base_address().
Referenced by build_access_from_call_arg(), build_access_from_expr_1(), disqualify_if_bad_bb_terminating_stmt(), and scan_function().
|
static |
Remove DECL from candidates for SRA and write REASON to the dump file if there is one.
References bitmap_clear_bit(), bitmap_set_bit, candidate_bitmap, candidates, constant_decl_p(), DECL_UID, disqualified_constants, dump_file, dump_flags, print_generic_expr(), and TDF_DETAILS.
Referenced by analyze_all_variable_accesses(), create_access(), disqualify_base_of_expr(), and scan_visit_addr().
Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and there is no alternative spot where to put statements SRA might need to generate after it. The spot we are looking for is an edge leading to a single non-EH successor, if it exists and is indeed single. RHS may be NULL, in that case ignore it.
References disqualify_base_of_expr(), gimple_bb(), single_non_eh_succ(), access::stmt, and stmt_ends_bb_p().
Referenced by build_accesses_from_assign(), and scan_function().
References access::base, DECL_UID, access::expr, access::grp_assignment_read, access::grp_assignment_write, access::grp_covered, access::grp_hint, access::grp_partial_lhs, access::grp_read, access::grp_same_access_path, access::grp_scalar_read, access::grp_scalar_write, access::grp_to_be_debug_replaced, access::grp_to_be_replaced, access::grp_total_scalarization, access::grp_unscalarizable_region, access::grp_unscalarized_data, access::grp_write, HOST_WIDE_INT_PRINT_DEC, access::offset, print_generic_expr(), access::reverse, access::size, access::type, and access::write.
Referenced by dump_access_tree_1(), and sort_and_splice_var_accesses().
|
static |
Dump all access trees for a variable, given the pointer to the first root in ACCESS.
References dump_access_tree_1(), and access::next_grp.
Referenced by analyze_all_variable_accesses().
|
static |
Dump a subtree rooted in ACCESS to file F, indent by LEVEL.
References dump_access(), dump_access_tree_1(), access::first_child, i, and access::next_sibling.
Referenced by dump_access_tree(), and dump_access_tree_1().
|
static |
Perform early intraprocedural SRA.
References perform_intra_sra(), and SRA_MODE_EARLY_INTRA.
Return true if expr contains some ARRAY_REFs into a variable bounded array.
References array_ref_low_bound(), handled_component_p(), TREE_CODE, tree_fits_shwi_p(), and TREE_OPERAND.
Referenced by analyze_access_subtree().
|
static |
Find an access with required OFFSET and SIZE in a subtree of accesses rooted in ACCESS. Return NULL if it cannot be found.
References access::first_child, access::next_sibling, access::offset, and access::size.
Referenced by get_var_base_offset_size_access(), and load_assign_lhs_subreplacements().
|
static |
The very first phase of intraprocedural SRA. It marks in candidate_bitmap those with type which is suitable for scalarization.
References cfun, current_function_decl, DECL_ARGUMENTS, DECL_CHAIN, FOR_EACH_LOCAL_DECL, i, maybe_add_sra_candidate(), and VAR_P.
Referenced by perform_intra_sra().
|
static |
Generate statements copying scalar replacements of accesses within a subtree into or out of AGG. ACCESS, all its children, siblings and their children are to be processed. AGG is an aggregate type expression (can be a declaration but does not have to be, it can for example also be a mem_ref or a series of handled components). TOP_OFFSET is the offset of the processed subtree which has to be subtracted from offsets of individual accesses to get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only replacements in the interval <start_offset, start_offset + chunk_size>, otherwise copy all. GSI is a statement iterator used to place the new statements. WRITE should be true when the statements should write from AGG to the replacement and false if vice versa. if INSERT_AFTER is true, new statements will be added after the current statement in GSI, they will be added before the statement otherwise.
References build_debug_ref_for_model(), build_ref_for_model(), constant_decl_p(), access::first_child, force_gimple_operand_gsi(), generate_subtree_copies(), get_access_replacement(), gimple_build_assign(), gimple_build_debug_bind(), gimple_set_location(), access::grp_partial_lhs, access::grp_to_be_debug_replaced, access::grp_to_be_replaced, gsi_insert_after(), gsi_insert_before(), GSI_NEW_STMT, GSI_SAME_STMT, gsi_stmt(), access::next_sibling, NULL_TREE, access::offset, access::size, sra_stats, access::stmt, suppress_warning(), update_stmt(), and access::write.
Referenced by generate_subtree_copies(), handle_unscalarized_data_in_subtree(), initialize_parameter_reductions(), sra_modify_assign(), sra_modify_call_arg(), sra_modify_constructor_assign(), and sra_modify_expr().
|
static |
Generate statements to call .DEFERRED_INIT to initialize scalar replacements of accesses within a subtree ACCESS; all its children, siblings and their children are to be processed. GSI is a statement iterator used to place the new statements.
References access::first_child, generate_subtree_deferred_init(), get_access_replacement(), gimple_build_call_internal(), gimple_call_set_lhs(), gimple_set_location(), access::grp_to_be_replaced, gsi_insert_before(), GSI_SAME_STMT, access::next_sibling, sra_stats, TREE_TYPE, TYPE_SIZE_UNIT, and update_stmt().
Referenced by generate_subtree_deferred_init(), and sra_modify_deferred_init().
Search for an access representative for the given expression EXPR and return it or NULL if it cannot be found.
References access::base, bitmap_bit_p, candidate_bitmap, DECL_P, DECL_SIZE, DECL_UID, get_ref_base_and_extent(), get_var_base_offset_size_access(), poly_int< N, C >::is_constant(), known_le, NULL, access::offset, poly_int_tree_p(), access::reverse, TREE_CODE, and TREE_OPERAND.
Referenced by sra_modify_assign(), sra_modify_call_arg(), sra_modify_constructor_assign(), sra_modify_deferred_init(), and sra_modify_expr().
Return ACCESS scalar replacement, which must exist.
References gcc_checking_assert, and access::replacement_decl.
Referenced by clobber_subtree(), generate_subtree_copies(), generate_subtree_deferred_init(), init_subtree_with_zero(), initialize_constant_pool_replacements(), load_assign_lhs_subreplacements(), sra_modify_assign(), sra_modify_deferred_init(), and sra_modify_expr().
Return a vector of pointers to accesses for the variable given in BASE or NULL if there is none.
References access::base, and base_access_vec.
Referenced by get_first_repr_for_decl(), initialize_parameter_reductions(), and sort_and_splice_var_accesses().
Return the first group representative for DECL or NULL if none exists.
References access::base, get_base_access_vector(), and NULL.
Referenced by analyze_all_variable_accesses(), get_var_base_offset_size_access(), initialize_constant_pool_replacements(), and verify_all_sra_access_forests().
Create and return a new suitable default definition SSA_NAME for RACC which is an access describing an uninitialized part of an aggregate that is being loaded. REG_TREE is used instead of the actual RACC type if that is not of a gimple register type.
References cfun, create_access_replacement(), gcc_checking_assert, get_or_create_ssa_default_def(), access::grp_to_be_debug_replaced, access::grp_to_be_replaced, and access::replacement_decl.
Referenced by sra_modify_assign().
|
static |
Find an access representative for the variable BASE and given OFFSET and SIZE. Requires that access trees have already been built. Return NULL if it cannot be found.
References access::base, find_access_in_subtree(), get_first_repr_for_decl(), access::next_grp, NULL, access::offset, and access::size.
Referenced by get_access_for_expr().
|
static |
Store all replacements in the access tree rooted in TOP_RACC either to their base aggregate if there are unscalarized data or directly to LHS of the statement that is pointed to by GSI otherwise.
References subreplacement_assignment_data::assignment_lhs, subreplacement_assignment_data::assignment_rhs, access::base, access::first_child, generate_subtree_copies(), access::grp_unscalarized_data, subreplacement_assignment_data::loc, access::offset, subreplacement_assignment_data::old_gsi, subreplacement_assignment_data::refreshed, SRA_UDH_LEFT, SRA_UDH_RIGHT, subreplacement_assignment_data::top_racc, and TREE_READONLY.
Referenced by load_assign_lhs_subreplacements(), and sra_modify_assign().
|
static |
Assign zero to all scalar replacements in an access subtree. ACCESS is the root of the subtree to be processed. GSI is the statement iterator used for inserting statements which are added after the current statement if INSERT_AFTER is true or before it otherwise.
References build_zero_cst(), access::first_child, get_access_replacement(), gimple_build_assign(), gimple_build_debug_bind(), gimple_set_location(), access::grp_to_be_debug_replaced, access::grp_to_be_replaced, gsi_insert_after(), gsi_insert_before(), GSI_NEW_STMT, GSI_SAME_STMT, gsi_stmt(), init_subtree_with_zero(), access::next_sibling, access::stmt, access::type, and update_stmt().
Referenced by init_subtree_with_zero(), and sra_modify_constructor_assign().
|
static |
Set any scalar replacements of values in the constant pool to the initial value of the constant. (Constant-pool decls like *.LC0 have effectively been initialized before the program starts, we must do the same for their replacements.) Thus, we output statements like 'SR.1 = *.LC0[0];' into the function's entry block.
References candidate(), candidate_bitmap, cfun, constant_decl_p(), dump_file, dump_flags, ENTRY_BLOCK_PTR_FOR_FN, EXECUTE_IF_SET_IN_BITMAP, access::expr, access::first_child, get_access_replacement(), get_first_repr_for_decl(), gimple_build_assign(), gsi_insert_after(), gsi_insert_seq_on_edge_immediate(), GSI_NEW_STMT, gsi_seq(), gsi_start(), i, access::next_grp, access::next_sibling, NULL, access::parent, print_gimple_stmt(), access::replacement_decl, single_succ_edge(), access::stmt, TDF_DETAILS, unshare_expr(), and update_stmt().
Referenced by sra_modify_function_body().
|
static |
Generate statements initializing scalar replacements of parts of function parameters.
References bitmap_bit_p, candidate_bitmap, cfun, current_function_decl, DECL_ARGUMENTS, DECL_CHAIN, DECL_UID, ENTRY_BLOCK_PTR_FOR_FN, EXPR_LOCATION, generate_subtree_copies(), get_base_access_vector(), gsi_insert_seq_on_edge_immediate(), gsi_seq(), gsi_start(), access::next_grp, NULL, and single_succ_edge().
Referenced by perform_intra_sra().
|
static |
Perform "late" intraprocedural SRA.
References perform_intra_sra(), and SRA_MODE_INTRA.
|
static |
Try to generate statements to load all sub-replacements in an access subtree formed by children of LACC from scalar replacements in the SAD->top_racc subtree. If that is not possible, refresh the SAD->top_racc base aggregate and load the accesses from it.
References subreplacement_assignment_data::assignment_lhs, subreplacement_assignment_data::assignment_rhs, access::base, build_debug_ref_for_model(), build_ref_for_model(), constant_decl_p(), find_access_in_subtree(), access::first_child, fold_build1_loc(), force_gimple_operand_gsi(), get_access_replacement(), gimple_build_assign(), gimple_build_debug_bind(), gimple_set_location(), access::grp_covered, access::grp_partial_lhs, access::grp_read, access::grp_to_be_debug_replaced, access::grp_to_be_replaced, access::grp_write, gsi_insert_after(), GSI_NEW_STMT, GSI_SAME_STMT, gsi_stmt(), handle_unscalarized_data_in_subtree(), subreplacement_assignment_data::left_offset, load_assign_lhs_subreplacements(), subreplacement_assignment_data::loc, subreplacement_assignment_data::new_gsi, access::next_sibling, NULL, NULL_TREE, access::offset, subreplacement_assignment_data::old_gsi, subreplacement_assignment_data::refreshed, access::size, sra_stats, SRA_UDH_LEFT, SRA_UDH_NONE, SRA_UDH_RIGHT, access::stmt, subreplacement_assignment_data::top_racc, TREE_TYPE, access::type, update_stmt(), and useless_type_conversion_p().
Referenced by load_assign_lhs_subreplacements(), and sra_modify_assign().
|
static |
Append a name of the declaration to the name obstack. A helper function for make_fancy_name.
References DECL_NAME, DECL_UID, IDENTIFIER_LENGTH, IDENTIFIER_POINTER, and name_obstack.
Referenced by make_fancy_name_1().
|
static |
Create a human readable name for replacement variable of ACCESS.
References make_fancy_name_1(), and name_obstack.
Referenced by create_access_replacement().
|
static |
Helper for make_fancy_name.
References DECL_P, gcc_unreachable, HOST_WIDE_INT_PRINT_DEC, integer_zerop(), make_fancy_decl_name(), make_fancy_name_1(), name_obstack, TREE_CODE, TREE_INT_CST_LOW, and TREE_OPERAND.
Referenced by make_fancy_name(), and make_fancy_name_1().
gimple_opt_pass * make_pass_sra | ( | gcc::context * | ctxt | ) |
gimple_opt_pass * make_pass_sra_early | ( | gcc::context * | ctxt | ) |
Return true if VAR is a candidate for SRA.
References AGGREGATE_TYPE_P, aggregate_value_p(), bitmap_set_bit, candidate_bitmap, candidates, cfun, COMPLETE_TYPE_P, constant_decl_p(), current_function_decl, DECL_BY_REFERENCE, DECL_UID, dump_file, dump_flags, is_global_var(), is_va_list_type(), msg, print_generic_expr(), pt_solution_includes(), reject(), SRA_MODE_EARLY_INTRA, TDF_DETAILS, TREE_ADDRESSABLE, TREE_CODE, tree_fits_shwi_p(), TREE_THIS_VOLATILE, tree_to_shwi(), TREE_TYPE, type_internals_preclude_sra_p(), and TYPE_SIZE.
Referenced by create_access(), and find_var_candidates().
Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs ending either with a DECL or a MEM_REF with zero offset.
References DECL_P, gcc_assert, handled_component_p(), TREE_CODE, TREE_OPERAND, and zerop().
Referenced by create_total_scalarization_access(), and sort_and_splice_var_accesses().
|
static |
The "main" function of intraprocedural SRA passes. Runs the analysis and if it reveals there are components of some aggregates to be scalarized, it runs the required transformations.
References analyze_all_variable_accesses(), cfun, find_var_candidates(), initialize_parameter_reductions(), scan_function(), sra_deinitialize(), sra_initialize(), sra_modify_function_body(), sra_stats, statistics_counter_event(), TODO_cleanup_cfg, and TODO_update_ssa.
Referenced by early_intra_sra(), and late_intra_sra().
|
static |
Pop an access from the work queue for propagating from LHS to RHS, and return it, assuming there is one.
References access::grp_lhs_queued, lhs_work_queue_head, access::next_lhs_queued, and NULL.
Referenced by propagate_all_subaccesses().
|
static |
Pop an access from the work queue for propagating from RHS to LHS, and return it, assuming there is one.
References access::grp_rhs_queued, access::next_rhs_queued, NULL, and rhs_work_queue_head.
Referenced by propagate_all_subaccesses().
|
static |
Given an array type TYPE, extract element size to *EL_SIZE, minimum index to *IDX and maximum index to *MAX so that the caller can iterate over all elements and return true, except if the array is known to be zero-length, then return false.
References gcc_assert, wi::sext(), wi::to_offset(), TREE_CODE, tree_fits_shwi_p(), tree_to_shwi(), TREE_TYPE, TYPE_DOMAIN, TYPE_MAX_VALUE, TYPE_MIN_VALUE, TYPE_PRECISION, TYPE_SIZE, and TYPE_UNSIGNED.
Referenced by totally_scalarizable_type_p(), and totally_scalarize_subtree().
|
static |
Propagate all subaccesses across assignment links.
References add_access_to_lhs_work_queue(), add_access_to_rhs_work_queue(), access::base, bitmap_bit_p, candidate_bitmap, DECL_UID, access::first_lhs_link, access::first_rhs_link, gcc_assert, access::group_representative, access::grp_write, assign_link::lacc, lhs_work_queue_head, access::parent, pop_access_from_lhs_work_queue(), pop_access_from_rhs_work_queue(), propagate_subaccesses_from_lhs(), propagate_subaccesses_from_rhs(), propagation_budget, assign_link::racc, rhs_work_queue_head, and subtree_mark_written_and_rhs_enqueue().
Referenced by analyze_all_variable_accesses().
Propagate subaccesses of LACC across an assignment link to RACC if they should inhibit total scalarization of the corresponding area. No flags are being propagated in the process. Return true if anything changed.
References add_access_to_lhs_work_queue(), access::base, budget_for_propagation_access(), child_would_conflict_in_acc(), create_artificial_child_access(), access::first_child, access::grp_result_of_prop_from_lhs, access::grp_unscalarizable_region, is_gimple_reg_type(), access::next_sibling, NULL, access::offset, propagate_subaccesses_from_lhs(), access::size, access::type, and types_compatible_p().
Referenced by propagate_all_subaccesses(), and propagate_subaccesses_from_lhs().
Propagate subaccesses and grp_write flags of RACC across an assignment link to LACC. Enqueue sub-accesses as necessary so that the write flag is propagated transitively. Return true if anything changed. Additionally, if RACC is a scalar access but LACC is not, change the type of the latter, if possible.
References access_or_its_child_written(), add_access_to_rhs_work_queue(), access::base, budget_for_propagation_access(), build_ref_for_model(), build_user_friendly_ref_for_offset(), child_would_conflict_in_acc(), comes_initialized_p(), create_artificial_child_access(), access::expr, EXPR_LOCATION, access::first_child, gcc_assert, gcc_checking_assert, access::grp_hint, access::grp_no_warning, access::grp_read, access::grp_same_access_path, access::grp_unscalarizable_region, access::grp_write, is_gimple_reg_type(), access::next_sibling, NULL, access::offset, POINTER_TYPE_P, propagate_subaccesses_from_rhs(), REF_REVERSE_STORAGE_ORDER, access::reverse, access::size, subtree_mark_written_and_rhs_enqueue(), TREE_CODE, TREE_TYPE, access::type, TYPE_REVERSE_STORAGE_ORDER, types_compatible_p(), types_risk_mangled_binary_repr_p(), and VECTOR_TYPE_P.
Referenced by propagate_all_subaccesses(), and propagate_subaccesses_from_rhs().
|
static |
Print message to dump file why a variable was rejected.
References DECL_UID, dump_file, dump_flags, msg, print_generic_expr(), and TDF_DETAILS.
Referenced by combine_validate_cost(), find_reloads(), maybe_add_sra_candidate(), and process_alt_operands().
Move all link structures in their linked list in OLD_ACC to the linked list in NEW_ACC.
References access::first_lhs_link, access::first_rhs_link, gcc_assert, access::last_lhs_link, access::last_rhs_link, assign_link::next_lhs, assign_link::next_rhs, and NULL.
Referenced by sort_and_splice_var_accesses().
Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return true if the chain of these handled components are exactly the same as EXP2 and the expression under them is the same DECL or an equivalent MEM_REF. The reference picked by compare_access_positions must go to EXP1.
References is_gimple_reg_type(), OEP_ADDRESS_OF, operand_equal_p(), TREE_CODE, TREE_OPERAND, TREE_TYPE, and TYPE_MAIN_VARIANT.
Referenced by sort_and_splice_var_accesses().
|
static |
Scan function and look for interesting expressions and create access structures for them. Return true iff any access is created.
References as_a(), build_access_from_call_arg(), build_access_from_expr(), build_access_from_expr_1(), build_accesses_from_assign(), cfun, disqualify_base_of_expr(), disqualify_if_bad_bb_terminating_stmt(), EAF_NOT_RETURNED_DIRECTLY, FOR_EACH_BB_FN, gimple_asm_input_op(), gimple_asm_ninputs(), gimple_asm_noutputs(), gimple_asm_output_op(), gimple_bb(), gimple_call_arg(), gimple_call_arg_flags(), gimple_call_chain(), gimple_call_internal_p(), gimple_call_lhs(), gimple_call_num_args(), gimple_return_retval(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_start_phis(), gsi_stmt(), i, NULL, NULL_TREE, scan_visit_addr(), single_succ_p(), SRA_OUTGOING_EDGES_UNCHECKED, stmt_ends_bb_p(), TREE_VALUE, and walk_stmt_load_store_addr_ops().
Referenced by ipa_sra_summarize_function(), and perform_intra_sra().
Callback of walk_stmt_load_store_addr_ops visit_addr used to detect taking addresses of candidates a places which are not call arguments. Such candidates are disqalified from SRA. This also applies to GIMPLE_ASM operands with memory constrains which cannot be scalarized.
References DECL_P, disqualify_candidate(), and get_base_address().
Referenced by scan_function().
|
static |
Return the single non-EH successor edge of BB or NULL if there is none or more than one.
References FOR_EACH_EDGE, NULL, and basic_block_def::succs.
Referenced by disqualify_if_bad_bb_terminating_stmt(), sra_modify_assign(), and sra_modify_expr().
Sort all accesses for the given variable, check for partial overlaps and return NULL if there are any. If there are none, pick a representative for each combination of offset and size and create a linked list out of them. Return the pointer to the first representative and make sure it is the first one in the vector of accesses.
References access::base, bitmap_bit_p, compare_access_positions(), constant_decl_p(), DECL_BIT_FIELD, DECL_UID, dump_access(), dump_file, dump_flags, access::expr, gcc_assert, get_base_access_vector(), access::group_representative, access::grp_assignment_read, access::grp_assignment_write, access::grp_hint, access::grp_partial_lhs, access::grp_read, access::grp_same_access_path, access::grp_scalar_read, access::grp_scalar_write, access::grp_unscalarizable_region, access::grp_write, i, INTEGRAL_TYPE_P, is_gimple_reg_type(), access::next_grp, NULL, access::offset, passed_by_ref_in_call, path_comparable_for_same_access(), print_generic_expr(), relink_to_new_repr(), same_access_path_p(), access::size, TDF_DETAILS, TREE_CODE, TREE_OPERAND, access::type, TYPE_PRECISION, types_risk_mangled_binary_repr_p(), and access::write.
Referenced by analyze_all_variable_accesses().
|
static |
Deallocate all general structures.
References access_pool, assign_link_pool, base_access_vec, BITMAP_FREE, candidate_bitmap, candidates, cannot_scalarize_away_bitmap, disqualified_constants, name_obstack, NULL, passed_by_ref_in_call, and should_scalarize_away_bitmap.
Referenced by perform_intra_sra().
unsigned HOST_WIDE_INT sra_get_max_scalarization_size | ( | void | ) |
Get the total total scalarization size limit in the current function.
References cfun, get_move_ratio(), optimize_function_for_size_p(), and OPTION_SET_P.
Referenced by analyze_all_variable_accesses(), and ipa_icf_gimple::func_checker::safe_for_total_scalarization_p().
Return true if the BIT_FIELD_REF read EXPR is handled by SRA.
References bit_field_offset(), bit_field_size(), and pow2p_hwi().
Referenced by build_access_from_expr_1(), sra_modify_assign(), and sra_modify_expr().
|
static |
Allocate necessary structures.
References base_access_vec, BITMAP_ALLOC, candidate_bitmap, candidates, cannot_scalarize_away_bitmap, cfun, disqualified_constants, gcc_obstack_init, name_obstack, NULL, passed_by_ref_in_call, should_scalarize_away_bitmap, sra_stats, and vec_safe_length().
Referenced by perform_intra_sra().
|
static |
Examine both sides of the assignment statement pointed to by STMT, replace them with a scalare replacement if there is one and generate copying of replacements if scalarized aggregates have been used in the assignment. GSI is used to hold generated statements for type conversions and subtree copying.
References access_has_children_p(), access_has_replacements_p(), AGGREGATE_TYPE_P, subreplacement_assignment_data::assignment_lhs, subreplacement_assignment_data::assignment_rhs, access::base, build_debug_ref_for_model(), build_ref_for_model(), contains_bitfld_component_ref_p(), contains_vce_or_bfcref_p(), dump_file, access::first_child, fold_build1_loc(), force_gimple_operand_gsi(), gcc_assert, generate_subtree_copies(), get_access_for_expr(), get_access_replacement(), get_repl_default_def_ssa_name(), gimple_assign_lhs(), gimple_assign_lhs_ptr(), gimple_assign_rhs1(), gimple_assign_rhs1_ptr(), gimple_assign_set_lhs(), gimple_assign_set_rhs_from_tree(), gimple_assign_single_p(), gimple_build_debug_bind(), gimple_has_volatile_ops(), gimple_location(), access::grp_covered, access::grp_partial_lhs, access::grp_read, access::grp_to_be_debug_replaced, access::grp_to_be_replaced, access::grp_unscalarizable_region, access::grp_unscalarized_data, gsi_bb(), gsi_insert_before(), gsi_next(), gsi_none(), gsi_remove(), GSI_SAME_STMT, gsi_start_edge(), gsi_stmt(), handle_unscalarized_data_in_subtree(), is_gimple_reg_type(), subreplacement_assignment_data::left_offset, load_assign_lhs_subreplacements(), subreplacement_assignment_data::loc, subreplacement_assignment_data::new_gsi, NULL_TREE, access::offset, subreplacement_assignment_data::old_gsi, print_gimple_stmt(), subreplacement_assignment_data::refreshed, release_defs(), access::replacement_decl, access::reverse, single_non_eh_succ(), SRA_AM_MODIFIED, SRA_AM_NONE, SRA_AM_REMOVED, sra_handled_bf_read_p(), sra_modify_constructor_assign(), sra_modify_expr(), sra_stats, SRA_UDH_NONE, SRA_UDH_RIGHT, access::stmt, stmt_ends_bb_p(), subreplacement_assignment_data::top_racc, TREE_CODE, TREE_READONLY, TREE_TYPE, TYPE_REVERSE_STORAGE_ORDER, unlink_stmt_vdef(), unshare_expr(), and useless_type_conversion_p().
Referenced by sra_modify_function_body().
|
static |
If EXPR, which must be a call argument, is an ADDR_EXPR, generate writes and reads from its base before and after the call statement given in CALL_GSI and return true if any copying took place. Otherwise call sra_modify_expr on EXPR and return its value. FLAGS is what the gimple_call_arg_flags return for the given parameter.
References access::base, DECL_P, EAF_NO_DIRECT_CLOBBER, EAF_UNUSED, FOR_EACH_EDGE, generate_subtree_copies(), get_access_for_expr(), get_base_address(), gimple_location(), gsi_bb(), gsi_start_edge(), gsi_stmt(), sra_modify_expr(), access::stmt, stmt_ends_bb_p(), TREE_CODE, and TREE_OPERAND.
Referenced by sra_modify_function_body().
|
static |
Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer to the assignment and GSI is the statement iterator pointing at it. Returns the same values as sra_modify_assign.
References access_has_children_p(), clobber_subtree(), CONSTRUCTOR_NELTS, access::first_child, generate_subtree_copies(), get_access_for_expr(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_clobber_p(), gimple_location(), access::grp_covered, gsi_remove(), init_subtree_with_zero(), access::offset, release_defs(), SRA_AM_MODIFIED, SRA_AM_NONE, SRA_AM_REMOVED, access::stmt, and unlink_stmt_vdef().
Referenced by sra_modify_assign().
|
static |
For a call to .DEFERRED_INIT: var = .DEFERRED_INIT (size_of_var, init_type, name_of_var); examine the LHS variable VAR and replace it with a scalar replacement if there is one, also replace the RHS call to a call to .DEFERRED_INIT of the corresponding scalar relacement variable. Examine the subtree and do the scalar replacements in the subtree too. STMT is the call, GSI is the statment iterator to place newly created statement.
References access::first_child, gcc_assert, generate_subtree_deferred_init(), get_access_for_expr(), get_access_replacement(), gimple_call_arg(), gimple_call_lhs(), gimple_call_set_arg(), gimple_call_set_lhs(), gimple_location(), access::grp_covered, access::grp_to_be_replaced, gsi_remove(), release_defs(), SRA_AM_MODIFIED, SRA_AM_NONE, SRA_AM_REMOVED, sra_stats, access::stmt, TREE_TYPE, TYPE_SIZE_UNIT, and unlink_stmt_vdef().
Referenced by sra_modify_function_body().
|
static |
Replace the expression EXPR with a scalar replacement if there is one and generate other statements to do type conversion or subtree copying if necessary. WRITE is true if the expression is being written to (it is on a LHS of a statement or output in an assembly statement). STMT_GSI is used to place newly created statements before the processed statement, REFRESH_GSI is used to place them afterwards - unless the processed statement must end a BB in which case it is placed on the outgoing non-EH edge. REFRESH_GSI and is then used to continue iteration over the BB. If sra_modify_expr is called only once with WRITE equal to true on a given statement, both iterator parameters can point to the same one.
References access::base, build1(), build_ref_for_model(), access::first_child, force_gimple_operand_gsi(), gcc_checking_assert, generate_subtree_copies(), get_access_for_expr(), get_access_replacement(), gimple_build_assign(), gimple_build_debug_bind(), gimple_location(), gimple_set_location(), access::grp_partial_lhs, access::grp_to_be_debug_replaced, access::grp_to_be_replaced, gsi_bb(), gsi_insert_after(), gsi_insert_before(), GSI_NEW_STMT, gsi_none(), GSI_SAME_STMT, gsi_start_edge(), gsi_stmt(), make_ssa_name(), NULL_TREE, access::offset, REF_REVERSE_STORAGE_ORDER, single_non_eh_succ(), size_binop, sra_handled_bf_read_p(), sra_stats, access::stmt, stmt_ends_bb_p(), TREE_CODE, tree_fits_uhwi_p(), TREE_OPERAND, TREE_READONLY, tree_to_uhwi(), TREE_TYPE, access::type, TYPE_SIZE, useless_type_conversion_p(), and access::write.
Referenced by sra_modify_assign(), sra_modify_call_arg(), and sra_modify_function_body().
|
static |
Traverse the function body and all modifications as decided in analyze_all_variable_accesses. Return true iff the CFG has been changed.
References as_a(), cfg_changed, cfun, FOR_EACH_BB_FN, gimple_asm_input_op(), gimple_asm_ninputs(), gimple_asm_noutputs(), gimple_asm_output_op(), gimple_bb(), gimple_call_arg_flags(), gimple_call_arg_ptr(), gimple_call_chain(), gimple_call_chain_ptr(), gimple_call_internal_p(), gimple_call_lhs(), gimple_call_lhs_ptr(), gimple_call_num_args(), gimple_call_static_chain_flags(), gimple_purge_dead_eh_edges(), gimple_return_retval_ptr(), gsi_commit_edge_inserts(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), i, initialize_constant_pool_replacements(), maybe_clean_eh_stmt(), NULL_TREE, SRA_AM_MODIFIED, SRA_AM_REMOVED, sra_modify_assign(), sra_modify_call_arg(), sra_modify_deferred_init(), sra_modify_expr(), access::stmt, TREE_VALUE, and update_stmt().
Referenced by perform_intra_sra().
Given two types in an assignment, return true either if any one cannot be totally scalarized or if they have padding (i.e. not copied bits)
References check_ts_and_push_padding_to_vec(), i, and sra_padding_collecting::m_padding.
Referenced by ipa_icf_gimple::func_checker::safe_for_total_scalarization_p().
|
static |
Beginning with ACCESS, traverse its whole access subtree and mark all sub-trees as written to. If any of them has not been marked so previously and has assignment links leading from it, re-enqueue it.
References add_access_to_rhs_work_queue(), access::first_child, access::grp_write, access::next_sibling, and subtree_mark_written_and_rhs_enqueue().
Referenced by propagate_all_subaccesses(), propagate_subaccesses_from_rhs(), and subtree_mark_written_and_rhs_enqueue().
|
static |
Do all the necessary steps in total scalarization when the given aggregate type has a TYPE at POS with the given SIZE should be put into PARENT and when we have processed all its siblings with smaller offsets up until and including LAST_SEEN_SIBLING (which can be NULL). If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as appropriate. Return TOTAL_FLD_CREATE id the caller should carry on with creating a new access, TOTAL_FLD_DONE if access or accesses capable of representing the described part of the aggregate for the purposes of total scalarization already exist or TOTAL_FLD_FAILED if there is a problem which prevents total scalarization from happening at all.
References access_and_field_type_match_p(), access::first_child, is_gimple_reg_type(), access::next_sibling, access::offset, access::parent, access::size, TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED, totally_scalarize_subtree(), and access::type.
Referenced by totally_scalarize_subtree().
|
static |
Return true iff TYPE is totally scalarizable - i.e. a RECORD_TYPE or fixed-length ARRAY_TYPE with fields that are either of gimple register types (excluding bit-fields) or (recursively) scalarizable types. CONST_DECL must be true if we are considering a decl from constant pool. If it is false, char arrays will be refused. TOTAL_OFFSET is the offset of TYPE within any outer type that is being examined. If PC is non-NULL, collect padding information into the vector within the structure. The information is however only complete if the function returns true and does not contain any padding at its end.
References DECL_BIT_FIELD, DECL_CHAIN, DECL_SIZE, i, int_bit_position(), is_gimple_reg_type(), sra_padding_collecting::m_data_until, sra_padding_collecting::m_padding, NULL_TREE, prepare_iteration_over_array_elts(), sra_padding_collecting::record_padding(), totally_scalarizable_type_p(), TREE_CODE, tree_fits_shwi_p(), tree_to_shwi(), TREE_TYPE, type_contains_placeholder_p(), TYPE_DOMAIN, TYPE_FIELDS, TYPE_MAX_VALUE, TYPE_MIN_VALUE, TYPE_SIZE, and zerop().
Referenced by analyze_all_variable_accesses(), check_ts_and_push_padding_to_vec(), and totally_scalarizable_type_p().
Go over sub-tree rooted in ROOT and attempt to create scalar accesses spanning all uncovered areas covered by ROOT, return false if the attempt failed. All created accesses will have grp_unscalarizable_region set (and should be ignored if the function returns false).
References build3(), build4(), create_total_access_and_reshape(), DECL_CHAIN, DECL_SIZE, access::expr, access::first_child, gcc_checking_assert, gcc_unreachable, access::grp_unscalarizable_region, int_bit_position(), is_gimple_reg_type(), access::next_sibling, NULL, NULL_TREE, access::offset, prepare_iteration_over_array_elts(), access::size, TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED, total_should_skip_creating_access(), totally_scalarize_subtree(), TREE_CODE, tree_to_uhwi(), TREE_TYPE, access::type, TYPE_DOMAIN, TYPE_FIELDS, and wide_int_to_tree().
Referenced by analyze_all_variable_accesses(), total_should_skip_creating_access(), and totally_scalarize_subtree().
Return true iff the type contains a field or an element which does not allow scalarization.
References msg, and type_internals_preclude_sra_p_1().
Referenced by maybe_add_sra_candidate().
|
static |
Return true iff the type contains a field or an element which does not allow scalarization. Use VISITED_TYPES to avoid re-checking already checked (sub-)types.
References hash_set< KeyId, Lazy, Traits >::add(), AGGREGATE_TYPE_P, bit_position(), hash_set< KeyId, Lazy, Traits >::contains(), DECL_CHAIN, DECL_FIELD_OFFSET, DECL_SIZE, int_bit_position(), msg, TREE_CODE, tree_fits_shwi_p(), tree_fits_uhwi_p(), TREE_THIS_VOLATILE, TREE_TYPE, TYPE_FIELDS, type_internals_preclude_sra_p_1(), and TYPE_VOLATILE.
Referenced by type_internals_preclude_sra_p(), and type_internals_preclude_sra_p_1().
Return true when either T1 is a type that, when loaded into a register and stored back to memory will yield the same bits or when both T1 and T2 are compatible.
References mode_can_transfer_bits(), TYPE_MODE, and types_compatible_p().
Referenced by propagate_subaccesses_from_rhs(), and sort_and_splice_var_accesses().
DEBUG_FUNCTION void verify_all_sra_access_forests | ( | void | ) |
Verify access forests of all candidates with accesses by calling verify_access_forest on each on them.
References access::base, candidate(), candidate_bitmap, EXECUTE_IF_SET_IN_BITMAP, gcc_assert, get_first_repr_for_decl(), i, and verify_sra_access_forest().
Referenced by analyze_all_variable_accesses().
DEBUG_FUNCTION void verify_sra_access_forest | ( | struct access * | root | ) |
Traverse the access forest where ROOT is the first root and verify that various important invariants hold true.
References access::base, DECL_P, access::expr, access::first_child, gcc_assert, gcc_unreachable, get_ref_base_and_extent(), access::grp_total_scalarization, access::grp_unscalarizable_region, poly_int< N, C >::is_constant(), is_gimple_reg_type(), access::next_grp, access::next_sibling, access::offset, access::parent, access::reverse, access::size, and access::type.
Referenced by verify_all_sra_access_forests().
|
static |
Alloc pool for allocating access structures.
Referenced by create_access_1(), create_artificial_child_access(), create_total_scalarization_access(), and sra_deinitialize().
|
static |
Alloc pool for allocating assign link structures.
Referenced by build_accesses_from_assign(), and sra_deinitialize().
Base (tree) -> Vector (vec<access_p> *) map.
Referenced by create_access_1(), get_base_access_vector(), sra_deinitialize(), and sra_initialize().
|
static |
Set of candidates.
Referenced by analyze_all_variable_accesses(), build_access_from_expr_1(), create_access(), disqualify_candidate(), get_access_for_expr(), initialize_constant_pool_replacements(), initialize_parameter_reductions(), maybe_add_sra_candidate(), propagate_all_subaccesses(), sra_deinitialize(), sra_initialize(), and verify_all_sra_access_forests().
|
static |
Referenced by add_misspelling_candidates(), candidate(), candidates_list_and_hint(), check_offload_target_name(), cmdline_handle_error(), disqualify_candidate(), gcc::dump_manager::dump_switch_p(), expand_omp_metadirective(), find_closest_identifier(), find_closest_string(), find_subroutines(), find_unswitching_predicates_for_bb(), gimplify_omp_dispatch(), gimplify_omp_metadirective(), gimplify_variant_call_expr(), init_loop_unswitch_info(), instrument_decisions(), is_linear_load_p(), maybe_add_sra_candidate(), omp_declare_variant_candidates(), omp_early_resolve_metadirective(), omp_metadirective_candidates(), optimize_range_tests_cmp_bitwise(), optimize_range_tests_to_bit_test(), resolve_omp_variant_cookies(), sra_deinitialize(), sra_initialize(), and undistribute_ops_list().
|
static |
|
static |
Bitmap of candidates in the constant pool, which cannot be scalarized because this would produce non-constant expressions (e.g. Ada).
Referenced by create_access(), disqualify_candidate(), sra_deinitialize(), and sra_initialize().
|
static |
Referenced by add_access_to_lhs_work_queue(), pop_access_from_lhs_work_queue(), and propagate_all_subaccesses().
|
static |
Obstack for creation of fancy names.
Referenced by create_access_replacement(), make_fancy_decl_name(), make_fancy_name(), make_fancy_name_1(), sra_deinitialize(), and sra_initialize().
|
static |
Bitmap of candidates which are passed by reference in call arguments.
Referenced by build_access_from_call_arg(), sort_and_splice_var_accesses(), sra_deinitialize(), and sra_initialize().
Hash to limit creation of artificial accesses
Referenced by budget_for_propagation_access(), and propagate_all_subaccesses().
|
static |
Head of a linked list of accesses that need to have its subaccesses propagated to their assignment counterparts.
Referenced by add_access_to_rhs_work_queue(), pop_access_from_rhs_work_queue(), and propagate_all_subaccesses().
|
static |
Bitmap of candidates which we should try to entirely scalarize away and those which cannot be (because they are and need be used as a whole).
Referenced by analyze_all_variable_accesses(), build_accesses_from_assign(), sra_deinitialize(), and sra_initialize().
Global variable describing which aggregate reduction we are performing at the moment.
struct { ... } sra_stats |
Dump contents of ACCESS to file F in a human friendly way. If GRP is true, representative fields are dumped, otherwise those which only describe the individual access are.
Referenced by create_access_replacement(), generate_subtree_copies(), generate_subtree_deferred_init(), load_assign_lhs_subreplacements(), perform_intra_sra(), sra_initialize(), sra_modify_assign(), sra_modify_deferred_init(), and sra_modify_expr().