GCC Middle and Back End API Reference
ifcvt.c File Reference

Data Structures

struct  noce_if_info

Functions

static int count_bb_insns (const_basic_block)
static bool cheap_bb_rtx_cost_p (const_basic_block, int, int)
static rtx first_active_insn (basic_block)
static rtx last_active_insn (basic_block, int)
static rtx find_active_insn_before (basic_block, rtx)
static rtx find_active_insn_after (basic_block, rtx)
static basic_block block_fallthru (basic_block)
static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int)
static rtx cond_exec_get_condition (rtx)
static rtx noce_get_condition (rtx, rtx *, bool)
static int noce_operand_ok (const_rtx)
static void merge_if_block (ce_if_block_t *)
static int find_cond_trap (basic_block, edge, edge)
static basic_block find_if_header (basic_block, int)
static int block_jumps_and_fallthru_p (basic_block, basic_block)
static int noce_find_if_block (basic_block, edge, edge, int)
static int cond_exec_find_if_block (ce_if_block_t *)
static int find_if_case_1 (basic_block, edge, edge)
static int find_if_case_2 (basic_block, edge, edge)
static int dead_or_predicable (basic_block, basic_block, basic_block, edge, int)
static void noce_emit_move_insn (rtx, rtx)
static rtx block_has_only_trap (basic_block)
static int count_bb_insns ()
static bool cheap_bb_rtx_cost_p ()
static rtx first_active_insn ()
static rtx last_active_insn ()
static rtx find_active_insn_before ()
static rtx find_active_insn_after ()
static basic_block block_fallthru ()
static rtx cond_exec_get_condition ()
static int cond_exec_process_if_block (ce_if_block_t *ce_info, int do_multiple_p)
static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int)
static int noce_try_move (struct noce_if_info *)
static int noce_try_store_flag (struct noce_if_info *)
static int noce_try_addcc (struct noce_if_info *)
static int noce_try_store_flag_constants (struct noce_if_info *)
static int noce_try_store_flag_mask (struct noce_if_info *)
static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx, rtx, rtx, rtx)
static int noce_try_cmove (struct noce_if_info *)
static int noce_try_cmove_arith (struct noce_if_info *)
static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx *)
static int noce_try_minmax (struct noce_if_info *)
static int noce_try_abs (struct noce_if_info *)
static int noce_try_sign_mask (struct noce_if_info *)
static void noce_emit_move_insn ()
static rtx end_ifcvt_sequence ()
static int noce_try_move ()
static int noce_try_store_flag ()
static int noce_try_store_flag_constants ()
static int noce_try_addcc ()
static int noce_try_store_flag_mask ()
static int noce_try_cmove ()
static int noce_try_cmove_arith ()
static int noce_try_minmax ()
static int noce_try_abs ()
static int noce_try_sign_mask ()
static int noce_try_bitop ()
static rtx noce_get_condition ()
static int noce_operand_ok ()
static bool noce_mem_write_may_trap_or_fault_p ()
static bool noce_can_store_speculate_p ()
static int noce_process_if_block ()
static int check_cond_move_block (basic_block bb, struct pointer_map_t *vals, vec< rtx > *regs, rtx cond)
static bool cond_move_convert_if_block (struct noce_if_info *if_infop, basic_block bb, rtx cond, struct pointer_map_t *then_vals, struct pointer_map_t *else_vals, bool else_block_p)
static int cond_move_process_if_block ()
static void merge_if_block ()
static basic_block find_if_header ()
static int block_jumps_and_fallthru_p ()
static int cond_exec_find_if_block ()
static int find_cond_trap ()
static rtx block_has_only_trap ()
static int find_if_case_1 ()
static int find_if_case_2 ()
static void if_convert ()
static bool gate_handle_if_conversion ()
static unsigned int rest_of_handle_if_conversion ()
rtl_opt_passmake_pass_rtl_ifcvt ()
static bool gate_handle_if_after_combine ()
static unsigned int rest_of_handle_if_after_combine ()
rtl_opt_passmake_pass_if_after_combine ()
static bool gate_handle_if_after_reload ()
static unsigned int rest_of_handle_if_after_reload ()
rtl_opt_passmake_pass_if_after_reload ()

Variables

