cgraphbuild.c (rebuild_cgraph_edges): Export.

* cgraphbuild.c (rebuild_cgraph_edges): Export.
	* cgraph.h (rebuild_cgraph_edges): Declare.
	* tree-pass.h (pass_expand_omp_ssa): New.
	* omp-low.c (find_omp_clause): Export.
	(copy_var_decl): Split from omp_copy_decl_2.
	(build_omp_barrier): Return the call to emit instead of emitting
	it directly.
	(lower_rec_input_clauses, expand_omp_single): Gimplify the result of
	build_omp_barrier.
	(extract_omp_for_data, expand_parallel_call, expand_omp_parallel,
	expand_omp_for_generic, expand_omp_for_static_nochunk,
	expand_omp_for_static_chunk, expand_omp_for, expand_omp_sections):
	Adapted to work on SSA form.
	(execute_expand_omp): Do not invalidate dominance information.
	(gate_expand_omp): Do not run with -fopenmp-ssa flag.
	(gate_expand_omp_ssa, pass_expand_omp_ssa): New.
	* gimplify.c (gimplify_omp_for): Ensure that the control variable is
	a gimple_reg.
	(force_gimple_operand): Allow gimplifying code expressions without
	value.
	* tree-predcom.c (mark_virtual_ops_for_renaming): Handle phi nodes.
	* common.opt (fopenmp-ssa): New.
	* tree-flow.h (find_omp_clause, copy_var_decl): Declare.
	* Makefile.in (tree-cfg.o): Add TREE_INLINE_H dependency.
	* tree-cfg.c: Include tree-inline.h.
	(struct move_stmt_d): Replace vars_to_remove by vars_map field.
	(replace_by_duplicate_decl, replace_ssa_name,
	mark_virtual_ops_in_region): New functions.
	(move_stmt_r, move_block_to_fn, move_sese_region_to_fn): Adapted
	to work on SSA form.
	* passes.c (init_optimization_passes): Add pass_expand_omp_ssa pass.
	* tree-ssa-operands.c (get_expr_operands): Handle operands of OMP
	constructs.

From-SVN: r128223
This commit is contained in:
Zdenek Dvorak 2007-09-07 04:40:14 +02:00 committed by Zdenek Dvorak
parent e054e6fb64
commit 917948d364
13 changed files with 863 additions and 377 deletions

View File

@ -1,3 +1,39 @@
2007-09-06 Zdenek Dvorak <ook@ucw.cz>
* cgraphbuild.c (rebuild_cgraph_edges): Export.
* cgraph.h (rebuild_cgraph_edges): Declare.
* tree-pass.h (pass_expand_omp_ssa): New.
* omp-low.c (find_omp_clause): Export.
(copy_var_decl): Split from omp_copy_decl_2.
(build_omp_barrier): Return the call to emit instead of emitting
it directly.
(lower_rec_input_clauses, expand_omp_single): Gimplify the result of
build_omp_barrier.
(extract_omp_for_data, expand_parallel_call, expand_omp_parallel,
expand_omp_for_generic, expand_omp_for_static_nochunk,
expand_omp_for_static_chunk, expand_omp_for, expand_omp_sections):
Adapted to work on SSA form.
(execute_expand_omp): Do not invalidate dominance information.
(gate_expand_omp): Do not run with -fopenmp-ssa flag.
(gate_expand_omp_ssa, pass_expand_omp_ssa): New.
* gimplify.c (gimplify_omp_for): Ensure that the control variable is
a gimple_reg.
(force_gimple_operand): Allow gimplifying code expressions without
value.
* tree-predcom.c (mark_virtual_ops_for_renaming): Handle phi nodes.
* common.opt (fopenmp-ssa): New.
* tree-flow.h (find_omp_clause, copy_var_decl): Declare.
* Makefile.in (tree-cfg.o): Add TREE_INLINE_H dependency.
* tree-cfg.c: Include tree-inline.h.
(struct move_stmt_d): Replace vars_to_remove by vars_map field.
(replace_by_duplicate_decl, replace_ssa_name,
mark_virtual_ops_in_region): New functions.
(move_stmt_r, move_block_to_fn, move_sese_region_to_fn): Adapted
to work on SSA form.
* passes.c (init_optimization_passes): Add pass_expand_omp_ssa pass.
* tree-ssa-operands.c (get_expr_operands): Handle operands of OMP
constructs.
2007-09-06 Laurynas Biveinis <laurynas.biveinis@gmail.com>
* tree-loop-linear.c: Include obstack.h.

