diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/autopar/pr46099.c | 47 | ||||
-rw-r--r-- | gcc/tree-parloops.c | 71 |
4 files changed, 121 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9af445b0b85..b5c8c4bd765 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -3,6 +3,19 @@ * cfgexpand.c (expand_debug_expr): Handle MEM_REF with non-zero offset. + PR tree-optimization/46099 + * tree-parloops.c (take_address_of): Add GSI argument. Return NULL + if it is NULL and uid wasn't found in the hash table. Just fold the + result if it is NULL otherwise. Insert other potentially needed + stmts right before current stmt instead of on the entry edge. + (struct elv_data): Add gsi and reset fields. + (eliminate_local_variables_1): Adjust caller. If take_address_of + failed for debug stmt, set dta->reset and return. + (eliminate_local_variables_stmt): Change STMT argument for GSI, + pass GSI through to the callback, handle resetting of debug stmts. + (eliminate_local_variables): Adjust caller. Process debug stmts + in second phase. + PR middle-end/43690 * gimplify.c (gimplify_asm_expr): If a "m" input is a {pre,post}{in,de}crement, fail. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8ac52a0d4af..96317720140 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2010-11-05 Jakub Jelinek <jakub@redhat.com> + PR tree-optimization/46099 + * gcc.dg/autopar/pr46099.c: New test. + PR middle-end/43690 * c-c++-common/pr43690.c: New test. diff --git a/gcc/testsuite/gcc.dg/autopar/pr46099.c b/gcc/testsuite/gcc.dg/autopar/pr46099.c new file mode 100644 index 00000000000..074278e644b --- /dev/null +++ b/gcc/testsuite/gcc.dg/autopar/pr46099.c @@ -0,0 +1,47 @@ +/* PR tree-optimization/46099 */ +/* { dg-do compile } */ +/* { dg-options "-ftree-parallelize-loops=2 -fcompare-debug -O" } */ + +static inline void +bar (int *i) +{ + int j = *i; +} + +void baz (int *, int *, int *); + +void +f1 (int n) +{ + int i; + for (i = 0; i < n; i++) + bar (&i); +} + +void +f2 (int n) +{ + int i; + int a[10000], b[10000], c[10000]; + baz (a, b, c); + for (i = 0; i < n; i++) + { + void *p = c; + a[i] = b[i] + c[i]; + } + baz (a, b, c); +} + +void +f3 (int n) +{ + int i; + int a[10000], b[10000], c[10000]; + baz (a, b, c); + for (i = 0; i < n; i++) + { + a[i] = b[i] + c[i]; + void *p = c; + } + baz (a, b, c); +} diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index de9faefe778..a634b249a61 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -314,10 +314,12 @@ loop_has_blocks_with_irreducible_flag (struct loop *loop) /* 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; @@ -346,6 +348,8 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address) dslot = htab_find_slot_with_hash (decl_address, &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 @@ -366,17 +370,20 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address) /* 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); + 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); + 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; @@ -438,7 +445,9 @@ struct elv_data 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 @@ -462,7 +471,14 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data) type = TREE_TYPE (t); addr_type = build_pointer_type (type); - addr = take_address_of (t, addr_type, dta->entry, dta->decl_address); + 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; @@ -492,7 +508,13 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data) 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; @@ -505,27 +527,40 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data) 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); @@ -549,6 +584,7 @@ eliminate_local_variables (edge entry, edge exit) 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; @@ -559,8 +595,17 @@ eliminate_local_variables (edge entry, edge exit) 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); |