|
GCC Middle and Back End API Reference
|
#include "config.h"#include "system.h"#include "coretypes.h"#include "backend.h"#include "insn-codes.h"#include "rtl.h"#include "tree.h"#include "gimple.h"#include "cfghooks.h"#include "tree-pass.h"#include "ssa.h"#include "tree-ssa.h"#include "optabs-tree.h"#include "insn-config.h"#include "gimple-pretty-print.h"#include "fold-const.h"#include "stor-layout.h"#include "cfganal.h"#include "gimple-iterator.h"#include "tree-cfg.h"#include "tree-dfa.h"#include "domwalk.h"#include "cfgloop.h"#include "tree-data-ref.h"#include "tree-scalar-evolution.h"#include "tree-inline.h"#include "case-cfn-macros.h"#include "tree-eh.h"#include "gimple-fold.h"#include "internal-fn.h"#include "gimple-range.h"#include "gimple-match.h"#include "dbgcnt.h"#include "tree-ssa-propagate.h"#include "tree-ssa-dce.h"#include "tree-ssa-loop-niter.h"#include "gimple-predict.h"#include "alias.h"#include "tree-ssa-threadedge.h"
Data Structures | |
| class | auto_flow_sensitive |
| struct | ref_to_bb |
| struct | refs_hasher |
| class | nontrapping_dom_walker |
Variables | |
| static unsigned int | nt_call_phase |
Returns true if ARG is an absorbing element for operation CODE.
References absorbing_element_p(), integer_all_onesp(), integer_zerop(), and tree_single_nonzero_p().
Referenced by absorbing_element_p(), and value_replacement().
|
static |
The function comparison_combine tries to handle cases like: if (a CMP0 b) d = a CMP1 b; PHI<d, [0,1]> This has to be seperately as `a CMP1 b` might be trapping and match_simplify_replacement does not handle trapping statements. Returns true if a replacement happens.
References as_a(), boolean_type_node, combine_comparisons(), comparison_combine(), EDGE_SUCC, empty_block_p(), extract_true_false_edges_from_block(), FLOAT_TYPE_P, gcc_assert, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_build(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), GSI_CONTINUE_LINKING, gsi_insert_seq_before(), gsi_last_bb(), HONOR_NANS(), integer_onep(), integer_zerop(), invert_tree_comparison(), last_nondebug_stmt(), one_feeding_comparison_into_p(), operand_equal_p(), replace_phi_edge_with_variable(), ssa_name_maybe_undef_p(), TREE_CODE, TREE_TYPE, and types_compatible_p().
Referenced by comparison_combine().
|
static |
Conditional store replacement. We already know that the recognized pattern looks like so: split: if (cond) goto THEN_BB; else goto ELSE_BB (edge E1) THEN_BB: ... X = Y; ... goto JOIN_BB; ELSE_BB: ... X = Z; ... fallthrough (edge E0) JOIN_BB: some more We check that it is safe to sink the store to JOIN_BB by verifying that there are no read-after-write or write-after-write dependencies in THEN_BB and ELSE_BB.
References chrec_dont_know, chrec_known, compute_all_dependences(), cond_if_else_store_replacement(), cond_if_else_store_replacement_1(), cond_if_else_store_replacement_limited(), DDR_A, DDR_ARE_DEPENDENT, DDR_B, DR_IS_READ, DR_IS_WRITE, DR_STMT, find_data_references_in_bb(), FOR_EACH_VEC_ELT_REVERSE, free_data_refs(), free_dependence_relations(), get_virtual_phi(), gimple_get_lhs(), gimple_set_visited(), gimple_uid(), gimple_visited_p(), i, NULL, NULL_TREE, operand_equal_p(), renumber_gimple_stmt_uids_in_blocks(), and vNULL.
Referenced by cond_if_else_store_replacement().
|
static |
Do the main work of conditional store replacement.
References add_phi_arg(), cfun, CLOBBER_KIND, cond_if_else_store_replacement_1(), create_phi_node(), DECL_P, dump_file, dump_flags, EDGE_SUCC, get_base_address(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_build_assign(), gimple_clobber_p(), gimple_has_volatile_ops(), gimple_location(), gimple_phi_result(), gimple_phi_set_result(), gimple_set_vdef(), gimple_set_vuse(), gimple_vop(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), GSI_NEW_STMT, gsi_remove(), is_gimple_reg_type(), make_ssa_name(), make_temp_ssa_name(), NULL, NULL_TREE, operand_equal_p(), print_gimple_stmt(), release_defs(), SSA_NAME_DEF_STMT, statistics_counter_event(), stmt_references_abnormal_ssa_name(), TDF_DETAILS, TDF_MEMSYMS, TDF_VOPS, TREE_CLOBBER_P, TREE_CODE, TREE_TYPE, unlink_stmt_vdef(), and update_stmt().
Referenced by cond_if_else_store_replacement(), cond_if_else_store_replacement_1(), and cond_if_else_store_replacement_limited().
|
static |
Limited Conditional store replacement. We already know that the recognized pattern looks like so: split: if (cond) goto THEN_BB; else goto ELSE_BB (edge E1) THEN_BB: ... STORE = Y; ... goto JOIN_BB; ELSE_BB: ... STORE = Z; ... fallthrough (edge E0) JOIN_BB: some more Handles only the case with store in THEN_BB and ELSE_BB. That is cheap enough due to in phiopt and not worry about heurstics. Moving the store out might provide an opportunity for a phiopt to happen. At -O1 (!flag_expensive_optimizations), this only handles the only store in the BBs.
References cond_if_else_store_replacement_1(), cond_if_else_store_replacement_limited(), get_virtual_phi(), PHI_ARG_DEF_FROM_EDGE, single_succ_edge(), and trailing_store_in_bb().
Referenced by cond_if_else_store_replacement(), cond_if_else_store_replacement_limited(), and factor_out_all().
|
static |
Optimize x ? __builtin_fun (x) : C, where C is __builtin_fun (0). Convert <bb 2> if (b_4(D) != 0) goto <bb 3> else goto <bb 4> <bb 3> _2 = (unsigned long) b_4(D); _9 = __builtin_popcountl (_2); OR _9 = __builtin_popcountl (b_4(D)); <bb 4> c_12 = PHI <0(2), _9(3)> Into <bb 2> _2 = (unsigned long) b_4(D); _9 = __builtin_popcountl (_2); OR _9 = __builtin_popcountl (b_4(D)); <bb 4> c_12 = PHI <_9(2)> Similarly for __builtin_clz or __builtin_ctz if C?Z_DEFINED_VALUE_AT_ZERO is 2, optab is present and instead of 0 above it uses the value from that macro.
References BITINT_TYPE_P, build_int_cst(), CLZ_DEFINED_VALUE_AT_ZERO, cond_removal_in_builtin_zero_pattern(), CONVERT_EXPR_CODE_P, CTZ_DEFINED_VALUE_AT_ZERO, direct_internal_fn_supported_p(), dyn_cast(), EDGE_SUCC, extract_true_false_edges_from_block(), gcc_assert, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_build_call_internal(), gimple_call_arg(), gimple_call_combined_fn(), gimple_call_internal_p(), gimple_call_num_args(), gimple_call_set_lhs(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_get_lhs(), gsi_end_p(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_move_before(), gsi_next_nondebug(), gsi_remove(), GSI_SAME_STMT, gsi_start_nondebug_after_labels_bb(), gsi_stmt(), integer_type_node, integer_zerop(), INTEGRAL_TYPE_P, is_gimple_call(), long_integer_type_node, long_long_integer_type_node, NULL, NULL_TREE, OPTIMIZE_FOR_BOTH, replace_phi_edge_with_variable(), reset_flow_sensitive_info(), SCALAR_INT_TYPE_MODE, wi::to_wide(), TREE_CODE, tree_fits_shwi_p(), tree_to_shwi(), TREE_TYPE, and TYPE_PRECISION.
Referenced by cond_removal_in_builtin_zero_pattern().
|
static |
Do the main work of conditional store replacement. We already know that the recognized pattern looks like so: split: if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1) MIDDLE_BB: something fallthrough (edge E0) JOIN_BB: some more ASSIGN is a store in MIDDLE_BB which is the candidate for cselim. We check that MIDDLE_BB contains only one store (i.e., ASSIGN), that that store doesn't trap (not via NOTRAP, but via checking if an access to the same memory location dominates us, or the store is to a local addressable object) and that the store has a "simple" RHS.
References add_phi_arg(), build2(), build_fold_addr_expr, build_zero_cst(), cfun, cond_store_replacement(), hash_set< KeyId, Lazy, Traits >::contains(), create_phi_node(), DECL_P, dump_file, dump_flags, fold_convert, FOR_EACH_IMM_USE_STMT, FOR_EACH_SSA_TREE_OPERAND, get_virtual_phi(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_bb(), gimple_build_assign(), gimple_has_volatile_ops(), gimple_location(), gimple_phi_arg_def(), gimple_phi_result(), gimple_phi_set_result(), gimple_set_location(), gimple_set_vdef(), gimple_set_vuse(), gimple_vop(), gimple_vuse(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), gsi_insert_on_edge(), GSI_NEW_STMT, gsi_remove(), handled_component_p(), is_gimple_reg_type(), lhs_could_trap_p(), make_ssa_name(), make_temp_ssa_name(), NULL, print_gimple_stmt(), ptr_type_node, ref_can_have_store_data_races(), REFERENCE_CLASS_P, release_defs(), SSA_NAME_DEF_STMT, SSA_OP_USE, statistics_counter_event(), suppress_warning(), TDF_DETAILS, TDF_MEMSYMS, TDF_VOPS, TREE_CODE, TREE_OPERAND, TREE_TYPE, unlink_stmt_vdef(), unshare_expr(), and update_stmt().
Referenced by cond_store_replacement().
|
static |
Do the main work of a limited conditional store replacement. This recognized pattern like so: COND_BB: store = a_1; // no loads if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1) MIDDLE_BB: something // no loads store = a_2; something // no loads fallthrough (edge E0) JOIN_BB: some more This is a limited form of the full cond_store_replacement to be allowed from use from phiopt and can be done without calculating the non-trapping cases.
References add_phi_arg(), auto_var_p(), cfun, cond_store_replacement_limited(), copy_mem_with_alias_set_zero(), create_phi_node(), DECL_P, dump_file, dump_flags, EDGE_COUNT, FOR_EACH_IMM_USE_STMT, gcc_assert, get_base_address(), get_virtual_phi(), gimple_assign_lhs(), gimple_assign_load_p(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_bb(), gimple_build_assign(), gimple_clobber_p(), gimple_has_volatile_ops(), gimple_location(), gimple_phi_arg_def(), gimple_phi_arg_def_from_edge(), gimple_phi_result(), gimple_phi_set_result(), gimple_set_location(), gimple_set_vdef(), gimple_set_vuse(), gimple_vop(), gimple_vuse(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), gsi_insert_on_edge(), gsi_remove(), GSI_SAME_STMT, is_gimple_reg_type(), lhs_could_trap_p(), make_ssa_name(), make_temp_ssa_name(), NULL, operand_equal_p(), basic_block_def::preds, print_gimple_stmt(), ref_can_have_store_data_races(), REFERENCE_CLASS_P, release_defs(), single_pred_p(), SSA_NAME_DEF_STMT, statistics_counter_event(), suppress_warning(), TDF_DETAILS, TDF_MEMSYMS, TDF_VOPS, trailing_store_in_bb(), TREE_ADDRESSABLE, TREE_TYPE, unlink_stmt_vdef(), unshare_expr(), and update_stmt().
Referenced by cond_store_replacement_limited(), and factor_out_all().
|
static |
Returns true if BB contains an user provided predictor (PRED_HOT_LABEL/PRED_COLD_LABEL).
References contains_hot_cold_predict(), gimple_predict_predictor(), gsi_end_p(), gsi_next_nondebug(), gsi_start_nondebug_after_labels_bb(), and gsi_stmt().
Referenced by contains_hot_cold_predict(), and match_simplify_replacement().
Takes a MEM and changes the aliasing set to be zero on it. This handles all variants include decls.
References build2(), build_fold_addr_expr, build_zero_cst(), copy_mem_with_alias_set_zero(), fold_convert, handled_component_p(), ptr_type_node, TREE_CODE, TREE_OPERAND, TREE_TYPE, and unshare_expr().
Referenced by cond_store_replacement_limited(), and copy_mem_with_alias_set_zero().
|
static |
Return the only store in MIDDLE_BB as the candidate store for cselim. Return NULL if no candidate can be found.
References cselim_candidate(), get_virtual_phi(), NULL, PHI_ARG_DEF_FROM_EDGE, and trailing_store_in_bb().
Referenced by cselim_candidate().
|
static |
empty_bb_or_one_feeding_into_p returns true if bb was empty basic block or it has one cheap preparation statement that feeds into the PHI statement and it sets STMT to that statement.
References empty_bb_or_one_feeding_into_p(), empty_block_p(), FOR_EACH_SSA_TREE_OPERAND, gimple_assign_lhs(), gimple_call_combined_fn(), gimple_call_lhs(), gimple_could_trap_p(), gimple_has_side_effects(), gimple_seq_empty_p(), gimple_vuse(), gsi_end_p(), gsi_next_nondebug(), gsi_start_nondebug_after_labels_bb(), gsi_stmt(), is_gimple_assign(), is_gimple_call(), phi_nodes(), single_imm_use(), single_pred_p(), ssa_name_maybe_undef_p(), SSA_OP_USE, and TREE_CODE.
Referenced by empty_bb_or_one_feeding_into_p(), and match_simplify_replacement().
|
static |
References cfun, EDGE_COUNT, EDGE_SUCC, execute_over_cond_phis(), free(), gsi_last_bb(), i, n_basic_blocks_for_fn, NUM_FIXED_BLOCKS, safe_dyn_cast(), single_pred_before_succ_order(), single_succ_p(), and basic_block_def::succs.
Referenced by execute_over_cond_phis().
|
static |
Factor out operations and stores from the phi of the MERGE block coming in from the edges E1 and E2 if possible. COND_STMT is the conditional statement of the origin block. DIAMOND_P says that both E1 and E2 src are not the origin block but rather 2 middle BBs. EARLY_P is true if this was the early phi-opt. Returns true if a factoring happened.
References cond_if_else_store_replacement_limited(), cond_store_replacement_limited(), factor_out_all(), factor_out_conditional_load(), factor_out_conditional_operation(), fold_before_rtl_expansion_p(), loop::force_vectorize, get_virtual_phi(), gsi_end_p(), gsi_next(), gsi_start_phis(), basic_block_def::loop_father, and single_pred_p().
Referenced by factor_out_all().
|
static |
If PHI at MERGE is a "load PHI", PHI <*P, *Q> whose two arguments are single-use, non-volatile scalar MEM_REF loads reading the same memory state (same VUSE), factor the load out: introduce P' = PHI <P, Q> and a single load *P' replacing the PHI. No speculative load is introduced (the load uses whichever pointer the taken edge selected). E0/E1 are the middle bbs to MERGE edges. EARLY_P is set when the first phiopt is run. BEFORE_VECT is true if this is before vectorization, where some extra checks are needed for profitability. Returns true if a load was factored out.
References add_phi_arg(), alias_ptr_types_compatible_p(), bb_loop_depth(), build2(), build5(), build_zero_cst(), cfun, create_phi_node(), dump_file, dump_flags, factor_out_conditional_load(), fold_convert, get_virtual_phi(), gimple_assign_load_p(), gimple_assign_rhs1(), gimple_bb(), gimple_build(), gimple_build_assign(), gimple_has_volatile_ops(), gimple_location(), gimple_phi_arg_def(), gimple_phi_arg_location(), gimple_phi_num_args(), gimple_phi_result(), gimple_set_vuse(), gimple_vuse(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), gsi_remove(), GSI_SAME_STMT, has_single_use(), induction_based(), is_factor_profitable(), make_ssa_name(), MR_DEPENDENCE_BASE, MR_DEPENDENCE_CLIQUE, operand_equal_p(), print_generic_expr(), ptr_type_node, REF_REVERSE_STORAGE_ORDER, release_defs(), remove_phi_node(), safe_operand_equal_p(), sizetype, SSA_NAME_DEF_STMT, statistics_counter_event(), TDF_DETAILS, TMR_INDEX, TMR_INDEX2, TMR_STEP, TREE_CODE, TREE_OPERAND, TREE_TYPE, TYPE_ALIGN, types_compatible_p(), UNKNOWN_LOCATION, and virtual_operand_p().
Referenced by factor_out_all(), and factor_out_conditional_load().
|
static |
PR66726: Factor operations out of COND_EXPR. If the arguments of the PHI stmt are Unary operator, factor out the operation and perform the operation to the result of PHI stmt. COND_STMT is the controlling predicate. Return true if the operation was factored out; false otherwise.
References add_phi_arg(), annotate_all_with_location(), cfun, gimple_match_op::code, create_phi_node(), drop_tree_overflow(), dump_file, dump_flags, dyn_cast(), factor_operation_ok(), factor_out_conditional_operation(), find_different_opnum(), fold_convert, gcc_assert, gimple_assign_cast_p(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_bb(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_extract_op(), gimple_has_location(), gimple_location(), gimple_phi_arg_def(), gimple_phi_arg_location(), gimple_phi_num_args(), gimple_phi_result(), gsi_after_labels(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_for_stmt(), gsi_insert_seq_before(), gsi_prev_nondebug(), gsi_remove(), gsi_stmt(), has_single_use(), int_fits_type_p(), INTEGRAL_TYPE_P, is_factor_profitable(), make_ssa_name(), maybe_push_res_to_seq(), NULL, NULL_TREE, gimple_match_op::num_ops, operand_equal_for_phi_arg_p(), gimple_match_op::operands_occurs_in_abnormal_phi(), gimple_match_op::ops, phi_nodes(), print_generic_expr(), release_defs(), release_ssa_name(), remove_phi_node(), single_non_singleton_phi_for_edges(), SSA_NAME_DEF_STMT, statistics_counter_event(), TDF_DETAILS, TREE_CODE, TREE_OVERFLOW, TREE_TYPE, TYPE_PRECISION, TYPE_UNSIGNED, UNKNOWN_LOCATION, and virtual_operand_p().
Referenced by factor_out_all(), and factor_out_conditional_operation().
|
static |
Determine whether we should attempt to hoist adjacent loads out of diamond patterns in pass_phiopt. Always hoist loads if -fhoist-adjacent-loads is specified and the target machine has both a conditional move instruction and a defined cache line size.
References gate_hoist_loads().
Referenced by gate_hoist_loads().
This is the entry point of gathering non trapping memory accesses. It will do a dominator walk over the whole function, and it will make use of the bb->aux pointers. It returns a set of trees (the MEM_REFs itself) which can't trap.
References CDI_DOMINATORS, cfun, clear_aux_for_blocks(), get_non_trapping(), nontrapping_dom_walker::nontrapping_dom_walker(), and nt_call_phase.
Referenced by get_non_trapping().
|
static |
gimple_simplify_phiopt is like gimple_simplify but designed for PHIOPT. Return NULL if nothing can be simplified or the resulting simplified value with parts pushed if EARLY_P was true. Also rejects non allowed tree code if EARLY_P is set. Takes the comparison from COMP_STMT and two args, ARG0 and ARG1 and tries to simplify CMP ? ARG0 : ARG1. Also try to simplify (!CMP) ? ARG1 : ARG0 if the non-inverse failed.
References annotate_all_with_location(), boolean_type_node, build2_loc(), dump_file, dump_flags, follow_all_ssa_edges(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_location(), gimple_seq_add_seq_without_update(), gimple_seq_discard(), gimple_simplify_phiopt(), HONOR_NANS(), invert_tree_comparison(), maybe_push_res_to_seq(), NULL, phiopt_early_allow(), print_generic_expr(), print_gimple_seq(), gimple_match_op::resimplify(), TDF_FOLDING, TDF_MEMSYMS, TDF_VOPS, gimple_match_cond::UNCOND, and UNKNOWN_LOCATION.
Referenced by gimple_simplify_phiopt(), and match_simplify_replacement().
|
static |
Given a "diamond" control-flow pattern where BB0 tests a condition, BB1 and BB2 are "then" and "else" blocks dependent on this test, and BB3 rejoins control flow following BB1 and BB2, look for opportunities to hoist loads as follows. If BB3 contains a PHI of two loads, one each occurring in BB1 and BB2, and the loads are provably of adjacent fields in the same structure, then move both loads into BB0. Of course this can only be done if there are no dependencies preventing such motion. One of the hoisted loads will always be speculative, so the transformation is currently conservative: - The fields must be strictly adjacent. - The two fields must occupy a single memory block that is guaranteed to not cross a page boundary. The last is difficult to prove, as such memory blocks should be aligned on the minimum of the stack alignment boundary and the alignment guaranteed by heap allocation interfaces. Thus we rely on a parameter for the alignment value. Provided a good value is used for the last case, the first restriction could possibly be relaxed.
References bit_position(), cfun, DECL_ALIGN, DECL_CHAIN, DECL_SIZE, dump_file, dump_flags, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_bb(), gimple_has_volatile_ops(), gimple_phi_arg_def(), gimple_phi_num_args(), gimple_phi_result(), gsi_end_p(), gsi_for_stmt(), gsi_move_to_bb_end(), gsi_next(), gsi_start_phis(), hoist_adjacent_loads(), basic_block_def::index, local_mem_dependence(), operand_equal_p(), optab_handler(), gphi_iterator::phi(), print_gimple_stmt(), reset_flow_sensitive_info(), SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, statistics_counter_event(), TDF_DETAILS, TDF_MEMSYMS, TDF_VOPS, TREE_CODE, tree_fits_uhwi_p(), TREE_OPERAND, tree_to_uhwi(), TREE_TYPE, TYPE_MODE, and virtual_operand_p().
Referenced by hoist_adjacent_loads().
|
static |
Returns true when P is based on an induction variable inside MERGE's inner most loop.
References analyze_scalar_evolution(), chrec_contains_symbols_defined_in_loop(), chrec_contains_undetermined(), induction_based(), basic_block_def::loop_father, loop::num, TREE_CODE, and tree_does_not_contain_chrecs().
Referenced by factor_out_conditional_load(), and induction_based().
|
static |
Returns true if the OPERANDS (OPCOUNTED) defined from DEF_STMT is profitable to move to the usage into the basic block MERGE where the new statement will be located.
References CDI_DOMINATORS, dominated_by_p(), FOR_EACH_IMM_USE_FAST, gimple_bb(), gsi_end_p(), gsi_for_stmt(), gsi_next_nondebug(), gsi_stmt(), i, is_factor_profitable(), is_gimple_debug(), is_gimple_min_invariant(), TREE_CODE, and USE_STMT.
Referenced by factor_out_conditional_load(), factor_out_conditional_operation(), and is_factor_profitable().
Update *ARG which is defined in STMT so that it contains the computed value if that seems profitable. Return true if the statement is made dead by that rewriting.
References get_addr_base_and_unit_offset(), gimple_assign_rhs1(), gimple_assign_rhs_code(), jump_function_from_stmt(), known_eq, mem_ref_offset(), TREE_CODE, and TREE_OPERAND.
Referenced by jump_function_from_stmt(), and value_replacement().
|
static |
Return TRUE if STMT has a VUSE whose corresponding VDEF is in BB.
References gimple_bb(), gimple_vuse(), local_mem_dependence(), SSA_NAME_DEF_STMT, and data_reference::stmt.
Referenced by hoist_adjacent_loads(), and local_mem_dependence().
| gimple_opt_pass * make_pass_cselim | ( | gcc::context * | ctxt | ) |
References make_pass_cselim().
Referenced by make_pass_cselim(), and make_pass_empty_loop().
| gimple_opt_pass * make_pass_phiopt | ( | gcc::context * | ctxt | ) |
References make_pass_phiopt().
Referenced by make_pass_empty_loop(), and make_pass_phiopt().
|
static |
The function match_simplify_replacement does the main work of doing the replacement using match and simplify. Return true if the replacement is done. Otherwise return false. BB is the basic block where the replacement is going to be done on. ARG0 is argument 0 from PHI. Likewise for ARG1.
References bitmap_set_bit, boolean_type_node, cfun, contains_hot_cold_predict(), dump_file, dump_flags, EDGE_SUCC, empty_bb_or_one_feeding_into_p(), extract_true_false_edges_from_block(), gcc_assert, gimple_assign_lhs(), gimple_assign_rhs_code(), gimple_build(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_phi_result(), gimple_seq_first_stmt(), gimple_seq_singleton_p(), gimple_simplify_phiopt(), GSI_CONTINUE_LINKING, gsi_insert_seq_before(), gsi_last_bb(), HONOR_NANS(), HONOR_SIGNED_ZEROS(), is_gimple_assign(), last_nondebug_stmt(), mark_lhs_in_seq_for_dce(), match_simplify_replacement(), move_stmt(), NULL, operand_equal_for_phi_arg_p(), replace_phi_edge_with_variable(), SSA_NAME_IS_DEFAULT_DEF, ssa_name_maybe_undef_p(), SSA_NAME_VERSION, statistics_counter_event(), tcc_comparison, TDF_FOLDING, TREE_CODE, TREE_CODE_CLASS, and TREE_TYPE.
Referenced by match_simplify_replacement().
|
static |
Move STMT to before GSI and insert its defining name into INSERTED_EXPRS bitmap. Also rewrite its if it might be undefined when unconditionalized.
References bitmap_set_bit, dump_file, dump_flags, gimple_get_lhs(), gimple_needing_rewrite_undefined(), gsi_for_stmt(), gsi_move_before(), GSI_NEW_STMT, move_stmt(), print_gimple_stmt(), reset_flow_sensitive_info(), rewrite_to_defined_unconditional(), SSA_NAME_VERSION, TDF_DETAILS, TDF_MEMSYMS, and TDF_VOPS.
Referenced by match_simplify_replacement(), and move_stmt().
Returns true if ARG is a neutral element for operation CODE on the RIGHT side.
References integer_all_onesp(), integer_onep(), integer_zerop(), and neutral_element_p().
Referenced by neutral_element_p(), and value_replacement().
|
static |
one_feeding_comparison_into_p returns true if BB has one comparison statement and it sets STMT to that statement. Note the comparison can be trapping too.
References a, cfun, dyn_cast(), empty_block_p(), gimple_assign_lhs(), gimple_assign_rhs_code(), gimple_seq_empty_p(), gimple_vuse(), gsi_end_p(), gsi_next_nondebug(), gsi_start_nondebug_after_labels_bb(), gsi_stmt(), one_feeding_comparison_into_p(), phi_nodes(), single_imm_use(), single_pred_p(), stmt_could_throw_p(), tcc_comparison, TREE_CODE, and TREE_CODE_CLASS.
Referenced by comparison_combine(), and one_feeding_comparison_into_p().
|
static |
Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND. Also return TRUE if arg0/arg1 are equal to the source arguments of an EQ comparison feeding a BIT_AND_EXPR, or NE comparison feeding a BIT_IOR_EXPR which feeds COND. Return FALSE otherwise.
References gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_cond_lhs(), gimple_cond_rhs(), integer_zerop(), is_gimple_assign(), operand_equal_for_phi_arg_p(), operand_equal_for_value_replacement(), rhs_is_fed_for_value_replacement(), SSA_NAME_DEF_STMT, and TREE_CODE.
Referenced by operand_equal_for_value_replacement(), and value_replacement().
|
static |
Return TRUE if SEQ/OP pair should be allowed during early phiopt. Currently this is to allow MIN/MAX and ABS/NEGATE and constants.
References gimple_match_op::code, gimple_assign_rhs_code(), gimple_seq_empty_p(), gimple_seq_first_stmt(), gimple_seq_singleton_p(), is_gimple_assign(), code_helper::is_tree_code(), and phiopt_early_allow().
Referenced by gimple_simplify_phiopt(), and phiopt_early_allow().
|
static |
Replace PHI node element whose edge is E in block BB with variable NEW. Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK is known to have two edges, one of which must reach BB).
References profile_probability::always(), loop::any_likely_upper_bound, loop::any_upper_bound, as_a(), cfun, copy_phi_arg_into_existing_phi(), dbg_cnt(), delete_basic_block(), dump_file, dump_flags, duplicate_ssa_name_range_info(), EDGE_COUNT, EDGE_SUCC, empty_block_p(), find_edge(), free_numbers_of_iterations_estimates(), gcc_assert, gcc_unreachable, gimple_bb(), gimple_cond_make_false(), gimple_cond_make_true(), gimple_phi_result(), gsi_last_bb(), gsi_remove(), basic_block_def::index, INTEGRAL_TYPE_P, loop_exits_from_bb_p(), basic_block_def::loop_father, NULL, PHI_ARG_DEF_PTR, redirect_edge_and_branch(), replace_phi_edge_with_variable(), SET_USE, simple_dce_from_worklist(), single_pred_p(), single_succ_p(), SSA_NAME_DEF_STMT, SSA_NAME_RANGE_INFO, statistics_counter_event(), TDF_DETAILS, TREE_CODE, and TREE_TYPE.
Referenced by comparison_combine(), cond_removal_in_builtin_zero_pattern(), match_simplify_replacement(), replace_phi_edge_with_variable(), and value_replacement().
This pass tries to replaces an if-then-else block with an
assignment. We have different kinds of transformations.
Some of these transformations are also performed by the ifcvt
RTL optimizer.
PHI-OPT using Match-and-simplify infrastructure
-----------------------
The PHI-OPT pass will try to use match-and-simplify infrastructure
(gimple_simplify) to do transformations. This is implemented in
match_simplify_replacement.
The way it works is it replaces:
bb0:
if (cond) goto bb2; else goto bb1;
bb1:
bb2:
x = PHI <a (bb1), b (bb0), ...>;
with a statement if it gets simplified from `cond ? b : a`.
bb0:
x1 = cond ? b : a;
bb2:
x = PHI <a (bb1), x1 (bb0), ...>;
Bb1 might be removed as it becomes unreachable when doing the replacement.
Though bb1 does not have to be considered a forwarding basic block from bb0.
Will try to see if `(!cond) ? a : b` gets simplified (iff !cond simplifies);
this is done not to have an explosion of patterns in match.pd.
Note bb1 does not need to be completely empty, it can contain
one statement which is known not to trap.
It also can handle the case where we have two forwarding bbs (diamond):
bb0:
if (cond) goto bb2; else goto bb1;
bb1: goto bb3;
bb2: goto bb3;
bb3:
x = PHI <a (bb1), b (bb2), ...>;
And that is replaced with a statement if it is simplified
from `cond ? b : a`.
Again bb1 and bb2 does not have to be completely empty but
each can contain one statement which is known not to trap.
But in this case bb1/bb2 can only be forwarding basic blocks.
This fully replaces the old "Conditional Replacement",
"ABS Replacement" and "MIN/MAX Replacement" transformations as they are now
implemented in match.pd.
Value Replacement
-----------------
This transformation, implemented in value_replacement, replaces
bb0:
if (a != b) goto bb2; else goto bb1;
bb1:
bb2:
x = PHI <a (bb1), b (bb0), ...>;
with
bb0:
bb2:
x = PHI <b (bb0), ...>;
This opportunity can sometimes occur as a result of other
optimizations.
Another case caught by value replacement looks like this:
bb0:
t1 = a == CONST;
t2 = b > c;
t3 = t1 & t2;
if (t3 != 0) goto bb1; else goto bb2;
bb1:
bb2:
x = PHI (CONST, a)
Gets replaced with:
bb0:
bb2:
t1 = a == CONST;
t2 = b > c;
t3 = t1 & t2;
x = a;
This pass also performs a fifth transformation of a slightly different
flavor.
Factor operations in COND_EXPR
------------------------------
This transformation factors the unary operations out of COND_EXPR with
factor_out_conditional_operation.
For example:
if (a <= CST) goto <bb 3>; else goto <bb 4>;
<bb 3>:
tmp = (int) a;
<bb 4>:
tmp = PHI <tmp, CST>
Into:
if (a <= CST) goto <bb 3>; else goto <bb 4>;
<bb 3>:
<bb 4>:
a = PHI <a, CST>
tmp = (int) a;
Adjacent Load Hoisting
----------------------
This transformation replaces
bb0:
if (...) goto bb2; else goto bb1;
bb1:
x1 = (<expr>).field1;
goto bb3;
bb2:
x2 = (<expr>).field2;
bb3:
# x = PHI <x1, x2>;
with
bb0:
x1 = (<expr>).field1;
x2 = (<expr>).field2;
if (...) goto bb2; else goto bb1;
bb1:
goto bb3;
bb2:
bb3:
# x = PHI <x1, x2>;
The purpose of this transformation is to enable generation of conditional
move instructions such as Intel CMOVE or PowerPC ISEL. Because one of
the loads is speculative, the transformation is restricted to very
specific cases to avoid introducing a page fault. We are looking for
the common idiom:
if (...)
x = y->left;
else
x = y->right;
where left and right are typically adjacent pointers in a tree structure. Replicate the join block at E's destination into E's source. The copy's PHIs degenerate to their argument on E, so the copied conditional tests the predecessor's own value. The net effect after cleanups, for edge (3, 5) would be: <bb 3>: <bb 3>: t_9 = a < b; t_9 = a < b; goto <bb 5>; if (t_9 != 0) <bb 4>: -> <bb 4>: t_6 = c < d; t_6 = c < d; goto <bb 5>; goto <bb 5>; <bb 5>: <bb 5>: # t_1 = PHI <t_9(3), t_6(4)> # t_1 = PHI <t_6(4)> if (t_1 != 0) if (t_1 != 0) Return TRUE if the replication was performed.
References add_phi_args_after_copy(), can_duplicate_block_on_edge_p(), dump_file, dump_flags, duplicate_block(), flush_pending_stmts(), basic_block_def::index, NULL, replicate_cond_into_pred(), and TDF_DETAILS.
Referenced by replicate_cond_into_pred(), and replicate_conds_over_phis().
|
static |
Replicate conditionals over a PHI of comparisons into the
qualifying predecessors of every join block in the function, so
each arm branches directly on its own comparison instead of merging
into a boolean that is tested again:
<bb 3>: <bb 3>:
t_9 = a < b; t_9 = a < b;
goto <bb 5>; if (t_9 != 0)
<bb 4>: -> <bb 4>:
t_6 = c < d; t_6 = c < d;
goto <bb 5>; if (t_6 != 0)
<bb 5>:
# t_1 = PHI <t_9(3), t_6(4)>
if (t_1 != 0)
References cfun, cond_on_phi_p(), EDGE_COUNT, ei_next(), ei_safe_edge(), ei_start, FOR_EACH_BB_FN, free_original_copy_tables(), loop::header, initialize_original_copy_tables(), basic_block_def::loop_father, LOOPS_NEED_FIXUP, loops_state_set(), phi_arg_from_cmp_p(), basic_block_def::preds, replicate_cond_into_pred(), and replicate_conds_over_phis().
Referenced by replicate_conds_over_phis().
|
static |
RHS is a source argument in a BIT_AND_EXPR or BIT_IOR_EXPR which feeds a conditional of the form SSA_NAME NE 0. If RHS is fed by a simple EQ_EXPR or NE_EXPR comparison of two values, see if the two input values of the comparison match arg0 and arg1. If so update *code and return TRUE. Otherwise return FALSE.
References gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), is_gimple_assign(), operand_equal_for_phi_arg_p(), rhs_is_fed_for_value_replacement(), SSA_NAME_DEF_STMT, and TREE_CODE.
Referenced by operand_equal_for_value_replacement(), and rhs_is_fed_for_value_replacement().
|
static |
Optimization of PHI nodes by converting them into straightline code. Copyright (C) 2004-2026 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/>.
Return the singleton PHI in the SEQ of PHIs for edges E0 and E1.
References as_a(), gimple_phi_arg_def(), gimple_phi_result(), gsi_end_p(), gsi_next(), gsi_start(), gsi_stmt(), i, NULL, operand_equal_for_phi_arg_p(), single_non_singleton_phi_for_edges(), and virtual_operand_p().
Referenced by factor_out_conditional_operation(), single_non_singleton_phi_for_edges(), and value_replacement().
|
static |
Attempt to optimize (x <=> y) cmp 0 and similar comparisons. For strong ordering <=> try to match something like: <bb 2> : // cond3_bb (== cond2_bb) if (x_4(D) != y_5(D)) goto <bb 3>; [INV] else goto <bb 6>; [INV] <bb 3> : // cond_bb if (x_4(D) < y_5(D)) goto <bb 6>; [INV] else goto <bb 4>; [INV] <bb 4> : // middle_bb <bb 6> : // phi_bb # iftmp.0_2 = PHI <1(4), 0(2), -1(3)> _1 = iftmp.0_2 == 0; and for partial ordering <=> something like: <bb 2> : // cond3_bb if (a_3(D) == b_5(D)) goto <bb 6>; [50.00%] else goto <bb 3>; [50.00%] <bb 3> [local count: 536870913]: // cond2_bb if (a_3(D) < b_5(D)) goto <bb 6>; [50.00%] else goto <bb 4>; [50.00%] <bb 4> [local count: 268435456]: // cond_bb if (a_3(D) > b_5(D)) goto <bb 6>; [50.00%] else goto <bb 5>; [50.00%] <bb 5> [local count: 134217728]: // middle_bb <bb 6> [local count: 1073741824]: // phi_bb # SR.27_4 = PHI <0(2), -1(3), 1(4), -128(5)> _2 = SR.27_4 > 0;
References absu_hwi(), as_a(), boolean_false_node, boolean_type_node, build2(), build3(), build_debug_expr_decl(), build_int_cst(), build_one_cst(), build_zero_cst(), cfun, COMPARISON_CLASS_P, cond_only_block_p(), EDGE_COUNT, EDGE_SUCC, empty_block_p(), fold_build1, fold_convert, FOR_EACH_IMM_USE_FAST, g, gcc_assert, gcc_checking_assert, gcc_unreachable, gimple_assign_cast_p(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), gimple_assign_rhs_code(), gimple_assign_set_rhs1(), gimple_assign_set_rhs2(), gimple_assign_set_rhs_code(), gimple_assign_set_rhs_with_ops(), gimple_bb(), GIMPLE_BINARY_RHS, gimple_build_assign(), gimple_build_debug_bind(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_cond_set_code(), gimple_cond_set_lhs(), gimple_cond_set_rhs(), gimple_phi_arg_def(), gimple_phi_result(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_remove(), GSI_SAME_STMT, HONOR_NANS(), IN_RANGE, integer_minus_onep(), integer_onep(), integer_zerop(), INTEGRAL_TYPE_P, invert_tree_comparison(), is_gimple_assign(), is_gimple_debug(), make_ssa_name(), MAY_HAVE_DEBUG_BIND_STMTS, wi::ne_p(), NULL_TREE, operand_equal_p(), basic_block_def::preds, release_ssa_name(), remove_phi_node(), replace_uses_by(), safe_dyn_cast(), single_imm_use(), single_pred(), single_pred_p(), spaceship_replacement(), SSA_NAME_DEF_STMT, SSA_NAME_OCCURS_IN_ABNORMAL_PHI, statistics_counter_event(), basic_block_def::succs, swap_tree_comparison(), wi::to_wide(), wi::to_widest(), TREE_CODE, tree_fits_shwi_p(), tree_int_cst_lt(), TREE_OPERAND, tree_to_shwi(), TREE_TYPE, TYPE_PRECISION, TYPE_UNSIGNED, update_stmt(), USE_STMT, and useless_type_conversion_p().
Referenced by spaceship_replacement().
|
static |
Return the last store in BB with VDEF or NULL if there are loads following the store. VPHI is where the only use of the vdef should be. If ONLYONESTORE is true, then the store is the only store in the BB.
References ref_to_bb::bb, gimple_bb(), gimple_vdef(), gimple_vuse(), NULL, single_imm_use(), SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, and trailing_store_in_bb().
Referenced by cond_if_else_store_replacement_limited(), cond_store_replacement_limited(), cselim_candidate(), and trailing_store_in_bb().
|
static |
The function value_replacement does the main work of doing the value replacement. Return non-zero if the replacement is done. Otherwise return 0. If we remove the middle basic block, return 2. BB is the basic block where the replacement is going to be done on. ARG0 is argument 0 from the PHI. Likewise for ARG1.
References absorbing_element_p(), as_a(), bb_seq(), boolean_type_node, build2(), build3(), build_debug_expr_decl(), CASE_CONVERT, cfun, CONVERT_EXPR_CODE_P, dump_file, dump_flags, EDGE_COUNT, EDGE_PRED, eni_time_weights, estimate_num_insns(), estimate_num_insns_seq(), profile_probability::even(), extract_true_false_edges_from_block(), fold_convert, FOR_EACH_IMM_USE_ON_STMT, FOR_EACH_IMM_USE_STMT, g, gcc_assert, get_global_range_query(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), gimple_assign_rhs_code(), gimple_bb(), GIMPLE_BINARY_RHS, gimple_build_debug_bind(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_phi_result(), gimple_seq_empty_p(), gsi_after_labels(), gsi_end_p(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_move_before(), gsi_next_nondebug(), gsi_prev_nondebug(), GSI_SAME_STMT, gsi_start_nondebug_after_labels_bb(), gsi_stmt(), HONOR_SIGNED_ZEROS(), i, basic_block_def::index, int_const_binop(), INTEGRAL_TYPE_P, is_gimple_assign(), is_gimple_debug(), jump_function_from_stmt(), MAY_HAVE_DEBUG_BIND_STMTS, neutral_element_p(), NULL, NULL_TREE, operand_equal_for_phi_arg_p(), operand_equal_for_value_replacement(), optimize_bb_for_speed_p(), phi_nodes(), POINTER_TYPE_P, print_generic_expr(), PROFILE_ABSENT, profile_status_for_fn, r, replace_exp(), replace_phi_edge_with_variable(), reset_debug_uses(), reset_flow_sensitive_info(), sc, SET_PHI_ARG_DEF, set_range_info(), single_imm_use(), single_non_singleton_phi_for_edges(), single_pred_p(), single_succ_edge(), ssa_name_maybe_undef_p(), SSA_NAME_RANGE_INFO, statistics_counter_event(), tcc_comparison, TDF_DETAILS, TREE_CODE, TREE_CODE_CLASS, tree_int_cst_equal(), tree_int_cst_le(), tree_int_cst_lt(), TREE_OVERFLOW, TREE_TYPE, update_stmt(), value_replacement(), and virtual_operand_p().
Referenced by value_replacement().
|
static |
Used for quick clearing of the hash-table when we see calls. Hash entries with phase < nt_call_phase are invalid.
Referenced by nontrapping_dom_walker::add_or_mark_expr(), nontrapping_dom_walker::before_dom_children(), and get_non_trapping().