View File

@ -2079,7 +2079,7 @@ tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) except.h langhooks.h $(CFGLOOP_H) tree-pass.h \
$(CFGLAYOUT_H) $(BASIC_BLOCK_H) hard-reg-set.h toplev.h \
tree-ssa-propagate.h
tree-ssa-propagate.h $(TREE_INLINE_H)
tree-cfgcleanup.o : tree-cfgcleanup.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
$(DIAGNOSTIC_H) toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \

View File

@ -344,6 +344,9 @@ struct cgraph_node *save_inline_function_body (struct cgraph_node *);
void record_references_in_initializer (tree);
bool cgraph_process_new_functions (void);
/* In cgraphbuild.c */
unsigned int rebuild_cgraph_edges (void);
/* In ipa.c */
bool cgraph_remove_unreachable_nodes (bool, FILE *);
int cgraph_postorder (struct cgraph_node **);

View File

@ -202,7 +202,7 @@ record_references_in_initializer (tree decl)
/* Rebuild cgraph edges for current function node. This needs to be run after
passes that don't update the cgraph. */
static unsigned int
unsigned int
rebuild_cgraph_edges (void)
{
basic_block bb;

View File

@ -709,6 +709,10 @@ fomit-frame-pointer
Common Report Var(flag_omit_frame_pointer) Optimization
When possible do not generate stack frames
fopenmp-ssa
Common Report Var(flag_openmp_ssa)
Expand OpenMP operations on SSA form
foptimize-register-move
Common Report Var(flag_regmove) Optimization
Do the full register move optimization pass

View File

@ -5114,8 +5114,9 @@ gimplify_omp_parallel (tree *expr_p, tree *pre_p)
static enum gimplify_status
gimplify_omp_for (tree *expr_p, tree *pre_p)
{
tree for_stmt, decl, t;
tree for_stmt, decl, var, t;
enum gimplify_status ret = GS_OK;
tree body, init_decl = NULL_TREE;
for_stmt = *expr_p;
@ -5134,6 +5135,20 @@ gimplify_omp_for (tree *expr_p, tree *pre_p)
else
omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
/* If DECL is not a gimple register, create a temporary variable to act as an
iteration counter. This is valid, since DECL cannot be modified in the
body of the loop. */
if (!is_gimple_reg (decl))
{
var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
GENERIC_TREE_OPERAND (t, 0) = var;
init_decl = build_gimple_modify_stmt (decl, var);
omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
}
else
var = decl;
ret |= gimplify_expr (&GENERIC_TREE_OPERAND (t, 1),
&OMP_FOR_PRE_BODY (for_stmt),
NULL, is_gimple_val, fb_rvalue);
@ -5143,6 +5158,7 @@ gimplify_omp_for (tree *expr_p, tree *pre_p)
t = OMP_FOR_COND (for_stmt);
gcc_assert (COMPARISON_CLASS_P (t));
gcc_assert (GENERIC_TREE_OPERAND (t, 0) == decl);
TREE_OPERAND (t, 0) = var;
ret |= gimplify_expr (&GENERIC_TREE_OPERAND (t, 1),
&OMP_FOR_PRE_BODY (for_stmt),
@ -5155,21 +5171,23 @@ gimplify_omp_for (tree *expr_p, tree *pre_p)
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
t = build_int_cst (TREE_TYPE (decl), 1);
t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
t = build_gimple_modify_stmt (decl, t);
t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
t = build_gimple_modify_stmt (var, t);
OMP_FOR_INCR (for_stmt) = t;
break;
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
t = build_int_cst (TREE_TYPE (decl), -1);
t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
t = build_gimple_modify_stmt (decl, t);
t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
t = build_gimple_modify_stmt (var, t);
OMP_FOR_INCR (for_stmt) = t;
break;
case GIMPLE_MODIFY_STMT:
gcc_assert (GIMPLE_STMT_OPERAND (t, 0) == decl);
GIMPLE_STMT_OPERAND (t, 0) = var;
t = GIMPLE_STMT_OPERAND (t, 1);
switch (TREE_CODE (t))
{
@ -5177,11 +5195,14 @@ gimplify_omp_for (tree *expr_p, tree *pre_p)
if (TREE_OPERAND (t, 1) == decl)
{
TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
TREE_OPERAND (t, 0) = decl;
TREE_OPERAND (t, 0) = var;
break;
}
/* Fallthru. */
case MINUS_EXPR:
gcc_assert (TREE_OPERAND (t, 0) == decl);
TREE_OPERAND (t, 0) = var;
break;
default:
gcc_unreachable ();
@ -5195,7 +5216,13 @@ gimplify_omp_for (tree *expr_p, tree *pre_p)
gcc_unreachable ();
}
gimplify_to_stmt_list (&OMP_FOR_BODY (for_stmt));
body = OMP_FOR_BODY (for_stmt);
gimplify_to_stmt_list (&body);
t = alloc_stmt_list ();
if (init_decl)
append_to_statement_list (init_decl, &t);
append_to_statement_list (body, &t);
OMP_FOR_BODY (for_stmt) = t;
gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
return ret == GS_ALL_DONE ? GS_ALL_DONE : GS_ERROR;
@ -6591,9 +6618,18 @@ force_gimple_operand (tree expr, tree *stmts, bool simple, tree var)
if (var)
expr = build_gimple_modify_stmt (var, expr);
ret = gimplify_expr (&expr, stmts, NULL,
gimple_test_f, fb_rvalue);
gcc_assert (ret != GS_ERROR);
if (TREE_CODE (expr) != GIMPLE_MODIFY_STMT
&& TREE_TYPE (expr) == void_type_node)
{
gimplify_and_add (expr, stmts);
expr = NULL_TREE;
}
else
{
ret = gimplify_expr (&expr, stmts, NULL,
gimple_test_f, fb_rvalue);
gcc_assert (ret != GS_ERROR);
}
if (gimple_referenced_vars (cfun))
{

File diff suppressed because it is too large Load Diff

View File

@ -515,6 +515,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_referenced_vars);
NEXT_PASS (pass_reset_cc_flags);
NEXT_PASS (pass_build_ssa);
NEXT_PASS (pass_expand_omp_ssa);
NEXT_PASS (pass_early_warn_uninitialized);
NEXT_PASS (pass_rebuild_cgraph_edges);
NEXT_PASS (pass_early_inline);

View File

@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "value-prof.h"
#include "pointer-set.h"
#include "tree-inline.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
@ -5248,13 +5249,89 @@ gather_blocks_in_sese_region (basic_block entry, basic_block exit,
}
}
/* Replaces *TP with a duplicate (belonging to function TO_CONTEXT).
The duplicates are recorded in VARS_MAP. */
static void
replace_by_duplicate_decl (tree *tp, struct pointer_map_t *vars_map,
tree to_context)
{
tree t = *tp, new_t;
struct function *f = DECL_STRUCT_FUNCTION (to_context);
void **loc;
if (DECL_CONTEXT (t) == to_context)
return;
loc = pointer_map_contains (vars_map, t);
if (!loc)
{
loc = pointer_map_insert (vars_map, t);
if (SSA_VAR_P (t))
{
new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t));
f->unexpanded_var_list
= tree_cons (NULL_TREE, new_t, f->unexpanded_var_list);
}
else
{
gcc_assert (TREE_CODE (t) == CONST_DECL);
new_t = copy_node (t);
}
DECL_CONTEXT (new_t) = to_context;
*loc = new_t;
}
else
new_t = *loc;
*tp = new_t;
}
/* Creates an ssa name in TO_CONTEXT equivalent to NAME.
VARS_MAP maps old ssa names and var_decls to the new ones. */
static tree
replace_ssa_name (tree name, struct pointer_map_t *vars_map,
tree to_context)
{
void **loc;
tree new_name, decl = SSA_NAME_VAR (name);
gcc_assert (is_gimple_reg (name));
loc = pointer_map_contains (vars_map, name);
if (!loc)
{
replace_by_duplicate_decl (&decl, vars_map, to_context);
push_cfun (DECL_STRUCT_FUNCTION (to_context));
if (gimple_in_ssa_p (cfun))
add_referenced_var (decl);
new_name = make_ssa_name (decl, SSA_NAME_DEF_STMT (name));
if (SSA_NAME_IS_DEFAULT_DEF (name))
set_default_def (decl, new_name);
pop_cfun ();
loc = pointer_map_insert (vars_map, name);
*loc = new_name;
}
else
new_name = *loc;
return new_name;
}
struct move_stmt_d
{
tree block;
tree from_context;
tree to_context;
bitmap vars_to_remove;
struct pointer_map_t *vars_map;
htab_t new_label_map;
bool remap_decls_p;
};
@ -5289,9 +5366,11 @@ move_stmt_r (tree *tp, int *walk_subtrees, void *data)
p->remap_decls_p = save_remap_decls_p;
}
else if (DECL_P (t) && DECL_CONTEXT (t) == p->from_context)
else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
{
if (TREE_CODE (t) == LABEL_DECL)
if (TREE_CODE (t) == SSA_NAME)
*tp = replace_ssa_name (t, p->vars_map, p->to_context);
else if (TREE_CODE (t) == LABEL_DECL)
{
if (p->new_label_map)
{
@ -5306,20 +5385,26 @@ move_stmt_r (tree *tp, int *walk_subtrees, void *data)
}
else if (p->remap_decls_p)
{
DECL_CONTEXT (t) = p->to_context;
/* Replace T with its duplicate. T should no longer appear in the
parent function, so this looks wasteful; however, it may appear
in referenced_vars, and more importantly, as virtual operands of
statements, and in alias lists of other variables. It would be
quite difficult to expunge it from all those places. ??? It might
suffice to do this for addressable variables. */
if ((TREE_CODE (t) == VAR_DECL
&& !is_global_var (t))
|| TREE_CODE (t) == CONST_DECL)
replace_by_duplicate_decl (tp, p->vars_map, p->to_context);
if (TREE_CODE (t) == VAR_DECL)
if (SSA_VAR_P (t)
&& gimple_in_ssa_p (cfun))
{
struct function *f = DECL_STRUCT_FUNCTION (p->to_context);
f->unexpanded_var_list
= tree_cons (0, t, f->unexpanded_var_list);
/* Mark T to be removed from the original function,
otherwise it will be given a DECL_RTL when the
original function is expanded. */
bitmap_set_bit (p->vars_to_remove, DECL_UID (t));
push_cfun (DECL_STRUCT_FUNCTION (p->to_context));
add_referenced_var (*tp);
pop_cfun ();
}
}
*walk_subtrees = 0;
}
else if (TYPE_P (t))
*walk_subtrees = 0;
@ -5327,6 +5412,26 @@ move_stmt_r (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
/* Marks virtual operands of all statements in basic blocks BBS for
renaming. */
static void
mark_virtual_ops_in_region (VEC (basic_block,heap) *bbs)
{
tree phi;
block_stmt_iterator bsi;
basic_block bb;
unsigned i;
for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
{
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
mark_virtual_ops_for_renaming (phi);
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
mark_virtual_ops_for_renaming (bsi_stmt (bsi));
}
}
/* Move basic block BB from function CFUN to function DEST_FN. The
block is moved out of the original linked list and placed after
@ -5335,13 +5440,14 @@ move_stmt_r (tree *tp, int *walk_subtrees, void *data)
If UPDATE_EDGE_COUNT_P is true, the edge counts on both CFGs is
updated to reflect the moved edges.
On exit, local variables that need to be removed from
CFUN->UNEXPANDED_VAR_LIST will have been added to VARS_TO_REMOVE. */
The local variables are remapped to new instances, VARS_MAP is used
to record the mapping. */
static void
move_block_to_fn (struct function *dest_cfun, basic_block bb,
basic_block after, bool update_edge_count_p,
bitmap vars_to_remove, htab_t new_label_map, int eh_offset)
struct pointer_map_t *vars_map, htab_t new_label_map,
int eh_offset)
{
struct control_flow_graph *cfg;
edge_iterator ei;
@ -5349,6 +5455,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
block_stmt_iterator si;
struct move_stmt_d d;
unsigned old_len, new_len;
tree phi;
/* Remove BB from dominance structures. */
delete_from_dominance_info (CDI_DOMINATORS, bb);
@ -5385,20 +5492,39 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
VEC_replace (basic_block, cfg->x_basic_block_info,
bb->index, bb);
/* Remap the variables in phi nodes. */
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
use_operand_p use;
tree op = PHI_RESULT (phi);
ssa_op_iter oi;
if (!is_gimple_reg (op))
continue;
SET_PHI_RESULT (phi, replace_ssa_name (op, vars_map, dest_cfun->decl));
FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE)
{
op = USE_FROM_PTR (use);
if (TREE_CODE (op) == SSA_NAME)
SET_USE (use, replace_ssa_name (op, vars_map, dest_cfun->decl));
}
}
/* The statements in BB need to be associated with a new TREE_BLOCK.
Labels need to be associated with a new label-to-block map. */
memset (&d, 0, sizeof (d));
d.vars_to_remove = vars_to_remove;
d.vars_map = vars_map;
d.from_context = cfun->decl;
d.to_context = dest_cfun->decl;
d.new_label_map = new_label_map;
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
tree stmt = bsi_stmt (si);
int region;
d.from_context = cfun->decl;
d.to_context = dest_cfun->decl;
d.remap_decls_p = true;
d.new_label_map = new_label_map;
if (TREE_BLOCK (stmt))
d.block = DECL_INITIAL (dest_cfun->decl);
@ -5441,6 +5567,8 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
gimple_duplicate_stmt_histograms (dest_cfun, stmt, cfun, stmt);
gimple_remove_stmt_histograms (cfun, stmt);
}
update_stmt (stmt);
}
}
@ -5518,21 +5646,17 @@ basic_block
move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
basic_block exit_bb)
{
VEC(basic_block,heap) *bbs;
basic_block after, bb, *entry_pred, *exit_succ;
struct function *saved_cfun;
VEC(basic_block,heap) *bbs, *dom_bbs;
basic_block dom_entry = get_immediate_dominator (CDI_DOMINATORS, entry_bb);
basic_block after, bb, *entry_pred, *exit_succ, abb;
struct function *saved_cfun = cfun;
int *entry_flag, *exit_flag, eh_offset;
unsigned *entry_prob, *exit_prob;
unsigned i, num_entry_edges, num_exit_edges;
edge e;
edge_iterator ei;
bitmap vars_to_remove;
htab_t new_label_map;
saved_cfun = cfun;
/* Collect all the blocks in the region. Manually add ENTRY_BB
because it won't be added by dfs_enumerate_from. */
calculate_dominance_info (CDI_DOMINATORS);
struct pointer_map_t *vars_map;
/* If ENTRY does not strictly dominate EXIT, this cannot be an SESE
region. */
@ -5540,10 +5664,18 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
&& (!exit_bb
|| dominated_by_p (CDI_DOMINATORS, exit_bb, entry_bb)));
/* Collect all the blocks in the region. Manually add ENTRY_BB
because it won't be added by dfs_enumerate_from. */
bbs = NULL;
VEC_safe_push (basic_block, heap, bbs, entry_bb);
gather_blocks_in_sese_region (entry_bb, exit_bb, &bbs);
/* The blocks that used to be dominated by something in BBS will now be
dominated by the new block. */
dom_bbs = get_dominated_by_region (CDI_DOMINATORS,
VEC_address (basic_block, bbs),
VEC_length (basic_block, bbs));
/* Detach ENTRY_BB and EXIT_BB from CFUN->CFG. We need to remember
the predecessor edges to ENTRY_BB and the successor edges to
EXIT_BB so that we can re-attach them to the new basic block that
@ -5551,9 +5683,11 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
num_entry_edges = EDGE_COUNT (entry_bb->preds);
entry_pred = (basic_block *) xcalloc (num_entry_edges, sizeof (basic_block));
entry_flag = (int *) xcalloc (num_entry_edges, sizeof (int));
entry_prob = XNEWVEC (unsigned, num_entry_edges);
i = 0;
for (ei = ei_start (entry_bb->preds); (e = ei_safe_edge (ei)) != NULL;)
{
entry_prob[i] = e->probability;
entry_flag[i] = e->flags;
entry_pred[i++] = e->src;
remove_edge (e);
@ -5565,9 +5699,11 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
exit_succ = (basic_block *) xcalloc (num_exit_edges,
sizeof (basic_block));
exit_flag = (int *) xcalloc (num_exit_edges, sizeof (int));
exit_prob = XNEWVEC (unsigned, num_exit_edges);
i = 0;
for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
{
exit_prob[i] = e->probability;
exit_flag[i] = e->flags;
exit_succ[i++] = e->dest;
remove_edge (e);
@ -5578,11 +5714,12 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
num_exit_edges = 0;
exit_succ = NULL;
exit_flag = NULL;
exit_prob = NULL;
}
/* Switch context to the child function to initialize DEST_FN's CFG. */
gcc_assert (dest_cfun->cfg == NULL);
set_cfun (dest_cfun);
push_cfun (dest_cfun);
init_empty_tree_cfg ();
@ -5605,46 +5742,30 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
}
}
set_cfun (saved_cfun);
pop_cfun ();
/* The ssa form for virtual operands in the source function will have to
be repaired. We do not care for the real operands -- the sese region
must be closed with respect to those. */
mark_virtual_ops_in_region (bbs);
/* Move blocks from BBS into DEST_CFUN. */
gcc_assert (VEC_length (basic_block, bbs) >= 2);
after = dest_cfun->cfg->x_entry_block_ptr;
vars_to_remove = BITMAP_ALLOC (NULL);
vars_map = pointer_map_create ();
for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
{
/* No need to update edge counts on the last block. It has
already been updated earlier when we detached the region from
the original CFG. */
move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_to_remove,
move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_map,
new_label_map, eh_offset);
after = bb;
}
if (new_label_map)
htab_delete (new_label_map);
/* Remove the variables marked in VARS_TO_REMOVE from
CFUN->UNEXPANDED_VAR_LIST. Otherwise, they will be given a
DECL_RTL in the context of CFUN. */
if (!bitmap_empty_p (vars_to_remove))
{
tree *p;
for (p = &cfun->unexpanded_var_list; *p; )
{
tree var = TREE_VALUE (*p);
if (bitmap_bit_p (vars_to_remove, DECL_UID (var)))
{
*p = TREE_CHAIN (*p);
continue;
}
p = &TREE_CHAIN (*p);
}
}
BITMAP_FREE (vars_to_remove);
pointer_map_destroy (vars_map);
/* Rewire the entry and exit blocks. The successor to the entry
block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in
@ -5655,30 +5776,41 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
FIXME, this is silly. The CFG ought to become a parameter to
these helpers. */
set_cfun (dest_cfun);
push_cfun (dest_cfun);
make_edge (ENTRY_BLOCK_PTR, entry_bb, EDGE_FALLTHRU);
if (exit_bb)
make_edge (exit_bb, EXIT_BLOCK_PTR, 0);
set_cfun (saved_cfun);
pop_cfun ();
/* Back in the original function, the SESE region has disappeared,
create a new basic block in its place. */
bb = create_empty_bb (entry_pred[0]);
for (i = 0; i < num_entry_edges; i++)
make_edge (entry_pred[i], bb, entry_flag[i]);
{
e = make_edge (entry_pred[i], bb, entry_flag[i]);
e->probability = entry_prob[i];
}
for (i = 0; i < num_exit_edges; i++)
make_edge (bb, exit_succ[i], exit_flag[i]);
{
e = make_edge (bb, exit_succ[i], exit_flag[i]);
e->probability = exit_prob[i];
}
set_immediate_dominator (CDI_DOMINATORS, bb, dom_entry);
for (i = 0; VEC_iterate (basic_block, dom_bbs, i, abb); i++)
set_immediate_dominator (CDI_DOMINATORS, abb, bb);
VEC_free (basic_block, heap, dom_bbs);
if (exit_bb)
{
free (exit_prob);
free (exit_flag);
free (exit_succ);
}
free (entry_prob);
free (entry_flag);
free (entry_pred);
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
VEC_free (basic_block, heap, bbs);
return bb;

