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 dependency graph for tree-sra.cc:

Data Structures

struct  access
 
struct  assign_link
 
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 charmake_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 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
 
struct { 
 
   int   replacements 
 
   int   exprs 
 
   int   subtree_copies 
 
   int   subreplacements 
 
   int   deleted 
 
   int   separate_lhs_rhs_handling 
 
   int   deleted_unused_parameters 
 
   int   scalar_by_ref_to_by_val 
 
   int   aggregate_params_reduced 
 
   int   param_reductions_created 
 
   int   deferred_init 
 
   int   subtree_deferred_init 
 
sra_stats 
 

Typedef Documentation

◆ 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

Scalar Replacement of Aggregates (SRA) converts some structure
   references into scalar references, exposing them to the scalar
   optimizers.
   Copyright (C) 2008-2024 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()

static 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, ggc_alloc(), 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()

static 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, ggc_alloc(), TREE_CODE, TREE_TYPE, TYPE_FIELDS, TYPE_MAIN_VARIANT, and zerop().

Referenced by total_should_skip_creating_access().

◆ access_has_children_p()

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

References ggc_alloc().

Referenced by sra_modify_assign(), and sra_modify_constructor_assign().

◆ access_has_replacements_p()

static 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(), ggc_alloc(), and access::next_sibling.

Referenced by access_has_replacements_p(), and sra_modify_assign().

◆ access_or_its_child_written()

static 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(), and ggc_alloc().

Referenced by access_or_its_child_written(), and propagate_subaccesses_from_rhs().

◆ add_access_to_lhs_work_queue()

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

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

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

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

static 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, ggc_alloc(), 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()

static 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(), ggc_alloc(), access::grp_total_scalarization, access::next_grp, and NULL.

Referenced by analyze_all_variable_accesses().

◆ analyze_all_variable_accesses()

◆ budget_for_propagation_access()

static 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, hash_map< KeyId, Value, Traits >::get(), ggc_alloc(), print_generic_expr(), propagation_budget, hash_map< KeyId, Value, Traits >::put(), and TDF_DETAILS.

Referenced by propagate_subaccesses_from_lhs(), and propagate_subaccesses_from_rhs().

◆ build_access_from_call_arg()

static 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, get_base_address(), ggc_alloc(), 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()

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

static struct access * build_access_from_expr_1 ( tree expr,
gimple * stmt,
bool write )
static
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(), ggc_alloc(), 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_access_subtree()

static 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, ggc_alloc(), access::grp_write, access::next_grp, NULL, access::offset, access::parent, and access::size.

Referenced by build_access_subtree(), and build_access_trees().

◆ build_access_trees()

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

static 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, fold_build2_loc(), get_addr_base_and_unit_offset(), ggc_alloc(), int_const_binop(), NULL_TREE, offset, reference_alias_ptr_type(), TREE_CODE, TREE_OPERAND, TREE_TYPE, and unshare_expr().

Referenced by generate_subtree_copies(), load_assign_lhs_subreplacements(), and sra_modify_assign().

◆ build_reconstructed_reference()

static 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 expr, ggc_alloc(), 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()

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
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, fold_build3_loc(), gcc_assert, ggc_alloc(), int_bit_position(), NULL_TREE, offset, REF_REVERSE_STORAGE_ORDER, TREE_CODE, TREE_OPERAND, TREE_THIS_VOLATILE, TREE_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(), ggc_alloc(), 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, offset, 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()

static 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, expr, gcc_assert, ggc_alloc(), int_const_binop(), integer_zerop(), NULL_TREE, offset, 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()

static 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, ggc_alloc(), 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()

static 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 ggc_alloc(), 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()

static 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 ggc_alloc(), access::next_sibling, access::offset, and access::size.

Referenced by propagate_subaccesses_from_lhs(), and propagate_subaccesses_from_rhs().

◆ clobber_subtree()

static 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(), ggc_alloc(), 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()

static 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(), ggc_alloc(), and TREE_CODE.

Referenced by analyze_access_subtree(), build_accesses_from_assign(), and propagate_subaccesses_from_rhs().

◆ compare_access_positions()

static 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, ggc_alloc(), 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()

static 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, ggc_alloc(), handled_component_p(), 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()

static bool contains_view_convert_expr_p ( const_tree ref)
inlinestatic
Return true if REF has an VIEW_CONVERT_EXPR somewhere in it.   

References ggc_alloc(), handled_component_p(), TREE_CODE, and TREE_OPERAND.

Referenced by build_access_from_expr_1().

◆ create_access()

◆ create_access_1()

static 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, ggc_alloc(), offset, access::offset, and access::size.

Referenced by create_access().

◆ create_access_replacement()

static 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(), ggc_alloc(), 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, 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()

static 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(), expr, access::expr, EXPR_LOCATION, access::first_child, gcc_assert, ggc_alloc(), access::grp_no_warning, access::grp_read, 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()

static 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(), ggc_alloc(), access::next_sibling, NULL, access::offset, access::parent, and access::size.

Referenced by totally_scalarize_subtree().

◆ create_total_scalarization_access()

static 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, expr, access::expr, ggc_alloc(), 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, type(), and access::type.

Referenced by create_total_access_and_reshape().

◆ disqualify_base_of_expr()

static 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(), get_base_address(), and ggc_alloc().

Referenced by build_access_from_call_arg(), build_access_from_expr_1(), disqualify_if_bad_bb_terminating_stmt(), and scan_function().

◆ disqualify_candidate()

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

◆ disqualify_if_bad_bb_terminating_stmt()

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

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

static 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, ggc_alloc(), i, and access::next_sibling.

Referenced by dump_access_tree(), and dump_access_tree_1().

◆ early_intra_sra()

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

static 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(), ggc_alloc(), handled_component_p(), TREE_CODE, tree_fits_shwi_p(), and TREE_OPERAND.

Referenced by analyze_access_subtree().

◆ find_access_in_subtree()

static 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, offset, access::offset, and access::size.

Referenced by get_var_base_offset_size_access(), and load_assign_lhs_subreplacements().

◆ find_var_candidates()

static 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, ggc_alloc(), i, maybe_add_sra_candidate(), and VAR_P.

Referenced by perform_intra_sra().

◆ gate_intra_sra()

static bool gate_intra_sra ( void )
static

References dbg_cnt(), and ggc_alloc().

◆ generate_subtree_copies()

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
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(), expr, access::first_child, force_gimple_operand_gsi(), generate_subtree_copies(), get_access_replacement(), ggc_alloc(), 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()

static 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(), ggc_alloc(), 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()

static struct access * get_access_for_expr ( tree expr)
static

◆ get_access_replacement()

◆ get_base_access_vector()

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

static struct access * get_first_repr_for_decl ( tree base)
static

◆ get_repl_default_def_ssa_name()

static 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(), ggc_alloc(), 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()

static 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, offset, access::offset, and access::size.

Referenced by get_access_for_expr().

◆ handle_unscalarized_data_in_subtree()

static void handle_unscalarized_data_in_subtree ( struct subreplacement_assignment_data * sad)
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 generate_subtree_copies(), ggc_alloc(), SRA_UDH_LEFT, SRA_UDH_RIGHT, and TREE_READONLY.

Referenced by load_assign_lhs_subreplacements(), and sra_modify_assign().

◆ init_subtree_with_zero()

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

static 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(), ggc_alloc(), 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()

◆ late_intra_sra()

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

References perform_intra_sra(), and SRA_MODE_INTRA.

◆ load_assign_lhs_subreplacements()

◆ make_fancy_decl_name()

static 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, ggc_alloc(), IDENTIFIER_LENGTH, IDENTIFIER_POINTER, and name_obstack.

Referenced by make_fancy_name_1().

◆ make_fancy_name()

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

References ggc_alloc(), 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)

