GCC Middle and Back End API Reference
tree-ssa-loop-ivopts.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "tree-pass.h"
#include "memmodel.h"
#include "tm_p.h"
#include "ssa.h"
#include "expmed.h"
#include "insn-config.h"
#include "emit-rtl.h"
#include "recog.h"
#include "cgraph.h"
#include "gimple-pretty-print.h"
#include "alias.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "tree-eh.h"
#include "gimplify.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "tree-cfg.h"
#include "tree-ssa-loop-ivopts.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
#include "explow.h"
#include "expr.h"
#include "tree-dfa.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "tree-affine.h"
#include "tree-ssa-propagate.h"
#include "tree-ssa-address.h"
#include "builtins.h"
#include "tree-vectorizer.h"
#include "dbgcnt.h"
#include "cfganal.h"
#include "langhooks.h"
#include "gt-tree-ssa-loop-ivopts.h"
Include dependency graph for tree-ssa-loop-ivopts.cc:

Data Structures

struct  iv
 
struct  version_info
 
class  comp_cost
 
class  cost_pair
 
struct  iv_use
 
struct  iv_group
 
struct  iv_cand
 
class  iv_common_cand
 
struct  iv_common_cand_hasher
 
struct  iv_inv_expr_ent
 
struct  iv_inv_expr_hasher
 
struct  ivopts_data
 
class  iv_ca
 
struct  iv_ca_delta
 
struct  ifs_ivopts_data
 
struct  walk_tree_data
 
struct  ainc_cost_data
 

Macros

#define INFTY   1000000000
 
#define CONSIDER_ALL_CANDIDATES_BOUND    ((unsigned) param_iv_consider_all_candidates_bound)
 
#define MAX_CONSIDERED_GROUPS    ((unsigned) param_iv_max_considered_uses)
 
#define ALWAYS_PRUNE_CAND_SET_BOUND    ((unsigned) param_iv_always_prune_cand_set_bound)
 
#define COST_SCALING_FACTOR_BOUND   (20)
 

Enumerations

enum  use_type { USE_NONLINEAR_EXPR , USE_REF_ADDRESS , USE_PTR_ADDRESS , USE_COMPARE }
 
enum  iv_position {
  IP_NORMAL , IP_END , IP_BEFORE_USE , IP_AFTER_USE ,
  IP_ORIGINAL
}
 
enum  comp_iv_rewrite { COMP_IV_NA , COMP_IV_EXPR , COMP_IV_EXPR_2 , COMP_IV_ELIM }
 
enum  ainc_type {
  AINC_PRE_INC , AINC_PRE_DEC , AINC_POST_INC , AINC_POST_DEC ,
  AINC_NONE
}
 

Functions

static HOST_WIDE_INT avg_loop_niter (class loop *loop)
 
comp_cost operator+ (comp_cost cost1, comp_cost cost2)
 
comp_cost operator- (comp_cost cost1, comp_cost cost2)
 
bool operator< (comp_cost cost1, comp_cost cost2)
 
bool operator== (comp_cost cost1, comp_cost cost2)
 
bool operator<= (comp_cost cost1, comp_cost cost2)
 
static int sort_iv_inv_expr_ent (const void *a, const void *b)
 
bool address_p (use_type type)
 
static comp_cost force_expr_to_var_cost (tree, bool)
 
edge single_dom_exit (class loop *loop)
 
void dump_iv (FILE *file, struct iv *iv, bool dump_name, unsigned indent_level)
 
void dump_use (FILE *file, struct iv_use *use)
 
void dump_groups (FILE *file, struct ivopts_data *data)
 
void dump_cand (FILE *file, struct iv_cand *cand)
 
static struct version_infover_info (struct ivopts_data *data, unsigned ver)
 
static struct version_infoname_info (struct ivopts_data *data, tree name)
 
static bool stmt_after_ip_normal_pos (class loop *loop, gimple *stmt)
 
static bool stmt_after_inc_pos (struct iv_cand *cand, gimple *stmt, bool true_if_equal)
 
static bool stmt_after_increment (class loop *loop, struct iv_cand *cand, gimple *stmt)
 
static tree contains_abnormal_ssa_name_p_1 (tree *tp, int *walk_subtrees, void *)
 
bool contains_abnormal_ssa_name_p (tree expr)
 
static class tree_niter_descniter_for_exit (struct ivopts_data *data, edge exit)
 
static class tree_niter_descniter_for_single_dom_exit (struct ivopts_data *data)
 
static void tree_ssa_iv_optimize_init (struct ivopts_data *data)
 
static tree determine_base_object_1 (tree *tp, int *walk_subtrees, void *wdata)
 
static tree determine_base_object (struct ivopts_data *data, tree expr)
 
static bool contain_complex_addr_expr (tree expr)
 
static struct ivalloc_iv (struct ivopts_data *data, tree base, tree step, bool no_overflow=false)
 
static void set_iv (struct ivopts_data *data, tree iv, tree base, tree step, bool no_overflow)
 
static struct ivget_iv (struct ivopts_data *data, tree var)
 
static tree extract_single_var_from_expr (tree expr)
 
static bool find_bivs (struct ivopts_data *data)
 
static void mark_bivs (struct ivopts_data *data)
 
static bool find_givs_in_stmt_scev (struct ivopts_data *data, gimple *stmt, affine_iv *iv)
 
static void find_givs_in_stmt (struct ivopts_data *data, gimple *stmt)
 
static void find_givs_in_bb (struct ivopts_data *data, basic_block bb)
 
static void find_givs (struct ivopts_data *data, basic_block *body)
 
static bool find_induction_variables (struct ivopts_data *data, basic_block *body)
 
static struct iv_userecord_use (struct iv_group *group, tree *use_p, struct iv *iv, gimple *stmt, enum use_type type, tree mem_type, tree addr_base, poly_uint64 addr_offset)
 
static void record_invariant (struct ivopts_data *data, tree op, bool nonlinear_use)
 
static struct iv_grouprecord_group (struct ivopts_data *data, enum use_type type)
 
static struct iv_userecord_group_use (struct ivopts_data *data, tree *use_p, struct iv *iv, gimple *stmt, enum use_type type, tree mem_type)
 
static struct iv_usefind_interesting_uses_op (struct ivopts_data *data, tree op)
 
static enum comp_iv_rewrite extract_cond_operands (struct ivopts_data *data, gimple *stmt, tree **control_var, tree **bound, struct iv **iv_var, struct iv **iv_bound)
 
static void find_interesting_uses_cond (struct ivopts_data *data, gimple *stmt)
 
class loopoutermost_invariant_loop_for_expr (class loop *loop, tree expr)
 
bool expr_invariant_in_loop_p (class loop *loop, tree expr)
 
static struct ivfind_deriving_biv_for_expr (struct ivopts_data *data, tree expr)
 
static void record_biv_for_address_use (struct ivopts_data *data, struct iv *biv)
 
static bool idx_find_step (tree base, tree *idx, void *data)
 
static bool idx_record_use (tree base, tree *idx, void *vdata)
 
static bool constant_multiple_of (tree top, tree bot, widest_int *mul)
 
static bool may_be_unaligned_p (tree ref, tree step)
 
bool may_be_nonaddressable_p (tree expr)
 
static void find_interesting_uses_address (struct ivopts_data *data, gimple *stmt, tree *op_p)
 
static void find_invariants_stmt (struct ivopts_data *data, gimple *stmt)
 
static tree get_mem_type_for_internal_fn (gcall *call, tree *op_p)
 
static bool find_address_like_use (struct ivopts_data *data, gimple *stmt, tree *op_p, struct iv *iv)
 
static void find_interesting_uses_stmt (struct ivopts_data *data, gimple *stmt)
 
static void find_interesting_uses_outside (struct ivopts_data *data, edge exit)
 
static bool addr_offset_valid_p (struct iv_use *use, poly_int64 offset)
 
static int group_compare_offset (const void *a, const void *b)
 
static bool split_small_address_groups_p (struct ivopts_data *data)
 
static void split_address_groups (struct ivopts_data *data)
 
static void find_interesting_uses (struct ivopts_data *data, basic_block *body)
 
static tree strip_offset_1 (tree expr, bool inside_addr, bool top_compref, poly_int64 *offset)
 
static tree strip_offset (tree expr, poly_uint64 *offset)
 
static tree generic_type_for (tree type)
 
static tree find_inv_vars_cb (tree *expr_p, int *ws, void *data)
 
static void find_inv_vars (struct ivopts_data *data, tree *expr_p, bitmap *inv_vars)
 
static iv_inv_expr_entget_loop_invariant_expr (struct ivopts_data *data, tree inv_expr)
 
static tree find_ssa_undef (tree *tp, int *walk_subtrees, void *bb_)
 
static struct iv_candadd_candidate_1 (struct ivopts_data *data, tree base, tree step, bool important, enum iv_position pos, struct iv_use *use, gimple *incremented_at, struct iv *orig_iv=NULL, bool doloop=false)
 
static bool allow_ip_end_pos_p (class loop *loop)
 
static void add_autoinc_candidates (struct ivopts_data *data, tree base, tree step, bool important, struct iv_use *use)
 
static void add_candidate (struct ivopts_data *data, tree base, tree step, bool important, struct iv_use *use, struct iv *orig_iv=NULL, bool doloop=false)
 
static void add_standard_iv_candidates (struct ivopts_data *data)
 
static void add_iv_candidate_for_biv (struct ivopts_data *data, struct iv *iv)
 
static void add_iv_candidate_for_bivs (struct ivopts_data *data)
 
static void record_common_cand (struct ivopts_data *data, tree base, tree step, struct iv_use *use)
 
static int common_cand_cmp (const void *p1, const void *p2)
 
static void add_iv_candidate_derived_from_uses (struct ivopts_data *data)
 
static void add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use)
 
static void add_iv_candidate_for_groups (struct ivopts_data *data)
 
static void record_important_candidates (struct ivopts_data *data)
 
static void alloc_use_cost_map (struct ivopts_data *data)
 
static void set_group_iv_cost (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand, comp_cost cost, bitmap inv_vars, tree value, enum tree_code comp, bitmap inv_exprs)
 
static class cost_pairget_group_iv_cost (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand)
 
static rtx produce_memory_decl_rtl (tree obj, int *regno)
 
static tree prepare_decl_rtl (tree *expr_p, int *ws, void *data)
 
static bool generic_predict_doloop_p (struct ivopts_data *data)
 
static unsigned computation_cost (tree expr, bool speed)
 
static tree var_at_stmt (class loop *loop, struct iv_cand *cand, gimple *stmt)
 
static tree determine_common_wider_type (tree *a, tree *b)
 
static bool get_computation_aff_1 (class loop *loop, gimple *at, struct iv_use *use, struct iv_cand *cand, class aff_tree *aff_inv, class aff_tree *aff_var, widest_int *prat=NULL)
 
static bool get_computation_aff (class loop *loop, gimple *at, struct iv_use *use, struct iv_cand *cand, class aff_tree *aff)
 
static tree get_use_type (struct iv_use *use)
 
static tree get_computation_at (class loop *loop, gimple *at, struct iv_use *use, struct iv_cand *cand)
 
static tree get_debug_computation_at (class loop *loop, gimple *at, struct iv_use *use, struct iv_cand *cand)
 
static int64_t adjust_setup_cost (struct ivopts_data *data, int64_t cost, bool round_up_p=false)
 
