summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-05 11:15:28 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-05 11:15:28 +0000
commitad57283e6aeefab1a9ca1508bc5d5e27165695bb (patch)
tree497bf216ccc6089f923a3ccd4a77deee89c2538a /gcc
parentc246fb4f62d4e078e0f0156b2da447c91c7df27f (diff)
downloadgcc-ad57283e6aeefab1a9ca1508bc5d5e27165695bb.tar.gz
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. * gcc.dg/autopar/pr46099.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166355 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/autopar/pr46099.c47
-rw-r--r--gcc/tree-parloops.c71
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);