GCC Middle and Back End API Reference
tree-sra.cc File 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"
#include "tree-ssa-alias-compare.h"
Include dependency graph for tree-sra.cc:

Data Structures

struct  access
struct  uid_decl_hasher
class  sra_padding_collecting
struct  subreplacement_assignment_data

Typedefs

typedef struct accessaccess_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 }

Functions

static tree candidate (unsigned uid)
static void dump_access (FILE *f, struct access *access, bool grp)
static void dump_access_tree_1 (FILE *f, struct access *access, int level)
static void dump_access_tree (FILE *f, struct access *access)
static bool access_has_children_p (struct access *acc)
static bool access_has_replacements_p (struct access *acc)
static vec< access_p > * get_base_access_vector (tree base)
static struct accessfind_access_in_subtree (struct access *access, HOST_WIDE_INT offset, HOST_WIDE_INT size)
static struct accessget_first_repr_for_decl (tree base)
static struct accessget_var_base_offset_size_access (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
static void add_link_to_rhs (struct access *racc, struct assign_link *link)
static void add_link_to_lhs (struct access *lacc, struct assign_link *link)
static void relink_to_new_repr (struct access *new_acc, struct access *old_acc)
static void add_access_to_rhs_work_queue (struct access *access)
static void add_access_to_lhs_work_queue (struct access *access)
static struct accesspop_access_from_rhs_work_queue (void)
static struct accesspop_access_from_lhs_work_queue (void)
static void sra_initialize (void)
static void sra_deinitialize (void)
static bool constant_decl_p (tree decl)
static void disqualify_candidate (tree decl, const char *reason)
static bool type_internals_preclude_sra_p_1 (tree type, const char **msg, hash_set< tree > *visited_types)
bool type_internals_preclude_sra_p (tree type, const char **msg)
static struct accesscreate_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
static bool maybe_add_sra_candidate (tree)
static struct accesscreate_access (tree expr, gimple *stmt, bool write)
static bool prepare_iteration_over_array_elts (tree type, HOST_WIDE_INT *el_size, offset_int *idx, offset_int *max)
static bool totally_scalarizable_type_p (tree type, bool const_decl, HOST_WIDE_INT total_offset, sra_padding_collecting *pc)
static bool contains_view_convert_expr_p (const_tree ref)
static bool contains_vce_or_bfcref_p (const_tree ref, bool *type_changing_p=NULL)
static void disqualify_base_of_expr (tree t, const char *reason)
static bool sra_handled_bf_read_p (tree expr)
static struct accessbuild_access_from_expr_1 (tree expr, gimple *stmt, bool write)
static bool build_access_from_expr (tree expr, gimple *stmt, bool write)
static bool abnormal_edge_after_stmt_p (gimple *stmt, enum out_edge_check *oe_check)
static bool build_access_from_call_arg (tree expr, gimple *stmt, bool can_be_returned, enum out_edge_check *oe_check)
static edge single_non_eh_succ (basic_block bb)
static bool disqualify_if_bad_bb_terminating_stmt (gimple *stmt, tree lhs, tree rhs)
static bool comes_initialized_p (tree base)
static bool build_accesses_from_assign (gimple *stmt)
static bool scan_visit_addr (gimple *, tree op, tree, void *)
static bool scan_function (void)
static int compare_access_positions (const void *a, const void *b)
static void make_fancy_decl_name (tree decl)
static void make_fancy_name_1 (tree expr)
static char * make_fancy_name (tree 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)
static tree build_reconstructed_reference (location_t, tree base, struct access *model)
static tree build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset, struct access *model, gimple_stmt_iterator *gsi, bool insert_after)
static tree build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset, struct access *model)
static bool build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset, tree exp_type)
static void reject (tree var, const char *msg)
static bool find_var_candidates (void)
static bool path_comparable_for_same_access (tree expr)
static bool same_access_path_p (tree exp1, tree exp2)
static bool types_risk_mangled_binary_repr_p (tree t1, tree t2)
static struct accesssort_and_splice_var_accesses (tree var)
static tree create_access_replacement (struct access *access, tree reg_type=NULL_TREE)
static tree get_access_replacement (struct access *access)
static bool build_access_subtree (struct access **access)
static bool build_access_trees (struct access *access)
DEBUG_FUNCTION void verify_sra_access_forest (struct access *root)
DEBUG_FUNCTION void verify_all_sra_access_forests (void)
static bool expr_with_var_bounded_array_refs_p (tree expr)
static bool analyze_access_subtree (struct access *root, struct access *parent, bool allow_replacements, bool totally)
static bool analyze_access_trees (struct access *access)
static bool child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset, HOST_WIDE_INT size, struct access **exact_match)
static struct accesscreate_artificial_child_access (struct access *parent, struct access *model, HOST_WIDE_INT new_offset, bool set_grp_read, bool set_grp_write)
static void subtree_mark_written_and_rhs_enqueue (struct access *access)
static bool budget_for_propagation_access (tree decl)
static bool access_or_its_child_written (struct access *acc)
static bool propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
static bool propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
static void propagate_all_subaccesses (void)
static bool can_totally_scalarize_forest_p (struct access *root)
static struct accesscreate_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos, HOST_WIDE_INT size, tree type, tree expr, struct access **ptr, struct access *next_sibling)
static struct accesscreate_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos, HOST_WIDE_INT size, tree type, tree expr, struct access **ptr)
static bool totally_scalarize_subtree (struct access *root)
static bool access_and_field_type_match_p (tree outer, tree inner)
static enum total_sra_field_state total_should_skip_creating_access (struct access *parent, struct access **last_seen_sibling, tree type, HOST_WIDE_INT pos, HOST_WIDE_INT size)
unsigned HOST_WIDE_INT sra_get_max_scalarization_size (void)
static bool analyze_all_variable_accesses (void)
static void generate_subtree_copies (struct access *access, tree agg, HOST_WIDE_INT top_offset, HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size, gimple_stmt_iterator *gsi, bool write, bool insert_after, location_t loc)
static void init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi, bool insert_after, location_t loc)
static void clobber_subtree (struct access *access, gimple_stmt_iterator *gsi, bool insert_after, location_t loc)
static struct accessget_access_for_expr (tree expr)
static bool sra_modify_expr (tree *expr, bool write, gimple_stmt_iterator *stmt_gsi, gimple_stmt_iterator *refresh_gsi)
static bool sra_modify_call_arg (tree *expr, gimple_stmt_iterator *call_gsi, gimple_stmt_iterator *refresh_gsi, int flags)
static void handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
static void load_assign_lhs_subreplacements (struct access *lacc, struct subreplacement_assignment_data *sad)
static enum assignment_mod_result sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
static tree get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
static void generate_subtree_deferred_init (struct access *access, tree init_type, tree decl_name, gimple_stmt_iterator *gsi, location_t loc)
static enum assignment_mod_result sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
static enum assignment_mod_result sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
static void initialize_constant_pool_replacements (void)
static bool sra_modify_function_body (void)
static void initialize_parameter_reductions (void)
static unsigned int perform_intra_sra (void)
static unsigned int early_intra_sra (void)
static unsigned int late_intra_sra (void)
static bool gate_intra_sra (void)
gimple_opt_passmake_pass_sra_early (gcc::context *ctxt)
gimple_opt_passmake_pass_sra (gcc::context *ctxt)
static bool check_ts_and_push_padding_to_vec (tree type, sra_padding_collecting *pc)
bool sra_total_scalarization_would_copy_same_data_p (tree t1, tree t2)

Variables

static enum sra_mode sra_mode
static object_allocator< struct accessaccess_pool ("SRA accesses")
static object_allocator< assign_linkassign_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 accessrhs_work_queue_head
static struct accesslhs_work_queue_head
static struct { ... }  sra_stats

Typedef Documentation

◆ access_p

typedef struct access* access_p

Enumeration Type Documentation

◆ assignment_mod_result

Result code for SRA assignment modification.
Enumerator
SRA_AM_NONE 
SRA_AM_MODIFIED 
SRA_AM_REMOVED 

◆ out_edge_check

Enumerator
SRA_OUTGOING_EDGES_UNCHECKED 
SRA_OUTGOING_EDGES_OK 
SRA_OUTGOING_EDGES_FAIL 

◆ sra_mode

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 

◆ total_sra_field_state

Return type of total_should_skip_creating_access indicating whether a total scalarization access for a field/element should be created, whether it already exists or whether the entire total scalarization has to fail.
Enumerator
TOTAL_FLD_CREATE 
TOTAL_FLD_DONE 
TOTAL_FLD_FAILED 

◆ unscalarized_data_handling

Where scalar replacements of the RHS have been written to when a replacement of a LHS of an assigments cannot be direclty loaded from a replacement of the RHS.
Enumerator
SRA_UDH_NONE 
SRA_UDH_RIGHT 
SRA_UDH_LEFT 