static bool get_shiftadd_cost (tree expr, scalar_int_mode mode, comp_cost cost0, comp_cost cost1, tree mult, bool speed, comp_cost *cost)
 
static comp_cost force_var_cost (struct ivopts_data *data, tree expr, bitmap *inv_vars)
 
static comp_cost get_address_cost_ainc (poly_int64 ainc_step, poly_int64 ainc_offset, machine_mode addr_mode, machine_mode mem_mode, addr_space_t as, bool speed)
 
static comp_cost get_address_cost (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand, aff_tree *aff_inv, aff_tree *aff_var, HOST_WIDE_INT ratio, bitmap *inv_vars, iv_inv_expr_ent **inv_expr, bool *can_autoinc, bool speed)
 
static comp_cost get_scaled_computation_cost_at (ivopts_data *data, gimple *at, comp_cost cost)
 
static comp_cost get_computation_cost (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand, bool address_p, bitmap *inv_vars, bool *can_autoinc, iv_inv_expr_ent **inv_expr)
 
static bool determine_group_iv_cost_generic (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand)
 
static bool determine_group_iv_cost_address (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand)
 
static void cand_value_at (class loop *loop, struct iv_cand *cand, gimple *at, class tree_niter_desc *desc, aff_tree *val)
 
static tree iv_period (struct iv *iv)
 
static enum tree_code iv_elimination_compare (struct ivopts_data *data, struct iv_use *use)
 
static bool difference_cannot_overflow_p (struct ivopts_data *data, tree base, tree offset)
 
static bool iv_elimination_compare_lt (struct ivopts_data *data, struct iv_cand *cand, enum tree_code *comp_p, class tree_niter_desc *niter)
 
static bool may_eliminate_iv (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand, tree *bound, enum tree_code *comp)
 
static int parm_decl_cost (struct ivopts_data *data, tree bound)
 
static bool determine_group_iv_cost_cond (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand)
 
static bool determine_group_iv_cost (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand)
 
static bool autoinc_possible_for_pair (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
 
static void set_autoinc_for_original_candidates (struct ivopts_data *data)
 
static void relate_compare_use_with_all_cands (struct ivopts_data *data)
 
static tree compute_doloop_base_on_mode (machine_mode preferred_mode, tree niter, const widest_int &iterations_max)
 
static void add_iv_candidate_for_doloop (struct ivopts_data *data)
 
static void find_iv_candidates (struct ivopts_data *data)
 
static void determine_group_iv_costs (struct ivopts_data *data)
 
static void determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand)
 
static void determine_iv_costs (struct ivopts_data *data)
 
static unsigned ivopts_estimate_reg_pressure (struct ivopts_data *data, unsigned n_invs, unsigned n_cands)
 
static void determine_set_costs (struct ivopts_data *data)
 
static bool cheaper_cost_pair (class cost_pair *a, class cost_pair *b)
 
static int compare_cost_pair (class cost_pair *a, class cost_pair *b)
 
static class cost_pairiv_ca_cand_for_group (class iv_ca *ivs, struct iv_group *group)
 
static void iv_ca_recount_cost (struct ivopts_data *data, class iv_ca *ivs)
 
static void iv_ca_set_remove_invs (class iv_ca *ivs, bitmap invs, unsigned *n_inv_uses)
 
static void iv_ca_set_no_cp (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group)
 
static void iv_ca_set_add_invs (class iv_ca *ivs, bitmap invs, unsigned *n_inv_uses)
 
static void iv_ca_set_cp (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group, class cost_pair *cp)
 
static void iv_ca_add_group (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group)
 
static comp_cost iv_ca_cost (class iv_ca *ivs)
 
static int iv_ca_compare_deps (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group, class cost_pair *old_cp, class cost_pair *new_cp)
 
static struct iv_ca_deltaiv_ca_delta_add (struct iv_group *group, class cost_pair *old_cp, class cost_pair *new_cp, struct iv_ca_delta *next)
 
static struct iv_ca_deltaiv_ca_delta_join (struct iv_ca_delta *l1, struct iv_ca_delta *l2)
 
static struct iv_ca_deltaiv_ca_delta_reverse (struct iv_ca_delta *delta)
 
static void iv_ca_delta_commit (struct ivopts_data *data, class iv_ca *ivs, struct iv_ca_delta *delta, bool forward)
 
static bool iv_ca_cand_used_p (class iv_ca *ivs, struct iv_cand *cand)
 
static unsigned iv_ca_n_cands (class iv_ca *ivs)
 
static void iv_ca_delta_free (struct iv_ca_delta **delta)
 
static class iv_caiv_ca_new (struct ivopts_data *data)
 
static void iv_ca_free (class iv_ca **ivs)
 
static void iv_ca_dump (struct ivopts_data *data, FILE *file, class iv_ca *ivs)
 
static comp_cost iv_ca_extend (struct ivopts_data *data, class iv_ca *ivs, struct iv_cand *cand, struct iv_ca_delta **delta, unsigned *n_ivs, bool min_ncand)
 
static comp_cost iv_ca_narrow (struct ivopts_data *data, class iv_ca *ivs, struct iv_cand *cand, struct iv_cand *start, struct iv_ca_delta **delta)
 
static comp_cost iv_ca_prune (struct ivopts_data *data, class iv_ca *ivs, struct iv_cand *except_cand, struct iv_ca_delta **delta)
 
static class cost_paircheaper_cost_with_cand (struct ivopts_data *data, struct iv_group *group, unsigned int cand_idx, struct iv_cand *old_cand, class cost_pair *best_cp)
 
static comp_cost iv_ca_replace (struct ivopts_data *data, class iv_ca *ivs, struct iv_ca_delta **delta)
 
static bool try_add_cand_for (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group, bool originalp)
 
static class iv_caget_initial_solution (struct ivopts_data *data, bool originalp)
 
static bool try_improve_iv_set (struct ivopts_data *data, class iv_ca *ivs, bool *try_replace_p)
 
static class iv_cafind_optimal_iv_set_1 (struct ivopts_data *data, bool originalp)
 
static class iv_cafind_optimal_iv_set (struct ivopts_data *data)
 
static void create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
 
static void create_new_ivs (struct ivopts_data *data, class iv_ca *set)
 
static void rewrite_use_nonlinear_expr (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
 
static void adjust_iv_update_pos (struct iv_cand *cand, struct iv_use *use)
 
static tree get_alias_ptr_type_for_ptr_address (iv_use *use)
 
static void rewrite_use_address (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
 
static void rewrite_use_compare (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
 
static void rewrite_groups (struct ivopts_data *data)
 
static void remove_unused_ivs (struct ivopts_data *data, bitmap toremove)
 
bool free_tree_niter_desc (edge const &, tree_niter_desc *const &value, void *)
 
static void free_loop_data (struct ivopts_data *data)
 
static void tree_ssa_iv_optimize_finalize (struct ivopts_data *data)
 
static bool loop_body_includes_call (basic_block *body, unsigned num_nodes)
 
static void determine_scaling_factor (struct ivopts_data *data, basic_block *body)
 
static bool find_doloop_use (struct ivopts_data *data)
 
void analyze_and_mark_doloop_use (struct ivopts_data *data)
 
static bool tree_ssa_iv_optimize_loop (struct ivopts_data *data, class loop *loop, bitmap toremove)
 
void tree_ssa_iv_optimize (void)
 

Variables

static const comp_cost no_cost
 
static const comp_cost infinite_cost (INFTY, 0, INFTY)
 
static vec< treedecl_rtl_to_reset
 
static vec< rtx, va_gc > * addr_list
 

Macro Definition Documentation

◆ ALWAYS_PRUNE_CAND_SET_BOUND

#define ALWAYS_PRUNE_CAND_SET_BOUND    ((unsigned) param_iv_always_prune_cand_set_bound)
If there are at most this number of ivs in the set, try removing unnecessary
ivs from the set always.   

Referenced by iv_ca_replace(), and try_improve_iv_set().

◆ CONSIDER_ALL_CANDIDATES_BOUND

#define CONSIDER_ALL_CANDIDATES_BOUND    ((unsigned) param_iv_consider_all_candidates_bound)
Bound on number of candidates below that all candidates are considered.   

Referenced by record_important_candidates().

◆ COST_SCALING_FACTOR_BOUND

#define COST_SCALING_FACTOR_BOUND   (20)
Determine cost scaling factor for basic blocks in loop.   

Referenced by determine_scaling_factor().

◆ INFTY

#define INFTY   1000000000
Induction variable optimizations.
   Copyright (C) 2003-2024 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.

GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
This pass tries to find the optimal set of induction variables for the loop.
It optimizes just the basic linear induction variables (although adding
support for other types should not be too hard).  It includes the
optimizations commonly known as strength reduction, induction variable
coalescing and induction variable elimination.  It does it in the
following steps:

1) The interesting uses of induction variables are found.  This includes

   -- uses of induction variables in non-linear expressions
   -- addresses of arrays
   -- comparisons of induction variables

   Note the interesting uses are categorized and handled in group.
   Generally, address type uses are grouped together if their iv bases
   are different in constant offset.

2) Candidates for the induction variables are found.  This includes

   -- old induction variables
   -- the variables defined by expressions derived from the "interesting
      groups/uses" above

3) The optimal (w.r. to a cost function) set of variables is chosen.  The
   cost function assigns a cost to sets of induction variables and consists
   of three parts:

   -- The group/use costs.  Each of the interesting groups/uses chooses
      the best induction variable in the set and adds its cost to the sum.
      The cost reflects the time spent on modifying the induction variables
      value to be usable for the given purpose (adding base and offset for
      arrays, etc.).
   -- The variable costs.  Each of the variables has a cost assigned that
      reflects the costs associated with incrementing the value of the
      variable.  The original variables are somewhat preferred.
   -- The set cost.  Depending on the size of the set, extra cost may be
      added to reflect register pressure.

   All the costs are defined in a machine-specific way, using the target
   hooks and machine descriptions to determine them.

4) The trees are transformed to use the new variables, the dead code is
   removed.

All of this is done loop by loop.  Doing it globally is theoretically
possible, it might give a better performance and it might enable us
to decide costs more precisely, but getting all the interactions right
would be complicated.

For the targets supporting low-overhead loops, IVOPTs has to take care of
the loops which will probably be transformed in RTL doloop optimization,
to try to make selected IV candidate set optimal.  The process of doloop
support includes:

1) Analyze the current loop will be transformed to doloop or not, find and
   mark its compare type IV use as doloop use (iv_group field doloop_p), and
   set flag doloop_use_p of ivopts_data to notify subsequent processings on
   doloop.  See analyze_and_mark_doloop_use and its callees for the details.
   The target hook predict_doloop_p can be used for target specific checks.

2) Add one doloop dedicated IV cand {(may_be_zero ? 1 : (niter + 1)), +, -1},
   set flag doloop_p of iv_cand, step cost is set as zero and no extra cost
   like biv.  For cost determination between doloop IV cand and IV use, the
   target hooks doloop_cost_for_generic and doloop_cost_for_address are
   provided to add on extra costs for generic type and address type IV use.
   Zero cost is assigned to the pair between doloop IV cand and doloop IV
   use, and bound zero is set for IV elimination.

3) With the cost setting in step 2), the current cost model based IV
   selection algorithm will process as usual, pick up doloop dedicated IV if
   profitable.   
For lang_hooks.types.type_for_mode.   
FIXME: Expressions are expanded to RTL in this pass to determine the
cost of different addressing modes.  This should be moved to a TBD
interface between the GIMPLE and RTL worlds.   
The infinite cost.   

