GCC Middle and Back End API Reference
tree-ssa-phiopt.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "insn-codes.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
#include "tree-ssa.h"
#include "optabs-tree.h"
#include "insn-config.h"
#include "gimple-pretty-print.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "cfganal.h"
#include "gimplify.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "tree-cfg.h"
#include "tree-dfa.h"
#include "domwalk.h"
#include "cfgloop.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
#include "tree-inline.h"
#include "case-cfn-macros.h"
#include "tree-eh.h"
#include "gimple-fold.h"
#include "internal-fn.h"
#include "gimple-range.h"
#include "gimple-match.h"
#include "dbgcnt.h"
#include "tree-ssa-propagate.h"
#include "tree-ssa-dce.h"
Include dependency graph for tree-ssa-phiopt.cc:

Data Structures

class  auto_flow_sensitive
 
struct  ref_to_bb
 
struct  refs_hasher
 
class  nontrapping_dom_walker
 

Functions

static gphisingle_non_singleton_phi_for_edges (gimple_seq seq, edge e0, edge e1)
 
static void replace_phi_edge_with_variable (basic_block cond_block, edge e, gphi *phi, tree new_tree, bitmap dce_ssa_names=nullptr)
 
static gphifactor_out_conditional_operation (edge e0, edge e1, gphi *phi, tree arg0, tree arg1, gimple *cond_stmt)
 
static bool phiopt_early_allow (gimple_seq &seq, gimple_match_op &op)
 
static tree gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt, tree arg0, tree arg1, gimple_seq *seq)
 
static bool empty_bb_or_one_feeding_into_p (basic_block bb, gimple *phi, gimple *&stmt)
 
static void move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, auto_bitmap &inserted_exprs)
 
static bool match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, basic_block middle_bb_alt, edge e0, edge e1, gphi *phi, tree arg0, tree arg1, bool early_p, bool threeway_p)
 
static bool jump_function_from_stmt (tree *arg, gimple *stmt)
 
static bool rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1, enum tree_code *code, const_tree rhs)
 
static bool operand_equal_for_value_replacement (const_tree arg0, const_tree arg1, enum tree_code *code, gimple *cond)
 
static bool neutral_element_p (tree_code code, tree arg, bool right)
 
static bool absorbing_element_p (tree_code code, tree arg, bool right, tree rval)
 
static int value_replacement (basic_block cond_bb, basic_block middle_bb, edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
 
static tree strip_bit_not (tree var)
 
enum tree_code invert_minmax_code (enum tree_code code)
 
static bool minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block alt_middle_bb, edge e0, edge e1, gphi *phi, tree arg0, tree arg1, bool threeway_p)
 
static bool spaceship_replacement (basic_block cond_bb, basic_block middle_bb, edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
 
static bool cond_removal_in_builtin_zero_pattern (basic_block cond_bb, basic_block middle_bb, edge e1, edge e2, gphi *phi, tree arg0, tree arg1)
 
static hash_set< tree > * get_non_trapping (void)
 
static bool cond_store_replacement (basic_block middle_bb, basic_block join_bb, edge e0, edge e1, hash_set< tree > *nontrap)
 
static bool cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, basic_block join_bb, gimple *then_assign, gimple *else_assign)
 
static gimplesingle_trailing_store_in_bb (basic_block bb, tree vdef)
 
static bool cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, basic_block join_bb)
 
static bool local_mem_dependence (gimple *stmt, basic_block bb)
 
static void hoist_adjacent_loads (basic_block bb0, basic_block bb1, basic_block bb2, basic_block bb3)
 
static bool gate_hoist_loads (void)
 
gimple_opt_passmake_pass_phiopt (gcc::context *ctxt)
 
gimple_opt_passmake_pass_cselim (gcc::context *ctxt)
 

Variables

static unsigned int nt_call_phase
 

Function Documentation

◆ absorbing_element_p()

static bool absorbing_element_p ( tree_code code,
tree arg,
bool right,
tree rval )
static
Returns true if ARG is an absorbing element for operation CODE.   

References ggc_alloc(), integer_all_onesp(), integer_zerop(), NULL, and tree_single_nonzero_warnv_p().

Referenced by value_replacement().

◆ cond_if_else_store_replacement()