Function Documentation

◆ abnormal_edge_after_stmt_p()

bool abnormal_edge_after_stmt_p ( gimple * stmt,
enum out_edge_check * oe_check )
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().

◆ access_and_field_type_match_p()

bool access_and_field_type_match_p ( tree outer,
tree inner )
static
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().

◆ access_has_children_p()

bool access_has_children_p ( struct access * acc)
inlinestatic
Return true iff ACC is non-NULL and has subaccesses.

References access::first_child.

Referenced by sra_modify_assign(), and sra_modify_constructor_assign().

◆ access_has_replacements_p()

bool access_has_replacements_p ( struct access * acc)
static
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().

◆ access_or_its_child_written()

bool access_or_its_child_written ( struct access * acc)
static
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().

◆ add_access_to_lhs_work_queue()

void add_access_to_lhs_work_queue ( struct access * access)
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().

◆ add_access_to_rhs_work_queue()

void add_access_to_rhs_work_queue ( struct access * access)
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().

◆ add_link_to_lhs()

void add_link_to_lhs ( struct access * lacc,
struct assign_link * link )
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().

◆ add_link_to_rhs()

void add_link_to_rhs ( struct access * racc,
struct assign_link * link )
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().

◆ analyze_access_subtree()

bool analyze_access_subtree ( struct access * root,
struct access * parent,
bool allow_replacements,
bool totally )
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_access_trees()

bool analyze_access_trees ( struct access * access)
static
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().

◆ analyze_all_variable_accesses()

◆ budget_for_propagation_access()

bool budget_for_propagation_access ( tree decl)
static
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().

◆ build_access_from_call_arg()

bool build_access_from_call_arg ( tree expr,
gimple * stmt,
bool can_be_returned,
enum out_edge_check * oe_check )
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().

◆ build_access_from_expr()

bool build_access_from_expr ( tree expr,
gimple * stmt,
bool write )
static
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().

◆ build_access_from_expr_1()

struct access * build_access_from_expr_1 ( tree expr,
gimple * stmt,
bool write )
static

◆ build_access_subtree()

bool build_access_subtree ( struct access ** access)
static
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_access_trees()

bool build_access_trees ( struct access * access)
static
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().

◆ build_accesses_from_assign()

◆ build_debug_ref_for_model()

tree build_debug_ref_for_model ( location_t loc,
tree base,
HOST_WIDE_INT offset,
struct access * model )
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().

◆ build_reconstructed_reference()

tree build_reconstructed_reference ( location_t ,
tree base,
struct access * model )
static
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().

◆ build_ref_for_model()

tree build_ref_for_model ( location_t loc,
tree base,
HOST_WIDE_INT offset,
struct access * model,
gimple_stmt_iterator * gsi,
bool insert_after )
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().

◆ build_ref_for_offset()

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().

◆ build_user_friendly_ref_for_offset()