Referenced by adjust_setup_cost(), get_address_cost_ainc(), comp_cost::infinite_cost_p(), and comp_cost::operator+=().

◆ MAX_CONSIDERED_GROUPS

#define MAX_CONSIDERED_GROUPS    ((unsigned) param_iv_max_considered_uses)
If there are more iv occurrences, we just give up (it is quite unlikely that
optimizing such a loop would help, and it would take ages).   

Referenced by tree_ssa_iv_optimize_loop().

Enumeration Type Documentation

◆ ainc_type

Returns cost of auto-modifying address expression in shape base + offset.
AINC_STEP is step size of the address IV.  AINC_OFFSET is offset of the
address expression.  The address expression has ADDR_MODE in addr space
AS.  The memory access has MEM_MODE.  SPEED means we are optimizing for
speed or size.   
Enumerator
AINC_PRE_INC 
AINC_PRE_DEC 
AINC_POST_INC 
AINC_POST_DEC 
AINC_NONE 

◆ comp_iv_rewrite

Indicate how compare type iv_use can be handled.   
Enumerator
COMP_IV_NA 
COMP_IV_EXPR 
COMP_IV_EXPR_2 
COMP_IV_ELIM 

◆ iv_position

The position where the iv is computed.   
Enumerator
IP_NORMAL 
IP_END 
IP_BEFORE_USE 
IP_AFTER_USE 
IP_ORIGINAL 

◆ use_type

Types of uses.   
Enumerator
USE_NONLINEAR_EXPR 
USE_REF_ADDRESS 
USE_PTR_ADDRESS 
USE_COMPARE 

Function Documentation

◆ add_autoinc_candidates()

◆ add_candidate()

static void add_candidate ( struct ivopts_data * data,
tree base,
tree step,
bool important,
struct iv_use * use,
struct iv * orig_iv = NULL,
bool doloop = false )
static
Adds a candidate BASE + STEP * i.  Important field is set to IMPORTANT and
position to POS.  If USE is not NULL, the candidate is set as related to
it.  The candidate computation is scheduled before exit condition and at
the end of loop.   

References add_candidate_1(), allow_ip_end_pos_p(), ggc_alloc(), iv_cand::important, IP_END, ip_end_pos(), IP_NORMAL, ip_normal_pos(), NULL, and iv_cand::orig_iv.

Referenced by add_iv_candidate_for_biv(), add_iv_candidate_for_doloop(), add_iv_candidate_for_use(), and add_standard_iv_candidates().

◆ add_candidate_1()

static struct iv_cand * add_candidate_1 ( struct ivopts_data * data,
tree base,
tree step,
bool important,
enum iv_position pos,
struct iv_use * use,
gimple * incremented_at,
struct iv * orig_iv = NULL,
bool doloop = false )
static
Adds a candidate BASE + STEP * i.  Important field is set to IMPORTANT and
position to POS.  If USE is not NULL, the candidate is set as related to
it.  If both BASE and STEP are NULL, we add a pseudocandidate for the
replacement of the final value of the iv by a direct computation.   

References alloc_iv(), BITMAP_ALLOC, bitmap_clear(), bitmap_set_bit, create_tmp_var_raw(), dump_cand(), dump_file, dump_flags, find_inv_vars(), find_ssa_undef(), fold_convert, gcc_assert, generic_type_for(), get_loop_invariant_expr(), ggc_alloc(), i, iv_cand::important, iv_cand::incremented_at, iv_cand::involves_undefs, IP_AFTER_USE, IP_BEFORE_USE, IP_ORIGINAL, NULL, operand_equal_p(), iv_cand::orig_iv, POINTER_TYPE_P, poly_int_tree_p(), iv_cand::pos, TDF_DETAILS, TREE_TYPE, type(), TYPE_PRECISION, and walk_tree.

Referenced by add_autoinc_candidates(), add_candidate(), add_iv_candidate_derived_from_uses(), and add_iv_candidate_for_biv().

◆ add_iv_candidate_derived_from_uses()

◆ add_iv_candidate_for_biv()

◆ add_iv_candidate_for_bivs()

static void add_iv_candidate_for_bivs ( struct ivopts_data * data)
static
Adds candidates based on the old induction variables.   

References add_iv_candidate_for_biv(), iv::biv_p, EXECUTE_IF_SET_IN_BITMAP, i, integer_zerop(), version_info::iv, iv::step, and ver_info().

Referenced by find_iv_candidates().

◆ add_iv_candidate_for_doloop()

◆ add_iv_candidate_for_groups()

static void add_iv_candidate_for_groups ( struct ivopts_data * data)
static
Adds candidates based on the uses.   

References add_iv_candidate_derived_from_uses(), add_iv_candidate_for_use(), gcc_assert, i, NULL, and iv_group::vuses.

Referenced by find_iv_candidates().

◆ add_iv_candidate_for_use()

◆ add_standard_iv_candidates()

◆ addr_offset_valid_p()

◆ address_p()

◆ adjust_iv_update_pos()

static void adjust_iv_update_pos ( struct iv_cand * cand,
struct iv_use * use )
static
Performs a peephole optimization to reorder the iv update statement with
  a mem ref to enable instruction combining in later phases. The mem ref uses
  the iv value before the update, so the reordering transformation requires
  adjustment of the offset. CAND is the selected IV_CAND.

  Example:

  t = MEM_REF (base, iv1, 8, 16);  // base, index, stride, offset
  iv2 = iv1 + 1;

  if (t < val)      (1)
    goto L;
  goto Head;


  directly propagating t over to (1) will introduce overlapping live range
  thus increase register pressure. This peephole transform it into:


  iv2 = iv1 + 1;
  t = MEM_REF (base, iv2, 8, 8);
  if (t < val)
    goto L;
  goto Head;

References dump_file, dump_flags, ggc_alloc(), gimple_assign_lhs(), gimple_bb(), gsi_end_p(), gsi_for_stmt(), gsi_last_nondebug_bb(), gsi_move_before(), gsi_prev_nondebug(), gsi_stmt(), IP_BEFORE_USE, IP_NORMAL, print_gimple_stmt(), SSA_NAME_DEF_STMT, TDF_DETAILS, and TREE_CODE.

Referenced by rewrite_use_address().

◆ adjust_setup_cost()

static int64_t adjust_setup_cost ( struct ivopts_data * data,
int64_t cost,
bool round_up_p = false )
static
Adjust the cost COST for being in loop setup rather than loop body.
If we're optimizing for space, the loop setup overhead is constant;
if we're optimizing for speed, amortize it over the per-iteration cost.
If ROUND_UP_P is true, the result is round up rather than to zero when
optimizing for speed.   

References avg_loop_niter(), ggc_alloc(), INFTY, and optimize_loop_for_speed_p().

Referenced by determine_group_iv_cost_cond(), determine_iv_cost(), get_address_cost(), and get_computation_cost().

◆ alloc_iv()

◆ alloc_use_cost_map()

static void alloc_use_cost_map ( struct ivopts_data * data)
static
Allocates the data structure mapping the (use, candidate) pairs to costs.
If consider_all_candidates is true, we use a two-dimensional array, otherwise
we allocate a simple list to every use.   

References bitmap_count_bits(), ceil_log2(), iv_group::cost_map, ggc_alloc(), i, iv_group::n_map_members, and iv_group::related_cands.

Referenced by determine_group_iv_costs().

◆ allow_ip_end_pos_p()

static bool allow_ip_end_pos_p ( class loop * loop)
static
Returns true if incrementing the induction variable at the end of the LOOP
is allowed.

The purpose is to avoid splitting latch edge with a biv increment, thus
creating a jump, possibly confusing other optimization passes and leaving
less freedom to scheduler.  So we allow IP_END only if IP_NORMAL is not
available (so we do not have a better alternative), or if the latch edge
is already nonempty.   

References empty_block_p(), ip_end_pos(), and ip_normal_pos().

Referenced by add_candidate(), and add_iv_candidate_derived_from_uses().

◆ analyze_and_mark_doloop_use()

void analyze_and_mark_doloop_use ( struct ivopts_data * data)
For the targets which support doloop, to predict whether later RTL doloop
transformation will perform on this loop, further detect the doloop use and
mark the flag doloop_use_p if predicted.   

References dump_file, dump_flags, find_doloop_use(), flow_loop_dump(), generic_predict_doloop_p(), ggc_alloc(), NULL, loop::num, TDF_DETAILS, and USHRT_MAX.

Referenced by tree_ssa_iv_optimize_loop().

◆ autoinc_possible_for_pair()

static bool autoinc_possible_for_pair ( struct ivopts_data * data,
struct iv_use * use,
struct iv_cand * cand )
static
Return true if get_computation_cost indicates that autoincrement is
a possibility for the pair of USE and CAND, false otherwise.   

References address_p(), get_computation_cost(), ggc_alloc(), and NULL.

Referenced by set_autoinc_for_original_candidates().

◆ avg_loop_niter()

static HOST_WIDE_INT avg_loop_niter ( class loop * loop)
inlinestatic
Returns the expected number of loop iterations for LOOP.
The average trip count is computed from profile data if it
exists.  

References estimated_stmt_executions_int(), ggc_alloc(), and likely_max_stmt_executions_int().

Referenced by adjust_setup_cost(), and create_new_ivs().

◆ cand_value_at()

◆ cheaper_cost_pair()

static bool cheaper_cost_pair ( class cost_pair * a,
class cost_pair * b )
static
Returns true if A is a cheaper cost pair than B.   

References a, and b.

Referenced by cheaper_cost_with_cand(), compare_cost_pair(), and iv_ca_add_group().

◆ cheaper_cost_with_cand()

static class cost_pair * cheaper_cost_with_cand ( struct ivopts_data * data,
struct iv_group * group,
unsigned int cand_idx,
struct iv_cand * old_cand,
class cost_pair * best_cp )
static
Check if CAND_IDX is a candidate other than OLD_CAND and has
cheaper local cost for GROUP than BEST_CP.  Return pointer to
the corresponding cost_pair, otherwise just return BEST_CP.   

References cheaper_cost_pair(), gcc_assert, get_group_iv_cost(), ggc_alloc(), and NULL.

Referenced by iv_ca_replace().

◆ common_cand_cmp()

static int common_cand_cmp ( const void * p1,
const void * p2 )
static
Comparison function used to sort common candidates.   

References ggc_alloc().

Referenced by add_iv_candidate_derived_from_uses().

◆ compare_cost_pair()

static int compare_cost_pair ( class cost_pair * a,
class cost_pair * b )
static
Compare if A is a more expensive cost pair than B.  Return 1, 0 and -1
for more expensive, equal and cheaper respectively.   

References a, b, and cheaper_cost_pair().

Referenced by iv_ca_extend().

◆ computation_cost()

◆ compute_doloop_base_on_mode()

static tree compute_doloop_base_on_mode ( machine_mode preferred_mode,
tree niter,
const widest_int & iterations_max )
static
If PREFERRED_MODE is suitable and profitable, use the preferred
PREFERRED_MODE to compute doloop iv base from niter: base = niter + 1.   

References build_int_cst(), fold_build2, fold_convert, gcc_assert, ggc_alloc(), wi::ltu_p(), wi::max_value(), TREE_CODE, TREE_TYPE, lang_hooks_for_types::type_for_mode, TYPE_PRECISION, lang_hooks::types, unshare_expr(), and UNSIGNED.

