public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/guojiufu/heads/personal-branch)] get and save idx elements
@ 2021-06-04 12:06 Jiu Fu Guo
0 siblings, 0 replies; only message in thread
From: Jiu Fu Guo @ 2021-06-04 12:06 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:380d6682d3e9217669cfb6e57b81a247d7094245
commit 380d6682d3e9217669cfb6e57b81a247d7094245
Author: guojiufu <guojiufu@linux.ibm.com>
Date: Fri Jun 4 20:06:30 2021 +0800
get and save idx elements
Diff:
---
gcc/tree-ssa-loop-split.c | 289 +++++++++++++++++++++++-----------------------
1 file changed, 147 insertions(+), 142 deletions(-)
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index 7df406e72fb..185b8a995cd 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -1595,18 +1595,6 @@ split_loop_on_cond (struct loop *loop)
}
/* Filter out type conversions on IDX.
-
- i = phi (b, n)
- ...
- n0 = ik + 1
- n1 = (type)n0
- ...
- if (i != bnd) or if (n != bnd)
- ...
- n = ()nl
-
- IDX is the i' or n'.
-
Store the shortest type during conversion to SMALL_TYPE.
Store the longest type during conversion to LARGE_TYPE. */
@@ -1649,102 +1637,155 @@ filter_conversions (class loop *loop, tree idx, tree *small_type = NULL,
return stmt;
}
+struct idx_elements
+{
+ gcond *gc;
+ gphi *phi;
+ tree idx;
+ tree bnd;
+ tree next;
+ tree large_type;
+ tree small_type;
+ gimple *inc_stmt;
+ bool cmp_on_next;
+};
+
+/* Analyze and get the idx related elements: bnd, next,
+ phi, increase stmt from exit edge E.
+
+ i = phi (b, n)
+ ...
+ n0 = ik + 1
+ n1 = (type)n0
+ ...
+ if (i != bnd) or if (n != bnd)
+ ...
+ n = ()nl
+
+ IDX is the i' or n'. */
+
+bool
+analyze_idx_elements (class loop *loop, edge e, idx_elements &data)
+{
+ if (e->flags & EDGE_FAKE)
+ return false;
+
+ gimple *last = last_stmt (e->src);
+ if (!last || gimple_code (last) != GIMPLE_COND)
+ return false;
+
+ /* Get idx and bnd from gcond. */
+ gcond *gc = as_a<gcond *> (last);
+ tree bnd = gimple_cond_rhs (gc);
+ tree idx = gimple_cond_lhs (gc);
+ if (expr_invariant_in_loop_p (loop, idx))
+ std::swap (idx, bnd);
+ else if (!expr_invariant_in_loop_p (loop, bnd))
+ return false;
+ if (TREE_CODE (idx) != SSA_NAME)
+ return false;
+
+ gimple *inc_stmt = NULL;
+ bool cmp_next = false;
+ tree small_type = TREE_TYPE (idx);
+ tree large_type = small_type;
+ gimple *stmt = filter_conversions (loop, idx, &small_type, &large_type);
+ /* The idx on gcond is not PHI, it would be next. */
+ if (is_gimple_assign (stmt))
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (rhs) == SSA_NAME)
+ return false;
+
+ cmp_next = true;
+ inc_stmt = stmt;
+ stmt = filter_conversions (loop, rhs, &small_type, &large_type);
+ }
+
+ /* Get phi and next. */
+ if (gimple_code (stmt) != GIMPLE_PHI || gimple_bb (stmt) != loop->header)
+ return false;
+ gphi *phi = as_a<gphi *> (stmt);
+ tree next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
+ if (TREE_CODE (next) != SSA_NAME)
+ return false;
+
+ /* The define of next should be the increasement stmt. */
+ stmt = filter_conversions (loop, next, &small_type, &large_type);
+ if (inc_stmt != NULL && inc_stmt != stmt)
+ return false;
+ if (!is_gimple_assign (stmt)
+ || !flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
+ return false;
+ tree_code rhs_code = gimple_assign_rhs_code (stmt);
+ if (rhs_code != PLUS_EXPR && rhs_code != MINUS_EXPR)
+ return false;
+ if (TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST)
+ return false;
+ inc_stmt = stmt;
+
+ data.gc = gc;
+ data.phi = phi;
+ data.idx = idx;
+ data.bnd = bnd;
+ data.next = next;
+ data.large_type = large_type;
+ data.small_type = small_type;
+ data.inc_stmt = inc_stmt;
+ data.cmp_on_next = cmp_next;
+
+ return true;
+}
+
/* Check if the loop is possible to wrap at index.
Return the assumption under which the wrap will not happen.
Return NULL_TREE, if wrap will not happen. */
static tree
-get_wrap_assumption (class loop *loop, edge *exit)
+get_wrap_assumption (class loop *loop, edge *exit, idx_elements &data)
{
int i;
edge e;
auto_vec<edge> edges = get_loop_exit_edges (loop);
FOR_EACH_VEC_ELT (edges, i, e)
{
- if (e->flags & EDGE_FAKE)
- continue;
-
- basic_block bb = e->src;
-
- /* Check gcond. */
- gimple *last = last_stmt (bb);
- if (!last || gimple_code (last) != GIMPLE_COND)
- continue;
- gcond *gc = as_a<gcond *> (last);
-
- /* Check if bound is invarant. */
- tree bnd = gimple_cond_rhs (gc);
- tree idx = gimple_cond_lhs (gc);
- enum tree_code code = gimple_cond_code (gc);
- if (expr_invariant_in_loop_p (loop, idx))
- {
- std::swap (idx, bnd);
- code = swap_tree_comparison (code);
- }
- else if (!expr_invariant_in_loop_p (loop, bnd))
+ if (!analyze_idx_elements (loop, e, data))
continue;
/* Check if bound is MAX/MIN val of a integral type. */
+ tree bnd = data.bnd;
tree bnd_type = TREE_TYPE (bnd);
- if (!(INTEGRAL_TYPE_P (bnd_type)))
+ if (!INTEGRAL_TYPE_P (bnd_type) || !TYPE_UNSIGNED (bnd_type))
continue;
if (TREE_CODE (bnd) == INTEGER_CST
- && (bnd == TYPE_MAX_VALUE (bnd_type)
- || bnd == TYPE_MIN_VALUE (bnd_type)))
+ && (tree_int_cst_equal (bnd, TYPE_MAX_VALUE (bnd_type))
+ || tree_int_cst_equal (bnd, TYPE_MIN_VALUE (bnd_type))))
continue;
/* Check if it is "idx != bnd" or "idx < bnd". */
+ gcond *gc = data.gc;
+ enum tree_code code = gimple_cond_code (gc);
+ if (bnd == gimple_cond_lhs (gc))
+ code = swap_tree_comparison (code);
if (e->flags & EDGE_TRUE_VALUE)
code = invert_tree_comparison (code, false);
if (code != NE_EXPR && code != LT_EXPR && code != LE_EXPR)
continue;
- /* Check if idx is a valid SSA. */
- if (TREE_CODE (idx) != SSA_NAME)
- continue;
-
- /* Get the phi for idx. */
- gimple *stmt = filter_conversions (loop, idx);
- if (is_gimple_assign (stmt))
- {
- tree rhs = gimple_assign_rhs1 (stmt);
- if (TREE_CODE (rhs) != SSA_NAME)
- continue;
- stmt = filter_conversions (loop, rhs);
- }
- if (gimple_code (stmt) != GIMPLE_PHI || gimple_bb (stmt) != loop->header)
- continue;
- gphi *idx_phi = as_a<gphi *> (stmt);
- tree next = PHI_ARG_DEF_FROM_EDGE (idx_phi, loop_latch_edge (loop));
- if (TREE_CODE (next) != SSA_NAME)
- continue;
-
/* Check if idx is iv with base and step. */
affine_iv iv;
tree iv_niters = NULL_TREE;
- idx = PHI_RESULT (idx_phi);
+ tree idx = PHI_RESULT (data.phi);
if (!simple_iv_with_niters (loop, loop_containing_stmt (gc), idx, &iv,
&iv_niters, false))
continue;
- if (!iv.base || !iv.step || !integer_onep (iv.step))
- continue;
-
- /* If there is conversions on idx,
- Get the longest and shortest type during converting. */
- tree small_type = TREE_TYPE (next);
- tree large_type = small_type;
- stmt = filter_conversions (loop, next, &small_type, &large_type);
- if (!is_gimple_assign (stmt)
- || gimple_assign_rhs_code (stmt) != PLUS_EXPR
- || !flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
- continue;
- tree prev = gimple_assign_rhs1 (stmt);
- if (TREE_CODE (prev) != SSA_NAME)
+ if (!iv.base || !iv.step)
continue;
- stmt = filter_conversions (loop, prev, &small_type, &large_type);
- /* Update the type of bae, bound and the max value of boundary. */
+ /* Update the type for base, bound and the max value of boundary. */
tree base = iv.base;
+ tree small_type = data.small_type;
+ tree large_type = data.large_type;
tree maxv = TYPE_MAX_VALUE (small_type);
if (large_type != TREE_TYPE (base))
base = fold_convert (large_type, base);
@@ -1776,67 +1817,16 @@ get_wrap_assumption (class loop *loop, edge *exit)
/* Update the idx and bnd with faster type for no wrap/oveflow loop. */
static bool
-update_idx_bnd_type (class loop *loop, edge e)
+update_idx_bnd_type (class loop *loop, idx_elements &data)
{
- return false;
- /* Get bnd and idx from gcond. */
- gimple *last = last_stmt (e->src);
- if (!last || gimple_code (last) != GIMPLE_COND)
- return false;
- gcond *gc = as_a<gcond *> (last);
- tree bnd = gimple_cond_rhs (gc);
- tree idx = gimple_cond_lhs (gc);
- bool inv = false;
- if (expr_invariant_in_loop_p (loop, idx))
- {
- inv = true;
- std::swap (idx, bnd);
- }
-
- gphi *idx_phi;
- tree next;
- edge latch_e = loop_latch_edge (loop);
-
- /* Get increasement stmt: next = prev + 1.
- And check the exit gcond is comparing on the prev or next. */
- gimple *inc_stmt = NULL;
- bool cmp_next = false;
- gcc_assert (TREE_CODE (idx) == SSA_NAME);
- gimple *stmt = filter_conversions (loop, idx);
- if (gimple_code (stmt) == GIMPLE_PHI)
- {
- idx_phi = as_a <gphi *> (stmt);
- next = PHI_ARG_DEF_FROM_EDGE (idx_phi, latch_e);
- gcc_assert (TREE_CODE (next) == SSA_NAME);
- inc_stmt = filter_conversions (loop, next);
- cmp_next = false;
- }
- else
- {
- inc_stmt = stmt;
- if (!is_gimple_assign (inc_stmt))
- return false;
- tree rhs = gimple_assign_rhs1 (stmt);
- gcc_assert (TREE_CODE (rhs) == SSA_NAME);
- stmt = filter_conversions (loop, rhs);
- if (gimple_code (stmt) != GIMPLE_PHI)
- return false;
- idx_phi = as_a<gphi *> (stmt);
- cmp_next = true;
- }
-
- if (!is_gimple_assign (inc_stmt)
- || gimple_assign_rhs_code (inc_stmt) != PLUS_EXPR
- || !flow_bb_inside_loop_p (loop, gimple_bb (inc_stmt))
- || gimple_bb (idx_phi) != loop->header)
- return false;
-
/* Use sizetype as machine fast type, ok for most targets? */
tree fast_type = sizetype;
/* New base and new bound. */
+ gphi *phi = data.phi;
+ tree bnd = data.bnd;
edge pre_e = loop_preheader_edge (loop);
- tree base = PHI_ARG_DEF_FROM_EDGE (idx_phi, pre_e);
+ tree base = PHI_ARG_DEF_FROM_EDGE (phi, pre_e);
tree new_base = fold_convert (fast_type, base);
tree new_bnd = fold_convert (fast_type, bnd);
gimple_seq seq = NULL;
@@ -1850,33 +1840,37 @@ update_idx_bnd_type (class loop *loop, edge e)
/* new_i = phi (new_b, new_n)
new_n = new_i + 1 */
- basic_block bb = gimple_bb (idx_phi);
+ edge latch_e = loop_latch_edge (loop);
const char *name = "idx";
tree new_idx = make_temp_ssa_name (fast_type, NULL, name);
tree new_next = make_temp_ssa_name (fast_type, NULL, name);
- gphi *newphi = create_phi_node (new_idx, bb);
+ gphi *newphi = create_phi_node (new_idx, loop->header);
add_phi_arg (newphi, new_base, pre_e, UNKNOWN_LOCATION);
add_phi_arg (newphi, new_next, latch_e, UNKNOWN_LOCATION);
/* New increase stmt. */
+ gimple *inc_stmt = data.inc_stmt;
tree step = gimple_assign_rhs2 (inc_stmt);
- gcc_assert (TREE_CODE (step) == INTEGER_CST);
step = fold_convert (fast_type, step);
new_idx = PHI_RESULT (newphi);
- gimple *new_inc = gimple_build_assign (new_next, PLUS_EXPR, new_idx, step);
+ tree_code inc_code = gimple_assign_rhs_code (inc_stmt);
+ gimple *new_inc = gimple_build_assign (new_next, inc_code, new_idx, step);
gimple_stmt_iterator gsi = gsi_for_stmt (inc_stmt);
gsi_insert_before (&gsi, new_inc, GSI_SAME_STMT);
/* Update gcond. */
- tree cmp_idx = cmp_next ? new_next : new_idx;
+ gcond *gc = data.gc;
+ bool inv = bnd == gimple_cond_lhs (gc);
+ tree cmp_idx = data.cmp_on_next ? new_next : new_idx;
gimple_cond_set_lhs (gc, inv ? new_bnd : cmp_idx);
gimple_cond_set_rhs (gc, inv ? cmp_idx : new_bnd);
update_stmt (gc);
/* next = (next type)new_next
And remove next = prev + 1. */
+ tree next = data.next;
tree type = TREE_TYPE (next);
- stmt = gimple_build_assign (next, fold_convert (type, new_next));
+ gimple *stmt = gimple_build_assign (next, fold_convert (type, new_next));
gsi = gsi_for_stmt (inc_stmt);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
@@ -1885,13 +1879,13 @@ update_idx_bnd_type (class loop *loop, edge e)
/* prev = (prev type)new_prev
And remove prev = phi. */
- idx = PHI_RESULT (idx_phi);
+ tree idx = PHI_RESULT (phi);
type = TREE_TYPE (idx);
stmt = gimple_build_assign (idx, fold_convert (type, new_idx));
- gsi = gsi_start_bb (bb);
+ gsi = gsi_start_bb (loop->header);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- gsi = gsi_for_stmt (idx_phi);
+ gsi = gsi_for_stmt (phi);
gsi_remove (&gsi, true);
return true;
@@ -1926,14 +1920,24 @@ split_wrap_boundary (class loop *loop, edge e, tree no_wrap_cond)
gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
}
+ /* Update gcond code and edge. */
gcond *gc = as_a<gcond *> (last_stmt (e->src));
enum tree_code code = gimple_cond_code (gc);
enum tree_code new_code;
bool inv = expr_invariant_in_loop_p (loop, gimple_cond_lhs (gc));
new_code = inv ? GT_EXPR : LT_EXPR;
if (code == EQ_EXPR)
- new_code = invert_tree_comparison (new_code, false);
-
+ {
+ new_code = invert_tree_comparison (new_code, false);
+ edge out = EDGE_SUCC (e->src, 0);
+ edge in = EDGE_SUCC (e->src, 1);
+ if (in->flags & EDGE_TRUE_VALUE)
+ std::swap (in, out);
+ in->flags |= EDGE_TRUE_VALUE;
+ in->flags &= ~EDGE_FALSE_VALUE;
+ out->flags |= EDGE_FALSE_VALUE;
+ out->flags &= ~EDGE_TRUE_VALUE;
+ }
if (code == NE_EXPR || code == EQ_EXPR)
gimple_cond_set_code (gc, new_code);
@@ -1987,13 +1991,14 @@ split_loop_on_wrap (class loop *loop)
free (bbs);
edge e;
- tree no_wrap_assumption = get_wrap_assumption (loop, &e);
+ idx_elements data;
+ tree no_wrap_assumption = get_wrap_assumption (loop, &e, data);
if (no_wrap_assumption
&& (integer_onep (no_wrap_assumption)
|| split_wrap_boundary (loop, e, no_wrap_assumption)))
{
- update_idx_bnd_type (loop, e);
+ update_idx_bnd_type (loop, data);
return true;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-06-04 12:06 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-04 12:06 [gcc(refs/users/guojiufu/heads/personal-branch)] get and save idx elements Jiu Fu Guo
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).