From: rakdver Date: Wed, 19 Dec 2007 15:01:19 +0000 (+0000) Subject: PR tree-optimization/34355 X-Git-Tag: upstream/4.9.2~44459 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c1fb5b25cf1cfeeb4771612651d69a4feddeebac;p=platform%2Fupstream%2Flinaro-gcc.git 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131063 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9aee92..d038634 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2007-12-19 Zdenek Dvorak + + 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 Revital Eres diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9701bee..024867a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-12-19 Zdenek Dvorak + + PR tree-optimization/34355 + * g++.dg/tree-ssa/pr34355.C: New test. + 2007-12-19 Revital Eres * gcc.dg/sms-5.c: New testcase. diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr34355.C b/gcc/testsuite/g++.dg/tree-ssa/pr34355.C new file mode 100644 index 0000000..212c547 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr34355.C @@ -0,0 +1,26 @@ +// { 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); +} diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 550c2e5..7639af6 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -431,29 +431,37 @@ loop_parallel_p (struct loop *loop, htab_t reduction_list, struct tree_niter_des 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 - 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 -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; struct int_tree_map ielt, *nielt; - tree name, bvar, stmt; + tree *var_p, name, bvar, stmt, addr; 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; dslot = htab_find_slot_with_hash (decl_address, &ielt, uid, INSERT); 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); - stmt = build_gimple_modify_stmt (bvar, - fold_convert (type, - build_addr (var, - current_function_decl))); + stmt = build_gimple_modify_stmt (bvar, addr); name = make_ssa_name (bvar, stmt); GIMPLE_STMT_OPERAND (stmt, 0) = name; 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) nielt->uid = uid; nielt->to = name; *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; + if (var_p != &obj) + { + *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name); + name = force_gimple_operand (build_addr (obj, current_function_decl), + &stmt, true, NULL_TREE); + if (stmt) + bsi_insert_on_edge_immediate (entry, stmt); + } - bvar = SSA_NAME_VAR (name); - stmt = build_gimple_modify_stmt (bvar, fold_convert (type, name)); - name = make_ssa_name (bvar, stmt); - GIMPLE_STMT_OPERAND (stmt, 0) = name; - 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); + } return name; } @@ -543,10 +558,10 @@ struct elv_data walk_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; - tree t = *tp, var, addr, addr_type, type; + tree t = *tp, var, addr, addr_type, type, obj; if (DECL_P (t)) { @@ -566,16 +581,28 @@ eliminate_local_variables_1 (tree * tp, int *walk_subtrees, void *data) if (TREE_CODE (t) == ADDR_EXPR) { - var = TREE_OPERAND (t, 0); - if (!DECL_P (var)) + /* ADDR_EXPR may appear in two contexts: + -- 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; *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; 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; dta->changed = true;