mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-24 11:24:05 +08:00
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:
parent
e054e6fb64
commit
917948d364
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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 **);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
{
|
||||
|
799
gcc/omp-low.c
799
gcc/omp-low.c
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
256
gcc/tree-cfg.c
256
gcc/tree-cfg.c
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user