static bool cond_if_else_store_replacement ( basic_block then_bb,
basic_block else_bb,
basic_block join_bb )
static
Conditional store replacement.  We already know
that the recognized pattern looks like so:

split:
  if (cond) goto THEN_BB; else goto ELSE_BB (edge E1)
THEN_BB:
  ...
  X = Y;
  ...
  goto JOIN_BB;
ELSE_BB:
  ...
  X = Z;
  ...
  fallthrough (edge E0)
JOIN_BB:
  some more

We check that it is safe to sink the store to JOIN_BB by verifying that
there are no read-after-write or write-after-write dependencies in
THEN_BB and ELSE_BB.   

References chrec_dont_know, chrec_known, compute_all_dependences(), cond_if_else_store_replacement_1(), DDR_A, DDR_ARE_DEPENDENT, DDR_B, DR_IS_READ, DR_IS_WRITE, DR_STMT, find_data_references_in_bb(), FOR_EACH_VEC_ELT, free_data_refs(), free_dependence_relations(), ggc_alloc(), gimple_get_lhs(), gimple_phi_result(), gimple_uid(), gsi_end_p(), gsi_next(), gsi_start_phis(), i, NULL, NULL_TREE, operand_equal_p(), PHI_ARG_DEF_FROM_EDGE, renumber_gimple_stmt_uids_in_blocks(), si, single_succ_edge(), single_trailing_store_in_bb(), virtual_operand_p(), and vNULL.

◆ cond_if_else_store_replacement_1()

◆ cond_removal_in_builtin_zero_pattern()

static bool cond_removal_in_builtin_zero_pattern ( basic_block cond_bb,
basic_block middle_bb,
edge e1,
edge e2,
gphi * phi,
tree arg0,
tree arg1 )
static
Optimize x ? __builtin_fun (x) : C, where C is __builtin_fun (0).
Convert

<bb 2>
if (b_4(D) != 0)
goto <bb 3>
else
goto <bb 4>

<bb 3>
_2 = (unsigned long) b_4(D);
_9 = __builtin_popcountl (_2);
OR
_9 = __builtin_popcountl (b_4(D));

<bb 4>
c_12 = PHI <0(2), _9(3)>

Into
<bb 2>
_2 = (unsigned long) b_4(D);
_9 = __builtin_popcountl (_2);
OR
_9 = __builtin_popcountl (b_4(D));

<bb 4>
c_12 = PHI <_9(2)>

Similarly for __builtin_clz or __builtin_ctz if
C?Z_DEFINED_VALUE_AT_ZERO is 2, optab is present and
instead of 0 above it uses the value from that macro.   

References build_int_cst(), CLZ_DEFINED_VALUE_AT_ZERO, CONVERT_EXPR_CODE_P, CTZ_DEFINED_VALUE_AT_ZERO, direct_internal_fn_supported_p(), ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_build_call_internal(), gimple_call_arg(), gimple_call_combined_fn(), gimple_call_internal_p(), gimple_call_num_args(), gimple_call_set_lhs(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_get_lhs(), gsi_end_p(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_move_before(), gsi_next_nondebug(), gsi_remove(), GSI_SAME_STMT, gsi_start_nondebug_after_labels_bb(), gsi_stmt(), IFN_LAST, integer_type_node, integer_zerop(), INTEGRAL_TYPE_P, is_gimple_call(), long_integer_type_node, long_long_integer_type_node, NULL, NULL_TREE, OPTIMIZE_FOR_BOTH, replace_phi_edge_with_variable(), reset_flow_sensitive_info(), SCALAR_INT_TYPE_MODE, wi::to_wide(), TREE_CODE, tree_fits_shwi_p(), tree_to_shwi(), TREE_TYPE, and TYPE_PRECISION.

◆ cond_store_replacement()

static bool cond_store_replacement ( basic_block middle_bb,
basic_block join_bb,
edge e0,
edge e1,
hash_set< tree > * nontrap )
static
Do the main work of conditional store replacement.  We already know
that the recognized pattern looks like so:

split:
  if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1)
MIDDLE_BB:
  something
  fallthrough (edge E0)
JOIN_BB:
  some more

We check that MIDDLE_BB contains only one store, that that store
doesn't trap (not via NOTRAP, but via checking if an access to the same
memory location dominates us, or the store is to a local addressable
object) and that the store has a "simple" RHS.   

