124 lines
4.4 KiB
Diff
124 lines
4.4 KiB
Diff
|
|
This backport contains 1 patch from gcc main stream tree.
|
||
|
|
The commit id of these patchs list as following in the order of time.
|
||
|
|
|
||
|
|
0001-tree-optimization-39612-avoid-issueing-loads-in-SM-w.patch
|
||
|
|
f9e1ea10e657af9fb02fafecf1a600740fd34409
|
||
|
|
|
||
|
|
diff -Nurp a/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c b/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c
|
||
|
|
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c 1970-01-01 08:00:00.000000000 +0800
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c 2020-08-17 11:14:08.000000000 +0800
|
||
|
|
@@ -0,0 +1,21 @@
|
||
|
|
+/* { dg-do compile } */
|
||
|
|
+/* { dg-options "-O2 -fdump-tree-lim2-details -Wuninitialized" } */
|
||
|
|
+
|
||
|
|
+void foo(int *);
|
||
|
|
+void f2(int dst[3], int R)
|
||
|
|
+{
|
||
|
|
+ int i, inter[2];
|
||
|
|
+
|
||
|
|
+ for (i = 1; i < R; i++) {
|
||
|
|
+ if (i & 8)
|
||
|
|
+ {
|
||
|
|
+ inter[0] = 1;
|
||
|
|
+ inter[1] = 1;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ foo(inter);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+/* { dg-final { scan-tree-dump-times "Executing store motion" 2 "lim2" } } */
|
||
|
|
+/* { dg-final { scan-tree-dump-not " = inter\\\[\[0-1\]\\\];" "lim2" } } */
|
||
|
|
diff -Nurp a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
|
||
|
|
--- a/gcc/tree-ssa-loop-im.c 2020-08-17 11:13:58.436000000 +0800
|
||
|
|
+++ b/gcc/tree-ssa-loop-im.c 2020-08-17 11:14:08.000000000 +0800
|
||
|
|
@@ -127,6 +127,8 @@ struct im_mem_ref
|
||
|
|
|
||
|
|
bitmap stored; /* The set of loops in that this memory location
|
||
|
|
is stored to. */
|
||
|
|
+ bitmap loaded; /* The set of loops in that this memory location
|
||
|
|
+ is loaded from. */
|
||
|
|
vec<mem_ref_loc> accesses_in_loop;
|
||
|
|
/* The locations of the accesses. Vector
|
||
|
|
indexed by the loop number. */
|
||
|
|
@@ -1394,6 +1396,7 @@ mem_ref_alloc (ao_ref *mem, unsigned has
|
||
|
|
ref->ref_decomposed = false;
|
||
|
|
ref->hash = hash;
|
||
|
|
ref->stored = NULL;
|
||
|
|
+ ref->loaded = NULL;
|
||
|
|
bitmap_initialize (&ref->indep_loop, &lim_bitmap_obstack);
|
||
|
|
bitmap_initialize (&ref->dep_loop, &lim_bitmap_obstack);
|
||
|
|
ref->accesses_in_loop.create (1);
|
||
|
|
@@ -1434,6 +1437,27 @@ mark_ref_stored (im_mem_ref *ref, struct
|
||
|
|
loop = loop_outer (loop);
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Set the LOOP bit in REF loaded bitmap and allocate that if
|
||
|
|
+ necessary. Return whether a bit was changed. */
|
||
|
|
+
|
||
|
|
+static bool
|
||
|
|
+set_ref_loaded_in_loop (im_mem_ref *ref, class loop *loop)
|
||
|
|
+{
|
||
|
|
+ if (!ref->loaded)
|
||
|
|
+ ref->loaded = BITMAP_ALLOC (&lim_bitmap_obstack);
|
||
|
|
+ return bitmap_set_bit (ref->loaded, loop->num);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+/* Marks reference REF as loaded in LOOP. */
|
||
|
|
+
|
||
|
|
+static void
|
||
|
|
+mark_ref_loaded (im_mem_ref *ref, class loop *loop)
|
||
|
|
+{
|
||
|
|
+ while (loop != current_loops->tree_root
|
||
|
|
+ && set_ref_loaded_in_loop (ref, loop))
|
||
|
|
+ loop = loop_outer (loop);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Gathers memory references in statement STMT in LOOP, storing the
|
||
|
|
information about them in the memory_accesses structure. Marks
|
||
|
|
the vops accessed through unrecognized statements there as
|
||
|
|
@@ -1569,6 +1593,8 @@ gather_mem_refs_stmt (struct loop *loop,
|
||
|
|
bitmap_set_bit (&memory_accesses.refs_stored_in_loop[loop->num], ref->id);
|
||
|
|
mark_ref_stored (ref, loop);
|
||
|
|
}
|
||
|
|
+ else
|
||
|
|
+ mark_ref_loaded (ref, loop);
|
||
|
|
init_lim_data (stmt)->ref = ref->id;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
@@ -1956,6 +1982,8 @@ execute_sm_if_changed (edge ex, tree mem
|
||
|
|
gsi = gsi_start_bb (then_bb);
|
||
|
|
/* Insert actual store. */
|
||
|
|
stmt = gimple_build_assign (unshare_expr (mem), tmp_var);
|
||
|
|
+ /* Make sure to not warn about maybe-uninit uses of tmp_var here. */
|
||
|
|
+ gimple_set_no_warning (stmt, true);
|
||
|
|
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
|
||
|
|
|
||
|
|
edge e1 = single_succ_edge (new_bb);
|
||
|
|
@@ -2102,14 +2130,17 @@ execute_sm (struct loop *loop, vec<edge>
|
||
|
|
by move_computations after all dependencies. */
|
||
|
|
gsi = gsi_for_stmt (first_mem_ref_loc (loop, ref)->stmt);
|
||
|
|
|
||
|
|
- /* FIXME/TODO: For the multi-threaded variant, we could avoid this
|
||
|
|
- load altogether, since the store is predicated by a flag. We
|
||
|
|
- could, do the load only if it was originally in the loop. */
|
||
|
|
- load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref));
|
||
|
|
- lim_data = init_lim_data (load);
|
||
|
|
- lim_data->max_loop = loop;
|
||
|
|
- lim_data->tgt_loop = loop;
|
||
|
|
- gsi_insert_before (&gsi, load, GSI_SAME_STMT);
|
||
|
|
+ /* Avoid doing a load if there was no load of the ref in the loop.
|
||
|
|
+ Esp. when the ref is not always stored we cannot optimize it
|
||
|
|
+ away later. */
|
||
|
|
+ if (ref->loaded && bitmap_bit_p (ref->loaded, loop->num))
|
||
|
|
+ {
|
||
|
|
+ load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref));
|
||
|
|
+ lim_data = init_lim_data (load);
|
||
|
|
+ lim_data->max_loop = loop;
|
||
|
|
+ lim_data->tgt_loop = loop;
|
||
|
|
+ gsi_insert_before (&gsi, load, GSI_SAME_STMT);
|
||
|
|
+ }
|
||
|
|
|
||
|
|
if (multi_threaded_model_p)
|
||
|
|
{
|