summaryrefslogtreecommitdiff
path: root/gcc/tree-parloops.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-10-30 09:35:42 +0000
committer <>2015-01-09 11:51:27 +0000
commitc27a97d04853380f1e80525391b3f0d156ed4c84 (patch)
tree68ffaade7c605bc80cffa18360799c98a810976f /gcc/tree-parloops.c
parent6af3fdec2262dd94954acc5e426ef71cbd4521d3 (diff)
downloadgcc-tarball-c27a97d04853380f1e80525391b3f0d156ed4c84.tar.gz
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-4.9.2.tar.bz2.gcc-4.9.2
Diffstat (limited to 'gcc/tree-parloops.c')
-rw-r--r--gcc/tree-parloops.c606
1 files changed, 337 insertions, 269 deletions
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 0ae5d444e6..47179a967e 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1,8 +1,7 @@
/* Loop autoparallelization.
- Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
- Free Software Foundation, Inc.
- Contributed by Sebastian Pop <pop@cri.ensmp.fr> and
- Zdenek Dvorak <dvorakz@suse.cz>.
+ Copyright (C) 2006-2014 Free Software Foundation, Inc.
+ Contributed by Sebastian Pop <pop@cri.ensmp.fr>
+ Zdenek Dvorak <dvorakz@suse.cz> and Razya Ladelsky <razya@il.ibm.com>.
This file is part of GCC.
@@ -23,7 +22,30 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tree-flow.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimplify-me.h"
+#include "gimple-walk.h"
+#include "stor-layout.h"
+#include "tree-nested.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
@@ -31,6 +53,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "langhooks.h"
#include "tree-vectorizer.h"
+#include "tree-hasher.h"
+#include "tree-parloops.h"
+#include "omp-low.h"
+#include "tree-nested.h"
/* This pass tries to distribute iterations of loops into several threads.
The implementation is straightforward -- for each loop we test whether its
@@ -54,9 +80,9 @@ along with GCC; see the file COPYING3. If not see
-- if there are several parallelizable loops in a function, it may be
possible to generate the threads just once (using synchronization to
ensure that cross-loop dependences are obeyed).
- -- handling of common scalar dependence patterns (accumulation, ...)
- -- handling of non-innermost loops */
-
+ -- handling of common reduction patterns for outer loops.
+
+ More info can also be found at http://gcc.gnu.org/wiki/AutoParInGCC */
/*
Reduction handling:
currently we use vect_force_simple_reduction() to detect reduction patterns.
@@ -177,36 +203,44 @@ struct reduction_info
operation. */
};
-/* Equality and hash functions for hashtab code. */
+/* Reduction info hashtable helpers. */
-static int
-reduction_info_eq (const void *aa, const void *bb)
+struct reduction_hasher : typed_free_remove <reduction_info>
{
- const struct reduction_info *a = (const struct reduction_info *) aa;
- const struct reduction_info *b = (const struct reduction_info *) bb;
+ typedef reduction_info value_type;
+ typedef reduction_info compare_type;
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+};
+/* Equality and hash functions for hashtab code. */
+
+inline bool
+reduction_hasher::equal (const value_type *a, const compare_type *b)
+{
return (a->reduc_phi == b->reduc_phi);
}
-static hashval_t
-reduction_info_hash (const void *aa)
+inline hashval_t
+reduction_hasher::hash (const value_type *a)
{
- const struct reduction_info *a = (const struct reduction_info *) aa;
-
return a->reduc_version;
}
+typedef hash_table <reduction_hasher> reduction_info_table_type;
+
+
static struct reduction_info *
-reduction_phi (htab_t reduction_list, gimple phi)
+reduction_phi (reduction_info_table_type reduction_list, gimple phi)
{
struct reduction_info tmpred, *red;
- if (htab_elements (reduction_list) == 0 || phi == NULL)
+ if (reduction_list.elements () == 0 || phi == NULL)
return NULL;
tmpred.reduc_phi = phi;
tmpred.reduc_version = gimple_uid (phi);
- red = (struct reduction_info *) htab_find (reduction_list, &tmpred);
+ red = reduction_list.find (&tmpred);
return red;
}
@@ -221,25 +255,32 @@ struct name_to_copy_elt
value. */
};
-/* Equality and hash functions for hashtab code. */
+/* Name copies hashtable helpers. */
-static int
-name_to_copy_elt_eq (const void *aa, const void *bb)
+struct name_to_copy_hasher : typed_free_remove <name_to_copy_elt>
{
- const struct name_to_copy_elt *a = (const struct name_to_copy_elt *) aa;
- const struct name_to_copy_elt *b = (const struct name_to_copy_elt *) bb;
+ typedef name_to_copy_elt value_type;
+ typedef name_to_copy_elt compare_type;
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+};
+/* Equality and hash functions for hashtab code. */
+
+inline bool
+name_to_copy_hasher::equal (const value_type *a, const compare_type *b)
+{
return a->version == b->version;
}
-static hashval_t
-name_to_copy_elt_hash (const void *aa)
+inline hashval_t
+name_to_copy_hasher::hash (const value_type *a)
{
- const struct name_to_copy_elt *a = (const struct name_to_copy_elt *) aa;
-
return (hashval_t) a->version;
}
+typedef hash_table <name_to_copy_hasher> name_to_copy_table_type;
+
/* A transformation matrix, which is a self-contained ROWSIZE x COLSIZE
matrix. Rather than use floats, we simply keep a single DENOMINATOR that
represents the denominator for every element in the matrix. */
@@ -304,7 +345,7 @@ lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
static bool
lambda_transform_legal_p (lambda_trans_matrix trans,
int nb_loops,
- VEC (ddr_p, heap) *dependence_relations)
+ vec<ddr_p> dependence_relations)
{
unsigned int i, j;
lambda_vector distres;
@@ -314,10 +355,10 @@ lambda_transform_legal_p (lambda_trans_matrix trans,
&& LTM_ROWSIZE (trans) == nb_loops);
/* When there are no dependences, the transformation is correct. */
- if (VEC_length (ddr_p, dependence_relations) == 0)
+ if (dependence_relations.length () == 0)
return true;
- ddr = VEC_index (ddr_p, dependence_relations, 0);
+ ddr = dependence_relations[0];
if (ddr == NULL)
return true;
@@ -329,7 +370,7 @@ lambda_transform_legal_p (lambda_trans_matrix trans,
distres = lambda_vector_new (nb_loops);
/* For each distance vector in the dependence graph. */
- FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr)
+ FOR_EACH_VEC_ELT (dependence_relations, i, ddr)
{
/* Don't care about relations for which we know that there is no
dependence, nor about read-read (aka. output-dependences):
@@ -367,9 +408,8 @@ lambda_transform_legal_p (lambda_trans_matrix trans,
static bool
loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
{
- VEC (loop_p, heap) *loop_nest;
- VEC (ddr_p, heap) *dependence_relations;
- VEC (data_reference_p, heap) *datarefs;
+ vec<ddr_p> dependence_relations;
+ vec<data_reference_p> datarefs;
lambda_trans_matrix trans;
bool ret = false;
@@ -384,9 +424,9 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
/* Check for problems with dependences. If the loop can be reversed,
the iterations are independent. */
- datarefs = VEC_alloc (data_reference_p, heap, 10);
- dependence_relations = VEC_alloc (ddr_p, heap, 10 * 10);
- loop_nest = VEC_alloc (loop_p, heap, 3);
+ auto_vec<loop_p, 3> loop_nest;
+ datarefs.create (10);
+ dependence_relations.create (100);
if (! compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs,
&dependence_relations))
{
@@ -412,7 +452,6 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
" FAILED: data dependencies exist across iterations\n");
end:
- VEC_free (loop_p, heap, loop_nest);
free_dependence_relations (dependence_relations);
free_data_refs (datarefs);
@@ -446,13 +485,13 @@ loop_has_blocks_with_irreducible_flag (struct loop *loop)
right before GSI. */
static tree
-take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
- gimple_stmt_iterator *gsi)
+take_address_of (tree obj, tree type, edge entry,
+ int_tree_htab_type decl_address, gimple_stmt_iterator *gsi)
{
int uid;
- void **dslot;
+ int_tree_map **dslot;
struct int_tree_map ielt, *nielt;
- tree *var_p, name, bvar, addr;
+ tree *var_p, name, addr;
gimple stmt;
gimple_seq stmts;
@@ -473,19 +512,19 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
on it. */
uid = DECL_UID (TREE_OPERAND (TREE_OPERAND (*var_p, 0), 0));
ielt.uid = uid;
- dslot = htab_find_slot_with_hash (decl_address, &ielt, uid, INSERT);
+ dslot = decl_address.find_slot_with_hash (&ielt, uid, INSERT);
if (!*dslot)
{
if (gsi == NULL)
return NULL;
addr = TREE_OPERAND (*var_p, 0);
- bvar = create_tmp_var (TREE_TYPE (addr),
- get_name (TREE_OPERAND
- (TREE_OPERAND (*var_p, 0), 0)));
- add_referenced_var (bvar);
- stmt = gimple_build_assign (bvar, addr);
- name = make_ssa_name (bvar, stmt);
- gimple_assign_set_lhs (stmt, name);
+ const char *obj_name
+ = get_name (TREE_OPERAND (TREE_OPERAND (*var_p, 0), 0));
+ if (obj_name)
+ name = make_temp_ssa_name (TREE_TYPE (addr), NULL, obj_name);
+ else
+ name = make_ssa_name (TREE_TYPE (addr), NULL);
+ stmt = gimple_build_assign (name, addr);
gsi_insert_on_edge_immediate (entry, stmt);
nielt = XNEW (struct int_tree_map);
@@ -494,7 +533,7 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
*dslot = nielt;
}
else
- name = ((struct int_tree_map *) *dslot)->to;
+ name = (*dslot)->to;
/* Express the address in terms of the canonical SSA name. */
TREE_OPERAND (*var_p, 0) = name;
@@ -521,15 +560,14 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
for reduction described in SLOT, and place it at the preheader of
the loop described in DATA. */
-static int
-initialize_reductions (void **slot, void *data)
+int
+initialize_reductions (reduction_info **slot, struct loop *loop)
{
tree init, c;
tree bvar, type, arg;
edge e;
- struct reduction_info *const reduc = (struct reduction_info *) *slot;
- struct loop *loop = (struct loop *) data;
+ struct reduction_info *const reduc = *slot;
/* Create initialization in preheader:
reduction_variable = initialization value of reduction. */
@@ -540,7 +578,6 @@ initialize_reductions (void **slot, void *data)
/* Create a new variable to initialize the reduction. */
type = TREE_TYPE (PHI_RESULT (reduc->reduc_phi));
bvar = create_tmp_var (type, "reduction");
- add_referenced_var (bvar);
c = build_omp_clause (gimple_location (reduc->reduc_stmt),
OMP_CLAUSE_REDUCTION);
@@ -572,7 +609,7 @@ struct elv_data
{
struct walk_stmt_info info;
edge entry;
- htab_t decl_address;
+ int_tree_htab_type decl_address;
gimple_stmt_iterator *gsi;
bool changed;
bool reset;
@@ -662,7 +699,7 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data)
static void
eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi,
- htab_t decl_address)
+ int_tree_htab_type decl_address)
{
struct elv_data dta;
gimple stmt = gsi_stmt (*gsi);
@@ -684,6 +721,12 @@ eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi,
dta.changed = true;
}
}
+ else if (gimple_clobber_p (stmt))
+ {
+ stmt = gimple_build_nop ();
+ gsi_replace (gsi, stmt, false);
+ dta.changed = true;
+ }
else
{
dta.gsi = gsi;
@@ -709,18 +752,18 @@ static void
eliminate_local_variables (edge entry, edge exit)
{
basic_block bb;
- VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
+ auto_vec<basic_block, 3> body;
unsigned i;
gimple_stmt_iterator gsi;
bool has_debug_stmt = false;
- htab_t decl_address = htab_create (10, int_tree_map_hash, int_tree_map_eq,
- free);
+ int_tree_htab_type decl_address;
+ decl_address.create (10);
basic_block entry_bb = entry->src;
basic_block exit_bb = exit->dest;
gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
- FOR_EACH_VEC_ELT (basic_block, body, i, bb)
+ FOR_EACH_VEC_ELT (body, i, bb)
if (bb != entry_bb && bb != exit_bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
if (is_gimple_debug (gsi_stmt (gsi)))
@@ -732,14 +775,13 @@ eliminate_local_variables (edge entry, edge exit)
eliminate_local_variables_stmt (entry, &gsi, decl_address);
if (has_debug_stmt)
- FOR_EACH_VEC_ELT (basic_block, body, i, bb)
+ FOR_EACH_VEC_ELT (body, i, bb)
if (bb != entry_bb && bb != exit_bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
if (gimple_debug_bind_p (gsi_stmt (gsi)))
eliminate_local_variables_stmt (entry, &gsi, decl_address);
- htab_delete (decl_address);
- VEC_free (basic_block, heap, body);
+ decl_address.dispose ();
}
/* Returns true if expression EXPR is not defined between ENTRY and
@@ -777,35 +819,52 @@ expr_invariant_in_region_p (edge entry, edge exit, tree expr)
duplicated, storing the copies in DECL_COPIES. */
static tree
-separate_decls_in_region_name (tree name,
- htab_t name_copies, htab_t decl_copies,
- bool copy_name_p)
+separate_decls_in_region_name (tree name, name_to_copy_table_type name_copies,
+ int_tree_htab_type decl_copies, bool copy_name_p)
{
tree copy, var, var_copy;
unsigned idx, uid, nuid;
struct int_tree_map ielt, *nielt;
struct name_to_copy_elt elt, *nelt;
- void **slot, **dslot;
+ name_to_copy_elt **slot;
+ int_tree_map **dslot;
if (TREE_CODE (name) != SSA_NAME)
return name;
idx = SSA_NAME_VERSION (name);
elt.version = idx;
- slot = htab_find_slot_with_hash (name_copies, &elt, idx,
- copy_name_p ? INSERT : NO_INSERT);
+ slot = name_copies.find_slot_with_hash (&elt, idx,
+ copy_name_p ? INSERT : NO_INSERT);
if (slot && *slot)
- return ((struct name_to_copy_elt *) *slot)->new_name;
+ return (*slot)->new_name;
+
+ if (copy_name_p)
+ {
+ copy = duplicate_ssa_name (name, NULL);
+ nelt = XNEW (struct name_to_copy_elt);
+ nelt->version = idx;
+ nelt->new_name = copy;
+ nelt->field = NULL_TREE;
+ *slot = nelt;
+ }
+ else
+ {
+ gcc_assert (!slot);
+ copy = name;
+ }
var = SSA_NAME_VAR (name);
+ if (!var)
+ return copy;
+
uid = DECL_UID (var);
ielt.uid = uid;
- dslot = htab_find_slot_with_hash (decl_copies, &ielt, uid, INSERT);
+ dslot = decl_copies.find_slot_with_hash (&ielt, uid, INSERT);
if (!*dslot)
{
var_copy = create_tmp_var (TREE_TYPE (var), get_name (var));
DECL_GIMPLE_REG_P (var_copy) = DECL_GIMPLE_REG_P (var);
- add_referenced_var (var_copy);
nielt = XNEW (struct int_tree_map);
nielt->uid = uid;
nielt->to = var_copy;
@@ -815,7 +874,7 @@ separate_decls_in_region_name (tree name,
it again. */
nuid = DECL_UID (var_copy);
ielt.uid = nuid;
- dslot = htab_find_slot_with_hash (decl_copies, &ielt, nuid, INSERT);
+ dslot = decl_copies.find_slot_with_hash (&ielt, nuid, INSERT);
gcc_assert (!*dslot);
nielt = XNEW (struct int_tree_map);
nielt->uid = nuid;
@@ -825,22 +884,7 @@ separate_decls_in_region_name (tree name,
else
var_copy = ((struct int_tree_map *) *dslot)->to;
- if (copy_name_p)
- {
- copy = duplicate_ssa_name (name, NULL);
- nelt = XNEW (struct name_to_copy_elt);
- nelt->version = idx;
- nelt->new_name = copy;
- nelt->field = NULL_TREE;
- *slot = nelt;
- }
- else
- {
- gcc_assert (!slot);
- copy = name;
- }
-
- SSA_NAME_VAR (copy) = var_copy;
+ replace_ssa_name_symbol (copy, var_copy);
return copy;
}
@@ -853,7 +897,8 @@ separate_decls_in_region_name (tree name,
static void
separate_decls_in_region_stmt (edge entry, edge exit, gimple stmt,
- htab_t name_copies, htab_t decl_copies)
+ name_to_copy_table_type name_copies,
+ int_tree_htab_type decl_copies)
{
use_operand_p use;
def_operand_p def;
@@ -861,8 +906,6 @@ separate_decls_in_region_stmt (edge entry, edge exit, gimple stmt,
tree name, copy;
bool copy_name_p;
- mark_virtual_ops_for_renaming (stmt);
-
FOR_EACH_PHI_OR_STMT_DEF (def, stmt, oi, SSA_OP_DEF)
{
name = DEF_FROM_PTR (def);
@@ -893,15 +936,17 @@ separate_decls_in_region_stmt (edge entry, edge exit, gimple stmt,
replacement decls are stored in DECL_COPIES. */
static bool
-separate_decls_in_region_debug (gimple stmt, htab_t name_copies,
- htab_t decl_copies)
+separate_decls_in_region_debug (gimple stmt,
+ name_to_copy_table_type name_copies,
+ int_tree_htab_type decl_copies)
{
use_operand_p use;
ssa_op_iter oi;
tree var, name;
struct int_tree_map ielt;
struct name_to_copy_elt elt;
- void **slot, **dslot;
+ name_to_copy_elt **slot;
+ int_tree_map **dslot;
if (gimple_debug_bind_p (stmt))
var = gimple_debug_bind_get_var (stmt);
@@ -913,7 +958,7 @@ separate_decls_in_region_debug (gimple stmt, htab_t name_copies,
return true;
gcc_assert (DECL_P (var) && SSA_VAR_P (var));
ielt.uid = DECL_UID (var);
- dslot = htab_find_slot_with_hash (decl_copies, &ielt, ielt.uid, NO_INSERT);
+ dslot = decl_copies.find_slot_with_hash (&ielt, ielt.uid, NO_INSERT);
if (!dslot)
return true;
if (gimple_debug_bind_p (stmt))
@@ -928,7 +973,7 @@ separate_decls_in_region_debug (gimple stmt, htab_t name_copies,
continue;
elt.version = SSA_NAME_VERSION (name);
- slot = htab_find_slot_with_hash (name_copies, &elt, elt.version, NO_INSERT);
+ slot = name_copies.find_slot_with_hash (&elt, elt.version, NO_INSERT);
if (!slot)
{
gimple_debug_bind_reset_value (stmt);
@@ -936,7 +981,7 @@ separate_decls_in_region_debug (gimple stmt, htab_t name_copies,
break;
}
- SET_USE (use, ((struct name_to_copy_elt *) *slot)->new_name);
+ SET_USE (use, (*slot)->new_name);
}
return false;
@@ -945,15 +990,14 @@ separate_decls_in_region_debug (gimple stmt, htab_t name_copies,
/* Callback for htab_traverse. Adds a field corresponding to the reduction
specified in SLOT. The type is passed in DATA. */
-static int
-add_field_for_reduction (void **slot, void *data)
+int
+add_field_for_reduction (reduction_info **slot, tree type)
{
- struct reduction_info *const red = (struct reduction_info *) *slot;
- tree const type = (tree) data;
- tree var = SSA_NAME_VAR (gimple_assign_lhs (red->reduc_stmt));
- tree field = build_decl (gimple_location (red->reduc_stmt),
- FIELD_DECL, DECL_NAME (var), TREE_TYPE (var));
+ struct reduction_info *const red = *slot;
+ tree var = gimple_assign_lhs (red->reduc_stmt);
+ tree field = build_decl (gimple_location (red->reduc_stmt), FIELD_DECL,
+ SSA_NAME_IDENTIFIER (var), TREE_TYPE (var));
insert_field_into_struct (type, field);
@@ -965,15 +1009,14 @@ add_field_for_reduction (void **slot, void *data)
/* Callback for htab_traverse. Adds a field corresponding to a ssa name
described in SLOT. The type is passed in DATA. */
-static int
-add_field_for_name (void **slot, void *data)
+int
+add_field_for_name (name_to_copy_elt **slot, tree type)
{
- struct name_to_copy_elt *const elt = (struct name_to_copy_elt *) *slot;
- tree type = (tree) data;
+ struct name_to_copy_elt *const elt = *slot;
tree name = ssa_name (elt->version);
- tree var = SSA_NAME_VAR (name);
- tree field = build_decl (DECL_SOURCE_LOCATION (var),
- FIELD_DECL, DECL_NAME (var), TREE_TYPE (var));
+ tree field = build_decl (UNKNOWN_LOCATION,
+ FIELD_DECL, SSA_NAME_IDENTIFIER (name),
+ TREE_TYPE (name));
insert_field_into_struct (type, field);
elt->field = field;
@@ -988,11 +1031,10 @@ add_field_for_name (void **slot, void *data)
The phi's result will be stored in NEW_PHI field of the
reduction's data structure. */
-static int
-create_phi_for_local_result (void **slot, void *data)
+int
+create_phi_for_local_result (reduction_info **slot, struct loop *loop)
{
- struct reduction_info *const reduc = (struct reduction_info *) *slot;
- const struct loop *const loop = (const struct loop *) data;
+ struct reduction_info *const reduc = *slot;
edge e;
gimple new_phi;
basic_block store_bb;
@@ -1013,12 +1055,9 @@ create_phi_for_local_result (void **slot, void *data)
e = EDGE_PRED (store_bb, 1);
else
e = EDGE_PRED (store_bb, 0);
- local_res
- = make_ssa_name (SSA_NAME_VAR (gimple_assign_lhs (reduc->reduc_stmt)),
- NULL);
+ local_res = copy_ssa_name (gimple_assign_lhs (reduc->reduc_stmt), NULL);
locus = gimple_location (reduc->reduc_stmt);
new_phi = create_phi_node (local_res, store_bb);
- SSA_NAME_DEF_STMT (local_res) = new_phi;
add_phi_arg (new_phi, reduc->init, e, locus);
add_phi_arg (new_phi, gimple_assign_lhs (reduc->reduc_stmt),
FALLTHRU_EDGE (loop->latch), locus);
@@ -1041,11 +1080,10 @@ struct clsn_data
DATA annotates the place in memory the atomic operation relates to,
and the basic block it needs to be generated in. */
-static int
-create_call_for_reduction_1 (void **slot, void *data)
+int
+create_call_for_reduction_1 (reduction_info **slot, struct clsn_data *clsn_data)
{
- struct reduction_info *const reduc = (struct reduction_info *) *slot;
- struct clsn_data *const clsn_data = (struct clsn_data *) data;
+ struct reduction_info *const reduc = *slot;
gimple_stmt_iterator gsi;
tree type = TREE_TYPE (PHI_RESULT (reduc->reduc_phi));
tree load_struct;
@@ -1068,7 +1106,6 @@ create_call_for_reduction_1 (void **slot, void *data)
new_bb = e->dest;
tmp_load = create_tmp_var (TREE_TYPE (TREE_TYPE (addr)), NULL);
- add_referenced_var (tmp_load);
tmp_load = make_ssa_name (tmp_load, NULL);
load = gimple_build_omp_atomic_load (tmp_load, addr);
SSA_NAME_DEF_STMT (tmp_load) = load;
@@ -1095,23 +1132,24 @@ create_call_for_reduction_1 (void **slot, void *data)
LD_ST_DATA describes the shared data structure where
shared data is stored in and loaded from. */
static void
-create_call_for_reduction (struct loop *loop, htab_t reduction_list,
+create_call_for_reduction (struct loop *loop,
+ reduction_info_table_type reduction_list,
struct clsn_data *ld_st_data)
{
- htab_traverse (reduction_list, create_phi_for_local_result, loop);
+ reduction_list.traverse <struct loop *, create_phi_for_local_result> (loop);
/* Find the fallthru edge from GIMPLE_OMP_CONTINUE. */
ld_st_data->load_bb = FALLTHRU_EDGE (loop->latch)->dest;
- htab_traverse (reduction_list, create_call_for_reduction_1, ld_st_data);
+ reduction_list
+ .traverse <struct clsn_data *, create_call_for_reduction_1> (ld_st_data);
}
/* Callback for htab_traverse. Loads the final reduction value at the
join point of all threads, and inserts it in the right place. */
-static int
-create_loads_for_reductions (void **slot, void *data)
+int
+create_loads_for_reductions (reduction_info **slot, struct clsn_data *clsn_data)
{
- struct reduction_info *const red = (struct reduction_info *) *slot;
- struct clsn_data *const clsn_data = (struct clsn_data *) data;
+ struct reduction_info *const red = *slot;
gimple stmt;
gimple_stmt_iterator gsi;
tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
@@ -1127,7 +1165,6 @@ create_loads_for_reductions (void **slot, void *data)
x = load_struct;
name = PHI_RESULT (red->keep_res);
stmt = gimple_build_assign (name, x);
- SSA_NAME_DEF_STMT (name) = stmt;
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
@@ -1145,7 +1182,7 @@ create_loads_for_reductions (void **slot, void *data)
REDUCTION_LIST describes the list of reductions that the
loads should be generated for. */
static void
-create_final_loads_for_reduction (htab_t reduction_list,
+create_final_loads_for_reduction (reduction_info_table_type reduction_list,
struct clsn_data *ld_st_data)
{
gimple_stmt_iterator gsi;
@@ -1157,9 +1194,9 @@ create_final_loads_for_reduction (htab_t reduction_list,
stmt = gimple_build_assign (ld_st_data->load, t);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
- SSA_NAME_DEF_STMT (ld_st_data->load) = stmt;
- htab_traverse (reduction_list, create_loads_for_reductions, ld_st_data);
+ reduction_list
+ .traverse <struct clsn_data *, create_loads_for_reductions> (ld_st_data);
}
@@ -1169,11 +1206,10 @@ create_final_loads_for_reduction (htab_t reduction_list,
The reduction is specified in SLOT. The store information is
passed in DATA. */
-static int
-create_stores_for_reduction (void **slot, void *data)
+int
+create_stores_for_reduction (reduction_info **slot, struct clsn_data *clsn_data)
{
- struct reduction_info *const red = (struct reduction_info *) *slot;
- struct clsn_data *const clsn_data = (struct clsn_data *) data;
+ struct reduction_info *const red = *slot;
tree t;
gimple stmt;
gimple_stmt_iterator gsi;
@@ -1182,7 +1218,6 @@ create_stores_for_reduction (void **slot, void *data)
gsi = gsi_last_bb (clsn_data->store_bb);
t = build3 (COMPONENT_REF, type, clsn_data->store, red->field, NULL_TREE);
stmt = gimple_build_assign (t, red->initial_value);
- mark_virtual_ops_for_renaming (stmt);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
return 1;
@@ -1192,11 +1227,11 @@ create_stores_for_reduction (void **slot, void *data)
store to a field of STORE in STORE_BB for the ssa name and its duplicate
specified in SLOT. */
-static int
-create_loads_and_stores_for_name (void **slot, void *data)
+int
+create_loads_and_stores_for_name (name_to_copy_elt **slot,
+ struct clsn_data *clsn_data)
{
- struct name_to_copy_elt *const elt = (struct name_to_copy_elt *) *slot;
- struct clsn_data *const clsn_data = (struct clsn_data *) data;
+ struct name_to_copy_elt *const elt = *slot;
tree t;
gimple stmt;
gimple_stmt_iterator gsi;
@@ -1206,14 +1241,12 @@ create_loads_and_stores_for_name (void **slot, void *data)
gsi = gsi_last_bb (clsn_data->store_bb);
t = build3 (COMPONENT_REF, type, clsn_data->store, elt->field, NULL_TREE);
stmt = gimple_build_assign (t, ssa_name (elt->version));
- mark_virtual_ops_for_renaming (stmt);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
gsi = gsi_last_bb (clsn_data->load_bb);
load_struct = build_simple_mem_ref (clsn_data->load);
t = build3 (COMPONENT_REF, type, load_struct, elt->field, NULL_TREE);
stmt = gimple_build_assign (elt->new_name, t);
- SSA_NAME_DEF_STMT (elt->new_name) = stmt;
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
return 1;
@@ -1254,22 +1287,23 @@ create_loads_and_stores_for_name (void **slot, void *data)
in LOOP. */
static void
-separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
+separate_decls_in_region (edge entry, edge exit,
+ reduction_info_table_type reduction_list,
tree *arg_struct, tree *new_arg_struct,
struct clsn_data *ld_st_data)
{
basic_block bb1 = split_edge (entry);
basic_block bb0 = single_pred (bb1);
- htab_t name_copies = htab_create (10, name_to_copy_elt_hash,
- name_to_copy_elt_eq, free);
- htab_t decl_copies = htab_create (10, int_tree_map_hash, int_tree_map_eq,
- free);
+ name_to_copy_table_type name_copies;
+ name_copies.create (10);
+ int_tree_htab_type decl_copies;
+ decl_copies.create (10);
unsigned i;
tree type, type_name, nvar;
gimple_stmt_iterator gsi;
struct clsn_data clsn_data;
- VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
+ auto_vec<basic_block, 3> body;
basic_block bb;
basic_block entry_bb = bb1;
basic_block exit_bb = exit->dest;
@@ -1278,7 +1312,7 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
entry = single_succ_edge (entry_bb);
gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
- FOR_EACH_VEC_ELT (basic_block, body, i, bb)
+ FOR_EACH_VEC_ELT (body, i, bb)
{
if (bb != entry_bb && bb != exit_bb)
{
@@ -1306,7 +1340,7 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
and discard those for which we know there's nothing we can
do. */
if (has_debug_stmt)
- FOR_EACH_VEC_ELT (basic_block, body, i, bb)
+ FOR_EACH_VEC_ELT (body, i, bb)
if (bb != entry_bb && bb != exit_bb)
{
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
@@ -1327,9 +1361,7 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
}
}
- VEC_free (basic_block, heap, body);
-
- if (htab_elements (name_copies) == 0 && htab_elements (reduction_list) == 0)
+ if (name_copies.elements () == 0 && reduction_list.elements () == 0)
{
/* It may happen that there is nothing to copy (if there are only
loop carried and external variables in the loop). */
@@ -1345,20 +1377,17 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
type);
TYPE_NAME (type) = type_name;
- htab_traverse (name_copies, add_field_for_name, type);
- if (reduction_list && htab_elements (reduction_list) > 0)
+ name_copies.traverse <tree, add_field_for_name> (type);
+ if (reduction_list.is_created () && reduction_list.elements () > 0)
{
/* Create the fields for reductions. */
- htab_traverse (reduction_list, add_field_for_reduction,
- type);
+ reduction_list.traverse <tree, add_field_for_reduction> (type);
}
layout_type (type);
/* Create the loads and stores. */
*arg_struct = create_tmp_var (type, ".paral_data_store");
- add_referenced_var (*arg_struct);
nvar = create_tmp_var (build_pointer_type (type), ".paral_data_load");
- add_referenced_var (nvar);
*new_arg_struct = make_ssa_name (nvar, NULL);
ld_st_data->store = *arg_struct;
@@ -1366,15 +1395,17 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
ld_st_data->store_bb = bb0;
ld_st_data->load_bb = bb1;
- htab_traverse (name_copies, create_loads_and_stores_for_name,
- ld_st_data);
+ name_copies
+ .traverse <struct clsn_data *, create_loads_and_stores_for_name>
+ (ld_st_data);
/* Load the calculation from memory (after the join of the threads). */
- if (reduction_list && htab_elements (reduction_list) > 0)
+ if (reduction_list.is_created () && reduction_list.elements () > 0)
{
- htab_traverse (reduction_list, create_stores_for_reduction,
- ld_st_data);
+ reduction_list
+ .traverse <struct clsn_data *, create_stores_for_reduction>
+ (ld_st_data);
clsn_data.load = make_ssa_name (nvar, NULL);
clsn_data.load_bb = exit->dest;
clsn_data.store = ld_st_data->store;
@@ -1382,8 +1413,8 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
}
}
- htab_delete (decl_copies);
- htab_delete (name_copies);
+ decl_copies.dispose ();
+ name_copies.dispose ();
}
/* Bitmap containing uids of functions created by parallelization. We cannot
@@ -1394,7 +1425,7 @@ static GTY(()) bitmap parallelized_functions;
/* Returns true if FN was created by create_loop_fn. */
-static bool
+bool
parallelized_function_p (tree fn)
{
if (!parallelized_functions || !DECL_ARTIFICIAL (fn))
@@ -1415,6 +1446,7 @@ create_loop_fn (location_t loc)
struct function *act_cfun = cfun;
static unsigned loopfn_num;
+ loc = LOCATION_LOCUS (loc);
snprintf (buf, 100, "%s.$loopfn", current_function_name ());
ASM_FORMAT_PRIVATE_NAME (tname, buf, loopfn_num++);
clean_symbol_name (tname);
@@ -1471,7 +1503,9 @@ create_loop_fn (location_t loc)
REDUCTION_LIST describes the reductions in LOOP. */
static void
-transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit)
+transform_to_exit_first_loop (struct loop *loop,
+ reduction_info_table_type reduction_list,
+ tree nit)
{
basic_block *bbs, *nbbs, ex_bb, orig_header;
unsigned n;
@@ -1481,8 +1515,6 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
gimple phi, nphi, cond_stmt, stmt, cond_nit;
gimple_stmt_iterator gsi;
tree nit_1;
- edge exit_1;
- tree new_rhs;
split_block_after_labels (loop->header);
orig_header = single_succ (loop->header);
@@ -1498,10 +1530,9 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
{
phi = gsi_stmt (gsi);
res = PHI_RESULT (phi);
- t = make_ssa_name (SSA_NAME_VAR (res), phi);
+ t = copy_ssa_name (res, phi);
SET_PHI_RESULT (phi, t);
nphi = create_phi_node (res, orig_header);
- SSA_NAME_DEF_STMT (res) = nphi;
add_phi_arg (nphi, t, hpred, UNKNOWN_LOCATION);
if (res == control)
@@ -1512,41 +1543,10 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
}
}
- /* Setting the condition towards peeling the last iteration:
- If the block consisting of the exit condition has the latch as
- successor, then the body of the loop is executed before
- the exit condition is tested. In such case, moving the
- condition to the entry, causes that the loop will iterate
- one less iteration (which is the wanted outcome, since we
- peel out the last iteration). If the body is executed after
- the condition, moving the condition to the entry requires
- decrementing one iteration. */
- exit_1 = EDGE_SUCC (exit->src, EDGE_SUCC (exit->src, 0) == exit);
- if (exit_1->dest == loop->latch)
- new_rhs = gimple_cond_rhs (cond_stmt);
- else
- {
- new_rhs = fold_build2 (MINUS_EXPR, TREE_TYPE (gimple_cond_rhs (cond_stmt)),
- gimple_cond_rhs (cond_stmt),
- build_int_cst (TREE_TYPE (gimple_cond_rhs (cond_stmt)), 1));
- if (TREE_CODE (gimple_cond_rhs (cond_stmt)) == SSA_NAME)
- {
- basic_block preheader;
- gimple_stmt_iterator gsi1;
-
- preheader = loop_preheader_edge(loop)->src;
- gsi1 = gsi_after_labels (preheader);
- new_rhs = force_gimple_operand_gsi (&gsi1, new_rhs, true,
- NULL_TREE,false,GSI_CONTINUE_LINKING);
- }
- }
- gimple_cond_set_rhs (cond_stmt, unshare_expr (new_rhs));
- gimple_cond_set_lhs (cond_stmt, unshare_expr (gimple_cond_lhs (cond_stmt)));
-
bbs = get_loop_body_in_dom_order (loop);
- for (n = 0; bbs[n] != loop->latch; n++)
- continue;
+ for (n = 0; bbs[n] != exit->src; n++)
+ continue;
nbbs = XNEWVEC (basic_block, n);
ok = gimple_duplicate_sese_tail (single_succ_edge (loop->header), exit,
bbs + 1, n, nbbs);
@@ -1557,13 +1557,13 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
/* Other than reductions, the only gimple reg that should be copied
out of the loop is the control variable. */
-
+ exit = single_dom_exit (loop);
control_name = NULL_TREE;
for (gsi = gsi_start_phis (ex_bb); !gsi_end_p (gsi); )
{
phi = gsi_stmt (gsi);
res = PHI_RESULT (phi);
- if (!is_gimple_reg (res))
+ if (virtual_operand_p (res))
{
gsi_next (&gsi);
continue;
@@ -1574,9 +1574,7 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
PHI_RESULT of this phi is the resulting value of the reduction
variable when exiting the loop. */
- exit = single_dom_exit (loop);
-
- if (htab_elements (reduction_list) > 0)
+ if (reduction_list.elements () > 0)
{
struct reduction_info *red;
@@ -1606,7 +1604,6 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
false, NULL_TREE, false, GSI_SAME_STMT);
stmt = gimple_build_assign (control_name, nit_1);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
- SSA_NAME_DEF_STMT (control_name) = stmt;
}
/* Create the parallel constructs for LOOP as described in gen_parallel_loop.
@@ -1647,12 +1644,10 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
param = make_ssa_name (DECL_ARGUMENTS (loop_fn), NULL);
stmt = gimple_build_assign (param, build_fold_addr_expr (data));
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- SSA_NAME_DEF_STMT (param) = stmt;
stmt = gimple_build_assign (new_data,
fold_convert (TREE_TYPE (new_data), param));
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- SSA_NAME_DEF_STMT (new_data) = stmt;
}
/* Emit GIMPLE_OMP_RETURN for GIMPLE_OMP_PARALLEL. */
@@ -1670,7 +1665,7 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
cvar_base = SSA_NAME_VAR (cvar);
phi = SSA_NAME_DEF_STMT (cvar);
cvar_init = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
- initvar = make_ssa_name (cvar_base, NULL);
+ initvar = copy_ssa_name (cvar, NULL);
SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, loop_preheader_edge (loop)),
initvar);
cvar_next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
@@ -1713,7 +1708,7 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
t = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
OMP_CLAUSE_SCHEDULE_KIND (t) = OMP_CLAUSE_SCHEDULE_STATIC;
- for_stmt = gimple_build_omp_for (NULL, t, 1, NULL);
+ for_stmt = gimple_build_omp_for (NULL, GF_OMP_FOR_KIND_FOR, t, 1, NULL);
gimple_set_location (for_stmt, loc);
gimple_omp_for_set_index (for_stmt, 0, initvar);
gimple_omp_for_set_initial (for_stmt, 0, cvar_init);
@@ -1740,6 +1735,10 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
gimple_set_location (stmt, loc);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+ /* After the above dom info is hosed. Re-compute it. */
+ free_dominance_info (CDI_DOMINATORS);
+ calculate_dominance_info (CDI_DOMINATORS);
+
return paral_bb;
}
@@ -1750,10 +1749,9 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
REDUCTION_LIST describes the reductions existent in the LOOP. */
static void
-gen_parallel_loop (struct loop *loop, htab_t reduction_list,
+gen_parallel_loop (struct loop *loop, reduction_info_table_type reduction_list,
unsigned n_threads, struct tree_niter_desc *niter)
{
- loop_iterator li;
tree many_iterations_cond, type, nit;
tree arg_struct, new_arg_struct;
gimple_seq stmts;
@@ -1763,6 +1761,7 @@ gen_parallel_loop (struct loop *loop, htab_t reduction_list,
unsigned prob;
location_t loc;
gimple cond_stmt;
+ unsigned int m_p_thread=2;
/* From
@@ -1817,15 +1816,31 @@ gen_parallel_loop (struct loop *loop, htab_t reduction_list,
loop that will be split to loop_fn, the new one will be used for the
remaining iterations. */
+ /* We should compute a better number-of-iterations value for outer loops.
+ That is, if we have
+
+ for (i = 0; i < n; ++i)
+ for (j = 0; j < m; ++j)
+ ...
+
+ we should compute nit = n * m, not nit = n.
+ Also may_be_zero handling would need to be adjusted. */
+
type = TREE_TYPE (niter->niter);
nit = force_gimple_operand (unshare_expr (niter->niter), &stmts, true,
NULL_TREE);
if (stmts)
gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
- many_iterations_cond =
- fold_build2 (GE_EXPR, boolean_type_node,
- nit, build_int_cst (type, MIN_PER_THREAD * n_threads));
+ if (loop->inner)
+ m_p_thread=2;
+ else
+ m_p_thread=MIN_PER_THREAD;
+
+ many_iterations_cond =
+ fold_build2 (GE_EXPR, boolean_type_node,
+ nit, build_int_cst (type, m_p_thread * n_threads));
+
many_iterations_cond
= fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
invert_truthvalue (unshare_expr (niter->may_be_zero)),
@@ -1859,8 +1874,8 @@ gen_parallel_loop (struct loop *loop, htab_t reduction_list,
transform_to_exit_first_loop (loop, reduction_list, nit);
/* Generate initializations for reductions. */
- if (htab_elements (reduction_list) > 0)
- htab_traverse (reduction_list, initialize_reductions, loop);
+ if (reduction_list.elements () > 0)
+ reduction_list.traverse <struct loop *, initialize_reductions> (loop);
/* Eliminate the references to local variables from the loop. */
gcc_assert (single_exit (loop));
@@ -1880,7 +1895,7 @@ gen_parallel_loop (struct loop *loop, htab_t reduction_list,
loc = gimple_location (cond_stmt);
parallel_head = create_parallel_loop (loop, create_loop_fn (loc), arg_struct,
new_arg_struct, n_threads, loc);
- if (htab_elements (reduction_list) > 0)
+ if (reduction_list.elements () > 0)
create_call_for_reduction (loop, reduction_list, &clsn_data);
scev_reset ();
@@ -1891,7 +1906,7 @@ gen_parallel_loop (struct loop *loop, htab_t reduction_list,
/* Free loop bound estimations that could contain references to
removed statements. */
- FOR_EACH_LOOP (li, loop, 0)
+ FOR_EACH_LOOP (loop, 0)
free_numbers_of_iterations_estimates_loop (loop);
/* Expand the parallel constructs. We do it directly here instead of running
@@ -1927,9 +1942,10 @@ loop_has_vector_phi_nodes (struct loop *loop ATTRIBUTE_UNUSED)
and PHI, insert it to the REDUCTION_LIST. */
static void
-build_new_reduction (htab_t reduction_list, gimple reduc_stmt, gimple phi)
+build_new_reduction (reduction_info_table_type reduction_list,
+ gimple reduc_stmt, gimple phi)
{
- PTR *slot;
+ reduction_info **slot;
struct reduction_info *new_reduction;
gcc_assert (reduc_stmt);
@@ -1948,16 +1964,16 @@ build_new_reduction (htab_t reduction_list, gimple reduc_stmt, gimple phi)
new_reduction->reduc_phi = phi;
new_reduction->reduc_version = SSA_NAME_VERSION (gimple_phi_result (phi));
new_reduction->reduction_code = gimple_assign_rhs_code (reduc_stmt);
- slot = htab_find_slot (reduction_list, new_reduction, INSERT);
+ slot = reduction_list.find_slot (new_reduction, INSERT);
*slot = new_reduction;
}
/* Callback for htab_traverse. Sets gimple_uid of reduc_phi stmts. */
-static int
-set_reduc_phi_uids (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+set_reduc_phi_uids (reduction_info **slot, void *data ATTRIBUTE_UNUSED)
{
- struct reduction_info *const red = (struct reduction_info *) *slot;
+ struct reduction_info *const red = *slot;
gimple_set_uid (red->reduc_phi, red->reduc_version);
return 1;
}
@@ -1965,12 +1981,11 @@ set_reduc_phi_uids (void **slot, void *data ATTRIBUTE_UNUSED)
/* Detect all reductions in the LOOP, insert them into REDUCTION_LIST. */
static void
-gather_scalar_reductions (loop_p loop, htab_t reduction_list)
+gather_scalar_reductions (loop_p loop, reduction_info_table_type reduction_list)
{
gimple_stmt_iterator gsi;
loop_vec_info simple_loop_info;
- vect_dump = NULL;
simple_loop_info = vect_analyze_loop_form (loop);
for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -1980,7 +1995,7 @@ gather_scalar_reductions (loop_p loop, htab_t reduction_list)
tree res = PHI_RESULT (phi);
bool double_reduc;
- if (!is_gimple_reg (res))
+ if (virtual_operand_p (res))
continue;
if (!simple_iv (loop, loop, res, &iv, true)
@@ -1998,7 +2013,7 @@ gather_scalar_reductions (loop_p loop, htab_t reduction_list)
/* As gimple_uid is used by the vectorizer in between vect_analyze_loop_form
and destroy_loop_vec_info, we can set gimple_uid of reduc_phi stmts
only now. */
- htab_traverse (reduction_list, set_reduc_phi_uids, NULL);
+ reduction_list.traverse <void *, set_reduc_phi_uids> (NULL);
}
/* Try to initialize NITER for code generation part. */
@@ -2027,7 +2042,8 @@ try_get_loop_niter (loop_p loop, struct tree_niter_desc *niter)
REDUCTION_LIST describes the reductions. */
static bool
-try_create_reduction_list (loop_p loop, htab_t reduction_list)
+try_create_reduction_list (loop_p loop,
+ reduction_info_table_type reduction_list)
{
edge exit = single_dom_exit (loop);
gimple_stmt_iterator gsi;
@@ -2046,7 +2062,7 @@ try_create_reduction_list (loop_p loop, htab_t reduction_list)
gimple reduc_phi;
tree val = PHI_ARG_DEF_FROM_EDGE (phi, exit);
- if (is_gimple_reg (val))
+ if (!virtual_operand_p (val))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -2058,7 +2074,7 @@ try_create_reduction_list (loop_p loop, htab_t reduction_list)
fprintf (dump_file,
" checking if it a part of reduction pattern: \n");
}
- if (htab_elements (reduction_list) == 0)
+ if (reduction_list.elements () == 0)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
@@ -2101,7 +2117,7 @@ try_create_reduction_list (loop_p loop, htab_t reduction_list)
tree def = PHI_RESULT (phi);
affine_iv iv;
- if (is_gimple_reg (def) && !simple_iv (loop, loop, def, &iv, true))
+ if (!virtual_operand_p (def) && !simple_iv (loop, loop, def, &iv, true))
{
struct reduction_info *red;
@@ -2131,11 +2147,10 @@ parallelize_loops (void)
bool changed = false;
struct loop *loop;
struct tree_niter_desc niter_desc;
- loop_iterator li;
- htab_t reduction_list;
+ reduction_info_table_type reduction_list;
struct obstack parloop_obstack;
HOST_WIDE_INT estimated;
- LOC loop_loc;
+ source_location loop_loc;
/* Do not parallelize loops in the functions created by parallelization. */
if (parallelized_function_p (cfun->decl))
@@ -2144,13 +2159,12 @@ parallelize_loops (void)
return false;
gcc_obstack_init (&parloop_obstack);
- reduction_list = htab_create (10, reduction_info_hash,
- reduction_info_eq, free);
+ reduction_list.create (10);
init_stmt_vec_info_vec ();
- FOR_EACH_LOOP (li, loop, 0)
+ FOR_EACH_LOOP (loop, 0)
{
- htab_empty (reduction_list);
+ reduction_list.empty ();
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Trying loop %d as candidate\n",loop->num);
@@ -2183,17 +2197,17 @@ parallelize_loops (void)
|| loop_has_blocks_with_irreducible_flag (loop)
|| (loop_preheader_edge (loop)->src->flags & BB_IRREDUCIBLE_LOOP)
/* FIXME: the check for vector phi nodes could be removed. */
- || loop_has_vector_phi_nodes (loop)
- /* FIXME: transform_to_exit_first_loop does not handle not
- header-copied loops correctly - see PR46886. */
- || !do_while_loop_p (loop))
+ || loop_has_vector_phi_nodes (loop))
continue;
- estimated = max_stmt_executions_int (loop, false);
+
+ estimated = estimated_stmt_executions_int (loop);
+ if (estimated == -1)
+ estimated = max_stmt_executions_int (loop);
/* FIXME: Bypass this check as graphite doesn't update the
- count and frequency correctly now. */
+ count and frequency correctly now. */
if (!flag_loop_parallelize_all
- && ((estimated !=-1
- && estimated <= (HOST_WIDE_INT) n_threads * MIN_PER_THREAD)
+ && ((estimated != -1
+ && estimated <= (HOST_WIDE_INT) n_threads * MIN_PER_THREAD)
/* Do not bother with loops in cold areas. */
|| optimize_loop_nest_for_size_p (loop)))
continue;
@@ -2216,20 +2230,16 @@ parallelize_loops (void)
else
fprintf (dump_file, "parallelizing inner loop %d\n",loop->header->index);
loop_loc = find_loop_location (loop);
- if (loop_loc != UNKNOWN_LOC)
+ if (loop_loc != UNKNOWN_LOCATION)
fprintf (dump_file, "\nloop at %s:%d: ",
- LOC_FILE (loop_loc), LOC_LINE (loop_loc));
+ LOCATION_FILE (loop_loc), LOCATION_LINE (loop_loc));
}
gen_parallel_loop (loop, reduction_list,
n_threads, &niter_desc);
- verify_flow_info ();
- verify_dominators (CDI_DOMINATORS);
- verify_loop_structure ();
- verify_loop_closed_ssa (true);
}
free_stmt_vec_info_vec ();
- htab_delete (reduction_list);
+ reduction_list.dispose ();
obstack_free (&parloop_obstack, NULL);
/* Parallelization will cause new function calls to be inserted through
@@ -2241,4 +2251,62 @@ parallelize_loops (void)
return changed;
}
+/* Parallelization. */
+
+static bool
+gate_tree_parallelize_loops (void)
+{
+ return flag_tree_parallelize_loops > 1;
+}
+
+static unsigned
+tree_parallelize_loops (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ if (parallelize_loops ())
+ return TODO_cleanup_cfg | TODO_rebuild_alias;
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_parallelize_loops =
+{
+ GIMPLE_PASS, /* type */
+ "parloops", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_PARALLELIZE_LOOPS, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_flow, /* todo_flags_finish */
+};
+
+class pass_parallelize_loops : public gimple_opt_pass
+{
+public:
+ pass_parallelize_loops (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_parallelize_loops, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_parallelize_loops (); }
+ unsigned int execute () { return tree_parallelize_loops (); }
+
+}; // class pass_parallelize_loops
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_parallelize_loops (gcc::context *ctxt)
+{
+ return new pass_parallelize_loops (ctxt);
+}
+
+
#include "gt-tree-parloops.h"