Referenced by add_iv_candidate_for_doloop().

◆ constant_multiple_of()

static bool constant_multiple_of ( tree top,
tree bot,
widest_int * mul )
static
If we can prove that TOP = cst * BOT for some constant cst,
store cst to MUL and return true.  Otherwise return false.
The returned value is always sign-extended, regardless of the
signedness of TOP and BOT.   

References constant_multiple_of(), wi::divmod_trunc(), ggc_alloc(), operand_equal_p(), POLY_INT_CST_P, wi::sext(), SIGNED, STRIP_NOPS, wi::to_poly_widest(), wi::to_wide(), wi::to_widest(), TREE_CODE, TREE_OPERAND, TREE_TYPE, and TYPE_PRECISION.

Referenced by constant_multiple_of(), get_computation_aff_1(), and get_debug_computation_at().

◆ contain_complex_addr_expr()

static bool contain_complex_addr_expr ( tree expr)
static
Return true if address expression with non-DECL_P operand appears
in EXPR.   

References contain_complex_addr_expr(), DECL_P, ggc_alloc(), STRIP_NOPS, TREE_CODE, and TREE_OPERAND.

Referenced by alloc_iv(), and contain_complex_addr_expr().

◆ contains_abnormal_ssa_name_p()

bool contains_abnormal_ssa_name_p ( tree expr)
Returns true if EXPR contains a ssa name that occurs in an
abnormal phi node.   

References contains_abnormal_ssa_name_p_1(), NULL, NULL_TREE, and walk_tree_without_duplicates.

Referenced by can_unroll_loop_p(), final_value_replacement_loop(), find_bivs(), find_givs_in_stmt_scev(), and niter_for_exit().

◆ contains_abnormal_ssa_name_p_1()

static tree contains_abnormal_ssa_name_p_1 ( tree * tp,
int * walk_subtrees,
void *  )
static
walk_tree callback for contains_abnormal_ssa_name_p.   

References EXPR_P, ggc_alloc(), NULL_TREE, SSA_NAME_OCCURS_IN_ABNORMAL_PHI, and TREE_CODE.

Referenced by contains_abnormal_ssa_name_p().

◆ create_new_iv()

◆ create_new_ivs()

◆ determine_base_object()

static tree determine_base_object ( struct ivopts_data * data,
tree expr )
static
Returns a memory object to that EXPR points with caching.  Return NULL if we
are able to determine that it does not point to any such object; specially
return integer_zero_node if EXPR contains multiple base objects.   

References determine_base_object_1(), ggc_alloc(), NULL, NULL_TREE, and walk_tree_without_duplicates.

Referenced by alloc_iv().

◆ determine_base_object_1()

static tree determine_base_object_1 ( tree * tp,
int * walk_subtrees,
void * wdata )
static

◆ determine_common_wider_type()

static tree determine_common_wider_type ( tree * a,
tree * b )
static
If A is (TYPE) BA and B is (TYPE) BB, and the types of BA and BB have the
same precision that is at least as wide as the precision of TYPE, stores
BA to A and BB to B, and returns the type of BA.  Otherwise, returns the
type of A and B.   

References a, b, CONVERT_EXPR_P, ggc_alloc(), NULL, TREE_OPERAND, TREE_TYPE, and TYPE_PRECISION.

Referenced by get_computation_aff_1().

◆ determine_group_iv_cost()

static bool determine_group_iv_cost ( struct ivopts_data * data,
struct iv_group * group,
struct iv_cand * cand )
static
Determines cost of computing uses in GROUP with CAND.  Returns false
if USE cannot be represented with CAND.   

References determine_group_iv_cost_address(), determine_group_iv_cost_cond(), determine_group_iv_cost_generic(), gcc_unreachable, iv_group::type, USE_COMPARE, USE_NONLINEAR_EXPR, USE_PTR_ADDRESS, and USE_REF_ADDRESS.

Referenced by determine_group_iv_costs().

◆ determine_group_iv_cost_address()

static bool determine_group_iv_cost_address ( struct ivopts_data * data,
struct iv_group * group,
struct iv_cand * cand )
static

◆ determine_group_iv_cost_cond()

◆ determine_group_iv_cost_generic()

static bool determine_group_iv_cost_generic ( struct ivopts_data * data,
struct iv_group * group,
struct iv_cand * cand )
static
Determines cost of computing the use in GROUP with CAND in a generic
expression.   

References BITMAP_ALLOC, bitmap_set_bit, get_computation_cost(), ggc_alloc(), comp_cost::infinite_cost_p(), IP_ORIGINAL, no_cost, NULL, NULL_TREE, operand_equal_p(), set_group_iv_cost(), and iv_group::vuses.

Referenced by determine_group_iv_cost().

◆ determine_group_iv_costs()

◆ determine_iv_cost()

◆ determine_iv_costs()

static void determine_iv_costs ( struct ivopts_data * data)
static
Determines costs of computation of the candidates.   

References determine_iv_cost(), dump_file, dump_flags, ggc_alloc(), i, and TDF_DETAILS.

Referenced by tree_ssa_iv_optimize_loop().

◆ determine_scaling_factor()

◆ determine_set_costs()

◆ difference_cannot_overflow_p()

static bool difference_cannot_overflow_p ( struct ivopts_data * data,
tree base,
tree offset )
static
Returns true if we can prove that BASE - OFFSET does not overflow.  For now,
we only detect the situation that BASE = SOMETHING + OFFSET, where the
calculation is performed in non-wrapping type.

TODO: More generally, we could test for the situation that
      BASE = SOMETHING + OFFSET' and OFFSET is between OFFSET' and zero.
      This would require knowing the sign of OFFSET.   

References aff_combination_add(), aff_combination_scale(), aff_combination_zero_p(), expand_simple_operations(), get_gimple_rhs_class(), ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), GIMPLE_BINARY_RHS, nowrap_type_p(), offset, SSA_NAME_DEF_STMT, TREE_CODE, TREE_OPERAND, tree_to_aff_combination_expand(), and TREE_TYPE.

Referenced by iv_elimination_compare_lt().

◆ dump_cand()

void dump_cand ( FILE * file,
struct iv_cand * cand )
Dumps information about induction variable candidate CAND to FILE.   

References dump_bitmap(), dump_iv(), ggc_alloc(), IP_AFTER_USE, IP_BEFORE_USE, IP_END, IP_NORMAL, IP_ORIGINAL, print_generic_expr(), and TDF_SLIM.

Referenced by add_candidate_1(), and create_new_ivs().

◆ dump_groups()

void dump_groups ( FILE * file,
struct ivopts_data * data )

◆ dump_iv()

void dump_iv ( FILE * file,
struct iv * iv,
bool dump_name,
unsigned indent_level )
Dumps information about the induction variable IV to FILE.  Don't dump
variable's name if DUMP_NAME is FALSE.  The information is dumped with
preceding spaces indicated by INDENT_LEVEL.   

References iv::base, iv::base_object, iv::biv_p, ggc_alloc(), iv::no_overflow, print_generic_expr(), iv::ssa_name, iv::step, TDF_SLIM, and TREE_TYPE.

Referenced by dump_cand(), dump_use(), and find_induction_variables().

◆ dump_use()

void dump_use ( FILE * file,
struct iv_use * use )
Dumps information about the USE to FILE.   

References dump_iv(), ggc_alloc(), print_generic_expr(), print_gimple_stmt(), and TDF_SLIM.

Referenced by dump_groups().

◆ expr_invariant_in_loop_p()

◆ extract_cond_operands()

static enum comp_iv_rewrite extract_cond_operands ( struct ivopts_data * data,
gimple * stmt,
tree ** control_var,
tree ** bound,
struct iv ** iv_var,
struct iv ** iv_bound )
static
Given a condition in statement STMT, checks whether it is a compare
of an induction variable and an invariant.  If this is the case,
CONTROL_VAR is set to location of the iv, BOUND to the location of
the invariant, IV_VAR and IV_BOUND are set to the corresponding
induction variable descriptions, and true is returned.  If this is not
the case, CONTROL_VAR and BOUND are set to the arguments of the
condition and false is returned.   

References COMP_IV_ELIM, COMP_IV_EXPR, COMP_IV_EXPR_2, COMP_IV_NA, end(), get_iv(), ggc_alloc(), gimple_assign_rhs1_ptr(), gimple_assign_rhs2_ptr(), gimple_cond_lhs_ptr(), gimple_cond_rhs_ptr(), integer_zero_node, integer_zerop(), and TREE_CODE.

Referenced by determine_group_iv_cost_cond(), and find_interesting_uses_cond().

◆ extract_single_var_from_expr()

static tree extract_single_var_from_expr ( tree expr)
static

◆ find_address_like_use()

static bool find_address_like_use ( struct ivopts_data * data,
gimple * stmt,
tree * op_p,
struct iv * iv )
static
IV is a (non-address) iv that describes operand *OP_P of STMT.
Return true if the operand will become an address when STMT
is expanded and record the associated address use if so.   

References alloc_iv(), iv::base, iv::base_object, get_mem_type_for_internal_fn(), ggc_alloc(), gimple_call_internal_p(), NULL_TREE, record_group_use(), iv::step, ifs_ivopts_data::stmt, and USE_PTR_ADDRESS.

Referenced by find_interesting_uses_stmt().

◆ find_bivs()

◆ find_deriving_biv_for_expr()

static struct iv * find_deriving_biv_for_expr ( struct ivopts_data * data,
tree expr )
static

◆ find_doloop_use()

◆ find_givs()

static void find_givs ( struct ivopts_data * data,
basic_block * body )
static
Finds general ivs.   

References find_givs_in_bb(), i, and loop::num_nodes.

Referenced by find_induction_variables().

◆ find_givs_in_bb()

static void find_givs_in_bb ( struct ivopts_data * data,
basic_block bb )
static
Finds general ivs in basic block BB.   

References find_givs_in_stmt(), ggc_alloc(), gsi_end_p(), gsi_next(), gsi_start_bb(), and gsi_stmt().

Referenced by find_givs().

◆ find_givs_in_stmt()

static void find_givs_in_stmt ( struct ivopts_data * data,
gimple * stmt )
static
Finds general ivs in statement STMT.   

References iv::base, find_givs_in_stmt_scev(), gimple_assign_lhs(), iv::no_overflow, set_iv(), and iv::step.

Referenced by find_givs_in_bb().

◆ find_givs_in_stmt_scev()

static bool find_givs_in_stmt_scev ( struct ivopts_data * data,
gimple * stmt,
affine_iv * iv )
static

◆ find_induction_variables()

static bool find_induction_variables ( struct ivopts_data * data,
basic_block * body )
static
For each ssa name defined in LOOP determines whether it is an induction
variable and if so, its initial value and step.   

References dump_file, dump_flags, dump_iv(), EXECUTE_IF_SET_IN_BITMAP, find_bivs(), find_givs(), ggc_alloc(), i, integer_zerop(), version_info::iv, mark_bivs(), tree_niter_desc::niter, niter_for_single_dom_exit(), print_generic_expr(), iv::step, TDF_DETAILS, TDF_SLIM, and ver_info().

Referenced by tree_ssa_iv_optimize_loop().

◆ find_interesting_uses()

◆ find_interesting_uses_address()

◆ find_interesting_uses_cond()

static void find_interesting_uses_cond ( struct ivopts_data * data,
gimple * stmt )
static
Checks whether the condition in STMT is interesting and if so,
records it.   