References add_phi_arg(), auto_var_p(), build2(), build_fold_addr_expr, build_zero_cst(), cfun, create_phi_node(), DECL_P, dump_file, dump_flags, fold_convert, get_base_address(), ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_build_assign(), gimple_has_volatile_ops(), gimple_location(), gimple_seq_empty_p(), gimple_set_location(), gsi_after_labels(), gsi_end_p(), gsi_for_stmt(), gsi_insert_after(), gsi_insert_before(), gsi_insert_on_edge(), gsi_last_bb(), GSI_NEW_STMT, gsi_remove(), handled_component_p(), is_gimple_reg_type(), last_and_only_stmt(), make_temp_ssa_name(), NULL, phi_nodes(), PHI_RESULT, print_gimple_stmt(), ptr_type_node, REFERENCE_CLASS_P, release_defs(), statistics_counter_event(), suppress_warning(), TDF_DETAILS, TDF_MEMSYMS, TDF_VOPS, TREE_ADDRESSABLE, TREE_CODE, tree_could_trap_p(), TREE_OPERAND, TREE_TYPE, unlink_stmt_vdef(), and unshare_expr().

◆ empty_bb_or_one_feeding_into_p()

static bool empty_bb_or_one_feeding_into_p ( basic_block bb,
gimple * phi,
gimple *& stmt )
static

◆ factor_out_conditional_operation()

◆ gate_hoist_loads()

static bool gate_hoist_loads ( void )
static
Determine whether we should attempt to hoist adjacent loads out of
diamond patterns in pass_phiopt.  Always hoist loads if
-fhoist-adjacent-loads is specified and the target machine has
both a conditional move instruction and a defined cache line size.   

References ggc_alloc().

◆ get_non_trapping()

static hash_set< tree > * get_non_trapping ( void )
static
This is the entry point of gathering non trapping memory accesses.
It will do a dominator walk over the whole function, and it will
make use of the bb->aux pointers.  It returns a set of trees
(the MEM_REFs itself) which can't trap.   

References CDI_DOMINATORS, cfun, clear_aux_for_blocks(), ggc_alloc(), nt_call_phase, and dom_walker::walk().

◆ gimple_simplify_phiopt()

static tree gimple_simplify_phiopt ( bool early_p,
tree type,
gimple * comp_stmt,
tree arg0,
tree arg1,
gimple_seq * seq )
static
gimple_simplify_phiopt is like gimple_simplify but designed for PHIOPT.
Return NULL if nothing can be simplified or the resulting simplified value
with parts pushed if EARLY_P was true. Also rejects non allowed tree code
if EARLY_P is set.
Takes the comparison from COMP_STMT and two args, ARG0 and ARG1 and tries
to simplify CMP ? ARG0 : ARG1.
Also try to simplify (!CMP) ? ARG1 : ARG0 if the non-inverse failed.   