View File

@ -711,6 +711,8 @@ extern struct omp_region *root_omp_region;
extern struct omp_region *new_omp_region (basic_block, enum tree_code,
struct omp_region *);
extern void free_omp_regions (void);
extern tree find_omp_clause (tree, enum tree_code);
tree copy_var_decl (tree, tree, tree);
/*---------------------------------------------------------------------------
Function prototypes

View File

@ -290,6 +290,7 @@ extern struct tree_opt_pass pass_lower_vector;
extern struct tree_opt_pass pass_lower_vector_ssa;
extern struct tree_opt_pass pass_lower_omp;
extern struct tree_opt_pass pass_expand_omp;
extern struct tree_opt_pass pass_expand_omp_ssa;
extern struct tree_opt_pass pass_object_sizes;
extern struct tree_opt_pass pass_fold_builtins;
extern struct tree_opt_pass pass_stdarg;

View File

@ -1393,7 +1393,16 @@ mark_virtual_ops_for_renaming (tree stmt)
tree var;
if (TREE_CODE (stmt) == PHI_NODE)
return;
{
var = PHI_RESULT (stmt);
if (is_gimple_reg (var))
return;
if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var);
mark_sym_for_renaming (var);
return;
}
update_stmt (stmt);

View File

@ -2247,21 +2247,72 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
get_expr_operands (stmt, &CHANGE_DYNAMIC_TYPE_LOCATION (expr), opf_use);
return;
case OMP_FOR:
{
tree init = OMP_FOR_INIT (expr);
tree cond = OMP_FOR_COND (expr);
tree incr = OMP_FOR_INCR (expr);
tree c, clauses = OMP_FOR_CLAUSES (stmt);
get_expr_operands (stmt, &GIMPLE_STMT_OPERAND (init, 0), opf_def);
get_expr_operands (stmt, &GIMPLE_STMT_OPERAND (init, 1), opf_use);
get_expr_operands (stmt, &TREE_OPERAND (cond, 1), opf_use);
get_expr_operands (stmt, &TREE_OPERAND (GIMPLE_STMT_OPERAND (incr, 1), 1),
opf_use);
c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
if (c)
get_expr_operands (stmt, &OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c),
opf_use);
return;
}
case OMP_CONTINUE:
{
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_def);
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
return;
}
case OMP_PARALLEL:
{
tree c, clauses = OMP_PARALLEL_CLAUSES (stmt);
if (OMP_PARALLEL_DATA_ARG (stmt))
{
get_expr_operands (stmt, &OMP_PARALLEL_DATA_ARG (stmt), opf_use);
add_to_addressable_set (OMP_PARALLEL_DATA_ARG (stmt),
&s_ann->addresses_taken);
}
c = find_omp_clause (clauses, OMP_CLAUSE_IF);
if (c)
get_expr_operands (stmt, &OMP_CLAUSE_IF_EXPR (c), opf_use);
c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
if (c)
get_expr_operands (stmt, &OMP_CLAUSE_NUM_THREADS_EXPR (c), opf_use);
return;
}
case OMP_SECTIONS:
{
get_expr_operands (stmt, &OMP_SECTIONS_CONTROL (expr), opf_def);
return;
}
case BLOCK:
case FUNCTION_DECL:
case EXC_PTR_EXPR:
case FILTER_EXPR:
case LABEL_DECL:
case CONST_DECL:
case OMP_PARALLEL:
case OMP_SECTIONS:
case OMP_FOR:
case OMP_SINGLE:
case OMP_MASTER:
case OMP_ORDERED:
case OMP_CRITICAL:
case OMP_RETURN:
case OMP_CONTINUE:
case OMP_SECTION:
case OMP_SECTIONS_SWITCH:
/* Expressions that make no memory references. */
return;