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

Data Structures

struct  reg_stat_struct
struct  insn_link
struct  undo
struct  undobuf
struct  likely_spilled_retval_info

Typedefs

typedef struct reg_stat_struct reg_stat_type

Enumerations

enum  undo_kind { UNDO_RTX, UNDO_INT, UNDO_MODE, UNDO_LINKS }

Functions

static struct insn_linkalloc_insn_link ()
static rtx reg_nonzero_bits_for_combine (const_rtx, enum machine_mode, const_rtx, enum machine_mode, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *)
static rtx reg_num_sign_bit_copies_for_combine (const_rtx, enum machine_mode, const_rtx, enum machine_mode, unsigned int, unsigned int *)
static void do_SUBST (rtx *, rtx)
static void do_SUBST_INT (int *, int)
static void init_reg_last (void)
static void setup_incoming_promotions (rtx)
static void set_nonzero_bits_and_sign_copies (rtx, const_rtx, void *)
static int cant_combine_insn_p (rtx)
static int can_combine_p (rtx, rtx, rtx, rtx, rtx, rtx, rtx *, rtx *)
static int combinable_i3pat (rtx, rtx *, rtx, rtx, rtx, int, int, rtx *)
static int contains_muldiv (rtx)
static rtx try_combine (rtx, rtx, rtx, rtx, int *, rtx)
static void undo_all (void)
static void undo_commit (void)
static rtxfind_split_point (rtx *, rtx, bool)
static rtx subst (rtx, rtx, rtx, int, int, int)
static rtx combine_simplify_rtx (rtx, enum machine_mode, int, int)
static rtx simplify_if_then_else (rtx)
static rtx simplify_set (rtx)
static rtx simplify_logical (rtx)
static rtx expand_compound_operation (rtx)
static const_rtx expand_field_assignment (const_rtx)
static rtx make_extraction (enum machine_mode, rtx, HOST_WIDE_INT, rtx, unsigned HOST_WIDE_INT, int, int, int)
static rtx extract_left_shift (rtx, int)
static int get_pos_from_mask (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *)
static rtx canon_reg_for_combine (rtx, rtx)
static rtx force_to_mode (rtx, enum machine_mode, unsigned HOST_WIDE_INT, int)
static rtx if_then_else_cond (rtx, rtx *, rtx *)
static rtx known_cond (rtx, enum rtx_code, rtx, rtx)
static int rtx_equal_for_field_assignment_p (rtx, rtx)
static rtx make_field_assignment (rtx)
static rtx apply_distributive_law (rtx)
static rtx distribute_and_simplify_rtx (rtx, int)
static rtx simplify_and_const_int_1 (enum machine_mode, rtx, unsigned HOST_WIDE_INT)
static rtx simplify_and_const_int (rtx, enum machine_mode, rtx, unsigned HOST_WIDE_INT)
static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code, HOST_WIDE_INT, enum machine_mode, int *)
static rtx simplify_shift_const_1 (enum rtx_code, enum machine_mode, rtx, int)
static rtx simplify_shift_const (rtx, enum rtx_code, enum machine_mode, rtx, int)
static int recog_for_combine (rtx *, rtx, rtx *)
static rtx gen_lowpart_for_combine (enum machine_mode, rtx)
static enum rtx_code simplify_compare_const (enum rtx_code, rtx, rtx *)
static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *)
static void update_table_tick (rtx)
static void record_value_for_reg (rtx, rtx, rtx)
static void check_promoted_subreg (rtx, rtx)
static void record_dead_and_set_regs_1 (rtx, const_rtx, void *)
static void record_dead_and_set_regs (rtx)
static int get_last_value_validate (rtx *, rtx, int, int)
static rtx get_last_value (const_rtx)
static int use_crosses_set_p (const_rtx, int)
static void reg_dead_at_p_1 (rtx, const_rtx, void *)
static int reg_dead_at_p (rtx, rtx)
static void move_deaths (rtx, rtx, int, rtx, rtx *)
static int reg_bitfield_target_p (rtx, rtx)
static void distribute_notes (rtx, rtx, rtx, rtx, rtx, rtx, rtx)
static void distribute_links (struct insn_link *)
static void mark_used_regs_combine (rtx)
static void record_promoted_value (rtx, rtx)
static int unmentioned_reg_p_1 (rtx *, void *)
static bool unmentioned_reg_p (rtx, rtx)
static int record_truncated_value (rtx *, void *)
static void record_truncated_values (rtx *, void *)
static bool reg_truncated_to_mode (enum machine_mode, const_rtx)
static rtx gen_lowpart_or_truncate (enum machine_mode, rtx)
static void target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1, bool op0_preserve_value)
static rtx combine_split_insns ()
static rtxfind_single_use_1 ()
static rtxfind_single_use ()
static void do_SUBST ()
static void do_SUBST_INT ()
static void do_SUBST_MODE ()
static void do_SUBST_LINK ()
static bool combine_validate_cost (rtx i0, rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat, rtx newotherpat)
static void delete_noop_moves ()
static void create_log_links ()
static bool insn_a_feeds_b ()
static int combine_instructions ()
static void setup_incoming_promotions ()
static void set_nonzero_bits_and_sign_copies ()
static int contains_muldiv ()
static int cant_combine_insn_p ()
static void likely_spilled_retval_1 ()
static int likely_spilled_retval_p ()
static void adjust_for_new_dest ()
static bool can_change_dest_mode ()
static bool reg_subword_p ()
static void update_cfg_for_uncondjump ()
static rtxfind_split_point ()
static rtx subst ()
static rtx simplify_if_then_else ()
static rtx simplify_set ()
static rtx simplify_logical ()
static rtx expand_compound_operation ()
static const_rtx expand_field_assignment ()
static rtx extract_left_shift ()
rtx make_compound_operation ()
static int get_pos_from_mask ()
static rtx canon_reg_for_combine ()
static rtx gen_lowpart_or_truncate ()
static rtx if_then_else_cond ()
static rtx known_cond ()
static int rtx_equal_for_field_assignment_p ()
static rtx make_field_assignment ()
static rtx apply_distributive_law ()
static rtx distribute_and_simplify_rtx ()
unsigned int extended_count ()
static int merge_outer_ops ()
static enum machine_mode try_widen_shift_mode (enum rtx_code code, rtx op, int count, enum machine_mode orig_mode, enum machine_mode mode, enum rtx_code outer_code, HOST_WIDE_INT outer_const)
static int recog_for_combine ()
static rtx gen_lowpart_for_combine ()
static enum rtx_code simplify_compare_const ()
static enum rtx_code simplify_comparison ()
static int count_rtxs ()
static void update_table_tick ()
static void record_value_for_reg ()
static void record_dead_and_set_regs_1 ()
static void record_dead_and_set_regs ()
static void record_promoted_value ()
static bool reg_truncated_to_mode ()
static int record_truncated_value ()
static void record_truncated_values ()
static void check_promoted_subreg ()
static int get_last_value_validate ()
static rtx get_last_value ()
static int use_crosses_set_p ()
static void reg_dead_at_p_1 ()
static int reg_dead_at_p ()
static void mark_used_regs_combine ()
rtx remove_death ()
static int reg_bitfield_target_p ()
static void distribute_links ()
static int unmentioned_reg_p_1 ()
static bool unmentioned_reg_p ()
DEBUG_FUNCTION void dump_combine_stats ()
void dump_combine_total_stats ()
static bool gate_handle_combine ()
static unsigned int rest_of_handle_combine ()
rtl_opt_passmake_pass_combine ()

Variables

static int combine_attempts
static int combine_merges
static int combine_extras
static int combine_successes
static int total_attempts
static int total_merges
static int total_extras
static int total_successes
static rtx i2mod
static rtx i2mod_old_rhs
static rtx i2mod_new_rhs
static vec< reg_stat_typereg_stat
static int mem_last_set
static int last_call_luid
static rtx subst_insn
static int subst_low_luid
static HARD_REG_SET newpat_used_regs
static rtx added_links_insn
static basic_block this_basic_block
static bool optimize_this_for_speed_p
static int max_uid_known
static int * uid_insn_cost
static struct insn_link ** uid_log_links
static struct obstack insn_link_obstack
static int label_tick
static int label_tick_ebb_start
static enum machine_mode nonzero_bits_mode
static int nonzero_sign_valid
static struct undobuf undobuf
static int n_occurrences
static struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER
static unsigned int reg_dead_regno
static unsigned int reg_dead_endregno
static int reg_dead_flag

Typedef Documentation


Enumeration Type Documentation

enum undo_kind
Record one modification to rtl structure
   to be undone by storing old_contents into *where.   
Enumerator:
UNDO_RTX 
UNDO_INT 
UNDO_MODE 
UNDO_LINKS 

