GCC Middle and Back End API Reference
tree-ssa-forwprop.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
#include "expmed.h"
#include "optabs-query.h"
#include "gimple-pretty-print.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "gimple-iterator.h"
#include "gimple-fold.h"
#include "tree-eh.h"
#include "gimplify.h"
#include "gimplify-me.h"
#include "tree-cfg.h"
#include "expr.h"
#include "tree-dfa.h"
#include "tree-ssa-propagate.h"
#include "tree-ssa-dom.h"
#include "tree-ssa-strlen.h"
#include "builtins.h"
#include "tree-cfgcleanup.h"
#include "cfganal.h"
#include "optabs-tree.h"
#include "insn-config.h"
#include "recog.h"
#include "cfgloop.h"
#include "tree-vectorizer.h"
#include "tree-vector-builder.h"
#include "vec-perm-indices.h"
#include "internal-fn.h"
#include "cgraph.h"
#include "tree-ssa.h"
#include "gimple-range.h"
#include "tree-ssa-dce.h"
#include "tree-ssa-math-opts.h"
Include dependency graph for tree-ssa-forwprop.cc:

Data Structures

struct  _vec_perm_simplify_seq
struct  long_mul_summand
struct  long_mul_row

Macros

#define CPD_ITERATIONS   5
#define CASE_ATOMIC(NAME, OTHER, OP)

Typedefs

typedef struct _vec_perm_simplify_seqvec_perm_simplify_seq

Enumerations

enum  long_mul_kind {
  LMK_MUL_HIHI , LMK_MUL_LOLO , LMK_MUL_HILO , LMK_CROSS_SUM ,
  LMK_LOW_ACCUM , LMK_LOW_SUM , LMK_LADDER_SUM1 , LMK_LADDER_SUM2 ,
  LMK_LADDER_SUM3 , LMK_LADDER_PART_SUM , LMK_CARRY_LOW , LMK_CARRY_CROSS_SUM ,
  LMK_CARRY_LOW_SUM
}
enum  long_mul_extract { LMX_NONE , LMX_HI , LMX_LO , LMX_SHL_N }

Functions

static bool forward_propagate_addr_expr (tree, tree, bool)
static tree rhs_to_tree (tree type, gimple *stmt)
static void fwprop_set_lattice_val (tree name, tree val)
static void fwprop_invalidate_lattice (tree name)
static gimpleget_prop_source_stmt (tree name, bool single_use_only, bool *single_use_p)
static bool can_propagate_from (gimple *def_stmt)
static void remove_prop_source_from_use (tree name)
static tree combine_cond_expr_cond (gimple *stmt, enum tree_code code, tree type, tree op0, tree op1, bool invariant_only)
static tree forward_propagate_into_comparison_1 (gimple *stmt, enum tree_code code, tree type, tree op0, tree op1)
static bool forward_propagate_into_comparison (gimple_stmt_iterator *gsi)
static int forward_propagate_into_gimple_cond (gcond *stmt)
static void tidy_after_forward_propagate_addr (gimple *stmt)
static bool forward_propagate_addr_expr_1 (tree name, tree def_rhs, gimple_stmt_iterator *use_stmt_gsi, bool single_use_p)
static void simplify_gimple_switch_label_vec (gswitch *stmt, tree index_type, vec< std::pair< int, int > > &edges_to_remove)
static bool simplify_gimple_switch (gswitch *stmt, vec< std::pair< int, int > > &edges_to_remove, bitmap simple_dce_worklist)
static tree constant_pointer_difference (tree p1, tree p2)
static void optimize_aggr_zeroprop_1 (gimple *defstmt, gimple *stmt, tree dest, poly_int64 offset, tree val, poly_offset_int len)
static void optimize_aggr_zeroprop (gimple *stmt, bool full_walk)
static tree split_core_and_offset_size (tree expr, poly_int64 *pbytesize, poly_int64 *pbytepos, tree *poffset, int *preversep)
static tree new_src_based_on_copy (tree src2, tree dest, tree src)
static bool same_for_assignment (tree src, tree dest)
static void optimize_agr_copyprop_1 (gimple *stmt, gimple *use_stmt, tree dest, tree src)
static void optimize_agr_copyprop_arg (gimple *defstmt, gcall *call, tree dest, tree src)
static void optimize_agr_copyprop_return (gimple *defstmt, greturn *use, tree dest, tree src)
static void optimize_agr_copyprop (gimple *stmt)
static void do_simple_agr_dse (gassign *stmt, bool full_walk)
static bool simplify_builtin_memcmp (gimple_stmt_iterator *gsi_p, gcall *stmt)
static bool simplify_builtin_memchr (gimple_stmt_iterator *gsi_p, gcall *stmt)
static bool simplify_builtin_memcpy_memset (gimple_stmt_iterator *gsi_p, gcall *stmt2)
static bool optimize_stack_restore (gimple_stmt_iterator *gsi, gimple *call)
static bool optimize_strlen_comp (gimple_stmt_iterator *gsi, gimple *call)
static bool simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2, bool full_walk)
static void defcodefor_name (tree name, enum tree_code *code, tree *arg1, tree *arg2)
static bool simplify_rotate (gimple_stmt_iterator *gsi)
template<typename ValidateFn>
static bool check_table_array (tree ctor, HOST_WIDE_INT &zero_val, unsigned bits, ValidateFn validate_fn)
template<typename ValidateFn>
static bool check_table_string (tree string, HOST_WIDE_INT &zero_val, unsigned bits, ValidateFn validate_fn)
template<typename ValidateFn>
static bool check_table (tree ctor, tree type, HOST_WIDE_INT &zero_val, unsigned bits, ValidateFn validate_fn)
bool gimple_ctz_table_index (tree, tree *, tree(*)(tree))
bool gimple_clz_table_index (tree, tree *, tree(*)(tree))
bool gimple_clz_msb_iso_table_index (tree, tree *, tree(*)(tree))
static bool simplify_count_zeroes (gimple_stmt_iterator *gsi)
bool gimple_cond_carry_add (tree, tree *, tree(*)(tree))
bool gimple_cond_carry_add_neg (tree, tree *, tree(*)(tree))
bool gimple_mul_hi (tree, tree *, tree(*)(tree))
bool gimple_mul_lo (tree, tree *, tree(*)(tree))
bool gimple_mul_hilo (tree, tree *, tree(*)(tree))
bool gimple_mul_lolo (tree, tree *, tree(*)(tree))
bool gimple_mul_hihi (tree, tree *, tree(*)(tree))
bool gimple_mul_cross_sum (tree, tree *, tree(*)(tree))
bool gimple_mul_low_sum (tree, tree *, tree(*)(tree))
bool gimple_mul_low_accum (tree, tree *, tree(*)(tree))
bool gimple_mul_carry_cross_sum (tree, tree *, tree(*)(tree))
bool gimple_mul_carry_low_sum (tree, tree *, tree(*)(tree))
bool gimple_mul_carry_low (tree, tree *, tree(*)(tree))
bool gimple_mul_ladder_sum1 (tree, tree *, tree(*)(tree))
bool gimple_mul_ladder_sum2 (tree, tree *, tree(*)(tree))
bool gimple_mul_ladder_sum3 (tree, tree *, tree(*)(tree))
bool gimple_mul_ladder_part_sum (tree, tree *, tree(*)(tree))
static void build_mul_high_seq (tree op1, tree op2, tree dest, location_t loc, gimple_seq *seq)
static void long_mul_apply_extras (tree acc, const vec< tree > &extras, tree_code outer, gassign *stmt, gimple_seq *seq)
static void create_mul_high_seq (tree op1, tree op2, gassign *stmt, const vec< tree > &extras, tree_code outer)
static void create_mul_low_seq (tree op1, tree op2, gassign *stmt, const vec< tree > &extras, tree_code outer)
static bool long_mul_linearize_chain (gimple *stmt, tree_code outer, vec< tree > &leaves, gimple **shared_def_out=NULL)
static bool long_mul_is_lshift_def (tree expr, tree *inner_out, unsigned HOST_WIDE_INT *shift_out)
static void long_mul_set_summand (long_mul_summand *info, long_mul_kind kind, const tree *res_ops)
static bool long_mul_classify_carry (tree leaf, long_mul_summand *info)
static bool long_mul_classify_plus_kinds (tree inner, long_mul_summand *info)
static bool long_mul_classify_hi_extract (tree inner, unsigned HOST_WIDE_INT shift, long_mul_summand *info)
static bool long_mul_classify_lo_extract (tree inner, long_mul_summand *info)
static bool long_mul_classify_shl_extract (tree inner, unsigned HOST_WIDE_INT shift, long_mul_summand *info)
static bool long_mul_classify_bare (tree leaf, long_mul_summand *info)
static bool long_mul_classify_summand (tree leaf, long_mul_summand *info)
static int long_mul_summand_compare (const void *a, const void *b)
static bool long_mul_same_ops (tree a, tree b, tree op0, tree op1)
static bool long_mul_is_cross_half (tree h, tree op0, tree op1)
static int long_mul_hilo_orientation (tree h, tree op0, tree op1)
static bool long_mul_canonical_ops (const vec< long_mul_summand > &summands, tree *op0_out, tree *op1_out)
static const long_mul_summandlong_mul_find_summand (const vec< long_mul_summand > &summands, long_mul_kind kind)
static bool long_mul_check_consistency (const vec< long_mul_summand > &summands, tree *op0_out, tree *op1_out)
static bool long_mul_signature_matches (const vec< long_mul_summand > &summands, const long_mul_row &row)
static bool long_mul_check_two_carries (const vec< long_mul_summand > &summands, gimple *)
static bool long_mul_check_low_plus_defer (const vec< long_mul_summand > &, gimple *stmt)
static void long_mul_hint_shared_intermediate (gimple *shared_def)
static const long_mul_rowlong_mul_classify_match (const vec< long_mul_summand > &summands, tree lhs_type, tree_code outer, gimple *candidate_stmt, tree *out_op0, tree *out_op1)
static const long_mul_rowlong_mul_classify_chain (gimple *stmt, tree_code outer, tree lhs_type, gimple *candidate, const long_mul_summand *extra, vec< tree > *extras_out, tree *out_op0, tree *out_op1)
static bool match_long_mul (gassign *stmt)
static bool match_long_mul_phi (gphi *phi)
static int is_combined_permutation_identity (tree mask1, tree mask2)
static bool simplify_permutation (gimple_stmt_iterator *gsi)
static tree get_bit_field_ref_def (tree val, enum tree_code &conv_code)
static bool simplify_vector_constructor (gimple_stmt_iterator *gsi)
static tree prepare_target_mem_ref_lvalue (tree ref, gimple_stmt_iterator *gsi)
static void optimize_vector_load (gimple_stmt_iterator *gsi)
static tree fwprop_ssa_val (tree name)
static bool recognise_vec_perm_simplify_seq (gassign *stmt, vec_perm_simplify_seq *seq)
static void narrow_vec_perm_simplify_seq (const vec_perm_simplify_seq &seq)
static bool can_blend_vec_perm_simplify_seqs_p (vec_perm_simplify_seq seq1, vec_perm_simplify_seq seq2, bool *need_swap)
static bool calc_perm_vec_perm_simplify_seqs (vec_perm_simplify_seq seq1, vec_perm_simplify_seq seq2, vec_perm_indices *seq2_stmt_indices, vec_perm_indices *seq1_v_1_stmt_indices, vec_perm_indices *seq1_v_2_stmt_indices)
static void blend_vec_perm_simplify_seqs (vec_perm_simplify_seq seq1, vec_perm_simplify_seq seq2, const vec_perm_indices &seq2_stmt_indices, const vec_perm_indices &seq1_v_1_stmt_indices, const vec_perm_indices &seq1_v_2_stmt_indices)
static void process_vec_perm_simplify_seq_list (vec< vec_perm_simplify_seq > *l)
static void append_vec_perm_simplify_seq_list (vec< vec_perm_simplify_seq > *l, const vec_perm_simplify_seq &seq)
gimple_opt_passmake_pass_forwprop (gcc::context *ctxt)