static bool ifcvt_after_combine
static int num_possible_if_blocks
static int num_updated_if_blocks
static int num_true_changes
static int cond_exec_changed_p

Function Documentation

static basic_block block_fallthru ( basic_block  )
static
static basic_block block_fallthru ( )
static
Return the basic block reached by falling though the basic block BB.   

References edge_def::dest, find_fallthru_edge(), and basic_block_def::succs.

static rtx block_has_only_trap ( basic_block  )
static

Referenced by find_cond_trap().

static rtx block_has_only_trap ( )
static
Subroutine of find_cond_trap: if BB contains only a trap insn,
   return it.   

References const_true_rtx, first_active_insn(), and basic_block_def::succs.

static int block_jumps_and_fallthru_p ( basic_block  ,
basic_block   
)
static

Referenced by cond_exec_find_if_block().

static int block_jumps_and_fallthru_p ( )
static
Return true if a block has two edges, one of which falls through to the next
   block, and the other jumps to a specific block, so that we can tell if the
   block is part of an && test or an || test.  Returns either -1 or the number
   of non-note, non-jump, non-USE/CLOBBER insns in the block.   

References edge_def::dest, edge_def::flags, and basic_block_def::succs.

static bool cheap_bb_rtx_cost_p ( const_basic_block  ,
int  ,
int   
)
static

Referenced by find_if_case_1(), and find_if_case_2().

static bool cheap_bb_rtx_cost_p ( )
static
Determine whether the total insn_rtx_cost on non-jump insns in
   basic block BB is less than MAX_COST.  This function returns
   false if the cost of any instruction could not be estimated. 

   The cost of the non-jump insns in BB is scaled by REG_BR_PROB_BASE
   as those insns are being speculated.  MAX_COST is scaled with SCALE
   plus a small fudge factor.   

References cfun, count, ifcvt_after_combine, insn_rtx_cost(), optimize_bb_for_speed_p(), and optimize_function_for_speed_p().

static int check_cond_move_block ( basic_block  bb,
struct pointer_map_t vals,
vec< rtx > *  regs,
rtx  cond 
)
static
Check whether a block is suitable for conditional move conversion.
   Every insn must be a simple set of a register to a constant or a
   register.  For each assignment, store the value in the pointer map
   VALS, keyed indexed by register pointer, then store the register
   pointer in REGS.  COND is the condition we will test.   

References may_trap_p(), modified_between_p(), onlyjump_p(), pointer_map_contains(), pointer_map_insert(), reg_overlap_mentioned_p(), register_operand(), side_effects_p(), and targetm.

Referenced by cond_move_process_if_block().

static int cond_exec_find_if_block ( ce_if_block_t )
static

Referenced by find_if_header().

static rtx cond_exec_get_condition ( rtx  )
static
static rtx cond_exec_get_condition ( )
static
Return the condition for a jump.  Do not do any special processing.   

References any_condjump_p(), pc_set(), and reversed_comparison_code().

static int cond_exec_process_insns ( ce_if_block_t ce_info,
rtx  start,
rtx  end,
rtx  test,
rtx  prob_val,
int  mod_ok 
)
static
Go through a bunch of insns, converting them to conditional
   execution format if possible.  Return TRUE if all of the non-note
   insns were processed.   

References alloc_EXPR_LIST(), copy_rtx(), modified_in_p(), reload_completed, and validate_change().

Referenced by cond_exec_process_if_block(), and dead_or_predicable().

static bool cond_move_convert_if_block ( struct noce_if_info if_infop,
basic_block  bb,
rtx  cond,
struct pointer_map_t then_vals,
struct pointer_map_t else_vals,
bool  else_block_p 
)
static
Given a basic block BB suitable for conditional move conversion,
   a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing
   the register values depending on COND, emit the insns in the block as
   conditional moves.  If ELSE_BLOCK is true, THEN_BB was already
   processed.  The caller has started a sequence for the conversion.
   Return true if successful, false if something goes wrong.   

References noce_emit_cmove(), noce_emit_move_insn(), and pointer_map_contains().

Referenced by cond_move_process_if_block().

static int count_bb_insns ( const_basic_block  )
static
Forward references.   

Referenced by cond_exec_process_if_block().

static int count_bb_insns ( )
static
Count the number of non-jump active insns in BB.   

References count.