References ggc_alloc().

◆ make_pass_sra_early()

gimple_opt_pass * make_pass_sra_early ( gcc::context * ctxt)

References ggc_alloc().

◆ maybe_add_sra_candidate()

◆ path_comparable_for_same_access()

static 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, ggc_alloc(), handled_component_p(), TREE_CODE, TREE_OPERAND, and zerop().

Referenced by create_total_scalarization_access(), and sort_and_splice_var_accesses().

◆ perform_intra_sra()

static 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(), ggc_alloc(), 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()

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

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

static 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, ggc_alloc(), 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()

static 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, ggc_alloc(), access::grp_unscalarizable_region, is_gimple_reg_type(), NULL, access::offset, propagate_subaccesses_from_lhs(), access::type, and types_compatible_p().

Referenced by propagate_all_subaccesses(), and propagate_subaccesses_from_lhs().

◆ propagate_subaccesses_from_rhs()

◆ reject()

static 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, ggc_alloc(), 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()

static 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 gcc_assert, ggc_alloc(), and NULL.

Referenced by sort_and_splice_var_accesses().

◆ same_access_path_p()

static 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 ggc_alloc(), 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()

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

static 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, ggc_alloc(), 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(), ggc_alloc(), 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()

static 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(), ggc_alloc(), offset, and pow2p_hwi().

