#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
#include "tree-flow.h"
#include "cfgloop.h"
-#include "ggc.h"
#include "tree-data-ref.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
#include "tree-pass.h"
#include "tree-scalar-evolution.h"
#include "hashtab.h"
/*
Reduction handling:
- currently we use vect_is_simple_reduction() to detect reduction patterns.
+ currently we use vect_force_simple_reduction() to detect reduction patterns.
The code transformation will be introduced by an example.
in parallel). */
static bool
-loop_parallel_p (struct loop *loop)
+loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
{
VEC (ddr_p, heap) * dependence_relations;
VEC (data_reference_p, heap) *datarefs;
if (dump_file && (dump_flags & TDF_DETAILS))
dump_data_dependence_relations (dump_file, dependence_relations);
- trans = lambda_trans_matrix_new (1, 1);
+ trans = lambda_trans_matrix_new (1, 1, parloop_obstack);
LTM_MATRIX (trans)[0][0] = -1;
if (lambda_transform_legal_p (trans, 1, dependence_relations))
/* Assigns the address of OBJ in TYPE to an ssa name, and returns this name.
The assignment statement is placed on edge ENTRY. DECL_ADDRESS maps decls
to their addresses that can be reused. The address of OBJ is known to
- be invariant in the whole function. */
+ be invariant in the whole function. Other needed statements are placed
+ right before GSI. */
static tree
-take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
+take_address_of (tree obj, tree type, edge entry, htab_t decl_address,
+ gimple_stmt_iterator *gsi)
{
int uid;
void **dslot;
handled_component_p (*var_p);
var_p = &TREE_OPERAND (*var_p, 0))
continue;
- uid = DECL_UID (*var_p);
+ /* Canonicalize the access to base on a MEM_REF. */
+ if (DECL_P (*var_p))
+ *var_p = build_simple_mem_ref (build_fold_addr_expr (*var_p));
+
+ /* Assign a canonical SSA name to the address of the base decl used
+ in the address and share it for all accesses and addresses based
+ 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);
if (!*dslot)
{
- addr = build_addr (*var_p, current_function_decl);
- bvar = create_tmp_var (TREE_TYPE (addr), get_name (*var_p));
+ 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);
else
name = ((struct int_tree_map *) *dslot)->to;
- if (var_p != &obj)
- {
- *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
- name = force_gimple_operand (build_addr (obj, current_function_decl),
- &stmts, true, NULL_TREE);
- if (!gimple_seq_empty_p (stmts))
- gsi_insert_seq_on_edge_immediate (entry, stmts);
- }
+ /* Express the address in terms of the canonical SSA name. */
+ TREE_OPERAND (*var_p, 0) = name;
+ if (gsi == NULL)
+ return build_fold_addr_expr_with_type (obj, type);
- if (TREE_TYPE (name) != type)
+ name = force_gimple_operand (build_addr (obj, current_function_decl),
+ &stmts, true, NULL_TREE);
+ if (!gimple_seq_empty_p (stmts))
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+
+ if (!useless_type_conversion_p (type, TREE_TYPE (name)))
{
name = force_gimple_operand (fold_convert (type, name), &stmts, true,
NULL_TREE);
if (!gimple_seq_empty_p (stmts))
- gsi_insert_seq_on_edge_immediate (entry, stmts);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
}
return name;
struct walk_stmt_info info;
edge entry;
htab_t decl_address;
+ gimple_stmt_iterator *gsi;
bool changed;
+ bool reset;
};
/* Eliminates references to local variables in *TP out of the single
type = TREE_TYPE (t);
addr_type = build_pointer_type (type);
- addr = take_address_of (t, addr_type, dta->entry, dta->decl_address);
- *tp = build1 (INDIRECT_REF, TREE_TYPE (*tp), addr);
+ addr = take_address_of (t, addr_type, dta->entry, dta->decl_address,
+ dta->gsi);
+ if (dta->gsi == NULL && addr == NULL_TREE)
+ {
+ dta->reset = true;
+ return NULL_TREE;
+ }
+
+ *tp = build_simple_mem_ref (addr);
dta->changed = true;
return NULL_TREE;
return NULL_TREE;
addr_type = TREE_TYPE (t);
- addr = take_address_of (obj, addr_type, dta->entry, dta->decl_address);
+ addr = take_address_of (obj, addr_type, dta->entry, dta->decl_address,
+ dta->gsi);
+ if (dta->gsi == NULL && addr == NULL_TREE)
+ {
+ dta->reset = true;
+ return NULL_TREE;
+ }
*tp = addr;
dta->changed = true;
return NULL_TREE;
}
-/* Moves the references to local variables in STMT out of the single
+/* Moves the references to local variables in STMT at *GSI out of the single
entry single exit region starting at ENTRY. DECL_ADDRESS contains
addresses of the references that had their address taken
already. */
static void
-eliminate_local_variables_stmt (edge entry, gimple stmt,
+eliminate_local_variables_stmt (edge entry, gimple_stmt_iterator *gsi,
htab_t decl_address)
{
struct elv_data dta;
+ gimple stmt = gsi_stmt (*gsi);
memset (&dta.info, '\0', sizeof (dta.info));
dta.entry = entry;
dta.decl_address = decl_address;
dta.changed = false;
+ dta.reset = false;
if (gimple_debug_bind_p (stmt))
- walk_tree (gimple_debug_bind_get_value_ptr (stmt),
- eliminate_local_variables_1, &dta.info, NULL);
+ {
+ dta.gsi = NULL;
+ walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+ eliminate_local_variables_1, &dta.info, NULL);
+ if (dta.reset)
+ {
+ gimple_debug_bind_reset_value (stmt);
+ dta.changed = true;
+ }
+ }
else
- walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
+ {
+ dta.gsi = gsi;
+ walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
+ }
if (dta.changed)
update_stmt (stmt);
VEC (basic_block, heap) *body = VEC_alloc (basic_block, heap, 3);
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);
basic_block entry_bb = entry->src;
gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
- for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+ FOR_EACH_VEC_ELT (basic_block, body, i, bb)
if (bb != entry_bb && bb != exit_bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- eliminate_local_variables_stmt (entry, gsi_stmt (gsi),
- decl_address);
+ if (gimple_debug_bind_p (gsi_stmt (gsi)))
+ has_debug_stmt = true;
+ else
+ eliminate_local_variables_stmt (entry, &gsi, decl_address);
+
+ if (has_debug_stmt)
+ FOR_EACH_VEC_ELT (basic_block, 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);
struct clsn_data *const clsn_data = (struct clsn_data *) data;
gimple_stmt_iterator gsi;
tree type = TREE_TYPE (PHI_RESULT (reduc->reduc_phi));
- tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
tree load_struct;
basic_block bb;
basic_block new_bb;
tree tmp_load, name;
gimple load;
- load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
+ load_struct = build_simple_mem_ref (clsn_data->load);
t = build3 (COMPONENT_REF, type, load_struct, reduc->field, NULL_TREE);
addr = build_addr (t, current_function_decl);
gimple stmt;
gimple_stmt_iterator gsi;
tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
- tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
tree load_struct;
tree name;
tree x;
gsi = gsi_after_labels (clsn_data->load_bb);
- load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
+ load_struct = build_simple_mem_ref (clsn_data->load);
load_struct = build3 (COMPONENT_REF, type, load_struct, red->field,
NULL_TREE);
gimple stmt;
gimple_stmt_iterator gsi;
tree type = TREE_TYPE (elt->new_name);
- tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
tree load_struct;
gsi = gsi_last_bb (clsn_data->store_bb);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
gsi = gsi_last_bb (clsn_data->load_bb);
- load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
+ 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;
entry = single_succ_edge (entry_bb);
gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
- for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+ FOR_EACH_VEC_ELT (basic_block, body, i, bb)
{
if (bb != entry_bb && bb != exit_bb)
{
and discard those for which we know there's nothing we can
do. */
if (has_debug_stmt)
- for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+ FOR_EACH_VEC_ELT (basic_block, body, i, bb)
if (bb != entry_bb && bb != exit_bb)
{
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
initvar);
cvar_next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
- gsi = gsi_last_bb (loop->latch);
+ gsi = gsi_last_nondebug_bb (loop->latch);
gcc_assert (gsi_stmt (gsi) == SSA_NAME_DEF_STMT (cvar_next));
gsi_remove (&gsi, true);
if (!simple_iv (loop, loop, res, &iv, true)
&& simple_loop_info)
{
- gimple reduc_stmt = vect_is_simple_reduction (simple_loop_info, phi, true, &double_reduc);
+ gimple reduc_stmt = vect_force_simple_reduction (simple_loop_info,
+ phi, true,
+ &double_reduc);
if (reduc_stmt && !double_reduc)
build_new_reduction (reduction_list, reduc_stmt, phi);
}
reduc_phi = NULL;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, val)
{
- if (flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
+ if (!gimple_debug_bind_p (USE_STMT (use_p))
+ && flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
{
reduc_phi = USE_STMT (use_p);
break;
struct tree_niter_desc niter_desc;
loop_iterator li;
htab_t reduction_list;
+ struct obstack parloop_obstack;
HOST_WIDE_INT estimated;
LOC loop_loc;
-
+
/* Do not parallelize loops in the functions created by parallelization. */
if (parallelized_function_p (cfun->decl))
return false;
if (cfun->has_nonlocal_label)
return false;
+ gcc_obstack_init (&parloop_obstack);
reduction_list = htab_create (10, reduction_info_hash,
reduction_info_eq, free);
init_stmt_vec_info_vec ();
if (!try_create_reduction_list (loop, reduction_list))
continue;
- if (!flag_loop_parallelize_all && !loop_parallel_p (loop))
+ if (!flag_loop_parallelize_all
+ && !loop_parallel_p (loop, &parloop_obstack))
continue;
changed = true;
free_stmt_vec_info_vec ();
htab_delete (reduction_list);
+ obstack_free (&parloop_obstack, NULL);
/* Parallelization will cause new function calls to be inserted through
- which local variables will escape. Reset the points-to solutions
- for ESCAPED and CALLUSED. */
+ which local variables will escape. Reset the points-to solution
+ for ESCAPED. */
if (changed)
- {
- pt_solution_reset (&cfun->gimple_df->escaped);
- pt_solution_reset (&cfun->gimple_df->callused);
- }
+ pt_solution_reset (&cfun->gimple_df->escaped);
return changed;
}