References annotate_all_with_location(), boolean_type_node, build2_loc(), cmp1(), dump_file, dump_flags, follow_all_ssa_edges(), ggc_alloc(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_location(), gimple_seq_add_seq_without_update(), gimple_seq_discard(), HONOR_NANS(), invert_tree_comparison(), maybe_push_res_to_seq(), NULL, phiopt_early_allow(), print_generic_expr(), print_gimple_seq(), gimple_match_op::resimplify(), TDF_FOLDING, TDF_MEMSYMS, TDF_VOPS, gimple_match_cond::UNCOND, and UNKNOWN_LOCATION.

Referenced by match_simplify_replacement().

◆ hoist_adjacent_loads()

static void hoist_adjacent_loads ( basic_block bb0,
basic_block bb1,
basic_block bb2,
basic_block bb3 )
static
Given a "diamond" control-flow pattern where BB0 tests a condition,
BB1 and BB2 are "then" and "else" blocks dependent on this test,
and BB3 rejoins control flow following BB1 and BB2, look for
opportunities to hoist loads as follows.  If BB3 contains a PHI of
two loads, one each occurring in BB1 and BB2, and the loads are
provably of adjacent fields in the same structure, then move both
loads into BB0.  Of course this can only be done if there are no
dependencies preventing such motion.

One of the hoisted loads will always be speculative, so the
transformation is currently conservative:

 - The fields must be strictly adjacent.
 - The two fields must occupy a single memory block that is
   guaranteed to not cross a page boundary.

 The last is difficult to prove, as such memory blocks should be
 aligned on the minimum of the stack alignment boundary and the
 alignment guaranteed by heap allocation interfaces.  Thus we rely
 on a parameter for the alignment value.

 Provided a good value is used for the last case, the first
 restriction could possibly be relaxed.   

References bit_position(), cfun, DECL_ALIGN, DECL_CHAIN, DECL_SIZE, dump_file, dump_flags, ggc_alloc(), gimple_assign_rhs1(), gimple_assign_single_p(), gimple_bb(), gimple_has_volatile_ops(), gimple_phi_arg_def(), gimple_phi_num_args(), gimple_phi_result(), gsi_end_p(), gsi_for_stmt(), gsi_move_to_bb_end(), gsi_next(), gsi_start_phis(), local_mem_dependence(), operand_equal_p(), optab_handler(), gphi_iterator::phi(), print_gimple_stmt(), SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, statistics_counter_event(), TDF_DETAILS, TDF_MEMSYMS, TDF_VOPS, TREE_CODE, tree_fits_uhwi_p(), TREE_OPERAND, tree_to_uhwi(), TREE_TYPE, TYPE_MODE, and virtual_operand_p().

◆ invert_minmax_code()

enum tree_code invert_minmax_code ( enum tree_code code)
Invert a MIN to a MAX or a MAX to a MIN expression CODE.   

References gcc_unreachable, and ggc_alloc().

Referenced by minmax_replacement().

◆ jump_function_from_stmt()

static bool jump_function_from_stmt ( tree * arg,
gimple * stmt )
static
Update *ARG which is defined in STMT so that it contains the
computed value if that seems profitable.  Return true if the
statement is made dead by that rewriting.   

References get_addr_base_and_unit_offset(), ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs_code(), known_eq, mem_ref_offset(), offset, TREE_CODE, and TREE_OPERAND.

Referenced by value_replacement().

◆ local_mem_dependence()

static bool local_mem_dependence ( gimple * stmt,
basic_block bb )
static
Return TRUE if STMT has a VUSE whose corresponding VDEF is in BB.   

References gimple_bb(), gimple_vuse(), SSA_NAME_DEF_STMT, and data_reference::stmt.

Referenced by hoist_adjacent_loads().

◆ make_pass_cselim()

gimple_opt_pass * make_pass_cselim ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_phiopt()

gimple_opt_pass * make_pass_phiopt ( gcc::context * ctxt)

References ggc_alloc().

◆ match_simplify_replacement()

static bool match_simplify_replacement ( basic_block cond_bb,
basic_block middle_bb,
basic_block middle_bb_alt,
edge e0,
edge e1,
gphi * phi,
tree arg0,
tree arg1,
bool early_p,
bool threeway_p )
static
The function match_simplify_replacement does the main work of doing the
replacement using match and simplify.  Return true if the replacement is done.
Otherwise return false.
BB is the basic block where the replacement is going to be done on.  ARG0
is argument 0 from PHI.  Likewise for ARG1.   

References bitmap_set_bit, cfun, dump_file, dump_flags, EDGE_SUCC, empty_bb_or_one_feeding_into_p(), extract_true_false_edges_from_block(), gcc_assert, ggc_alloc(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_get_lhs(), gimple_phi_result(), gimple_simplify_phiopt(), GSI_CONTINUE_LINKING, gsi_end_p(), gsi_insert_seq_before(), gsi_last_bb(), gsi_next(), gsi_start(), gsi_stmt(), last_nondebug_stmt(), move_stmt(), NULL, operand_equal_for_phi_arg_p(), replace_phi_edge_with_variable(), SSA_NAME_IS_DEFAULT_DEF, ssa_name_maybe_undef_p(), SSA_NAME_VERSION, statistics_counter_event(), TDF_FOLDING, TREE_CODE, and TREE_TYPE.

◆ minmax_replacement()

static bool minmax_replacement ( basic_block cond_bb,
basic_block middle_bb,
basic_block alt_middle_bb,
edge e0,
edge e1,
gphi * phi,
tree arg0,
tree arg1,
bool threeway_p )
static
The function minmax_replacement does the main work of doing the minmax
replacement.  Return true if the replacement is done.  Otherwise return
false.
BB is the basic block where the replacement is going to be done on.  ARG0
is argument 0 from the PHI.  Likewise for ARG1.

If THREEWAY_P then expect the BB to be laid out in diamond shape with each
BB containing only a MIN or MAX expression.   

References wi::add(), boolean_type_node, EDGE_PRED, EDGE_SUCC, empty_block_p(), wi::eq_p(), extract_true_false_edges_from_block(), fold_build2, gcc_assert, ggc_alloc(), gimple_assign_cast_p(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_build(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_location(), gsi_insert_seq_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_move_before(), GSI_NEW_STMT, gsi_one_nondebug_before_end_p(), gsi_start_nondebug_after_labels_bb(), gsi_stmt(), HONOR_NANS(), HONOR_SIGNED_ZEROS(), integer_nonzerop(), integer_zerop(), INTEGRAL_TYPE_P, invert_minmax_code(), is_gimple_assign(), last_and_only_stmt(), last_nondebug_stmt(), wi::max_value(), wi::min_value(), NULL, NULL_TREE, operand_equal_for_phi_arg_p(), PHI_RESULT, replace_phi_edge_with_variable(), reset_flow_sensitive_info(), single_pred_p(), SINGLE_SSA_TREE_OPERAND, SSA_NAME_DEF_STMT, SSA_OP_DEF, strip_bit_not(), wi::sub(), wi::to_wide(), TREE_CODE, TREE_TYPE, TYPE_PRECISION, TYPE_SIGN, TYPE_UNSIGNED, useless_type_conversion_p(), and wide_int_to_tree().

◆ move_stmt()

static void move_stmt ( gimple * stmt,
gimple_stmt_iterator * gsi,
auto_bitmap & inserted_exprs )
static

◆ neutral_element_p()

static bool neutral_element_p ( tree_code code,
tree arg,
bool right )
static
Returns true if ARG is a neutral element for operation CODE
on the RIGHT side.   

References ggc_alloc(), integer_all_onesp(), integer_onep(), and integer_zerop().

Referenced by value_replacement().

◆ operand_equal_for_value_replacement()

static bool operand_equal_for_value_replacement ( const_tree arg0,
const_tree arg1,
enum tree_code * code,
gimple * cond )
static
Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND. 

Also return TRUE if arg0/arg1 are equal to the source arguments of a
an EQ comparison feeding a BIT_AND_EXPR which feeds COND. 

Return FALSE otherwise.   

References ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), gimple_cond_lhs(), gimple_cond_rhs(), integer_zerop(), is_gimple_assign(), operand_equal_for_phi_arg_p(), rhs_is_fed_for_value_replacement(), SSA_NAME_DEF_STMT, and TREE_CODE.

Referenced by value_replacement().

◆ phiopt_early_allow()

static bool phiopt_early_allow ( gimple_seq & seq,
gimple_match_op & op )
static
Return TRUE if SEQ/OP pair should be allowed during early phiopt.
Currently this is to allow MIN/MAX and ABS/NEGATE and constants.   

References gimple_match_op::code, ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs_code(), gimple_seq_empty_p(), gimple_seq_first_stmt(), gimple_seq_singleton_p(), is_gimple_assign(), code_helper::is_tree_code(), and gimple_match_op::ops.

Referenced by gimple_simplify_phiopt().

◆ replace_phi_edge_with_variable()

◆ rhs_is_fed_for_value_replacement()

static bool rhs_is_fed_for_value_replacement ( const_tree arg0,
const_tree arg1,
enum tree_code * code,
const_tree rhs )
static
RHS is a source argument in a BIT_AND_EXPR which feeds a conditional
of the form SSA_NAME NE 0.

If RHS is fed by a simple EQ_EXPR comparison of two values, see if
the two input values of the EQ_EXPR match arg0 and arg1.

If so update *code and return TRUE.  Otherwise return FALSE.   

References ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), is_gimple_assign(), operand_equal_for_phi_arg_p(), SSA_NAME_DEF_STMT, and TREE_CODE.

Referenced by operand_equal_for_value_replacement().

◆ single_non_singleton_phi_for_edges()

static gphi * single_non_singleton_phi_for_edges ( gimple_seq seq,
edge e0,
edge e1 )
static
Optimization of PHI nodes by converting them into straightline code.
   Copyright (C) 2004-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/>.   
Return the singleton PHI in the SEQ of PHIs for edges E0 and E1.  

References ggc_alloc(), gimple_phi_arg_def(), gimple_phi_result(), gsi_end_p(), gsi_next(), gsi_start(), gsi_stmt(), i, NULL, operand_equal_for_phi_arg_p(), and virtual_operand_p().

Referenced by value_replacement().

◆ single_trailing_store_in_bb()

static gimple * single_trailing_store_in_bb ( basic_block bb,
tree vdef )
static
Return the single store in BB with VDEF or NULL if there are
other stores in the BB or loads following the store.   

References ref_to_bb::bb, FOR_EACH_IMM_USE_FAST, ggc_alloc(), gimple_bb(), gimple_vdef(), gimple_vuse(), NULL, SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, and USE_STMT.

Referenced by cond_if_else_store_replacement().

◆ spaceship_replacement()

static bool spaceship_replacement ( basic_block cond_bb,
basic_block middle_bb,
edge e0,
edge e1,
gphi * phi,
tree arg0,
tree arg1 )
static
Attempt to optimize (x <=> y) cmp 0 and similar comparisons.
For strong ordering <=> try to match something like:
 <bb 2> :  // cond3_bb (== cond2_bb)
 if (x_4(D) != y_5(D))
   goto <bb 3>; [INV]
 else
   goto <bb 6>; [INV]

 <bb 3> :  // cond_bb
 if (x_4(D) < y_5(D))
   goto <bb 6>; [INV]
 else
   goto <bb 4>; [INV]

 <bb 4> :  // middle_bb

 <bb 6> :  // phi_bb
 # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
 _1 = iftmp.0_2 == 0;

and for partial ordering <=> something like:

 <bb 2> :  // cond3_bb
 if (a_3(D) == b_5(D))
   goto <bb 6>; [50.00%]
 else
   goto <bb 3>; [50.00%]

 <bb 3> [local count: 536870913]:  // cond2_bb
 if (a_3(D) < b_5(D))
   goto <bb 6>; [50.00%]
 else
   goto <bb 4>; [50.00%]

 <bb 4> [local count: 268435456]:  // cond_bb
 if (a_3(D) > b_5(D))
   goto <bb 6>; [50.00%]
 else
   goto <bb 5>; [50.00%]

 <bb 5> [local count: 134217728]:  // middle_bb

 <bb 6> [local count: 1073741824]:  // phi_bb
 # SR.27_4 = PHI <0(2), -1(3), 1(4), 2(5)>
 _2 = SR.27_4 > 0;   

References absu_hwi(), boolean_type_node, build2(), build3(), build_debug_expr_decl(), build_int_cst(), build_one_cst(), build_zero_cst(), cfun, cmp1(), COMPARISON_CLASS_P, cond_only_block_p(), DECL_ARTIFICIAL, EDGE_COUNT, EDGE_SUCC, empty_block_p(), fold_convert, FOR_EACH_IMM_USE_FAST, g, gcc_assert, gcc_checking_assert, gcc_unreachable, ggc_alloc(), gimple_assign_cast_p(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), gimple_assign_rhs_code(), gimple_assign_set_rhs1(), gimple_assign_set_rhs2(), gimple_assign_set_rhs_code(), gimple_assign_set_rhs_with_ops(), gimple_bb(), GIMPLE_BINARY_RHS, gimple_build_debug_bind(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_cond_set_code(), gimple_cond_set_lhs(), gimple_cond_set_rhs(), gimple_phi_arg_def(), gsi_after_labels(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_remove(), GSI_SAME_STMT, HONOR_NANS(), IN_RANGE, integer_minus_onep(), integer_onep(), integer_zerop(), INTEGRAL_TYPE_P, is_gimple_assign(), is_gimple_debug(), make_node(), MAY_HAVE_DEBUG_BIND_STMTS, wi::ne_p(), NULL_TREE, operand_equal_p(), PHI_RESULT, remove_phi_node(), replace_uses_by(), SET_DECL_MODE, wi::shifted_mask(), single_imm_use(), single_pred(), single_pred_p(), SSA_NAME_OCCURS_IN_ABNORMAL_PHI, statistics_counter_event(), wi::to_wide(), wi::to_widest(), TREE_CODE, tree_fits_shwi_p(), tree_int_cst_lt(), TREE_OPERAND, tree_to_shwi(), TREE_TYPE, TYPE_MODE, TYPE_PRECISION, TYPE_UNSIGNED, update_stmt(), and USE_STMT.

◆ strip_bit_not()

static tree strip_bit_not ( tree var)
static
If VAR is an SSA_NAME that points to a BIT_NOT_EXPR then return the TREE for
the value being inverted.   

References ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs_code(), NULL_TREE, SSA_NAME_DEF_STMT, and TREE_CODE.

Referenced by minmax_replacement().

◆ value_replacement()

static int value_replacement ( basic_block cond_bb,
basic_block middle_bb,
edge e0,
edge e1,
gphi * phi,
tree arg0,
tree arg1 )
static
The function value_replacement does the main work of doing the value
replacement.  Return non-zero if the replacement is done.  Otherwise return
0.  If we remove the middle basic block, return 2.
BB is the basic block where the replacement is going to be done on.  ARG0
is argument 0 from the PHI.  Likewise for ARG1.   

References absorbing_element_p(), bb_seq(), boolean_type_node, build2(), build3(), build_debug_expr_decl(), CASE_CONVERT, cfun, CONVERT_EXPR_CODE_P, dump_file, dump_flags, EDGE_COUNT, EDGE_PRED, eni_time_weights, estimate_num_insns(), estimate_num_insns_seq(), profile_probability::even(), extract_true_false_edges_from_block(), fold_convert, FOR_EACH_IMM_USE_ON_STMT, FOR_EACH_IMM_USE_STMT, g, gcc_assert, get_global_range_query(), ggc_alloc(), gimple_assign_lhs(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_class(), gimple_assign_rhs_code(), gimple_bb(), GIMPLE_BINARY_RHS, gimple_build_debug_bind(), gimple_cond_code(), gimple_cond_lhs(), gimple_cond_rhs(), gimple_phi_result(), gimple_seq_empty_p(), gsi_after_labels(), gsi_end_p(), gsi_for_stmt(), gsi_insert_before(), gsi_last_bb(), gsi_last_nondebug_bb(), gsi_move_before(), gsi_next_nondebug(), gsi_prev_nondebug(), GSI_SAME_STMT, gsi_start_nondebug_after_labels_bb(), gsi_stmt(), HONOR_SIGNED_ZEROS(), i, int_const_binop(), INTEGRAL_TYPE_P, is_gimple_assign(), is_gimple_debug(), jump_function_from_stmt(), MAY_HAVE_DEBUG_BIND_STMTS, neutral_element_p(), NULL, NULL_TREE, operand_equal_for_phi_arg_p(), operand_equal_for_value_replacement(), optimize_bb_for_speed_p(), phi_nodes(), POINTER_TYPE_P, print_generic_expr(), PROFILE_ABSENT, profile_status_for_fn, r, replace_exp(), replace_phi_edge_with_variable(), reset_debug_uses(), reset_flow_sensitive_info(), sc, SET_PHI_ARG_DEF, set_range_info(), single_imm_use(), single_non_singleton_phi_for_edges(), single_pred_p(), single_succ_edge(), ssa_name_maybe_undef_p(), SSA_NAME_RANGE_INFO, statistics_counter_event(), tcc_comparison, TDF_DETAILS, wi::to_wide(), TREE_CODE, TREE_CODE_CLASS, tree_int_cst_equal(), tree_int_cst_le(), tree_int_cst_lt(), TREE_OVERFLOW, TREE_TYPE, update_stmt(), and virtual_operand_p().

Variable Documentation

◆ nt_call_phase

unsigned int nt_call_phase
static
Used for quick clearing of the hash-table when we see calls.
Hash entries with phase < nt_call_phase are invalid.   

Referenced by nontrapping_dom_walker::add_or_mark_expr(), nontrapping_dom_walker::before_dom_children(), and get_non_trapping().