References COMP_IV_EXPR_2, COMP_IV_NA, extract_cond_operands(), find_interesting_uses_op(), ggc_alloc(), NULL_TREE, record_group_use(), and USE_COMPARE.

Referenced by find_interesting_uses_stmt().

◆ find_interesting_uses_op()

◆ find_interesting_uses_outside()

static void find_interesting_uses_outside ( struct ivopts_data * data,
edge exit )
static
Finds interesting uses of induction variables outside of loops
on loop exit edge EXIT.   

References find_interesting_uses_op(), gsi_end_p(), gsi_next(), gsi_start_phis(), gphi_iterator::phi(), PHI_ARG_DEF_FROM_EDGE, and virtual_operand_p().

Referenced by find_interesting_uses().

◆ find_interesting_uses_stmt()

◆ find_inv_vars()

static void find_inv_vars ( struct ivopts_data * data,
tree * expr_p,
bitmap * inv_vars )
inlinestatic
Records invariants in *EXPR_P.  INV_VARS is the bitmap to that we should
store it.   

References find_inv_vars_cb(), ggc_alloc(), walk_tree_data::inv_vars, NULL, and walk_tree.

Referenced by add_candidate_1(), determine_group_iv_cost_cond(), and force_var_cost().

◆ find_inv_vars_cb()

static tree find_inv_vars_cb ( tree * expr_p,
int * ws,
void * data )
static
Callback function for walk_tree, it records invariants and symbol
reference in *EXPR_P.  DATA is the structure storing result info.   

References BITMAP_ALLOC, bitmap_set_bit, build_int_cst(), flow_bb_inside_loop_p(), ggc_alloc(), gimple_bb(), version_info::has_nonlin_use, idata, version_info::inv_id, version_info::iv, name_info(), NULL, NULL_TREE, POINTER_TYPE_P, record_invariant(), set_iv(), sizetype, SSA_NAME_DEF_STMT, TREE_CODE, and TREE_TYPE.

Referenced by find_inv_vars().

◆ find_invariants_stmt()

static void find_invariants_stmt ( struct ivopts_data * data,
gimple * stmt )
static
Finds and records invariants used in STMT.   

References FOR_EACH_PHI_OR_STMT_USE, ggc_alloc(), record_invariant(), SSA_OP_USE, ifs_ivopts_data::stmt, and USE_FROM_PTR.

Referenced by find_interesting_uses_stmt().

◆ find_iv_candidates()

◆ find_optimal_iv_set()

◆ find_optimal_iv_set_1()

static class iv_ca * find_optimal_iv_set_1 ( struct ivopts_data * data,
bool originalp )
static
Attempts to find the optimal set of induction variables.  We do simple
greedy heuristic -- we try to replace at most one candidate in the selected
solution and remove the unused ivs while this improves the cost.   

References dump_file, dump_flags, get_initial_solution(), ggc_alloc(), iv_ca_cost(), iv_ca_dump(), iv_ca_free(), NULL, TDF_DETAILS, and try_improve_iv_set().

Referenced by find_optimal_iv_set().

◆ find_ssa_undef()

static tree find_ssa_undef ( tree * tp,
int * walk_subtrees,
void * bb_ )
static
Return *TP if it is an SSA_NAME marked with TREE_VISITED, i.e., as
unsuitable as ivopts candidates for potentially involving undefined
behavior.   

References EXPR_P, ggc_alloc(), NULL, ssa_name_any_use_dominates_bb_p(), ssa_name_maybe_undef_p(), and TREE_CODE.

Referenced by add_candidate_1().

◆ force_expr_to_var_cost()

◆ force_var_cost()

static comp_cost force_var_cost ( struct ivopts_data * data,
tree expr,
bitmap * inv_vars )
static
Estimates cost of forcing EXPR into a variable.  INV_VARS is a set of the
invariants the computation depends on.   

References find_inv_vars(), force_expr_to_var_cost(), and no_cost.

Referenced by determine_group_iv_cost_cond(), determine_iv_cost(), get_address_cost(), and get_computation_cost().

◆ free_loop_data()

◆ free_tree_niter_desc()

bool free_tree_niter_desc ( edge const & ,
tree_niter_desc *const & value,
void *  )
Frees memory occupied by class tree_niter_desc in *VALUE. Callback
for hash_map::traverse.   

References free().

Referenced by free_loop_data().

◆ generic_predict_doloop_p()

static bool generic_predict_doloop_p ( struct ivopts_data * data)
static
Predict whether the given loop will be transformed in the RTL
doloop_optimize pass.  Attempt to duplicate some doloop_optimize checks.
This is only for target independent checks, see targetm.predict_doloop_p
for the target dependent ones.

Note that according to some initial investigation, some checks like costly
niter check and invalid stmt scanning don't have much gains among general
cases, so keep this as simple as possible first.

Some RTL specific checks seems unable to be checked in gimple, if any new
checks or easy checks _are_ missing here, please add them.   

References dump_file, dump_flags, get_estimated_loop_iterations_int(), get_likely_max_loop_iterations_int(), ggc_alloc(), niter_for_exit(), single_dom_exit(), targetm, and TDF_DETAILS.

Referenced by analyze_and_mark_doloop_use().

◆ generic_type_for()

static tree generic_type_for ( tree type)
static
Returns variant of TYPE that can be used as base for different uses.
We return unsigned type with the same precision, which avoids problems
with overflows.   

References POINTER_TYPE_P, type(), TYPE_UNSIGNED, and unsigned_type_for().

Referenced by add_candidate_1().

◆ get_address_cost()

static comp_cost get_address_cost ( struct ivopts_data * data,
struct iv_use * use,
struct iv_cand * cand,
aff_tree * aff_inv,
aff_tree * aff_var,
HOST_WIDE_INT ratio,
bitmap * inv_vars,
iv_inv_expr_ent ** inv_expr,
bool * can_autoinc,
bool speed )
static
Return cost of computing USE's address expression by using CAND.
AFF_INV and AFF_VAR represent invariant and variant parts of the
address expression, respectively.  If AFF_INV is simple, store
the loop invariant variables which are depended by it in INV_VARS;
if AFF_INV is complicated, handle it as a new invariant expression
and record it in INV_EXPR.  RATIO indicates multiple times between
steps of USE and CAND.  If CAN_AUTOINC is nonNULL, store boolean
value to it indicating if this is an auto-increment address.   

References add_cost(), addr_for_mem_ref(), address_cost(), adjust_setup_cost(), aff_combination_add_elt(), aff_combination_const_p(), aff_combination_singleton_var_p(), aff_combination_to_tree(), aff_combination_zero_p(), bitmap_clear(), force_var_cost(), gcc_assert, get_address_cost_ainc(), get_loop_invariant_expr(), ggc_alloc(), gimple_call_internal_fn(), gimple_call_internal_p(), integer_one_node, integer_zerop(), memory_address_addr_space_p(), move_fixed_address_to_symbol(), mult_by_coeff_cost(), no_cost, NULL, NULL_TREE, ptrdiff_tree_p(), sizetype, stmt_after_increment(), TREE_TYPE, TYPE_ADDR_SPACE, TYPE_MODE, USE_PTR_ADDRESS, valid_mem_ref_p(), and wide_int_to_tree().

Referenced by get_computation_cost().

◆ get_address_cost_ainc()

◆ get_alias_ptr_type_for_ptr_address()

static tree get_alias_ptr_type_for_ptr_address ( iv_use * use)
static
Return the alias pointer type that should be used for a MEM_REF
associated with USE, which has type USE_PTR_ADDRESS.   

References gcc_assert, gcc_unreachable, ggc_alloc(), gimple_call_arg(), gimple_call_arg_ptr(), gimple_call_internal_fn(), and TREE_TYPE.

Referenced by rewrite_use_address().

◆ get_computation_aff()

static bool get_computation_aff ( class loop * loop,
gimple * at,
struct iv_use * use,
struct iv_cand * cand,
class aff_tree * aff )
static
Determines the expression by that USE is expressed from induction variable
CAND at statement AT in LOOP.  The expression is stored in a decomposed
form into AFF.  Returns false if USE cannot be expressed using CAND.   

References aff_combination_add(), get_computation_aff_1(), and ggc_alloc().

Referenced by get_computation_at(), and rewrite_use_address().

◆ get_computation_aff_1()

static bool get_computation_aff_1 ( class loop * loop,
gimple * at,
struct iv_use * use,
struct iv_cand * cand,
class aff_tree * aff_inv,
class aff_tree * aff_var,
widest_int * prat = NULL )
static
Determines the expression by that USE is expressed from induction variable
CAND at statement AT in LOOP.  The expression is stored in two parts in a
decomposed form.  The invariant part is stored in AFF_INV; while variant
part in AFF_VAR.  Store ratio of CAND.step over USE.step in PRAT if it's
non-null.  Returns false if USE cannot be expressed using CAND.   

References aff_combination_add(), aff_combination_convert(), aff_combination_scale(), constant_multiple_of(), CONVERT_EXPR_P, determine_common_wider_type(), fold_convert, gcc_assert, ggc_alloc(), gimple_assign_lhs(), IP_ORIGINAL, is_gimple_assign(), NULL, poly_int_tree_p(), stmt_after_increment(), TREE_OPERAND, tree_to_aff_combination(), TREE_TYPE, TYPE_PRECISION, unsigned_type_for(), and var_at_stmt().

Referenced by get_computation_aff(), get_computation_cost(), and rewrite_use_nonlinear_expr().

◆ get_computation_at()

static tree get_computation_at ( class loop * loop,
gimple * at,
struct iv_use * use,
struct iv_cand * cand )
static
Determines the expression by that USE is expressed from induction variable
CAND at statement AT in LOOP.  The computation is unshared.   

References aff_combination_to_tree(), fold_convert, get_computation_aff(), get_use_type(), ggc_alloc(), NULL_TREE, and unshare_aff_combination().

Referenced by get_debug_computation_at(), and rewrite_use_compare().

◆ get_computation_cost()

static comp_cost get_computation_cost ( struct ivopts_data * data,
struct iv_use * use,
struct iv_cand * cand,
bool address_p,
bitmap * inv_vars,
bool * can_autoinc,
iv_inv_expr_ent ** inv_expr )
static
Determines the cost of the computation by that USE is expressed
from induction variable CAND.  If ADDRESS_P is true, we just need
to create an address from it, otherwise we want to get it into
register.  A set of invariants we depend on is stored in INV_VARS.
If CAN_AUTOINC is nonnull, use it to record whether autoinc
addressing is likely.  If INV_EXPR is nonnull, record invariant
expr entry in it.   

References add_cost(), address_p(), adjust_setup_cost(), aff_combination_const_p(), aff_combination_convert(), aff_combination_singleton_var_p(), aff_combination_to_tree(), aff_combination_type(), aff_combination_zero_p(), bitmap_clear(), CONSTANT_CLASS_P, convert_cost(), comp_cost::cost, wi::fits_shwi_p(), force_var_cost(), get_address_cost(), get_computation_aff_1(), get_loop_invariant_expr(), get_scaled_computation_cost_at(), ggc_alloc(), gimple_bb(), infinite_cost, integer_zerop(), mult_by_coeff_cost(), no_cost, NULL, NULL_TREE, operand_equal_p(), optimize_bb_for_speed_p(), POINTER_TYPE_P, comp_cost::scratch, signed_type_for(), targetm, TREE_TYPE, TYPE_MODE, TYPE_PRECISION, and USE_NONLINEAR_EXPR.