static int dead_or_predicable ( basic_block  test_bb,
basic_block  merge_bb,
basic_block  other_bb,
edge  dest_edge,
int  reversep 
)
static
static rtx end_ifcvt_sequence ( )
static
Return sequence of instructions generated by if conversion.  This
   function calls end_sequence() to end the current stream, ensures
   that are instructions are unshared, recognizable non-jump insns.
   On failure, this function returns a NULL_RTX.   

References noce_if_info::a, noce_if_info::b, noce_if_info::cond, end_sequence(), get_insns(), recog_memoized(), set_used_flags(), unshare_all_rtl_in_chain(), and noce_if_info::x.

Referenced by cond_move_process_if_block(), noce_try_abs(), noce_try_addcc(), noce_try_bitop(), noce_try_cmove(), noce_try_cmove_arith(), noce_try_minmax(), noce_try_move(), noce_try_sign_mask(), noce_try_store_flag(), noce_try_store_flag_constants(), and noce_try_store_flag_mask().

static rtx find_active_insn_after ( basic_block  ,
rtx   
)
static
static rtx find_active_insn_after ( )
static
Return the active insn after INSN inside basic block CURR_BB.  
static rtx find_active_insn_before ( basic_block  ,
rtx   
)
static
static rtx find_active_insn_before ( )
static
Return the active insn before INSN inside basic block CURR_BB.  
static int find_cond_trap ( basic_block  ,
edge  ,
edge   
)
static

Referenced by find_if_header().

static int find_if_case_1 ( basic_block  ,
edge  ,
edge   
)
static

Referenced by find_if_header().

static int find_if_case_1 ( )
static
Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
   transformable, but not necessarily the other.  There need be no
   JOIN block.

   Return TRUE if we were successful at converting the block.

   Cases we'd like to look at:

   (1)
        if (test) goto over; // x not live
        x = a;
        goto label;
        over:

   becomes

        x = a;
        if (! test) goto label;

   (2)
        if (test) goto E; // x not live
        x = big();
        goto L;
        E:
        x = b;
        goto M;

   becomes

        x = b;
        if (test) goto M;
        x = big();
        goto L;

   (3) // This one's really only interesting for targets that can do
       // multiway branching, e.g. IA-64 BBB bundles.  For other targets
       // it results in multiple branches on a cache line, which often
       // does not sit well with predictors.

        if (test1) goto E; // predicted not taken
        x = a;
        if (test2) goto F;
        ...
        E:
        x = b;
        J:

   becomes

        x = a;
        if (test1) goto E;
        if (test2) goto F;

   Notes:

   (A) Don't do (2) if the branch is predicted against the block we're
   eliminating.  Do it anyway if we can eliminate a branch; this requires
   that the sole successor of the eliminated block postdominate the other
   side of the if.

   (B) With CE, on (3) we can steal from both sides of the if, creating

        if (test1) x = a;
        if (!test1) x = b;
        if (test1) goto J;
        if (test2) goto F;
        ...
        J:

   Again, this is most useful if J postdominates.

   (C) CE substitutes for helpful life information.

   (D) These heuristics need a lot of work.   
Tests for case 1 above.   

References cheap_bb_rtx_cost_p(), dead_or_predicable(), delete_basic_block(), edge_def::dest, df_bb_replace(), df_set_bb_dirty(), dump_file, noce_if_info::else_bb, find_reg_note(), force_nonfallthru_and_redirect(), forwarder_block_p(), basic_block_def::index, noce_if_info::jump, basic_block_def::next_bb, num_possible_if_blocks, num_true_changes, num_updated_if_blocks, optimize_bb_for_speed_p(), predictable_edge_p(), basic_block_def::prev_bb, edge_def::probability, redirect_edge_and_branch_force(), redirect_edge_succ(), single_pred_p(), single_succ_edge(), single_succ_p(), edge_def::src, and noce_if_info::then_bb.

static int find_if_case_2 ( basic_block  ,
edge  ,
edge   
)
static

Referenced by find_if_header().

static basic_block find_if_header ( basic_block  ,
int   
)
static

Referenced by if_convert().

static basic_block find_if_header ( )
static
Find a block ending in a simple IF condition and try to transform it
   in some way.  When converting a multi-block condition, put the new code
   in the first such block and delete the rest.  Return a pointer to this
   first block if some transformation was done.  Return NULL otherwise.   