bool build_user_friendly_ref_for_offset ( tree * res,
tree type,
HOST_WIDE_INT offset,
tree exp_type )
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().

◆ can_totally_scalarize_forest_p()

bool can_totally_scalarize_forest_p ( struct access * root)
static
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().

◆ candidate()

◆ check_ts_and_push_padding_to_vec()

bool check_ts_and_push_padding_to_vec ( tree type,
sra_padding_collecting * pc )
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().

◆ child_would_conflict_in_acc()

bool child_would_conflict_in_acc ( struct access * acc,
HOST_WIDE_INT norm_offset,
HOST_WIDE_INT size,
struct access ** exact_match )
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().

◆ clobber_subtree()

void clobber_subtree ( struct access * access,
gimple_stmt_iterator * gsi,
bool insert_after,
location_t loc )
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().

◆ comes_initialized_p()

bool comes_initialized_p ( tree base)
static
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().

◆ compare_access_positions()

int compare_access_positions ( const void * a,
const void * b )
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().

◆ constant_decl_p()

◆ contains_vce_or_bfcref_p()

bool contains_vce_or_bfcref_p ( const_tree ref,
bool * type_changing_p = NULL )
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().

◆ contains_view_convert_expr_p()

bool contains_view_convert_expr_p ( const_tree ref)
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_access()

◆ create_access_1()

struct access * create_access_1 ( tree base,
HOST_WIDE_INT offset,
HOST_WIDE_INT size )
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_access_replacement()

tree create_access_replacement ( struct access * access,
tree reg_type = NULL_TREE )
static
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().

◆ create_artificial_child_access()

struct access * create_artificial_child_access ( struct access * parent,
struct access * model,
HOST_WIDE_INT new_offset,
bool set_grp_read,
bool set_grp_write )
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().

◆ create_total_access_and_reshape()

struct access * create_total_access_and_reshape ( struct access * parent,
HOST_WIDE_INT pos,
HOST_WIDE_INT size,
tree type,
tree expr,
struct access ** ptr )
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().

◆ create_total_scalarization_access()

struct access * create_total_scalarization_access ( struct access * parent,
HOST_WIDE_INT pos,
HOST_WIDE_INT size,
tree type,
tree expr,
struct access ** ptr,
struct access * next_sibling )
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, access::reverse, reverse_storage_order_for_component_p(), access::size, and access::type.

Referenced by create_total_access_and_reshape().

◆ disqualify_base_of_expr()

void disqualify_base_of_expr ( tree t,
const char * reason )
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().

◆ disqualify_candidate()

void disqualify_candidate ( tree decl,
const char * reason )
static

◆ disqualify_if_bad_bb_terminating_stmt()

bool disqualify_if_bad_bb_terminating_stmt ( gimple * stmt,
tree lhs,
tree rhs )
static
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().

◆ dump_access()

◆ dump_access_tree()

void dump_access_tree ( FILE * f,
struct access * access )
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().

◆ dump_access_tree_1()

void dump_access_tree_1 ( FILE * f,
struct access * access,
int level )
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().

◆ early_intra_sra()

unsigned int early_intra_sra ( void )
static
Perform early intraprocedural SRA.

References perform_intra_sra(), and SRA_MODE_EARLY_INTRA.

◆ expr_with_var_bounded_array_refs_p()

bool expr_with_var_bounded_array_refs_p ( tree expr)
static
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().

◆ find_access_in_subtree()

struct access * find_access_in_subtree ( struct access * access,
HOST_WIDE_INT offset,
HOST_WIDE_INT size )
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().

◆ find_var_candidates()

bool find_var_candidates ( void )
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().

◆ gate_intra_sra()

bool gate_intra_sra ( void )
static

References dbg_cnt().

◆ generate_subtree_copies()

void generate_subtree_copies ( struct access * access,
tree agg,
HOST_WIDE_INT top_offset,
HOST_WIDE_INT start_offset,
HOST_WIDE_INT chunk_size,
gimple_stmt_iterator * gsi,
bool write,
bool insert_after,
location_t loc )
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().

