/* Tail merging for gimple.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2021 Free Software Foundation, Inc.
Contributed by Tom de Vries (tom@codesourcery.com)
This file is part of GCC.
#include "gimple-iterator.h"
#include "tree-cfg.h"
#include "tree-into-ssa.h"
-#include "params.h"
#include "tree-ssa-sccvn.h"
#include "cfgloop.h"
#include "tree-eh.h"
#include "tree-cfgcleanup.h"
+const int ignore_edge_flags = EDGE_DFS_BACK | EDGE_EXECUTABLE;
+
/* Describes a group of bbs with the same successors. The successor bbs are
cached in succs, and the successor edge flags are cached in succ_flags.
If a bb has the EDGE_TRUE/FALSE_VALUE flags swapped compared to succ_flags,
#define BB_VOP_AT_EXIT(bb) (((struct aux_bb_info *)bb->aux)->vop_at_exit)
#define BB_DEP_BB(bb) (((struct aux_bb_info *)bb->aux)->dep_bb)
+/* Valueization helper querying the VN lattice. */
+
+static tree
+tail_merge_valueize (tree name)
+{
+ if (TREE_CODE (name) == SSA_NAME
+ && has_VN_INFO (name))
+ {
+ tree tem = VN_INFO (name)->valnum;
+ if (tem != VN_TOP)
+ return tem;
+ }
+ return name;
+}
+
/* Returns true if the only effect a statement STMT has, is to define locally
used SSA_NAMEs. */
if (gimple_vdef (stmt) != NULL_TREE
|| gimple_has_side_effects (stmt)
|| gimple_could_trap_p_1 (stmt, false, false)
- || gimple_vuse (stmt) != NULL_TREE)
+ || gimple_vuse (stmt) != NULL_TREE
+ /* Copied from tree-ssa-ifcombine.c:bb_no_side_effects_p():
+ const calls don't match any of the above, yet they could
+ still have some side-effects - they could contain
+ gimple_could_trap_p statements, like floating point
+ exceptions or integer division by zero. See PR70586.
+ FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
+ should handle this. */
+ || is_gimple_call (stmt))
return false;
def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
if (val1 == val2)
return true;
- if (vn_valueize (val1) != vn_valueize (val2))
+ if (tail_merge_valueize (val1) != tail_merge_valueize (val2))
return false;
return ((TREE_CODE (val1) == SSA_NAME || CONSTANT_CLASS_P (val1))
for (i = 0; i < gimple_call_num_args (stmt); i++)
{
arg = gimple_call_arg (stmt, i);
- arg = vn_valueize (arg);
+ arg = tail_merge_valueize (arg);
inchash::add_expr (arg, hstate);
}
}
hstate.add_int (size);
BB_SIZE (bb) = size;
+ hstate.add_int (bb->loop_father->num);
+
for (i = 0; i < e->succ_flags.length (); ++i)
{
flags = e->succ_flags[i];
if (BB_SIZE (bb1) != BB_SIZE (bb2))
return 0;
+ if (bb1->loop_father != bb2->loop_father)
+ return 0;
+
gsi1 = gsi_start_nondebug_bb (bb1);
gsi2 = gsi_start_nondebug_bb (bb2);
gsi_advance_fw_nondebug_nonlocal (&gsi1);
edge_iterator ei;
edge e;
- if (bb == NULL
- /* Be conservative with loop structure. It's not evident that this test
- is sufficient. Before tail-merge, we've just called
- loop_optimizer_finalize, and LOOPS_MAY_HAVE_MULTIPLE_LATCHES is now
- set, so there's no guarantee that the loop->latch value is still valid.
- But we assume that, since we've forced LOOPS_HAVE_SIMPLE_LATCHES at the
- start of pre, we've kept that property intact throughout pre, and are
- keeping it throughout tail-merge using this test. */
- || bb->loop_father->latch == bb)
+ if (bb == NULL)
return;
bitmap_set_bit (same->bbs, bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
{
int index = e->dest->index;
bitmap_set_bit (same->succs, index);
- same_succ_edge_flags[index] = e->flags;
+ same_succ_edge_flags[index] = (e->flags & ~ignore_edge_flags);
}
EXECUTE_IF_SET_IN_BITMAP (same->succs, 0, j, bj)
same->succ_flags.safe_push (same_succ_edge_flags[j]);
if (lhs1 == NULL_TREE || lhs2 == NULL_TREE)
return false;
if (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME)
- return vn_valueize (lhs1) == vn_valueize (lhs2);
+ return tail_merge_valueize (lhs1) == tail_merge_valueize (lhs2);
return operand_equal_p (lhs1, lhs2, 0);
case GIMPLE_ASSIGN:
if (!gimple_operand_equal_value_p (t1, t2))
return false;
- code1 = gimple_expr_code (s1);
- code2 = gimple_expr_code (s2);
+ code1 = gimple_cond_code (s1);
+ code2 = gimple_cond_code (s2);
inv_cond = (bitmap_bit_p (same_succ->inverse, bb1->index)
!= bitmap_bit_p (same_succ->inverse, bb2->index));
if (inv_cond)
case IFN_UBSAN_CHECK_SUB:
case IFN_UBSAN_CHECK_MUL:
case IFN_UBSAN_OBJECT_SIZE:
+ case IFN_UBSAN_PTR:
case IFN_ASAN_CHECK:
/* For these internal functions, gimple_location is an implicit
parameter, which will be used explicitly after expansion.
unsigned int i, j;
bitmap_iterator bi, bj;
int nr_comparisons;
- int max_comparisons = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_COMPARISONS);
+ int max_comparisons = param_max_tail_merge_comparisons;
EXECUTE_IF_SET_IN_BITMAP (same_succ->bbs, 0, i, bi)
{
/* TODO: handle blocks with phi-nodes. We'll have to find corresponding
phi-nodes in bb1 and bb2, with the same alternatives for the same
preds. */
- if (bb_has_non_vop_phi (bb1) || bb_has_eh_pred (bb1))
+ if (bb_has_non_vop_phi (bb1) || bb_has_eh_pred (bb1)
+ || bb_has_abnormal_pred (bb1))
continue;
nr_comparisons = 0;
{
bb2 = BASIC_BLOCK_FOR_FN (cfun, j);
- if (bb_has_non_vop_phi (bb2) || bb_has_eh_pred (bb2))
+ if (bb_has_non_vop_phi (bb2) || bb_has_eh_pred (bb2)
+ || bb_has_abnormal_pred (bb2))
continue;
if (BB_CLUSTER (bb1) != NULL && BB_CLUSTER (bb1) == BB_CLUSTER (bb2))
replace_block_by (basic_block bb1, basic_block bb2)
{
edge pred_edge;
- edge e1, e2;
- edge_iterator ei;
unsigned int i;
gphi *bb2_phi;
pred_edge, UNKNOWN_LOCATION);
}
- bb2->count += bb1->count;
/* Merge the outgoing edge counts from bb1 onto bb2. */
- profile_count out_sum = profile_count::zero ();
- int out_freq_sum = 0;
-
- /* Recompute the edge probabilities from the new merged edge count.
- Use the sum of the new merged edge counts computed above instead
- of bb2's merged count, in case there are profile count insanities
- making the bb count inconsistent with the edge weights. */
- FOR_EACH_EDGE (e1, ei, bb1->succs)
- {
- if (e1->count.initialized_p ())
- out_sum += e1->count;
- out_freq_sum += EDGE_FREQUENCY (e1);
- }
- FOR_EACH_EDGE (e1, ei, bb2->succs)
- {
- if (e1->count.initialized_p ())
- out_sum += e1->count;
- out_freq_sum += EDGE_FREQUENCY (e1);
- }
+ edge e1, e2;
+ edge_iterator ei;
- FOR_EACH_EDGE (e1, ei, bb1->succs)
- {
- e2 = find_edge (bb2, e1->dest);
- gcc_assert (e2);
- e2->count += e1->count;
- if (out_sum > 0 && e2->count.initialized_p ())
- {
- e2->probability = e2->count.probability_in (bb2->count);
- }
- else if (bb1->frequency && bb2->frequency)
- e2->probability = e1->probability;
- else if (bb2->frequency && !bb1->frequency)
- ;
- else if (out_freq_sum)
- e2->probability = profile_probability::from_reg_br_prob_base
- (GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
- + EDGE_FREQUENCY (e2),
- out_freq_sum));
- out_sum += e2->count;
- }
- bb2->frequency += bb1->frequency;
- if (bb2->frequency > BB_FREQ_MAX)
- bb2->frequency = BB_FREQ_MAX;
+ if (bb2->count.initialized_p ())
+ FOR_EACH_EDGE (e1, ei, bb1->succs)
+ {
+ e2 = find_edge (bb2, e1->dest);
+ gcc_assert (e2);
+
+ /* If probabilities are same, we are done.
+ If counts are nonzero we can distribute accordingly. In remaining
+ cases just avreage the values and hope for the best. */
+ e2->probability = e1->probability.combine_with_count
+ (bb1->count, e2->probability, bb2->count);
+ }
+ bb2->count += bb1->count;
/* Move over any user labels from bb1 after the bb2 labels. */
gimple_stmt_iterator gsi1 = gsi_start_bb (bb1);
int nr_bbs_removed;
bool loop_entered = false;
int iteration_nr = 0;
- int max_iterations = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_ITERATIONS);
+ int max_iterations = param_max_tail_merge_iterations;
if (!flag_tree_tail_merge
|| max_iterations == 0)
{
cleanup_tree_cfg ();
todo &= ~TODO_cleanup_cfg;
- split_critical_edges ();
+ split_edges_for_insertion ();
}
if (!dom_info_available_p (CDI_DOMINATORS))
if (nr_bbs_removed_total > 0)
{
- if (MAY_HAVE_DEBUG_STMTS)
+ if (MAY_HAVE_DEBUG_BIND_STMTS)
{
calculate_dominance_info (CDI_DOMINATORS);
update_debug_stmts ();