References CDI_POST_DOMINATORS, cond_exec_changed_p, cond_exec_find_if_block(), edge_def::dest, df_get_bb_dirty(), dom_info_state(), DOM_NO_FAST_QUERY, dump_file, ce_if_block::else_bb, find_cond_trap(), find_if_case_1(), find_if_case_2(), edge_def::flags, memset(), noce_find_if_block(), optab_handler(), ce_if_block::pass, reload_completed, basic_block_def::succs, targetm, ce_if_block::test_bb, noce_if_info::test_bb, ce_if_block::then_bb, and word_mode.

static rtx first_active_insn ( )
static
Return the first non-jump active insn in the basic block.   
static bool gate_handle_if_after_combine ( )
static

References dbg_cnt().

static bool gate_handle_if_after_reload ( )
static

References dbg_cnt().

static bool gate_handle_if_conversion ( )
static

References dbg_cnt().

static rtx last_active_insn ( basic_block  ,
int   
)
static
static rtx last_active_insn ( )
static
Return the last non-jump active (non-jump) insn in the basic block.   
rtl_opt_pass* make_pass_if_after_combine ( )
rtl_opt_pass* make_pass_if_after_reload ( )
rtl_opt_pass* make_pass_rtl_ifcvt ( )
static void merge_if_block ( ce_if_block_t )
static
static bool noce_can_store_speculate_p ( )
static
Return whether we can use store speculation for MEM.  TOP_BB is the
   basic block above the conditional block where we are considering
   doing the speculative store.  We look for whether MEM is set
   unconditionally later in the function.   

References CDI_POST_DOMINATORS, get_immediate_dominator(), memory_must_be_modified_in_insn_p(), modified_in_p(), and volatile_insn_p().

Referenced by noce_process_if_block().

static rtx noce_emit_cmove ( struct noce_if_info if_info,
rtx  x,
enum rtx_code  code,
rtx  cmp_a,
rtx  cmp_b,
rtx  vfalse,
rtx  vtrue 
)
static
static void noce_emit_move_insn ( )
static
Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
   X is the destination/target and Y is the value to copy.   

References code_to_optab(), emit_insn(), emit_move_insn(), end_sequence(), expand_binop(), expand_unop(), get_insns(), HOST_WIDE_INT, OPTAB_DIRECT, recog_memoized(), RTX_BIN_ARITH, RTX_COMM_ARITH, RTX_UNARY, start_sequence(), and store_bit_field().

static int noce_find_if_block ( basic_block  test_bb,
edge  then_edge,
edge  else_edge,
int  pass 
)
static
Determine if a given basic block heads a simple IF-THEN-JOIN or an
   IF-THEN-ELSE-JOIN block.

   If so, we'll try to convert the insns to not require the branch,
   using only transformations that do not require conditional execution.

   Return TRUE if we were successful at converting the block.   

References noce_if_info::branch_cost, noce_if_info::cond, noce_if_info::cond_earliest, cond_move_process_if_block(), edge_def::dest, dump_file, noce_if_info::else_bb, basic_block_def::index, noce_if_info::join_bb, noce_if_info::jump, memset(), noce_get_condition(), noce_process_if_block(), num_possible_if_blocks, onlyjump_p(), optimize_bb_for_speed_p(), predictable_edge_p(), reload_completed, single_pred_p(), single_succ(), single_succ_edge(), single_succ_p(), noce_if_info::test_bb, noce_if_info::then_bb, and noce_if_info::then_else_reversed.

Referenced by find_if_header().

static rtx noce_get_alt_condition ( struct noce_if_info if_info,
rtx  target,
rtx earliest 
)
static
For most cases, the simplified condition we found is the best
   choice, but this is not the case for the min/max/abs transforms.
   For these we wish to know that it is A or B in the condition.   

References noce_if_info::a, noce_if_info::b, canonicalize_condition(), noce_if_info::cond, noce_if_info::cond_earliest, find_reg_equal_equiv_note(), HOST_WIDE_INT, noce_if_info::jump, modified_in_p(), pc_set(), prev_nonnote_insn(), reg_mentioned_p(), reg_overlap_mentioned_p(), rtx_equal_p(), SET, swap_condition(), noce_if_info::then_else_reversed, and noce_if_info::x.