Referenced by build_access_from_expr_1(), sra_modify_assign(), and sra_modify_expr().

◆ sra_initialize()

◆ sra_modify_assign()

static 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, 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(), ggc_alloc(), 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(), load_assign_lhs_subreplacements(), subreplacement_assignment_data::loc, NULL_TREE, access::offset, print_gimple_stmt(), 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(), 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()

static 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(), ggc_alloc(), gimple_location(), gsi_bb(), gsi_start_edge(), gsi_stmt(), sra_modify_expr(), access::stmt, stmt_ends_bb_p(), basic_block_def::succs, TREE_CODE, and TREE_OPERAND.

Referenced by sra_modify_function_body().

◆ sra_modify_constructor_assign()

static 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, generate_subtree_copies(), get_access_for_expr(), ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_clobber_p(), gimple_location(), gsi_remove(), init_subtree_with_zero(), 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()

static 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 gcc_assert, generate_subtree_deferred_init(), get_access_for_expr(), get_access_replacement(), ggc_alloc(), gimple_call_arg(), gimple_call_lhs(), gimple_call_set_arg(), gimple_call_set_lhs(), gimple_location(), 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()

static 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(), expr, access::first_child, force_gimple_operand_gsi(), gcc_checking_assert, generate_subtree_copies(), get_access_for_expr(), get_access_replacement(), ggc_alloc(), 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, 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(), ggc_alloc(), and i.

Referenced by ipa_icf_gimple::func_checker::safe_for_total_scalarization_p().

◆ subtree_mark_written_and_rhs_enqueue()

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

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 )
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, ggc_alloc(), is_gimple_reg_type(), access::parent, access::size, TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED, and totally_scalarize_subtree().

Referenced by totally_scalarize_subtree().

◆ totally_scalarizable_type_p()

static 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, ggc_alloc(), i, int_bit_position(), is_gimple_reg_type(), NULL_TREE, prepare_iteration_over_array_elts(), 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()

static 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 ggc_alloc(), msg, and type_internals_preclude_sra_p_1().

Referenced by maybe_add_sra_candidate().

◆ type_internals_preclude_sra_p_1()

static bool type_internals_preclude_sra_p_1 ( tree type,
const char ** msg,
hash_set< tree > * visited_types )
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 AGGREGATE_TYPE_P, bit_position(), DECL_CHAIN, DECL_FIELD_OFFSET, DECL_SIZE, ggc_alloc(), 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().

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

◆ aggregate_params_reduced

int aggregate_params_reduced

◆ 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

◆ deferred_init

int deferred_init

◆ deleted

◆ deleted_unused_parameters

int deleted_unused_parameters

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

◆ exprs

◆ lhs_work_queue_head

◆ name_obstack

struct obstack name_obstack
static

◆ param_reductions_created

int param_reductions_created

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

◆ replacements

int replacements

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

◆ scalar_by_ref_to_by_val

int scalar_by_ref_to_by_val

◆ separate_lhs_rhs_handling

int separate_lhs_rhs_handling

◆ 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

Global variable describing which aggregate reduction we are performing at
the moment.   

◆ [struct]

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

◆ subreplacements

int subreplacements

◆ subtree_copies

int subtree_copies

◆ subtree_deferred_init

int subtree_deferred_init