GCC Middle and Back End API Reference
combine.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "cfghooks.h"
#include "predict.h"
#include "df.h"
#include "memmodel.h"
#include "tm_p.h"
#include "optabs.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
#include "cgraph.h"
#include "stor-layout.h"
#include "cfgrtl.h"
#include "cfgcleanup.h"
#include "explow.h"
#include "insn-attr.h"
#include "rtlhooks-def.h"
#include "expr.h"
#include "tree-pass.h"
#include "valtrack.h"
#include "rtl-iter.h"
#include "print-rtl.h"
#include "function-abi.h"
#include "rtlanal.h"
Include dependency graph for combine.cc:

Data Structures

struct  reg_stat_type
 
struct  insn_link
 
struct  undo
 
struct  undobuf
 
struct  likely_spilled_retval_info
 

Macros

#define INSN_COST(INSN)   (uid_insn_cost[insn_uid_check (INSN)])
 
#define LOG_LINKS(INSN)   (uid_log_links[insn_uid_check (INSN)])
 
#define FOR_EACH_LOG_LINK(L, INSN)    for ((L) = LOG_LINKS (INSN); (L); (L) = (L)->next)
 
#define RTL_HOOKS_GEN_LOWPART   gen_lowpart_for_combine
 
#define RTL_HOOKS_GEN_LOWPART_NO_EMIT   gen_lowpart_for_combine
 
#define RTL_HOOKS_REG_NONZERO_REG_BITS   reg_nonzero_bits_for_combine
 
#define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES   reg_num_sign_bit_copies_for_combine
 
#define RTL_HOOKS_REG_TRUNCATED_TO_MODE   reg_truncated_to_mode
 
#define SUBST(INTO, NEWVAL)   do_SUBST (&(INTO), (NEWVAL))
 
#define SUBST_INT(INTO, NEWVAL)   do_SUBST_INT (&(INTO), (NEWVAL))
 
#define SUBST_LINK(oldval, newval)   do_SUBST_LINK (&oldval, newval)
 
#define COMBINE_RTX_EQUAL_P(X, Y)
 

Enumerations

enum  undo_kind { UNDO_RTX , UNDO_INT , UNDO_MODE , UNDO_LINKS }
 

Functions

static int insn_uid_check (const_rtx insn)
 
static struct insn_linkalloc_insn_link (rtx_insn *insn, unsigned int regno, struct insn_link *next)
 
static rtx reg_nonzero_bits_for_combine (const_rtx, scalar_int_mode, scalar_int_mode, unsigned HOST_WIDE_INT *)
 
static rtx reg_num_sign_bit_copies_for_combine (const_rtx, scalar_int_mode, scalar_int_mode, 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_insn *)
 
static void set_nonzero_bits_and_sign_copies (rtx, const_rtx, void *)
 
static bool cant_combine_insn_p (rtx_insn *)
 
static bool can_combine_p (rtx_insn *, rtx_insn *, rtx_insn *, rtx_insn *, rtx_insn *, rtx_insn *, rtx *, rtx *)
 
static bool combinable_i3pat (rtx_insn *, rtx *, rtx, rtx, rtx, bool, bool, rtx *)
 
static bool contains_muldiv (rtx)
 
static rtx_insntry_combine (rtx_insn *, rtx_insn *, rtx_insn *, rtx_insn *, bool *, rtx_insn *)
 
static void undo_all (void)
 
static void undo_commit (void)
 
static rtxfind_split_point (rtx *, rtx_insn *, bool)
 
static rtx subst (rtx, rtx, rtx, bool, bool, bool)
 
static rtx combine_simplify_rtx (rtx, machine_mode, bool, bool)
 
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 (machine_mode, rtx, HOST_WIDE_INT, rtx, unsigned HOST_WIDE_INT, bool, bool, bool)
 
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_int_to_mode (rtx, scalar_int_mode, scalar_int_mode, scalar_int_mode, unsigned HOST_WIDE_INT, bool)
 
static rtx force_to_mode (rtx, machine_mode, unsigned HOST_WIDE_INT, bool)
 
static rtx if_then_else_cond (rtx, rtx *, rtx *)
 
static rtx known_cond (rtx, enum rtx_code, rtx, rtx)
 
static bool rtx_equal_for_field_assignment_p (rtx, rtx, bool=false)
 
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 (scalar_int_mode, rtx, unsigned HOST_WIDE_INT)
 
static rtx simplify_and_const_int (rtx, scalar_int_mode, rtx, unsigned HOST_WIDE_INT)
 
static bool merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code, HOST_WIDE_INT, machine_mode, bool *)
 
static rtx simplify_shift_const_1 (enum rtx_code, machine_mode, rtx, int)
 
static rtx simplify_shift_const (rtx, enum rtx_code, machine_mode, rtx, int)
 
static int recog_for_combine (rtx *, rtx_insn *, rtx *)
 
static rtx gen_lowpart_for_combine (machine_mode, rtx)
 
static enum rtx_code simplify_compare_const (enum rtx_code, machine_mode, 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_insn *, rtx)
 
static void check_promoted_subreg (rtx_insn *, rtx)
 
static void record_dead_and_set_regs_1 (rtx, const_rtx, void *)
 
static void record_dead_and_set_regs (rtx_insn *)
 
static bool get_last_value_validate (rtx *, rtx_insn *, int, bool)
 
static rtx get_last_value (const_rtx)
 
static void reg_dead_at_p_1 (rtx, const_rtx, void *)
 
static bool reg_dead_at_p (rtx, rtx_insn *)
 
static void move_deaths (rtx, rtx, int, rtx_insn *, rtx *)
 
static bool reg_bitfield_target_p (rtx, rtx)
 
static void distribute_notes (rtx, rtx_insn *, rtx_insn *, rtx_insn *, rtx, rtx, rtx)
 
static void distribute_links (struct insn_link *)
 
static void mark_used_regs_combine (rtx)
 
static void record_promoted_value (rtx_insn *, rtx)
 
static bool unmentioned_reg_p (rtx, rtx)
 
static void record_truncated_values (rtx *, void *)
 
static bool reg_truncated_to_mode (machine_mode, const_rtx)
 
static rtx gen_lowpart_or_truncate (machine_mode, rtx)
 
static void target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1, bool op0_preserve_value)
 
static rtx_insncombine_split_insns (rtx pattern, rtx_insn *insn)
 
static rtxfind_single_use_1 (rtx dest, rtx *loc)
 
static rtxfind_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc)
 
static void subst_mode (int regno, machine_mode newval)
 
static void do_SUBST_LINK (struct insn_link **into, struct insn_link *newval)
 
static bool combine_validate_cost (rtx_insn *i0, rtx_insn *i1, rtx_insn *i2, rtx_insn *i3, rtx newpat, rtx newi2pat, rtx newotherpat)
 
static bool delete_noop_moves (void)
 
static bool can_combine_def_p (df_ref def)
 
static bool can_combine_use_p (df_ref use)
 
static void create_log_links (void)
 
static bool insn_a_feeds_b (rtx_insn *a, rtx_insn *b)
 
static bool combine_instructions (rtx_insn *f, unsigned int nregs)
 
static rtx sign_extend_short_imm (rtx src, machine_mode mode, unsigned int prec)
 
static void update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, const_rtx set, rtx x)
 
static void likely_spilled_retval_1 (rtx x, const_rtx set, void *data)
 
static bool likely_spilled_retval_p (rtx_insn *insn)
 
static void adjust_for_new_dest (rtx_insn *insn)
 
static bool can_change_dest_mode (rtx x, bool added_sets, machine_mode mode)
 
static bool reg_subword_p (rtx x, rtx reg)
 
static bool is_parallel_of_n_reg_sets (rtx pat, int n)
 
static bool can_split_parallel_of_n_reg_sets (rtx_insn *insn, int n)
 
static bool is_just_move (rtx_insn *x)
 
static int count_auto_inc (rtx, rtx, rtx, rtx, rtx, void *arg)
 
static voidget_undo_marker (void)
 
static void undo_to_marker (void *marker)
 
static void maybe_swap_commutative_operands (rtx x)
 
static rtx extract_left_shift (scalar_int_mode mode, rtx x, int count)
 
static rtx make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr, enum rtx_code in_code, enum rtx_code *next_code_ptr)
 
rtx make_compound_operation (rtx x, enum rtx_code in_code)
 
unsigned int extended_count (const_rtx x, machine_mode mode, bool unsignedp)
 
static scalar_int_mode try_widen_shift_mode (enum rtx_code code, rtx op, int count, scalar_int_mode orig_mode, scalar_int_mode mode, enum rtx_code outer_code, HOST_WIDE_INT outer_const)
 
static int recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
 
static bool change_zero_ext (rtx pat)
 
static int count_rtxs (rtx x)
 
static bool record_truncated_value (rtx x)
 
rtx remove_death (unsigned int regno, rtx_insn *insn)
 
static void make_more_copies (void)
 
static void rest_of_handle_combine (void)
 
rtl_opt_passmake_pass_combine (gcc::context *ctxt)
 

Variables

static int combine_attempts
 
static int combine_merges
 
static int combine_extras
 
static int combine_successes
 
static rtx_insni2mod
 
static rtx i2mod_old_rhs
 
static rtx i2mod_new_rhs
 
static vec< reg_stat_typereg_stat
 
static unsigned int reg_n_sets_max
 
static int mem_last_set
 
static int last_call_luid
 
static rtx_insnsubst_insn
 
static int subst_low_luid
 
static HARD_REG_SET newpat_used_regs
 
static rtx_insnadded_links_insn
 
static rtx_insnadded_notes_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 scalar_int_mode nonzero_bits_mode
 
static int nonzero_sign_valid
 
static struct undobuf undobuf
 
static int n_occurrences
 
static const 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
 
rtx reg_dead_reg
 

Macro Definition Documentation

◆ COMBINE_RTX_EQUAL_P

#define COMBINE_RTX_EQUAL_P ( X,
Y )
Value:
((X) == (Y) \
|| (REG_P (X) && REG_P (Y) \
&& REGNO (X) == REGNO (Y) && GET_MODE (X) == GET_MODE (Y)))
#define Y
Definition gensupport.cc:203
T * ggc_alloc(ALONE_CXX_MEM_STAT_INFO)
Definition ggc.h:184
#define REGNO(RTX)
Definition rtl.h:1914
#define REG_P(X)
Definition rtl.h:746
#define GET_MODE(RTX)
Definition rtl.h:728

◆ FOR_EACH_LOG_LINK

◆ INSN_COST

#define INSN_COST ( INSN)    (uid_insn_cost[insn_uid_check (INSN)])

◆ LOG_LINKS

◆ RTL_HOOKS_GEN_LOWPART

#define RTL_HOOKS_GEN_LOWPART   gen_lowpart_for_combine
It is not safe to use ordinary gen_lowpart in combine.
See comments in gen_lowpart_for_combine.   

◆ RTL_HOOKS_GEN_LOWPART_NO_EMIT

#define RTL_HOOKS_GEN_LOWPART_NO_EMIT   gen_lowpart_for_combine
Our implementation of gen_lowpart never emits a new pseudo.   

◆ RTL_HOOKS_REG_NONZERO_REG_BITS

#define RTL_HOOKS_REG_NONZERO_REG_BITS   reg_nonzero_bits_for_combine

◆ RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES

#define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES   reg_num_sign_bit_copies_for_combine

◆ RTL_HOOKS_REG_TRUNCATED_TO_MODE

#define RTL_HOOKS_REG_TRUNCATED_TO_MODE   reg_truncated_to_mode

◆ SUBST

◆ SUBST_INT

#define SUBST_INT ( INTO,
NEWVAL )   do_SUBST_INT (&(INTO), (NEWVAL))

Referenced by recog_for_combine_1().

◆ SUBST_LINK

#define SUBST_LINK ( oldval,
newval )   do_SUBST_LINK (&oldval, newval)

Referenced by try_combine().

Enumeration Type Documentation

◆ 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

◆ adjust_for_new_dest()

static void adjust_for_new_dest ( rtx_insn * insn)
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(), gcc_assert, GET_CODE, ggc_alloc(), NULL, REG_P, REGNO, remove_reg_equal_equiv_notes(), SET_DEST, single_set(), and XEXP.

Referenced by try_combine().

◆ alloc_insn_link()

static struct insn_link * alloc_insn_link ( rtx_insn * insn,
unsigned int regno,
struct insn_link * next )
inlinestatic

◆ apply_distributive_law()

◆ can_change_dest_mode()

static bool can_change_dest_mode ( rtx x,
bool added_sets,
machine_mode mode )
static
Return TRUE if combine can reuse reg X in mode MODE.
ADDED_SETS is trueif the original set is still required.   

References GET_MODE, ggc_alloc(), hard_regno_nregs(), REG_N_SETS(), reg_n_sets_max, REG_NREGS, REG_P, REG_USERVAR_P, REGMODE_NATURAL_SIZE, likely_spilled_retval_info::regno, REGNO, and targetm.

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

◆ can_combine_def_p()

static bool can_combine_def_p ( df_ref def)
static

◆ can_combine_p()