◆ generate_subtree_deferred_init()

void generate_subtree_deferred_init ( struct access * access,
tree init_type,
tree decl_name,
gimple_stmt_iterator * gsi,
location_t loc )
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().

◆ get_access_for_expr()

◆ get_access_replacement()

◆ get_base_access_vector()

vec< access_p > * get_base_access_vector ( tree base)
static
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().

◆ get_first_repr_for_decl()

struct access * get_first_repr_for_decl ( tree base)
static
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().

◆ get_repl_default_def_ssa_name()

tree get_repl_default_def_ssa_name ( struct access * racc,
tree reg_type )
static
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().

◆ get_var_base_offset_size_access()

struct access * get_var_base_offset_size_access ( tree base,
HOST_WIDE_INT offset,
HOST_WIDE_INT size )
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().

◆ handle_unscalarized_data_in_subtree()

void handle_unscalarized_data_in_subtree ( struct subreplacement_assignment_data * sad)
static

◆ init_subtree_with_zero()

void init_subtree_with_zero ( struct access * access,
gimple_stmt_iterator * gsi,
bool insert_after,
location_t loc )
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().

◆ initialize_constant_pool_replacements()

void initialize_constant_pool_replacements ( void )
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().

◆ initialize_parameter_reductions()

void initialize_parameter_reductions ( void )
static

◆ late_intra_sra()

unsigned int late_intra_sra ( void )
static
Perform "late" intraprocedural SRA.

References perform_intra_sra(), and SRA_MODE_INTRA.

◆ load_assign_lhs_subreplacements()

void load_assign_lhs_subreplacements ( struct access * lacc,
struct subreplacement_assignment_data * sad )
static

◆ make_fancy_decl_name()

void make_fancy_decl_name ( tree decl)
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().

◆ make_fancy_name()

char * make_fancy_name ( tree expr)
static
Create a human readable name for replacement variable of ACCESS.

References make_fancy_name_1(), and name_obstack.

Referenced by create_access_replacement().

◆ make_fancy_name_1()

◆ make_pass_sra()

gimple_opt_pass * make_pass_sra ( gcc::context * ctxt)

◆ make_pass_sra_early()

gimple_opt_pass * make_pass_sra_early ( gcc::context * ctxt)

◆ maybe_add_sra_candidate()

◆ path_comparable_for_same_access()

bool path_comparable_for_same_access ( tree expr)
static
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 sort_and_splice_var_accesses().

◆ perform_intra_sra()

unsigned int perform_intra_sra ( void )
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().

◆ pop_access_from_lhs_work_queue()

struct access * pop_access_from_lhs_work_queue ( void )
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().

◆ pop_access_from_rhs_work_queue()

struct access * pop_access_from_rhs_work_queue ( void )
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().

◆ prepare_iteration_over_array_elts()

bool prepare_iteration_over_array_elts ( tree type,
HOST_WIDE_INT * el_size,
offset_int * idx,
offset_int * max )
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().

◆ propagate_all_subaccesses()

◆ propagate_subaccesses_from_lhs()

bool propagate_subaccesses_from_lhs ( struct access * lacc,
struct access * racc )
static
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_from_rhs()

◆ reject()

void reject ( tree var,
const char * msg )
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().

◆ relink_to_new_repr()

void relink_to_new_repr ( struct access * new_acc,
struct access * old_acc )
static
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().

◆ same_access_path_p()

bool same_access_path_p ( tree exp1,
tree exp2 )
static
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().

◆ scan_function()

◆ scan_visit_addr()

bool scan_visit_addr ( gimple * ,
tree op,
tree ,
void *  )
static
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().

◆ single_non_eh_succ()

edge single_non_eh_succ ( basic_block bb)
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_and_splice_var_accesses()

◆ sra_deinitialize()

◆ sra_get_max_scalarization_size()

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().

◆ sra_handled_bf_read_p()

bool sra_handled_bf_read_p ( tree expr)
static
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().

