GCC Middle and Back End API Reference
|
Data Structures | |
struct | iv_to_split |
struct | var_to_expand |
struct | iv_split_hasher |
struct | var_expand_hasher |
struct | opt_info |
|
static |
Allocate basic variable for the induction variable chain.
References iv_to_split::base_var, gen_reg_rtx(), get_ivts_expr(), and iv_to_split::insn.
Referenced by apply_opt_in_copies().
|
staticread |
Referenced by analyze_insns_in_loop().
|
staticread |
Determine whether INSN contains an accumulator which can be expanded into separate copies, one for each copy of the LOOP body. for (i = 0 ; i < n; i++) sum += a[i]; ==> sum += a[i] .... i = i+1; sum1 += a[i] .... i = i+1 sum2 += a[i]; .... Return NULL if INSN contains no opportunity for expansion of accumulator. Otherwise, allocate a VAR_TO_EXPAND structure, fill it with the relevant information and return a pointer to it.
References copy_rtx(), dump_file, var_to_expand::expansion_count, have_insn_for(), var_to_expand::insn, var_to_expand::next, var_to_expand::op, print_rtl(), referenced_in_one_insn_in_loop_p(), var_to_expand::reg, reset_debug_uses_in_loop(), var_to_expand::reuse_expansion, rtx_equal_p(), rtx_referenced_p(), and var_to_expand::var_expansions.
|
staticread |
Determines which of insns in LOOP can be optimized. Return a OPT_INFO struct with the relevant hash tables filled with all insns to be optimized. The FIRST_NEW_BLOCK field is undefined for the return value.
References analyze_insn_to_expand_var(), analyze_iv_to_split_insn(), CDI_DOMINATORS, hash_table< Descriptor, Allocator >::create(), dominated_by_p(), hash_table< Descriptor, Allocator >::find_slot(), edge_def::flags, free(), get_loop_body(), get_loop_exit_edges(), opt_info::insns_to_split, opt_info::insns_with_var_to_expand, hash_table< Descriptor, Allocator >::is_created(), iv_analysis_loop_init(), opt_info::iv_to_split_head, opt_info::iv_to_split_tail, loop::latch, opt_info::loop_exit, opt_info::loop_preheader, loop_preheader_edge(), iv_to_split::next, var_to_expand::next, loop::num_nodes, split_edge(), edge_def::src, opt_info::var_to_expand_head, and opt_info::var_to_expand_tail.
|
staticread |
Referenced by analyze_insns_in_loop().
|
staticread |
Determine whether there is an induction variable in INSN that we would like to split during unrolling. I.e. replace i = i + 1; ... i = i + 1; ... i = i + 1; ... type chains by i0 = i + 1 ... i = i0 + 1 ... i = i0 + 2 ... Return NULL if INSN contains no interesting IVs. Otherwise, allocate an IV_TO_SPLIT structure, fill it with the relevant information and return a pointer to it.
References iv_to_split::base_var, biv_p(), rtx_iv::extend_mode, iv_to_split::insn, iv_analyze_result(), iv_to_split::loc, rtx_iv::mode, iv_to_split::n_loc, iv_to_split::next, iv_to_split::orig_var, iv_to_split::step, and rtx_iv::step.
|
static |
Apply loop optimizations in loop copies using the data which gathered during the unrolling. Structure OPT_INFO record that data. UNROLLING is true if we unrolled (not peeled) the loop. REWRITE_ORIGINAL_BODY is true if we should also rewrite the original body of the loop (as it should happen in complete unrolling, but not in ordinary peeling of the loop).
References allocate_basic_variable(), basic_block_def::aux, combine_var_copies_in_loop_exit(), determine_split_iv_delta(), expand_var_during_unrolling(), hash_table< Descriptor, Allocator >::find(), opt_info::first_new_block, get_bb_copy(), get_bb_original(), insert_base_initialization(), insert_var_expansion_initialization(), iv_to_split::insn, var_to_expand::insn, opt_info::insns_to_split, opt_info::insns_with_var_to_expand, hash_table< Descriptor, Allocator >::is_created(), opt_info::iv_to_split_head, opt_info::loop_exit, opt_info::loop_preheader, maybe_strip_eq_note_for_split_iv(), iv_to_split::next, var_to_expand::next, split_iv(), and opt_info::var_to_expand_head.
Referenced by peel_loop_completely(), peel_loop_simple(), unroll_loop_constant_iterations(), unroll_loop_runtime_iterations(), and unroll_loop_stupid().
|
static |
Referenced by apply_opt_in_copies().
|
static |
Combine the variable expansions at the loop exit. PLACE is the loop exit basic block where the summation of the expansions should take place.
References emit_insn_after(), emit_move_insn(), end_sequence(), force_operand(), get_insns(), var_to_expand::insn, var_to_expand::op, var_to_expand::reg, simplify_gen_binary(), start_sequence(), and var_to_expand::var_expansions.
|
static |
Referenced by peel_loops_completely().
|
static |
Decide whether the LOOP is suitable for complete peeling.
References niter_desc::assumptions, can_duplicate_loop_p(), niter_desc::const_iter, lpt_decision::decision, dump_file, get_simple_loop_desc(), HOST_WIDEST_INT_PRINT_DEC, niter_desc::infinite, loop::inner, loop::lpt_decision, LPT_PEEL_COMPLETELY, loop::ninsns, niter_desc::niter, optimize_loop_for_size_p(), and niter_desc::simple_p.
|
static |
Referenced by peel_loops_completely().
|
static |
Decide whether the LOOP is once rolling and suitable for complete peeling.
References niter_desc::assumptions, niter_desc::const_iter, lpt_decision::decision, dump_file, get_simple_loop_desc(), niter_desc::infinite, loop::lpt_decision, LPT_PEEL_COMPLETELY, max_loop_iterations_int(), loop::ninsns, niter_desc::niter, and niter_desc::simple_p.
|
static |
Referenced by decide_unrolling_and_peeling().
|
static |
Decide whether to simply peel LOOP and how much.
References lpt_decision::decision, dump_file, estimated_loop_iterations(), double_int::from_shwi(), HOST_WIDEST_INT, HOST_WIDEST_INT_PRINT_DEC, loop::lpt_decision, LPT_PEEL_SIMPLE, max_loop_iterations(), loop::ninsns, num_loop_branches(), PROFILE_READ, lpt_decision::times, double_int::to_shwi(), UAP_PEEL, and double_int::ult().
|
static |
Referenced by decide_unrolling_and_peeling().
|
static |
Decide whether to unroll LOOP iterating constant number of times and how much.
References niter_desc::assumptions, loop::av_ninsns, niter_desc::const_iter, lpt_decision::decision, dump_file, estimated_loop_iterations(), double_int::from_shwi(), get_simple_loop_desc(), loop_exit_at_end_p(), loop::lpt_decision, LPT_UNROLL_CONSTANT, max_loop_iterations(), loop::ninsns, niter_desc::niter, niter_desc::noloop_assumptions, niter_desc::simple_p, lpt_decision::times, UAP_UNROLL, and double_int::ult().
|
static |
Referenced by decide_unrolling_and_peeling().
|
static |
Decide whether to unroll LOOP iterating runtime computable number of times and how much.
References niter_desc::assumptions, loop::av_ninsns, niter_desc::const_iter, lpt_decision::decision, dump_file, estimated_loop_iterations(), double_int::from_shwi(), get_simple_loop_desc(), loop::lpt_decision, LPT_UNROLL_RUNTIME, max_loop_iterations(), loop::ninsns, niter_desc::simple_p, targetm, lpt_decision::times, UAP_UNROLL, and double_int::ult().
|
static |
Referenced by decide_unrolling_and_peeling().
|
static |
Decide whether to unroll LOOP stupidly and how much.
References niter_desc::assumptions, loop::av_ninsns, lpt_decision::decision, dump_file, estimated_loop_iterations(), double_int::from_shwi(), get_simple_loop_desc(), loop::lpt_decision, LPT_UNROLL_STUPID, max_loop_iterations(), loop::ninsns, num_loop_branches(), niter_desc::simple_p, targetm, lpt_decision::times, UAP_UNROLL_ALL, and double_int::ult().
|
static |
Referenced by unroll_and_peel_loops().
|
static |
Decide whether unroll or peel loops (depending on FLAGS) and how much.
References loop::av_ninsns, average_num_loop_insns(), can_duplicate_loop_p(), decide_peel_simple(), decide_unroll_constant_iterations(), decide_unroll_runtime_iterations(), decide_unroll_stupid(), lpt_decision::decision, dump_enabled_p(), dump_file, dump_printf_loc(), get_loop_location(), loop::header, basic_block_def::index, loop::inner, LI_FROM_INNERMOST, loop::lpt_decision, LPT_NONE, loop::ninsns, loop::num, num_loop_insns(), optimize_loop_for_size_p(), and report_unroll_peel().
|
static |
Determine the number of iterations between initialization of the base variable and the current copy (N_COPY). N_COPIES is the total number of newly created copies. UNROLLING is true if we are unrolling (not peeling) the loop.
Referenced by apply_opt_in_copies().
|
static |
Referenced by apply_opt_in_copies().
|
static |
Given INSN replace the uses of the accumulator recorded in VE with a new register.
References apply_change_group(), var_to_expand::expansion_count, gen_reg_rtx(), get_expansion(), var_to_expand::reg, validate_replace_rtx_group(), and var_to_expand::var_expansions.
|
static |
|
static |
|
static |
Referenced by expand_var_during_unrolling().
|
static |
Return one expansion of the accumulator recorded in struct VE.
References var_to_expand::reg, var_to_expand::reuse_expansion, and var_to_expand::var_expansions.
|
static |
Locate in EXPR the expression corresponding to the location recorded in IVTS, and return a pointer to the RTX for this location.
References iv_to_split::loc, and iv_to_split::n_loc.
Referenced by allocate_basic_variable(), insert_base_initialization(), and split_iv().
|
static |
Insert initialization of basic variable of IVTS before INSN, taking the initial value from INSN.
References iv_to_split::base_var, copy_rtx(), emit_insn_before(), emit_move_insn(), end_sequence(), force_operand(), get_insns(), get_ivts_expr(), and start_sequence().
Referenced by apply_opt_in_copies().
|
static |
Initialize the variable expansions in loop preheader. PLACE is the loop-preheader basic block where the initialization of the expansions should take place. The expansions are initialized with (-0) when the operation is plus or minus to honor sign zero. This way we can prevent cases where the sign of the final result is effected by the sign of the expansion. Here is an example to demonstrate this: for (i = 0 ; i < n; i++) sum += something; ==> sum += something .... i = i+1; sum1 += something .... i = i+1 sum2 += something; .... When SUM is initialized with -zero and SOMETHING is also -zero; the final result of sum should be -zero thus the expansions sum1 and sum2 should be initialized with -zero as well (otherwise we will get +zero as the final result).
References emit_insn_after(), emit_move_insn(), end_sequence(), get_insns(), var_to_expand::op, var_to_expand::reg, simplify_gen_unary(), start_sequence(), and var_to_expand::var_expansions.
Referenced by apply_opt_in_copies().
|
static |
Check whether exit of the LOOP is at the end of loop body.
References edge_def::dest, get_simple_loop_desc(), niter_desc::in_edge, and loop::latch.
Referenced by decide_unroll_constant_iterations(), unroll_loop_constant_iterations(), and unroll_loop_runtime_iterations().
|
static |
Strip away REG_EQUAL notes for IVs we're splitting. Updating REG_EQUAL notes for IVs we split is tricky: We cannot tell until after unrolling, DF-rescanning, and liveness updating, whether an EQ_USE is reached by the split IV while the IV reg is still live. See PR55006. ??? We cannot use remove_reg_equal_equiv_notes_for_regno, because RTL loop-iv requires us to defer rescanning insns and any notes attached to them. So resort to old techniques...
References find_reg_equal_equiv_note(), opt_info::iv_to_split_head, iv_to_split::next, iv_to_split::orig_var, reg_mentioned_p(), and remove_note().
Referenced by apply_opt_in_copies().
|
static |
|
static |
Called just before loop duplication. Records start of duplicated area to OPT_INFO.
References opt_info::first_new_block.
|
static |
Referenced by peel_loops_completely().
|
static |
Peel all iterations of LOOP, remove exit edges and cancel the loop completely. The transformation done: for (i = 0; i < 4; i++) body; ==> i = 0; body; i++; body; i++; body; i++; body; i++;
References analyze_insns_in_loop(), apply_opt_in_copies(), bitmap_clear_bit(), bitmap_ones(), dump_file, duplicate_loop_to_header_edge(), free(), free_opt_info(), free_simple_loop_desc(), get_simple_loop_desc(), HOST_WIDE_INT, niter_desc::in_edge, loop_preheader_edge(), niter_desc::niter, niter_desc::noloop_assumptions, opt_info_start_duplication(), niter_desc::out_edge, remove_path(), and sbitmap_alloc().
|
static |
Referenced by unroll_and_peel_loops().
|
static |
Peel a LOOP LOOP->LPT_DECISION.TIMES times. The transformation does this: while (cond) body; ==> (LOOP->LPT_DECISION.TIMES == 3) if (!cond) goto end; body; if (!cond) goto end; body; if (!cond) goto end; body; while (cond) body; end: ;
References analyze_insns_in_loop(), apply_opt_in_copies(), bitmap_clear(), niter_desc::const_iter, dump_file, duplicate_loop_to_header_edge(), free(), free_opt_info(), free_simple_loop_desc(), get_simple_loop_desc(), loop_preheader_edge(), loop::lpt_decision, niter_desc::niter, niter_desc::niter_expr, niter_desc::noloop_assumptions, opt_info_start_duplication(), sbitmap_alloc(), niter_desc::simple_p, and lpt_decision::times.
|
static |
Referenced by unroll_and_peel_loops().
|
static |
Depending on FLAGS, check whether to peel loops completely and do so.
References calculate_dominance_info(), CDI_DOMINATORS, changed, decide_peel_completely(), decide_peel_once_rolling(), lpt_decision::decision, dump_enabled_p(), dump_printf_loc(), fix_loop_structure(), get_loop_location(), loop::header, basic_block_def::index, LI_FROM_INNERMOST, loop::lpt_decision, LPT_NONE, LPT_PEEL_COMPLETELY, loop::ninsns, loop::num, num_loop_insns(), peel_loop_completely(), and report_unroll_peel().
Returns true if REG is referenced in one nondebug insn in LOOP. Set *DEBUG_USES to the number of debug insns that reference the variable.
References free(), get_loop_body(), loop::num_nodes, and rtx_referenced_p().
Referenced by analyze_insn_to_expand_var().
|
static |
Emit a message summarizing the unroll or peel that will be performed for LOOP, along with the loop's location LOCUS, if appropriate given the dump or -fopt-info settings.
References niter_desc::const_iter, basic_block_def::count, lpt_decision::decision, dump_enabled_p(), dump_printf(), dump_printf_loc(), expected_loop_iterations(), get_simple_loop_desc(), loop::header, loop::lpt_decision, LPT_NONE, LPT_PEEL_COMPLETELY, LPT_PEEL_SIMPLE, niter_desc::niter, profile_info, and lpt_decision::times.
Referenced by decide_unrolling_and_peeling(), and peel_loops_completely().
|
static |
Reset the DEBUG_USES debug insns in LOOP that reference REG.
References free(), get_loop_body(), loop::num_nodes, rtx_referenced_p(), and validate_change().
Referenced by analyze_insn_to_expand_var().
basic_block split_edge_and_insert | ( | ) |
Splits edge E and inserts the sequence of instructions INSNS on it, and returns the newly created block. If INSNS is NULL_RTX, nothing is changed and NULL is returned instead.
References emit_insn_after(), and split_edge().
|
static |
Replace the use of induction variable described in IVTS in INSN by base variable + DELTA * step.
References iv_to_split::base_var, copy_rtx(), delete_insn(), emit_insn_before(), emit_move_insn(), end_sequence(), force_operand(), gen_int_mode(), gen_reg_rtx(), get_insns(), get_ivts_expr(), simplify_gen_binary(), start_sequence(), iv_to_split::step, and validate_change().
Referenced by apply_opt_in_copies().
void unroll_and_peel_loops | ( | ) |
Unroll and/or peel (depending on FLAGS) LOOPS.
References calculate_dominance_info(), CDI_DOMINATORS, changed, decide_unrolling_and_peeling(), lpt_decision::decision, fix_loop_structure(), iv_analysis_done(), LI_FROM_INNERMOST, loop::lpt_decision, LPT_NONE, LPT_PEEL_COMPLETELY, LPT_PEEL_SIMPLE, LPT_UNROLL_CONSTANT, LPT_UNROLL_RUNTIME, LPT_UNROLL_STUPID, peel_loop_simple(), peel_loops_completely(), unroll_loop_constant_iterations(), unroll_loop_runtime_iterations(), and unroll_loop_stupid().
|
static |
Referenced by unroll_and_peel_loops().
|
static |
Unroll LOOP with constant number of iterations LOOP->LPT_DECISION.TIMES times. The transformation does this: for (i = 0; i < 102; i++) body; ==> (LOOP->LPT_DECISION.TIMES == 3) i = 0; body; i++; body; i++; while (i < 102) { body; i++; body; i++; body; i++; body; i++; }
References analyze_insns_in_loop(), loop::any_estimate, apply_opt_in_copies(), bitmap_clear_bit(), bitmap_ones(), bitmap_set_bit(), edge_def::dest, dump_file, duplicate_loop_to_header_edge(), free(), free_opt_info(), double_int::from_uhwi(), get_bb_copy(), get_simple_loop_desc(), HOST_WIDE_INT, niter_desc::in_edge, loop_exit_at_end_p(), loop_latch_edge(), loop_preheader_edge(), loop::lpt_decision, loop::nb_iterations_estimate, loop::nb_iterations_upper_bound, niter_desc::niter, niter_desc::niter_expr, niter_desc::noloop_assumptions, num_loop_insns(), opt_info_start_duplication(), niter_desc::out_edge, remove_path(), sbitmap_alloc(), edge_def::src, lpt_decision::times, double_int::udiv(), and double_int::ule().
|
static |
Referenced by unroll_and_peel_loops().
|
static |
Unroll LOOP for which we are able to count number of iterations in runtime LOOP->LPT_DECISION.TIMES times. The transformation does this (with some extra care for case n < 0): for (i = 0; i < n; i++) body; ==> (LOOP->LPT_DECISION.TIMES == 3) i = 0; mod = n % 4; switch (mod) { case 3: body; i++; case 2: body; i++; case 1: body; i++; case 0: ; } while (i < n) { body; i++; body; i++; body; i++; body; i++; }
References analyze_insns_in_loop(), loop::any_estimate, apply_opt_in_copies(), bitmap_clear(), bitmap_clear_bit(), bitmap_ones(), bitmap_set_bit(), block_label(), CDI_DOMINATORS, compare_and_jump_seq(), niter_desc::const_iter, copy_rtx(), edge_def::count, basic_block_def::count, edge_def::dest, dump_file, duplicate_loop_to_header_edge(), emit_move_insn(), end_sequence(), expand_simple_binop(), flow_bb_inside_loop_p(), force_operand(), free(), free_opt_info(), double_int::from_uhwi(), gen_reg_rtx(), get_bb_copy(), get_dominated_by(), get_insns(), get_loop_body(), get_simple_loop_desc(), niter_desc::in_edge, iterate_fix_dominators(), loop_exit_at_end_p(), loop_latch_edge(), loop_preheader_edge(), loop::lpt_decision, make_edge(), niter_desc::mode, loop::nb_iterations_estimate, loop::nb_iterations_upper_bound, niter_desc::niter, niter_desc::niter_expr, niter_desc::noloop_assumptions, num_loop_insns(), loop::num_nodes, opt_info_start_duplication(), OPTAB_LIB_WIDEN, niter_desc::out_edge, edge_def::probability, remove_path(), sbitmap_alloc(), set_immediate_dominator(), simplify_gen_binary(), single_pred_edge(), single_succ_edge(), split_edge(), split_edge_and_insert(), edge_def::src, start_sequence(), lpt_decision::times, double_int::udiv(), and unshare_all_rtl_in_chain().
|
static |
Referenced by unroll_and_peel_loops().
|
static |
Unroll a LOOP LOOP->LPT_DECISION.TIMES times. The transformation does this: while (cond) body; ==> (LOOP->LPT_DECISION.TIMES == 3) while (cond) { body; if (!cond) break; body; if (!cond) break; body; if (!cond) break; body; }
References analyze_insns_in_loop(), apply_opt_in_copies(), bitmap_clear(), dump_file, duplicate_loop_to_header_edge(), free(), free_opt_info(), get_simple_loop_desc(), loop_latch_edge(), loop::lpt_decision, num_loop_insns(), opt_info_start_duplication(), sbitmap_alloc(), niter_desc::simple_p, and lpt_decision::times.