GCC Middle and Back End API Reference
|
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
#include "cgraph.h"
#include "gimple-pretty-print.h"
#include "fold-const.h"
#include "profile.h"
#include "gimple-iterator.h"
#include "gimple-fold.h"
#include "tree-eh.h"
#include "tree-cfg.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
#include "tree-inline.h"
#include "tree-cfgcleanup.h"
#include "builtins.h"
#include "tree-ssa-sccvn.h"
#include "tree-vectorizer.h"
#include "dbgcnt.h"
Data Structures | |
struct | loop_size |
Macros | |
#define | INCLUDE_MEMORY |
Enumerations | |
enum | unroll_level { UL_SINGLE_ITER , UL_NO_GROWTH , UL_ALL } |
Functions | |
void | create_canonical_iv (class loop *loop, edge exit, tree niter, tree *var_before=NULL, tree *var_after=NULL) |
static bool | constant_after_peeling (tree op, gimple *stmt, class loop *loop) |
static bool | tree_estimate_loop_size (class loop *loop, edge exit, edge edge_to_cancel, struct loop_size *size, int upper_bound) |
static unsigned HOST_WIDE_INT | estimated_unrolled_size (struct loop_size *size, unsigned HOST_WIDE_INT nunroll) |
static edge | loop_edge_to_cancel (class loop *loop) |
static bool | remove_exits_and_undefined_stmts (class loop *loop, unsigned int npeeled) |
static bool | remove_redundant_iv_tests (class loop *loop) |
void | unloop_loops (vec< class loop * > &loops_to_unloop, vec< int > &loops_to_unloop_nunroll, vec< edge > &edges_to_remove, bitmap loop_closed_ssa_invalidated, bool *irred_invalidated) |
static bool | try_unroll_loop_completely (class loop *loop, edge exit, tree niter, bool may_be_zero, enum unroll_level ul, HOST_WIDE_INT maxiter, dump_user_location_t locus, bool allow_peel, bool cunrolli) |
static unsigned HOST_WIDE_INT | estimated_peeled_sequence_size (struct loop_size *size, unsigned HOST_WIDE_INT npeel) |
void | adjust_loop_info_after_peeling (class loop *loop, int npeel, bool precise) |
static bool | try_peel_loop (class loop *loop, edge exit, tree niter, bool may_be_zero, HOST_WIDE_INT maxiter) |
static bool | canonicalize_loop_induction_variables (class loop *loop, bool create_iv, enum unroll_level ul, bool try_eval, bool allow_peel, bool cunrolli) |
unsigned int | canonicalize_induction_variables (void) |
static bool | tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer, bitmap father_bbs, class loop *loop, bool cunrolli) |
static unsigned int | tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) |
gimple_opt_pass * | make_pass_iv_canon (gcc::context *ctxt) |
gimple_opt_pass * | make_pass_complete_unroll (gcc::context *ctxt) |
gimple_opt_pass * | make_pass_complete_unrolli (gcc::context *ctxt) |
Variables | |
static vec< loop_p > | loops_to_unloop |
static vec< int > | loops_to_unloop_nunroll |
static vec< edge > | edges_to_remove |
static bitmap | peeled_loops |
#define INCLUDE_MEMORY |
Induction variable canonicalization and loop peeling. Copyright (C) 2004-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 detects the loops that iterate a constant number of times, adds a canonical induction variable (step -1, tested against 0) and replaces the exit test. This enables the less powerful rtl level analysis to use this information. This might spoil the code in some cases (by increasing register pressure). Note that in the case the new variable is not needed, ivopts will get rid of it, so it might only be a problem when there are no other linear induction variables. In that case the created optimization possibilities are likely to pay up. We also perform - complete unrolling (or peeling) when the loops is rolling few enough times - simple peeling (i.e. copying few initial iterations prior the loop) when number of iteration estimate is known (typically by the profile info).
enum unroll_level |
Update loop estimates after peeling LOOP by NPEEL. If PRECISE is false only likely exists were duplicated and thus do not update any estimates that are supposed to be always reliable.
References loop::any_estimate, loop::any_likely_upper_bound, loop::any_upper_bound, gcc_unreachable, wi::leu_p(), loop::nb_iterations_estimate, loop::nb_iterations_likely_upper_bound, and loop::nb_iterations_upper_bound.
Referenced by try_peel_loop().
unsigned int canonicalize_induction_variables | ( | void | ) |
The main entry point of the pass. Adds canonical induction variables to the suitable loops.
References BITMAP_ALLOC, bitmap_empty_p(), BITMAP_FREE, canonicalize_loop_induction_variables(), cfun, changed, edges_to_remove, estimate_numbers_of_iterations(), free_numbers_of_iterations_estimates(), gcc_assert, gcc_checking_assert, LI_FROM_INNERMOST, LOOP_CLOSED_SSA, LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS, loops_state_satisfies_p(), loops_to_unloop, loops_to_unloop_nunroll, mark_irreducible_loops(), need_ssa_update_p(), NULL, rewrite_into_loop_closed_ssa(), scev_reset(), TODO_cleanup_cfg, TODO_update_ssa, UL_SINGLE_ITER, and unloop_loops().
|
static |
Adds a canonical induction variable to LOOP if suitable. CREATE_IV is true if we may create a new iv. UL determines which loops we are allowed to completely unroll. If TRY_EVAL is true, we try to determine the number of iterations of a loop by direct evaluation. Returns true if cfg is changed.
References build_int_cst(), chrec_contains_undetermined(), chrec_dont_know, COMPARISON_CLASS_P, create_canonical_iv(), create_iv(), dump_file, dump_flags, find_loop_location(), find_loop_niter(), find_loop_niter_by_eval(), fold_build3, get_loop_exit_edges(), integer_zerop(), just_once_each_iteration_p(), likely_max_loop_iterations_int(), max_loop_iterations_int(), tree_niter_desc::may_be_zero, niter_desc::niter, tree_niter_desc::niter, NULL, NULL_TREE, loop::num, number_of_iterations_exit(), print_generic_expr(), record_niter_bound(), remove_redundant_iv_tests(), single_exit(), single_likely_exit(), TDF_DETAILS, TDF_SLIM, wi::to_widest(), TREE_CODE, TREE_TYPE, try_peel_loop(), try_unroll_loop_completely(), ul, and UL_ALL.
Referenced by canonicalize_induction_variables(), and tree_unroll_loops_completely_1().
Return true if OP in STMT will be constant after peeling LOOP.
References analyze_scalar_evolution(), ANY_INTEGRAL_TYPE_P, as_a(), chrec_contains_symbols(), chrec_contains_undetermined(), constant_after_peeling(), CONSTANT_CLASS_P, ctor_for_folding(), DECL_P, dyn_cast(), error_mark_node, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), gimple_bb(), GIMPLE_BINARY_RHS, gimple_phi_arg_def_from_edge(), gimple_phi_result(), handled_component_p(), loop::header, is_a(), loop_containing_stmt(), loop_latch_edge(), loop_preheader_edge(), SSA_NAME_DEF_STMT, TREE_CODE, TREE_OPERAND, and TREE_TYPE.
Referenced by constant_after_peeling(), and tree_estimate_loop_size().
void create_canonical_iv | ( | class loop * | loop, |
edge | exit, | ||
tree | niter, | ||
tree * | var_before = NULL, | ||
tree * | var_after = NULL ) |
Adds a canonical induction variable to LOOP iterating NITER times. EXIT is the exit edge whose condition is replaced. The ssa versions of the new IV before and after increment will be stored in VAR_BEFORE and VAR_AFTER if they are not NULL.
References as_a(), build_int_cst(), create_iv(), dump_file, dump_flags, EDGE_SUCC, fold_build2, gimple_cond_set_code(), gimple_cond_set_lhs(), gimple_cond_set_rhs(), gsi_last_bb(), NULL_TREE, loop::num, print_generic_expr(), TDF_DETAILS, TDF_SLIM, TREE_TYPE, type(), and update_stmt().
Referenced by canonicalize_loop_induction_variables(), and tree_loop_interchange::interchange_loops().
|
static |
Return number of instructions after peeling.
References loop_size::eliminated_by_peeling, MAX, and loop_size::overall.
Referenced by try_peel_loop().
|
static |
Estimate number of insns of completely unrolled loop. It is (NUNROLL + 1) * size of loop body with taking into account the fact that in last copy everything after exit conditional is dead and that some instructions will be eliminated after peeling.
References loop_size::eliminated_by_peeling, loop_size::last_iteration, loop_size::last_iteration_eliminated_by_peeling, and loop_size::overall.
Referenced by try_unroll_loop_completely().
Loop LOOP is known to not loop. See if there is an edge in the loop body that can be remove to make the loop to always exit and at the same time it does not make any code potentially executed during the last iteration dead. After complete unrolling we still may get rid of the conditional on the exit in the last copy even if we have no idea what it does. This is quite common case for loops of form int a[5]; for (i=0;i<b;i++) a[i]=0; Here we prove the loop to iterate 5 times but we do not know it from induction variable. For now we handle only simple case where there is exit condition just before the latch block and the latch block contains no statements with side effect that may otherwise terminate the execution of loop (such as by EH or by terminating the program or longjmp). In the general case we may want to cancel the paths leading to statements loop-niter identified as having undefined effect in the last iteration. The other cases are hopefully rare and will be cleaned up later.
References EDGE_COUNT, EDGE_SUCC, FOR_EACH_VEC_ELT, gcc_assert, get_loop_exit_edges(), gimple_has_side_effects(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), loop::header, i, loop::latch, NULL, and basic_block_def::preds.
Referenced by try_unroll_loop_completely().
gimple_opt_pass * make_pass_complete_unroll | ( | gcc::context * | ctxt | ) |
gimple_opt_pass * make_pass_complete_unrolli | ( | gcc::context * | ctxt | ) |
gimple_opt_pass * make_pass_iv_canon | ( | gcc::context * | ctxt | ) |
Remove all tests for exits that are known to be taken after LOOP was peeled NPEELED times. Put gcc_unreachable before every statement known to not be executed.
References profile_probability::always(), as_a(), nb_iter_bound::bound, loop::bounds, changed, dump_file, dump_flags, EDGE_SUCC, gcc_checking_assert, gimple_bb(), gimple_build_builtin_unreachable(), gimple_cond_make_false(), gimple_cond_make_true(), gimple_location(), gsi_for_stmt(), gsi_insert_before(), GSI_NEW_STMT, nb_iter_bound::is_exit, wi::leu_p(), loop_exit_edge_p(), wi::ltu_p(), nb_iter_bound::next, print_gimple_stmt(), split_block(), nb_iter_bound::stmt, TDF_DETAILS, and update_stmt().
Referenced by unloop_loops().
Remove all exits that are known to be never taken because of the loop bound discovered.
References loop::any_upper_bound, as_a(), nb_iter_bound::bound, loop::bounds, changed, dump_file, dump_flags, EDGE_SUCC, gimple_bb(), gimple_cond_make_false(), gimple_cond_make_true(), integer_onep(), integer_zerop(), nb_iter_bound::is_exit, loop_exit_edge_p(), wi::ltu_p(), loop::nb_iterations_upper_bound, nb_iter_bound::next, tree_niter_desc::niter, number_of_iterations_exit(), print_gimple_stmt(), SIGNED, nb_iter_bound::stmt, TDF_DETAILS, wi::to_widest(), TREE_CODE, and update_stmt().
Referenced by canonicalize_loop_induction_variables().
|
static |
Computes an estimated number of insns in LOOP. EXIT (if non-NULL) is an exite edge that will be eliminated in all but last iteration of the loop. EDGE_TO_CANCEL (if non-NULL) is an non-exit edge eliminated in the last iteration of loop. Return results in SIZE, estimate benefits for complete unrolling exiting by EXIT. Stop estimating after UPPER_BOUND is met. Return true in this case.
References as_a(), CDI_DOMINATORS, constant_after_peeling(), loop_size::constant_iv, dominated_by_p(), dump_file, dump_flags, ECF_CONST, ECF_PURE, loop_size::eliminated_by_peeling, eni_size_weights, estimate_num_insns(), free(), get_loop_body(), get_loop_hot_path(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), GIMPLE_BINARY_RHS, gimple_call_flags(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_has_side_effects(), gimple_inexpensive_call_p(), gimple_switch_index(), GIMPLE_TERNARY_RHS, gsi_end_p(), gsi_last_bb(), gsi_next(), gsi_start_bb(), gsi_stmt(), i, is_gimple_min_invariant(), loop_size::last_iteration, loop_size::last_iteration_eliminated_by_peeling, loop_size::non_call_stmts_on_hot_path, loop::num, loop_size::num_branches_on_hot_path, loop::num_nodes, loop_size::num_non_pure_calls_on_hot_path, loop_size::num_pure_calls_on_hot_path, loop_size::overall, print_gimple_stmt(), TDF_DETAILS, and TREE_CODE.
Referenced by try_peel_loop(), and try_unroll_loop_completely().
|
static |
Unroll LOOPS completely if they iterate just few times. Unless MAY_INCREASE_SIZE is true, perform the unrolling only if the size of the code does not increase.
References BASIC_BLOCK_FOR_FN, BITMAP_ALLOC, bitmap_clear(), bitmap_empty_p(), BITMAP_FREE, bitmap_set_bit, cfun, changed, cleanup_tree_cfg(), current_loops, do_rpo_vn(), loop_exit::e, edges_to_remove, estimate_numbers_of_iterations(), EXECUTE_IF_SET_IN_BITMAP, free_numbers_of_iterations_estimates(), get_loop(), i, LOOP_CLOSED_SSA, basic_block_def::loop_father, loop_outer(), loop_preheader_edge(), LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS, loops_state_satisfies_p(), loops_to_unloop, loops_to_unloop_nunroll, mark_irreducible_loops(), loop_exit::next, NULL, loop::num, rewrite_into_loop_closed_ssa(), scev_reset(), TODO_update_ssa, TODO_update_ssa_only_virtuals, tree_unroll_loops_completely_1(), unloop_loops(), update_ssa(), and verify_loop_closed_ssa().
|
static |
Process loops from innermost to outer, stopping at the innermost loop we unrolled.
References BITMAP_ALLOC, bitmap_bit_p, bitmap_clear(), BITMAP_FREE, bitmap_ior_into(), bitmap_set_bit, canonicalize_loop_induction_variables(), cfun, changed, loop::force_vectorize, loop::header, basic_block_def::index, loop::inner, loop_outer(), loop::next, NULL, loop::num, number_of_loops(), optimize_loop_nest_for_speed_p(), PENDING_TODO_force_next_scalar_cleanup, tree_unroll_loops_completely_1(), ul, UL_ALL, UL_NO_GROWTH, and loop::unroll.
Referenced by tree_unroll_loops_completely(), and tree_unroll_loops_completely_1().
|
static |
If the loop is expected to iterate N times and is small enough, duplicate the loop body N+1 times before the loop itself. This way the hot path will never enter the loop. Parameters are the same as for try_unroll_loops_completely
References adjust_loop_info_after_peeling(), bitmap_bit_p, bitmap_clear(), bitmap_clear_bit(), bitmap_ones(), bitmap_set_bit, dbg_cnt(), DLTHE_FLAG_UPDATE_FREQ, dump_file, dump_flags, edges_to_remove, estimated_loop_iterations_int(), estimated_peeled_sequence_size(), free_original_copy_tables(), gimple_duplicate_loop_body_to_header_edge(), initialize_original_copy_tables(), loop::inner, wi::leu_p(), likely_max_loop_iterations_int(), loop_preheader_edge(), NULL, loop::num, optimize_loop_for_speed_p(), peeled_loops, TDF_DETAILS, wi::to_widest(), TREE_CODE, tree_estimate_loop_size(), and loop::unroll.
Referenced by canonicalize_loop_induction_variables().
|
static |
Tries to unroll LOOP completely, i.e. NITER times. UL determines which loops we are allowed to unroll. EXIT is the exit of the loop that should be eliminated. MAXITER specfy bound on number of iterations, -1 if it is not known or too large for HOST_WIDE_INT. The location LOCUS corresponding to the loop is used when emitting a summary of the unroll to the dump file.
References profile_probability::always(), as_a(), bitmap_clear(), bitmap_clear_bit(), bitmap_ones(), loop_size::constant_iv, basic_block_def::count, dbg_cnt(), DLTHE_FLAG_COMPLETTE_PEEL, DLTHE_FLAG_UPDATE_FREQ, dump_enabled_p(), dump_file, dump_flags, dump_printf(), dump_printf_loc(), EDGE_SUCC, edges_to_remove, wi::eq_p(), estimated_unrolled_size(), force_edge_cold(), free_original_copy_tables(), gimple_cond_make_false(), gimple_cond_make_true(), gimple_duplicate_loop_body_to_header_edge(), gsi_last_bb(), loop::header, initialize_original_copy_tables(), profile_count::initialized_p(), loop::inner, wi::leu_p(), loop_edge_to_cancel(), loop_preheader_edge(), loops_to_unloop, loops_to_unloop_nunroll, MSG_OPTIMIZED_LOCATIONS, loop_size::non_call_stmts_on_hot_path, NULL, loop::num, loop_size::num_branches_on_hot_path, loop_size::num_non_pure_calls_on_hot_path, loop_size::num_pure_calls_on_hot_path, loop_size::overall, scale_loop_profile(), TDF_DETAILS, profile_count::to_gcov_type(), wi::to_widest(), TREE_CODE, tree_estimate_loop_size(), tree_fits_uhwi_p(), tree_to_uhwi(), ul, UL_NO_GROWTH, UL_SINGLE_ITER, loop::unroll, and update_stmt().
Referenced by canonicalize_loop_induction_variables().
void unloop_loops | ( | vec< class loop * > & | loops_to_unloop, |
vec< int > & | loops_to_unloop_nunroll, | ||
vec< edge > & | edges_to_remove, | ||
bitmap | loop_closed_ssa_invalidated, | ||
bool * | irred_invalidated ) |
Cancel all fully unrolled loops by putting __builtin_unreachable on the latch edge. We do it after all unrolling since unlooping moves basic blocks across loop boundaries trashing loop closed SSA form as well as SCEV info needed to be intact during unrolling. IRRED_INVALIDATED is used to bookkeep if information about irreducible regions may become invalid as a result of the transformation. LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case when we need to go into loop closed SSA form.
References add_bb_to_loop(), BASIC_BLOCK_FOR_FN, CDI_DOMINATORS, cfun, create_basic_block(), current_loops, edges_to_remove, FOR_EACH_VEC_ELT, gcc_assert, gimple_build_builtin_unreachable(), gsi_insert_after(), GSI_NEW_STMT, gsi_start_bb(), i, loop::latch, loop_latch_edge(), loops_to_unloop, loops_to_unloop_nunroll, make_edge(), profile_probability::never(), NULL, remove_exits_and_undefined_stmts(), remove_path(), set_immediate_dominator(), unloop(), and profile_count::zero().
Referenced by canonicalize_induction_variables(), and tree_unroll_loops_completely().
Stores loops that will be unlooped and edges that will be removed after we process whole loop tree.
Referenced by canonicalize_induction_variables(), tree_unroll_loops_completely(), try_unroll_loop_completely(), and unloop_loops().
|
static |
|
static |
Stores loops that has been peeled.
Referenced by try_peel_loop().