Function Documentation

static void adjust_for_new_dest ( )
static
Adjust INSN after we made a change to its destination.

   Changing the destination can invalidate notes that say something about
   the results of the insn and a LOG_LINK pointing to the insn.   

References alloc_insn_link(), df_insn_rescan(), distribute_links(), and remove_reg_equal_equiv_notes().

Referenced by try_combine().

static struct insn_link* alloc_insn_link ( )
staticread
static rtx apply_distributive_law ( )
static
See if X is of the form (+ (* a c) (* b c)) and convert to (* (+ a b) c)
   if so.   

References apply_distributive_law(), expand_compound_operation(), rtx_equal_p(), simplify_gen_binary(), and simplify_gen_unary().

static bool can_change_dest_mode ( )
static
Return TRUE if combine can reuse reg X in mode MODE.
   ADDED_SETS is nonzero if the original set is still required.   

References REG_N_SETS(), and likely_spilled_retval_info::regno.

Referenced by simplify_set(), and try_combine().

static int can_combine_p ( rtx  insn,
rtx  i3,
rtx  pred,
rtx  pred2,
rtx  succ,
rtx  succ2,
rtx pdest,
rtx psrc 
)
static
See if INSN can be combined into I3.  PRED, PRED2, SUCC and SUCC2 are
   optionally insns that were previously combined into I3 or that will be
   combined into the merger of INSN and I3.  The order is PRED, PRED2,
   INSN, SUCC, SUCC2, I3.

   Return 0 if the combination is not allowed for any reason.

   If the combination is allowed, *PDEST will be set to the single
   destination of INSN and *PSRC to the single source, and this function
   will return 1.   

References expand_field_assignment(), find_reg_fusage(), find_reg_note(), global_regs, insn_nothrow_p(), last_call_luid, next_active_insn(), prev_nonnote_insn(), reg_overlap_mentioned_p(), reg_set_between_p(), reg_used_between_p(), rtx_equal_p(), SET, sets_cc0_p(), side_effects_p(), subst_low_luid, use_crosses_set_p(), volatile_insn_p(), and volatile_refs_p().

Referenced by try_combine().

static rtx canon_reg_for_combine ( rtx  ,
rtx   
)
static
static rtx canon_reg_for_combine ( )
static
static int cant_combine_insn_p ( rtx  )
static

Referenced by try_combine().

static int cant_combine_insn_p ( )
static
Determine whether INSN can be used in a combination.  Return nonzero if
   not.  This is used in try_combine to detect early some cases where we
   can't perform combinations.   

References targetm.

static void check_promoted_subreg ( rtx  ,
rtx   
)
static
static void check_promoted_subreg ( )
static
Scan X for promoted SUBREGs.  For each one found,
   note what it implies to the registers used in it.   

References check_promoted_subreg(), and record_promoted_value().

static int combinable_i3pat ( rtx  i3,
rtx loc,
rtx  i2dest,
rtx  i1dest,
rtx  i0dest,
int  i1_not_in_src,
int  i0_not_in_src,
rtx pi3dest_killed 
)
static
LOC is the location within I3 that contains its pattern or the component
   of a PARALLEL of the pattern.  We validate that it is valid for combining.

   One problem is if I3 modifies its output, as opposed to replacing it
   entirely, we can't allow the output to contain I2DEST, I1DEST or I0DEST as
   doing so would produce an insn that is not equivalent to the original insns.

   Consider:

         (set (reg:DI 101) (reg:DI 100))
         (set (subreg:SI (reg:DI 101) 0) <foo>)

   This is NOT equivalent to:

         (parallel [(set (subreg:SI (reg:DI 100) 0) <foo>)
                    (set (reg:DI 101) (reg:DI 100))])

   Not only does this modify 100 (in which case it might still be valid
   if 100 were dead in I2), it sets 101 to the ORIGINAL value of 100.

   We can also run into a problem if I2 sets a register that I1
   uses and I1 gets directly substituted into I3 (not via I2).  In that
   case, we would be getting the wrong value of I2DEST into I3, so we
   must reject the combination.  This case occurs when I2 and I1 both
   feed into I3, rather than when I1 feeds into I2, which feeds into I3.
   If I1_NOT_IN_SRC is nonzero, it means that finding I1 in the source
   of a SET must prevent combination from occurring.  The same situation
   can occur for I0, in which case I0_NOT_IN_SRC is set.

   Before doing the above check, we first try to expand a field assignment
   into a set of logical operations.

   If PI3_DEST_KILLED is nonzero, it is a pointer to a location in which
   we place a register that is both set and used within I3.  If more than one
   such register is detected, we fail.

   Return 1 if the combination is valid, zero otherwise.   

References reg_overlap_mentioned_p(), reg_referenced_p(), rtx_equal_p(), and SET.

Referenced by try_combine().

static rtx combine_split_insns ( )
static
Try to split PATTERN found in INSN.  This returns NULL_RTX if
   PATTERN can not be split.  Otherwise, it returns an insn sequence.
   This is a wrapper around split_insns which ensures that the
   reg_stat vector is made larger if the splitter creates a new
   register.   

References max_reg_num(), reg_stat, and split_insns().

Referenced by find_split_point(), and try_combine().

static bool combine_validate_cost ( rtx  i0,
rtx  i1,
rtx  i2,
rtx  i3,
rtx  newpat,
rtx  newi2pat,
rtx  newotherpat 
)
static
Subroutine of try_combine.  Determine whether the replacement patterns
   NEWPAT, NEWI2PAT and NEWOTHERPAT are cheaper according to insn_rtx_cost
   than the original sequence I0, I1, I2, I3 and undobuf.other_insn.  Note
   that I0, I1 and/or NEWI2PAT may be NULL_RTX.  Similarly, NEWOTHERPAT and
   undobuf.other_insn may also both be NULL_RTX.  Return false if the cost
   of all the instructions can be estimated and the replacements are more
   expensive than the original sequence.   

References dump_file, insn_rtx_cost(), new_cost(), optimize_this_for_speed_p, and undobuf::other_insn.

Referenced by try_combine().

static int contains_muldiv ( rtx  )
static

Referenced by contains_muldiv(), and try_combine().

static int contains_muldiv ( )
static
Return 1 if X is an arithmetic expression that contains a multiplication
   and division.  We don't count multiplications by powers of two here.   

References contains_muldiv(), and exact_log2().

static int count_rtxs ( )
static
Utility function for record_value_for_reg.  Count number of
   rtxs in X.   

References RTX_BIN_ARITH, and RTX_COMM_ARITH.

Referenced by record_value_for_reg().

static void create_log_links ( )
static
static void delete_noop_moves ( )
static
Delete any insns that copy a register to itself.   

References delete_insn_and_edges(), dump_file, insn_link::insn, insn_link::next, and noop_move_p().

Referenced by combine_instructions().

static rtx distribute_and_simplify_rtx ( rtx  ,
int   
)
static
static rtx distribute_and_simplify_rtx ( )
static
See if X is of the form (* (+ A B) C), and if so convert to
   (+ (* A C) (* B C)) and try to simplify.

   Most of the time, this results in no change.  However, if some of
   the operands are the same or inverses of each other, simplifications
   will result.

   For example, (and (ior A B) (not B)) can occur as the result of
   expanding a bit field assignment.  When we apply the distributive
   law to this, we get (ior (and (A (not B))) (and (B (not B)))),
   which then simplifies to (and (A (not B))).

   Note that no checks happen on the validity of applying the inverse
   distributive law.  This is pointless since we can do it in the
   few places where this routine is called.

   N is the index of the term that is decomposed (the arithmetic operation,
   i.e. (+ A B) in the first example above).  !N is the index of the term that
   is distributed, i.e. of C in the first example above.   

References apply_distributive_law(), optimize_this_for_speed_p, set_src_cost(), and simplify_gen_binary().

static void distribute_links ( struct insn_link )
static
static void distribute_links ( )
static
Similarly to above, distribute the LOG_LINKS that used to be present on
   I3, I2, and I1 to new locations.  This is also called to add a link
   pointing at I3 when I3's destination is changed.   

References added_links_insn, find_reg_fusage(), insn_link::insn, insn_link::next, basic_block_def::next_bb, reg_overlap_mentioned_p(), reg_referenced_p(), reg_set_p(), and this_basic_block.

static void distribute_notes ( rtx  notes,
rtx  from_insn,
rtx  i3,
rtx  i2,
rtx  elim_i2,
rtx  elim_i1,
rtx  elim_i0 
)
static
Given a chain of REG_NOTES originally from FROM_INSN, try to place them
   as appropriate.  I3 and I2 are the insns resulting from the combination
   insns including FROM (I2 may be zero).

   ELIM_I2 and ELIM_I1 are either zero or registers that we know will
   not need REG_DEAD notes because they are being substituted for.  This
   saves searching in the most common cases.

   Each note in the list is either ignored or placed on some insns, depending
   on the type of note.   