Referenced by autoinc_possible_for_pair(), determine_group_iv_cost_address(), determine_group_iv_cost_cond(), and determine_group_iv_cost_generic().

◆ get_debug_computation_at()

static tree get_debug_computation_at ( class loop * loop,
gimple * at,
struct iv_use * use,
struct iv_cand * cand )
static

◆ get_group_iv_cost()

◆ get_initial_solution()

static class iv_ca * get_initial_solution ( struct ivopts_data * data,
bool originalp )
static
Finds an initial assignment of candidates to uses.   

References ggc_alloc(), i, iv_ca_free(), iv_ca_new(), NULL, and try_add_cand_for().

Referenced by find_optimal_iv_set_1().

◆ get_iv()

◆ get_loop_invariant_expr()

static iv_inv_expr_ent * get_loop_invariant_expr ( struct ivopts_data * data,
tree inv_expr )
static
Get entry from invariant expr hash table for INV_EXPR.  New entry
will be recorded if it doesn't exist yet.  Given below two exprs:
  inv_expr + cst1, inv_expr + cst2
It's hard to make decision whether constant part should be stripped
or not.  We choose to not strip based on below facts:
  1) We need to count ADD cost for constant part if it's stripped,
     which isn't always trivial where this functions is called.
  2) Stripping constant away may be conflict with following loop
     invariant hoisting pass.
  3) Not stripping constant away results in more invariant exprs,
     which usually leads to decision preferring lower reg pressure.   

References ggc_alloc(), iterative_hash_expr(), NULL, poly_int_tree_p(), STRIP_NOPS, and TREE_CODE.

Referenced by add_candidate_1(), determine_group_iv_cost_cond(), get_address_cost(), and get_computation_cost().

◆ get_mem_type_for_internal_fn()

static tree get_mem_type_for_internal_fn ( gcall * call,
tree * op_p )
static
CALL calls an internal function.  If operand *OP_P will become an
address when the call is expanded, return the type of the memory
being addressed, otherwise return null.   

References ggc_alloc(), gimple_call_arg(), gimple_call_arg_ptr(), gimple_call_internal_fn(), gimple_call_lhs(), internal_fn_stored_value_index(), NULL_TREE, and TREE_TYPE.

Referenced by find_address_like_use().

◆ get_scaled_computation_cost_at()

static comp_cost get_scaled_computation_cost_at ( ivopts_data * data,
gimple * at,
comp_cost cost )
static
Scale (multiply) the computed COST (except scratch part that should be
hoisted out a loop) by header->frequency / AT->frequency, which makes
expected cost more accurate.   

References basic_block_def::aux, cfun, comp_cost::cost, dump_file, dump_flags, gcc_assert, ggc_alloc(), gimple_bb(), PRId64, comp_cost::scratch, and TDF_DETAILS.

Referenced by get_computation_cost().

◆ get_shiftadd_cost()

static bool get_shiftadd_cost ( tree expr,
scalar_int_mode mode,
comp_cost cost0,
comp_cost cost1,
tree mult,
bool speed,
comp_cost * cost )
static
Calculate the SPEED or size cost of shiftadd EXPR in MODE.  MULT is the
EXPR operand holding the shift.  COST0 and COST1 are the costs for
calculating the operands of EXPR.  Returns true if successful, and returns
the cost in COST.   

References add_cost(), BITS_PER_WORD, exact_log2(), force_expr_to_var_cost(), GET_MODE_BITSIZE(), ggc_alloc(), int_cst_value(), is_gimple_val(), MIN, mult, operand_equal_p(), shift_cost(), shiftadd_cost(), shiftsub0_cost(), shiftsub1_cost(), STRIP_NOPS, TREE_CODE, and TREE_OPERAND.

Referenced by force_expr_to_var_cost().

◆ get_use_type()

◆ group_compare_offset()

static int group_compare_offset ( const void * a,
const void * b )
static
Comparison function to sort group in ascending order of addr_offset.   

References a, b, and ggc_alloc().

Referenced by split_small_address_groups_p().

◆ idx_find_step()

◆ idx_record_use()

static bool idx_record_use ( tree base,
tree * idx,
void * vdata )
static
Records use in index IDX.  Callback for for_each_index.  Ivopts data
object is passed to it in DATA.   

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

Referenced by find_interesting_uses_address().

◆ iv_ca_add_group()

static void iv_ca_add_group ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_group * group )
static
Extend set IVS by expressing USE by some of the candidates in it
if possible.  Consider all important candidates if candidates in
set IVS don't give any result.   

References cheaper_cost_pair(), EXECUTE_IF_SET_IN_BITMAP, gcc_assert, get_group_iv_cost(), ggc_alloc(), i, iv_group::id, iv_ca_set_cp(), and NULL.

Referenced by try_add_cand_for().

◆ iv_ca_cand_for_group()

static class cost_pair * iv_ca_cand_for_group ( class iv_ca * ivs,
struct iv_group * group )
static
Returns candidate by that USE is expressed in IVS.   

References ggc_alloc(), and iv_group::id.

Referenced by find_optimal_iv_set(), iv_ca_delta_commit(), iv_ca_dump(), iv_ca_extend(), iv_ca_narrow(), iv_ca_replace(), and try_add_cand_for().

◆ iv_ca_cand_used_p()

static bool iv_ca_cand_used_p ( class iv_ca * ivs,
struct iv_cand * cand )
static
Returns true if CAND is used in IVS.   

References ggc_alloc().

Referenced by try_add_cand_for(), and try_improve_iv_set().

◆ iv_ca_compare_deps()

static int iv_ca_compare_deps ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_group * group,
class cost_pair * old_cp,
class cost_pair * new_cp )
static
Compare if applying NEW_CP to GROUP for IVS introduces more invariants
than OLD_CP.  Return 1, 0 and -1 for more, equal and fewer invariants
respectively.   

References gcc_assert, ggc_alloc(), and iv_ca_set_cp().

Referenced by iv_ca_extend().

◆ iv_ca_cost()

◆ iv_ca_delta_add()

static struct iv_ca_delta * iv_ca_delta_add ( struct iv_group * group,
class cost_pair * old_cp,
class cost_pair * new_cp,
struct iv_ca_delta * next )
static
Creates change of expressing GROUP by NEW_CP instead of OLD_CP and chains
it before NEXT.   

References ggc_alloc(), iv_ca_delta::group, iv_ca_delta::new_cp, iv_ca_delta::next, and iv_ca_delta::old_cp.

Referenced by iv_ca_extend(), iv_ca_narrow(), iv_ca_replace(), and try_add_cand_for().

◆ iv_ca_delta_commit()

static void iv_ca_delta_commit ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_ca_delta * delta,
bool forward )
static
Commit changes in DELTA to IVS.  If FORWARD is false, the changes are
reverted instead.   

References gcc_assert, ggc_alloc(), iv_ca_cand_for_group(), iv_ca_delta_reverse(), and iv_ca_set_cp().

Referenced by iv_ca_extend(), iv_ca_narrow(), iv_ca_prune(), iv_ca_replace(), try_add_cand_for(), and try_improve_iv_set().

◆ iv_ca_delta_free()

static void iv_ca_delta_free ( struct iv_ca_delta ** delta)
static
Free the list of changes DELTA.   

References free(), ggc_alloc(), iv_ca_delta::next, and NULL.

Referenced by iv_ca_narrow(), iv_ca_prune(), iv_ca_replace(), try_add_cand_for(), and try_improve_iv_set().

◆ iv_ca_delta_join()

static struct iv_ca_delta * iv_ca_delta_join ( struct iv_ca_delta * l1,
struct iv_ca_delta * l2 )
static
Joins two lists of changes L1 and L2.  Destructive -- old lists
are rewritten.   

References ggc_alloc(), last, and filedep::next.

Referenced by iv_ca_prune(), iv_ca_replace(), and try_improve_iv_set().

◆ iv_ca_delta_reverse()

static struct iv_ca_delta * iv_ca_delta_reverse ( struct iv_ca_delta * delta)
static
Reverse the list of changes DELTA, forming the inverse to it.   

References ggc_alloc(), iv_ca_delta::next, and NULL.

Referenced by iv_ca_delta_commit().

◆ iv_ca_dump()

◆ iv_ca_extend()

static comp_cost iv_ca_extend ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_cand * cand,
struct iv_ca_delta ** delta,
unsigned * n_ivs,
bool min_ncand )
static
Try changing candidate in IVS to CAND for each use.  Return cost of the
new set, and store differences in DELTA.  Number of induction variables
in the new set is stored to N_IVS. MIN_NCAND is a flag. When it is true
the function will try to find a solution with mimimal iv candidates.   

References cost_pair::cand, compare_cost_pair(), cost_pair::cost, get_group_iv_cost(), ggc_alloc(), i, iv_ca_cand_for_group(), iv_ca_compare_deps(), iv_ca_cost(), iv_ca_delta_add(), iv_ca_delta_commit(), iv_ca_n_cands(), and NULL.

Referenced by try_add_cand_for(), and try_improve_iv_set().

◆ iv_ca_free()

static void iv_ca_free ( class iv_ca ** ivs)
static
Free memory occupied by the set IVS.   

References BITMAP_FREE, free(), ggc_alloc(), and NULL.

Referenced by find_optimal_iv_set(), find_optimal_iv_set_1(), get_initial_solution(), and tree_ssa_iv_optimize_loop().

◆ iv_ca_n_cands()

static unsigned iv_ca_n_cands ( class iv_ca * ivs)
static
Returns number of induction variable candidates in the set IVS.   

References ggc_alloc().

Referenced by iv_ca_extend().

◆ iv_ca_narrow()

static comp_cost iv_ca_narrow ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_cand * cand,
struct iv_cand * start,
struct iv_ca_delta ** delta )
static
Try narrowing set IVS by removing CAND.  Return the cost of
the new set and store the differences in DELTA.  START is
the candidate with which we start narrowing.   

References cost_pair::cand, iv_cand::cost, EXECUTE_IF_AND_IN_BITMAP, EXECUTE_IF_SET_IN_BITMAP, get_group_iv_cost(), ggc_alloc(), i, infinite_cost, iv_ca_cand_for_group(), iv_ca_cost(), iv_ca_delta_add(), iv_ca_delta_commit(), iv_ca_delta_free(), iv_ca_set_cp(), NULL, and iv_group::related_cands.

Referenced by iv_ca_prune().

◆ iv_ca_new()

static class iv_ca * iv_ca_new ( struct ivopts_data * data)
static
Allocates new iv candidates assignment.   

References BITMAP_ALLOC, ggc_alloc(), no_cost, and NULL.

Referenced by get_initial_solution().

◆ iv_ca_prune()

static comp_cost iv_ca_prune ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_cand * except_cand,
struct iv_ca_delta ** delta )
static
Try optimizing the set of candidates IVS by removing candidates different
from to EXCEPT_CAND from it.  Return cost of the new set, and store
differences in DELTA.   

References EXECUTE_IF_SET_IN_BITMAP, ggc_alloc(), i, iv_ca_cost(), iv_ca_delta_commit(), iv_ca_delta_free(), iv_ca_delta_join(), iv_ca_narrow(), iv_ca_prune(), and NULL.

Referenced by iv_ca_prune(), iv_ca_replace(), and try_improve_iv_set().

◆ iv_ca_recount_cost()

static void iv_ca_recount_cost ( struct ivopts_data * data,
class iv_ca * ivs )
static
Computes the cost field of IVS structure.   

