1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
From bdb0f40cea4aa1a92ead381b645363ae0571c065 Mon Sep 17 00:00:00 2001
From: zhanghaijian <z.zhanghaijian@huawei.com>
Date: Mon, 12 Jul 2021 10:36:15 +0800
Subject: [PATCH 04/13] [Backport]tree-optimization: Avoid issueing loads in SM
when possible
Reference:https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f9e1ea10e657af9fb02fafecf1a600740fd34409
Currently store-motion emits a load of the value in the loop
preheader even when the original loop does not contain any read
of the reference. This avoids doing this. In the conditional
store-motion case we need to mark the sunk stores with no-warning
since the control dependence is too tricky to figure out for
the uninit warning.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c b/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c
new file mode 100755
index 00000000000..884f905148f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c
@@ -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 --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index abd5f702b91..b3fd1647fbd 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -127,6 +127,8 @@ public:
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. */
@@ -1395,6 +1397,7 @@ mem_ref_alloc (ao_ref *mem, unsigned hash, unsigned id)
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);
@@ -1435,6 +1438,27 @@ mark_ref_stored (im_mem_ref *ref, class loop *loop)
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
@@ -1571,6 +1595,8 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt)
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;
}
@@ -1968,6 +1994,8 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
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);
@@ -2115,14 +2143,17 @@ execute_sm (class loop *loop, vec<edge> exits, im_mem_ref *ref)
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)
{
--
2.21.0.windows.1
|