Referenced by noce_try_abs(), and noce_try_minmax().

static rtx noce_get_condition ( rtx  ,
rtx ,
bool   
)
static
static rtx noce_get_condition ( )
static
Similar to get_condition, only the resulting condition must be
   valid at JUMP, instead of at EARLIEST.

   If THEN_ELSE_REVERSED is true, the fallthrough does not go to the
   THEN block of the caller, and we have to reverse the condition.   

References any_condjump_p(), canonicalize_condition(), pc_set(), reverse_condition(), side_effects_p(), and targetm.

static bool noce_mem_write_may_trap_or_fault_p ( )
static
Return true if a write into MEM may trap or fault.   

References decl_readonly_section(), may_trap_or_fault_p(), and targetm.

Referenced by noce_process_if_block().

static int noce_operand_ok ( const_rtx  )
static

Referenced by noce_process_if_block().

static int noce_operand_ok ( )
static
Return true if OP is ok for if-then-else processing.   

References may_trap_p(), and side_effects_p().

static int noce_try_abs ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_addcc ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_cmove ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_cmove ( )
static
Try only simple constants and registers here.  More complex cases
   are handled in noce_try_cmove_arith after noce_try_store_flag_arith
   has had a go at it.   

References noce_if_info::a, noce_if_info::b, noce_if_info::cond, emit_insn_before_setloc(), end_ifcvt_sequence(), end_sequence(), noce_if_info::insn_a, noce_if_info::jump, noce_emit_cmove(), noce_emit_move_insn(), register_operand(), start_sequence(), and noce_if_info::x.

static int noce_try_cmove_arith ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_minmax ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_move ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_move ( )
static
Convert "if (a != b) x = a; else x = b" into "x = a" and
   "if (a == b) x = a; else x = b" into "x = b".   

References noce_if_info::a, noce_if_info::b, noce_if_info::cond, emit_insn_before_setloc(), end_ifcvt_sequence(), noce_if_info::insn_a, noce_if_info::jump, noce_emit_move_insn(), rtx_equal_p(), start_sequence(), and noce_if_info::x.

static int noce_try_sign_mask ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_store_flag ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_store_flag ( )
static
Convert "if (test) x = 1; else x = 0".

   Only try 0 and STORE_FLAG_VALUE here.  Other combinations will be
   tried in noce_try_store_flag_constants after noce_try_cmove has had
   a go at the conversion.   

References noce_if_info::a, noce_if_info::b, noce_if_info::cond, emit_insn_before_setloc(), end_ifcvt_sequence(), end_sequence(), noce_if_info::insn_a, noce_if_info::jump, noce_emit_move_insn(), noce_emit_store_flag(), reversed_comparison_code(), start_sequence(), and noce_if_info::x.

static int noce_try_store_flag_constants ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static int noce_try_store_flag_mask ( struct noce_if_info )
static

Referenced by noce_process_if_block().

static unsigned int rest_of_handle_if_after_combine ( )
static
Rerun if-conversion, as combine may have simplified things enough
   to now meet sequence length restrictions.   

References if_convert().

static unsigned int rest_of_handle_if_after_reload ( )
static

References if_convert().

static unsigned int rest_of_handle_if_conversion ( )
static
If-conversion and CFG cleanup.   

References cleanup_cfg(), dump_file, dump_flags, dump_flow_info(), dump_reg_info(), and if_convert().


Variable Documentation

int cond_exec_changed_p
static
Whether conditional execution changes were made.   

Referenced by cond_exec_process_if_block(), find_if_header(), and if_convert().

bool ifcvt_after_combine
static
True if after combine pass.   

Referenced by cheap_bb_rtx_cost_p(), and if_convert().

int num_possible_if_blocks
static
# of IF-THEN or IF-THEN-ELSE blocks we looked at   

Referenced by cond_exec_find_if_block(), find_if_case_1(), find_if_case_2(), if_convert(), and noce_find_if_block().

int num_updated_if_blocks
static
# of IF-THEN or IF-THEN-ELSE blocks were converted to conditional
   execution.   

Referenced by cond_move_process_if_block(), find_cond_trap(), find_if_case_1(), find_if_case_2(), if_convert(), merge_if_block(), and noce_process_if_block().