◆ sra_initialize()

◆ sra_modify_assign()

enum assignment_mod_result sra_modify_assign ( gimple * stmt,
gimple_stmt_iterator * gsi )
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().

◆ sra_modify_call_arg()

bool sra_modify_call_arg ( tree * expr,
gimple_stmt_iterator * call_gsi,
gimple_stmt_iterator * refresh_gsi,
int flags )
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().

◆ sra_modify_constructor_assign()

enum assignment_mod_result sra_modify_constructor_assign ( gimple * stmt,
gimple_stmt_iterator * gsi )
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().

◆ sra_modify_deferred_init()

enum assignment_mod_result sra_modify_deferred_init ( gimple * stmt,
gimple_stmt_iterator * gsi )
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().

◆ sra_modify_expr()

bool sra_modify_expr ( tree * expr,
bool write,
gimple_stmt_iterator * stmt_gsi,
gimple_stmt_iterator * refresh_gsi )
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().

◆ sra_modify_function_body()

◆ sra_total_scalarization_would_copy_same_data_p()

bool sra_total_scalarization_would_copy_same_data_p ( tree t1,
tree t2 )
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().

◆ subtree_mark_written_and_rhs_enqueue()

void subtree_mark_written_and_rhs_enqueue ( struct access * access)
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().

◆ total_should_skip_creating_access()

enum total_sra_field_state total_should_skip_creating_access ( struct access * parent,
struct access ** last_seen_sibling,
tree type,
HOST_WIDE_INT pos,
HOST_WIDE_INT size )
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().

◆ totally_scalarizable_type_p()

bool totally_scalarizable_type_p ( tree type,
bool const_decl,
HOST_WIDE_INT total_offset,
sra_padding_collecting * pc )
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().

◆ totally_scalarize_subtree()

bool totally_scalarize_subtree ( struct access * root)
static

◆ type_internals_preclude_sra_p()

bool type_internals_preclude_sra_p ( tree type,
const char ** msg )
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().

◆ type_internals_preclude_sra_p_1()

bool type_internals_preclude_sra_p_1 ( tree type,
const char ** msg,
hash_set< tree > * visited_types )
static

◆ types_risk_mangled_binary_repr_p()

bool types_risk_mangled_binary_repr_p ( tree t1,
tree t2 )
static
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().

◆ verify_all_sra_access_forests()

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().

◆ verify_sra_access_forest()

Variable Documentation

◆ access_pool

object_allocator< struct access > access_pool("SRA accesses") ( "SRA accesses" )
static
Alloc pool for allocating access structures.

Referenced by create_access_1(), create_artificial_child_access(), create_total_scalarization_access(), and sra_deinitialize().

◆ assign_link_pool

object_allocator< assign_link > assign_link_pool("SRA links") ( "SRA links" )
static
Alloc pool for allocating assign link structures.

Referenced by build_accesses_from_assign(), and sra_deinitialize().

◆ base_access_vec

hash_map<tree, auto_vec<access_p> >* base_access_vec
static
Base (tree) -> Vector (vec<access_p> *) map.

Referenced by create_access_1(), get_base_access_vector(), sra_deinitialize(), and sra_initialize().

◆ candidate_bitmap

◆ candidates

◆ cannot_scalarize_away_bitmap

◆ disqualified_constants

bitmap disqualified_constants
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().

◆ lhs_work_queue_head

◆ name_obstack

struct obstack name_obstack
static

◆ passed_by_ref_in_call

bitmap passed_by_ref_in_call
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().

◆ propagation_budget

hash_map<tree, unsigned>* propagation_budget
static
Hash to limit creation of artificial accesses

Referenced by budget_for_propagation_access(), and propagate_all_subaccesses().

◆ rhs_work_queue_head

struct access* rhs_work_queue_head
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().

◆ should_scalarize_away_bitmap

bitmap should_scalarize_away_bitmap
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().

◆ sra_mode

enum sra_mode sra_mode
static
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().