Commit fc06280e by Bin Cheng

re PR tree-optimization/64705 (Bad code generation of sieve on x86-64 because of…

re PR tree-optimization/64705 (Bad code generation of sieve on x86-64 because of too aggressive IV optimizations)


	PR tree-optimization/64705
	* tree-ssa-loop-niter.h (expand_simple_operations): New parameter.
	* tree-ssa-loop-niter.c (expand_simple_operations): New parameter.
	* tree-ssa-loop-ivopts.c (extract_single_var_from_expr): New.
	(find_bivs, find_givs_in_stmt_scev): Pass new argument to
	expand_simple_operations.

	testsuite
	PR tree-optimization/64705
	* gcc.dg/tree-ssa/pr64705.c: New test.

From-SVN: r220676
parent 785f21af
2015-02-12 H.J. Lu <hongjiu.lu@intel.com> 2015-02-13 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/64705
* tree-ssa-loop-niter.h (expand_simple_operations): New parameter.
* tree-ssa-loop-niter.c (expand_simple_operations): New parameter.
* tree-ssa-loop-ivopts.c (extract_single_var_from_expr): New.
(find_bivs, find_givs_in_stmt_scev): Pass new argument to
expand_simple_operations.
2015-02-13 H.J. Lu <hongjiu.lu@intel.com>
Richard Henderson <rth@redhat.com> Richard Henderson <rth@redhat.com>
PR rtl/32219 PR rtl/32219
...@@ -21,7 +30,7 @@ ...@@ -21,7 +30,7 @@
* config/rs6000/rs6000.c (rs6000_emit_epilogue): Fix typo in * config/rs6000/rs6000.c (rs6000_emit_epilogue): Fix typo in
code setting up r11 for out-of-line fp restore. code setting up r11 for out-of-line fp restore.
2015-02-12 Eric Botcazou <ebotcazou@adacore.com> 2015-02-13 Eric Botcazou <ebotcazou@adacore.com>
* config/visium/visium.opt (msv-mode): Add RejectNegative and Report. * config/visium/visium.opt (msv-mode): Add RejectNegative and Report.
(muser-mode): Likewise. (muser-mode): Likewise.
......
2015-02-13 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/64705
* gcc.dg/tree-ssa/pr64705.c: New test.
2015-02-12 H.J. Lu <hongjiu.lu@intel.com> 2015-02-12 H.J. Lu <hongjiu.lu@intel.com>
PR rtl/32219 PR rtl/32219
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
double g;
int foo(char *flags, long len, long i, long steps)
{
register long step, iter;
if(*(flags + i))
{
step = i + i + 3;
for(iter = i + step ; iter <= len ; iter += step)
{
steps++;
*(flags + iter)=0;
}
}
g = 5.0*(double)steps;
return 0;
}
/* Don't expand iv {base+step, step}_loop into {base+x+y, step}_loop
even if "step == x + y". */
/* { dg-final { scan-tree-dump "base step_\[0-9\]* \\+ iter|base iter_\[0-9\]* \\+ step" "ivopts"} } */
/* { dg-final { cleanup-tree-dump "ivopts" } } */
...@@ -1081,13 +1081,40 @@ determine_biv_step (gphi *phi) ...@@ -1081,13 +1081,40 @@ determine_biv_step (gphi *phi)
return integer_zerop (iv.step) ? NULL_TREE : iv.step; return integer_zerop (iv.step) ? NULL_TREE : iv.step;
} }
/* Return the first non-invariant ssa var found in EXPR. */
static tree
extract_single_var_from_expr (tree expr)
{
int i, n;
tree tmp;
enum tree_code code;
if (!expr || is_gimple_min_invariant (expr))
return NULL;
code = TREE_CODE (expr);
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
n = TREE_OPERAND_LENGTH (expr);
for (i = 0; i < n; i++)
{
tmp = extract_single_var_from_expr (TREE_OPERAND (expr, i));
if (tmp)
return tmp;
}
}
return (TREE_CODE (expr) == SSA_NAME) ? expr : NULL;
}
/* Finds basic ivs. */ /* Finds basic ivs. */
static bool static bool
find_bivs (struct ivopts_data *data) find_bivs (struct ivopts_data *data)
{ {
gphi *phi; gphi *phi;
tree step, type, base; tree step, type, base, stop;
bool found = false; bool found = false;
struct loop *loop = data->current_loop; struct loop *loop = data->current_loop;
gphi_iterator psi; gphi_iterator psi;
...@@ -1104,7 +1131,13 @@ find_bivs (struct ivopts_data *data) ...@@ -1104,7 +1131,13 @@ find_bivs (struct ivopts_data *data)
continue; continue;
base = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop)); base = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
base = expand_simple_operations (base); /* Stop expanding iv base at the first ssa var referred by iv step.
Ideally we should stop at any ssa var, because that's expensive
and unusual to happen, we just do it on the first one.
See PR64705 for the rationale. */
stop = extract_single_var_from_expr (step);
base = expand_simple_operations (base, stop);
if (contains_abnormal_ssa_name_p (base) if (contains_abnormal_ssa_name_p (base)
|| contains_abnormal_ssa_name_p (step)) || contains_abnormal_ssa_name_p (step))
continue; continue;
...@@ -1176,7 +1209,7 @@ mark_bivs (struct ivopts_data *data) ...@@ -1176,7 +1209,7 @@ mark_bivs (struct ivopts_data *data)
static bool static bool
find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv) find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv)
{ {
tree lhs; tree lhs, stop;
struct loop *loop = data->current_loop; struct loop *loop = data->current_loop;
iv->base = NULL_TREE; iv->base = NULL_TREE;
...@@ -1191,13 +1224,19 @@ find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv) ...@@ -1191,13 +1224,19 @@ find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv)
if (!simple_iv (loop, loop_containing_stmt (stmt), lhs, iv, true)) if (!simple_iv (loop, loop_containing_stmt (stmt), lhs, iv, true))
return false; return false;
iv->base = expand_simple_operations (iv->base);
/* Stop expanding iv base at the first ssa var referred by iv step.
Ideally we should stop at any ssa var, because that's expensive
and unusual to happen, we just do it on the first one.
See PR64705 for the rationale. */
stop = extract_single_var_from_expr (iv->step);
iv->base = expand_simple_operations (iv->base, stop);
if (contains_abnormal_ssa_name_p (iv->base) if (contains_abnormal_ssa_name_p (iv->base)
|| contains_abnormal_ssa_name_p (iv->step)) || contains_abnormal_ssa_name_p (iv->step))
return false; return false;
/* If STMT could throw, then do not consider STMT as defining a GIV. /* If STMT could throw, then do not consider STMT as defining a GIV.
While this will suppress optimizations, we can not safely delete this While this will suppress optimizations, we can not safely delete this
GIV and associated statements, even if it appears it is not used. */ GIV and associated statements, even if it appears it is not used. */
if (stmt_could_throw_p (stmt)) if (stmt_could_throw_p (stmt))
......
...@@ -1563,10 +1563,11 @@ simplify_replace_tree (tree expr, tree old, tree new_tree) ...@@ -1563,10 +1563,11 @@ simplify_replace_tree (tree expr, tree old, tree new_tree)
} }
/* Expand definitions of ssa names in EXPR as long as they are simple /* Expand definitions of ssa names in EXPR as long as they are simple
enough, and return the new expression. */ enough, and return the new expression. If STOP is specified, stop
expanding if EXPR equals to it. */
tree tree
expand_simple_operations (tree expr) expand_simple_operations (tree expr, tree stop)
{ {
unsigned i, n; unsigned i, n;
tree ret = NULL_TREE, e, ee, e1; tree ret = NULL_TREE, e, ee, e1;
...@@ -1586,7 +1587,7 @@ expand_simple_operations (tree expr) ...@@ -1586,7 +1587,7 @@ expand_simple_operations (tree expr)
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
e = TREE_OPERAND (expr, i); e = TREE_OPERAND (expr, i);
ee = expand_simple_operations (e); ee = expand_simple_operations (e, stop);
if (e == ee) if (e == ee)
continue; continue;
...@@ -1605,7 +1606,8 @@ expand_simple_operations (tree expr) ...@@ -1605,7 +1606,8 @@ expand_simple_operations (tree expr)
return ret; return ret;
} }
if (TREE_CODE (expr) != SSA_NAME) /* Stop if it's not ssa name or the one we don't want to expand. */
if (TREE_CODE (expr) != SSA_NAME || expr == stop)
return expr; return expr;
stmt = SSA_NAME_DEF_STMT (expr); stmt = SSA_NAME_DEF_STMT (expr);
...@@ -1625,7 +1627,7 @@ expand_simple_operations (tree expr) ...@@ -1625,7 +1627,7 @@ expand_simple_operations (tree expr)
&& src->loop_father != dest->loop_father) && src->loop_father != dest->loop_father)
return expr; return expr;
return expand_simple_operations (e); return expand_simple_operations (e, stop);
} }
if (gimple_code (stmt) != GIMPLE_ASSIGN) if (gimple_code (stmt) != GIMPLE_ASSIGN)
return expr; return expr;
...@@ -1645,7 +1647,7 @@ expand_simple_operations (tree expr) ...@@ -1645,7 +1647,7 @@ expand_simple_operations (tree expr)
return e; return e;
if (code == SSA_NAME) if (code == SSA_NAME)
return expand_simple_operations (e); return expand_simple_operations (e, stop);
return expr; return expr;
} }
...@@ -1654,7 +1656,7 @@ expand_simple_operations (tree expr) ...@@ -1654,7 +1656,7 @@ expand_simple_operations (tree expr)
{ {
CASE_CONVERT: CASE_CONVERT:
/* Casts are simple. */ /* Casts are simple. */
ee = expand_simple_operations (e); ee = expand_simple_operations (e, stop);
return fold_build1 (code, TREE_TYPE (expr), ee); return fold_build1 (code, TREE_TYPE (expr), ee);
case PLUS_EXPR: case PLUS_EXPR:
...@@ -1669,7 +1671,7 @@ expand_simple_operations (tree expr) ...@@ -1669,7 +1671,7 @@ expand_simple_operations (tree expr)
if (!is_gimple_min_invariant (e1)) if (!is_gimple_min_invariant (e1))
return expr; return expr;
ee = expand_simple_operations (e); ee = expand_simple_operations (e, stop);
return fold_build2 (code, TREE_TYPE (expr), ee, e1); return fold_build2 (code, TREE_TYPE (expr), ee, e1);
default: default:
......
...@@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_SSA_LOOP_NITER_H #ifndef GCC_TREE_SSA_LOOP_NITER_H
#define GCC_TREE_SSA_LOOP_NITER_H #define GCC_TREE_SSA_LOOP_NITER_H
extern tree expand_simple_operations (tree); extern tree expand_simple_operations (tree, tree = NULL);
extern bool loop_only_exit_p (const struct loop *, const_edge); extern bool loop_only_exit_p (const struct loop *, const_edge);
extern bool number_of_iterations_exit (struct loop *, edge, extern bool number_of_iterations_exit (struct loop *, edge,
struct tree_niter_desc *niter, bool, struct tree_niter_desc *niter, bool,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment