Commit 8a171a59 by Zdenek Dvorak Committed by Zdenek Dvorak

re PR tree-optimization/34355 (ICE: invariant not recomputed when ADDR_EXPR…

re PR tree-optimization/34355 (ICE: invariant not recomputed when ADDR_EXPR changed with -ftree-parallelize-loops)

	PR tree-optimization/34355
	* tree-parloops.c (take_address_of): Handle expresions
	instead of just variables.
	(eliminate_local_variables_1): Force whole invariant
	address to ssa name.

	* g++.dg/tree-ssa/pr34355.C: New test.

From-SVN: r131063
parent 89deeaff
2007-12-19 Zdenek Dvorak <ook@ucw.cz>
PR tree-optimization/34355
* tree-parloops.c (take_address_of): Handle expresions
instead of just variables.
(eliminate_local_variables_1): Force whole invariant
address to ssa name.
2007-12-19 Alexander Monakov <amonakov@ispras.ru> 2007-12-19 Alexander Monakov <amonakov@ispras.ru>
Revital Eres <eres@il.ibm.com> Revital Eres <eres@il.ibm.com>
2007-12-19 Zdenek Dvorak <ook@ucw.cz>
PR tree-optimization/34355
* g++.dg/tree-ssa/pr34355.C: New test.
2007-12-19 Revital Eres <eres@il.ibm.com> 2007-12-19 Revital Eres <eres@il.ibm.com>
* gcc.dg/sms-5.c: New testcase. * gcc.dg/sms-5.c: New testcase.
// { dg-do compile }
// { dg-options "-O3 -ftree-parallelize-loops=4" }
typedef double EXPRESS[5];
extern int Terms;
void Parse_Rel_Factor (EXPRESS Express, int *Terms)
{
EXPRESS Local_Express = {5.0, 4.0, 3.0, 2.0, 1.0};
int Local_Terms = 5;
int i;
for (i = (*Terms); i < Local_Terms; i++)
Express[i] = 0.0;
Express[i] += Local_Express[i];
}
double Parse_Float ()
{
EXPRESS Express = {1.0, 2.0, 3.0, 4.0, 5.0};
Parse_Rel_Factor (Express, &Terms);
}
...@@ -431,29 +431,37 @@ loop_parallel_p (struct loop *loop, htab_t reduction_list, struct tree_niter_des ...@@ -431,29 +431,37 @@ loop_parallel_p (struct loop *loop, htab_t reduction_list, struct tree_niter_des
return ret; return ret;
} }
/* Assigns the address of VAR in TYPE to an ssa name, and returns this name. /* Assigns the address of OBJ in TYPE to an ssa name, and returns this name.
The assignment statement is placed before LOOP. DECL_ADDRESS maps decls The assignment statement is placed before LOOP. DECL_ADDRESS maps decls
to their addresses that can be reused. */ to their addresses that can be reused. The address of OBJ is known to
be invariant in the whole function. */
static tree static tree
take_address_of (tree var, tree type, struct loop *loop, htab_t decl_address) take_address_of (tree obj, tree type, struct loop *loop, htab_t decl_address)
{ {
int uid = DECL_UID (var); int uid;
void **dslot; void **dslot;
struct int_tree_map ielt, *nielt; struct int_tree_map ielt, *nielt;
tree name, bvar, stmt; tree *var_p, name, bvar, stmt, addr;
edge entry = loop_preheader_edge (loop); edge entry = loop_preheader_edge (loop);
/* Since the address of OBJ is invariant, the trees may be shared.
Avoid rewriting unrelated parts of the code. */
obj = unshare_expr (obj);
for (var_p = &obj;
handled_component_p (*var_p);
var_p = &TREE_OPERAND (*var_p, 0))
continue;
uid = DECL_UID (*var_p);
ielt.uid = uid; ielt.uid = uid;
dslot = htab_find_slot_with_hash (decl_address, &ielt, uid, INSERT); dslot = htab_find_slot_with_hash (decl_address, &ielt, uid, INSERT);
if (!*dslot) if (!*dslot)
{ {
bvar = create_tmp_var (type, get_name (var)); addr = build_addr (*var_p, current_function_decl);
bvar = create_tmp_var (TREE_TYPE (addr), get_name (*var_p));
add_referenced_var (bvar); add_referenced_var (bvar);
stmt = build_gimple_modify_stmt (bvar, stmt = build_gimple_modify_stmt (bvar, addr);
fold_convert (type,
build_addr (var,
current_function_decl)));
name = make_ssa_name (bvar, stmt); name = make_ssa_name (bvar, stmt);
GIMPLE_STMT_OPERAND (stmt, 0) = name; GIMPLE_STMT_OPERAND (stmt, 0) = name;
bsi_insert_on_edge_immediate (entry, stmt); bsi_insert_on_edge_immediate (entry, stmt);
...@@ -462,19 +470,26 @@ take_address_of (tree var, tree type, struct loop *loop, htab_t decl_address) ...@@ -462,19 +470,26 @@ take_address_of (tree var, tree type, struct loop *loop, htab_t decl_address)
nielt->uid = uid; nielt->uid = uid;
nielt->to = name; nielt->to = name;
*dslot = nielt; *dslot = nielt;
return name;
} }
else
name = ((struct int_tree_map *) *dslot)->to; name = ((struct int_tree_map *) *dslot)->to;
if (TREE_TYPE (name) == type)
return name;
bvar = SSA_NAME_VAR (name); if (var_p != &obj)
stmt = build_gimple_modify_stmt (bvar, fold_convert (type, name)); {
name = make_ssa_name (bvar, stmt); *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
GIMPLE_STMT_OPERAND (stmt, 0) = name; name = force_gimple_operand (build_addr (obj, current_function_decl),
&stmt, true, NULL_TREE);
if (stmt)
bsi_insert_on_edge_immediate (entry, stmt);
}
if (TREE_TYPE (name) != type)
{
name = force_gimple_operand (fold_convert (type, name), &stmt, true,
NULL_TREE);
if (stmt)
bsi_insert_on_edge_immediate (entry, stmt); bsi_insert_on_edge_immediate (entry, stmt);
}
return name; return name;
} }
...@@ -543,10 +558,10 @@ struct elv_data ...@@ -543,10 +558,10 @@ struct elv_data
walk_tree. */ walk_tree. */
static tree static tree
eliminate_local_variables_1 (tree * tp, int *walk_subtrees, void *data) eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data)
{ {
struct elv_data *dta = data; struct elv_data *dta = data;
tree t = *tp, var, addr, addr_type, type; tree t = *tp, var, addr, addr_type, type, obj;
if (DECL_P (t)) if (DECL_P (t))
{ {
...@@ -566,16 +581,28 @@ eliminate_local_variables_1 (tree * tp, int *walk_subtrees, void *data) ...@@ -566,16 +581,28 @@ eliminate_local_variables_1 (tree * tp, int *walk_subtrees, void *data)
if (TREE_CODE (t) == ADDR_EXPR) if (TREE_CODE (t) == ADDR_EXPR)
{ {
var = TREE_OPERAND (t, 0); /* ADDR_EXPR may appear in two contexts:
if (!DECL_P (var)) -- as a gimple operand, when the address taken is a function invariant
-- as gimple rhs, when the resulting address in not a function
invariant
We do not need to do anything special in the latter case (the base of
the memory reference whose address is taken may be replaced in the
DECL_P case). The former case is more complicated, as we need to
ensure that the new address is still a gimple operand. Thus, it
is not sufficient to replace just the base of the memory reference --
we need to move the whole computation of the address out of the
loop. */
if (!is_gimple_val (t))
return NULL_TREE; return NULL_TREE;
*walk_subtrees = 0; *walk_subtrees = 0;
if (!SSA_VAR_P (var) || DECL_EXTERNAL (var)) obj = TREE_OPERAND (t, 0);
var = get_base_address (obj);
if (!var || !SSA_VAR_P (var) || DECL_EXTERNAL (var))
return NULL_TREE; return NULL_TREE;
addr_type = TREE_TYPE (t); addr_type = TREE_TYPE (t);
addr = take_address_of (var, addr_type, dta->loop, dta->decl_address); addr = take_address_of (obj, addr_type, dta->loop, dta->decl_address);
*tp = addr; *tp = addr;
dta->changed = true; dta->changed = true;
......
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