static bool can_combine_p ( rtx_insn * insn,
rtx_insn * i3,
rtx_insn * pred,
rtx_insn * pred2,
rtx_insn * succ,
rtx_insn * 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 false 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 true.   

References AUTO_INC_DEC, bool, CALL_P, CONSTANT_P, DF_INSN_LUID, expand_field_assignment(), extract_asm_operands(), find_reg_fusage(), FIND_REG_INC_NOTE, find_reg_note(), fixed_regs, GET_CODE, GET_MODE, ggc_alloc(), global_regs, HARD_REGISTER_P, i, insn_link::insn, insn_nothrow_p(), INSN_P, INSN_UID(), JUMP_P, last_call_luid, MEM_P, MEM_VOLATILE_P, modified_between_p(), next_active_insn(), NEXT_INSN(), NULL_RTX, PATTERN(), PREV_INSN(), REG_NOTE_KIND, REG_NOTES, reg_overlap_mentioned_p(), REG_P, reg_set_between_p(), reg_used_between_p(), REG_USERVAR_P, insn_link::regno, REGNO, rtx_equal_p(), SET, SET_DEST, SET_SRC, side_effects_p(), stack_pointer_rtx, subst_low_luid, targetm, volatile_insn_p(), volatile_refs_p(), XEXP, XVECEXP, and XVECLEN.

Referenced by try_combine().

◆ can_combine_use_p()

static bool can_combine_use_p ( df_ref use)
static
Return false if we do not want to (or cannot) combine USE.   

References DF_REF_CALL_STACK_USAGE, and DF_REF_FLAGS.

Referenced by create_log_links().

◆ can_split_parallel_of_n_reg_sets()

static bool can_split_parallel_of_n_reg_sets ( rtx_insn * insn,
int n )
static
Return whether INSN, a PARALLEL of N register SETs (and maybe some
CLOBBERs), can be split into individual SETs in that order, without
changing semantics.   

References ggc_alloc(), i, insn_nothrow_p(), PATTERN(), reg_referenced_p(), SET_DEST, SET_SRC, side_effects_p(), and XVECEXP.

Referenced by try_combine().

◆ canon_reg_for_combine()

◆ cant_combine_insn_p()

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

References fixed_reg_set, GET_CODE, ggc_alloc(), HARD_REGISTER_P, insn_link::insn, NONDEBUG_INSN_P, REG_P, REGNO, SET_DEST, SET_SRC, single_set(), SUBREG_REG, targetm, and TEST_HARD_REG_BIT.

Referenced by try_combine().

◆ change_zero_ext()

static bool change_zero_ext ( rtx pat)
static

◆ check_promoted_subreg()

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

References check_promoted_subreg(), GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, insn_link::insn, record_promoted_value(), REG_P, SUBREG_PROMOTED_VAR_P, SUBREG_REG, XEXP, XVEC, XVECEXP, and XVECLEN.

Referenced by check_promoted_subreg(), and combine_instructions().

◆ combinable_i3pat()

static bool combinable_i3pat ( rtx_insn * i3,
rtx * loc,
rtx i2dest,
rtx i1dest,
rtx i0dest,
bool i1_not_in_src,
bool 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 true if the combination is valid, false otherwise.   

References combinable_i3pat(), fixed_regs, GET_CODE, GET_MODE, ggc_alloc(), HARD_FRAME_POINTER_IS_FRAME_POINTER, HARD_FRAME_POINTER_REGNUM, i, MEM_P, partial_subreg_p(), PATTERN(), reg_overlap_mentioned_p(), REG_P, reg_referenced_p(), REGNO, rtx_equal_p(), SET, SET_DEST, SET_SRC, SUBREG_REG, targetm, XEXP, XVECEXP, and XVECLEN.

Referenced by combinable_i3pat(), and try_combine().

◆ combine_instructions()

static bool combine_instructions ( rtx_insn * f,
unsigned int nregs )
static
Main entry point for combiner.  F is the first insn of the function.
NREGS is the first unused pseudo-reg number.

Return nonzero if the CFG was changed (e.g. if the combiner has
turned an indirect jump instruction into a direct jump).   

References AUTO_INC_DEC, BB_END, BB_HEAD, BLOCK_FOR_INSN(), cfun, check_promoted_subreg(), clear_bb_flags(), combine_attempts, combine_extras, combine_merges, combine_rtl_hooks, combine_successes, copy_rtx(), create_log_links(), default_rtl_profile(), delete_noop_moves(), DF_INSN_LUID, dump_file, dump_insn_slim(), EDGE_COUNT, ENTRY_BLOCK_PTR_FOR_FN, find_reg_equal_equiv_note(), FOR_BB_INSNS, FOR_EACH_BB_FN, FOR_EACH_LOG_LINK, free(), undobuf::frees, gcc_obstack_init, general_rtl_hooks, GET_CODE, get_max_uid(), GET_MODE, ggc_alloc(), HOST_BITS_PER_WIDE_INT, i2mod, i2mod_new_rhs, i2mod_old_rhs, init_recog(), init_recog_no_volatile(), init_reg_last(), insn_link::insn, INSN_CODE, INSN_COST, insn_cost(), insn_link_obstack, INSN_P, int_mode_for_size(), label_tick, label_tick_ebb_start, last_call_luid, max_uid_known, mem_last_set, insn_link::next, undo::next, NEXT_INSN(), NONDEBUG_INSN_P, nonzero_bits_mode, nonzero_sign_valid, NOTE_P, note_stores(), note_uses(), NULL, NULL_RTX, optimize_bb_for_speed_p(), optimize_this_for_speed_p, PATTERN(), basic_block_def::preds, PREV_INSN(), purge_all_dead_edges(), record_dead_and_set_regs(), record_truncated_values(), REG_NOTE_KIND, REG_NOTES, reg_stat, opt_mode< T >::require(), rtl_profile_for_bb(), SCALAR_INT_MODE_P, SET_DEST, set_nonzero_bits_and_sign_copies(), SET_SRC, setup_incoming_promotions(), side_effects_p(), single_pred(), single_pred_p(), single_set(), statistics_counter_event(), subst_insn, subst_low_luid, this_basic_block, try_combine(), uid_insn_cost, uid_log_links, unmentioned_reg_p(), and XEXP.

Referenced by rest_of_handle_combine().

◆ combine_simplify_rtx()

static rtx combine_simplify_rtx ( rtx x,
machine_mode op0_mode,
bool in_dest,
bool in_cond )
static
Simplify X, a piece of RTL.  We just operate on the expression at the
outer level; call `subst' to simplify recursively.  Return the new
expression.

OP0_MODE is the original mode of XEXP (x, 0).  IN_DEST is true
if we are inside a SET_DEST.  IN_COND is true if we are at the top level
of a condition.   

References apply_distributive_law(), BINARY_P, combine_simplify_rtx(), COMMUTATIVE_ARITH_P, COMPARISON_P, const0_rtx, CONST0_RTX, const1_rtx, CONST_INT_P, const_true_rtx, CONSTANT_P, constm1_rtx, copy_rtx(), distribute_and_simplify_rtx(), exact_log2(), expand_compound_operation(), false_rtx, FLOAT_MODE_P, force_to_mode(), gen_int_mode(), gen_lowpart, gen_lowpart_common(), general_operand(), GET_CODE, get_last_value(), GET_MODE, GET_MODE_CLASS, GET_MODE_MASK, GET_MODE_PRECISION(), GET_MODE_UNIT_BITSIZE, GET_MODE_UNIT_PRECISION, GET_RTX_CLASS, ggc_alloc(), HOST_WIDE_INT_1U, HWI_COMPUTABLE_MODE_P(), i, if_then_else_cond(), INTEGRAL_MODE_P, INTVAL, is_int_mode(), known_eq, lowpart_subreg(), make_compound_operation(), maybe_swap_commutative_operands(), MEM_ADDR_SPACE, MEM_P, MEM_VOLATILE_P, mode_dependent_address_p(), nonzero_bits(), NULL, NULL_RTX, num_sign_bit_copies(), OBJECT_P, pc_rtx, plus_constant(), poly_int_rtx_p(), pow2p_hwi(), REG_P, reversed_comparison_code_parts(), RTX_BIN_ARITH, RTX_BITFIELD_OPS, RTX_COMM_ARITH, RTX_COMM_COMPARE, RTX_COMPARE, rtx_equal_p(), RTX_TERNARY, RTX_UNARY, SET, SHIFT_COUNT_TRUNCATED, side_effects_p(), simplify_and_const_int(), simplify_binary_operation(), simplify_comparison(), simplify_gen_binary(), simplify_gen_relational(), simplify_gen_unary(), simplify_if_then_else(), simplify_logical(), simplify_relational_operation(), simplify_set(), simplify_shift_const(), simplify_subreg(), simplify_ternary_operation(), simplify_unary_operation(), STORE_FLAG_VALUE, SUBREG_BYTE, subreg_lowpart_offset(), SUBREG_REG, SUBST, subst(), true_rtx, TRULY_NOOP_TRUNCATION_MODES_P, UINTVAL, UNARY_P, val_signbit_p(), vec_series_lowpart_p(), and XEXP.

Referenced by combine_simplify_rtx(), and subst().

◆ combine_split_insns()

static rtx_insn * combine_split_insns ( rtx pattern,
rtx_insn * insn )
static
Try to split PATTERN found in INSN.  This returns NULL_RTX if
PATTERN cannot 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 ggc_alloc(), max_reg_num(), reg_stat, and split_insns().

Referenced by find_split_point(), and try_combine().

◆ combine_validate_cost()

static bool combine_validate_cost ( rtx_insn * i0,
rtx_insn * i1,
rtx_insn * i2,
rtx_insn * 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_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, ggc_alloc(), i1, i2, INSN_CODE, INSN_COST, insn_cost(), INSN_UID(), optimize_this_for_speed_p, undobuf::other_insn, PATTERN(), and reject().

Referenced by try_combine().

◆ contains_muldiv()

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

References BINARY_P, CONST_INT_P, contains_muldiv(), GET_CODE, ggc_alloc(), pow2p_hwi(), UINTVAL, UNARY_P, and XEXP.

Referenced by contains_muldiv(), and try_combine().

◆ count_auto_inc()

static int count_auto_inc ( rtx ,
rtx ,
rtx ,
rtx ,
rtx ,
void * arg )
static
Callback function to count autoincs.   

Referenced by try_combine().

◆ count_rtxs()

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

References count_rtxs(), GET_CODE, GET_RTX_CLASS, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, RTX_BIN_ARITH, RTX_COMM_ARITH, XEXP, XVECEXP, and XVECLEN.

Referenced by count_rtxs(), and record_value_for_reg().

◆ create_log_links()

◆ delete_noop_moves()

static bool delete_noop_moves ( void )
static
Delete any insns that copy a register to itself.
Return true if the CFG was changed.   

References BB_END, BB_HEAD, cfun, delete_insn_and_edges(), dump_file, FOR_EACH_BB_FN, ggc_alloc(), insn_link::insn, INSN_P, INSN_UID(), insn_link::next, NEXT_INSN(), and noop_move_p().

Referenced by combine_instructions().

◆ distribute_and_simplify_rtx()

static rtx distribute_and_simplify_rtx ( rtx x,
int n )
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(), ARITHMETIC_P, FLOAT_MODE_P, GET_CODE, GET_MODE, ggc_alloc(), NULL_RTX, optimize_this_for_speed_p, set_src_cost(), simplify_gen_binary(), and XEXP.

Referenced by combine_simplify_rtx(), and simplify_logical().

◆ distribute_links()

static void distribute_links ( struct insn_link * 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, BB_HEAD, CALL_P, cfun, DEBUG_INSN_P, DF_INSN_LUID, EXIT_BLOCK_PTR_FOR_FN, find_reg_fusage(), FOR_EACH_LOG_LINK, GET_CODE, ggc_alloc(), i, insn_link::insn, INSN_P, LOG_LINKS, link::next, basic_block_def::next_bb, NEXT_INSN(), NOTE_P, NULL, PATTERN(), pc_rtx, reg_overlap_mentioned_p(), REG_P, reg_referenced_p(), reg_set_p(), REGNO, SET, SET_DEST, this_basic_block, XEXP, XVECEXP, and XVECLEN.

Referenced by adjust_for_new_dest(), distribute_notes(), and try_combine().

◆ distribute_notes()

static void distribute_notes ( rtx notes,
rtx_insn * from_insn,
rtx_insn * i3,
rtx_insn * 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 ACCUMULATE_OUTGOING_ARGS, add_reg_note(), add_shallow_copy_of_reg_note(), added_notes_insn, alloc_reg_note(), BB_HEAD, CALL_P, can_nonlocal_goto(), cfun, CONSTANT_P, dead_or_set_p(), dead_or_set_regno_p(), DF_INSN_LUID, distribute_links(), distribute_notes(), END_REGNO(), find_reg_fusage(), find_reg_note(), find_regno_fusage(), find_regno_note(), fixup_args_size_notes(), gcc_assert, gcc_unreachable, get_args_size(), GET_CODE, ggc_alloc(), global_regs, hard_regno_nregs(), i, i2, i2mod, i2mod_new_rhs, i2mod_old_rhs, insn_could_throw_p(), INSN_P, INT_MIN, INTVAL, JUMP_LABEL, JUMP_P, LABEL_NUSES, LABEL_P, label_ref_label(), LOG_LINKS, may_trap_p(), next_nonnote_nondebug_insn(), NONDEBUG_INSN_P, noop_move_p(), NULL, NULL_RTX, PATTERN(), pc_rtx, PREV_INSN(), PUT_REG_NOTE_KIND, record_value_for_reg(), refers_to_regno_p(), reg_bitfield_target_p(), reg_mentioned_p(), REG_NOTE_KIND, REG_NOTES, REG_NREGS, reg_overlap_mentioned_p(), REG_P, reg_raw_mode, reg_referenced_p(), reg_set_between_p(), reg_set_p(), reg_stat, insn_link::regno, REGNO, regno_reg_rtx, rtx_equal_p(), SET_DEST, SET_INSN_DELETED, SET_SRC, side_effects_p(), single_set(), this_basic_block, and XEXP.

Referenced by distribute_notes(), and try_combine().

◆ do_SUBST()

static void do_SUBST ( rtx * into,
rtx newval )
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 CONST_INT_P, undobuf::frees, gcc_assert, GET_CODE, GET_MODE, GET_MODE_CLASS, ggc_alloc(), INTVAL, undo::kind, undo::next, undo::old_contents, undo::r, SUBREG_REG, trunc_int_for_mode(), UNDO_RTX, undobuf::undos, undo::where, and XEXP.

◆ do_SUBST_INT()

static void do_SUBST_INT ( int * into,
int newval )
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, ggc_alloc(), undo::i, undo::kind, undo::next, undo::old_contents, UNDO_INT, undobuf::undos, and undo::where.

◆ do_SUBST_LINK()

static void do_SUBST_LINK ( struct insn_link ** into,
struct insn_link * newval )
static
Similar to SUBST, but NEWVAL is a LOG_LINKS expression.   

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

◆ expand_compound_operation()

static rtx expand_compound_operation ( rtx x)
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 COMPARISON_P, CONST_INT_P, expand_compound_operation(), gen_lowpart, GET_CODE, GET_MODE, GET_MODE_MASK, GET_MODE_PRECISION(), GET_MODE_SIZE(), ggc_alloc(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, HWI_COMPUTABLE_MODE_P(), INTVAL, nonzero_bits(), NULL_RTX, optimize_this_for_speed_p, set_src_cost(), simplify_and_const_int(), simplify_shift_const(), STORE_FLAG_VALUE, subreg_lowpart_p(), SUBREG_REG, and XEXP.

Referenced by apply_distributive_law(), combine_simplify_rtx(), expand_compound_operation(), force_int_to_mode(), make_field_assignment(), simplify_comparison(), and simplify_shift_const_1().

◆ expand_field_assignment()

static const_rtx expand_field_assignment ( const_rtx x)
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 CONST_INT_P, copy_rtx(), FLOAT_MODE_P, GEN_INT, gen_int_mode(), gen_lowpart, GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_PRECISION(), ggc_alloc(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, int_mode_for_size(), INTVAL, nonzero_sign_valid, read_modify_subreg_p(), SET_DEST, SET_SRC, simplify_gen_binary(), simplify_gen_unary(), subreg_lowpart_p(), subreg_lsb(), SUBREG_REG, targetm, and XEXP.

Referenced by can_combine_p(), and set_nonzero_bits_and_sign_copies().

◆ extended_count()

unsigned int extended_count ( const_rtx x,
machine_mode mode,
bool unsignedp )
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(), GET_MODE_PRECISION(), ggc_alloc(), HWI_COMPUTABLE_MODE_P(), nonzero_bits(), nonzero_sign_valid, and num_sign_bit_copies().

◆ extract_left_shift()

static rtx extract_left_shift ( scalar_int_mode mode,
rtx x,
int count )
static
See if X (of mode MODE) 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 CONST_INT_P, count, extract_left_shift(), gen_int_mode(), GET_CODE, ggc_alloc(), HOST_WIDE_INT_1U, INTVAL, NULL_RTX, simplify_gen_binary(), simplify_gen_unary(), simplify_shift_const(), UINTVAL, and XEXP.

Referenced by extract_left_shift(), and make_compound_operation_int().

◆ find_single_use()

static rtx * find_single_use ( rtx dest,
rtx_insn * insn,
rtx_insn ** ploc )
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.

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 BLOCK_FOR_INSN(), dead_or_set_p(), find_single_use_1(), FOR_EACH_LOG_LINK, ggc_alloc(), insn_link::insn, insn_link::next, NEXT_INSN(), NONDEBUG_INSN_P, PATTERN(), REG_P, and REGNO.

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

◆ find_single_use_1()

static rtx * find_single_use_1 ( rtx dest,
rtx * loc )
static
This is used by find_single_use to locate an rtx in LOC that
contains exactly one use of DEST, which is typically a REG.
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 CASE_CONST_ANY, find_single_use_1(), GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, NULL, read_modify_subreg_p(), REG_P, REGNO, SET, SET_DEST, SET_SRC, SUBREG_REG, XEXP, XVECEXP, and XVECLEN.

Referenced by find_single_use(), and find_single_use_1().

◆ find_split_point()

◆ force_int_to_mode()

static rtx force_int_to_mode ( rtx x,
scalar_int_mode mode,
scalar_int_mode xmode,
scalar_int_mode op_mode,
unsigned HOST_WIDE_INT mask,
bool just_select )
static

◆ force_to_mode()

static rtx force_to_mode ( rtx x,
machine_mode mode,
unsigned HOST_WIDE_INT mask,
bool 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 true, 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 const0_rtx, CONST_INT_P, force_int_to_mode(), force_to_mode(), GEN_INT, gen_int_mode(), gen_lowpart, gen_lowpart_common(), gen_lowpart_or_truncate(), GET_CODE, GET_MODE, GET_MODE_CLASS, GET_MODE_MASK, ggc_alloc(), have_insn_for(), INTVAL, nonzero_bits(), paradoxical_subreg_p(), partial_subreg_p(), SCALAR_INT_MODE_P, side_effects_p(), subreg_lowpart_p(), and SUBREG_REG.

Referenced by combine_simplify_rtx(), force_int_to_mode(), force_to_mode(), make_compound_operation_int(), make_extraction(), make_field_assignment(), simplify_and_const_int_1(), simplify_comparison(), and simplify_set().

◆ gen_lowpart_for_combine()

static rtx gen_lowpart_for_combine ( machine_mode omode,
rtx x )
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 adjust_address_nv, byte_lowpart_offset(), COMPARISON_P, const0_rtx, CONST_SCALAR_INT_P, gen_lowpart_common(), gen_rtx_SUBREG(), GET_CODE, GET_MODE, GET_MODE_SIZE(), ggc_alloc(), int_mode_for_mode(), known_eq, lowpart_subreg(), maybe_gt, MEM_ADDR_SPACE, MEM_P, MEM_VOLATILE_P, mode_dependent_address_p(), NULL, offset, paradoxical_subreg_p(), opt_mode< T >::require(), SCALAR_INT_MODE_P, SUBREG_REG, and XEXP.

◆ gen_lowpart_or_truncate()

static rtx gen_lowpart_or_truncate ( machine_mode mode,
rtx x )
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 CONST_INT_P, gen_lowpart, GET_MODE, ggc_alloc(), int_mode_for_mode(), partial_subreg_p(), REG_P, reg_truncated_to_mode(), require(), SCALAR_INT_MODE_P, simplify_gen_unary(), and TRULY_NOOP_TRUNCATION_MODES_P.

Referenced by force_int_to_mode(), force_to_mode(), simplify_comparison(), and simplify_shift_const_1().

◆ get_last_value()

◆ get_last_value_validate()

static bool get_last_value_validate ( rtx * loc,
rtx_insn * insn,
int tick,
bool replace )
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 false if some are not.  If REPLACE is true, replace
the invalid references with (clobber (const_int 0)) and return true.  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 ARITHMETIC_P, cfun, const0_rtx, DF_INSN_LUID, DF_LR_IN, END_REGNO(), ENTRY_BLOCK_PTR_FOR_FN, GET_CODE, get_last_value_validate(), GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, insn_link::insn, label_tick, mem_last_set, MEM_P, MEM_READONLY_P, REG_N_SETS(), reg_n_sets_max, REG_P, reg_stat, insn_link::regno, REGNO, REGNO_REG_SET_P, tick, XEXP, XVECEXP, and XVECLEN.

Referenced by get_last_value(), get_last_value_validate(), and record_value_for_reg().

◆ get_pos_from_mask()

static int get_pos_from_mask ( unsigned HOST_WIDE_INT m,
unsigned HOST_WIDE_INT * plen )
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 ggc_alloc().

Referenced by make_field_assignment().

◆ get_undo_marker()

static void * get_undo_marker ( void )
static
Get a marker for undoing to the current state.   

References undobuf::undos.

Referenced by recog_for_combine().

◆ if_then_else_cond()

static rtx if_then_else_cond ( rtx x,
rtx * ptrue,
rtx * pfalse )
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 BINARY_P, COMPARISON_P, const0_rtx, const_true_rtx, CONSTANT_P, constm1_rtx, copy_rtx(), GEN_INT, gen_int_mode(), GET_CODE, get_last_value(), GET_MODE, GET_MODE_PRECISION(), ggc_alloc(), HWI_COMPUTABLE_MODE_P(), if_then_else_cond(), nonzero_bits(), NULL, num_sign_bit_copies(), pow2p_hwi(), REG_P, reversed_comparison_code(), rtx_equal_p(), SCALAR_INT_MODE_P, side_effects_p(), simplify_gen_binary(), simplify_gen_relational(), simplify_gen_subreg(), simplify_gen_unary(), STORE_FLAG_VALUE, SUBREG_BYTE, SUBREG_REG, swap_condition(), UNARY_P, and XEXP.

Referenced by combine_simplify_rtx(), and if_then_else_cond().

◆ init_reg_last()

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

References FOR_EACH_VEC_ELT, ggc_alloc(), i, offsetof, and reg_stat.

Referenced by combine_instructions().

◆ insn_a_feeds_b()

static bool insn_a_feeds_b ( rtx_insn * a,
rtx_insn * 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.   

References a, b, FOR_EACH_LOG_LINK, and ggc_alloc().

Referenced by try_combine().

◆ insn_uid_check()

static int insn_uid_check ( const_rtx insn)
inlinestatic

◆ is_just_move()

static bool is_just_move ( rtx_insn * x)
static
Return whether X is just a single_set, with the source
a general_operand.   

References general_operand(), ggc_alloc(), SET_SRC, and single_set().

Referenced by try_combine().

◆ is_parallel_of_n_reg_sets()

static bool is_parallel_of_n_reg_sets ( rtx pat,
int n )
static
Return whether PAT is a PARALLEL of exactly N register SETs followed
by an arbitrary number of CLOBBERs.   

References const0_rtx, GET_CODE, ggc_alloc(), i, REG_P, SET, SET_DEST, XEXP, XVECEXP, and XVECLEN.

Referenced by try_combine().

◆ known_cond()

static rtx known_cond ( rtx x,
enum rtx_code cond,
rtx reg,
rtx val )
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 COMMUTATIVE_ARITH_P, comparison_dominates_p(), COMPARISON_P, const0_rtx, CONST0_RTX, const_true_rtx, FLOAT_MODE_P, GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, known_cond(), NULL, r, reverse_condition(), reversed_comparison_code(), rtx_equal_p(), side_effects_p(), simplify_gen_unary(), simplify_subreg(), simplify_unary_operation(), SUBREG_BYTE, SUBREG_REG, SUBST, swap_condition(), VECTOR_MODE_P, XEXP, XVECEXP, and XVECLEN.

Referenced by known_cond(), and simplify_if_then_else().

◆ likely_spilled_retval_1()

static void likely_spilled_retval_1 ( rtx x,
const_rtx set,
void * data )
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 ggc_alloc(), likely_spilled_retval_info::mask, likely_spilled_retval_info::nregs, REG_NREGS, REG_P, likely_spilled_retval_info::regno, REGNO, and XEXP.

Referenced by likely_spilled_retval_p().

◆ likely_spilled_retval_p()

static bool likely_spilled_retval_p ( rtx_insn * insn)
static
Return true 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 BB_END, GET_CODE, ggc_alloc(), INSN_P, likely_spilled_retval_1(), likely_spilled_retval_info::mask, NONJUMP_INSN_P, note_stores(), likely_spilled_retval_info::nregs, PATTERN(), PREV_INSN(), REG_NREGS, REG_P, likely_spilled_retval_info::regno, REGNO, targetm, this_basic_block, and XEXP.

Referenced by try_combine().

◆ make_compound_operation()

rtx make_compound_operation ( rtx x,
enum rtx_code in_code )
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 it is MEM.  When processing the arguments of
a comparison or a COMPARE against zero, it is COMPARE, or EQ if more
precisely it is an equality comparison against zero.   

References COMPARISON_P, const0_rtx, GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, make_compound_operation(), make_compound_operation_int(), maybe_swap_commutative_operands(), SET, simplify_unary_operation(), SUBST, XEXP, XVECEXP, and XVECLEN.

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

◆ make_compound_operation_int()

static rtx make_compound_operation_int ( scalar_int_mode mode,
rtx * x_ptr,
enum rtx_code in_code,
enum rtx_code * next_code_ptr )
static
Subroutine of make_compound_operation.  *X_PTR is the rtx at the current
level of the expression and MODE is its mode.  IN_CODE is as for
make_compound_operation.  *NEXT_CODE_PTR is the value of IN_CODE
that should be used when recursing on operands of *X_PTR.

There are two possible actions:

- Return null.  This tells the caller to recurse on *X_PTR with IN_CODE
  equal to *NEXT_CODE_PTR, after which *X_PTR holds the final value.

- Return a new rtx, which the caller returns directly.   

References BITS_PER_WORD, CONST_INT_P, count, exact_log2(), extract_left_shift(), force_to_mode(), gen_int_mode(), gen_lowpart, GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_MASK, GET_MODE_PRECISION(), GET_MODE_SIZE(), ggc_alloc(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1, HOST_WIDE_INT_M1U, i, INTVAL, load_extend_op(), make_compound_operation(), make_extraction(), maybe_swap_commutative_operands(), MEM_P, nonzero_bits(), NULL, NULL_RTX, OBJECT_P, partial_subreg_p(), REG_P, rtx_equal_p(), SET, simplify_gen_binary(), simplify_gen_unary(), simplify_subreg(), SUBREG_BYTE, subreg_lowpart_p(), SUBREG_REG, SUBST, trunc_int_for_mode(), UINTVAL, WORD_REGISTER_OPERATIONS, and XEXP.

Referenced by make_compound_operation().

◆ make_extraction()

static rtx make_extraction ( machine_mode mode,
rtx inner,
HOST_WIDE_INT pos,
rtx pos_rtx,
unsigned HOST_WIDE_INT len,
bool unsignedp,
bool in_dest,
bool 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 true for an unsigned reference and zero for a signed one.

IN_DEST is true 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 true 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 adjust_address_nv, BITS_PER_WORD, bits_to_bytes_round_down, const0_rtx, CONST_INT_P, CONST_SCALAR_INT_P, EP_extv, EP_extzv, EP_insv, exact_log2(), extraction_insn::field_mode, force_to_mode(), GEN_INT, gen_int_mode(), gen_lowpart, gen_rtx_SUBREG(), get_best_reg_extraction_insn(), GET_CODE, GET_MODE, GET_MODE_ALIGNMENT, GET_MODE_BITSIZE(), GET_MODE_MASK, GET_MODE_PRECISION(), GET_MODE_SIZE(), GET_MODE_WIDER_MODE(), ggc_alloc(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, HOST_WIDE_INT_M1U, HWI_COMPUTABLE_MODE_P(), IN_RANGE, int_mode_for_size(), INTVAL, poly_int< N, C >::is_constant(), known_le, make_extraction(), maybe_gt, MEM_ADDR_SPACE, MEM_P, MEM_VOLATILE_P, mode_dependent_address_p(), nonzero_bits(), NULL_RTX, offset, optimize_this_for_speed_p, paradoxical_subreg_p(), partial_subreg_p(), extraction_insn::pos_mode, REG_P, reg_truncated_to_mode(), opt_mode< T >::require(), set_src_cost(), simplify_gen_unary(), simplify_unary_operation(), smallest_int_mode_for_size(), extraction_insn::struct_mode, subreg_lowpart_p(), subreg_offset_from_lsb(), SUBREG_REG, TRULY_NOOP_TRUNCATION_MODES_P, UINTVAL, validate_subreg(), word_mode, and XEXP.

Referenced by find_split_point(), make_compound_operation_int(), make_extraction(), and make_field_assignment().

◆ make_field_assignment()

◆ make_more_copies()

static void make_more_copies ( void )
static
Make pseudo-to-pseudo copies after every hard-reg-to-pseudo-copy, because
the reg-to-reg copy can usefully combine with later instructions, but we
do not want to combine the hard reg into later instructions, for that
restricts register allocation.   

References cfun, df_insn_rescan(), emit_insn_before(), fixed_reg_set, FOR_BB_INSNS, FOR_EACH_BB_FN, gen_move_insn(), gen_reg_rtx(), GET_MODE, ggc_alloc(), HARD_REGISTER_P, insn_link::insn, NONDEBUG_INSN_P, REG_P, REGNO, SET_DEST, SET_SRC, single_set(), and TEST_HARD_REG_BIT.

Referenced by rest_of_handle_combine().

◆ make_pass_combine()

rtl_opt_pass * make_pass_combine ( gcc::context * ctxt)

References ggc_alloc().

◆ mark_used_regs_combine()

◆ maybe_swap_commutative_operands()

static void maybe_swap_commutative_operands ( rtx x)
static
If X is a commutative operation whose operands are not in the canonical
order, use substitutions to swap them.   

References COMMUTATIVE_ARITH_P, CONST_INT_P, GEN_INT, GET_CODE, GET_MODE, GET_MODE_NUNITS(), ggc_alloc(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, SUBST, swap_commutative_operands_p(), UINTVAL, and XEXP.

Referenced by change_zero_ext(), combine_simplify_rtx(), make_compound_operation(), and make_compound_operation_int().

◆ merge_outer_ops()

static bool merge_outer_ops ( enum rtx_code * pop0,
HOST_WIDE_INT * pconst0,
enum rtx_code op1,
HOST_WIDE_INT const1,
machine_mode mode,
bool * pcomp_p )
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 true if we can do the operation and update *POP0 and *PCONST0 with
the resulting operation.  *PCOMP_P is set to true 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 false and do not change *POP0, *PCONST0, and *PCOMP_P.   

References GET_MODE_MASK, ggc_alloc(), SET, and trunc_int_for_mode().

Referenced by simplify_shift_const_1().

◆ move_deaths()

static void move_deaths ( rtx x,
rtx maybe_kill_insn,
int from_luid,
rtx_insn * 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(), BLOCK_FOR_INSN(), dead_or_set_regno_p(), DF_INSN_LUID, END_REGNO(), find_regno_note(), GET_CODE, GET_MODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), hard_regno_nregs(), i, insn_link::insn, MEM_P, move_deaths(), offset, partial_subreg_p(), prev_real_nondebug_insn(), read_modify_subreg_p(), REG_NREGS, reg_referenced_p(), reg_set_p(), reg_stat, insn_link::regno, REGNO, regno_reg_rtx, remove_death(), SET, SET_DEST, SET_SRC, SUBREG_REG, XEXP, XVECEXP, and XVECLEN.

Referenced by move_deaths(), and try_combine().

◆ recog_for_combine()

static int recog_for_combine ( rtx * pnewpat,
rtx_insn * insn,
rtx * pnotes )
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.  If the
instruction will still not match, we change ZERO_EXTEND and ZERO_EXTRACT
to the equivalent AND and perhaps LSHIFTRT patterns, and try with that
(and undo if that fails).

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 change_zero_ext(), changed, check_asm_operands(), CONST_INT_P, CONSTANT_P, crtl, force_const_mem(), GET_CODE, GET_MODE, get_undo_marker(), ggc_alloc(), i, recog_for_combine_1(), SET, SET_DEST, SET_SRC, SUBST, undo_to_marker(), XVECEXP, and XVECLEN.

Referenced by simplify_set(), and try_combine().

◆ recog_for_combine_1()

static int recog_for_combine_1 ( rtx * pnewpat,
rtx_insn * insn,
rtx * pnotes )
static

◆ record_dead_and_set_regs()

static void record_dead_and_set_regs ( rtx_insn * insn)
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 CALL_P, DF_INSN_LUID, END_REGNO(), EXECUTE_IF_SET_IN_HARD_REG_SET, function_abi::full_and_partial_reg_clobbers(), ggc_alloc(), i, insn_callee_abi(), last_call_luid, mem_last_set, note_stores(), NULL_RTX, record_dead_and_set_regs_1(), record_value_for_reg(), REG_NOTE_KIND, REG_NOTES, REG_P, reg_stat, REGNO, and XEXP.

Referenced by combine_instructions().

◆ record_dead_and_set_regs_1()

static void record_dead_and_set_regs_1 ( rtx dest,
const_rtx setter,
void * data )
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 BITS_PER_WORD, DF_INSN_LUID, gen_lowpart, GET_CODE, GET_MODE, GET_MODE_MASK, GET_MODE_PRECISION(), ggc_alloc(), known_le, mem_last_set, MEM_P, NULL, NULL_RTX, paradoxical_subreg_p(), partial_subreg_p(), push_operand(), record_value_for_reg(), REG_P, reg_stat, REGNO, SET, SET_DEST, SET_SRC, subreg_lowpart_p(), SUBREG_REG, word_register_operation_p(), and WORD_REGISTER_OPERATIONS.

Referenced by record_dead_and_set_regs().

◆ record_promoted_value()

static void record_promoted_value ( rtx_insn * insn,
rtx subreg )
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 GET_MODE, GET_MODE_MASK, ggc_alloc(), HWI_COMPUTABLE_MODE_P(), insn_link::insn, LOG_LINKS, REG_P, reg_stat, insn_link::regno, REGNO, SET_DEST, SET_SRC, single_set(), SUBREG_PROMOTED_UNSIGNED_P, and SUBREG_REG.

Referenced by check_promoted_subreg().

◆ record_truncated_value()

static bool record_truncated_value ( rtx x)
static
If X is a hard reg or a subreg record the mode that the register is
accessed in.  For non-TARGET_TRULY_NOOP_TRUNCATION targets we might be
able to turn a truncate into a subreg using this information.  Return true
if traversing X is complete.   

References GET_CODE, GET_MODE, ggc_alloc(), label_tick, label_tick_ebb_start, partial_subreg_p(), REG_P, reg_stat, REGNO, SUBREG_REG, and TRULY_NOOP_TRUNCATION_MODES_P.

Referenced by record_truncated_values().

◆ record_truncated_values()

static void record_truncated_values ( rtx * loc,
void * data )
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_SUBRTX_VAR, ggc_alloc(), and record_truncated_value().

Referenced by combine_instructions().

◆ record_value_for_reg()

static void record_value_for_reg ( rtx reg,
rtx_insn * insn,
rtx value )
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 ARITHMETIC_P, const0_rtx, copy_rtx(), count_occurrences(), count_rtxs(), DF_INSN_LUID, END_REGNO(), GET_CODE, get_last_value(), get_last_value_validate(), GET_MODE, GET_MODE_CLASS, ggc_alloc(), HWI_COMPUTABLE_MODE_P(), i, label_tick, label_tick_ebb_start, nonzero_bits(), nonzero_bits_mode, num_sign_bit_copies(), reg_overlap_mentioned_p(), reg_stat, REGNO, replace_rtx(), subst_low_luid, update_table_tick(), and XEXP.

Referenced by distribute_notes(), record_dead_and_set_regs(), record_dead_and_set_regs_1(), setup_incoming_promotions(), and try_combine().

◆ reg_bitfield_target_p()

static bool reg_bitfield_target_p ( rtx x,
rtx body )
static
Return true 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(), GET_CODE, GET_MODE, ggc_alloc(), i, reg_bitfield_target_p(), REG_P, insn_link::regno, REGNO, SET, SET_DEST, SUBREG_REG, XEXP, XVECEXP, and XVECLEN.

Referenced by distribute_notes(), and reg_bitfield_target_p().

◆ reg_dead_at_p()

static bool reg_dead_at_p ( rtx reg,
rtx_insn * insn )
static
Return true 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 BB_HEAD, BLOCK_FOR_INSN(), df_get_live_in(), END_REGNO(), find_regno_note(), fixed_regs, ggc_alloc(), i, insn_link::insn, INSN_P, newpat_used_regs, note_stores(), NULL, PREV_INSN(), reg_dead_at_p_1(), reg_dead_endregno, reg_dead_flag, reg_dead_reg, reg_dead_regno, REGNO, REGNO_REG_SET_P, and TEST_HARD_REG_BIT.

Referenced by recog_for_combine_1().

◆ reg_dead_at_p_1()

static void reg_dead_at_p_1 ( rtx dest,
const_rtx x,
void * data )
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 END_REGNO(), GET_CODE, ggc_alloc(), reg_dead_endregno, reg_dead_flag, reg_dead_regno, REG_P, insn_link::regno, and REGNO.

Referenced by reg_dead_at_p().

◆ reg_nonzero_bits_for_combine()

static rtx reg_nonzero_bits_for_combine ( const_rtx x,
scalar_int_mode xmode,
scalar_int_mode mode,
unsigned HOST_WIDE_INT * nonzero )
static
Given a REG X of mode XMODE, compute which bits in X can be nonzero.
We don't care about bits outside of those defined in MODE.
We DO care about all the bits in MODE, even if XMODE is smaller than 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 cfun, DF_INSN_LUID, DF_LR_IN, ENTRY_BLOCK_PTR_FOR_FN, get_last_value(), GET_MODE_CLASS, GET_MODE_MASK, GET_MODE_PRECISION(), ggc_alloc(), label_tick, label_tick_ebb_start, nonzero_sign_valid, NULL, REG_N_SETS(), reg_n_sets_max, reg_stat, REGNO, REGNO_REG_SET_P, SHORT_IMMEDIATES_SIGN_EXTEND, sign_extend_short_imm(), and subst_low_luid.

◆ reg_num_sign_bit_copies_for_combine()

static rtx reg_num_sign_bit_copies_for_combine ( const_rtx x,
scalar_int_mode xmode,
scalar_int_mode mode,
unsigned int * result )
static
Given a reg X of mode XMODE, 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; the returned value will always be between 1 and the
number of bits in MODE.   

References cfun, DF_INSN_LUID, DF_LR_IN, ENTRY_BLOCK_PTR_FOR_FN, get_last_value(), GET_MODE_PRECISION(), ggc_alloc(), label_tick, label_tick_ebb_start, nonzero_sign_valid, NULL, REG_N_SETS(), reg_n_sets_max, reg_stat, REGNO, REGNO_REG_SET_P, and subst_low_luid.

◆ reg_subword_p()

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

References GET_CODE, GET_MODE, GET_MODE_CLASS, ggc_alloc(), paradoxical_subreg_p(), REG_P, SUBREG_REG, and XEXP.

Referenced by try_combine().

◆ reg_truncated_to_mode()

static bool reg_truncated_to_mode ( machine_mode mode,
const_rtx x )
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 ggc_alloc(), label_tick_ebb_start, partial_subreg_p(), reg_stat, REGNO, and TRULY_NOOP_TRUNCATION_MODES_P.

Referenced by gen_lowpart_or_truncate(), and make_extraction().

◆ remove_death()

rtx remove_death ( unsigned int regno,
rtx_insn * insn )
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(), ggc_alloc(), insn_link::insn, insn_link::regno, and remove_note().

Referenced by combine_and_move_insns(), and move_deaths().

◆ rest_of_handle_combine()

◆ rtx_equal_for_field_assignment_p()

static bool rtx_equal_for_field_assignment_p ( rtx x,
rtx y,
bool widen_x )
static
See if X and Y are equal for the purposes of seeing if we can rewrite an
assignment as a field assignment.   

References adjust_address_nv, byte_lowpart_offset(), gen_lowpart, GET_CODE, GET_MODE, ggc_alloc(), MEM_P, paradoxical_subreg_p(), rtx_equal_p(), SUBREG_REG, and y.

Referenced by make_field_assignment().

◆ set_nonzero_bits_and_sign_copies()

static void set_nonzero_bits_and_sign_copies ( rtx x,
const_rtx set,
void * data )
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 BLOCK_FOR_INSN(), cfun, dead_or_set_p(), DF_LR_IN, ENTRY_BLOCK_PTR_FOR_FN, expand_field_assignment(), FOR_EACH_LOG_LINK, GET_CODE, GET_MODE, GET_MODE_MASK, ggc_alloc(), HWI_COMPUTABLE_MODE_P(), insn_link::insn, paradoxical_subreg_p(), PATTERN(), REG_P, reg_referenced_p(), reg_stat, REGNO, REGNO_REG_SET_P, SET_DEST, SUBREG_REG, and update_rsp_from_reg_equal().

Referenced by combine_instructions(), and try_combine().

◆ setup_incoming_promotions()

◆ sign_extend_short_imm()

static rtx sign_extend_short_imm ( rtx src,
machine_mode mode,
unsigned int prec )
static
If MODE has a precision lower than PREC and SRC is a non-negative constant
that would appear negative in MODE, sign-extend SRC for use in nonzero_bits
because some machines (maybe most) will actually do the sign-extension and
this is the conservative approach.

??? For 2.5, try to tighten up the MD files in this regard instead of this
kludge.   

References CONST_INT_P, GEN_INT, GET_MODE_MASK, GET_MODE_PRECISION(), ggc_alloc(), INTVAL, and val_signbit_known_set_p().

Referenced by reg_nonzero_bits_for_combine(), and update_rsp_from_reg_equal().

◆ simplify_and_const_int()

static rtx simplify_and_const_int ( rtx x,
scalar_int_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(), gen_lowpart, GET_MODE, ggc_alloc(), simplify_and_const_int_1(), and simplify_gen_binary().

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

◆ simplify_and_const_int_1()

static rtx simplify_and_const_int_1 ( scalar_int_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(), BITS_PER_WORD, const0_rtx, CONST_INT_P, exact_log2(), force_to_mode(), gen_int_mode(), gen_lowpart, GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_MASK, ggc_alloc(), i, INTVAL, nonzero_bits(), NULL_RTX, pow2p_hwi(), side_effects_p(), simplify_and_const_int(), simplify_gen_binary(), simplify_shift_const(), word_mode, WORD_REGISTER_OPERATIONS, and XEXP.

Referenced by simplify_and_const_int().

◆ simplify_compare_const()

static enum rtx_code simplify_compare_const ( enum rtx_code code,
machine_mode mode,
rtx * pop0,
rtx * pop1 )
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.
*POP0 and *POP1 may be updated.   

References adjust_address_nv, dump_file, dump_flags, FOR_EACH_MODE_UNTIL, gcc_fallthrough, GEN_INT, gen_int_mode(), GET_MODE, GET_MODE_MASK, GET_MODE_NAME, GET_MODE_PRECISION(), GET_MODE_SIZE(), GET_RTX_NAME, ggc_alloc(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, HOST_WIDE_INT_M1U, HOST_WIDE_INT_PRINT_HEX, HWI_COMPUTABLE_MODE_P(), INTVAL, MEM_P, MEM_VOLATILE_P, nonzero_bits(), num_sign_bit_copies(), offset, pow2p_hwi(), TDF_DETAILS, and trunc_int_for_mode().

Referenced by simplify_comparison(), and try_combine().

◆ simplify_comparison()

static enum rtx_code simplify_comparison ( enum rtx_code code,
rtx * pop0,
rtx * pop1 )
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 a, BITS_PER_WORD, changed, COMPARISON_P, const0_rtx, const1_rtx, CONST_INT_P, constm1_rtx, exact_log2(), opt_mode< T >::exists(), expand_compound_operation(), FOR_EACH_MODE_UNTIL, FOR_EACH_WIDER_MODE, force_to_mode(), GEN_INT, gen_int_mode(), gen_lowpart, gen_lowpart_or_truncate(), GET_CODE, get_last_value(), GET_MODE, GET_MODE_BITSIZE(), GET_MODE_CLASS, GET_MODE_MASK, GET_MODE_PRECISION(), GET_MODE_SIZE(), ggc_alloc(), have_insn_for(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1, HOST_WIDE_INT_1U, HWI_COMPUTABLE_MODE_P(), i, int_mode_for_size(), INTVAL, is_int_mode(), load_extend_op(), make_compound_operation(), MEM_P, nonzero_bits(), NULL, NULL_RTX, num_sign_bit_copies(), paradoxical_subreg_p(), REG_P, reverse_condition(), reversed_comparison_code(), rtx_equal_p(), SET, SHIFT_COUNT_TRUNCATED, simplify_and_const_int(), simplify_binary_operation(), simplify_compare_const(), simplify_gen_binary(), simplify_gen_unary(), simplify_shift_const(), simplify_unary_operation(), STORE_FLAG_VALUE, subreg_lowpart_p(), SUBREG_REG, swap_commutative_operands_p(), swap_condition(), target_canonicalize_comparison(), trunc_int_for_mode(), UINTVAL, unsigned_condition(), val_signbit_known_set_p(), WORD_REGISTER_OPERATIONS, and XEXP.

Referenced by combine_simplify_rtx(), and simplify_set().

◆ simplify_if_then_else()

◆ simplify_logical()

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

References CONST_INT_P, distribute_and_simplify_rtx(), gcc_unreachable, GET_CODE, GET_MODE, ggc_alloc(), HWI_COMPUTABLE_MODE_P(), INTVAL, simplify_and_const_int(), and XEXP.

Referenced by combine_simplify_rtx().

◆ simplify_set()

◆ simplify_shift_const()

static rtx simplify_shift_const ( rtx x,
enum rtx_code code,
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 count, gen_int_shift_amount(), gen_lowpart, GET_MODE, ggc_alloc(), simplify_gen_binary(), and simplify_shift_const_1().

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

◆ simplify_shift_const_1()

static rtx simplify_shift_const_1 ( enum rtx_code code,
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 adjust_address_nv, apply_distributive_law(), CEIL, const0_rtx, CONST_INT_P, constm1_rtx, count, exact_log2(), expand_compound_operation(), GEN_INT, gen_int_mode(), gen_int_shift_amount(), gen_lowpart, gen_lowpart_or_truncate(), GET_CODE, GET_MODE, GET_MODE_BITSIZE(), GET_MODE_CLASS, GET_MODE_INNER, GET_MODE_MASK, GET_MODE_PRECISION(), GET_MODE_SIZE(), GET_MODE_UNIT_BITSIZE, GET_MODE_UNIT_PRECISION, GET_RTX_CLASS, ggc_alloc(), HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT_1U, HWI_COMPUTABLE_MODE_P(), int_mode_for_size(), INTVAL, is_int_mode(), mask_rtx(), MEM_ADDR_SPACE, MEM_VOLATILE_P, merge_outer_ops(), mode_dependent_address_p(), mode_signbit_p(), nonzero_bits(), NULL_RTX, num_sign_bit_copies(), rtx_equal_p(), RTX_UNARY, SET, SHIFT_COUNT_TRUNCATED, side_effects_p(), simplify_and_const_int(), simplify_const_binary_operation(), simplify_gen_binary(), simplify_gen_unary(), simplify_shift_const(), simplify_shift_const_1(), STORE_FLAG_VALUE, subreg_lowpart_p(), SUBREG_REG, trunc_int_for_mode(), try_widen_shift_mode(), UINTVAL, val_signbit_known_clear_p(), and XEXP.

Referenced by simplify_shift_const(), and simplify_shift_const_1().

◆ subst()

static rtx subst ( rtx x,
rtx from,
rtx to,
bool in_dest,
bool in_cond,
bool unique_copy )
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 true if we are processing the SET_DEST of a SET.

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

UNIQUE_COPY is true 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(), COMBINE_RTX_EQUAL_P, combine_simplify_rtx(), const0_rtx, CONST_SCALAR_INT_P, copy_rtx(), GET_CODE, GET_MODE, GET_RTX_CLASS, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, MEM_P, MEM_READONLY_P, n_occurrences, OBJECT_P, reg_overlap_mentioned_p(), REG_P, REGNO, RTX_AUTOINC, SET, SET_DEST, SET_SRC, simplify_subreg(), simplify_subreg_regno(), simplify_unary_operation(), SUBREG_BYTE, SUBREG_REG, SUBST, subst(), targetm, XEXP, XVECEXP, and XVECLEN.

Referenced by calculate_equiv_gains(), combine_simplify_rtx(), commutate(), curr_insn_transform(), loc_equivalence_callback(), loc_equivalence_change_p(), lower_for(), lra_substitute_pseudo(), self_referential_size(), simplify_if_then_else(), simplify_operand_subreg(), subst(), and try_combine().

◆ subst_mode()

static void subst_mode ( int regno,
machine_mode newval )
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, GET_MODE, ggc_alloc(), undo::kind, undo::m, undo::next, undo::old_contents, undo::regno, regno_reg_rtx, UNDO_MODE, undobuf::undos, and undo::where.

Referenced by simplify_set(), and try_combine().

◆ target_canonicalize_comparison()

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 ggc_alloc(), and targetm.

Referenced by simplify_comparison(), and try_combine().

◆ try_combine()

static rtx_insn * try_combine ( rtx_insn * i3,
rtx_insn * i2,
rtx_insn * i1,
rtx_insn * i0,
bool * new_direct_jump_p,
rtx_insn * 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 true 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, added_notes_insn, adjust_for_new_dest(), adjust_reg_mode(), alloc_insn_link(), alloc_reg_note(), any_uncondjump_p(), asm_noperands(), AUTO_INC_DEC, BB_HEAD, BINARY_P, BITS_PER_WORD, BLOCK_FOR_INSN(), CALL_INSN_FUNCTION_USAGE, CALL_P, can_change_dest_mode(), can_combine_p(), can_split_parallel_of_n_reg_sets(), cant_combine_insn_p(), cfun, check_asm_operands(), CLEAR_HARD_REG_SET, combinable_i3pat(), combine_attempts, combine_extras, combine_merges, combine_split_insns(), combine_successes, combine_validate_cost(), COMPARISON_P, const0_rtx, const1_rtx, CONST_INT_P, CONST_SCALAR_INT_P, CONSTANT_P, contains_muldiv(), copy_rtx(), copy_rtx_if_shared(), count_auto_inc(), dead_or_set_p(), DEBUG_INSN_P, DF_INSN_LUID, df_insn_rescan(), distribute_links(), distribute_notes(), dump_file, dump_flags, dump_insn_slim(), rtvec_def::elem, emit_barrier_after_bb(), exact_log2(), EXIT_BLOCK_PTR_FOR_FN, FIND_REG_INC_NOTE, find_reg_note(), find_single_use(), find_split_point(), FLOAT_MODE_P, for_each_inc_dec(), FOR_EACH_LOG_LINK, FOR_EACH_SUBRTX_PTR, undobuf::frees, gcc_assert, gen_int_shift_amount(), gen_lowpart, gen_raw_REG(), gen_rtvec(), gen_rtx_INSN(), gen_rtx_REG(), GET_CODE, GET_MODE, GET_MODE_CLASS, GET_MODE_MASK, GET_MODE_PRECISION(), ggc_alloc(), HOST_BITS_PER_INT, i, i1, i2, immed_wide_int_const(), INC_REG_N_SETS, wi::insert(), insn_link::insn, insn_a_feeds_b(), INSN_CODE, insn_could_throw_p(), INSN_LOCATION(), insn_nothrow_p(), INSN_P, INSN_UID(), INTEGRAL_MODE_P, INTVAL, is_just_move(), is_parallel_of_n_reg_sets(), JUMP_P, undo::kind, known_lt, last, likely_spilled_retval_p(), load_extend_op(), LOG_LINKS, lowpart_subreg(), undo::m, mark_jump_label(), mark_used_regs_combine(), max_reg_num(), MAY_HAVE_DEBUG_BIND_INSNS, may_trap_p(), MEM_P, modified_between_p(), move_deaths(), n_occurrences, new_mode(), newpat_used_regs, undo::next, next_active_insn(), basic_block_def::next_bb, NEXT_INSN(), next_nonnote_nondebug_insn(), NONDEBUG_INSN_P, NONJUMP_INSN_P, nonzero_bits(), NOTE_KIND, NOTE_P, note_pattern_stores(), NULL, NULL_RTX, rtvec_def::num_elem, offset, undo::old_contents, undobuf::other_insn, PATTERN(), pc_rtx, propagate_for_debug(), r, recog_for_combine(), record_value_for_reg(), reg_mentioned_p(), reg_n_sets_max, REG_NOTE_KIND, REG_NOTES, reg_or_subregno(), reg_overlap_mentioned_p(), REG_P, reg_referenced_p(), reg_set_between_p(), reg_set_p(), reg_stat, reg_subword_p(), reg_used_between_p(), insn_link::regno, undo::regno, REGNO, regno_reg_rtx, remove_edge(), remove_note(), reset_used_flags(), returnjump_p(), rtvec_alloc(), RTVEC_ELT, rtx_equal_p(), rtx_referenced_p(), SELECT_CC_MODE, SET, SET_DEST, SET_INSN_DELETED, set_nonzero_bits_and_sign_copies(), set_noop_p(), SET_SRC, side_effects_p(), simplify_compare_const(), simplify_gen_binary(), simplify_replace_rtx(), single_set(), split_block(), subreg_lowpart_p(), SUBREG_REG, SUBST, subst(), subst_insn, SUBST_LINK, subst_low_luid, subst_mode(), target_canonicalize_comparison(), targetm, TDF_DETAILS, this_basic_block, UINTVAL, undo_all(), undo_commit(), UNDO_MODE, undobuf::undos, update_cfg_for_uncondjump(), volatile_refs_p(), undo::where, word_mode, XEXP, XVEC, XVECEXP, and XVECLEN.

Referenced by combine_instructions().

◆ try_widen_shift_mode()

static scalar_int_mode try_widen_shift_mode ( enum rtx_code code,
rtx op,
int count,
scalar_int_mode orig_mode,
scalar_int_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 count, gcc_assert, gcc_unreachable, GET_MODE_MASK, GET_MODE_PRECISION(), ggc_alloc(), HWI_COMPUTABLE_MODE_P(), low_bitmask_len(), nonzero_bits(), and num_sign_bit_copies().

Referenced by simplify_shift_const_1().

◆ undo_all()

static void undo_all ( void )
static
Undo all the modifications recorded in undobuf.   

References undo_to_marker().

Referenced by try_combine().

◆ undo_commit()

static void undo_commit ( void )
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().

◆ undo_to_marker()

◆ unmentioned_reg_p()

static bool unmentioned_reg_p ( rtx equiv,
rtx expr )
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_SUBRTX, ggc_alloc(), MEM_P, reg_mentioned_p(), and REG_P.

Referenced by combine_instructions().

◆ update_rsp_from_reg_equal()

◆ update_table_tick()

static void update_table_tick ( rtx x)
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.cc   

References ARITHMETIC_P, END_REGNO(), GET_CODE, GET_RTX_FORMAT, GET_RTX_LENGTH, ggc_alloc(), i, label_tick, r, reg_stat, REGNO, update_table_tick(), XEXP, XVECEXP, and XVECLEN.

Referenced by record_value_for_reg(), and update_table_tick().

Variable Documentation

◆ added_links_insn

rtx_insn* 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().

◆ added_notes_insn

rtx_insn* added_notes_insn
static
And similarly, for notes.   

Referenced by distribute_notes(), and try_combine().

◆ combine_attempts

int combine_attempts
static
Optimize by combining instructions for GNU compiler.
   Copyright (C) 1987-2024 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.   
This 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 success.

We check (with modified_between_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.   
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(), and try_combine().

◆ combine_extras

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

Referenced by combine_instructions(), and try_combine().

◆ combine_merges

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

Referenced by combine_instructions(), and try_combine().

◆ combine_rtl_hooks

const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER
static

Referenced by combine_instructions().

◆ combine_successes

int combine_successes
static
Number of instructions combined in this function.   

Referenced by combine_instructions(), and try_combine().

◆ i2mod

rtx_insn* 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().

◆ i2mod_new_rhs

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().

◆ i2mod_old_rhs

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().

◆ insn_link_obstack

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

Referenced by alloc_insn_link(), and combine_instructions().

◆ label_tick

◆ label_tick_ebb_start

int label_tick_ebb_start
static

◆ last_call_luid

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().

◆ max_uid_known

int max_uid_known
static
Length of the currently allocated uid_insn_cost array.   

Referenced by combine_instructions(), and insn_uid_check().

◆ mem_last_set

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(), and record_dead_and_set_regs_1().

◆ n_occurrences

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().

◆ newpat_used_regs

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().

◆ nonzero_bits_mode

scalar_int_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 update_rsp_from_reg_equal().

◆ nonzero_sign_valid

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().

◆ optimize_this_for_speed_p

◆ reg_dead_endregno

unsigned int reg_dead_endregno
static

Referenced by reg_dead_at_p(), and reg_dead_at_p_1().

◆ reg_dead_flag

int reg_dead_flag
static

Referenced by reg_dead_at_p(), and reg_dead_at_p_1().

◆ reg_dead_reg

rtx reg_dead_reg

Referenced by reg_dead_at_p().

◆ reg_dead_regno

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().

◆ reg_n_sets_max

unsigned int reg_n_sets_max
static
One plus the highest pseudo for which we track REG_N_SETS.
regstat_init_n_sets_and_refs allocates the array for REG_N_SETS just once,
but during combine_split_insns new pseudos can be created.  As we don't have
updated DF information in that case, it is hard to initialize the array
after growing.  The combiner only cares about REG_N_SETS (regno) == 1,
so instead of growing the arrays, just assume all newly created pseudos
during combine might be set multiple times.   

Referenced by can_change_dest_mode(), get_last_value(), get_last_value_validate(), reg_nonzero_bits_for_combine(), reg_num_sign_bit_copies_for_combine(), rest_of_handle_combine(), and try_combine().

◆ reg_stat

◆ subst_insn

rtx_insn* 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().

◆ subst_low_luid

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().

◆ this_basic_block

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(), propagate_for_debug(), and try_combine().

◆ uid_insn_cost

int* uid_insn_cost
static
The following array records the insn_cost for every insn
in the instruction stream.   

Referenced by combine_instructions().

◆ uid_log_links

struct insn_link** uid_log_links
static

Referenced by combine_instructions().

◆ undobuf

struct undobuf undobuf
static