public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/loop-unswitch-support-switches] More cleanups
@ 2022-05-17 17:13 Richard Biener
0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2022-05-17 17:13 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:ce7462de861d74e4cf1c81f94dfe8c0a5b49ef8e
commit ce7462de861d74e4cf1c81f94dfe8c0a5b49ef8e
Author: Richard Biener <rguenther@suse.de>
Date: Tue May 17 14:35:44 2022 +0200
More cleanups
This performs more API cleanups, adds comments and fixes minor
issues. It adds gcc.dg/loop-unswitch-16.c noting a regression
from the previous implementation.
Diff:
---
gcc/testsuite/gcc.dg/loop-unswitch-16.c | 22 ++
gcc/tree-ssa-loop-unswitch.cc | 389 ++++++++++++++++----------------
2 files changed, 213 insertions(+), 198 deletions(-)
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-16.c b/gcc/testsuite/gcc.dg/loop-unswitch-16.c
new file mode 100644
index 00000000000..394351985ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-16.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
+
+void bar (int);
+void foo (int a, int b, int c, int n)
+{
+ for (int i = 0; i < n; ++i)
+ {
+ if (a > 5)
+ bar (1);
+ if (b < 10)
+ bar (2);
+ if (c != 5)
+ bar (3);
+ }
+}
+
+/* We fail to unswitch all permutations of the predicates. */
+/* { dg-final { scan-tree-dump-times "Unswitching loop on condition" 7 "unswitch" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump "Unswitching loop on condition: a" "unswitch" } } */
+/* { dg-final { scan-tree-dump "Unswitching loop on condition: b" "unswitch" } } */
+/* { dg-final { scan-tree-dump "Unswitching loop on condition: c" "unswitch" } } */
diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
index 299aead7db6..a1dd7716b58 100644
--- a/gcc/tree-ssa-loop-unswitch.cc
+++ b/gcc/tree-ssa-loop-unswitch.cc
@@ -101,28 +101,55 @@ along with GCC; see the file COPYING3. If not see
7) The process is repeated until we reach a growth threshold or all
unswitching opportunities are taken. */
+/* Ranger instance used in the pass. */
+static gimple_ranger *ranger = NULL;
+
/* A tuple that holds a GENERIC condition and value range for an unswitching
predicate. */
struct unswitch_predicate
{
- /* Default constructor. */
- unswitch_predicate (tree cond, tree lhs_, int edge_index_ = -1)
+ unswitch_predicate (tree cond, tree lhs_, int edge_index_, edge e)
: condition (cond), lhs (lhs_), true_range (), false_range (),
merged_true_range (), merged_false_range (),
edge_index (edge_index_), handled (false)
- {}
-
- /* Based on true_range, compute inverted range. */
-
- inline void
- init_false_edge (void)
{
- false_range = true_range;
+ gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE)));
+ if (irange::supports_type_p (TREE_TYPE (lhs)))
+ {
+ if (ranger->gori ().outgoing_edge_range_p (true_range, e, lhs,
+ *get_global_range_query ()))
+ {
+ false_range = true_range;
+ if (!false_range.varying_p ()
+ && !false_range.undefined_p ())
+ false_range.invert ();
+ }
+ else
+ /* Huge switches are not supported by Ranger but without a range
+ we cannot simplify the copies. */
+ handled = true;
+ }
+ }
- if (!false_range.varying_p ()
- && !false_range.undefined_p ())
- false_range.invert ();
+ unswitch_predicate (tree cond, tree lhs_, edge e)
+ : condition (cond), lhs (lhs_), true_range (), false_range (),
+ merged_true_range (), merged_false_range (),
+ handled (false)
+ {
+ gcc_assert (e->flags & EDGE_TRUE_VALUE);
+ edge_index = (EDGE_SUCC (e->src, 0) == e) ? 0 : 1;
+ if (irange::supports_type_p (TREE_TYPE (lhs)))
+ {
+ if (ranger->gori ().outgoing_edge_range_p (true_range, e, lhs,
+ *get_global_range_query ()))
+ {
+ false_range = true_range;
+ if (!false_range.varying_p ()
+ && !false_range.undefined_p ())
+ false_range.invert ();
+ }
+ }
}
/* Copy ranges for purpose of usage in predicate path. */
@@ -146,27 +173,26 @@ struct unswitch_predicate
/* Modified range that is part of a predicate path. */
int_range_max merged_true_range, merged_false_range;
- /* For switch predicates, index of the edge the predicate belongs to. */
+ /* For switch predicates, index of the edge the predicate belongs to
+ in the successor vector. */
int edge_index;
- /* True if the predicate was already used for unswitching. */
+ /* True if the predicate was already used for unswitching or is
+ covered by another predicate unswitched. */
bool handled;
};
/* Cache storage for unswitch_predicate belonging to a basic block. */
static vec<vec<unswitch_predicate *>> *bb_predicates = NULL;
-/* Ranger instance used in the pass. */
-static gimple_ranger *ranger = NULL;
-
/* The type represents a predicate path leading to a basic block. */
typedef vec<std::pair<unswitch_predicate *, bool>> predicate_vector;
-static class loop *tree_unswitch_loop (class loop *, basic_block, tree);
-static bool tree_unswitch_single_loop (class loop *, int,
+static class loop *tree_unswitch_loop (class loop *, edge, tree);
+static bool tree_unswitch_single_loop (class loop *, dump_user_location_t,
predicate_vector &predicate_path,
- unsigned budget,
- const auto_edge_flag &ignored_edge_flag);
+ unsigned &budget,
+ int ignored_edge_flag);
static void
find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
vec<unswitch_predicate *> &candidates);
@@ -178,7 +204,7 @@ static bool used_outside_loop_p (class loop *, tree, vec<gimple *>&);
static void hoist_guard (class loop *, edge);
static bool check_exit_phi (class loop *);
static tree get_vop_from_header (class loop *);
-static void clean_up_after_unswitching (const auto_edge_flag &);
+static void clean_up_after_unswitching (int);
/* Return vector of predicates that belong to a basic block. */
@@ -257,6 +283,32 @@ tree_ssa_unswitch_loops (void)
{
if (!loop->inner)
{
+ /* Perform initial tests if unswitch is eligible. */
+ dump_user_location_t loc = find_loop_location (loop);
+
+ /* Do not unswitch in cold regions. */
+ if (optimize_loop_for_size_p (loop))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Not unswitching cold loops\n");
+ continue;
+ }
+
+ /* If the loop is not expected to iterate, there is no need
+ for unswitching. */
+ HOST_WIDE_INT iterations = estimated_loop_iterations_int (loop);
+ if (iterations < 0)
+ iterations = likely_max_loop_iterations_int (loop);
+ if (iterations >= 0 && iterations <= 1)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Not unswitching, loop is not expected"
+ " to iterate\n");
+ continue;
+ }
+
bb_predicates = new vec<vec<unswitch_predicate *>> ();
bb_predicates->safe_push (vec<unswitch_predicate *> ());
@@ -266,13 +318,13 @@ tree_ssa_unswitch_loops (void)
predicate_vector predicate_path;
predicate_path.create (8);
- changed |= tree_unswitch_single_loop (loop, 0, predicate_path,
+ changed |= tree_unswitch_single_loop (loop, loc, predicate_path,
budget, ignored_edge_flag);
predicate_path.release ();
- for (auto predlist: bb_predicates)
+ for (auto predlist : bb_predicates)
{
- for (auto predicate: predlist)
+ for (auto predicate : predlist)
delete predicate;
predlist.release ();
}
@@ -288,10 +340,12 @@ tree_ssa_unswitch_loops (void)
disable_ranger (cfun);
clear_aux_for_blocks ();
- clean_up_after_unswitching (ignored_edge_flag);
if (changed)
- return TODO_cleanup_cfg;
+ {
+ clean_up_after_unswitching (ignored_edge_flag);
+ return TODO_cleanup_cfg;
+ }
return 0;
}
@@ -419,16 +473,8 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
edge edge_true, edge_false;
extract_true_false_edges_from_block (bb, &edge_true, &edge_false);
- unswitch_predicate *predicate = new unswitch_predicate (cond, lhs);
-
- if (irange::supports_type_p (TREE_TYPE (lhs)))
- {
- ranger->gori ().outgoing_edge_range_p (predicate->true_range,
- edge_true, lhs,
- *get_global_range_query ());
- predicate->init_false_edge ();
- }
-
+ unswitch_predicate *predicate = new unswitch_predicate (cond, lhs,
+ edge_true);
candidates.safe_push (predicate);
}
else if (gswitch *stmt = safe_dyn_cast <gswitch *> (last))
@@ -490,15 +536,8 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
if (preds[edge_index] != NULL_TREE)
{
unswitch_predicate *predicate
- = new unswitch_predicate (preds[edge_index], idx, edge_index);
- if (!ranger->gori ().outgoing_edge_range_p
- (predicate->true_range, e, idx, *get_global_range_query ()))
- {
- /* Huge switches are not supported by Ranger. */
- delete predicate;
- continue;
- }
- predicate->init_false_edge ();
+ = new unswitch_predicate (preds[edge_index], idx,
+ edge_index, e);
candidates.safe_push (predicate);
}
}
@@ -560,59 +599,43 @@ find_range_for_lhs (predicate_vector &predicate_path, tree lhs,
return false;
}
-/* Simplifies COND using checks in front of the entry of the LOOP.
- Utilize both symbolic expressions and value ranges calculated by Ranger. */
+/* Simplifies STMT using the predicate we unswitched on which is the last
+ in PREDICATE_PATH. For switch statements add newly unreachable edges
+ to IGNORED_EDGES (but do not set IGNORED_EDGE_FLAG on them). */
static tree
evaluate_control_stmt_using_entry_checks (gimple *stmt,
predicate_vector &predicate_path,
- const auto_edge_flag &ignored_edge_flag,
+ int ignored_edge_flag,
hash_set<edge> *ignored_edges)
{
- tree lhs;
-
- gcond *condition = dyn_cast<gcond *> (stmt);
- gswitch *swtch = dyn_cast<gswitch *> (stmt);
-
unswitch_predicate *last_predicate = predicate_path.last ().first;
bool true_edge = predicate_path.last ().second;
- if (condition != NULL
- && (lhs = gimple_cond_lhs (stmt))
- && operand_equal_p (lhs, last_predicate->lhs, 0))
+ if (gcond *cond = dyn_cast<gcond *> (stmt))
{
- if (gimple_cond_code (stmt) == TREE_CODE (last_predicate->condition)
- && operand_equal_p (gimple_cond_rhs (stmt),
- TREE_OPERAND (last_predicate->condition, 1), 0))
- {
- edge edge_true, edge_false;
- extract_true_false_edges_from_block (gimple_bb (stmt),
- &edge_true, &edge_false);
- if (true_edge)
- {
- if (ignored_edges != NULL)
- ignored_edges->add (edge_true);
- return boolean_true_node;
- }
- else
- {
- if (ignored_edges != NULL)
- ignored_edges->add (edge_false);
- return boolean_false_node;
- }
- }
+ tree lhs = gimple_cond_lhs (cond);
+ if (!operand_equal_p (lhs, last_predicate->lhs))
+ return NULL_TREE;
+ /* Try a symbolic match which works for floating point and fully
+ symbolic conditions. */
+ if (gimple_cond_code (cond) == TREE_CODE (last_predicate->condition)
+ && operand_equal_p (gimple_cond_rhs (cond),
+ TREE_OPERAND (last_predicate->condition, 1)))
+ return true_edge ? boolean_true_node : boolean_false_node;
+ /* Else try ranger if it supports LHS. */
else if (irange::supports_type_p (TREE_TYPE (lhs)))
{
int_range_max r;
int_range_max path_range;
if (find_range_for_lhs (predicate_path, lhs, path_range)
- && fold_range (r, stmt, path_range)
+ && fold_range (r, cond, path_range)
&& r.singleton_p ())
return r.zero_p () ? boolean_false_node : boolean_true_node;
}
}
- else if (swtch != NULL)
+ else if (gswitch *swtch = dyn_cast<gswitch *> (stmt))
{
unsigned nlabels = gimple_switch_num_labels (swtch);
@@ -622,36 +645,41 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
if (TREE_CONSTANT (idx))
return NULL_TREE;
+ int_range_max path_range;
+ if (!find_range_for_lhs (predicate_path, idx, path_range))
+ return NULL_TREE;
+
tree result = NULL_TREE;
+ edge single_edge = NULL;
for (unsigned i = 0; i < nlabels; ++i)
{
tree lab = gimple_switch_label (swtch, i);
basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
edge e = find_edge (gimple_bb (stmt), dest);
if (e->flags & ignored_edge_flag)
- {
- ignored_edges->add (e);
- continue;
- }
+ continue;
int_range_max r;
- int_range_max path_range;
ranger->gori ().outgoing_edge_range_p (r, e, idx,
*get_global_range_query ());
- if (find_range_for_lhs (predicate_path, idx, path_range))
+ r.intersect (path_range);
+ if (r.undefined_p ())
+ ignored_edges->add (e);
+ else
{
- r.intersect (path_range);
- if (r.undefined_p ())
- ignored_edges->add (e);
- else
- result = CASE_LOW (lab);
+ if (!single_edge)
+ {
+ single_edge = e;
+ result = CASE_LOW (lab);
+ }
+ else if (single_edge != e)
+ result = NULL;
}
}
/* Only one edge from the switch is alive. */
- unsigned edge_count = EDGE_COUNT (gimple_bb (swtch)->succs);
- if (ignored_edges->elements () + 1 == edge_count)
+ if (single_edge && result)
return result;
}
@@ -663,47 +691,48 @@ evaluate_control_stmt_using_entry_checks (gimple *stmt,
static bool
simplify_loop_version (class loop *loop, predicate_vector &predicate_path,
- const auto_edge_flag &ignored_edge_flag)
+ int ignored_edge_flag)
{
bool changed = false;
basic_block *bbs = get_loop_body (loop);
+ hash_set<edge> ignored_edges;
for (unsigned i = 0; i != loop->num_nodes; i++)
{
vec<unswitch_predicate *> &predicates = get_predicates_for_bb (bbs[i]);
if (predicates.is_empty ())
continue;
- hash_set<edge> ignored_edges;
gimple *stmt = last_stmt (bbs[i]);
tree folded = evaluate_control_stmt_using_entry_checks (stmt,
predicate_path,
ignored_edge_flag,
&ignored_edges);
- gcond *cond = dyn_cast<gcond *> (stmt);
- gswitch *swtch = dyn_cast<gswitch *> (stmt);
-
- if (cond != NULL
- && folded != NULL_TREE)
+ if (gcond *cond = dyn_cast<gcond *> (stmt))
{
- /* Remove path. */
- if (integer_nonzerop (folded))
- gimple_cond_set_condition_from_tree (cond, boolean_true_node);
- else
- gimple_cond_set_condition_from_tree (cond, boolean_false_node);
+ if (folded)
+ {
+ /* Remove path. */
+ if (integer_nonzerop (folded))
+ gimple_cond_set_condition_from_tree (cond, boolean_true_node);
+ else
+ gimple_cond_set_condition_from_tree (cond, boolean_false_node);
+
+ gcc_assert (predicates.length () == 1);
+ predicates[0]->handled = true;
- gimple_set_uid (cond, 0);
- update_stmt (cond);
- changed = true;
+ update_stmt (cond);
+ changed = true;
+ }
}
- else if (swtch != NULL)
+ else if (gswitch *swtch = dyn_cast<gswitch *> (stmt))
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bbs[i]->succs)
if (ignored_edges.contains (e))
- e->flags = ignored_edge_flag;
+ e->flags |= ignored_edge_flag;
for (unsigned j = 0; j < predicates.length (); j++)
{
@@ -732,8 +761,7 @@ simplify_loop_version (class loop *loop, predicate_vector &predicate_path,
static unsigned
evaluate_insns (class loop *loop, basic_block *bbs,
predicate_vector &predicate_path,
- auto_bb_flag &reachable_flag,
- const auto_edge_flag &ignored_edge_flag)
+ int reachable_flag, int ignored_edge_flag)
{
auto_vec<basic_block> worklist (loop->num_nodes);
worklist.quick_push (bbs[0]);
@@ -743,7 +771,7 @@ evaluate_insns (class loop *loop, basic_block *bbs,
{
edge e;
edge_iterator ei;
- int flags = 0;
+ int flags = ignored_edge_flag;
basic_block bb = worklist.pop ();
gimple *last = last_stmt (bb);
@@ -758,11 +786,13 @@ evaluate_insns (class loop *loop, basic_block *bbs,
flags = EDGE_TRUE_VALUE;
else
{
- if (!get_predicates_for_bb (bb).is_empty ())
- evaluate_control_stmt_using_entry_checks (cond,
- predicate_path,
- ignored_edge_flag,
- &ignored_edges);
+ tree res;
+ if (!get_predicates_for_bb (bb).is_empty ()
+ && (res = evaluate_control_stmt_using_entry_checks
+ (cond, predicate_path, ignored_edge_flag,
+ &ignored_edges)))
+ flags = (integer_nonzerop (res)
+ ? EDGE_FALSE_VALUE : EDGE_TRUE_VALUE);
}
}
else if (swtch != NULL
@@ -807,7 +837,7 @@ static unsigned
evaluate_loop_insns_for_predicate (class loop *loop, basic_block *bbs,
predicate_vector &predicate_path,
unswitch_predicate *predicate,
- const auto_edge_flag &ignored_edge_flag)
+ int ignored_edge_flag)
{
auto_bb_flag reachable_flag (cfun);
@@ -824,83 +854,47 @@ evaluate_loop_insns_for_predicate (class loop *loop, basic_block *bbs,
return true_loop_cost + false_loop_cost;
}
-/* Unswitch single LOOP. NUM is number of unswitchings done; we do not allow
- it to grow too much, it is too easy to create example on that the code would
- grow exponentially. PREDICATE_PATH contains so far used predicates
+/* Unswitch single LOOP. PREDICATE_PATH contains so far used predicates
for unswitching. BUDGET is number of instruction for which we can increase
- the loop. */
+ the loop and is updated when unswitching occurs. */
static bool
-tree_unswitch_single_loop (class loop *loop, int num,
- predicate_vector &predicate_path, unsigned budget,
- const auto_edge_flag &ignored_edge_flag)
+tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
+ predicate_vector &predicate_path, unsigned &budget,
+ int ignored_edge_flag)
{
basic_block *bbs = NULL;
class loop *nloop;
bool changed = false;
- HOST_WIDE_INT iterations;
-
- dump_user_location_t loc = find_loop_location (loop);
-
- /* Perform initial tests if unswitch is eligible. */
- if (num == 0)
- {
- /* Do not unswitch in cold regions. */
- if (optimize_loop_for_size_p (loop))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, loc,
- "Not unswitching cold loops\n");
- return false;
- }
-
- /* If the loop is not expected to iterate, there is no need
- for unswitching. */
- iterations = estimated_loop_iterations_int (loop);
- if (iterations < 0)
- iterations = likely_max_loop_iterations_int (loop);
- if (iterations >= 0 && iterations <= 1)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, loc,
- "Not unswitching, loop is not expected"
- " to iterate\n");
- return false;
- }
- }
-
unswitch_predicate *predicate = NULL;
basic_block bb = NULL;
bbs = get_loop_body (loop);
for (unsigned i = 0; i < loop->num_nodes; i++)
- {
- vec<unswitch_predicate *> &preds = get_predicates_for_bb (bbs[i]);
- for (auto pred: preds)
- {
- if (pred->handled)
- continue;
-
- unsigned cost
- = evaluate_loop_insns_for_predicate (loop, bbs, predicate_path,
- pred, ignored_edge_flag);
+ for (auto pred : get_predicates_for_bb (bbs[i]))
+ {
+ if (pred->handled)
+ continue;
- /* FIXME: right now we select first candidate, but we can choose
- a cheapest (best) one. */
- if (cost <= budget)
- {
- predicate = pred;
- bb = bbs[i];
- budget -= cost;
- break;
- }
- else if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, loc,
- "Not unswitching condition, cost too big "
- "(%d insns)\n", cost);
- }
- }
+ unsigned cost
+ = evaluate_loop_insns_for_predicate (loop, bbs, predicate_path,
+ pred, ignored_edge_flag);
+
+ /* FIXME: right now we select first candidate, but we can choose
+ the cheapest or hottest one. */
+ if (cost <= budget)
+ {
+ predicate = pred;
+ bb = bbs[i];
+ budget -= cost;
+ break;
+ }
+ else if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, loc,
+ "Not unswitching condition, cost too big "
+ "(%d insns)\n", cost);
+ }
if (predicate != NULL)
{
@@ -915,7 +909,8 @@ tree_unswitch_single_loop (class loop *loop, int num,
predicate->handled = true;
initialize_original_copy_tables ();
/* Unswitch the loop on this condition. */
- nloop = tree_unswitch_loop (loop, bb, predicate->condition);
+ nloop = tree_unswitch_loop (loop, EDGE_SUCC (bb, predicate->edge_index),
+ predicate->condition);
if (!nloop)
{
free_original_copy_tables ();
@@ -937,14 +932,17 @@ tree_unswitch_single_loop (class loop *loop, int num,
add_predicate_to_path (predicate_path, predicate, false);
changed |= simplify_loop_version (nloop, predicate_path,
ignored_edge_flag);
- tree_unswitch_single_loop (nloop, num + 1, predicate_path, budget,
+ tree_unswitch_single_loop (nloop, loc, predicate_path, budget,
ignored_edge_flag);
predicate_path.pop ();
+ /* FIXME: After unwinding above we have to reset all ->handled
+ flags as otherwise we fail to realize unswitching opportunities
+ in the below recursion. See gcc.dg/loop-unswitch-16.c */
add_predicate_to_path (predicate_path, predicate, true);
changed |= simplify_loop_version (loop, predicate_path,
ignored_edge_flag);
- tree_unswitch_single_loop (loop, num + 1, predicate_path, budget,
+ tree_unswitch_single_loop (loop, loc, predicate_path, budget,
ignored_edge_flag);
predicate_path.pop ();
changed = true;
@@ -955,25 +953,20 @@ exit:
return changed;
}
-/* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON. We only support
- unswitching of innermost loops. COND is the condition determining which
- loop is entered -- the new loop is entered if COND is true. Returns NULL
- if impossible, new loop otherwise. */
+/* Unswitch a LOOP w.r. to given EDGE_TRUE. We only support unswitching of
+ innermost loops. COND is the condition determining which loop is entered;
+ the new loop is entered if COND is true. Returns NULL if impossible, new
+ loop otherwise. */
static class loop *
-tree_unswitch_loop (class loop *loop,
- basic_block unswitch_on, tree cond)
+tree_unswitch_loop (class loop *loop, edge edge_true, tree cond)
{
- profile_probability prob_true;
- edge edge_true, edge_false;
-
/* Some sanity checking. */
- gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
- gcc_assert (EDGE_COUNT (unswitch_on->succs) >= 2);
+ gcc_assert (flow_bb_inside_loop_p (loop, edge_true->src));
+ gcc_assert (EDGE_COUNT (edge_true->src->succs) >= 2);
gcc_assert (loop->inner == NULL);
- extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
- prob_true = edge_true->probability;
+ profile_probability prob_true = edge_true->probability;
return loop_version (loop, unshare_expr (cond),
NULL, prob_true,
prob_true.invert (),
@@ -1490,7 +1483,7 @@ check_exit_phi (class loop *loop)
/* Remove all dead cases from switches that are unswitched. */
static void
-clean_up_after_unswitching (const auto_edge_flag &ignored_edge_flag)
+clean_up_after_unswitching (int ignored_edge_flag)
{
basic_block bb;
edge e;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-05-17 17:13 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-17 17:13 [gcc/devel/loop-unswitch-support-switches] More cleanups Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).