Variables

static bool cfg_changed
static bitmap to_purge
static vec< treelattice
static constexpr unsigned LONG_MUL_MAX_CAPTURES = 8
static constexpr unsigned LONG_MUL_MAX_SUMMANDS = 4
static constexpr unsigned LONG_MUL_MAX_EXTRAS = 4
static const long_mul_row long_mul_table []

Macro Definition Documentation

◆ CASE_ATOMIC

#define CASE_ATOMIC ( NAME,
OTHER,
OP )
Value:
case BUILT_IN_##NAME##_1: \
case BUILT_IN_##NAME##_2: \
case BUILT_IN_##NAME##_4: \
case BUILT_IN_##NAME##_8: \
case BUILT_IN_##NAME##_16: \
atomic_op = OP; \
other_atomic \
= (enum built_in_function) (BUILT_IN_##OTHER##_1 \
+ (DECL_FUNCTION_CODE (callee2) \
- BUILT_IN_##NAME##_1)); \
goto handle_atomic_fetch_op;
built_in_function
Definition genmatch.cc:1009
@ NAME
Definition tree-ssa-pre.cc:241
built_in_function DECL_FUNCTION_CODE(const_tree decl)
Definition tree.h:4525

Referenced by simplify_builtin_call().

◆ CPD_ITERATIONS

#define CPD_ITERATIONS   5

Typedef Documentation

◆ vec_perm_simplify_seq

Enumeration Type Documentation

◆ long_mul_extract

How the leaf wraps its inner kind.  Carry kinds use LMX_NONE: their
match.pd pattern bakes the lshift in, so the leaf is already the
complete carry expression.   
Enumerator
LMX_NONE 
LMX_HI 
LMX_LO 
LMX_SHL_N 

◆ long_mul_kind

Enumerator
LMK_MUL_HIHI 
LMK_MUL_LOLO 
LMK_MUL_HILO 
LMK_CROSS_SUM 
LMK_LOW_ACCUM 
LMK_LOW_SUM 
LMK_LADDER_SUM1 
LMK_LADDER_SUM2 
LMK_LADDER_SUM3 
LMK_LADDER_PART_SUM 
LMK_CARRY_LOW 
LMK_CARRY_CROSS_SUM 
LMK_CARRY_LOW_SUM 

Function Documentation

◆ append_vec_perm_simplify_seq_list()

void append_vec_perm_simplify_seq_list ( vec< vec_perm_simplify_seq > * l,
const vec_perm_simplify_seq & seq )
static

◆ blend_vec_perm_simplify_seqs()

void blend_vec_perm_simplify_seqs ( vec_perm_simplify_seq seq1,
vec_perm_simplify_seq seq2,
const vec_perm_indices & seq2_stmt_indices,
const vec_perm_indices & seq1_v_1_stmt_indices,
const vec_perm_indices & seq1_v_2_stmt_indices )
static

◆ build_mul_high_seq()

void build_mul_high_seq ( tree op1,
tree op2,
tree dest,
location_t loc,
gimple_seq * seq )
static
Append to SEQ statements assigning DEST the high-part multiply of
OP1 and OP2, emitted as
  (N)(((2N) op1 * (2N) op2) >> N).
pass_optimize_widening_mul's convert_mult_to_widen and
convert_mult_to_highpart later rewrite this to a single
WIDEN_MULT_EXPR or MULT_HIGHPART_EXPR when the target supports it,
otherwise the 2N multiply expands directly.  Emitting the canonical
widening shape keeps target-capability decisions in the layer that
already owns them.   

References build_int_cst(), build_nonstandard_integer_type(), gimple_build(), gimple_build_assign(), gimple_convert(), gimple_seq_add_stmt(), gimple_set_location(), integer_type_node, TREE_TYPE, and TYPE_PRECISION.

Referenced by create_mul_high_seq(), and match_long_mul_phi().

◆ calc_perm_vec_perm_simplify_seqs()

bool calc_perm_vec_perm_simplify_seqs ( vec_perm_simplify_seq seq1,
vec_perm_simplify_seq seq2,
vec_perm_indices * seq2_stmt_indices,
vec_perm_indices * seq1_v_1_stmt_indices,
vec_perm_indices * seq1_v_2_stmt_indices )
static

◆ can_blend_vec_perm_simplify_seqs_p()

◆ can_propagate_from()

◆ check_table()

template<typename ValidateFn>
bool check_table ( tree ctor,
tree type,
HOST_WIDE_INT & zero_val,
unsigned bits,
ValidateFn validate_fn )
static
Check whether CTOR contains a valid table according to VALIDATE_FN.   

References CHAR_TYPE_SIZE, check_table_array(), check_table_string(), TREE_CODE, and TYPE_PRECISION.

Referenced by simplify_count_zeroes().

◆ check_table_array()

template<typename ValidateFn>
bool check_table_array ( tree ctor,
HOST_WIDE_INT & zero_val,
unsigned bits,
ValidateFn validate_fn )
static
Check whether an array contains a valid table according to VALIDATE_FN.   

References CONSTRUCTOR_ELTS, FOR_EACH_CONSTRUCTOR_ELT, i, RAW_DATA_LENGTH, RAW_DATA_SCHAR_ELT, RAW_DATA_UCHAR_ELT, TREE_CODE, tree_fits_shwi_p(), tree_to_shwi(), TREE_TYPE, and TYPE_UNSIGNED.

Referenced by check_table().

◆ check_table_string()

template<typename ValidateFn>
bool check_table_string ( tree string,
HOST_WIDE_INT & zero_val,
unsigned bits,
ValidateFn validate_fn )
static
Check whether a string contains a valid table according to VALIDATE_FN.   

References i, TREE_STRING_LENGTH, and TREE_STRING_POINTER.

Referenced by check_table().

◆ combine_cond_expr_cond()

tree combine_cond_expr_cond ( gimple * stmt,
enum tree_code code,
tree type,
tree op0,
tree op1,
bool invariant_only )
static
Combine OP0 CODE OP1 in the context of a COND_EXPR.  Returns
the folded result in a form suitable for COND_EXPR_COND or
NULL_TREE, if there is no suitable simplified form.  If
INVARIANT_ONLY is true only gimple_min_invariant results are
considered simplified.   

References canonicalize_cond_expr_cond(), fold_binary_loc(), gcc_assert, gimple_location(), is_gimple_min_invariant(), NULL_TREE, _vec_perm_simplify_seq::stmt, tcc_comparison, TREE_CODE, TREE_CODE_CLASS, and TREE_TYPE.

Referenced by forward_propagate_into_comparison_1().

◆ constant_pointer_difference()

◆ create_mul_high_seq()

void create_mul_high_seq ( tree op1,
tree op2,
gassign * stmt,
const vec< tree > & extras,
tree_code outer )
static
Replace STMT with a high-part multiply of OP1 and OP2, combining any
EXTRAS back on top under OUTER.   

References build_mul_high_seq(), gimple_assign_lhs(), gimple_location(), gsi_for_stmt(), gsi_replace_with_seq(), long_mul_apply_extras(), make_ssa_name(), NULL, _vec_perm_simplify_seq::stmt, and TREE_TYPE.

Referenced by match_long_mul().

◆ create_mul_low_seq()

void create_mul_low_seq ( tree op1,
tree op2,
gassign * stmt,
const vec< tree > & extras,
tree_code outer )
static
Replace STMT with a low-part multiply of OP1 and OP2, combining any
EXTRAS back on top under OUTER.   

References gimple_assign_lhs(), gimple_build_assign(), gimple_location(), gimple_seq_add_stmt(), gimple_set_location(), gsi_for_stmt(), gsi_replace_with_seq(), long_mul_apply_extras(), make_ssa_name(), NULL, _vec_perm_simplify_seq::stmt, and TREE_TYPE.

Referenced by match_long_mul().

◆ defcodefor_name()

void defcodefor_name ( tree name,
enum tree_code * code,
tree * arg1,
tree * arg2 )
inlinestatic
Given a ssa_name in NAME see if it was defined by an assignment and
set CODE to be the code and ARG1 to the first operand on the rhs and ARG2
to the second operand on the rhs.  

References can_propagate_from(), get_gimple_rhs_class(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs3(), gimple_assign_rhs_code(), GIMPLE_SINGLE_RHS, is_gimple_assign(), NULL_TREE, SSA_NAME_DEF_STMT, and TREE_CODE.

Referenced by simplify_rotate().

◆ do_simple_agr_dse()

void do_simple_agr_dse ( gassign * stmt,
bool full_walk )
static
Simple DSE of the lhs from a clobber STMT.
This is used mostly to clean up from optimize_agr_copyprop and
to remove (exactly one) extra copy that might later on confuse SRA.
An example is:
;; write to a and such.
b = a; // This statement is to be removed
b = {CLOBBER};
SRA will totally scalarize b (which means also a) here for the extra copy
which is not something welcomed. So removing the copy will
allow SRA to move the scalarization of a further down or not at all.

References ao_ref_init(), as_a(), bitmap_set_bit, CDI_DOMINATORS, cfun, DECL_P, dominated_by_p(), dump_file, dump_flags, dyn_cast(), ECF_CONST, ECF_LOOPING_CONST_OR_PURE, ECF_NOVOPS, ECF_PURE, FOR_EACH_IMM_USE_STMT, gimple_assign_lhs(), gimple_bb(), gimple_call_flags(), gimple_call_fntype(), gimple_call_lhs(), gimple_call_return_slot_opt_p(), gimple_call_set_lhs(), gimple_clobber_p(), gimple_nop_p(), gimple_phi_result(), gimple_store_p(), gimple_vdef(), gimple_vuse(), gsi_for_stmt(), gsi_remove(), basic_block_def::index, is_a(), NULL_TREE, poly_int_tree_p(), print_gimple_stmt(), ref_maybe_used_by_stmt_p(), release_defs(), single_imm_use(), SSA_NAME_DEF_STMT, statistics_counter_event(), _vec_perm_simplify_seq::stmt, stmt_could_throw_p(), stmt_may_clobber_ref_p_1(), stmt_unremovable_because_of_non_call_eh_p(), TDF_DETAILS, to_purge, TREE_ADDRESSABLE, TREE_TYPE, TYPE_SIZE, unlink_stmt_vdef(), and update_stmt().

◆ forward_propagate_addr_expr()

bool forward_propagate_addr_expr ( tree name,
tree rhs,
bool parent_single_use_p )
static
STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>.

Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME.
Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
node or for recovery of array indexing from pointer arithmetic.

PARENT_SINGLE_USE_P tells if, when in a recursive invocation, NAME was
the single use in the previous invocation.  Pass true when calling
this as toplevel.

Returns true, if all uses have been propagated into.   

References forward_propagate_addr_expr_1(), fwprop_invalidate_lattice(), gather_imm_use_stmts(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_get_lhs(), gsi_for_stmt(), gsi_remove(), gsi_stmt(), has_single_use(), has_zero_uses(), is_gimple_assign(), is_gimple_debug(), release_defs(), TREE_CODE, and update_stmt().

Referenced by forward_propagate_addr_expr_1().

◆ forward_propagate_addr_expr_1()

bool forward_propagate_addr_expr_1 ( tree name,
tree def_rhs,
gimple_stmt_iterator * use_stmt_gsi,
bool single_use_p )
static

◆ forward_propagate_into_comparison()

bool forward_propagate_into_comparison ( gimple_stmt_iterator * gsi)
static
Propagate from the ssa name definition statements of the assignment
from a comparison at *GSI into the conditional if that simplifies it.
Returns true if the stmt was modified.   

References dump_file, fold_stmt(), forward_propagate_into_comparison_1(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_assign_set_rhs_from_tree(), gsi_stmt(), print_generic_expr(), print_gimple_expr(), remove_prop_source_from_use(), _vec_perm_simplify_seq::stmt, TREE_CODE, TREE_TYPE, update_stmt(), and useless_type_conversion_p().

◆ forward_propagate_into_comparison_1()

tree forward_propagate_into_comparison_1 ( gimple * stmt,
enum tree_code code,
tree type,
tree op0,
tree op1 )
static
Combine the comparison OP0 CODE OP1 at LOC with the defining statements
of its operand.  Return a new comparison tree or NULL_TREE if there
were no simplifying combines.   

References can_propagate_from(), combine_cond_expr_cond(), CONVERT_EXPR_CODE_P, get_prop_source_stmt(), gimple_assign_rhs_code(), NULL_TREE, rhs_to_tree(), _vec_perm_simplify_seq::stmt, tcc_comparison, TREE_CODE, TREE_CODE_CLASS, TREE_OPERAND, and TREE_TYPE.

Referenced by forward_propagate_into_comparison(), and forward_propagate_into_gimple_cond().

◆ forward_propagate_into_gimple_cond()

int forward_propagate_into_gimple_cond ( gcond * stmt)
static
Propagate from the ssa name definition statements of COND_EXPR
in GIMPLE_COND statement STMT into the conditional if that simplifies it.
Returns zero if no statement was changed, one if there were
changes and two if cfg_cleanup needs to run.   

References boolean_type_node, canonicalize_bool_cond(), dump_file, forward_propagate_into_comparison_1(), gcc_assert, gimple_bb(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_cond_set_condition_from_tree(), is_gimple_condexpr_for_cond(), is_gimple_min_invariant(), print_generic_expr(), print_gimple_expr(), remove_prop_source_from_use(), _vec_perm_simplify_seq::stmt, tcc_comparison, TREE_CODE, TREE_CODE_CLASS, unshare_expr(), and update_stmt().

◆ fwprop_invalidate_lattice()

void fwprop_invalidate_lattice ( tree name)
static
Invalidate the lattice entry for NAME, done when releasing SSA names.   

References lattice, NULL_TREE, SSA_NAME_VERSION, and TREE_CODE.

Referenced by forward_propagate_addr_expr(), remove_prop_source_from_use(), and simplify_builtin_memcpy_memset().

◆ fwprop_set_lattice_val()

void fwprop_set_lattice_val ( tree name,
tree val )
static
Set the lattice entry for NAME to VAL.   

References lattice, maybe_duplicate_ssa_info_at_copy(), num_ssa_names, SSA_NAME_VERSION, and TREE_CODE.

◆ fwprop_ssa_val()

tree fwprop_ssa_val ( tree name)
static
Primitive "lattice" function for gimple_simplify.   

References lattice, SSA_NAME_VERSION, and TREE_CODE.

◆ get_bit_field_ref_def()

tree get_bit_field_ref_def ( tree val,
enum tree_code & conv_code )
static
Get the BIT_FIELD_REF definition of VAL, if any, looking through
conversions with code CONV_CODE or update it if still ERROR_MARK.
Return NULL_TREE if no such matching def was found.   

References CONVERT_EXPR_CODE_P, get_prop_source_stmt(), gimple_assign_rhs1(), gimple_assign_rhs_code(), is_gimple_assign(), NULL, NULL_TREE, SSA_NAME_DEF_STMT, and TREE_CODE.

Referenced by simplify_vector_constructor().

◆ get_prop_source_stmt()

gimple * get_prop_source_stmt ( tree name,
bool single_use_only,
bool * single_use_p )
static
Get the statement we can propagate from into NAME skipping
trivial copies.  Returns the statement which defines the
propagation source or NULL_TREE if there is no such one.
If SINGLE_USE_ONLY is set considers only sources which have
a single use chain up to NAME.  If SINGLE_USE_P is non-null,
it is set to whether the chain to NAME is a single use chain
or not.  SINGLE_USE_P is not written to if SINGLE_USE_ONLY is set.   

References gimple_assign_rhs1(), gimple_assign_rhs_code(), has_single_use(), is_gimple_assign(), NULL, single_use(), and SSA_NAME_DEF_STMT.

Referenced by forward_propagate_into_comparison_1(), get_bit_field_ref_def(), and simplify_permutation().

◆ gimple_clz_msb_iso_table_index()

bool gimple_clz_msb_iso_table_index ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by simplify_count_zeroes().

◆ gimple_clz_table_index()

bool gimple_clz_table_index ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by simplify_count_zeroes().

◆ gimple_cond_carry_add()

bool gimple_cond_carry_add ( tree ,
tree * ,
tree(*  )(tree) )
extern
Long-multiply fold framework.

Walks the outer addition or bit_ior chain on a candidate statement,
classifies each summand against the atom match patterns from
match.pd, and looks the resulting multiset of (kind, extract) tuples
up in a table.  On a hit, three cross-summand consistency checks
decide whether the wide multiply is emitted.   
Match.pd recognizers for the conditional carry-add pattern.  The
two names split the gcond polarity: cond_carry_add matches when
the true edge selects (base + pow2), cond_carry_add_neg when the
true edge selects base.   

Referenced by match_long_mul_phi().

◆ gimple_cond_carry_add_neg()

bool gimple_cond_carry_add_neg ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by match_long_mul_phi().

◆ gimple_ctz_table_index()

bool gimple_ctz_table_index ( tree ,
tree * ,
tree(*  )(tree) )
extern
Match.pd function to match the ctz expression.   

Referenced by simplify_count_zeroes().

◆ gimple_mul_carry_cross_sum()

bool gimple_mul_carry_cross_sum ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by long_mul_classify_carry().

◆ gimple_mul_carry_low()

bool gimple_mul_carry_low ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by long_mul_classify_carry().

◆ gimple_mul_carry_low_sum()

bool gimple_mul_carry_low_sum ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by long_mul_classify_carry().

◆ gimple_mul_cross_sum()

◆ gimple_mul_hi()

bool gimple_mul_hi ( tree ,
tree * ,
tree(*  )(tree) )
extern
Match.pd functions to match long multiplication.   

Referenced by long_mul_classify_summand().

◆ gimple_mul_hihi()

bool gimple_mul_hihi ( tree ,
tree * ,
tree(*  )(tree) )
extern

Referenced by long_mul_classify_bare().

◆ gimple_mul_hilo()

bool gimple_mul_hilo ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_ladder_part_sum()

bool gimple_mul_ladder_part_sum ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_ladder_sum1()

bool gimple_mul_ladder_sum1 ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_ladder_sum2()

bool gimple_mul_ladder_sum2 ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_ladder_sum3()

bool gimple_mul_ladder_sum3 ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_lo()

bool gimple_mul_lo ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_lolo()

bool gimple_mul_lolo ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_low_accum()

bool gimple_mul_low_accum ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ gimple_mul_low_sum()

bool gimple_mul_low_sum ( tree ,
tree * ,
tree(*  )(tree) )
extern

◆ is_combined_permutation_identity()

int is_combined_permutation_identity ( tree mask1,
tree mask2 )
static
Determine whether applying the 2 permutations (mask1 then mask2)
gives back one of the input.   

References fold_ternary, gcc_assert, gcc_checking_assert, i, NULL_TREE, operand_equal_p(), vec_perm_indices::series_p(), TREE_CODE, TREE_INT_CST_LOW, tree_to_vec_perm_builder(), TREE_TYPE, TYPE_VECTOR_SUBPARTS(), VECTOR_CST_ELT, and VECTOR_CST_NELTS.

Referenced by simplify_permutation().

◆ long_mul_apply_extras()

void long_mul_apply_extras ( tree acc,
const vec< tree > & extras,
tree_code outer,
gassign * stmt,
gimple_seq * seq )
static
Append to SEQ statements combining ACC with each of EXTRAS under
OUTER, the last one assigning to STMT's lhs.  EXTRAS are leaves of
STMT's own chain, so any combining order is valid.   

References gimple_assign_lhs(), gimple_build(), gimple_build_assign(), gimple_location(), gimple_seq_add_stmt(), gimple_set_location(), i, last, _vec_perm_simplify_seq::stmt, and TREE_TYPE.

Referenced by create_mul_high_seq(), and create_mul_low_seq().

◆ long_mul_canonical_ops()

bool long_mul_canonical_ops ( const vec< long_mul_summand > & summands,
tree * op0_out,
tree * op1_out )
static
Find the first summand that carries operand captures, and return its
(op0, op1) pair in *OP0_OUT / *OP1_OUT.  Returns false if no summand
provides them.   

Referenced by long_mul_check_consistency(), and long_mul_check_two_carries().

◆ long_mul_check_consistency()

bool long_mul_check_consistency ( const vec< long_mul_summand > & summands,
tree * op0_out,
tree * op1_out )
static
Run the cross-summand validation invariants and return the canonical
(op0, op1).  Returns false unless all summands that carry operands use
the same (op0, op1) pair (in either order), every LMX_HI/LMX_SHL_N shift
equals halfwidth, every captured hilo is a true cross-half product of
(op0, op1), and every cross-half pair (both those inside a single
mul_cross_sum-bearing summand and those spread across separate
LMK_MUL_HILO summands) contains one of each orientation.   

References a, b, INTEGRAL_TYPE_P, LMK_MUL_HILO, LMX_HI, LMX_SHL_N, long_mul_canonical_ops(), long_mul_hilo_orientation(), long_mul_is_cross_half(), long_mul_same_ops(), NULL_TREE, TREE_TYPE, and TYPE_PRECISION.

Referenced by long_mul_classify_match().

◆ long_mul_check_low_plus_defer()

bool long_mul_check_low_plus_defer ( const vec< long_mul_summand > & ,
gimple * stmt )
static
The lolo + cross_shifted shape is also the low half of a two-carry
long-multiply, where an unsigned overflow compare against one of
the PLUS operands is the low-carry term consumed by the matching
high-part fold.  Folding to mul_lo here destroys cross_shifted,
which both the compare and the high-part match still need; defer
so the high-part fold runs first.  After it does, the compare is
dead and the surviving lolo + cross_shifted is picked up by this
row in the next forwprop instance.  Returns false to defer.   

References dyn_cast(), FOR_EACH_IMM_USE_STMT, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), is_gimple_assign(), and NULL_TREE.

◆ long_mul_check_two_carries()

bool long_mul_check_two_carries ( const vec< long_mul_summand > & summands,
gimple *  )
static
Extra check for the two-carries high-part row: the LMK_CARRY_LOW summand's
two operands (carry_a, carry_b) must be a (cross_shifted, mul_lolo) pair
consistent with the multiset's canonical (op0, op1).   

References long_mul_summand::carry_a, long_mul_summand::carry_b, gimple_mul_cross_sum(), gimple_mul_lolo(), i, LMK_CARRY_LOW, long_mul_canonical_ops(), long_mul_find_summand(), long_mul_is_cross_half(), long_mul_is_lshift_def(), LONG_MUL_MAX_CAPTURES, long_mul_same_ops(), NULL, scratch, shift, TREE_TYPE, and TYPE_PRECISION.

◆ long_mul_classify_bare()

bool long_mul_classify_bare ( tree leaf,
long_mul_summand * info )
static
Classify LEAF as one of the bare-kind summands (no extraction
wrapper): mul_hihi or mul_lolo standing on their own.   

References gimple_mul_hihi(), gimple_mul_lolo(), LMK_MUL_HIHI, LMK_MUL_LOLO, LONG_MUL_MAX_CAPTURES, long_mul_set_summand(), and NULL.

Referenced by long_mul_classify_summand().

◆ long_mul_classify_carry()

bool long_mul_classify_carry ( tree leaf,
long_mul_summand * info )
static
Classify LEAF as a carry-kind summand.  The lshift amount is baked
into mul_carry_cross_sum / mul_carry_low_sum, so they're tried before
any branch that looks for a generic (X >> N) or (X << N) wrapper.   

References gimple_mul_carry_cross_sum(), gimple_mul_carry_low(), gimple_mul_carry_low_sum(), LMK_CARRY_CROSS_SUM, LMK_CARRY_LOW, LMK_CARRY_LOW_SUM, LONG_MUL_MAX_CAPTURES, long_mul_set_summand(), and NULL.

Referenced by long_mul_classify_summand().

◆ long_mul_classify_chain()

const long_mul_row * long_mul_classify_chain ( gimple * stmt,
tree_code outer,
tree lhs_type,
gimple * candidate,
const long_mul_summand * extra,
vec< tree > * extras_out,
tree * out_op0,
tree * out_op1 )
static
Walk STMT's outer chain (kind OUTER), classify each leaf as a
long-multiply summand, optionally add the already-classified EXTRA,
and look the multiset up in long_mul_table for a result of type
LHS_TYPE.  CANDIDATE is passed to per-row extra_check predicates.

If EXTRAS_OUT is non-NULL, leaves matching no summand are set aside
there instead of failing the match, and the caller must re-apply
them on top of the folded multiply.  A leaf that does match is
always consumed: if that makes the signature miss every row the
match fails, rather than retrying with the leaf demoted to an extra
(subset search would be exponential).

Returns the matched row and the half-width operands via
OUT_OP0/OUT_OP1, or NULL on a miss.  No IR mutation.   

References candidate(), long_mul_classify_match(), long_mul_classify_summand(), long_mul_hint_shared_intermediate(), long_mul_linearize_chain(), LONG_MUL_MAX_EXTRAS, LONG_MUL_MAX_SUMMANDS, long_mul_summand_compare(), and NULL.

Referenced by match_long_mul(), and match_long_mul_phi().

◆ long_mul_classify_hi_extract()

bool long_mul_classify_hi_extract ( tree inner,
unsigned HOST_WIDE_INT shift,
long_mul_summand * info )
static
Classify INNER -- already unwrapped from an outer (X >> SHIFT) -- as
a high-half-extracted summand.  mul_hilo (mult-shape) is orthogonal
to the plus-based kinds and is tried first; ladder_part_sum (one arm
unconstrained) and mul_cross_sum (any plus) are the fallbacks after
the shared plus-based ladder.   

References long_mul_summand::extract, gimple_mul_cross_sum(), gimple_mul_hilo(), gimple_mul_ladder_part_sum(), LMK_CROSS_SUM, LMK_LADDER_PART_SUM, LMK_MUL_HILO, LMX_HI, long_mul_classify_plus_kinds(), LONG_MUL_MAX_CAPTURES, long_mul_set_summand(), NULL, long_mul_summand::shift, and shift.

Referenced by long_mul_classify_summand().

◆ long_mul_classify_lo_extract()

bool long_mul_classify_lo_extract ( tree inner,
long_mul_summand * info )
static
Classify INNER -- already unwrapped from an outer (X & MASK) -- as
a low-half-masked summand.   

References long_mul_summand::extract, gimple_mul_lolo(), LMK_MUL_LOLO, LMX_LO, LONG_MUL_MAX_CAPTURES, long_mul_set_summand(), and NULL.

Referenced by long_mul_classify_summand().

◆ long_mul_classify_match()

const long_mul_row * long_mul_classify_match ( const vec< long_mul_summand > & summands,
tree lhs_type,
tree_code outer,
gimple * candidate_stmt,
tree * out_op0,
tree * out_op1 )
static
Search long_mul_table for a row whose multiset matches SUMMANDS for
outer kind OUTER on a result of type LHS_TYPE.  CANDIDATE_STMT is
passed to per-row extra_check predicates.  On a hit, returns the
matching row and writes the half-width operands via OUT_OP0/OUT_OP1.
No IR mutation.   

References GET_MODE_2XWIDER_MODE(), long_mul_row::HIGH_PART, is_a(), long_mul_check_consistency(), long_mul_signature_matches(), long_mul_table, NULL, optimize_widening_mul_active_p(), SSA_NAME_OCCURS_IN_ABNORMAL_PHI, TREE_CODE, and TYPE_MODE.

Referenced by long_mul_classify_chain().

◆ long_mul_classify_plus_kinds()

bool long_mul_classify_plus_kinds ( tree inner,
long_mul_summand * info )
static
Plus-based summand kinds shared by the (X >> SHIFT) and (X << SHIFT)
classifiers.  Order is by specificity: mul_low_sum's first arm is any
plus, so mul_ladder_sum1/3 (which constrain that arm to a plus
containing a mul_lo) and mul_low_accum (which constrains both arms)
shadow it and must come first.   

References gimple_mul_ladder_sum1(), gimple_mul_ladder_sum2(), gimple_mul_ladder_sum3(), gimple_mul_low_accum(), gimple_mul_low_sum(), LMK_LADDER_SUM1, LMK_LADDER_SUM2, LMK_LADDER_SUM3, LMK_LOW_ACCUM, LMK_LOW_SUM, LONG_MUL_MAX_CAPTURES, long_mul_set_summand(), and NULL.

Referenced by long_mul_classify_hi_extract(), and long_mul_classify_shl_extract().

◆ long_mul_classify_shl_extract()

bool long_mul_classify_shl_extract ( tree inner,
unsigned HOST_WIDE_INT shift,
long_mul_summand * info )
static
Classify INNER -- already unwrapped from an outer (X << SHIFT) -- as
a left-shifted summand.  No mul_hilo / ladder_part_sum here -- those
shapes appear only under (X >> SHIFT).   

References long_mul_summand::extract, gimple_mul_cross_sum(), LMK_CROSS_SUM, LMX_SHL_N, long_mul_classify_plus_kinds(), LONG_MUL_MAX_CAPTURES, long_mul_set_summand(), NULL, long_mul_summand::shift, and shift.

Referenced by long_mul_classify_summand().

◆ long_mul_classify_summand()

bool long_mul_classify_summand ( tree leaf,
long_mul_summand * info )
static
Classify LEAF as one of the long-multiply summand shapes.  On success,
fill *INFO with the kind, extract, captured operands and shift.
Dispatches to per-extract helpers; the order matters because the
carry kinds bake an lshift into the pattern and would otherwise be
misread by the (X << N) branch.   

References gimple_mul_hi(), gimple_mul_lo(), long_mul_classify_bare(), long_mul_classify_carry(), long_mul_classify_hi_extract(), long_mul_classify_lo_extract(), long_mul_classify_shl_extract(), long_mul_is_lshift_def(), LONG_MUL_MAX_CAPTURES, NULL, shift, and tree_to_uhwi().

Referenced by long_mul_classify_chain().

◆ long_mul_find_summand()

const long_mul_summand * long_mul_find_summand ( const vec< long_mul_summand > & summands,
long_mul_kind kind )
static
Return the first summand in SUMMANDS whose kind matches KIND, or NULL.   

References NULL.

Referenced by long_mul_check_two_carries().

◆ long_mul_hilo_orientation()

int long_mul_hilo_orientation ( tree h,
tree op0,
tree op1 )
static
Orientation of the mul_hilo capture H relative to (OP0, OP1):
returns 0 for high(OP0)*low(OP1), 1 for high(OP1)*low(OP0), or -1
if H does not decompose that way.  A cross-sum of two mul_hilos must
see one of each orientation -- otherwise a doubled factor would fold
to the wrong value.  (In a self-multiply the two orientations
coincide; see the OP0 == OP1 bypass in long_mul_check_consistency.)   

References gimple_mul_hilo(), LONG_MUL_MAX_CAPTURES, NULL, and scratch.

Referenced by long_mul_check_consistency().

◆ long_mul_hint_shared_intermediate()

void long_mul_hint_shared_intermediate ( gimple * shared_def)
static
If a multi-used inner addition (sharing the chain's outer code) blocked
linearization of a long-mul candidate, emit a dump-file hint pointing
at it.   

References dump_file, dump_flags, print_gimple_stmt(), TDF_DETAILS, and TDF_SLIM.

Referenced by long_mul_classify_chain().

◆ long_mul_is_cross_half()

bool long_mul_is_cross_half ( tree h,
tree op0,
tree op1 )
static
True if H is a cross-half product of (OP0, OP1) -- gimple_mul_hilo
recognizes it and its captured operands match the pair.   

References gimple_mul_hilo(), LONG_MUL_MAX_CAPTURES, long_mul_same_ops(), NULL, and scratch.

Referenced by long_mul_check_consistency(), and long_mul_check_two_carries().

◆ long_mul_is_lshift_def()

bool long_mul_is_lshift_def ( tree expr,
tree * inner_out,
unsigned HOST_WIDE_INT * shift_out )
static
If EXPR is defined by LSHIFT_EXPR with a uhwi-valued amount, return
the shifted input via *INNER_OUT and the amount via *SHIFT_OUT.   

References gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), is_gimple_assign(), SSA_NAME_DEF_STMT, TREE_CODE, tree_fits_uhwi_p(), and tree_to_uhwi().

Referenced by long_mul_check_two_carries(), and long_mul_classify_summand().

◆ long_mul_linearize_chain()

bool long_mul_linearize_chain ( gimple * stmt,
tree_code outer,
vec< tree > & leaves,
gimple ** shared_def_out = NULL )
static
Walk the OUTER addition or BIT_IOR chain rooted at STMT and collect
the leaf operands into LEAVES.  Descends through single-use
intermediate stmts of the same code.  Returns false once the leaf
count exceeds LONG_MUL_MAX_SUMMANDS + LONG_MUL_MAX_EXTRAS, so an
overlong chain bails mid-walk instead of after a full traversal.

If SHARED_DEF_OUT is non-NULL, record there the first inner stmt that
shares the outer code but has more than one use -- descending into it
would change semantics, so it stays as a leaf.  Such a leaf often
classifies as something no row matches, silently disabling the fold;
the caller surfaces this as a dump-file hint.   

References gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), has_single_use(), is_gimple_assign(), LONG_MUL_MAX_EXTRAS, LONG_MUL_MAX_SUMMANDS, NULL, SSA_NAME_DEF_STMT, and TREE_CODE.

Referenced by long_mul_classify_chain().

◆ long_mul_same_ops()

bool long_mul_same_ops ( tree a,
tree b,
tree op0,
tree op1 )
inlinestatic
True if (A, B) is the same pair as (OP0, OP1) in either order.   

References a, and b.

Referenced by long_mul_check_consistency(), long_mul_check_two_carries(), and long_mul_is_cross_half().

◆ long_mul_set_summand()

◆ long_mul_signature_matches()

bool long_mul_signature_matches ( const vec< long_mul_summand > & summands,
const long_mul_row & row )
static
Compare the (already-sorted) SUMMANDS multiset against ROW.sig.   

References long_mul_row::count, long_mul_row::extract, i, long_mul_row::kind, and long_mul_row::sig.

Referenced by long_mul_classify_match().

◆ long_mul_summand_compare()

int long_mul_summand_compare ( const void * a,
const void * b )
static
qsort comparator: sort summands by (kind, extract) to put a multiset
into canonical order for table lookup.  Unstable sort within a tie is
harmless: no row in long_mul_table pairs distinct subterms under the
same (kind, extract), and long_mul_check_consistency cross-validates
that matching summands share one canonical (op0, op1).   

References a, b, long_mul_summand::extract, and long_mul_summand::kind.

Referenced by long_mul_classify_chain().

◆ make_pass_forwprop()

gimple_opt_pass * make_pass_forwprop ( gcc::context * ctxt)

◆ match_long_mul()

bool match_long_mul ( gassign * stmt)
static
Top-level entry for long-multiply folding.  Walks STMT's outer
addition or BIT_IOR chain, classifies the summands, and dispatches
to create_mul_high_seq / create_mul_low_seq if the multiset matches
a known long-multiply form.  Returns true on success.   

References create_mul_high_seq(), create_mul_low_seq(), dump_file, dump_flags, gimple_assign_lhs(), gimple_assign_rhs_code(), gimple_bb(), long_mul_row::HIGH_PART, INTEGRAL_TYPE_P, is_gimple_assign(), long_mul_classify_chain(), NULL, long_mul_row::part, single_imm_use(), TDF_DETAILS, TREE_TYPE, TYPE_PRECISION, and TYPE_UNSIGNED.

◆ match_long_mul_phi()

bool match_long_mul_phi ( gphi * phi)
static
PHI-driven entry for long-multiply folding.  When PHI's value
flattens to base + (carry << N), probe sum to classify the carry
kind, linearize base for the remaining high-part summands, and run
the long-multiply table.  On a hit, emit a 2N-bit multiply at the
top of the join block with PHI_RES as its LHS and remove the PHI.
Otherwise leave the IR untouched.  Only HIGH_PART rows are
reachable.  LOW_PART rows are BIT_IOR-shaped and never produce a
carry PHI.   

References build_mul_high_seq(), long_mul_summand::carry_a, long_mul_summand::carry_b, dump_file, dump_flags, wi::exact_log2(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_bb(), gimple_cond_carry_add(), gimple_cond_carry_add_neg(), gimple_location(), gimple_mul_cross_sum(), gimple_mul_low_sum(), gimple_phi_result(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_seq_before(), GSI_SAME_STMT, long_mul_row::HIGH_PART, long_mul_summand::hilo0, long_mul_summand::hilo1, long_mul_summand::hilo2, INTEGRAL_TYPE_P, is_gimple_assign(), long_mul_summand::kind, LMK_CARRY_CROSS_SUM, LMK_CARRY_LOW, LMK_CARRY_LOW_SUM, long_mul_classify_chain(), LONG_MUL_MAX_CAPTURES, NULL, long_mul_summand::op0, long_mul_summand::op1, long_mul_row::part, remove_phi_node(), long_mul_summand::shift, SSA_NAME_DEF_STMT, TDF_DETAILS, wi::to_wide(), TREE_CODE, TREE_TYPE, TYPE_PRECISION, and TYPE_UNSIGNED.

◆ narrow_vec_perm_simplify_seq()

void narrow_vec_perm_simplify_seq ( const vec_perm_simplify_seq & seq)
static

◆ new_src_based_on_copy()

tree new_src_based_on_copy ( tree src2,
tree dest,
tree src )
static
Returns a new src based on the
copy `DEST = SRC` and for the old SRC2.
Returns null if SRC2 is not related to DEST.   

References cst_and_fits_in_hwi(), DECL_P, fold_build1, fold_build2, fold_convert, int_cst_value(), known_eq, NULL_TREE, operand_equal_p(), split_core_and_offset_size(), TREE_CODE, and TREE_TYPE.

Referenced by optimize_agr_copyprop_1(), optimize_agr_copyprop_arg(), and optimize_agr_copyprop_return().

◆ optimize_aggr_zeroprop()

◆ optimize_aggr_zeroprop_1()

◆ optimize_agr_copyprop()

void optimize_agr_copyprop ( gimple * stmt)
static
Optimizes
  DEST = SRC;
  DEST2 = DEST; # DEST2 = SRC2;
  into
  DEST = SRC;
  DEST2 = SRC;
  STMT is the first statement and SRC is the common
  between the statements.

  Also optimizes:
  DEST = SRC;
  call_func(..., DEST, ...);
  into:
  DEST = SRC;
  call_func(..., SRC, ...);

References as_a(), cfun, FOR_EACH_IMM_USE_STMT, gimple_assign_lhs(), gimple_assign_load_p(), gimple_assign_rhs1(), gimple_has_volatile_ops(), gimple_store_p(), gimple_vdef(), is_a(), is_gimple_call(), optimize_agr_copyprop_1(), optimize_agr_copyprop_arg(), optimize_agr_copyprop_return(), same_for_assignment(), _vec_perm_simplify_seq::stmt, and stmt_could_throw_p().

◆ optimize_agr_copyprop_1()

◆ optimize_agr_copyprop_arg()

void optimize_agr_copyprop_arg ( gimple * defstmt,
gcall * call,
tree dest,
tree src )
static
Helper function for optimize_agr_copyprop_1, propagate aggregates
into the arguments of USE_STMT if the argument matches with DEST;
replacing it with SRC.   

References changed, dump_file, dump_flags, gimple_call_arg_ptr(), gimple_call_num_args(), is_gimple_min_invariant(), new_src_based_on_copy(), print_gimple_stmt(), TDF_DETAILS, TREE_CODE, TREE_TYPE, TYPE_VOLATILE, unshare_expr(), and update_stmt().

Referenced by optimize_agr_copyprop().

◆ optimize_agr_copyprop_return()

void optimize_agr_copyprop_return ( gimple * defstmt,
greturn * use,
tree dest,
tree src )
static
Helper function for optimize_agr_copyprop, propagate aggregates
into the return stmt USE if the operand of the return matches DEST;
replacing it with SRC.   

References dump_file, dump_flags, gimple_return_retval(), gimple_return_set_retval(), is_gimple_min_invariant(), is_global_var(), new_src_based_on_copy(), print_gimple_stmt(), SSA_NAME_VAR, TDF_DETAILS, TREE_CODE, TREE_OPERAND, TREE_TYPE, TYPE_VOLATILE, update_stmt(), and VAR_P.

Referenced by optimize_agr_copyprop().

◆ optimize_stack_restore()

bool optimize_stack_restore ( gimple_stmt_iterator * gsi,
gimple * call )
static
Try to optimize out __builtin_stack_restore.  Optimize it out
if there is another __builtin_stack_restore in the same basic
block and no calls or ASM_EXPRs are in between, or if this block's
only outgoing edge is to EXIT_BLOCK and there are no calls or
ASM_EXPRs after this __builtin_stack_restore.
Note restore right before a noreturn function is not needed.
And skip some cheap calls that will most likely become an instruction.
Restoring the stack before a call is important to be able to keep
stack usage down so that call does not run out of stack.   

References build_int_cst(), cfun, dyn_cast(), EDGE_COUNT, EXIT_BLOCK_PTR_FOR_FN, fndecl_built_in_p(), fndecl_builtin_alloc_p(), fold_before_rtl_expansion_p(), gimple_call_arg(), gimple_call_fndecl(), gimple_call_internal_p(), gimple_call_noreturn_p(), gimple_call_num_args(), gsi_bb(), gsi_end_p(), gsi_for_stmt(), gsi_next(), gsi_stmt(), has_single_use(), i, is_a(), is_gimple_call(), is_inexpensive_builtin(), is_simple_builtin(), NULL_TREE, POINTER_TYPE_P, replace_call_with_value(), single_succ_edge(), SSA_NAME_DEF_STMT, _vec_perm_simplify_seq::stmt, basic_block_def::succs, TREE_CODE, and TREE_TYPE.

Referenced by simplify_builtin_call().

◆ optimize_strlen_comp()

◆ optimize_vector_load()

◆ prepare_target_mem_ref_lvalue()

tree prepare_target_mem_ref_lvalue ( tree ref,
gimple_stmt_iterator * gsi )
static
Prepare a TARGET_MEM_REF ref so that it can be subsetted as
lvalue.  This splits out an address computation stmt before *GSI
and returns a MEM_REF wrapping the address.   

References build1(), build2_loc(), build_int_cst(), build_pointer_type(), EXPR_LOCATION, gimple_build_assign(), gsi_insert_before(), GSI_SAME_STMT, make_ssa_name(), mark_addressable(), TREE_CODE, TREE_OPERAND, TREE_TYPE, and unshare_expr().

Referenced by optimize_vector_load().

◆ process_vec_perm_simplify_seq_list()

void process_vec_perm_simplify_seq_list ( vec< vec_perm_simplify_seq > * l)
static
Try to blend narrowed vec_perm_simplify_seqs pairwise.
The provided list will be empty after this call.   

References blend_vec_perm_simplify_seqs(), calc_perm_vec_perm_simplify_seqs(), can_blend_vec_perm_simplify_seqs_p(), dump_file, dump_flags, FOR_EACH_VEC_ELT, FOR_EACH_VEC_ELT_FROM, i, narrow_vec_perm_simplify_seq(), and TDF_DETAILS.

Referenced by append_vec_perm_simplify_seq_list().

◆ recognise_vec_perm_simplify_seq()

bool recognise_vec_perm_simplify_seq ( gassign * stmt,
vec_perm_simplify_seq * seq )
static
Search for opportunities to free half of the lanes in the following pattern:

  v_in = {e0, e1, e2, e3}
  v_1 = VEC_PERM <v_in, v_in, {0, 2, 0, 2}>
  // v_1 = {e0, e2, e0, e2}
  v_2 = VEC_PERM <v_in, v_in, {1, 3, 1, 3}>
  // v_2 = {e1, e3, e1, e3}

  v_x = v_1 + v_2
  // v_x = {e0+e1, e2+e3, e0+e1, e2+e3}
  v_y = v_1 - v_2
  // v_y = {e0-e1, e2-e3, e0-e1, e2-e3}

  v_out = VEC_PERM <v_x, v_y, {0, 1, 6, 7}>
  // v_out = {e0+e1, e2+e3, e0-e1, e2-e3}

The last statement could be simplified to:
  v_out' = VEC_PERM <v_x, v_y, {0, 1, 4, 5}>
  // v_out' = {e0+e1, e2+e3, e0-e1, e2-e3}

Characteristic properties:
- v_1 and v_2 are created from the same input vector v_in and introduce the
  lane duplication (in the selection operand) that we can eliminate.
- v_x and v_y are results from lane-preserving operations that use v_1 and
  v_2 as inputs.
- v_out is created by selecting from duplicated lanes.   

References can_vec_perm_const_p(), commutative_tree_code(), dump_file, dump_flags, dyn_cast(), gcc_checking_assert, gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs3(), gimple_assign_rhs_code(), gimple_bb(), has_single_use(), i, num_imm_uses(), print_generic_expr(), print_gimple_stmt(), SSA_NAME_DEF_STMT, tcc_binary, TDF_DETAILS, TREE_CODE, TREE_CODE_CLASS, TREE_INT_CST_LOW, TREE_TYPE, TYPE_MODE, vect_gen_perm_mask_checked(), VECTOR_CST_ELT, and VECTOR_CST_NELTS.

◆ remove_prop_source_from_use()

void remove_prop_source_from_use ( tree name)
static
Remove a chain of dead statements starting at the definition of
NAME.  The chain is linked via the first operand of the defining statements.
If NAME was replaced in its only use then this function can be used
to clean up dead stmts.  The function handles already released SSA
names gracefully.   

References bitmap_set_bit, fwprop_invalidate_lattice(), gimple_assign_rhs1(), gimple_bb(), gimple_get_lhs(), gimple_has_side_effects(), gsi_for_stmt(), gsi_remove(), has_zero_uses(), basic_block_def::index, is_gimple_assign(), NULL_TREE, release_defs(), SSA_NAME_DEF_STMT, SSA_NAME_IN_FREE_LIST, SSA_NAME_IS_DEFAULT_DEF, _vec_perm_simplify_seq::stmt, to_purge, TREE_CODE, and unlink_stmt_vdef().

Referenced by forward_propagate_into_comparison(), forward_propagate_into_gimple_cond(), and simplify_permutation().

◆ rhs_to_tree()

tree rhs_to_tree ( tree type,
gimple * stmt )
static
Return the rhs of a gassign *STMT in a form of a single tree,
converted to type TYPE.

This should disappear, but is needed so we can combine expressions and use
the fold() interfaces. Long term, we need to develop folding and combine
routines that deal with gimple exclusively .  

References build1(), fold_build2_loc(), fold_build3_loc(), gcc_unreachable, get_gimple_rhs_class(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs3(), gimple_assign_rhs_code(), GIMPLE_BINARY_RHS, gimple_location(), GIMPLE_SINGLE_RHS, GIMPLE_TERNARY_RHS, GIMPLE_UNARY_RHS, and _vec_perm_simplify_seq::stmt.

Referenced by forward_propagate_into_comparison_1().

◆ same_for_assignment()

bool same_for_assignment ( tree src,
tree dest )
static
Returns true if SRC and DEST are the same address such that
`SRC == DEST;` is considered a nop. This is more than an
operand_equal_p check as it needs to be similar to
new_src_based_on_copy.   

References cst_and_fits_in_hwi(), DECL_P, fold_build2, fold_convert, int_cst_value(), known_eq, operand_equal_p(), split_core_and_offset_size(), and TREE_TYPE.

Referenced by optimize_agr_copyprop(), and optimize_agr_copyprop_1().

◆ simplify_builtin_call()

bool simplify_builtin_call ( gimple_stmt_iterator * gsi_p,
tree callee2,
bool full_walk )
static
*GSI_P is a GIMPLE_CALL to a builtin function.
Optimize
memcpy (p, "abcd", 4);
memset (p + 4, ' ', 3);
into
memcpy (p, "abcd   ", 7);
call if the latter can be stored by pieces during expansion.

Optimize
memchr ("abcd", a, 4) == 0;
or
memchr ("abcd", a, 4) != 0;
to
(a == 'a' || a == 'b' || a == 'c' || a == 'd') == 0
or
(a == 'a' || a == 'b' || a == 'c' || a == 'd') != 0

Also canonicalize __atomic_fetch_op (p, x, y) op x
to __atomic_op_fetch (p, x, y) or
__atomic_op_fetch (p, x, y) iop x
to __atomic_fetch_op (p, x, y) when possible (also __sync).   

References a, as_a(), build_zero_cst(), builtin_decl_explicit(), CASE_ATOMIC, DECL_FUNCTION_CODE(), END_BUILTINS, fold_convert, FOR_EACH_IMM_USE_STMT, g, gcc_assert, gcc_unreachable, gimple_assign_cast_p(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), gimple_assign_rhs_code(), gimple_assign_set_rhs1(), gimple_assign_set_rhs2(), gimple_assign_set_rhs_with_ops(), GIMPLE_BINARY_RHS, gimple_build_assign(), gimple_call_arg(), gimple_call_lhs(), gimple_call_num_args(), gimple_call_set_fndecl(), gimple_call_set_lhs(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_cond_set_lhs(), gimple_cond_set_rhs(), gimple_debug_bind_reset_value(), gsi_for_stmt(), gsi_insert_after(), GSI_NEW_STMT, gsi_remove(), gsi_stmt(), INTEGRAL_TYPE_P, is_gimple_assign(), is_gimple_debug(), make_ssa_name(), wi::neg(), NULL, NULL_TREE, operand_equal_p(), optimize_aggr_zeroprop(), optimize_stack_restore(), optimize_strlen_comp(), release_ssa_name(), simplify_builtin_memchr(), simplify_builtin_memcmp(), simplify_builtin_memcpy_memset(), single_imm_use(), SSA_NAME_DEF_STMT, stmt_ends_bb_p(), wi::to_wide(), TREE_CODE, TREE_TYPE, TYPE_PRECISION, update_stmt(), and useless_type_conversion_p().

◆ simplify_builtin_memchr()

◆ simplify_builtin_memcmp()

◆ simplify_builtin_memcpy_memset()

bool simplify_builtin_memcpy_memset ( gimple_stmt_iterator * gsi_p,
gcall * stmt2 )
static

◆ simplify_count_zeroes()

bool simplify_count_zeroes ( gimple_stmt_iterator * gsi)
static

◆ simplify_gimple_switch()

bool simplify_gimple_switch ( gswitch * stmt,
vec< std::pair< int, int > > & edges_to_remove,
bitmap simple_dce_worklist )
static

◆ simplify_gimple_switch_label_vec()

void simplify_gimple_switch_label_vec ( gswitch * stmt,
tree index_type,
vec< std::pair< int, int > > & edges_to_remove )
static

◆ simplify_permutation()

◆ simplify_rotate()

bool simplify_rotate ( gimple_stmt_iterator * gsi)
static
Recognize rotation patterns.  Return true if a transformation
applied, otherwise return false.

We are looking for X with unsigned type T with bitsize B, OP being
+, | or ^, some type T2 wider than T.  For:
(X << CNT1) OP (X >> CNT2)                              iff CNT1 + CNT2 == B
((T) ((T2) X << CNT1)) OP ((T) ((T2) X >> CNT2))        iff CNT1 + CNT2 == B

transform these into:
X r<< CNT1

Or for:
(X << Y) OP (X >> (B - Y))
(X << (int) Y) OP (X >> (int) (B - Y))
((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y)))
((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) (B - Y)))
(X << Y) | (X >> ((-Y) & (B - 1)))
(X << (int) Y) | (X >> (int) ((-Y) & (B - 1)))
((T) ((T2) X << Y)) | ((T) ((T2) X >> ((-Y) & (B - 1))))
((T) ((T2) X << (int) Y)) | ((T) ((T2) X >> (int) ((-Y) & (B - 1))))

transform these into (last 2 only if ranger can prove Y < B
or Y = N * B):
X r<< Y
or
X r<< (& & (B - 1))
The latter for the forms with T2 wider than T if ranger can't prove Y < B.

Or for:
(X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1)))
(X << (int) (Y & (B - 1))) | (X >> (int) ((-Y) & (B - 1)))
((T) ((T2) X << (Y & (B - 1)))) | ((T) ((T2) X >> ((-Y) & (B - 1))))
((T) ((T2) X << (int) (Y & (B - 1)))) \
  | ((T) ((T2) X >> (int) ((-Y) & (B - 1))))

transform these into:
X r<< (Y & (B - 1))

Note, in the patterns with T2 type, the type of OP operands
might be even a signed type, but should have precision B.
Expressions with & (B - 1) should be recognized only if B is
a power of 2.   

References build_int_cst(), cfun, CONVERT_EXPR_CODE_P, defcodefor_name(), enable_ranger(), floor_log2(), wide_int_storage::from(), g, get_global_range_query(), get_range_query(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_build_assign(), gsi_insert_before(), gsi_replace(), GSI_SAME_STMT, gsi_stmt(), has_single_use(), i, INTEGRAL_TYPE_P, make_ssa_name(), MIN, NULL, NULL_TREE, operand_equal_for_phi_arg_p(), pow2p_hwi(), r, range_query::range_of_expr(), SSA_NAME_DEF_STMT, _vec_perm_simplify_seq::stmt, TREE_CODE, tree_fits_shwi_p(), tree_fits_uhwi_p(), tree_to_shwi(), tree_to_uhwi(), TREE_TYPE, type_has_mode_precision_p(), TYPE_PRECISION, TYPE_SIGN, TYPE_UNSIGNED, types_compatible_p(), irange::union_(), and useless_type_conversion_p().

◆ simplify_vector_constructor()

◆ split_core_and_offset_size()

tree split_core_and_offset_size ( tree expr,
poly_int64 * pbytesize,
poly_int64 * pbytepos,
tree * poffset,
int * preversep )
static
Returns the pointer to the base of the object of the
reference EXPR and extracts the information about
the offset of the access, storing it to PBYTESIZE,
PBYTEPOS and PREVERSEP.
If the access is not a byte sized or position is not
on the byte, return NULL.   

References build_fold_addr_expr_loc(), EXPR_LOCATION, get_inner_reference(), NULL_TREE, STRIP_NOPS, wi::to_poly_offset(), poly_int< N, C >::to_shwi(), TREE_CODE, and TREE_OPERAND.

Referenced by new_src_based_on_copy(), and same_for_assignment().

◆ tidy_after_forward_propagate_addr()

void tidy_after_forward_propagate_addr ( gimple * stmt)
static
We've just substituted an ADDR_EXPR into stmt.  Update all the
relevant data structures to match.   

References bitmap_set_bit, gimple_assign_rhs1(), gimple_bb(), maybe_clean_or_replace_eh_stmt(), recompute_tree_invariant_for_addr_expr(), _vec_perm_simplify_seq::stmt, to_purge, and TREE_CODE.

Referenced by forward_propagate_addr_expr_1().

Variable Documentation

◆ cfg_changed

◆ lattice

◆ LONG_MUL_MAX_CAPTURES

◆ LONG_MUL_MAX_EXTRAS

unsigned LONG_MUL_MAX_EXTRAS = 4
staticconstexpr
Cap on the leaves set aside as not part of the idiom, so an
arbitrarily long unrelated chain still bails early.   

Referenced by long_mul_classify_chain(), and long_mul_linearize_chain().

◆ LONG_MUL_MAX_SUMMANDS

unsigned LONG_MUL_MAX_SUMMANDS = 4
staticconstexpr
Longest variant in long_mul_table has 4 summands.   

Referenced by long_mul_classify_chain(), and long_mul_linearize_chain().

◆ long_mul_table

const long_mul_row long_mul_table[]
static
Long-multiply variant table.  Each row enumerates the multiset of
(kind, extract) summands that compose one long-multiply form.  Rows
are sorted by long_mul_summand_compare, matching the input summands'
sort order, so a plain element-wise compare suffices.  Rows describe
unsigned schoolbook expansions on an even-width 2N-bit type split at
half-width N; EXTRA_CHECK carries invariants the (kind, extract)
signature cannot express.

The formula on each row uses xh, xl, yh, yl for the half-width pieces
of x and y, cross_sum for xh*yl + xl*yh, and hilo for either cross-half
product (consumers validate the operand shape).   

Referenced by long_mul_classify_match().

◆ to_purge