References add_reg_note(), alloc_reg_note(), function::can_throw_non_call_exceptions, cc0_rtx, cfun, dead_or_set_p(), dead_or_set_regno_p(), distribute_links(), find_reg_fusage(), find_reg_note(), find_regno_fusage(), find_regno_note(), fixup_args_size_notes(), global_regs, i2, i2mod, i2mod_new_rhs, i2mod_old_rhs, reg_stat_struct::last_death, may_trap_p(), next_nonnote_nondebug_insn(), noop_move_p(), pc_rtx, prev_cc0_setter(), refers_to_regno_p(), reg_bitfield_target_p(), reg_mentioned_p(), reg_overlap_mentioned_p(), reg_referenced_p(), reg_set_p(), reg_stat, regno_reg_rtx, rtx_equal_p(), sets_cc0_p(), side_effects_p(), and this_basic_block.

Referenced by try_combine().

static void do_SUBST ( rtx ,
rtx   
)
static
static void do_SUBST ( )
static
Substitute NEWVAL, an rtx expression, into INTO, a place in some
   insn.  The substitution can be undone by undo_all.  If INTO is already
   set to NEWVAL, do not record this change.  Because computing NEWVAL might
   also call SUBST, we have to compute it before we put anything into
   the undo table.   

References undobuf::frees, undo::kind, undo::next, undo::old_contents, undo::r, trunc_int_for_mode(), UNDO_RTX, undobuf::undos, and undo::where.

static void do_SUBST_INT ( int *  ,
int   
)
static
static void do_SUBST_INT ( )
static
Similar to SUBST, but NEWVAL is an int expression.  Note that substitution
   for the value of a HOST_WIDE_INT value (including CONST_INT) is
   not safe.   

References undobuf::frees, undo::i, undo::kind, undo::next, undo::old_contents, UNDO_INT, undobuf::undos, and undo::where.

static void do_SUBST_LINK ( )
static
Similar to SUBST, but NEWVAL is a LOG_LINKS expression.   

References undobuf::frees, undo::kind, undo::l, undo::next, undo::old_contents, UNDO_LINKS, undobuf::undos, and undo::where.

static void do_SUBST_MODE ( )
static
Similar to SUBST, but just substitute the mode.  This is used when
   changing the mode of a pseudo-register, so that any other
   references to the entry in the regno_reg_rtx array will change as
   well.   

References adjust_reg_mode(), undobuf::frees, undo::kind, undo::m, undo::next, undo::old_contents, undo::r, UNDO_MODE, undobuf::undos, and undo::where.

DEBUG_FUNCTION void dump_combine_stats ( )
void dump_combine_total_stats ( )
static rtx expand_compound_operation ( )
static
We consider ZERO_EXTRACT, SIGN_EXTRACT, and SIGN_EXTEND as "compound
   operations" because they can be replaced with two more basic operations.
   ZERO_EXTEND is also considered "compound" because it can be replaced with
   an AND operation, which is simpler, though only one operation.

   The function expand_compound_operation is called with an rtx expression
   and will convert it to the appropriate shifts and AND operations,
   simplifying at each stage.

   The function make_compound_operation is called to convert an expression
   consisting of shifts and ANDs into the equivalent compound expression.
   It is the inverse of this function, loosely speaking.   

