public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/guojiufu/heads/personal-branch)] avoid max/min, get_bb_copy, param, msg, iv.no_overflow, ==, param
@ 2021-05-31 5:56 Jiu Fu Guo
0 siblings, 0 replies; 2+ messages in thread
From: Jiu Fu Guo @ 2021-05-31 5:56 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:fec77465e7163ee6430bea59eea9c98b678e5381
commit fec77465e7163ee6430bea59eea9c98b678e5381
Author: Jiufu Guo <guojiufu@linux.ibm.com>
Date: Fri May 14 19:57:19 2021 +0800
avoid max/min, get_bb_copy, param, msg,iv.no_overflow,==,param
Diff:
---
gcc/params.opt | 4 ---
gcc/tree-ssa-loop-split.c | 72 ++++++++++++++++++++++++++++-------------------
2 files changed, 43 insertions(+), 33 deletions(-)
diff --git a/gcc/params.opt b/gcc/params.opt
index f80b6bfd006..0d0dcd216f6 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -766,10 +766,6 @@ Min. ratio of insns to prefetches to enable prefetching for a loop with an unkno
Common Joined UInteger Var(param_min_loop_cond_split_prob) Init(30) IntegerRange(0, 100) Param Optimization
The minimum threshold for probability of semi-invariant condition statement to trigger loop split.
--param=max-insns-ne-cond-split=
-Common Joined UInteger Var(param_max_insn_ne_cond_split) Init(64) Param Optimization
-The maximum threshold for insnstructions number of a loop with ne condition to split.
-
-param=min-nondebug-insn-uid=
Common Joined UInteger Var(param_min_nondebug_insn_uid) Param
The minimum UID to be used for a nondebug insn.
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index 6a914e2a043..bd388f0dcc8 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -250,14 +250,13 @@ connect_loop_phis (class loop *loop1, class loop *loop2, edge new_e,
!gsi_end_p (psi_first);
gsi_next (&psi_first), gsi_next (&psi_second))
{
- tree init, next, new_init, prev;
+ tree init, next, new_init;
use_operand_p op;
gphi *phi_first = psi_first.phi ();
gphi *phi_second = psi_second.phi ();
init = PHI_ARG_DEF_FROM_EDGE (phi_first, firste);
next = PHI_ARG_DEF_FROM_EDGE (phi_first, firstn);
- prev = PHI_RESULT (phi_first);
op = PHI_ARG_DEF_PTR_FROM_EDGE (phi_second, seconde);
gcc_assert (operand_equal_for_phi_arg_p (init, USE_FROM_PTR (op)));
@@ -282,7 +281,8 @@ connect_loop_phis (class loop *loop1, class loop *loop2, edge new_e,
gphi * newphi = create_phi_node (new_init, rest);
add_phi_arg (newphi, init, skip_first, UNKNOWN_LOCATION);
- add_phi_arg (newphi, use_prev ? prev : next, new_e, UNKNOWN_LOCATION);
+ add_phi_arg (newphi, use_prev ? PHI_RESULT (phi_first) : next, new_e,
+ UNKNOWN_LOCATION);
SET_USE (op, new_init);
}
}
@@ -1596,9 +1596,10 @@ split_loop_on_cond (struct loop *loop)
return do_split;
}
-/* Check if the LOOP exit branch likes "if (idx != bound)".
- if INV is not NULL and the branch is "if (bound != idx)", set *INV to true.
- return the branch edge which exit loop. */
+/* Check if the LOOP exit branch likes "if (idx != bound)",
+ and if overflow/wrap may happen on "idx".
+ If INV is not NULL and the branch is "if (bound != idx)", set *INV to true.
+ Return the branch edge which exit loop. */
static edge
get_ne_cond_branch (struct loop *loop, bool *inv)
@@ -1617,10 +1618,11 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
continue;
gcond *cond = as_a<gcond *> (last);
enum tree_code code = gimple_cond_code (cond);
- if (code != NE_EXPR)
+ if (!(code == NE_EXPR
+ || (code == EQ_EXPR && (e->flags & EDGE_TRUE_VALUE))))
continue;
- /* Make sure idx and bound. */
+ /* Make sure bound is invarant. */
tree idx = gimple_cond_lhs (cond);
tree bnd = gimple_cond_rhs (cond);
if (expr_invariant_in_loop_p (loop, idx))
@@ -1632,7 +1634,23 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
else if (!expr_invariant_in_loop_p (loop, bnd))
continue;
- /* Extract conversion. */
+
+ /* There is type conversion on idx(or rhs of idx's def).
+ And there is converting shorter to longer type. */
+ tree type = TREE_TYPE (idx);
+ if (!INTEGRAL_TYPE_P (type) || TREE_CODE (idx) != SSA_NAME
+ || !TYPE_UNSIGNED (type)
+ || TYPE_PRECISION (type) == TYPE_PRECISION (sizetype))
+ continue;
+
+ /* Avoid to split if bound is MAX/MIN val. */
+ tree bound_type = TREE_TYPE (bnd);
+ if (TREE_CODE (bnd) == INTEGER_CST && INTEGRAL_TYPE_P (bound_type)
+ && (bnd == TYPE_MAX_VALUE (bound_type)
+ || bnd == TYPE_MIN_VALUE (bound_type)))
+ continue;
+
+ /* Extract conversion from idx. */
if (TREE_CODE (idx) == SSA_NAME)
{
gimple *stmt = SSA_NAME_DEF_STMT (idx);
@@ -1642,25 +1660,19 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
idx = gimple_assign_rhs1 (stmt);
}
- /* Make sure idx is iv. */
+ /* Check if idx is simple iv with possible overflow/wrap. */
class loop *useloop = loop_containing_stmt (cond);
affine_iv iv;
if (!simple_iv (loop, useloop, idx, &iv, false))
continue;
+ if (iv.no_overflow)
+ return NULL;
- /* No need to split loop, if base is know value.
- Or check range info. */
+ /* If base is know value (esplically 0/1), other optimizations may be
+ able to analyze "idx != bnd" as "idx < bnd" or "idx > bnd". */
if (TREE_CODE (iv.base) == INTEGER_CST)
continue;
- /* There is type conversion on idx(or rhs of idx's def).
- And there is converting shorter to longer type. */
- tree type = TREE_TYPE (idx);
- if (!INTEGRAL_TYPE_P (type) || TREE_CODE (idx) != SSA_NAME
- || !TYPE_UNSIGNED (type)
- || TYPE_PRECISION (type) == TYPE_PRECISION (sizetype))
- continue;
-
/* Check loop is simple to split. */
gcc_assert (bb != loop->latch);
@@ -1669,13 +1681,12 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
&& empty_block_p (loop->latch))
return e;
- /* Splitting is cheap for idx increase header. */
+ /* Splitting is cheap for idx increase header (only i++ or ++I). */
if (bb == loop->header)
{
if (get_virtual_phi (loop->header))
continue;
- /* In loop header: i++ or ++i. */
gimple_stmt_iterator gsi = gsi_start_bb (bb);
if (gsi_end_p (gsi))
return e;
@@ -1711,18 +1722,18 @@ split_ne_loop (struct loop *loop, edge cond_e)
gcc_assert (loop2);
update_ssa (TODO_update_ssa);
+ basic_block loop2_cond_exit_bb = get_bb_copy (cond_e->src);
free_original_copy_tables ();
/* Change if (i != n) to LOOP1:if (i > n) and LOOP2:if (i < n) */
bool inv = false;
- edge dup_cond = get_ne_cond_branch (loop2, &inv);
enum tree_code up_code = inv ? LT_EXPR : GT_EXPR;
enum tree_code down_code = inv ? GT_EXPR : LT_EXPR;
gcond *gc = as_a<gcond *> (last_stmt (cond_e->src));
gimple_cond_set_code (gc, up_code);
- gcond *dup_gc = as_a<gcond *> (last_stmt (dup_cond->src));
+ gcond *dup_gc = as_a<gcond *> (last_stmt (loop2_cond_exit_bb));
gimple_cond_set_code (dup_gc, down_code);
/* Link the exit cond edge to new loop. */
@@ -1753,7 +1764,7 @@ split_ne_loop (struct loop *loop, edge cond_e)
rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_USE, loop);
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Loop split.\n");
+ fprintf (dump_file, ";; Loop split on wrap.\n");
return true;
}
@@ -1783,17 +1794,20 @@ The loop with "i<N" is in favor both GIMPLE and RTL passes. */
static bool
split_loop_on_ne_cond (class loop *loop)
{
- if (!can_duplicate_loop_p (loop))
- return false;
-
int num = 0;
basic_block *bbs = get_loop_body (loop);
+ if (!can_copy_bbs_p (bbs, loop->num_nodes))
+ {
+ free (bbs);
+ return false;
+ }
+
for (unsigned i = 0; i < loop->num_nodes; i++)
num += estimate_num_insns_seq (bb_seq (bbs[i]), &eni_size_weights);
free (bbs);
- if (num > param_max_insn_ne_cond_split)
+ if (num > param_max_peeled_insns)
return false;
edge branch_edge = get_ne_cond_branch (loop, NULL);
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/users/guojiufu/heads/personal-branch)] avoid max/min, get_bb_copy, param, msg, iv.no_overflow, ==, param
@ 2021-05-20 6:28 Jiu Fu Guo
0 siblings, 0 replies; 2+ messages in thread
From: Jiu Fu Guo @ 2021-05-20 6:28 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:d35704b5601ebfed10b394dce050ef28a5583b97
commit d35704b5601ebfed10b394dce050ef28a5583b97
Author: Jiufu Guo <guojiufu@linux.ibm.com>
Date: Fri May 14 19:57:19 2021 +0800
avoid max/min, get_bb_copy, param, msg,iv.no_overflow,==,param
Diff:
---
gcc/params.opt | 4 ---
gcc/tree-ssa-loop-split.c | 72 ++++++++++++++++++++++++++++-------------------
2 files changed, 43 insertions(+), 33 deletions(-)
diff --git a/gcc/params.opt b/gcc/params.opt
index 900b59b5136..2e4cbdd7a71 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -766,10 +766,6 @@ Min. ratio of insns to prefetches to enable prefetching for a loop with an unkno
Common Joined UInteger Var(param_min_loop_cond_split_prob) Init(30) IntegerRange(0, 100) Param Optimization
The minimum threshold for probability of semi-invariant condition statement to trigger loop split.
--param=max-insns-ne-cond-split=
-Common Joined UInteger Var(param_max_insn_ne_cond_split) Init(64) Param Optimization
-The maximum threshold for insnstructions number of a loop with ne condition to split.
-
-param=min-nondebug-insn-uid=
Common Joined UInteger Var(param_min_nondebug_insn_uid) Param
The minimum UID to be used for a nondebug insn.
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index 6a914e2a043..bd388f0dcc8 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -250,14 +250,13 @@ connect_loop_phis (class loop *loop1, class loop *loop2, edge new_e,
!gsi_end_p (psi_first);
gsi_next (&psi_first), gsi_next (&psi_second))
{
- tree init, next, new_init, prev;
+ tree init, next, new_init;
use_operand_p op;
gphi *phi_first = psi_first.phi ();
gphi *phi_second = psi_second.phi ();
init = PHI_ARG_DEF_FROM_EDGE (phi_first, firste);
next = PHI_ARG_DEF_FROM_EDGE (phi_first, firstn);
- prev = PHI_RESULT (phi_first);
op = PHI_ARG_DEF_PTR_FROM_EDGE (phi_second, seconde);
gcc_assert (operand_equal_for_phi_arg_p (init, USE_FROM_PTR (op)));
@@ -282,7 +281,8 @@ connect_loop_phis (class loop *loop1, class loop *loop2, edge new_e,
gphi * newphi = create_phi_node (new_init, rest);
add_phi_arg (newphi, init, skip_first, UNKNOWN_LOCATION);
- add_phi_arg (newphi, use_prev ? prev : next, new_e, UNKNOWN_LOCATION);
+ add_phi_arg (newphi, use_prev ? PHI_RESULT (phi_first) : next, new_e,
+ UNKNOWN_LOCATION);
SET_USE (op, new_init);
}
}
@@ -1596,9 +1596,10 @@ split_loop_on_cond (struct loop *loop)
return do_split;
}
-/* Check if the LOOP exit branch likes "if (idx != bound)".
- if INV is not NULL and the branch is "if (bound != idx)", set *INV to true.
- return the branch edge which exit loop. */
+/* Check if the LOOP exit branch likes "if (idx != bound)",
+ and if overflow/wrap may happen on "idx".
+ If INV is not NULL and the branch is "if (bound != idx)", set *INV to true.
+ Return the branch edge which exit loop. */
static edge
get_ne_cond_branch (struct loop *loop, bool *inv)
@@ -1617,10 +1618,11 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
continue;
gcond *cond = as_a<gcond *> (last);
enum tree_code code = gimple_cond_code (cond);
- if (code != NE_EXPR)
+ if (!(code == NE_EXPR
+ || (code == EQ_EXPR && (e->flags & EDGE_TRUE_VALUE))))
continue;
- /* Make sure idx and bound. */
+ /* Make sure bound is invarant. */
tree idx = gimple_cond_lhs (cond);
tree bnd = gimple_cond_rhs (cond);
if (expr_invariant_in_loop_p (loop, idx))
@@ -1632,7 +1634,23 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
else if (!expr_invariant_in_loop_p (loop, bnd))
continue;
- /* Extract conversion. */
+
+ /* There is type conversion on idx(or rhs of idx's def).
+ And there is converting shorter to longer type. */
+ tree type = TREE_TYPE (idx);
+ if (!INTEGRAL_TYPE_P (type) || TREE_CODE (idx) != SSA_NAME
+ || !TYPE_UNSIGNED (type)
+ || TYPE_PRECISION (type) == TYPE_PRECISION (sizetype))
+ continue;
+
+ /* Avoid to split if bound is MAX/MIN val. */
+ tree bound_type = TREE_TYPE (bnd);
+ if (TREE_CODE (bnd) == INTEGER_CST && INTEGRAL_TYPE_P (bound_type)
+ && (bnd == TYPE_MAX_VALUE (bound_type)
+ || bnd == TYPE_MIN_VALUE (bound_type)))
+ continue;
+
+ /* Extract conversion from idx. */
if (TREE_CODE (idx) == SSA_NAME)
{
gimple *stmt = SSA_NAME_DEF_STMT (idx);
@@ -1642,25 +1660,19 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
idx = gimple_assign_rhs1 (stmt);
}
- /* Make sure idx is iv. */
+ /* Check if idx is simple iv with possible overflow/wrap. */
class loop *useloop = loop_containing_stmt (cond);
affine_iv iv;
if (!simple_iv (loop, useloop, idx, &iv, false))
continue;
+ if (iv.no_overflow)
+ return NULL;
- /* No need to split loop, if base is know value.
- Or check range info. */
+ /* If base is know value (esplically 0/1), other optimizations may be
+ able to analyze "idx != bnd" as "idx < bnd" or "idx > bnd". */
if (TREE_CODE (iv.base) == INTEGER_CST)
continue;
- /* There is type conversion on idx(or rhs of idx's def).
- And there is converting shorter to longer type. */
- tree type = TREE_TYPE (idx);
- if (!INTEGRAL_TYPE_P (type) || TREE_CODE (idx) != SSA_NAME
- || !TYPE_UNSIGNED (type)
- || TYPE_PRECISION (type) == TYPE_PRECISION (sizetype))
- continue;
-
/* Check loop is simple to split. */
gcc_assert (bb != loop->latch);
@@ -1669,13 +1681,12 @@ get_ne_cond_branch (struct loop *loop, bool *inv)
&& empty_block_p (loop->latch))
return e;
- /* Splitting is cheap for idx increase header. */
+ /* Splitting is cheap for idx increase header (only i++ or ++I). */
if (bb == loop->header)
{
if (get_virtual_phi (loop->header))
continue;
- /* In loop header: i++ or ++i. */
gimple_stmt_iterator gsi = gsi_start_bb (bb);
if (gsi_end_p (gsi))
return e;
@@ -1711,18 +1722,18 @@ split_ne_loop (struct loop *loop, edge cond_e)
gcc_assert (loop2);
update_ssa (TODO_update_ssa);
+ basic_block loop2_cond_exit_bb = get_bb_copy (cond_e->src);
free_original_copy_tables ();
/* Change if (i != n) to LOOP1:if (i > n) and LOOP2:if (i < n) */
bool inv = false;
- edge dup_cond = get_ne_cond_branch (loop2, &inv);
enum tree_code up_code = inv ? LT_EXPR : GT_EXPR;
enum tree_code down_code = inv ? GT_EXPR : LT_EXPR;
gcond *gc = as_a<gcond *> (last_stmt (cond_e->src));
gimple_cond_set_code (gc, up_code);
- gcond *dup_gc = as_a<gcond *> (last_stmt (dup_cond->src));
+ gcond *dup_gc = as_a<gcond *> (last_stmt (loop2_cond_exit_bb));
gimple_cond_set_code (dup_gc, down_code);
/* Link the exit cond edge to new loop. */
@@ -1753,7 +1764,7 @@ split_ne_loop (struct loop *loop, edge cond_e)
rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_USE, loop);
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ";; Loop split.\n");
+ fprintf (dump_file, ";; Loop split on wrap.\n");
return true;
}
@@ -1783,17 +1794,20 @@ The loop with "i<N" is in favor both GIMPLE and RTL passes. */
static bool
split_loop_on_ne_cond (class loop *loop)
{
- if (!can_duplicate_loop_p (loop))
- return false;
-
int num = 0;
basic_block *bbs = get_loop_body (loop);
+ if (!can_copy_bbs_p (bbs, loop->num_nodes))
+ {
+ free (bbs);
+ return false;
+ }
+
for (unsigned i = 0; i < loop->num_nodes; i++)
num += estimate_num_insns_seq (bb_seq (bbs[i]), &eni_size_weights);
free (bbs);
- if (num > param_max_insn_ne_cond_split)
+ if (num > param_max_peeled_insns)
return false;
edge branch_edge = get_ne_cond_branch (loop, NULL);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-05-31 5:56 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-31 5:56 [gcc(refs/users/guojiufu/heads/personal-branch)] avoid max/min, get_bb_copy, param, msg, iv.no_overflow, ==, param Jiu Fu Guo
-- strict thread matches above, loose matches on Subject: below --
2021-05-20 6:28 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).