References cost_pair::cost, ggc_alloc(), and ivopts_estimate_reg_pressure().

Referenced by iv_ca_set_cp(), and iv_ca_set_no_cp().

◆ iv_ca_replace()

static comp_cost iv_ca_replace ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_ca_delta ** delta )
static
Try breaking local optimal fixed-point for IVS by replacing candidates
which are used by more than one iv uses.  For each of those candidates,
this function tries to represent iv uses under that candidate using
other ones with lower local cost, then tries to prune the new set.
If the new set has lower cost, It returns the new cost after recording
candidate replacement in list DELTA.   

References ALWAYS_PRUNE_CAND_SET_BOUND, cost_pair::cand, cheaper_cost_with_cand(), EXECUTE_IF_SET_IN_BITMAP, ggc_alloc(), i, iv_ca_cand_for_group(), iv_ca_cost(), iv_ca_delta_add(), iv_ca_delta_commit(), iv_ca_delta_free(), iv_ca_delta_join(), iv_ca_prune(), NULL, and iv_group::related_cands.

Referenced by try_improve_iv_set().

◆ iv_ca_set_add_invs()

static void iv_ca_set_add_invs ( class iv_ca * ivs,
bitmap invs,
unsigned * n_inv_uses )
static
Add use of invariants in set INVS by increasing counter in N_INV_USES and
IVS.   

References EXECUTE_IF_SET_IN_BITMAP, gcc_assert, ggc_alloc(), and NULL.

Referenced by iv_ca_set_cp().

◆ iv_ca_set_cp()

◆ iv_ca_set_no_cp()

static void iv_ca_set_no_cp ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_group * group )
static
Set USE not to be expressed by any candidate in IVS.   

References bitmap_clear_bit(), ggc_alloc(), iv_group::id, iv_ca_recount_cost(), iv_ca_set_remove_invs(), NULL, and targetm.

Referenced by iv_ca_set_cp(), and try_add_cand_for().

◆ iv_ca_set_remove_invs()

static void iv_ca_set_remove_invs ( class iv_ca * ivs,
bitmap invs,
unsigned * n_inv_uses )
static
Remove use of invariants in set INVS by decreasing counter in N_INV_USES
and IVS.   

References EXECUTE_IF_SET_IN_BITMAP, gcc_assert, ggc_alloc(), and NULL.

Referenced by iv_ca_set_no_cp().

◆ iv_elimination_compare()

static enum tree_code iv_elimination_compare ( struct ivopts_data * data,
struct iv_use * use )
static
Returns the comparison operator used when eliminating the iv USE.   

References EDGE_SUCC, flow_bb_inside_loop_p(), ggc_alloc(), and gimple_bb().

Referenced by may_eliminate_iv().

◆ iv_elimination_compare_lt()

static bool iv_elimination_compare_lt ( struct ivopts_data * data,
struct iv_cand * cand,
enum tree_code * comp_p,
class tree_niter_desc * niter )
static
Tries to replace loop exit by one formulated in terms of a LT_EXPR
comparison with CAND.  NITER describes the number of iterations of
the loops.  If successful, the comparison in COMP_P is altered accordingly.

We aim to handle the following situation:

sometype *base, *p;
int a, b, i;

i = a;
p = p_0 = base + a;

do
  {
    bla (*p);
    p++;
    i++;
  }
while (i < b);

Here, the number of iterations of the loop is (a + 1 > b) ? 0 : b - a - 1.
We aim to optimize this to

p = p_0 = base + a;
do
  {
    bla (*p);
    p++;
  }
while (p < p_0 - a + b);

This preserves the correctness, since the pointer arithmetics does not
overflow.  More precisely:

1) if a + 1 <= b, then p_0 - a + b is the final value of p, hence there is no
   overflow in computing it or the values of p.
2) if a + 1 > b, then we need to verify that the expression p_0 - a does not
   overflow.  To prove this, we use the fact that p_0 = base + a.   

References a, aff_combination_add(), aff_combination_scale(), b, comp, cst_and_fits_in_hwi(), difference_cannot_overflow_p(), fold_build2, fold_convert, gcc_unreachable, ggc_alloc(), int_cst_value(), integer_onep(), invert_tree_comparison(), IP_ORIGINAL, tree_niter_desc::may_be_zero, tree_niter_desc::niter, nowrap_type_p(), offset, TREE_CODE, TREE_OPERAND, tree_to_aff_combination(), and TREE_TYPE.

Referenced by may_eliminate_iv().

◆ iv_period()

static tree iv_period ( struct iv * iv)
static

◆ ivopts_estimate_reg_pressure()

static unsigned ivopts_estimate_reg_pressure ( struct ivopts_data * data,
unsigned n_invs,
unsigned n_cands )
static
Estimate register pressure for loop having N_INVS invariants and N_CANDS
induction variables.  Note N_INVS includes both invariant variables and
invariant expressions.   

References iv_cand::cost, ggc_alloc(), target_avail_regs, target_clobbered_regs, target_reg_cost, target_res_regs, and target_spill_cost.

Referenced by determine_set_costs(), iv_ca_dump(), and iv_ca_recount_cost().

◆ loop_body_includes_call()

static bool loop_body_includes_call ( basic_block * body,
unsigned num_nodes )
static
Returns true if the loop body BODY includes any function calls.   

References gimple_call_fndecl(), gimple_call_internal_p(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), i, is_gimple_call(), and is_inexpensive_builtin().

Referenced by tree_ssa_iv_optimize_loop().

◆ mark_bivs()

◆ may_be_nonaddressable_p()

◆ may_be_unaligned_p()

static bool may_be_unaligned_p ( tree ref,
tree step )
static
Return true if memory reference REF with step STEP may be unaligned.   

References GET_MODE_ALIGNMENT, get_object_alignment_1(), ggc_alloc(), HOST_BITS_PER_INT, TREE_CODE, tree_ctz(), TREE_TYPE, TYPE_ALIGN, and TYPE_MODE.

Referenced by find_interesting_uses_address().

◆ may_eliminate_iv()

◆ name_info()

static struct version_info * name_info ( struct ivopts_data * data,
tree name )
inlinestatic

◆ niter_for_exit()

static class tree_niter_desc * niter_for_exit ( struct ivopts_data * data,
edge exit )
static
Returns the structure describing number of iterations determined from
EXIT of DATA->current_loop, or NULL if something goes wrong.   

References contains_abnormal_ssa_name_p(), ggc_alloc(), tree_niter_desc::niter, NULL, and number_of_iterations_exit().

Referenced by generic_predict_doloop_p(), may_eliminate_iv(), and niter_for_single_dom_exit().

◆ niter_for_single_dom_exit()

static class tree_niter_desc * niter_for_single_dom_exit ( struct ivopts_data * data)
static
Returns the structure describing number of iterations determined from
single dominating exit of DATA->current_loop, or NULL if something
goes wrong.   

References niter_for_exit(), NULL, and single_dom_exit().

Referenced by add_iv_candidate_for_doloop(), and find_induction_variables().

◆ operator+()

comp_cost operator+ ( comp_cost cost1,
comp_cost cost2 )

◆ operator-()

comp_cost operator- ( comp_cost cost1,
comp_cost cost2 )

◆ operator<()

bool operator< ( comp_cost cost1,
comp_cost cost2 )

◆ operator<=()

bool operator<= ( comp_cost cost1,
comp_cost cost2 )

◆ operator==()

bool operator== ( comp_cost cost1,
comp_cost cost2 )

◆ outermost_invariant_loop_for_expr()

class loop * outermost_invariant_loop_for_expr ( class loop * loop,
tree expr )
Returns the outermost loop EXPR is obviously invariant in
relative to the loop LOOP, i.e. if all its operands are defined
outside of the returned loop.  Returns NULL if EXPR is not
even obviously invariant in LOOP.   

References current_loops, EXPR_P, flow_bb_inside_loop_p(), ggc_alloc(), gimple_bb(), i, is_gimple_min_invariant(), loop_depth(), MAX, NULL, outermost_invariant_loop_for_expr(), SSA_NAME_DEF_STMT, superloop_at_depth(), TREE_CODE, TREE_OPERAND, and TREE_OPERAND_LENGTH.

Referenced by outermost_invariant_loop_for_expr(), vect_enhance_data_refs_alignment(), and vect_loop_versioning().

◆ parm_decl_cost()

◆ prepare_decl_rtl()

static tree prepare_decl_rtl ( tree * expr_p,
int * ws,
void * data )
static
Prepares decl_rtl for variables referred in *EXPR_P.  Callback for
walk_tree.  DATA contains the actual fake register number.   

References DECL_MODE, DECL_P, DECL_RTL_SET_P, decl_rtl_to_reset, gen_raw_REG(), ggc_alloc(), handled_component_p(), HAS_RTL_P, NULL_RTX, NULL_TREE, produce_memory_decl_rtl(), SET_DECL_RTL, SSA_NAME_VAR, TREE_CODE, and TREE_OPERAND.

Referenced by computation_cost().

◆ produce_memory_decl_rtl()

static rtx produce_memory_decl_rtl ( tree obj,
int * regno )
static

◆ record_biv_for_address_use()

static void record_biv_for_address_use ( struct ivopts_data * data,
struct iv * biv )
static
Record BIV, its predecessor and successor that they are used in
address type uses.   

References iv::base, iv::biv_p, EXECUTE_IF_SET_IN_BITMAP, fold_build2, ggc_alloc(), iv::have_address_use, i, integer_zerop(), INTEGRAL_TYPE_P, version_info::iv, iv::no_overflow, operand_equal_p(), iv::step, TREE_TYPE, type(), and ver_info().

Referenced by idx_find_step().

◆ record_common_cand()

static void record_common_cand ( struct ivopts_data * data,
tree base,
tree step,
struct iv_use * use )
static
Record common candidate {BASE, STEP} derived from USE in hashtable.   

References iv_common_cand::base, gcc_assert, ggc_alloc(), iterative_hash_expr(), NULL, and iv_common_cand::step.

Referenced by add_iv_candidate_for_use().

◆ record_group()

◆ record_group_use()

static struct iv_use * record_group_use ( struct ivopts_data * data,
tree * use_p,
struct iv * iv,
gimple * stmt,
enum use_type type,
tree mem_type )
static
Record a use of TYPE at *USE_P in STMT whose value is IV in a group.
New group will be created if there is no existing group for the use.
MEM_TYPE is the type of memory being addressed, or NULL if this
isn't an address reference.   

References iv_use::addr_base, iv_use::addr_offset, address_p(), iv::base, iv::base_object, gcc_assert, ggc_alloc(), i, int_cst_value(), iv_use::mem_type, NULL, operand_equal_p(), POINTER_TYPE_P, record_group(), record_use(), split_constant_offset(), iv::step, iv_use::stmt, TREE_TYPE, and iv_group::vuses.

Referenced by find_address_like_use(), find_interesting_uses_address(), find_interesting_uses_cond(), and find_interesting_uses_op().

◆ record_important_candidates()

static void record_important_candidates ( struct ivopts_data * data)
static
Record important candidates and add them to related_cands bitmaps.   

References bitmap_ior_into(), bitmap_set_bit, CONSIDER_ALL_CANDIDATES_BOUND, i, and iv_group::related_cands.

Referenced by find_iv_candidates().

◆ record_invariant()

static void record_invariant ( struct ivopts_data * data,
tree op,
bool nonlinear_use )
static
Checks whether OP is a loop-level invariant and if so, records it.
NONLINEAR_USE is true if the invariant is used in a way we do not
handle specially.   

