Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-parloops.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/tree-parloops.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/tree-parloops.c Tue Mar 22 17:18:12 2011 +0900 @@ -23,17 +23,12 @@ #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" -#include "tree.h" #include "tree-flow.h" #include "cfgloop.h" #include "tree-data-ref.h" -#include "diagnostic.h" -#include "tree-pretty-print.h" +#include "tree-scalar-evolution.h" #include "gimple-pretty-print.h" #include "tree-pass.h" -#include "tree-scalar-evolution.h" -#include "hashtab.h" #include "langhooks.h" #include "tree-vectorizer.h" @@ -169,6 +164,8 @@ gimple reduc_stmt; /* reduction statement. */ gimple reduc_phi; /* The phi node defining the reduction. */ enum tree_code reduction_code;/* code for the reduction operation. */ + unsigned reduc_version; /* SSA_NAME_VERSION of original reduc_phi + result. */ gimple keep_res; /* The PHI_RESULT of this phi is the resulting value of the reduction variable when existing the loop. */ tree initial_value; /* The initial value of the reduction var before entering the loop. */ @@ -196,7 +193,7 @@ { const struct reduction_info *a = (const struct reduction_info *) aa; - return htab_hash_pointer (a->reduc_phi); + return a->reduc_version; } static struct reduction_info * @@ -204,10 +201,11 @@ { struct reduction_info tmpred, *red; - if (htab_elements (reduction_list) == 0) + if (htab_elements (reduction_list) == 0 || phi == NULL) return NULL; tmpred.reduc_phi = phi; + tmpred.reduc_version = gimple_uid (phi); red = (struct reduction_info *) htab_find (reduction_list, &tmpred); return red; @@ -242,6 +240,125 @@ return (hashval_t) a->version; } +/* 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. */ +typedef struct lambda_trans_matrix_s +{ + lambda_matrix matrix; + int rowsize; + int colsize; + int denominator; +} *lambda_trans_matrix; +#define LTM_MATRIX(T) ((T)->matrix) +#define LTM_ROWSIZE(T) ((T)->rowsize) +#define LTM_COLSIZE(T) ((T)->colsize) +#define LTM_DENOMINATOR(T) ((T)->denominator) + +/* Allocate a new transformation matrix. */ + +static lambda_trans_matrix +lambda_trans_matrix_new (int colsize, int rowsize, + struct obstack * lambda_obstack) +{ + lambda_trans_matrix ret; + + ret = (lambda_trans_matrix) + obstack_alloc (lambda_obstack, sizeof (struct lambda_trans_matrix_s)); + LTM_MATRIX (ret) = lambda_matrix_new (rowsize, colsize, lambda_obstack); + LTM_ROWSIZE (ret) = rowsize; + LTM_COLSIZE (ret) = colsize; + LTM_DENOMINATOR (ret) = 1; + return ret; +} + +/* Multiply a vector VEC by a matrix MAT. + MAT is an M*N matrix, and VEC is a vector with length N. The result + is stored in DEST which must be a vector of length M. */ + +static void +lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n, + lambda_vector vec, lambda_vector dest) +{ + int i, j; + + lambda_vector_clear (dest, m); + for (i = 0; i < m; i++) + for (j = 0; j < n; j++) + dest[i] += matrix[i][j] * vec[j]; +} + +/* Return true if TRANS is a legal transformation matrix that respects + the dependence vectors in DISTS and DIRS. The conservative answer + is false. + + "Wolfe proves that a unimodular transformation represented by the + matrix T is legal when applied to a loop nest with a set of + lexicographically non-negative distance vectors RDG if and only if + for each vector d in RDG, (T.d >= 0) is lexicographically positive. + i.e.: if and only if it transforms the lexicographically positive + distance vectors to lexicographically positive vectors. Note that + a unimodular matrix must transform the zero vector (and only it) to + the zero vector." S.Muchnick. */ + +static bool +lambda_transform_legal_p (lambda_trans_matrix trans, + int nb_loops, + VEC (ddr_p, heap) *dependence_relations) +{ + unsigned int i, j; + lambda_vector distres; + struct data_dependence_relation *ddr; + + gcc_assert (LTM_COLSIZE (trans) == nb_loops + && LTM_ROWSIZE (trans) == nb_loops); + + /* When there are no dependences, the transformation is correct. */ + if (VEC_length (ddr_p, dependence_relations) == 0) + return true; + + ddr = VEC_index (ddr_p, dependence_relations, 0); + if (ddr == NULL) + return true; + + /* When there is an unknown relation in the dependence_relations, we + know that it is no worth looking at this loop nest: give up. */ + if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + return false; + + distres = lambda_vector_new (nb_loops); + + /* For each distance vector in the dependence graph. */ + FOR_EACH_VEC_ELT (ddr_p, 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): + these data accesses can happen in any order. */ + if (DDR_ARE_DEPENDENT (ddr) == chrec_known + || (DR_IS_READ (DDR_A (ddr)) && DR_IS_READ (DDR_B (ddr)))) + continue; + + /* Conservatively answer: "this transformation is not valid". */ + if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + return false; + + /* If the dependence could not be captured by a distance vector, + conservatively answer that the transform is not valid. */ + if (DDR_NUM_DIST_VECTS (ddr) == 0) + return false; + + /* Compute trans.dist_vect */ + for (j = 0; j < DDR_NUM_DIST_VECTS (ddr); j++) + { + lambda_matrix_vector_mult (LTM_MATRIX (trans), nb_loops, nb_loops, + DDR_DIST_VECT (ddr, j), distres); + + if (!lambda_vector_lexico_pos (distres, nb_loops)) + return false; + } + } + return true; +} /* Data dependency analysis. Returns true if the iterations of LOOP are independent on each other (that is, if we can execute them @@ -250,7 +367,8 @@ static bool loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack) { - VEC (ddr_p, heap) * dependence_relations; + VEC (loop_p, heap) *loop_nest; + VEC (ddr_p, heap) *dependence_relations; VEC (data_reference_p, heap) *datarefs; lambda_trans_matrix trans; bool ret = false; @@ -268,7 +386,8 @@ the iterations are independent. */ datarefs = VEC_alloc (data_reference_p, heap, 10); dependence_relations = VEC_alloc (ddr_p, heap, 10 * 10); - compute_data_dependences_for_loop (loop, true, &datarefs, + loop_nest = VEC_alloc (loop_p, heap, 3); + compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs, &dependence_relations); if (dump_file && (dump_flags & TDF_DETAILS)) dump_data_dependence_relations (dump_file, dependence_relations); @@ -286,6 +405,7 @@ fprintf (dump_file, " FAILED: data dependencies exist across iterations\n"); + VEC_free (loop_p, heap, loop_nest); free_dependence_relations (dependence_relations); free_data_refs (datarefs); @@ -315,10 +435,12 @@ /* 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; @@ -334,14 +456,25 @@ 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); @@ -356,21 +489,22 @@ 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; @@ -432,7 +566,9 @@ 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 @@ -456,8 +592,15 @@ 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; @@ -486,7 +629,13 @@ 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; @@ -499,27 +648,40 @@ 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); @@ -543,6 +705,7 @@ 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; @@ -550,11 +713,20 @@ 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); @@ -858,7 +1030,6 @@ 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; @@ -867,7 +1038,7 @@ 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); @@ -926,13 +1097,12 @@ 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); @@ -1013,7 +1183,6 @@ 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); @@ -1023,7 +1192,7 @@ 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; @@ -1091,7 +1260,7 @@ 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) { @@ -1119,7 +1288,7 @@ 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);) @@ -1154,7 +1323,7 @@ { /* Create the type for the structure to store the ssa names to. */ type = lang_hooks.types.make_type (RECORD_TYPE); - type_name = build_decl (BUILTINS_LOCATION, + type_name = build_decl (UNKNOWN_LOCATION, TYPE_DECL, create_tmp_var_name (".paral_data"), type); TYPE_NAME (type) = type_name; @@ -1221,7 +1390,7 @@ a parallelized loop. */ static tree -create_loop_fn (void) +create_loop_fn (location_t loc) { char buf[100]; char *tname; @@ -1235,8 +1404,7 @@ name = get_identifier (tname); type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); - decl = build_decl (BUILTINS_LOCATION, - FUNCTION_DECL, name, type); + decl = build_decl (loc, FUNCTION_DECL, name, type); if (!parallelized_functions) parallelized_functions = BITMAP_GGC_ALLOC (); bitmap_set_bit (parallelized_functions, DECL_UID (decl)); @@ -1251,14 +1419,12 @@ DECL_CONTEXT (decl) = NULL_TREE; DECL_INITIAL (decl) = make_node (BLOCK); - t = build_decl (BUILTINS_LOCATION, - RESULT_DECL, NULL_TREE, void_type_node); + t = build_decl (loc, RESULT_DECL, NULL_TREE, void_type_node); DECL_ARTIFICIAL (t) = 1; DECL_IGNORED_P (t) = 1; DECL_RESULT (decl) = t; - t = build_decl (BUILTINS_LOCATION, - PARM_DECL, get_identifier (".paral_data_param"), + t = build_decl (loc, PARM_DECL, get_identifier (".paral_data_param"), ptr_type_node); DECL_ARTIFICIAL (t) = 1; DECL_ARG_TYPE (t) = ptr_type_node; @@ -1400,7 +1566,7 @@ static basic_block create_parallel_loop (struct loop *loop, tree loop_fn, tree data, - tree new_data, unsigned n_threads) + tree new_data, unsigned n_threads, location_t loc) { gimple_stmt_iterator gsi; basic_block bb, paral_bb, for_bb, ex_bb; @@ -1414,10 +1580,11 @@ paral_bb = single_pred (bb); gsi = gsi_last_bb (paral_bb); - t = build_omp_clause (BUILTINS_LOCATION, OMP_CLAUSE_NUM_THREADS); + t = build_omp_clause (loc, OMP_CLAUSE_NUM_THREADS); OMP_CLAUSE_NUM_THREADS_EXPR (t) = build_int_cst (integer_type_node, n_threads); stmt = gimple_build_omp_parallel (NULL, t, loop_fn, data); + gimple_set_location (stmt, loc); gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); @@ -1440,7 +1607,9 @@ /* Emit GIMPLE_OMP_RETURN for GIMPLE_OMP_PARALLEL. */ bb = split_loop_exit_edge (single_dom_exit (loop)); gsi = gsi_last_bb (bb); - gsi_insert_after (&gsi, gimple_build_omp_return (false), GSI_NEW_STMT); + stmt = gimple_build_omp_return (false); + gimple_set_location (stmt, loc); + gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); /* Extract data for GIMPLE_OMP_FOR. */ gcc_assert (loop->header == single_dom_exit (loop)->src); @@ -1455,7 +1624,7 @@ 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); @@ -1490,10 +1659,11 @@ /* Emit GIMPLE_OMP_FOR. */ gimple_cond_set_lhs (cond_stmt, cvar_base); type = TREE_TYPE (cvar); - t = build_omp_clause (BUILTINS_LOCATION, OMP_CLAUSE_SCHEDULE); + 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); + 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); gimple_omp_for_set_final (for_stmt, 0, gimple_cond_rhs (cond_stmt)); @@ -1509,12 +1679,15 @@ /* Emit GIMPLE_OMP_CONTINUE. */ gsi = gsi_last_bb (loop->latch); stmt = gimple_build_omp_continue (cvar_next, cvar); + gimple_set_location (stmt, loc); gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); SSA_NAME_DEF_STMT (cvar_next) = stmt; /* Emit GIMPLE_OMP_RETURN for GIMPLE_OMP_FOR. */ gsi = gsi_last_bb (ex_bb); - gsi_insert_after (&gsi, gimple_build_omp_return (true), GSI_NEW_STMT); + stmt = gimple_build_omp_return (true); + gimple_set_location (stmt, loc); + gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); return paral_bb; } @@ -1537,6 +1710,8 @@ edge entry, exit; struct clsn_data clsn_data; unsigned prob; + location_t loc; + gimple cond_stmt; /* From @@ -1648,8 +1823,12 @@ &new_arg_struct, &clsn_data); /* Create the parallel constructs. */ - parallel_head = create_parallel_loop (loop, create_loop_fn (), arg_struct, - new_arg_struct, n_threads); + loc = UNKNOWN_LOCATION; + cond_stmt = last_stmt (loop->header); + if (cond_stmt) + 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) create_call_for_reduction (loop, reduction_list, &clsn_data); @@ -1716,11 +1895,22 @@ new_reduction->reduc_stmt = reduc_stmt; 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 = 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) +{ + struct reduction_info *const red = (struct reduction_info *) *slot; + gimple_set_uid (red->reduc_phi, red->reduc_version); + return 1; +} + /* Detect all reductions in the LOOP, insert them into REDUCTION_LIST. */ static void @@ -1752,7 +1942,12 @@ build_new_reduction (reduction_list, reduc_stmt, phi); } } - destroy_loop_vec_info (simple_loop_info, true); + destroy_loop_vec_info (simple_loop_info, true); + + /* 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); } /* Try to initialize NITER for code generation part. */ @@ -1822,7 +2017,8 @@ 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;