References expand_compound_operation(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, len, nonzero_bits(), optimize_this_for_speed_p, set_src_cost(), simplify_and_const_int(), simplify_shift_const(), and subreg_lowpart_p().

static const_rtx expand_field_assignment ( const_rtx  )
static
static const_rtx expand_field_assignment ( )
static
X is a SET which contains an assignment of one object into
   a part of another (such as a bit-field assignment, STRICT_LOW_PART,
   or certain SUBREGS). If possible, convert it into a series of
   logical operations.

   We half-heartedly support variable positions, but do not at all
   support variable lengths.   

References copy_rtx(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, len, mode_for_size(), nonzero_sign_valid, simplify_gen_binary(), simplify_gen_unary(), subreg_lowpart_p(), and subreg_lsb().

unsigned int extended_count ( )
Return the number of "extended" bits there are in X, when interpreted
   as a quantity in MODE whose signedness is indicated by UNSIGNEDP.  For
   unsigned quantities, this is the number of high-order zero bits.
   For signed quantities, this is the number of copies of the sign bit
   minus 1.  In both case, this function returns the number of "spare"
   bits.  For example, if two quantities for which this function returns
   at least 1 are added, the addition is known not to overflow.

   This function will always return 0 unless called during combine, which
   implies that it must be called from a define_split.   

References floor_log2(), nonzero_bits(), nonzero_sign_valid, and num_sign_bit_copies().

static rtx extract_left_shift ( rtx  ,
int   
)
static
static rtx extract_left_shift ( )
static
See if X contains an ASHIFT of COUNT or more bits that can be commuted
   with any other operations in X.  Return X without that shift if so.   

References extract_left_shift(), HOST_WIDE_INT, simplify_gen_binary(), simplify_gen_unary(), and simplify_shift_const().

static rtx* find_single_use ( )
static
See if DEST, produced in INSN, is used only a single time in the
   sequel.  If so, return a pointer to the innermost rtx expression in which
   it is used.

   If PLOC is nonzero, *PLOC is set to the insn containing the single use.

   If DEST is cc0_rtx, we look only at the next insn.  In that case, we don't
   care about REG_DEAD notes or LOG_LINKS.

   Otherwise, we find the single use by finding an insn that has a
   LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST.  If DEST is
   only referenced once in that insn, we know that it must be the first
   and last insn referencing DEST.   

References cc0_rtx, dead_or_set_p(), find_single_use_1(), insn_link::insn, and insn_link::next.

Referenced by find_split_point(), simplify_set(), and try_combine().

static rtx* find_single_use_1 ( )
static
This is used by find_single_use to locate an rtx in LOC that
   contains exactly one use of DEST, which is typically either a REG
   or CC0.  It returns a pointer to the innermost rtx expression
   containing DEST.  Appearances of DEST that are being used to
   totally replace it are not counted.   

References SET.

Referenced by find_single_use().

static rtx* find_split_point ( rtx ,
rtx  ,
bool   
)
static

Referenced by find_split_point(), and try_combine().

static rtx* find_split_point ( )
static
Find the innermost point within the rtx at LOC, possibly LOC itself,
   where we have an arithmetic expression and return that point.  LOC will
   be inside INSN.

   try_combine will call this function to see if an insn can be split into
   two insns.   

References cc0_rtx, combine_split_insns(), exact_log2(), find_single_use(), find_split_point(), gen_int_mode(), get_address_mode(), HOST_WIDE_INT, len, make_extraction(), memory_address_addr_space_p(), nonzero_bits(), reg_mentioned_p(), register_operand(), regno_reg_rtx, replace_rtx(), RTX_BIN_ARITH, RTX_BITFIELD_OPS, RTX_COMM_ARITH, RTX_COMM_COMPARE, RTX_COMPARE, RTX_TERNARY, RTX_UNARY, SET, side_effects_p(), simplify_gen_binary(), subst_insn, and trunc_int_for_mode().

static rtx force_to_mode ( rtx  x,
enum machine_mode  mode,
unsigned HOST_WIDE_INT  mask,
int  just_select 
)
static
See if X can be simplified knowing that we will only refer to it in
   MODE and will only refer to those bits that are nonzero in MASK.
   If other bits are being computed or if masking operations are done
   that select a superset of the bits in MASK, they can sometimes be
   ignored.

   Return a possibly simplified expression, but always convert X to
   MODE.  If X is a CONST_INT, AND the CONST_INT with MASK.

   If JUST_SELECT is nonzero, don't optimize by noticing that bits in MASK
   are all off in X.  This is used when X will be complemented, by either
   NOT, NEG, or XOR.   

References exact_log2(), expand_compound_operation(), floor_log2(), gen_int_mode(), gen_lowpart_common(), gen_lowpart_or_truncate(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT_1U, HOST_WIDE_INT_M1U, nonzero_bits(), num_sign_bit_copies(), optimize_this_for_speed_p, plus_constant(), set_src_cost(), side_effects_p(), simplify_and_const_int(), simplify_binary_operation(), simplify_gen_binary(), simplify_gen_unary(), simplify_shift_const(), subreg_lowpart_p(), and val_signbit_p().

Referenced by combine_simplify_rtx(), make_compound_operation(), make_extraction(), make_field_assignment(), simplify_and_const_int_1(), simplify_comparison(), and simplify_set().

static bool gate_handle_combine ( )
static
static rtx gen_lowpart_for_combine ( enum  machine_mode,
rtx   
)
static
static rtx gen_lowpart_for_combine ( )
static
Like gen_lowpart_general but for use by combine.  In combine it
   is not possible to create any new pseudoregs.  However, it is
   safe to create invalid memory addresses, because combine will
   try to recognize them and all they will do is make the combine
   attempt fail.

   If for some reason this cannot do its job, an rtx
   (clobber (const_int 0)) is returned.
   An insn containing that will not be recognized.   

References gen_lowpart_common(), gen_rtx_SUBREG(), int_mode_for_mode(), mode_dependent_address_p(), offset, simplify_gen_subreg(), and subreg_lowpart_offset().

static rtx gen_lowpart_or_truncate ( enum  machine_mode,
rtx   
)
static
static rtx gen_lowpart_or_truncate ( )
static
Return X converted to MODE.  If the value is already truncated to
   MODE we can just return a subreg even though in the general case we
   would need an explicit truncation.   

References int_mode_for_mode(), reg_truncated_to_mode(), and simplify_gen_unary().

static rtx get_last_value ( )
static
Get the last value assigned to X, if known.  Some registers
   in the value may be replaced with (clobber (const_int 0)) if their value
   is known longer known reliably.   

References copy_rtx(), get_last_value(), get_last_value_validate(), label_tick, label_tick_ebb_start, reg_stat_struct::last_set, reg_stat_struct::last_set_label, reg_stat_struct::last_set_value, paradoxical_subreg_p(), REG_N_SETS(), reg_stat, subreg_lowpart_p(), and subst_low_luid.

static int get_last_value_validate ( rtx ,
rtx  ,
int  ,
int   
)
static
static int get_last_value_validate ( )
static
Verify that all the registers and memory references mentioned in *LOC are
   still valid.  *LOC was part of a value set in INSN when label_tick was
   equal to TICK.  Return 0 if some are not.  If REPLACE is nonzero, replace
   the invalid references with (clobber (const_int 0)) and return 1.  This
   replacement is useful because we often can get useful information about
   the form of a value (e.g., if it was produced by a shift that always
   produces -1 or 0) even though we don't know exactly what registers it
   was produced from.   

References get_last_value_validate(), label_tick, reg_stat_struct::last_set_label, len, mem_last_set, REG_N_SETS(), and reg_stat.

static int get_pos_from_mask ( unsigned  HOST_WIDE_INT,
unsigned HOST_WIDE_INT  
)
static

Referenced by make_field_assignment().

static int get_pos_from_mask ( )
static
Given M see if it is a value that would select a field of bits
   within an item, but not the entire word.  Return -1 if not.
   Otherwise, return the starting position of the field, where 0 is the
   low-order bit.

   *PLEN is set to the length of the field.   

References ctz_hwi(), exact_log2(), and len.

static rtx if_then_else_cond ( rtx  ,
rtx ,
rtx  
)
static
static rtx if_then_else_cond ( )
static
Return nonzero if X is an expression that has one of two values depending on
   whether some other value is zero or nonzero.  In that case, we return the
   value that is being tested, *PTRUE is set to the value if the rtx being
   returned has a nonzero value, and *PFALSE is set to the other alternative.

   If we return zero, we set *PTRUE and *PFALSE to X.   

References const_true_rtx, copy_rtx(), exact_log2(), gen_int_mode(), get_last_value(), HOST_WIDE_INT, if_then_else_cond(), nonzero_bits(), num_sign_bit_copies(), reversed_comparison_code(), rtx_equal_p(), side_effects_p(), simplify_gen_binary(), simplify_gen_relational(), simplify_gen_subreg(), simplify_gen_unary(), and swap_condition().

static void init_reg_last ( )
static
Wipe the last_xxx fields of reg_stat in preparation for another pass.   

References undo::i, memset(), and reg_stat.

Referenced by combine_instructions().

static bool insn_a_feeds_b ( )
static
Walk the LOG_LINKS of insn B to see if we find a reference to A.  Return
   true if we found a LOG_LINK that proves that A feeds B.  This only works
   if there are no instructions between A and B which could have a link
   depending on A, since in that case we would not record a link for B.
   We also check the implicit dependency created by a cc0 setter/user
   pair.   

References insn_link::insn, and sets_cc0_p().

Referenced by try_combine().

static rtx known_cond ( rtx  ,
enum  rtx_code,
rtx  ,
rtx   
)
static
static rtx known_cond ( )
static
Return the value of expression X given the fact that condition COND
   is known to be true when applied to REG as its first operand and VAL
   as its second.  X is known to not be shared and so can be modified in
   place.

   We only handle the simplest cases, and specifically those cases that
   arise with IF_THEN_ELSE expressions.   

References comparison_dominates_p(), const_true_rtx, known_cond(), reverse_condition(), reversed_comparison_code(), rtx_equal_p(), side_effects_p(), simplify_gen_unary(), simplify_subreg(), simplify_unary_operation(), and swap_condition().

static void likely_spilled_retval_1 ( )
static
Called via note_stores by likely_spilled_retval_p.  Remove from info->mask
   hard registers that are known to be written to / clobbered in full.   

References likely_spilled_retval_info::mask, likely_spilled_retval_info::nregs, and likely_spilled_retval_info::regno.

Referenced by likely_spilled_retval_p().

static int likely_spilled_retval_p ( )
static
Return nonzero iff part of the return value is live during INSN, and
   it is likely spilled.  This can happen when more than one insn is needed
   to copy the return value, e.g. when we consider to combine into the
   second copy insn for a complex value.   

References likely_spilled_retval_1(), likely_spilled_retval_info::mask, note_stores(), likely_spilled_retval_info::nregs, likely_spilled_retval_info::regno, targetm, and this_basic_block.

Referenced by try_combine().

rtx make_compound_operation ( )
Look at the expression rooted at X.  Look for expressions
   equivalent to ZERO_EXTRACT, SIGN_EXTRACT, ZERO_EXTEND, SIGN_EXTEND.
   Form these expressions.

   Return the new rtx, usually just X.

   Also, for machines like the VAX that don't have logical shift insns,
   try to convert logical to arithmetic shift operations in cases where
   they are equivalent.  This undoes the canonicalizations to logical
   shifts done elsewhere.

   We try, as much as possible, to re-use rtl expressions to save memory.

   IN_CODE says what kind of expression we are processing.  Normally, it is
   SET.  In a memory address (inside a MEM, PLUS or minus, the latter two
   being kludges), it is MEM.  When processing the arguments of a comparison
   or a COMPARE against zero, it is COMPARE.   

References count, exact_log2(), extract_left_shift(), force_to_mode(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, make_extraction(), nonzero_bits(), rtx_equal_p(), SET, simplify_const_unary_operation(), simplify_gen_binary(), simplify_gen_unary(), simplify_subreg(), subreg_lowpart_p(), swap_commutative_operands_p(), and trunc_int_for_mode().

Referenced by combine_simplify_rtx(), propagate_for_debug_subst(), simplify_comparison(), simplify_if_then_else(), and simplify_set().

static rtx make_extraction ( enum machine_mode  mode,
rtx  inner,
HOST_WIDE_INT  pos,
rtx  pos_rtx,
unsigned HOST_WIDE_INT  len,
int  unsignedp,
int  in_dest,
int  in_compare 
)
static
Return an RTX for a reference to LEN bits of INNER.  If POS_RTX is nonzero,
   it is an RTX that represents the (variable) starting position; otherwise,
   POS is the (constant) starting bit position.  Both are counted from the LSB.

   UNSIGNEDP is nonzero for an unsigned reference and zero for a signed one.

   IN_DEST is nonzero if this is a reference in the destination of a SET.
   This is used when a ZERO_ or SIGN_EXTRACT isn't needed.  If nonzero,
   a STRICT_LOW_PART will be used, if zero, ZERO_EXTEND or SIGN_EXTEND will
   be used.

   IN_COMPARE is nonzero if we are in a COMPARE.  This means that a
   ZERO_EXTRACT should be built even for bits starting at bit 0.

   MODE is the desired mode of the result (if IN_DEST == 0).

   The result is an RTX for the extraction or NULL_RTX if the target
   can't handle it.   

References EP_extv, EP_extzv, EP_insv, extraction_insn::field_mode, force_to_mode(), gen_rtx_SUBREG(), get_best_reg_extraction_insn(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, mode_dependent_address_p(), mode_for_size(), nonzero_bits(), offset, optimize_this_for_speed_p, extraction_insn::pos_mode, reg_truncated_to_mode(), set_src_cost(), simplify_gen_unary(), simplify_unary_operation(), smallest_mode_for_size(), extraction_insn::struct_mode, subreg_lowpart_p(), validate_subreg(), and word_mode.

Referenced by find_split_point(), make_compound_operation(), and make_field_assignment().

static rtx make_field_assignment ( rtx  )
static

Referenced by simplify_set().

static rtx make_field_assignment ( )
static
See if X, a SET operation, can be rewritten as a bit-field assignment.
   Return that assignment if so.

   We only handle the most common cases.   

References canon_reg_for_combine(), expand_compound_operation(), force_to_mode(), gen_int_mode(), get_pos_from_mask(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, len, make_extraction(), nonzero_bits(), rtx_equal_for_field_assignment_p(), simplify_shift_const(), and subreg_lowpart_p().

rtl_opt_pass* make_pass_combine ( )
static void mark_used_regs_combine ( rtx  )
static
static void mark_used_regs_combine ( )
static
Note hard registers in X that are used.   

References add_to_hard_reg_set(), mark_used_regs_combine(), newpat_used_regs, and SET.

static int merge_outer_ops ( enum rtx_code ,
HOST_WIDE_INT ,
enum  rtx_code,
HOST_WIDE_INT  ,
enum  machine_mode,
int *   
)
static

Referenced by simplify_shift_const_1().

static int merge_outer_ops ( )
static
This function is called from `simplify_shift_const' to merge two
   outer operations.  Specifically, we have already found that we need
   to perform operation *POP0 with constant *PCONST0 at the outermost
   position.  We would now like to also perform OP1 with constant CONST1
   (with *POP0 being done last).

   Return 1 if we can do the operation and update *POP0 and *PCONST0 with
   the resulting operation.  *PCOMP_P is set to 1 if we would need to
   complement the innermost operand, otherwise it is unchanged.

   MODE is the mode in which the operation will be done.  No bits outside
   the width of this mode matter.  It is assumed that the width of this mode
   is smaller than or equal to HOST_BITS_PER_WIDE_INT.

   If *POP0 or OP1 are UNKNOWN, it means no operation is required.  Only NEG, PLUS,
   IOR, XOR, and AND are supported.  We may set *POP0 to SET if the proper
   result is simply *PCONST0.

   If the resulting operation cannot be expressed as one operation, we
   return 0 and do not change *POP0, *PCONST0, and *PCOMP_P.   

References HOST_WIDE_INT, SET, and trunc_int_for_mode().

static void move_deaths ( rtx  x,
rtx  maybe_kill_insn,
int  from_luid,
rtx  to_insn,
rtx pnotes 
)
static
For each register (hardware or pseudo) used within expression X, if its
   death is in an instruction with luid between FROM_LUID (inclusive) and
   TO_INSN (exclusive), put a REG_DEAD note for that register in the
   list headed by PNOTES.

   That said, don't move registers killed by maybe_kill_insn.

   This is done when X is being merged by combination into TO_INSN.  These
   notes will then be distributed as needed.   

References add_reg_note(), alloc_reg_note(), len, offset, reg_referenced_p(), reg_set_p(), reg_stat, regno_reg_rtx, remove_death(), and SET.

Referenced by try_combine().

static int recog_for_combine ( rtx ,
rtx  ,
rtx  
)
static

Referenced by simplify_set(), and try_combine().

static int recog_for_combine ( )
static
Like recog, but we receive the address of a pointer to a new pattern.
   We try to match the rtx that the pointer points to.
   If that fails, we may try to modify or replace the pattern,
   storing the replacement into the same pointer object.

   Modifications include deletion or addition of CLOBBERs.

   PNOTES is a pointer to a location where any REG_UNUSED notes added for
   the CLOBBERs are placed.

   The value is the final insn code from the pattern ultimately matched,
   or -1.   

References add_clobbers(), alloc_reg_note(), check_asm_operands(), dump_file, dump_flags, insn_code_number, print_rtl_single(), recog(), reg_dead_at_p(), rtvec_alloc(), SET, set_noop_p(), and targetm.

static void record_dead_and_set_regs ( rtx  )
static

Referenced by combine_instructions().

static void record_dead_and_set_regs ( )
static
Update the records of when each REG was most recently set or killed
   for the things done by INSN.  This is the last thing done in processing
   INSN in the combiner loop.

   We update reg_stat[], in particular fields last_set, last_set_value,
   last_set_mode, last_set_nonzero_bits, last_set_sign_bit_copies,
   last_death, and also the similar information mem_last_set (which insn
   most recently modified memory) and last_call_luid (which insn was the
   most recent subroutine call).   

References last_call_luid, reg_stat_struct::last_death, reg_stat_struct::last_set, reg_stat_struct::last_set_nonzero_bits, reg_stat_struct::last_set_sign_bit_copies, reg_stat_struct::last_set_value, mem_last_set, note_stores(), record_dead_and_set_regs_1(), record_value_for_reg(), and reg_stat.

static void record_dead_and_set_regs_1 ( rtx  ,
const_rtx  ,
void *   
)
static
static void record_dead_and_set_regs_1 ( )
static
Called via note_stores from record_dead_and_set_regs to handle one
   SET or CLOBBER in an insn.  DATA is the instruction in which the
   set is occurring.   

References mem_last_set, push_operand(), record_value_for_reg(), SET, and subreg_lowpart_p().

static void record_promoted_value ( rtx  ,
rtx   
)
static

Referenced by check_promoted_subreg().

static void record_promoted_value ( )
static
If a SUBREG has the promoted bit set, it is in fact a property of the
   register present in the SUBREG, so for each such SUBREG go back and
   adjust nonzero and sign bit information of the registers that are
   known to have some zero/sign bits set.

   This is needed because when combine blows the SUBREGs away, the
   information on zero/sign bits is lost and further combines can be
   missed because of that.   

References HOST_BITS_PER_WIDE_INT, insn_link::insn, reg_stat_struct::last_set, reg_stat_struct::last_set_nonzero_bits, insn_link::next, and reg_stat.

static int record_truncated_value ( rtx ,
void *   
)
static

Referenced by record_truncated_values().

static int record_truncated_value ( )
static
Callback for for_each_rtx.  If *P is a hard reg or a subreg record the mode
   that the register is accessed in.  For non-TRULY_NOOP_TRUNCATION targets we
   might be able to turn a truncate into a subreg using this information.
   Return -1 if traversing *P is complete or 0 otherwise.   

References label_tick, label_tick_ebb_start, and reg_stat.

static void record_truncated_values ( rtx ,
void *   
)
static

Referenced by combine_instructions().

static void record_truncated_values ( )
static
Callback for note_uses.  Find hardregs and subregs of pseudos and
   the modes they are used in.  This can help truning TRUNCATEs into
   SUBREGs.   

References for_each_rtx(), and record_truncated_value().

static void record_value_for_reg ( rtx  ,
rtx  ,
rtx   
)
static
static void record_value_for_reg ( )
static
Record that REG is set to VALUE in insn INSN.  If VALUE is zero, we
   are saying that the register is clobbered and we no longer know its
   value.  If INSN is zero, don't update reg_stat[].last_set; this is
   only permitted with VALUE also zero and is used to invalidate the
   register.   

References copy_rtx(), count_occurrences(), count_rtxs(), get_last_value(), get_last_value_validate(), label_tick, label_tick_ebb_start, reg_stat_struct::last_death, reg_stat_struct::last_set, reg_stat_struct::last_set_label, reg_stat_struct::last_set_nonzero_bits, reg_stat_struct::last_set_sign_bit_copies, reg_stat_struct::last_set_table_tick, reg_stat_struct::last_set_value, nonzero_bits(), nonzero_bits_mode, num_sign_bit_copies(), reg_overlap_mentioned_p(), reg_stat, replace_rtx(), subst_low_luid, and update_table_tick().

static int reg_bitfield_target_p ( rtx  ,
rtx   
)
static
static int reg_bitfield_target_p ( )
static
Return 1 if X is the target of a bit-field assignment in BODY, the
   pattern of an insn.  X must be a REG.   

References end_hard_regno(), reg_bitfield_target_p(), and SET.

static int reg_dead_at_p ( rtx  ,
rtx   
)
static

Referenced by recog_for_combine().

static int reg_dead_at_p ( )
static
Return nonzero if REG is known to be dead at INSN.

   We scan backwards from INSN.  If we hit a REG_DEAD note or a CLOBBER
   referencing REG, it is dead.  If we hit a SET referencing REG, it is
   live.  Otherwise, see if it is live or dead at the start of the basic
   block we are in.  Hard regs marked as being live in NEWPAT_USED_REGS
   must be assumed to be always live.   

References df_get_live_in(), find_regno_note(), newpat_used_regs, note_stores(), reg_dead_at_p_1(), reg_dead_endregno, reg_dead_flag, and reg_dead_regno.

static void reg_dead_at_p_1 ( rtx  ,
const_rtx  ,
void *   
)
static

Referenced by reg_dead_at_p().

static void reg_dead_at_p_1 ( )
static
Function called via note_stores from reg_dead_at_p.

   If DEST is within [reg_dead_regno, reg_dead_endregno), set
   reg_dead_flag to 1 if X is a CLOBBER and to -1 it is a SET.   

References reg_dead_endregno, reg_dead_flag, and reg_dead_regno.

static rtx reg_nonzero_bits_for_combine ( const_rtx  x,
enum machine_mode  mode,
const_rtx  known_x,
enum machine_mode  known_mode,
unsigned HOST_WIDE_INT  known_ret,
unsigned HOST_WIDE_INT nonzero 
)
static
Given a REG, X, compute which bits in X can be nonzero.
   We don't care about bits outside of those defined in MODE.

   For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
   a shift, AND, or zero_extract, we can do better.   

References get_last_value(), HOST_WIDE_INT, label_tick, label_tick_ebb_start, reg_stat_struct::last_set, reg_stat_struct::last_set_label, reg_stat_struct::last_set_nonzero_bits, reg_stat_struct::last_set_value, nonzero_sign_valid, REG_N_SETS(), reg_stat, subst_low_luid, and val_signbit_known_set_p().

static rtx reg_num_sign_bit_copies_for_combine ( const_rtx  x,
enum machine_mode  mode,
const_rtx  known_x,
enum machine_mode  known_mode,
unsigned int  known_ret,
unsigned int *  result 
)
static
Return the number of bits at the high-order end of X that are known to
   be equal to the sign bit.  X will be used in mode MODE; if MODE is
   VOIDmode, X will be used in its own mode.  The returned value  will always
   be between 1 and the number of bits in MODE.   

References get_last_value(), label_tick, label_tick_ebb_start, reg_stat_struct::last_set, reg_stat_struct::last_set_label, reg_stat_struct::last_set_sign_bit_copies, reg_stat_struct::last_set_value, nonzero_sign_valid, REG_N_SETS(), reg_stat, and subst_low_luid.

static bool reg_subword_p ( )
static
Check whether X, the destination of a set, refers to part of
   the register specified by REG.   

Referenced by try_combine().

static bool reg_truncated_to_mode ( enum  machine_mode,
const_rtx   
)
static
static bool reg_truncated_to_mode ( )
static
Check if X, a register, is known to contain a value already
   truncated to MODE.  In this case we can use a subreg to refer to
   the truncated value even though in the generic case we would need
   an explicit truncation.   

References label_tick_ebb_start, and reg_stat.

rtx remove_death ( )
Remove register number REGNO from the dead registers list of INSN.

   Return the note used to record the death, if there was one.   

References find_regno_note(), and remove_note().

Referenced by fixup_match_2(), move_deaths(), and update_equiv_regs().

static int rtx_equal_for_field_assignment_p ( rtx  ,
rtx   
)
static

Referenced by make_field_assignment().

static int rtx_equal_for_field_assignment_p ( )
static
See if X and Y are equal for the purposes of seeing if we can rewrite an
   assignment as a field assignment.   

References rtx_equal_p().

static void set_nonzero_bits_and_sign_copies ( rtx  ,
const_rtx  ,
void *   
)
static
static void set_nonzero_bits_and_sign_copies ( )
static
Called via note_stores.  If X is a pseudo that is narrower than
   HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero.

   If we are setting only a portion of X and we can't figure out what
   portion, assume all bits will be used since we don't know what will
   be happening.

   Similarly, set how many bits of X are known to be copies of the sign bit
   at all locations in the function.  This is the smallest number implied
   by any set of X.   

References dead_or_set_p(), expand_field_assignment(), HOST_WIDE_INT, insn_link::insn, nonzero_bits(), nonzero_bits_mode, num_sign_bit_copies(), paradoxical_subreg_p(), reg_referenced_p(), reg_stat, and val_signbit_known_set_p().

static void setup_incoming_promotions ( rtx  )
static

Referenced by combine_instructions().

static void setup_incoming_promotions ( )
static
Set up any promoted values for incoming argument registers.   

References cfun, cgraph_local_info(), current_function_decl, function::decl, cgraph_local_info::local, promote_function_mode(), and record_value_for_reg().

static rtx simplify_and_const_int ( rtx  x,
enum machine_mode  mode,
rtx  varop,
unsigned HOST_WIDE_INT  constop 
)
static
We have X, a logical `and' of VAROP with the constant CONSTOP, to be done
   in MODE.

   Return an equivalent form, if different from X.  Otherwise, return X.  If
   X is zero, we are to always construct the equivalent form.   

References gen_int_mode(), simplify_and_const_int_1(), and simplify_gen_binary().

Referenced by combine_simplify_rtx(), expand_compound_operation(), force_to_mode(), simplify_and_const_int_1(), simplify_comparison(), simplify_logical(), and simplify_shift_const_1().

static rtx simplify_and_const_int_1 ( enum machine_mode  mode,
rtx  varop,
unsigned HOST_WIDE_INT  constop 
)
static
Simplify a logical `and' of VAROP with the constant CONSTOP, to be done
   in MODE.  Return an equivalent form, if different from (and VAROP
   (const_int CONSTOP)).  Otherwise, return NULL_RTX.   

References apply_distributive_law(), exact_log2(), force_to_mode(), gen_int_mode(), HOST_WIDE_INT, nonzero_bits(), simplify_and_const_int(), simplify_gen_binary(), and simplify_shift_const().

Referenced by simplify_and_const_int().

static enum rtx_code simplify_compare_const ( enum  rtx_code,
rtx  ,
rtx  
)
static

Referenced by simplify_comparison(), and try_combine().

static enum rtx_code simplify_compare_const ( )
static
Try to simplify a comparison between OP0 and a constant OP1,
   where CODE is the comparison code that will be tested, into a
   (CODE OP0 const0_rtx) form.

   The result is a possibly different comparison code to use.
   *POP1 may be updated.   

References exact_log2(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, nonzero_bits(), num_sign_bit_copies(), and trunc_int_for_mode().

static enum rtx_code simplify_comparison ( enum  rtx_code,
rtx ,
rtx  
)
static
static enum rtx_code simplify_comparison ( )
static
Simplify a comparison between *POP0 and *POP1 where CODE is the
   comparison code that will be tested.

   The result is a possibly different comparison code to use.  *POP0 and
   *POP1 may be updated.

   It is possible that we might detect that a comparison is either always
   true or always false.  However, we do not perform general constant
   folding in combine, so this knowledge isn't useful.  Such tautologies
   should have been detected earlier.  Hence we ignore all such cases.   

References changed, exact_log2(), expand_compound_operation(), force_to_mode(), gen_int_mode(), get_last_value(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, make_compound_operation(), mode_for_size(), nonzero_bits(), num_sign_bit_copies(), paradoxical_subreg_p(), reg_truncated_to_mode(), reverse_condition(), reversed_comparison_code(), rtx_equal_p(), SET, simplify_and_const_int(), simplify_binary_operation(), simplify_compare_const(), simplify_gen_binary(), simplify_gen_unary(), simplify_shift_const(), simplify_unary_operation(), subreg_lowpart_p(), swap_commutative_operands_p(), swap_condition(), target_canonicalize_comparison(), trunc_int_for_mode(), unsigned_condition(), and val_signbit_known_set_p().

static rtx simplify_if_then_else ( rtx  )
static

Referenced by combine_simplify_rtx().

static rtx simplify_logical ( rtx  )
static

Referenced by combine_simplify_rtx().

static rtx simplify_logical ( )
static
Simplify, X, and AND, IOR, or XOR operation, and return the simplified
   result.   

References distribute_and_simplify_rtx(), and simplify_and_const_int().

static rtx simplify_set ( rtx  )
static

Referenced by combine_simplify_rtx().

static rtx simplify_shift_const ( rtx  x,
enum rtx_code  code,
enum machine_mode  result_mode,
rtx  varop,
int  count 
)
static
Simplify a shift of VAROP by COUNT bits.  CODE says what kind of shift.
   The result of the shift is RESULT_MODE.  If we cannot simplify it,
   return X or, if it is NULL, synthesize the expression with
   simplify_gen_binary.  Otherwise, return a simplified value.

   The shift is normally computed in the widest mode we find in VAROP, as
   long as it isn't a different number of words than RESULT_MODE.  Exceptions
   are ASHIFTRT and ROTATE, which are always done in their original mode.   

References simplify_gen_binary(), and simplify_shift_const_1().

Referenced by combine_simplify_rtx(), expand_compound_operation(), extract_left_shift(), force_to_mode(), make_field_assignment(), simplify_and_const_int_1(), simplify_comparison(), simplify_if_then_else(), and simplify_shift_const_1().

static rtx simplify_shift_const_1 ( enum rtx_code  code,
enum machine_mode  result_mode,
rtx  varop,
int  orig_count 
)
static
Simplify a shift of VAROP by ORIG_COUNT bits.  CODE says what kind
   of shift.  The result of the shift is RESULT_MODE.  Return NULL_RTX
   if we cannot simplify it.  Otherwise, return a simplified value.

   The shift is normally computed in the widest mode we find in VAROP, as
   long as it isn't a different number of words than RESULT_MODE.  Exceptions
   are ASHIFTRT and ROTATE, which are always done in their original mode.   

References apply_distributive_law(), count, exact_log2(), expand_compound_operation(), gen_lowpart_or_truncate(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, mask_rtx(), merge_outer_ops(), mode_dependent_address_p(), mode_for_size(), mode_signbit_p(), nonzero_bits(), num_sign_bit_copies(), rtx_equal_p(), RTX_UNARY, SET, side_effects_p(), simplify_and_const_int(), simplify_const_binary_operation(), simplify_gen_binary(), simplify_gen_unary(), simplify_shift_const(), subreg_lowpart_p(), trunc_int_for_mode(), try_widen_shift_mode(), and val_signbit_known_clear_p().

Referenced by simplify_shift_const().

static rtx subst ( )
static
Throughout X, replace FROM with TO, and return the result.
   The result is TO if X is FROM;
   otherwise the result is X, but its contents may have been modified.
   If they were modified, a record was made in undobuf so that
   undo_all will (among other things) return X to its original state.

   If the number of changes necessary is too much to record to undo,
   the excess changes are not made, so the result is invalid.
   The changes already made can still be undone.
   undobuf.num_undo is incremented for such changes, so by testing that
   the caller can tell whether the result is valid.

   `n_occurrences' is incremented each time FROM is replaced.

   IN_DEST is nonzero if we are processing the SET_DEST of a SET.

   IN_COND is nonzero if we are at the top level of a condition.

   UNIQUE_COPY is nonzero if each substitution must be unique.  We do this
   by copying if `n_occurrences' is nonzero.   
Two expressions are equal if they are identical copies of a shared
   RTX or if they are both registers with the same register number
   and mode.   

References avoid_constant_pool_reference(), cc0_rtx, combine_simplify_rtx(), copy_rtx(), undo::i, len, n_occurrences, reg_overlap_mentioned_p(), SET, simplify_subreg(), simplify_unary_operation(), and subst().

static void target_canonicalize_comparison ( enum rtx_code code,
rtx op0,
rtx op1,
bool  op0_preserve_value 
)
inlinestatic
Convenience wrapper for the canonicalize_comparison target hook.
   Target hooks cannot use enum rtx_code.   

References targetm.

Referenced by simplify_comparison(), and try_combine().

static rtx try_combine ( rtx  i3,
rtx  i2,
rtx  i1,
rtx  i0,
int *  new_direct_jump_p,
rtx  last_combined_insn 
)
static
Try to combine the insns I0, I1 and I2 into I3.
   Here I0, I1 and I2 appear earlier than I3.
   I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into
   I3.

   If we are combining more than two insns and the resulting insn is not
   recognized, try splitting it into two insns.  If that happens, I2 and I3
   are retained and I1/I0 are pseudo-deleted by turning them into a NOTE.
   Otherwise, I0, I1 and I2 are pseudo-deleted.

   Return 0 if the combination does not work.  Then nothing is changed.
   If we did the combination, return the insn at which combine should
   resume scanning.

   Set NEW_DIRECT_JUMP_P to a nonzero value if try_combine creates a
   new direct jump instruction.

   LAST_COMBINED_INSN is either I3, or some insn after I3 that has
   been I3 passed to an earlier try_combine within the same basic
   block.   

References added_links_insn, adjust_for_new_dest(), adjust_reg_mode(), alloc_insn_link(), alloc_reg_note(), double_int::and_not(), any_uncondjump_p(), asm_noperands(), can_change_dest_mode(), can_combine_p(), cant_combine_insn_p(), cc0_rtx, check_asm_operands(), combinable_i3pat(), combine_attempts, combine_extras, combine_merges, combine_split_insns(), combine_successes, combine_validate_cost(), contains_muldiv(), copy_rtx(), copy_rtx_if_shared(), dead_or_set_p(), df_insn_rescan(), distribute_links(), distribute_notes(), dump_file, dump_flags, dump_insn_slim(), rtvec_def::elem, exact_log2(), find_reg_note(), find_single_use(), find_split_point(), first, undobuf::frees, gen_raw_REG(), gen_rtvec(), gen_rtx_REG(), HOST_BITS_PER_INT, i1, i2, immed_double_int_const(), insn_link::insn, insn_a_feeds_b(), insn_code_number, insn_nothrow_p(), undo::kind, last, len, likely_spilled_retval_p(), double_int::llshift(), lowpart_subreg(), undo::m, mark_jump_label(), mark_used_regs_combine(), double_int::mask(), max_reg_num(), memcpy(), move_deaths(), n_occurrences, new_mode(), newpat_used_regs, undo::next, next_active_insn(), basic_block_def::next_bb, next_nonnote_nondebug_insn(), nonzero_bits(), note_stores(), rtvec_def::num_elem, offset, undo::old_contents, undobuf::other_insn, pc_rtx, prev_nonnote_insn(), propagate_for_debug(), undo::r, recog_for_combine(), record_value_for_reg(), reg_mentioned_p(), reg_overlap_mentioned_p(), reg_referenced_p(), reg_set_p(), reg_stat, reg_subword_p(), reg_used_between_p(), regno_reg_rtx, remove_note(), replace_rtx(), reset_used_flags(), returnjump_p(), rtvec_alloc(), rtx_equal_p(), rtx_to_double_int(), SET, set_nonzero_bits_and_sign_copies(), sets_cc0_p(), side_effects_p(), simplify_compare_const(), simplify_gen_binary(), subreg_lowpart_p(), subst(), subst_insn, subst_low_luid, target_canonicalize_comparison(), targetm, this_basic_block, undo_all(), undo_commit(), UNDO_MODE, undobuf::undos, update_cfg_for_uncondjump(), use_crosses_set_p(), undo::where, and word_mode.

Referenced by combine_instructions().

static enum machine_mode try_widen_shift_mode ( enum rtx_code  code,
rtx  op,
int  count,
enum machine_mode  orig_mode,
enum machine_mode  mode,
enum rtx_code  outer_code,
HOST_WIDE_INT  outer_const 
)
static
A helper to simplify_shift_const_1 to determine the mode we can perform
   the shift in.  The original shift operation CODE is performed on OP in
   ORIG_MODE.  Return the wider mode MODE if we can perform the operation
   in that mode.  Return ORIG_MODE otherwise.  We can also assume that the
   result of the shift is subject to operation OUTER_CODE with operand
   OUTER_CONST.   

References low_bitmask_len(), nonzero_bits(), and num_sign_bit_copies().

Referenced by simplify_shift_const_1().

static void undo_all ( )
static
static void undo_commit ( )
static
We've committed to accepting the changes we made.  Move all
   of the undos to the free list.   

References undobuf::frees, undo::next, and undobuf::undos.

Referenced by try_combine().

static bool unmentioned_reg_p ( rtx  ,
rtx   
)
static

Referenced by combine_instructions().

static bool unmentioned_reg_p ( )
static
Check for any register or memory mentioned in EQUIV that is not
   mentioned in EXPR.  This is used to restrict EQUIV to "specializations"
   of EXPR where some registers may have been replaced by constants.   

References for_each_rtx(), and unmentioned_reg_p_1().

static int unmentioned_reg_p_1 ( rtx ,
void *   
)
static

Referenced by unmentioned_reg_p().

static int unmentioned_reg_p_1 ( )
static
Subroutine of unmentioned_reg_p and callback from for_each_rtx.
   Check whether the expression pointer to by LOC is a register or
   memory, and if so return 1 if it isn't mentioned in the rtx EXPR.
   Otherwise return zero.   

References reg_mentioned_p().

static void update_cfg_for_uncondjump ( )
static
Delete the unconditional jump INSN and adjust the CFG correspondingly.
   Note that the INSN should be deleted *after* removing dead edges, so
   that the kept edge is the fallthrough edge for a (set (pc) (pc))
   but not for a (set (pc) (label_ref FOO)).   

References delete_insn(), edge_def::flags, purge_dead_edges(), single_succ_edge(), and basic_block_def::succs.

Referenced by try_combine().

static void update_table_tick ( rtx  )
static
static void update_table_tick ( )
static
Utility function for following routine.  Called when X is part of a value
   being stored into last_set_value.  Sets last_set_table_tick
   for each register mentioned.  Similar to mention_regs in cse.c   

References label_tick, reg_stat_struct::last_set_table_tick, reg_stat, and update_table_tick().

static int use_crosses_set_p ( const_rtx  ,
int   
)
static
static int use_crosses_set_p ( )
static
Return nonzero if expression X refers to a REG or to memory
   that is set in an instruction more recent than FROM_LUID.   

References label_tick, reg_stat_struct::last_set, reg_stat_struct::last_set_label, mem_last_set, reg_stat, and use_crosses_set_p().


Variable Documentation

rtx added_links_insn
static
This is an insn to which a LOG_LINKS entry has been added.  If this
   insn is the earlier than I2 or I3, combine should rescan starting at
   that location.   

Referenced by distribute_links(), and try_combine().

int combine_attempts
static
@verbatim Optimize by combining instructions for GNU compiler.

Copyright (C) 1987-2013 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 module is essentially the "combiner" phase of the U. of Arizona
   Portable Optimizer, but redone to work on our list-structured
   representation for RTL instead of their string representation.

   The LOG_LINKS of each insn identify the most recent assignment
   to each REG used in the insn.  It is a list of previous insns,
   each of which contains a SET for a REG that is used in this insn
   and not used or set in between.  LOG_LINKs never cross basic blocks.
   They were set up by the preceding pass (lifetime analysis).

   We try to combine each pair of insns joined by a logical link.
   We also try to combine triplets of insns A, B and C when C has
   a link back to B and B has a link back to A.  Likewise for a
   small number of quadruplets of insns A, B, C and D for which
   there's high likelihood of of success.

   LOG_LINKS does not have links for use of the CC0.  They don't
   need to, because the insn that sets the CC0 is always immediately
   before the insn that tests it.  So we always regard a branch
   insn as having a logical link to the preceding insn.  The same is true
   for an insn explicitly using CC0.

   We check (with use_crosses_set_p) to avoid combining in such a way
   as to move a computation to a place where its value would be different.

   Combination is done by mathematically substituting the previous
   insn(s) values for the regs they set into the expressions in
   the later insns that refer to these regs.  If the result is a valid insn
   for our target machine, according to the machine description,
   we install it, delete the earlier insns, and update the data flow
   information (LOG_LINKS and REG_NOTES) for what we did.

   There are a few exceptions where the dataflow information isn't
   completely updated (however this is only a local issue since it is
   regenerated before the next pass that uses it):

   - reg_live_length is not updated
   - reg_n_refs is not adjusted in the rare case when a register is
     no longer required in a computation
   - there are extremely rare cases (see distribute_notes) when a
     REG_DEAD note is lost
   - a LOG_LINKS entry that refers to an insn with multiple SETs may be
     removed because there is no way to know which register it was
     linking

   To simplify substitution, we combine only when the earlier insn(s)
   consist of only a single assignment.  To simplify updating afterward,
   we never combine when a subroutine call appears in the middle.

   Since we do not represent assignments to CC0 explicitly except when that
   is all an insn does, there is no LOG_LINKS entry in an insn that uses
   the condition code for the insn that set the condition code.
   Fortunately, these two insns must be consecutive.
   Therefore, every JUMP_INSN is taken to have an implicit logical link
   to the preceding insn.  This is not quite right, since non-jumps can
   also use the condition code; but in practice such insns would not
   combine anyway.   
Include expr.h after insn-config.h so we get HAVE_conditional_move.   
Number of attempts to combine instructions in this function.   

Referenced by combine_instructions(), dump_combine_stats(), and try_combine().

int combine_extras
static
Number of instructions combined with added SETs in this function.   

Referenced by combine_instructions(), dump_combine_stats(), and try_combine().

int combine_merges
static
Number of attempts that got as far as substitution in this function.   

Referenced by combine_instructions(), dump_combine_stats(), and try_combine().

struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER
static

Referenced by combine_instructions().

int combine_successes
static
Number of instructions combined in this function.   

Referenced by combine_instructions(), dump_combine_stats(), and try_combine().

rtx i2mod
static
combine_instructions may try to replace the right hand side of the
   second instruction with the value of an associated REG_EQUAL note
   before throwing it at try_combine.  That is problematic when there
   is a REG_DEAD note for a register used in the old right hand side
   and can cause distribute_notes to do wrong things.  This is the
   second instruction if it has been so modified, null otherwise.   

Referenced by combine_instructions(), and distribute_notes().

rtx i2mod_new_rhs
static
When I2MOD is nonnull, this is a copy of the new right hand side.   

Referenced by combine_instructions(), and distribute_notes().

rtx i2mod_old_rhs
static
When I2MOD is nonnull, this is a copy of the old right hand side.   

Referenced by combine_instructions(), and distribute_notes().

struct obstack insn_link_obstack
static
Links for LOG_LINKS are allocated from this obstack.   

Referenced by alloc_insn_link(), and combine_instructions().

int label_tick_ebb_start
static
int last_call_luid
static
Record the luid of the last CALL_INSN
   so we can tell whether a potential combination crosses any calls.   

Referenced by can_combine_p(), combine_instructions(), and record_dead_and_set_regs().

int max_uid_known
static
Length of the currently allocated uid_insn_cost array.   

Referenced by combine_instructions().

int mem_last_set
static
Record the luid of the last insn that invalidated memory
   (anything that writes memory, and subroutine calls, but not pushes).   

Referenced by combine_instructions(), get_last_value_validate(), record_dead_and_set_regs(), record_dead_and_set_regs_1(), and use_crosses_set_p().

int n_occurrences
static
Number of times the pseudo being substituted for
   was found and replaced.   

Referenced by check_operand_nalternatives(), delete_output_reload(), scan_operands(), subst(), and try_combine().

HARD_REG_SET newpat_used_regs
static
This contains any hard registers that are used in newpat; reg_dead_at_p
   must consider all these registers to be always live.   

Referenced by mark_used_regs_combine(), reg_dead_at_p(), and try_combine().

enum machine_mode nonzero_bits_mode
static
Mode used to compute significance in reg_stat[].nonzero_bits.  It is the
   largest integer mode that can fit in HOST_BITS_PER_WIDE_INT.   

Referenced by combine_instructions(), record_value_for_reg(), and set_nonzero_bits_and_sign_copies().

int nonzero_sign_valid
static
Nonzero when reg_stat[].nonzero_bits and reg_stat[].sign_bit_copies can
   be safely used.  It is zero while computing them and after combine has
   completed.  This former test prevents propagating values based on
   previously set values, which can be incorrect if a variable is modified
   in a loop.   

Referenced by combine_instructions(), expand_field_assignment(), extended_count(), reg_nonzero_bits_for_combine(), and reg_num_sign_bit_copies_for_combine().

unsigned int reg_dead_endregno
static

Referenced by reg_dead_at_p(), and reg_dead_at_p_1().

int reg_dead_flag
static

Referenced by reg_dead_at_p(), and reg_dead_at_p_1().

unsigned int reg_dead_regno
static
Define three variables used for communication between the following
   routines.   

Referenced by reg_dead_at_p(), and reg_dead_at_p_1().

rtx subst_insn
static
When `subst' is called, this is the insn that is being modified
   (by combining in a previous insn).  The PATTERN of this insn
   is still the old pattern partially modified and it should not be
   looked at, but this may be used to examine the successors of the insn
   to judge whether a simplification is valid.   

Referenced by combine_instructions(), find_split_point(), simplify_set(), and try_combine().

int subst_low_luid
static
This is the lowest LUID that `subst' is currently dealing with.
   get_last_value will not return a value if the register was set at or
   after this LUID.  If not for this mechanism, we could get confused if
   I2 or I1 in try_combine were an insn that used the old value of a register
   to obtain a new value.  In that case, we might erroneously get the
   new value of the register when we wanted the old one.   

Referenced by can_combine_p(), combine_instructions(), get_last_value(), record_value_for_reg(), reg_nonzero_bits_for_combine(), reg_num_sign_bit_copies_for_combine(), and try_combine().

basic_block this_basic_block
static
Basic block in which we are performing combines.   

Referenced by combine_instructions(), distribute_links(), distribute_notes(), likely_spilled_retval_p(), and try_combine().

int total_attempts
static
Totals over entire compilation.   

Referenced by combine_instructions(), and dump_combine_total_stats().

int total_extras
static
int total_merges
static
int total_successes
static
int* uid_insn_cost
static
The following array records the insn_rtx_cost for every insn
   in the instruction stream.   

Referenced by combine_instructions().

struct insn_link** uid_log_links
static

Referenced by combine_instructions().

struct undobuf undobuf
static