References bitmap_set_bit, flow_bb_inside_loop_p(), ggc_alloc(), gimple_bb(), version_info::has_nonlin_use, version_info::inv_id, version_info::name, name_info(), SSA_NAME_DEF_STMT, SSA_NAME_VERSION, TREE_CODE, and virtual_operand_p().

Referenced by find_interesting_uses_op(), find_inv_vars_cb(), and find_invariants_stmt().

◆ record_use()

static struct iv_use * record_use ( struct iv_group * group,
tree * use_p,
struct iv * iv,
gimple * stmt,
enum use_type type,
tree mem_type,
tree addr_base,
poly_uint64 addr_offset )
static
Records a use of TYPE at *USE_P in STMT whose value is IV in GROUP.
For address type use, ADDR_BASE is the stripped IV base, ADDR_OFFSET
is the const offset stripped from IV base and MEM_TYPE is the type
of the memory being addressed.  For uses of other types, ADDR_BASE
and ADDR_OFFSET are zero by default and MEM_TYPE is NULL_TREE.   

References iv_use::addr_base, iv_use::addr_offset, ggc_alloc(), iv_group::id, iv_use::iv, iv_use::mem_type, iv_use::stmt, type(), and iv_group::vuses.

Referenced by record_group_use().

◆ relate_compare_use_with_all_cands()

static void relate_compare_use_with_all_cands ( struct ivopts_data * data)
static
Relate compare use with all candidates.   

References bitmap_set_range(), count, i, iv_group::related_cands, iv_group::type, and USE_COMPARE.

Referenced by find_iv_candidates().

◆ remove_unused_ivs()

◆ rewrite_groups()

◆ rewrite_use_address()

◆ rewrite_use_compare()

◆ rewrite_use_nonlinear_expr()

◆ set_autoinc_for_original_candidates()

static void set_autoinc_for_original_candidates ( struct ivopts_data * data)
static
Examine IP_ORIGINAL candidates to see if they are incremented next to a
use that allows autoincrement, and set their AINC_USE if possible.   

References autoinc_possible_for_pair(), ggc_alloc(), gimple_bb(), gimple_uid(), i, IP_ORIGINAL, NULL, and iv_group::vuses.

Referenced by find_iv_candidates().

◆ set_group_iv_cost()

static void set_group_iv_cost ( struct ivopts_data * data,
struct iv_group * group,
struct iv_cand * cand,
comp_cost cost,
bitmap inv_vars,
tree value,
enum tree_code comp,
bitmap inv_exprs )
static
Sets cost of (GROUP, CAND) pair to COST and record that it depends
on invariants INV_VARS and that the value used in expressing it is
VALUE, and in case of iv elimination the comparison operator is COMP.   

References BITMAP_FREE, cost_pair::cand, comp, cost_pair::comp, cost_pair::cost, iv_group::cost_map, gcc_unreachable, i, comp_cost::infinite_cost_p(), cost_pair::inv_exprs, cost_pair::inv_vars, iv_group::n_map_members, and cost_pair::value.

Referenced by determine_group_iv_cost_address(), determine_group_iv_cost_cond(), and determine_group_iv_cost_generic().

◆ set_iv()

static void set_iv ( struct ivopts_data * data,
tree iv,
tree base,
tree step,
bool no_overflow )
static
Sets STEP and BASE for induction variable IV.  NO_OVERFLOW implies the IV
doesn't overflow.   

References alloc_iv(), bitmap_set_bit, gcc_assert, version_info::iv, name_info(), iv::ssa_name, and SSA_NAME_VERSION.

Referenced by find_bivs(), find_givs_in_stmt(), find_inv_vars_cb(), and get_iv().

◆ single_dom_exit()

◆ sort_iv_inv_expr_ent()

static int sort_iv_inv_expr_ent ( const void * a,
const void * b )
static
Sort iv_inv_expr_ent pair A and B by id field.   

References a, b, and ggc_alloc().

Referenced by determine_group_iv_costs().

◆ split_address_groups()

static void split_address_groups ( struct ivopts_data * data)
static
For each group of address type uses, this function further groups
these uses according to the maximum offset supported by target's
[base + offset] addressing mode.   

References iv_use::addr_offset, addr_offset_valid_p(), address_p(), gcc_assert, ggc_alloc(), iv_use::group_id, i, iv_use::id, iv_group::id, NULL, offset, record_group(), split_small_address_groups_p(), iv_group::type, and iv_group::vuses.

Referenced by find_interesting_uses().

◆ split_small_address_groups_p()

static bool split_small_address_groups_p ( struct ivopts_data * data)
static
Check if small groups should be split.  Return true if no group
contains more than two uses with distinct addr_offsets.  Return
false otherwise.  We want to split such groups because:

  1) Small groups don't have much benefit and may interfer with
     general candidate selection.
  2) Size for problem with only small groups is usually small and
     general algorithm can handle it well.

TODO -- Above claim may not hold when we want to merge memory
accesses with conseuctive addresses.   

References iv_use::addr_offset, address_p(), gcc_assert, ggc_alloc(), group_compare_offset(), i, iv_group::type, and iv_group::vuses.

Referenced by split_address_groups().

◆ stmt_after_inc_pos()

static bool stmt_after_inc_pos ( struct iv_cand * cand,
gimple * stmt,
bool true_if_equal )
static
Returns true if STMT if after the place where the original induction
variable CAND is incremented.  If TRUE_IF_EQUAL is set, we return true
if the positions are identical.   

References CDI_DOMINATORS, dominated_by_p(), ggc_alloc(), gimple_bb(), and gimple_uid().

Referenced by stmt_after_increment().

◆ stmt_after_increment()

static bool stmt_after_increment ( class loop * loop,
struct iv_cand * cand,
gimple * stmt )
static
Returns true if STMT if after the place where the induction variable
CAND is incremented in LOOP.   

References gcc_unreachable, IP_AFTER_USE, IP_BEFORE_USE, IP_END, IP_NORMAL, IP_ORIGINAL, stmt_after_inc_pos(), and stmt_after_ip_normal_pos().

Referenced by cand_value_at(), get_address_cost(), get_computation_aff_1(), get_debug_computation_at(), may_eliminate_iv(), and var_at_stmt().

◆ stmt_after_ip_normal_pos()

static bool stmt_after_ip_normal_pos ( class loop * loop,
gimple * stmt )
static
Returns true if STMT is after the place where the IP_NORMAL ivs will be
emitted in LOOP.   

References gcc_assert, ggc_alloc(), gimple_bb(), ip_normal_pos(), last_nondebug_stmt(), and loop::latch.

Referenced by stmt_after_increment().

◆ strip_offset()

static tree strip_offset ( tree expr,
poly_uint64 * offset )
static
Strips constant offsets from EXPR and stores them to OFFSET.   

References ggc_alloc(), offset, and strip_offset_1().

Referenced by add_iv_candidate_for_use().

◆ strip_offset_1()

static tree strip_offset_1 ( tree expr,
bool inside_addr,
bool top_compref,
poly_int64 * offset )
static
Strips constant offsets from EXPR and stores them to OFFSET.  If INSIDE_ADDR
is true, assume we are inside an address.  If TOP_COMPREF is true, assume
we are at the top-level of the processed address.   

References abs_hwi(), array_ref_element_size(), build_fold_addr_expr, build_int_cst(), component_ref_field_offset(), copy_node(), cst_and_fits_in_hwi(), DECL_FIELD_BIT_OFFSET, expr, fold_build1, fold_build2, fold_convert, ggc_alloc(), int_cst_value(), integer_zerop(), NULL_TREE, offset, ptrdiff_tree_p(), STRIP_NOPS, strip_offset_1(), TREE_CODE, TREE_OPERAND, TREE_TYPE, type(), TYPE_OVERFLOW_UNDEFINED, and unsigned_type_for().

Referenced by strip_offset(), and strip_offset_1().

◆ tree_ssa_iv_optimize()

◆ tree_ssa_iv_optimize_finalize()

static void tree_ssa_iv_optimize_finalize ( struct ivopts_data * data)
static
Finalizes data structures used by the iv optimization pass.  LOOPS is the
loop tree.   

References BITMAP_FREE, decl_rtl_to_reset, free(), free_affine_expand_cache(), free_loop_data(), ggc_alloc(), and NULL.

Referenced by tree_ssa_iv_optimize().

◆ tree_ssa_iv_optimize_init()

static void tree_ssa_iv_optimize_init ( struct ivopts_data * data)
static
Initializes data structures used by the iv optimization pass, stored
in DATA.   

References BITMAP_ALLOC, decl_rtl_to_reset, gcc_obstack_init, ggc_alloc(), NULL, and num_ssa_names.

Referenced by tree_ssa_iv_optimize().

◆ tree_ssa_iv_optimize_loop()

◆ try_add_cand_for()

static bool try_add_cand_for ( struct ivopts_data * data,
class iv_ca * ivs,
struct iv_group * group,
bool originalp )
static
Tries to extend the sets IVS in the best possible way in order to
express the GROUP.  If ORIGINALP is true, prefer candidates from
the original set of IVs, otherwise favor important candidates not
based on any memory object.   

References iv_group::cost_map, EXECUTE_IF_SET_IN_BITMAP, get_group_iv_cost(), ggc_alloc(), i, IP_ORIGINAL, iv_ca_add_group(), iv_ca_cand_for_group(), iv_ca_cand_used_p(), iv_ca_cost(), iv_ca_delta_add(), iv_ca_delta_commit(), iv_ca_delta_free(), iv_ca_extend(), iv_ca_set_cp(), iv_ca_set_no_cp(), iv_group::n_map_members, NULL, NULL_TREE, and iv_group::related_cands.

Referenced by get_initial_solution().

◆ try_improve_iv_set()

static bool try_improve_iv_set ( struct ivopts_data * data,
class iv_ca * ivs,
bool * try_replace_p )
static
Tries to improve set of induction variables IVS.  TRY_REPLACE_P
points to a bool variable, this function tries to break local
optimal fixed-point by replacing candidates in IVS if it's true.   

References ALWAYS_PRUNE_CAND_SET_BOUND, ggc_alloc(), i, iv_ca_cand_used_p(), iv_ca_cost(), iv_ca_delta_commit(), iv_ca_delta_free(), iv_ca_delta_join(), iv_ca_extend(), iv_ca_prune(), iv_ca_replace(), and NULL.

Referenced by find_optimal_iv_set_1().

◆ var_at_stmt()

static tree var_at_stmt ( class loop * loop,
struct iv_cand * cand,
gimple * stmt )
static
Returns variable containing the value of candidate CAND at statement AT.   

References stmt_after_increment().

Referenced by get_computation_aff_1(), get_debug_computation_at(), rewrite_use_address(), and rewrite_use_compare().

◆ ver_info()

Variable Documentation

◆ addr_list

vec<rtx, va_gc>* addr_list
static
Return TRUE if OFFSET is within the range of [base + offset] addressing
mode for memory reference represented by USE.   

Referenced by addr_offset_valid_p(), and new_elt_loc_list().

◆ decl_rtl_to_reset

vec<tree> decl_rtl_to_reset
static
The list of trees for that the decl_rtl field must be reset is stored
here.   

Referenced by free_loop_data(), prepare_decl_rtl(), tree_ssa_iv_optimize_finalize(), and tree_ssa_iv_optimize_init().

◆ infinite_cost

◆ no_cost