annotate gcc/tree-loop-distribution.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Loop distribution.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 Contributed by Georges-Andre Silber <Georges-Andre.Silber@ensmp.fr>
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 and Sebastian Pop <sebastian.pop@amd.com>.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 This file is part of GCC.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
7
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 under the terms of the GNU General Public License as published by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 Free Software Foundation; either version 3, or (at your option) any
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 later version.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
12
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 for more details.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
17
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 /* This pass performs loop distribution: for example, the loop
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 |DO I = 2, N
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 | A(I) = B(I) + C
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 | D(I) = A(I-1)*E
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 |ENDDO
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
29 is transformed to
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 |DOALL I = 2, N
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 | A(I) = B(I) + C
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 |ENDDO
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 |
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 |DOALL I = 2, N
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 | D(I) = A(I-1)*E
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 |ENDDO
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38
111
kono
parents: 67
diff changeset
39 Loop distribution is the dual of loop fusion. It separates statements
kono
parents: 67
diff changeset
40 of a loop (or loop nest) into multiple loops (or loop nests) with the
kono
parents: 67
diff changeset
41 same loop header. The major goal is to separate statements which may
kono
parents: 67
diff changeset
42 be vectorized from those that can't. This pass implements distribution
kono
parents: 67
diff changeset
43 in the following steps:
kono
parents: 67
diff changeset
44
kono
parents: 67
diff changeset
45 1) Seed partitions with specific type statements. For now we support
kono
parents: 67
diff changeset
46 two types seed statements: statement defining variable used outside
kono
parents: 67
diff changeset
47 of loop; statement storing to memory.
kono
parents: 67
diff changeset
48 2) Build reduced dependence graph (RDG) for loop to be distributed.
kono
parents: 67
diff changeset
49 The vertices (RDG:V) model all statements in the loop and the edges
kono
parents: 67
diff changeset
50 (RDG:E) model flow and control dependencies between statements.
kono
parents: 67
diff changeset
51 3) Apart from RDG, compute data dependencies between memory references.
kono
parents: 67
diff changeset
52 4) Starting from seed statement, build up partition by adding depended
kono
parents: 67
diff changeset
53 statements according to RDG's dependence information. Partition is
kono
parents: 67
diff changeset
54 classified as parallel type if it can be executed paralleled; or as
kono
parents: 67
diff changeset
55 sequential type if it can't. Parallel type partition is further
kono
parents: 67
diff changeset
56 classified as different builtin kinds if it can be implemented as
kono
parents: 67
diff changeset
57 builtin function calls.
kono
parents: 67
diff changeset
58 5) Build partition dependence graph (PG) based on data dependencies.
kono
parents: 67
diff changeset
59 The vertices (PG:V) model all partitions and the edges (PG:E) model
kono
parents: 67
diff changeset
60 all data dependencies between every partitions pair. In general,
kono
parents: 67
diff changeset
61 data dependence is either compilation time known or unknown. In C
kono
parents: 67
diff changeset
62 family languages, there exists quite amount compilation time unknown
kono
parents: 67
diff changeset
63 dependencies because of possible alias relation of data references.
kono
parents: 67
diff changeset
64 We categorize PG's edge to two types: "true" edge that represents
kono
parents: 67
diff changeset
65 compilation time known data dependencies; "alias" edge for all other
kono
parents: 67
diff changeset
66 data dependencies.
kono
parents: 67
diff changeset
67 6) Traverse subgraph of PG as if all "alias" edges don't exist. Merge
kono
parents: 67
diff changeset
68 partitions in each strong connected component (SCC) correspondingly.
kono
parents: 67
diff changeset
69 Build new PG for merged partitions.
kono
parents: 67
diff changeset
70 7) Traverse PG again and this time with both "true" and "alias" edges
kono
parents: 67
diff changeset
71 included. We try to break SCCs by removing some edges. Because
kono
parents: 67
diff changeset
72 SCCs by "true" edges are all fused in step 6), we can break SCCs
kono
parents: 67
diff changeset
73 by removing some "alias" edges. It's NP-hard to choose optimal
kono
parents: 67
diff changeset
74 edge set, fortunately simple approximation is good enough for us
kono
parents: 67
diff changeset
75 given the small problem scale.
kono
parents: 67
diff changeset
76 8) Collect all data dependencies of the removed "alias" edges. Create
kono
parents: 67
diff changeset
77 runtime alias checks for collected data dependencies.
kono
parents: 67
diff changeset
78 9) Version loop under the condition of runtime alias checks. Given
kono
parents: 67
diff changeset
79 loop distribution generally introduces additional overhead, it is
kono
parents: 67
diff changeset
80 only useful if vectorization is achieved in distributed loop. We
kono
parents: 67
diff changeset
81 version loop with internal function call IFN_LOOP_DIST_ALIAS. If
kono
parents: 67
diff changeset
82 no distributed loop can be vectorized, we simply remove distributed
kono
parents: 67
diff changeset
83 loops and recover to the original one.
kono
parents: 67
diff changeset
84
kono
parents: 67
diff changeset
85 TODO:
kono
parents: 67
diff changeset
86 1) We only distribute innermost two-level loop nest now. We should
kono
parents: 67
diff changeset
87 extend it for arbitrary loop nests in the future.
kono
parents: 67
diff changeset
88 2) We only fuse partitions in SCC now. A better fusion algorithm is
kono
parents: 67
diff changeset
89 desired to minimize loop overhead, maximize parallelism and maximize
kono
parents: 67
diff changeset
90 data reuse. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 #include "coretypes.h"
111
kono
parents: 67
diff changeset
95 #include "backend.h"
kono
parents: 67
diff changeset
96 #include "tree.h"
kono
parents: 67
diff changeset
97 #include "gimple.h"
kono
parents: 67
diff changeset
98 #include "cfghooks.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 #include "tree-pass.h"
111
kono
parents: 67
diff changeset
100 #include "ssa.h"
kono
parents: 67
diff changeset
101 #include "gimple-pretty-print.h"
kono
parents: 67
diff changeset
102 #include "fold-const.h"
kono
parents: 67
diff changeset
103 #include "cfganal.h"
kono
parents: 67
diff changeset
104 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
105 #include "gimplify-me.h"
kono
parents: 67
diff changeset
106 #include "stor-layout.h"
kono
parents: 67
diff changeset
107 #include "tree-cfg.h"
kono
parents: 67
diff changeset
108 #include "tree-ssa-loop-manip.h"
kono
parents: 67
diff changeset
109 #include "tree-ssa-loop-ivopts.h"
kono
parents: 67
diff changeset
110 #include "tree-ssa-loop.h"
kono
parents: 67
diff changeset
111 #include "tree-into-ssa.h"
kono
parents: 67
diff changeset
112 #include "tree-ssa.h"
kono
parents: 67
diff changeset
113 #include "cfgloop.h"
kono
parents: 67
diff changeset
114 #include "tree-scalar-evolution.h"
kono
parents: 67
diff changeset
115 #include "tree-vectorizer.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
116 #include "tree-eh.h"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
117 #include "gimple-fold.h"
111
kono
parents: 67
diff changeset
118
kono
parents: 67
diff changeset
119
kono
parents: 67
diff changeset
120 #define MAX_DATAREFS_NUM \
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
121 ((unsigned) param_loop_max_datarefs_for_datadeps)
111
kono
parents: 67
diff changeset
122
kono
parents: 67
diff changeset
123 /* Threshold controlling number of distributed partitions. Given it may
kono
parents: 67
diff changeset
124 be unnecessary if a memory stream cost model is invented in the future,
kono
parents: 67
diff changeset
125 we define it as a temporary macro, rather than a parameter. */
kono
parents: 67
diff changeset
126 #define NUM_PARTITION_THRESHOLD (4)
kono
parents: 67
diff changeset
127
kono
parents: 67
diff changeset
128 /* Hashtable helpers. */
kono
parents: 67
diff changeset
129
kono
parents: 67
diff changeset
130 struct ddr_hasher : nofree_ptr_hash <struct data_dependence_relation>
kono
parents: 67
diff changeset
131 {
kono
parents: 67
diff changeset
132 static inline hashval_t hash (const data_dependence_relation *);
kono
parents: 67
diff changeset
133 static inline bool equal (const data_dependence_relation *,
kono
parents: 67
diff changeset
134 const data_dependence_relation *);
kono
parents: 67
diff changeset
135 };
kono
parents: 67
diff changeset
136
kono
parents: 67
diff changeset
137 /* Hash function for data dependence. */
kono
parents: 67
diff changeset
138
kono
parents: 67
diff changeset
139 inline hashval_t
kono
parents: 67
diff changeset
140 ddr_hasher::hash (const data_dependence_relation *ddr)
kono
parents: 67
diff changeset
141 {
kono
parents: 67
diff changeset
142 inchash::hash h;
kono
parents: 67
diff changeset
143 h.add_ptr (DDR_A (ddr));
kono
parents: 67
diff changeset
144 h.add_ptr (DDR_B (ddr));
kono
parents: 67
diff changeset
145 return h.end ();
kono
parents: 67
diff changeset
146 }
kono
parents: 67
diff changeset
147
kono
parents: 67
diff changeset
148 /* Hash table equality function for data dependence. */
kono
parents: 67
diff changeset
149
kono
parents: 67
diff changeset
150 inline bool
kono
parents: 67
diff changeset
151 ddr_hasher::equal (const data_dependence_relation *ddr1,
kono
parents: 67
diff changeset
152 const data_dependence_relation *ddr2)
kono
parents: 67
diff changeset
153 {
kono
parents: 67
diff changeset
154 return (DDR_A (ddr1) == DDR_A (ddr2) && DDR_B (ddr1) == DDR_B (ddr2));
kono
parents: 67
diff changeset
155 }
kono
parents: 67
diff changeset
156
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
157
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
158
111
kono
parents: 67
diff changeset
159 #define DR_INDEX(dr) ((uintptr_t) (dr)->aux)
kono
parents: 67
diff changeset
160
kono
parents: 67
diff changeset
161 /* A Reduced Dependence Graph (RDG) vertex representing a statement. */
kono
parents: 67
diff changeset
162 struct rdg_vertex
kono
parents: 67
diff changeset
163 {
kono
parents: 67
diff changeset
164 /* The statement represented by this vertex. */
kono
parents: 67
diff changeset
165 gimple *stmt;
kono
parents: 67
diff changeset
166
kono
parents: 67
diff changeset
167 /* Vector of data-references in this statement. */
kono
parents: 67
diff changeset
168 vec<data_reference_p> datarefs;
kono
parents: 67
diff changeset
169
kono
parents: 67
diff changeset
170 /* True when the statement contains a write to memory. */
kono
parents: 67
diff changeset
171 bool has_mem_write;
kono
parents: 67
diff changeset
172
kono
parents: 67
diff changeset
173 /* True when the statement contains a read from memory. */
kono
parents: 67
diff changeset
174 bool has_mem_reads;
kono
parents: 67
diff changeset
175 };
kono
parents: 67
diff changeset
176
kono
parents: 67
diff changeset
177 #define RDGV_STMT(V) ((struct rdg_vertex *) ((V)->data))->stmt
kono
parents: 67
diff changeset
178 #define RDGV_DATAREFS(V) ((struct rdg_vertex *) ((V)->data))->datarefs
kono
parents: 67
diff changeset
179 #define RDGV_HAS_MEM_WRITE(V) ((struct rdg_vertex *) ((V)->data))->has_mem_write
kono
parents: 67
diff changeset
180 #define RDGV_HAS_MEM_READS(V) ((struct rdg_vertex *) ((V)->data))->has_mem_reads
kono
parents: 67
diff changeset
181 #define RDG_STMT(RDG, I) RDGV_STMT (&(RDG->vertices[I]))
kono
parents: 67
diff changeset
182 #define RDG_DATAREFS(RDG, I) RDGV_DATAREFS (&(RDG->vertices[I]))
kono
parents: 67
diff changeset
183 #define RDG_MEM_WRITE_STMT(RDG, I) RDGV_HAS_MEM_WRITE (&(RDG->vertices[I]))
kono
parents: 67
diff changeset
184 #define RDG_MEM_READS_STMT(RDG, I) RDGV_HAS_MEM_READS (&(RDG->vertices[I]))
kono
parents: 67
diff changeset
185
kono
parents: 67
diff changeset
186 /* Data dependence type. */
kono
parents: 67
diff changeset
187
kono
parents: 67
diff changeset
188 enum rdg_dep_type
kono
parents: 67
diff changeset
189 {
kono
parents: 67
diff changeset
190 /* Read After Write (RAW). */
kono
parents: 67
diff changeset
191 flow_dd = 'f',
kono
parents: 67
diff changeset
192
kono
parents: 67
diff changeset
193 /* Control dependence (execute conditional on). */
kono
parents: 67
diff changeset
194 control_dd = 'c'
kono
parents: 67
diff changeset
195 };
kono
parents: 67
diff changeset
196
kono
parents: 67
diff changeset
197 /* Dependence information attached to an edge of the RDG. */
kono
parents: 67
diff changeset
198
kono
parents: 67
diff changeset
199 struct rdg_edge
kono
parents: 67
diff changeset
200 {
kono
parents: 67
diff changeset
201 /* Type of the dependence. */
kono
parents: 67
diff changeset
202 enum rdg_dep_type type;
kono
parents: 67
diff changeset
203 };
kono
parents: 67
diff changeset
204
kono
parents: 67
diff changeset
205 #define RDGE_TYPE(E) ((struct rdg_edge *) ((E)->data))->type
kono
parents: 67
diff changeset
206
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
207 /* Kind of distributed loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
208 enum partition_kind {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
209 PKIND_NORMAL,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
210 /* Partial memset stands for a paritition can be distributed into a loop
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
211 of memset calls, rather than a single memset call. It's handled just
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
212 like a normal parition, i.e, distributed as separate loop, no memset
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
213 call is generated.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
214
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
215 Note: This is a hacking fix trying to distribute ZERO-ing stmt in a
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
216 loop nest as deep as possible. As a result, parloop achieves better
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
217 parallelization by parallelizing deeper loop nest. This hack should
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
218 be unnecessary and removed once distributed memset can be understood
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
219 and analyzed in data reference analysis. See PR82604 for more. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
220 PKIND_PARTIAL_MEMSET,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
221 PKIND_MEMSET, PKIND_MEMCPY, PKIND_MEMMOVE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
222 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
223
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
224 /* Type of distributed loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
225 enum partition_type {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
226 /* The distributed loop can be executed parallelly. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
227 PTYPE_PARALLEL = 0,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
228 /* The distributed loop has to be executed sequentially. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
229 PTYPE_SEQUENTIAL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
230 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
231
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
232 /* Builtin info for loop distribution. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
233 struct builtin_info
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
234 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
235 /* data-references a kind != PKIND_NORMAL partition is about. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
236 data_reference_p dst_dr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
237 data_reference_p src_dr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
238 /* Base address and size of memory objects operated by the builtin. Note
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
239 both dest and source memory objects must have the same size. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
240 tree dst_base;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
241 tree src_base;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
242 tree size;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
243 /* Base and offset part of dst_base after stripping constant offset. This
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
244 is only used in memset builtin distribution for now. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
245 tree dst_base_base;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
246 unsigned HOST_WIDE_INT dst_base_offset;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
247 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
248
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
249 /* Partition for loop distribution. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
250 struct partition
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
251 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
252 /* Statements of the partition. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
253 bitmap stmts;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
254 /* True if the partition defines variable which is used outside of loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
255 bool reduction_p;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
256 location_t loc;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
257 enum partition_kind kind;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
258 enum partition_type type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
259 /* Data references in the partition. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
260 bitmap datarefs;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
261 /* Information of builtin parition. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
262 struct builtin_info *builtin;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
263 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
264
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
265 /* Partitions are fused because of different reasons. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
266 enum fuse_type
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
267 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
268 FUSE_NON_BUILTIN = 0,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
269 FUSE_REDUCTION = 1,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
270 FUSE_SHARE_REF = 2,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
271 FUSE_SAME_SCC = 3,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
272 FUSE_FINALIZE = 4
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
273 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
274
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
275 /* Description on different fusing reason. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
276 static const char *fuse_message[] = {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
277 "they are non-builtins",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
278 "they have reductions",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
279 "they have shared memory refs",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
280 "they are in the same dependence scc",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
281 "there is no point to distribute loop"};
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
282
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
283
111
kono
parents: 67
diff changeset
284 /* Dump vertex I in RDG to FILE. */
kono
parents: 67
diff changeset
285
kono
parents: 67
diff changeset
286 static void
kono
parents: 67
diff changeset
287 dump_rdg_vertex (FILE *file, struct graph *rdg, int i)
kono
parents: 67
diff changeset
288 {
kono
parents: 67
diff changeset
289 struct vertex *v = &(rdg->vertices[i]);
kono
parents: 67
diff changeset
290 struct graph_edge *e;
kono
parents: 67
diff changeset
291
kono
parents: 67
diff changeset
292 fprintf (file, "(vertex %d: (%s%s) (in:", i,
kono
parents: 67
diff changeset
293 RDG_MEM_WRITE_STMT (rdg, i) ? "w" : "",
kono
parents: 67
diff changeset
294 RDG_MEM_READS_STMT (rdg, i) ? "r" : "");
kono
parents: 67
diff changeset
295
kono
parents: 67
diff changeset
296 if (v->pred)
kono
parents: 67
diff changeset
297 for (e = v->pred; e; e = e->pred_next)
kono
parents: 67
diff changeset
298 fprintf (file, " %d", e->src);
kono
parents: 67
diff changeset
299
kono
parents: 67
diff changeset
300 fprintf (file, ") (out:");
kono
parents: 67
diff changeset
301
kono
parents: 67
diff changeset
302 if (v->succ)
kono
parents: 67
diff changeset
303 for (e = v->succ; e; e = e->succ_next)
kono
parents: 67
diff changeset
304 fprintf (file, " %d", e->dest);
kono
parents: 67
diff changeset
305
kono
parents: 67
diff changeset
306 fprintf (file, ")\n");
kono
parents: 67
diff changeset
307 print_gimple_stmt (file, RDGV_STMT (v), 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents: 67
diff changeset
308 fprintf (file, ")\n");
kono
parents: 67
diff changeset
309 }
kono
parents: 67
diff changeset
310
kono
parents: 67
diff changeset
311 /* Call dump_rdg_vertex on stderr. */
kono
parents: 67
diff changeset
312
kono
parents: 67
diff changeset
313 DEBUG_FUNCTION void
kono
parents: 67
diff changeset
314 debug_rdg_vertex (struct graph *rdg, int i)
kono
parents: 67
diff changeset
315 {
kono
parents: 67
diff changeset
316 dump_rdg_vertex (stderr, rdg, i);
kono
parents: 67
diff changeset
317 }
kono
parents: 67
diff changeset
318
kono
parents: 67
diff changeset
319 /* Dump the reduced dependence graph RDG to FILE. */
kono
parents: 67
diff changeset
320
kono
parents: 67
diff changeset
321 static void
kono
parents: 67
diff changeset
322 dump_rdg (FILE *file, struct graph *rdg)
kono
parents: 67
diff changeset
323 {
kono
parents: 67
diff changeset
324 fprintf (file, "(rdg\n");
kono
parents: 67
diff changeset
325 for (int i = 0; i < rdg->n_vertices; i++)
kono
parents: 67
diff changeset
326 dump_rdg_vertex (file, rdg, i);
kono
parents: 67
diff changeset
327 fprintf (file, ")\n");
kono
parents: 67
diff changeset
328 }
kono
parents: 67
diff changeset
329
kono
parents: 67
diff changeset
330 /* Call dump_rdg on stderr. */
kono
parents: 67
diff changeset
331
kono
parents: 67
diff changeset
332 DEBUG_FUNCTION void
kono
parents: 67
diff changeset
333 debug_rdg (struct graph *rdg)
kono
parents: 67
diff changeset
334 {
kono
parents: 67
diff changeset
335 dump_rdg (stderr, rdg);
kono
parents: 67
diff changeset
336 }
kono
parents: 67
diff changeset
337
kono
parents: 67
diff changeset
338 static void
kono
parents: 67
diff changeset
339 dot_rdg_1 (FILE *file, struct graph *rdg)
kono
parents: 67
diff changeset
340 {
kono
parents: 67
diff changeset
341 int i;
kono
parents: 67
diff changeset
342 pretty_printer buffer;
kono
parents: 67
diff changeset
343 pp_needs_newline (&buffer) = false;
kono
parents: 67
diff changeset
344 buffer.buffer->stream = file;
kono
parents: 67
diff changeset
345
kono
parents: 67
diff changeset
346 fprintf (file, "digraph RDG {\n");
kono
parents: 67
diff changeset
347
kono
parents: 67
diff changeset
348 for (i = 0; i < rdg->n_vertices; i++)
kono
parents: 67
diff changeset
349 {
kono
parents: 67
diff changeset
350 struct vertex *v = &(rdg->vertices[i]);
kono
parents: 67
diff changeset
351 struct graph_edge *e;
kono
parents: 67
diff changeset
352
kono
parents: 67
diff changeset
353 fprintf (file, "%d [label=\"[%d] ", i, i);
kono
parents: 67
diff changeset
354 pp_gimple_stmt_1 (&buffer, RDGV_STMT (v), 0, TDF_SLIM);
kono
parents: 67
diff changeset
355 pp_flush (&buffer);
kono
parents: 67
diff changeset
356 fprintf (file, "\"]\n");
kono
parents: 67
diff changeset
357
kono
parents: 67
diff changeset
358 /* Highlight reads from memory. */
kono
parents: 67
diff changeset
359 if (RDG_MEM_READS_STMT (rdg, i))
kono
parents: 67
diff changeset
360 fprintf (file, "%d [style=filled, fillcolor=green]\n", i);
kono
parents: 67
diff changeset
361
kono
parents: 67
diff changeset
362 /* Highlight stores to memory. */
kono
parents: 67
diff changeset
363 if (RDG_MEM_WRITE_STMT (rdg, i))
kono
parents: 67
diff changeset
364 fprintf (file, "%d [style=filled, fillcolor=red]\n", i);
kono
parents: 67
diff changeset
365
kono
parents: 67
diff changeset
366 if (v->succ)
kono
parents: 67
diff changeset
367 for (e = v->succ; e; e = e->succ_next)
kono
parents: 67
diff changeset
368 switch (RDGE_TYPE (e))
kono
parents: 67
diff changeset
369 {
kono
parents: 67
diff changeset
370 case flow_dd:
kono
parents: 67
diff changeset
371 /* These are the most common dependences: don't print these. */
kono
parents: 67
diff changeset
372 fprintf (file, "%d -> %d \n", i, e->dest);
kono
parents: 67
diff changeset
373 break;
kono
parents: 67
diff changeset
374
kono
parents: 67
diff changeset
375 case control_dd:
kono
parents: 67
diff changeset
376 fprintf (file, "%d -> %d [label=control] \n", i, e->dest);
kono
parents: 67
diff changeset
377 break;
kono
parents: 67
diff changeset
378
kono
parents: 67
diff changeset
379 default:
kono
parents: 67
diff changeset
380 gcc_unreachable ();
kono
parents: 67
diff changeset
381 }
kono
parents: 67
diff changeset
382 }
kono
parents: 67
diff changeset
383
kono
parents: 67
diff changeset
384 fprintf (file, "}\n\n");
kono
parents: 67
diff changeset
385 }
kono
parents: 67
diff changeset
386
kono
parents: 67
diff changeset
387 /* Display the Reduced Dependence Graph using dotty. */
kono
parents: 67
diff changeset
388
kono
parents: 67
diff changeset
389 DEBUG_FUNCTION void
kono
parents: 67
diff changeset
390 dot_rdg (struct graph *rdg)
kono
parents: 67
diff changeset
391 {
kono
parents: 67
diff changeset
392 /* When debugging, you may want to enable the following code. */
kono
parents: 67
diff changeset
393 #ifdef HAVE_POPEN
kono
parents: 67
diff changeset
394 FILE *file = popen ("dot -Tx11", "w");
kono
parents: 67
diff changeset
395 if (!file)
kono
parents: 67
diff changeset
396 return;
kono
parents: 67
diff changeset
397 dot_rdg_1 (file, rdg);
kono
parents: 67
diff changeset
398 fflush (file);
kono
parents: 67
diff changeset
399 close (fileno (file));
kono
parents: 67
diff changeset
400 pclose (file);
kono
parents: 67
diff changeset
401 #else
kono
parents: 67
diff changeset
402 dot_rdg_1 (stderr, rdg);
kono
parents: 67
diff changeset
403 #endif
kono
parents: 67
diff changeset
404 }
kono
parents: 67
diff changeset
405
kono
parents: 67
diff changeset
406 /* Returns the index of STMT in RDG. */
kono
parents: 67
diff changeset
407
kono
parents: 67
diff changeset
408 static int
kono
parents: 67
diff changeset
409 rdg_vertex_for_stmt (struct graph *rdg ATTRIBUTE_UNUSED, gimple *stmt)
kono
parents: 67
diff changeset
410 {
kono
parents: 67
diff changeset
411 int index = gimple_uid (stmt);
kono
parents: 67
diff changeset
412 gcc_checking_assert (index == -1 || RDG_STMT (rdg, index) == stmt);
kono
parents: 67
diff changeset
413 return index;
kono
parents: 67
diff changeset
414 }
kono
parents: 67
diff changeset
415
kono
parents: 67
diff changeset
416 /* Creates dependence edges in RDG for all the uses of DEF. IDEF is
kono
parents: 67
diff changeset
417 the index of DEF in RDG. */
kono
parents: 67
diff changeset
418
kono
parents: 67
diff changeset
419 static void
kono
parents: 67
diff changeset
420 create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
kono
parents: 67
diff changeset
421 {
kono
parents: 67
diff changeset
422 use_operand_p imm_use_p;
kono
parents: 67
diff changeset
423 imm_use_iterator iterator;
kono
parents: 67
diff changeset
424
kono
parents: 67
diff changeset
425 FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, def)
kono
parents: 67
diff changeset
426 {
kono
parents: 67
diff changeset
427 struct graph_edge *e;
kono
parents: 67
diff changeset
428 int use = rdg_vertex_for_stmt (rdg, USE_STMT (imm_use_p));
kono
parents: 67
diff changeset
429
kono
parents: 67
diff changeset
430 if (use < 0)
kono
parents: 67
diff changeset
431 continue;
kono
parents: 67
diff changeset
432
kono
parents: 67
diff changeset
433 e = add_edge (rdg, idef, use);
kono
parents: 67
diff changeset
434 e->data = XNEW (struct rdg_edge);
kono
parents: 67
diff changeset
435 RDGE_TYPE (e) = flow_dd;
kono
parents: 67
diff changeset
436 }
kono
parents: 67
diff changeset
437 }
kono
parents: 67
diff changeset
438
kono
parents: 67
diff changeset
439 /* Creates an edge for the control dependences of BB to the vertex V. */
kono
parents: 67
diff changeset
440
kono
parents: 67
diff changeset
441 static void
kono
parents: 67
diff changeset
442 create_edge_for_control_dependence (struct graph *rdg, basic_block bb,
kono
parents: 67
diff changeset
443 int v, control_dependences *cd)
kono
parents: 67
diff changeset
444 {
kono
parents: 67
diff changeset
445 bitmap_iterator bi;
kono
parents: 67
diff changeset
446 unsigned edge_n;
kono
parents: 67
diff changeset
447 EXECUTE_IF_SET_IN_BITMAP (cd->get_edges_dependent_on (bb->index),
kono
parents: 67
diff changeset
448 0, edge_n, bi)
kono
parents: 67
diff changeset
449 {
kono
parents: 67
diff changeset
450 basic_block cond_bb = cd->get_edge_src (edge_n);
kono
parents: 67
diff changeset
451 gimple *stmt = last_stmt (cond_bb);
kono
parents: 67
diff changeset
452 if (stmt && is_ctrl_stmt (stmt))
kono
parents: 67
diff changeset
453 {
kono
parents: 67
diff changeset
454 struct graph_edge *e;
kono
parents: 67
diff changeset
455 int c = rdg_vertex_for_stmt (rdg, stmt);
kono
parents: 67
diff changeset
456 if (c < 0)
kono
parents: 67
diff changeset
457 continue;
kono
parents: 67
diff changeset
458
kono
parents: 67
diff changeset
459 e = add_edge (rdg, c, v);
kono
parents: 67
diff changeset
460 e->data = XNEW (struct rdg_edge);
kono
parents: 67
diff changeset
461 RDGE_TYPE (e) = control_dd;
kono
parents: 67
diff changeset
462 }
kono
parents: 67
diff changeset
463 }
kono
parents: 67
diff changeset
464 }
kono
parents: 67
diff changeset
465
kono
parents: 67
diff changeset
466 /* Creates the edges of the reduced dependence graph RDG. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 static void
111
kono
parents: 67
diff changeset
469 create_rdg_flow_edges (struct graph *rdg)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 {
111
kono
parents: 67
diff changeset
471 int i;
kono
parents: 67
diff changeset
472 def_operand_p def_p;
kono
parents: 67
diff changeset
473 ssa_op_iter iter;
kono
parents: 67
diff changeset
474
kono
parents: 67
diff changeset
475 for (i = 0; i < rdg->n_vertices; i++)
kono
parents: 67
diff changeset
476 FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
kono
parents: 67
diff changeset
477 iter, SSA_OP_DEF)
kono
parents: 67
diff changeset
478 create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
kono
parents: 67
diff changeset
479 }
kono
parents: 67
diff changeset
480
kono
parents: 67
diff changeset
481 /* Creates the edges of the reduced dependence graph RDG. */
kono
parents: 67
diff changeset
482
kono
parents: 67
diff changeset
483 static void
kono
parents: 67
diff changeset
484 create_rdg_cd_edges (struct graph *rdg, control_dependences *cd, loop_p loop)
kono
parents: 67
diff changeset
485 {
kono
parents: 67
diff changeset
486 int i;
kono
parents: 67
diff changeset
487
kono
parents: 67
diff changeset
488 for (i = 0; i < rdg->n_vertices; i++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 {
111
kono
parents: 67
diff changeset
490 gimple *stmt = RDG_STMT (rdg, i);
kono
parents: 67
diff changeset
491 if (gimple_code (stmt) == GIMPLE_PHI)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492 {
111
kono
parents: 67
diff changeset
493 edge_iterator ei;
kono
parents: 67
diff changeset
494 edge e;
kono
parents: 67
diff changeset
495 FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
kono
parents: 67
diff changeset
496 if (flow_bb_inside_loop_p (loop, e->src))
kono
parents: 67
diff changeset
497 create_edge_for_control_dependence (rdg, e->src, i, cd);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 else
111
kono
parents: 67
diff changeset
500 create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd);
kono
parents: 67
diff changeset
501 }
kono
parents: 67
diff changeset
502 }
kono
parents: 67
diff changeset
503
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
504
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
505 class loop_distribution
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
506 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
507 private:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
508 /* The loop (nest) to be distributed. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
509 vec<loop_p> loop_nest;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
510
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 /* Vector of data references in the loop to be distributed. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
512 vec<data_reference_p> datarefs_vec;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
513
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
514 /* If there is nonaddressable data reference in above vector. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
515 bool has_nonaddressable_dataref_p;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
517 /* Store index of data reference in aux field. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
518
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
519 /* Hash table for data dependence relation in the loop to be distributed. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
520 hash_table<ddr_hasher> *ddrs_table;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
521
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
522 /* Array mapping basic block's index to its topological order. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
523 int *bb_top_order_index;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 /* And size of the array. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
525 int bb_top_order_index_size;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
526
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
527 /* Build the vertices of the reduced dependence graph RDG. Return false
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
528 if that failed. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
529 bool create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
530
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
531 /* Initialize STMTS with all the statements of LOOP. We use topological
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
532 order to discover all statements. The order is important because
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
533 generate_loops_for_partition is using the same traversal for identifying
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
534 statements in loop copies. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
535 void stmts_from_loop (class loop *loop, vec<gimple *> *stmts);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
536
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
537
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
538 /* Build the Reduced Dependence Graph (RDG) with one vertex per statement of
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
539 LOOP, and one edge per flow dependence or control dependence from control
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
540 dependence CD. During visiting each statement, data references are also
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
541 collected and recorded in global data DATAREFS_VEC. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
542 struct graph * build_rdg (class loop *loop, control_dependences *cd);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
543
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
544 /* Merge PARTITION into the partition DEST. RDG is the reduced dependence
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
545 graph and we update type for result partition if it is non-NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
546 void partition_merge_into (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
547 partition *dest, partition *partition,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
548 enum fuse_type ft);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
549
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
550
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
551 /* Return data dependence relation for data references A and B. The two
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
552 data references must be in lexicographic order wrto reduced dependence
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
553 graph RDG. We firstly try to find ddr from global ddr hash table. If
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
554 it doesn't exist, compute the ddr and cache it. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
555 data_dependence_relation * get_data_dependence (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
556 data_reference_p a,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
557 data_reference_p b);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
558
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
559
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
560 /* In reduced dependence graph RDG for loop distribution, return true if
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
561 dependence between references DR1 and DR2 leads to a dependence cycle
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
562 and such dependence cycle can't be resolved by runtime alias check. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
563 bool data_dep_in_cycle_p (struct graph *rdg, data_reference_p dr1,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
564 data_reference_p dr2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
565
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
566
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
567 /* Given reduced dependence graph RDG, PARTITION1 and PARTITION2, update
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
568 PARTITION1's type after merging PARTITION2 into PARTITION1. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
569 void update_type_for_merge (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
570 partition *partition1, partition *partition2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
571
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
572
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
573 /* Returns a partition with all the statements needed for computing
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
574 the vertex V of the RDG, also including the loop exit conditions. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
575 partition *build_rdg_partition_for_vertex (struct graph *rdg, int v);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
576
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
577 /* Given data references DST_DR and SRC_DR in loop nest LOOP and RDG, classify
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
578 if it forms builtin memcpy or memmove call. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
579 void classify_builtin_ldst (loop_p loop, struct graph *rdg, partition *partition,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
580 data_reference_p dst_dr, data_reference_p src_dr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
581
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
582 /* Classifies the builtin kind we can generate for PARTITION of RDG and LOOP.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
583 For the moment we detect memset, memcpy and memmove patterns. Bitmap
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
584 STMT_IN_ALL_PARTITIONS contains statements belonging to all partitions.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
585 Returns true if there is a reduction in all partitions and we
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
586 possibly did not mark PARTITION as having one for this reason. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
587
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
588 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
589 classify_partition (loop_p loop,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
590 struct graph *rdg, partition *partition,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
591 bitmap stmt_in_all_partitions);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
592
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
593
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
594 /* Returns true when PARTITION1 and PARTITION2 access the same memory
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
595 object in RDG. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
596 bool share_memory_accesses (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
597 partition *partition1, partition *partition2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
598
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
599 /* For each seed statement in STARTING_STMTS, this function builds
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
600 partition for it by adding depended statements according to RDG.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
601 All partitions are recorded in PARTITIONS. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
602 void rdg_build_partitions (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
603 vec<gimple *> starting_stmts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
604 vec<partition *> *partitions);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
605
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
606 /* Compute partition dependence created by the data references in DRS1
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
607 and DRS2, modify and return DIR according to that. IF ALIAS_DDR is
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
608 not NULL, we record dependence introduced by possible alias between
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
609 two data references in ALIAS_DDRS; otherwise, we simply ignore such
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
610 dependence as if it doesn't exist at all. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
611 int pg_add_dependence_edges (struct graph *rdg, int dir, bitmap drs1,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
612 bitmap drs2, vec<ddr_p> *alias_ddrs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
613
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
614
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
615 /* Build and return partition dependence graph for PARTITIONS. RDG is
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
616 reduced dependence graph for the loop to be distributed. If IGNORE_ALIAS_P
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
617 is true, data dependence caused by possible alias between references
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
618 is ignored, as if it doesn't exist at all; otherwise all depdendences
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
619 are considered. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
620 struct graph *build_partition_graph (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
621 vec<struct partition *> *partitions,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
622 bool ignore_alias_p);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
623
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
624 /* Given reduced dependence graph RDG merge strong connected components
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
625 of PARTITIONS. If IGNORE_ALIAS_P is true, data dependence caused by
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
626 possible alias between references is ignored, as if it doesn't exist
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
627 at all; otherwise all depdendences are considered. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
628 void merge_dep_scc_partitions (struct graph *rdg, vec<struct partition *>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
629 *partitions, bool ignore_alias_p);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
630
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
631 /* This is the main function breaking strong conected components in
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
632 PARTITIONS giving reduced depdendence graph RDG. Store data dependence
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
633 relations for runtime alias check in ALIAS_DDRS. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
634 void break_alias_scc_partitions (struct graph *rdg, vec<struct partition *>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
635 *partitions, vec<ddr_p> *alias_ddrs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
636
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
637
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
638 /* Fuse PARTITIONS of LOOP if necessary before finalizing distribution.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
639 ALIAS_DDRS contains ddrs which need runtime alias check. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
640 void finalize_partitions (class loop *loop, vec<struct partition *>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
641 *partitions, vec<ddr_p> *alias_ddrs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
642
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
643 /* Distributes the code from LOOP in such a way that producer statements
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
644 are placed before consumer statements. Tries to separate only the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
645 statements from STMTS into separate loops. Returns the number of
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
646 distributed loops. Set NB_CALLS to number of generated builtin calls.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
647 Set *DESTROY_P to whether LOOP needs to be destroyed. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
648 int distribute_loop (class loop *loop, vec<gimple *> stmts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
649 control_dependences *cd, int *nb_calls, bool *destroy_p,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
650 bool only_patterns_p);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
651
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
652 /* Compute topological order for basic blocks. Topological order is
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
653 needed because data dependence is computed for data references in
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
654 lexicographical order. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
655 void bb_top_order_init (void);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
656
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
657 void bb_top_order_destroy (void);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
658
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
659 public:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
660
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
661 /* Getter for bb_top_order. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
662
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
663 inline int get_bb_top_order_index_size (void)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
664 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
665 return bb_top_order_index_size;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
666 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
667
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
668 inline int get_bb_top_order_index (int i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
669 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
670 return bb_top_order_index[i];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
671 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
672
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
673 unsigned int execute (function *fun);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
674 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
675
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
676
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
677 /* If X has a smaller topological sort number than Y, returns -1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
678 if greater, returns 1. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
679 static int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
680 bb_top_order_cmp_r (const void *x, const void *y, void *loop)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
681 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
682 loop_distribution *_loop =
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
683 (loop_distribution *) loop;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
684
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
685 basic_block bb1 = *(const basic_block *) x;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
686 basic_block bb2 = *(const basic_block *) y;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
687
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
688 int bb_top_order_index_size = _loop->get_bb_top_order_index_size ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
689
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
690 gcc_assert (bb1->index < bb_top_order_index_size
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
691 && bb2->index < bb_top_order_index_size);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
692 gcc_assert (bb1 == bb2
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
693 || _loop->get_bb_top_order_index(bb1->index)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
694 != _loop->get_bb_top_order_index(bb2->index));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
695
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
696 return (_loop->get_bb_top_order_index(bb1->index) -
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
697 _loop->get_bb_top_order_index(bb2->index));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
698 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
699
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
700 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
701 loop_distribution::create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
702 loop_p loop)
111
kono
parents: 67
diff changeset
703 {
kono
parents: 67
diff changeset
704 int i;
kono
parents: 67
diff changeset
705 gimple *stmt;
kono
parents: 67
diff changeset
706
kono
parents: 67
diff changeset
707 FOR_EACH_VEC_ELT (stmts, i, stmt)
kono
parents: 67
diff changeset
708 {
kono
parents: 67
diff changeset
709 struct vertex *v = &(rdg->vertices[i]);
kono
parents: 67
diff changeset
710
kono
parents: 67
diff changeset
711 /* Record statement to vertex mapping. */
kono
parents: 67
diff changeset
712 gimple_set_uid (stmt, i);
kono
parents: 67
diff changeset
713
kono
parents: 67
diff changeset
714 v->data = XNEW (struct rdg_vertex);
kono
parents: 67
diff changeset
715 RDGV_STMT (v) = stmt;
kono
parents: 67
diff changeset
716 RDGV_DATAREFS (v).create (0);
kono
parents: 67
diff changeset
717 RDGV_HAS_MEM_WRITE (v) = false;
kono
parents: 67
diff changeset
718 RDGV_HAS_MEM_READS (v) = false;
kono
parents: 67
diff changeset
719 if (gimple_code (stmt) == GIMPLE_PHI)
kono
parents: 67
diff changeset
720 continue;
kono
parents: 67
diff changeset
721
kono
parents: 67
diff changeset
722 unsigned drp = datarefs_vec.length ();
kono
parents: 67
diff changeset
723 if (!find_data_references_in_stmt (loop, stmt, &datarefs_vec))
kono
parents: 67
diff changeset
724 return false;
kono
parents: 67
diff changeset
725 for (unsigned j = drp; j < datarefs_vec.length (); ++j)
kono
parents: 67
diff changeset
726 {
kono
parents: 67
diff changeset
727 data_reference_p dr = datarefs_vec[j];
kono
parents: 67
diff changeset
728 if (DR_IS_READ (dr))
kono
parents: 67
diff changeset
729 RDGV_HAS_MEM_READS (v) = true;
kono
parents: 67
diff changeset
730 else
kono
parents: 67
diff changeset
731 RDGV_HAS_MEM_WRITE (v) = true;
kono
parents: 67
diff changeset
732 RDGV_DATAREFS (v).safe_push (dr);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
733 has_nonaddressable_dataref_p |= may_be_nonaddressable_p (dr->ref);
111
kono
parents: 67
diff changeset
734 }
kono
parents: 67
diff changeset
735 }
kono
parents: 67
diff changeset
736 return true;
kono
parents: 67
diff changeset
737 }
kono
parents: 67
diff changeset
738
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
739 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
740 loop_distribution::stmts_from_loop (class loop *loop, vec<gimple *> *stmts)
111
kono
parents: 67
diff changeset
741 {
kono
parents: 67
diff changeset
742 unsigned int i;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
743 basic_block *bbs = get_loop_body_in_custom_order (loop, this, bb_top_order_cmp_r);
111
kono
parents: 67
diff changeset
744
kono
parents: 67
diff changeset
745 for (i = 0; i < loop->num_nodes; i++)
kono
parents: 67
diff changeset
746 {
kono
parents: 67
diff changeset
747 basic_block bb = bbs[i];
kono
parents: 67
diff changeset
748
kono
parents: 67
diff changeset
749 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
kono
parents: 67
diff changeset
750 gsi_next (&bsi))
kono
parents: 67
diff changeset
751 if (!virtual_operand_p (gimple_phi_result (bsi.phi ())))
kono
parents: 67
diff changeset
752 stmts->safe_push (bsi.phi ());
kono
parents: 67
diff changeset
753
kono
parents: 67
diff changeset
754 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
kono
parents: 67
diff changeset
755 gsi_next (&bsi))
kono
parents: 67
diff changeset
756 {
kono
parents: 67
diff changeset
757 gimple *stmt = gsi_stmt (bsi);
kono
parents: 67
diff changeset
758 if (gimple_code (stmt) != GIMPLE_LABEL && !is_gimple_debug (stmt))
kono
parents: 67
diff changeset
759 stmts->safe_push (stmt);
kono
parents: 67
diff changeset
760 }
kono
parents: 67
diff changeset
761 }
kono
parents: 67
diff changeset
762
kono
parents: 67
diff changeset
763 free (bbs);
kono
parents: 67
diff changeset
764 }
kono
parents: 67
diff changeset
765
kono
parents: 67
diff changeset
766 /* Free the reduced dependence graph RDG. */
kono
parents: 67
diff changeset
767
kono
parents: 67
diff changeset
768 static void
kono
parents: 67
diff changeset
769 free_rdg (struct graph *rdg)
kono
parents: 67
diff changeset
770 {
kono
parents: 67
diff changeset
771 int i;
kono
parents: 67
diff changeset
772
kono
parents: 67
diff changeset
773 for (i = 0; i < rdg->n_vertices; i++)
kono
parents: 67
diff changeset
774 {
kono
parents: 67
diff changeset
775 struct vertex *v = &(rdg->vertices[i]);
kono
parents: 67
diff changeset
776 struct graph_edge *e;
kono
parents: 67
diff changeset
777
kono
parents: 67
diff changeset
778 for (e = v->succ; e; e = e->succ_next)
kono
parents: 67
diff changeset
779 free (e->data);
kono
parents: 67
diff changeset
780
kono
parents: 67
diff changeset
781 if (v->data)
kono
parents: 67
diff changeset
782 {
kono
parents: 67
diff changeset
783 gimple_set_uid (RDGV_STMT (v), -1);
kono
parents: 67
diff changeset
784 (RDGV_DATAREFS (v)).release ();
kono
parents: 67
diff changeset
785 free (v->data);
kono
parents: 67
diff changeset
786 }
kono
parents: 67
diff changeset
787 }
kono
parents: 67
diff changeset
788
kono
parents: 67
diff changeset
789 free_graph (rdg);
kono
parents: 67
diff changeset
790 }
kono
parents: 67
diff changeset
791
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
792 struct graph *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
793 loop_distribution::build_rdg (class loop *loop, control_dependences *cd)
111
kono
parents: 67
diff changeset
794 {
kono
parents: 67
diff changeset
795 struct graph *rdg;
kono
parents: 67
diff changeset
796
kono
parents: 67
diff changeset
797 /* Create the RDG vertices from the stmts of the loop nest. */
kono
parents: 67
diff changeset
798 auto_vec<gimple *, 10> stmts;
kono
parents: 67
diff changeset
799 stmts_from_loop (loop, &stmts);
kono
parents: 67
diff changeset
800 rdg = new_graph (stmts.length ());
kono
parents: 67
diff changeset
801 if (!create_rdg_vertices (rdg, stmts, loop))
kono
parents: 67
diff changeset
802 {
kono
parents: 67
diff changeset
803 free_rdg (rdg);
kono
parents: 67
diff changeset
804 return NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
805 }
111
kono
parents: 67
diff changeset
806 stmts.release ();
kono
parents: 67
diff changeset
807
kono
parents: 67
diff changeset
808 create_rdg_flow_edges (rdg);
kono
parents: 67
diff changeset
809 if (cd)
kono
parents: 67
diff changeset
810 create_rdg_cd_edges (rdg, cd, loop);
kono
parents: 67
diff changeset
811
kono
parents: 67
diff changeset
812 return rdg;
kono
parents: 67
diff changeset
813 }
kono
parents: 67
diff changeset
814
kono
parents: 67
diff changeset
815
kono
parents: 67
diff changeset
816 /* Allocate and initialize a partition from BITMAP. */
kono
parents: 67
diff changeset
817
kono
parents: 67
diff changeset
818 static partition *
kono
parents: 67
diff changeset
819 partition_alloc (void)
kono
parents: 67
diff changeset
820 {
kono
parents: 67
diff changeset
821 partition *partition = XCNEW (struct partition);
kono
parents: 67
diff changeset
822 partition->stmts = BITMAP_ALLOC (NULL);
kono
parents: 67
diff changeset
823 partition->reduction_p = false;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
824 partition->loc = UNKNOWN_LOCATION;
111
kono
parents: 67
diff changeset
825 partition->kind = PKIND_NORMAL;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
826 partition->type = PTYPE_PARALLEL;
111
kono
parents: 67
diff changeset
827 partition->datarefs = BITMAP_ALLOC (NULL);
kono
parents: 67
diff changeset
828 return partition;
kono
parents: 67
diff changeset
829 }
kono
parents: 67
diff changeset
830
kono
parents: 67
diff changeset
831 /* Free PARTITION. */
kono
parents: 67
diff changeset
832
kono
parents: 67
diff changeset
833 static void
kono
parents: 67
diff changeset
834 partition_free (partition *partition)
kono
parents: 67
diff changeset
835 {
kono
parents: 67
diff changeset
836 BITMAP_FREE (partition->stmts);
kono
parents: 67
diff changeset
837 BITMAP_FREE (partition->datarefs);
kono
parents: 67
diff changeset
838 if (partition->builtin)
kono
parents: 67
diff changeset
839 free (partition->builtin);
kono
parents: 67
diff changeset
840
kono
parents: 67
diff changeset
841 free (partition);
kono
parents: 67
diff changeset
842 }
kono
parents: 67
diff changeset
843
kono
parents: 67
diff changeset
844 /* Returns true if the partition can be generated as a builtin. */
kono
parents: 67
diff changeset
845
kono
parents: 67
diff changeset
846 static bool
kono
parents: 67
diff changeset
847 partition_builtin_p (partition *partition)
kono
parents: 67
diff changeset
848 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
849 return partition->kind > PKIND_PARTIAL_MEMSET;
111
kono
parents: 67
diff changeset
850 }
kono
parents: 67
diff changeset
851
kono
parents: 67
diff changeset
852 /* Returns true if the partition contains a reduction. */
kono
parents: 67
diff changeset
853
kono
parents: 67
diff changeset
854 static bool
kono
parents: 67
diff changeset
855 partition_reduction_p (partition *partition)
kono
parents: 67
diff changeset
856 {
kono
parents: 67
diff changeset
857 return partition->reduction_p;
kono
parents: 67
diff changeset
858 }
kono
parents: 67
diff changeset
859
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
860 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
861 loop_distribution::partition_merge_into (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
862 partition *dest, partition *partition, enum fuse_type ft)
111
kono
parents: 67
diff changeset
863 {
kono
parents: 67
diff changeset
864 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
865 {
kono
parents: 67
diff changeset
866 fprintf (dump_file, "Fuse partitions because %s:\n", fuse_message[ft]);
kono
parents: 67
diff changeset
867 fprintf (dump_file, " Part 1: ");
kono
parents: 67
diff changeset
868 dump_bitmap (dump_file, dest->stmts);
kono
parents: 67
diff changeset
869 fprintf (dump_file, " Part 2: ");
kono
parents: 67
diff changeset
870 dump_bitmap (dump_file, partition->stmts);
kono
parents: 67
diff changeset
871 }
kono
parents: 67
diff changeset
872
kono
parents: 67
diff changeset
873 dest->kind = PKIND_NORMAL;
kono
parents: 67
diff changeset
874 if (dest->type == PTYPE_PARALLEL)
kono
parents: 67
diff changeset
875 dest->type = partition->type;
kono
parents: 67
diff changeset
876
kono
parents: 67
diff changeset
877 bitmap_ior_into (dest->stmts, partition->stmts);
kono
parents: 67
diff changeset
878 if (partition_reduction_p (partition))
kono
parents: 67
diff changeset
879 dest->reduction_p = true;
kono
parents: 67
diff changeset
880
kono
parents: 67
diff changeset
881 /* Further check if any data dependence prevents us from executing the
kono
parents: 67
diff changeset
882 new partition parallelly. */
kono
parents: 67
diff changeset
883 if (dest->type == PTYPE_PARALLEL && rdg != NULL)
kono
parents: 67
diff changeset
884 update_type_for_merge (rdg, dest, partition);
kono
parents: 67
diff changeset
885
kono
parents: 67
diff changeset
886 bitmap_ior_into (dest->datarefs, partition->datarefs);
kono
parents: 67
diff changeset
887 }
kono
parents: 67
diff changeset
888
kono
parents: 67
diff changeset
889
kono
parents: 67
diff changeset
890 /* Returns true when DEF is an SSA_NAME defined in LOOP and used after
kono
parents: 67
diff changeset
891 the LOOP. */
kono
parents: 67
diff changeset
892
kono
parents: 67
diff changeset
893 static bool
kono
parents: 67
diff changeset
894 ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
kono
parents: 67
diff changeset
895 {
kono
parents: 67
diff changeset
896 imm_use_iterator imm_iter;
kono
parents: 67
diff changeset
897 use_operand_p use_p;
kono
parents: 67
diff changeset
898
kono
parents: 67
diff changeset
899 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def)
kono
parents: 67
diff changeset
900 {
kono
parents: 67
diff changeset
901 if (is_gimple_debug (USE_STMT (use_p)))
kono
parents: 67
diff changeset
902 continue;
kono
parents: 67
diff changeset
903
kono
parents: 67
diff changeset
904 basic_block use_bb = gimple_bb (USE_STMT (use_p));
kono
parents: 67
diff changeset
905 if (!flow_bb_inside_loop_p (loop, use_bb))
kono
parents: 67
diff changeset
906 return true;
kono
parents: 67
diff changeset
907 }
kono
parents: 67
diff changeset
908
kono
parents: 67
diff changeset
909 return false;
kono
parents: 67
diff changeset
910 }
kono
parents: 67
diff changeset
911
kono
parents: 67
diff changeset
912 /* Returns true when STMT defines a scalar variable used after the
kono
parents: 67
diff changeset
913 loop LOOP. */
kono
parents: 67
diff changeset
914
kono
parents: 67
diff changeset
915 static bool
kono
parents: 67
diff changeset
916 stmt_has_scalar_dependences_outside_loop (loop_p loop, gimple *stmt)
kono
parents: 67
diff changeset
917 {
kono
parents: 67
diff changeset
918 def_operand_p def_p;
kono
parents: 67
diff changeset
919 ssa_op_iter op_iter;
kono
parents: 67
diff changeset
920
kono
parents: 67
diff changeset
921 if (gimple_code (stmt) == GIMPLE_PHI)
kono
parents: 67
diff changeset
922 return ssa_name_has_uses_outside_loop_p (gimple_phi_result (stmt), loop);
kono
parents: 67
diff changeset
923
kono
parents: 67
diff changeset
924 FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
kono
parents: 67
diff changeset
925 if (ssa_name_has_uses_outside_loop_p (DEF_FROM_PTR (def_p), loop))
kono
parents: 67
diff changeset
926 return true;
kono
parents: 67
diff changeset
927
kono
parents: 67
diff changeset
928 return false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
929 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
930
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
931 /* Return a copy of LOOP placed before LOOP. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
932
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
933 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
934 copy_loop_before (class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
935 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
936 class loop *res;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
937 edge preheader = loop_preheader_edge (loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
938
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
939 initialize_original_copy_tables ();
111
kono
parents: 67
diff changeset
940 res = slpeel_tree_duplicate_loop_to_edge_cfg (loop, NULL, preheader);
kono
parents: 67
diff changeset
941 gcc_assert (res != NULL);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
942 free_original_copy_tables ();
111
kono
parents: 67
diff changeset
943 delete_update_ssa ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
944
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
945 return res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
946 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948 /* Creates an empty basic block after LOOP. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
949
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
950 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
951 create_bb_after_loop (class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
952 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
953 edge exit = single_exit (loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
954
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
955 if (!exit)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
956 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
957
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
958 split_edge (exit);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
961 /* Generate code for PARTITION from the code in LOOP. The loop is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
962 copied when COPY_P is true. All the statements not flagged in the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
963 PARTITION bitmap are removed from the loop or from its copy. The
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964 statements are indexed in sequence inside a basic block, and the
111
kono
parents: 67
diff changeset
965 basic blocks of a loop are taken in dom order. */
kono
parents: 67
diff changeset
966
kono
parents: 67
diff changeset
967 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
968 generate_loops_for_partition (class loop *loop, partition *partition,
111
kono
parents: 67
diff changeset
969 bool copy_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
970 {
111
kono
parents: 67
diff changeset
971 unsigned i;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
972 basic_block *bbs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
973
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
974 if (copy_p)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
975 {
111
kono
parents: 67
diff changeset
976 int orig_loop_num = loop->orig_loop_num;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977 loop = copy_loop_before (loop);
111
kono
parents: 67
diff changeset
978 gcc_assert (loop != NULL);
kono
parents: 67
diff changeset
979 loop->orig_loop_num = orig_loop_num;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
980 create_preheader (loop, CP_SIMPLE_PREHEADERS);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
981 create_bb_after_loop (loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
982 }
111
kono
parents: 67
diff changeset
983 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
984 {
111
kono
parents: 67
diff changeset
985 /* Origin number is set to the new versioned loop's num. */
kono
parents: 67
diff changeset
986 gcc_assert (loop->orig_loop_num != loop->num);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
987 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
988
111
kono
parents: 67
diff changeset
989 /* Remove stmts not in the PARTITION bitmap. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
990 bbs = get_loop_body_in_dom_order (loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
991
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
992 if (MAY_HAVE_DEBUG_BIND_STMTS)
111
kono
parents: 67
diff changeset
993 for (i = 0; i < loop->num_nodes; i++)
kono
parents: 67
diff changeset
994 {
kono
parents: 67
diff changeset
995 basic_block bb = bbs[i];
kono
parents: 67
diff changeset
996
kono
parents: 67
diff changeset
997 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
kono
parents: 67
diff changeset
998 gsi_next (&bsi))
kono
parents: 67
diff changeset
999 {
kono
parents: 67
diff changeset
1000 gphi *phi = bsi.phi ();
kono
parents: 67
diff changeset
1001 if (!virtual_operand_p (gimple_phi_result (phi))
kono
parents: 67
diff changeset
1002 && !bitmap_bit_p (partition->stmts, gimple_uid (phi)))
kono
parents: 67
diff changeset
1003 reset_debug_uses (phi);
kono
parents: 67
diff changeset
1004 }
kono
parents: 67
diff changeset
1005
kono
parents: 67
diff changeset
1006 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
kono
parents: 67
diff changeset
1007 {
kono
parents: 67
diff changeset
1008 gimple *stmt = gsi_stmt (bsi);
kono
parents: 67
diff changeset
1009 if (gimple_code (stmt) != GIMPLE_LABEL
kono
parents: 67
diff changeset
1010 && !is_gimple_debug (stmt)
kono
parents: 67
diff changeset
1011 && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
kono
parents: 67
diff changeset
1012 reset_debug_uses (stmt);
kono
parents: 67
diff changeset
1013 }
kono
parents: 67
diff changeset
1014 }
kono
parents: 67
diff changeset
1015
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1016 for (i = 0; i < loop->num_nodes; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1017 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1018 basic_block bb = bbs[i];
111
kono
parents: 67
diff changeset
1019 edge inner_exit = NULL;
kono
parents: 67
diff changeset
1020
kono
parents: 67
diff changeset
1021 if (loop != bb->loop_father)
kono
parents: 67
diff changeset
1022 inner_exit = single_exit (bb->loop_father);
kono
parents: 67
diff changeset
1023
kono
parents: 67
diff changeset
1024 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);)
kono
parents: 67
diff changeset
1025 {
kono
parents: 67
diff changeset
1026 gphi *phi = bsi.phi ();
kono
parents: 67
diff changeset
1027 if (!virtual_operand_p (gimple_phi_result (phi))
kono
parents: 67
diff changeset
1028 && !bitmap_bit_p (partition->stmts, gimple_uid (phi)))
kono
parents: 67
diff changeset
1029 remove_phi_node (&bsi, true);
kono
parents: 67
diff changeset
1030 else
kono
parents: 67
diff changeset
1031 gsi_next (&bsi);
kono
parents: 67
diff changeset
1032 }
kono
parents: 67
diff changeset
1033
kono
parents: 67
diff changeset
1034 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1035 {
111
kono
parents: 67
diff changeset
1036 gimple *stmt = gsi_stmt (bsi);
kono
parents: 67
diff changeset
1037 if (gimple_code (stmt) != GIMPLE_LABEL
kono
parents: 67
diff changeset
1038 && !is_gimple_debug (stmt)
kono
parents: 67
diff changeset
1039 && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1040 {
111
kono
parents: 67
diff changeset
1041 /* In distribution of loop nest, if bb is inner loop's exit_bb,
kono
parents: 67
diff changeset
1042 we choose its exit edge/path in order to avoid generating
kono
parents: 67
diff changeset
1043 infinite loop. For all other cases, we choose an arbitrary
kono
parents: 67
diff changeset
1044 path through the empty CFG part that this unnecessary
kono
parents: 67
diff changeset
1045 control stmt controls. */
kono
parents: 67
diff changeset
1046 if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
kono
parents: 67
diff changeset
1047 {
kono
parents: 67
diff changeset
1048 if (inner_exit && inner_exit->flags & EDGE_TRUE_VALUE)
kono
parents: 67
diff changeset
1049 gimple_cond_make_true (cond_stmt);
kono
parents: 67
diff changeset
1050 else
kono
parents: 67
diff changeset
1051 gimple_cond_make_false (cond_stmt);
kono
parents: 67
diff changeset
1052 update_stmt (stmt);
kono
parents: 67
diff changeset
1053 }
kono
parents: 67
diff changeset
1054 else if (gimple_code (stmt) == GIMPLE_SWITCH)
kono
parents: 67
diff changeset
1055 {
kono
parents: 67
diff changeset
1056 gswitch *switch_stmt = as_a <gswitch *> (stmt);
kono
parents: 67
diff changeset
1057 gimple_switch_set_index
kono
parents: 67
diff changeset
1058 (switch_stmt, CASE_LOW (gimple_switch_label (switch_stmt, 1)));
kono
parents: 67
diff changeset
1059 update_stmt (stmt);
kono
parents: 67
diff changeset
1060 }
kono
parents: 67
diff changeset
1061 else
kono
parents: 67
diff changeset
1062 {
kono
parents: 67
diff changeset
1063 unlink_stmt_vdef (stmt);
kono
parents: 67
diff changeset
1064 gsi_remove (&bsi, true);
kono
parents: 67
diff changeset
1065 release_defs (stmt);
kono
parents: 67
diff changeset
1066 continue;
kono
parents: 67
diff changeset
1067 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1068 }
111
kono
parents: 67
diff changeset
1069 gsi_next (&bsi);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1070 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1071 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1072
111
kono
parents: 67
diff changeset
1073 free (bbs);
kono
parents: 67
diff changeset
1074 }
kono
parents: 67
diff changeset
1075
kono
parents: 67
diff changeset
1076 /* If VAL memory representation contains the same value in all bytes,
kono
parents: 67
diff changeset
1077 return that value, otherwise return -1.
kono
parents: 67
diff changeset
1078 E.g. for 0x24242424 return 0x24, for IEEE double
kono
parents: 67
diff changeset
1079 747708026454360457216.0 return 0x44, etc. */
kono
parents: 67
diff changeset
1080
kono
parents: 67
diff changeset
1081 static int
kono
parents: 67
diff changeset
1082 const_with_all_bytes_same (tree val)
kono
parents: 67
diff changeset
1083 {
kono
parents: 67
diff changeset
1084 unsigned char buf[64];
kono
parents: 67
diff changeset
1085 int i, len;
kono
parents: 67
diff changeset
1086
kono
parents: 67
diff changeset
1087 if (integer_zerop (val)
kono
parents: 67
diff changeset
1088 || (TREE_CODE (val) == CONSTRUCTOR
kono
parents: 67
diff changeset
1089 && !TREE_CLOBBER_P (val)
kono
parents: 67
diff changeset
1090 && CONSTRUCTOR_NELTS (val) == 0))
kono
parents: 67
diff changeset
1091 return 0;
kono
parents: 67
diff changeset
1092
kono
parents: 67
diff changeset
1093 if (real_zerop (val))
kono
parents: 67
diff changeset
1094 {
kono
parents: 67
diff changeset
1095 /* Only return 0 for +0.0, not for -0.0, which doesn't have
kono
parents: 67
diff changeset
1096 an all bytes same memory representation. Don't transform
kono
parents: 67
diff changeset
1097 -0.0 stores into +0.0 even for !HONOR_SIGNED_ZEROS. */
kono
parents: 67
diff changeset
1098 switch (TREE_CODE (val))
kono
parents: 67
diff changeset
1099 {
kono
parents: 67
diff changeset
1100 case REAL_CST:
kono
parents: 67
diff changeset
1101 if (!real_isneg (TREE_REAL_CST_PTR (val)))
kono
parents: 67
diff changeset
1102 return 0;
kono
parents: 67
diff changeset
1103 break;
kono
parents: 67
diff changeset
1104 case COMPLEX_CST:
kono
parents: 67
diff changeset
1105 if (!const_with_all_bytes_same (TREE_REALPART (val))
kono
parents: 67
diff changeset
1106 && !const_with_all_bytes_same (TREE_IMAGPART (val)))
kono
parents: 67
diff changeset
1107 return 0;
kono
parents: 67
diff changeset
1108 break;
kono
parents: 67
diff changeset
1109 case VECTOR_CST:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1110 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1111 unsigned int count = vector_cst_encoded_nelts (val);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1112 unsigned int j;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1113 for (j = 0; j < count; ++j)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1114 if (const_with_all_bytes_same (VECTOR_CST_ENCODED_ELT (val, j)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1115 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1116 if (j == count)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1117 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1118 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1119 }
111
kono
parents: 67
diff changeset
1120 default:
kono
parents: 67
diff changeset
1121 break;
kono
parents: 67
diff changeset
1122 }
kono
parents: 67
diff changeset
1123 }
kono
parents: 67
diff changeset
1124
kono
parents: 67
diff changeset
1125 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
kono
parents: 67
diff changeset
1126 return -1;
kono
parents: 67
diff changeset
1127
kono
parents: 67
diff changeset
1128 len = native_encode_expr (val, buf, sizeof (buf));
kono
parents: 67
diff changeset
1129 if (len == 0)
kono
parents: 67
diff changeset
1130 return -1;
kono
parents: 67
diff changeset
1131 for (i = 1; i < len; i++)
kono
parents: 67
diff changeset
1132 if (buf[i] != buf[0])
kono
parents: 67
diff changeset
1133 return -1;
kono
parents: 67
diff changeset
1134 return buf[0];
kono
parents: 67
diff changeset
1135 }
kono
parents: 67
diff changeset
1136
kono
parents: 67
diff changeset
1137 /* Generate a call to memset for PARTITION in LOOP. */
kono
parents: 67
diff changeset
1138
kono
parents: 67
diff changeset
1139 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1140 generate_memset_builtin (class loop *loop, partition *partition)
111
kono
parents: 67
diff changeset
1141 {
kono
parents: 67
diff changeset
1142 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
1143 tree mem, fn, nb_bytes;
kono
parents: 67
diff changeset
1144 tree val;
kono
parents: 67
diff changeset
1145 struct builtin_info *builtin = partition->builtin;
kono
parents: 67
diff changeset
1146 gimple *fn_call;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1147
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1148 /* The new statements will be placed before LOOP. */
111
kono
parents: 67
diff changeset
1149 gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
kono
parents: 67
diff changeset
1150
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1151 nb_bytes = rewrite_to_non_trapping_overflow (builtin->size);
111
kono
parents: 67
diff changeset
1152 nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
kono
parents: 67
diff changeset
1153 false, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1154 mem = builtin->dst_base;
kono
parents: 67
diff changeset
1155 mem = force_gimple_operand_gsi (&gsi, mem, true, NULL_TREE,
kono
parents: 67
diff changeset
1156 false, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1157
kono
parents: 67
diff changeset
1158 /* This exactly matches the pattern recognition in classify_partition. */
kono
parents: 67
diff changeset
1159 val = gimple_assign_rhs1 (DR_STMT (builtin->dst_dr));
kono
parents: 67
diff changeset
1160 /* Handle constants like 0x15151515 and similarly
kono
parents: 67
diff changeset
1161 floating point constants etc. where all bytes are the same. */
kono
parents: 67
diff changeset
1162 int bytev = const_with_all_bytes_same (val);
kono
parents: 67
diff changeset
1163 if (bytev != -1)
kono
parents: 67
diff changeset
1164 val = build_int_cst (integer_type_node, bytev);
kono
parents: 67
diff changeset
1165 else if (TREE_CODE (val) == INTEGER_CST)
kono
parents: 67
diff changeset
1166 val = fold_convert (integer_type_node, val);
kono
parents: 67
diff changeset
1167 else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val)))
kono
parents: 67
diff changeset
1168 {
kono
parents: 67
diff changeset
1169 tree tem = make_ssa_name (integer_type_node);
kono
parents: 67
diff changeset
1170 gimple *cstmt = gimple_build_assign (tem, NOP_EXPR, val);
kono
parents: 67
diff changeset
1171 gsi_insert_after (&gsi, cstmt, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1172 val = tem;
kono
parents: 67
diff changeset
1173 }
kono
parents: 67
diff changeset
1174
kono
parents: 67
diff changeset
1175 fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
kono
parents: 67
diff changeset
1176 fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1177 gimple_set_location (fn_call, partition->loc);
111
kono
parents: 67
diff changeset
1178 gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1179 fold_stmt (&gsi);
111
kono
parents: 67
diff changeset
1180
kono
parents: 67
diff changeset
1181 if (dump_file && (dump_flags & TDF_DETAILS))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1182 {
111
kono
parents: 67
diff changeset
1183 fprintf (dump_file, "generated memset");
kono
parents: 67
diff changeset
1184 if (bytev == 0)
kono
parents: 67
diff changeset
1185 fprintf (dump_file, " zero\n");
kono
parents: 67
diff changeset
1186 else
kono
parents: 67
diff changeset
1187 fprintf (dump_file, "\n");
kono
parents: 67
diff changeset
1188 }
kono
parents: 67
diff changeset
1189 }
kono
parents: 67
diff changeset
1190
kono
parents: 67
diff changeset
1191 /* Generate a call to memcpy for PARTITION in LOOP. */
kono
parents: 67
diff changeset
1192
kono
parents: 67
diff changeset
1193 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1194 generate_memcpy_builtin (class loop *loop, partition *partition)
111
kono
parents: 67
diff changeset
1195 {
kono
parents: 67
diff changeset
1196 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
1197 gimple *fn_call;
kono
parents: 67
diff changeset
1198 tree dest, src, fn, nb_bytes;
kono
parents: 67
diff changeset
1199 enum built_in_function kind;
kono
parents: 67
diff changeset
1200 struct builtin_info *builtin = partition->builtin;
kono
parents: 67
diff changeset
1201
kono
parents: 67
diff changeset
1202 /* The new statements will be placed before LOOP. */
kono
parents: 67
diff changeset
1203 gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
kono
parents: 67
diff changeset
1204
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1205 nb_bytes = rewrite_to_non_trapping_overflow (builtin->size);
111
kono
parents: 67
diff changeset
1206 nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
kono
parents: 67
diff changeset
1207 false, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1208 dest = builtin->dst_base;
kono
parents: 67
diff changeset
1209 src = builtin->src_base;
kono
parents: 67
diff changeset
1210 if (partition->kind == PKIND_MEMCPY
kono
parents: 67
diff changeset
1211 || ! ptr_derefs_may_alias_p (dest, src))
kono
parents: 67
diff changeset
1212 kind = BUILT_IN_MEMCPY;
kono
parents: 67
diff changeset
1213 else
kono
parents: 67
diff changeset
1214 kind = BUILT_IN_MEMMOVE;
kono
parents: 67
diff changeset
1215
kono
parents: 67
diff changeset
1216 dest = force_gimple_operand_gsi (&gsi, dest, true, NULL_TREE,
kono
parents: 67
diff changeset
1217 false, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1218 src = force_gimple_operand_gsi (&gsi, src, true, NULL_TREE,
kono
parents: 67
diff changeset
1219 false, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1220 fn = build_fold_addr_expr (builtin_decl_implicit (kind));
kono
parents: 67
diff changeset
1221 fn_call = gimple_build_call (fn, 3, dest, src, nb_bytes);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1222 gimple_set_location (fn_call, partition->loc);
111
kono
parents: 67
diff changeset
1223 gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1224 fold_stmt (&gsi);
111
kono
parents: 67
diff changeset
1225
kono
parents: 67
diff changeset
1226 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
1227 {
kono
parents: 67
diff changeset
1228 if (kind == BUILT_IN_MEMCPY)
kono
parents: 67
diff changeset
1229 fprintf (dump_file, "generated memcpy\n");
kono
parents: 67
diff changeset
1230 else
kono
parents: 67
diff changeset
1231 fprintf (dump_file, "generated memmove\n");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1232 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1233 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1234
111
kono
parents: 67
diff changeset
1235 /* Remove and destroy the loop LOOP. */
kono
parents: 67
diff changeset
1236
kono
parents: 67
diff changeset
1237 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1238 destroy_loop (class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1239 {
111
kono
parents: 67
diff changeset
1240 unsigned nbbs = loop->num_nodes;
kono
parents: 67
diff changeset
1241 edge exit = single_exit (loop);
kono
parents: 67
diff changeset
1242 basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest;
kono
parents: 67
diff changeset
1243 basic_block *bbs;
kono
parents: 67
diff changeset
1244 unsigned i;
kono
parents: 67
diff changeset
1245
kono
parents: 67
diff changeset
1246 bbs = get_loop_body_in_dom_order (loop);
kono
parents: 67
diff changeset
1247
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1248 gimple_stmt_iterator dst_gsi = gsi_after_labels (exit->dest);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1249 bool safe_p = single_pred_p (exit->dest);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1250 for (unsigned i = 0; i < nbbs; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1251 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1252 /* We have made sure to not leave any dangling uses of SSA
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1253 names defined in the loop. With the exception of virtuals.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1254 Make sure we replace all uses of virtual defs that will remain
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1255 outside of the loop with the bare symbol as delete_basic_block
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1256 will release them. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1257 for (gphi_iterator gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1258 gsi_next (&gsi))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1259 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1260 gphi *phi = gsi.phi ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1261 if (virtual_operand_p (gimple_phi_result (phi)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1262 mark_virtual_phi_result_for_renaming (phi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1263 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1264 for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1265 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1266 gimple *stmt = gsi_stmt (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1267 tree vdef = gimple_vdef (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1268 if (vdef && TREE_CODE (vdef) == SSA_NAME)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1269 mark_virtual_operand_for_renaming (vdef);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1270 /* Also move and eventually reset debug stmts. We can leave
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1271 constant values in place in case the stmt dominates the exit.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1272 ??? Non-constant values from the last iteration can be
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1273 replaced with final values if we can compute them. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1274 if (gimple_debug_bind_p (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1275 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1276 tree val = gimple_debug_bind_get_value (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1277 gsi_move_before (&gsi, &dst_gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1278 if (val
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1279 && (!safe_p
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1280 || !is_gimple_min_invariant (val)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1281 || !dominated_by_p (CDI_DOMINATORS, exit->src, bbs[i])))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1282 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1283 gimple_debug_bind_reset_value (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1284 update_stmt (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1285 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1286 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1287 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1288 gsi_next (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1289 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1290 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1291
111
kono
parents: 67
diff changeset
1292 redirect_edge_pred (exit, src);
kono
parents: 67
diff changeset
1293 exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
kono
parents: 67
diff changeset
1294 exit->flags |= EDGE_FALLTHRU;
kono
parents: 67
diff changeset
1295 cancel_loop_tree (loop);
kono
parents: 67
diff changeset
1296 rescan_loop_exit (exit, false, true);
kono
parents: 67
diff changeset
1297
kono
parents: 67
diff changeset
1298 i = nbbs;
kono
parents: 67
diff changeset
1299 do
kono
parents: 67
diff changeset
1300 {
kono
parents: 67
diff changeset
1301 --i;
kono
parents: 67
diff changeset
1302 delete_basic_block (bbs[i]);
kono
parents: 67
diff changeset
1303 }
kono
parents: 67
diff changeset
1304 while (i != 0);
kono
parents: 67
diff changeset
1305
kono
parents: 67
diff changeset
1306 free (bbs);
kono
parents: 67
diff changeset
1307
kono
parents: 67
diff changeset
1308 set_immediate_dominator (CDI_DOMINATORS, dest,
kono
parents: 67
diff changeset
1309 recompute_dominator (CDI_DOMINATORS, dest));
kono
parents: 67
diff changeset
1310 }
kono
parents: 67
diff changeset
1311
kono
parents: 67
diff changeset
1312 /* Generates code for PARTITION. Return whether LOOP needs to be destroyed. */
kono
parents: 67
diff changeset
1313
kono
parents: 67
diff changeset
1314 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1315 generate_code_for_partition (class loop *loop,
111
kono
parents: 67
diff changeset
1316 partition *partition, bool copy_p)
kono
parents: 67
diff changeset
1317 {
kono
parents: 67
diff changeset
1318 switch (partition->kind)
kono
parents: 67
diff changeset
1319 {
kono
parents: 67
diff changeset
1320 case PKIND_NORMAL:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1321 case PKIND_PARTIAL_MEMSET:
111
kono
parents: 67
diff changeset
1322 /* Reductions all have to be in the last partition. */
kono
parents: 67
diff changeset
1323 gcc_assert (!partition_reduction_p (partition)
kono
parents: 67
diff changeset
1324 || !copy_p);
kono
parents: 67
diff changeset
1325 generate_loops_for_partition (loop, partition, copy_p);
kono
parents: 67
diff changeset
1326 return false;
kono
parents: 67
diff changeset
1327
kono
parents: 67
diff changeset
1328 case PKIND_MEMSET:
kono
parents: 67
diff changeset
1329 generate_memset_builtin (loop, partition);
kono
parents: 67
diff changeset
1330 break;
kono
parents: 67
diff changeset
1331
kono
parents: 67
diff changeset
1332 case PKIND_MEMCPY:
kono
parents: 67
diff changeset
1333 case PKIND_MEMMOVE:
kono
parents: 67
diff changeset
1334 generate_memcpy_builtin (loop, partition);
kono
parents: 67
diff changeset
1335 break;
kono
parents: 67
diff changeset
1336
kono
parents: 67
diff changeset
1337 default:
kono
parents: 67
diff changeset
1338 gcc_unreachable ();
kono
parents: 67
diff changeset
1339 }
kono
parents: 67
diff changeset
1340
kono
parents: 67
diff changeset
1341 /* Common tail for partitions we turn into a call. If this was the last
kono
parents: 67
diff changeset
1342 partition for which we generate code, we have to destroy the loop. */
kono
parents: 67
diff changeset
1343 if (!copy_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1344 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1345 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1346 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1347
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1348 data_dependence_relation *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1349 loop_distribution::get_data_dependence (struct graph *rdg, data_reference_p a,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1350 data_reference_p b)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1351 {
111
kono
parents: 67
diff changeset
1352 struct data_dependence_relation ent, **slot;
kono
parents: 67
diff changeset
1353 struct data_dependence_relation *ddr;
kono
parents: 67
diff changeset
1354
kono
parents: 67
diff changeset
1355 gcc_assert (DR_IS_WRITE (a) || DR_IS_WRITE (b));
kono
parents: 67
diff changeset
1356 gcc_assert (rdg_vertex_for_stmt (rdg, DR_STMT (a))
kono
parents: 67
diff changeset
1357 <= rdg_vertex_for_stmt (rdg, DR_STMT (b)));
kono
parents: 67
diff changeset
1358 ent.a = a;
kono
parents: 67
diff changeset
1359 ent.b = b;
kono
parents: 67
diff changeset
1360 slot = ddrs_table->find_slot (&ent, INSERT);
kono
parents: 67
diff changeset
1361 if (*slot == NULL)
kono
parents: 67
diff changeset
1362 {
kono
parents: 67
diff changeset
1363 ddr = initialize_data_dependence_relation (a, b, loop_nest);
kono
parents: 67
diff changeset
1364 compute_affine_dependence (ddr, loop_nest[0]);
kono
parents: 67
diff changeset
1365 *slot = ddr;
kono
parents: 67
diff changeset
1366 }
kono
parents: 67
diff changeset
1367
kono
parents: 67
diff changeset
1368 return *slot;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1369 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1370
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1371 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1372 loop_distribution::data_dep_in_cycle_p (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1373 data_reference_p dr1,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1374 data_reference_p dr2)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1375 {
111
kono
parents: 67
diff changeset
1376 struct data_dependence_relation *ddr;
kono
parents: 67
diff changeset
1377
kono
parents: 67
diff changeset
1378 /* Re-shuffle data-refs to be in topological order. */
kono
parents: 67
diff changeset
1379 if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
kono
parents: 67
diff changeset
1380 > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
kono
parents: 67
diff changeset
1381 std::swap (dr1, dr2);
kono
parents: 67
diff changeset
1382
kono
parents: 67
diff changeset
1383 ddr = get_data_dependence (rdg, dr1, dr2);
kono
parents: 67
diff changeset
1384
kono
parents: 67
diff changeset
1385 /* In case of no data dependence. */
kono
parents: 67
diff changeset
1386 if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
kono
parents: 67
diff changeset
1387 return false;
kono
parents: 67
diff changeset
1388 /* For unknown data dependence or known data dependence which can't be
kono
parents: 67
diff changeset
1389 expressed in classic distance vector, we check if it can be resolved
kono
parents: 67
diff changeset
1390 by runtime alias check. If yes, we still consider data dependence
kono
parents: 67
diff changeset
1391 as won't introduce data dependence cycle. */
kono
parents: 67
diff changeset
1392 else if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
kono
parents: 67
diff changeset
1393 || DDR_NUM_DIST_VECTS (ddr) == 0)
kono
parents: 67
diff changeset
1394 return !runtime_alias_check_p (ddr, NULL, true);
kono
parents: 67
diff changeset
1395 else if (DDR_NUM_DIST_VECTS (ddr) > 1)
kono
parents: 67
diff changeset
1396 return true;
kono
parents: 67
diff changeset
1397 else if (DDR_REVERSED_P (ddr)
kono
parents: 67
diff changeset
1398 || lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), 1))
kono
parents: 67
diff changeset
1399 return false;
kono
parents: 67
diff changeset
1400
kono
parents: 67
diff changeset
1401 return true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1402 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1403
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1404 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1405 loop_distribution::update_type_for_merge (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1406 partition *partition1,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1407 partition *partition2)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1408 {
111
kono
parents: 67
diff changeset
1409 unsigned i, j;
kono
parents: 67
diff changeset
1410 bitmap_iterator bi, bj;
kono
parents: 67
diff changeset
1411 data_reference_p dr1, dr2;
kono
parents: 67
diff changeset
1412
kono
parents: 67
diff changeset
1413 EXECUTE_IF_SET_IN_BITMAP (partition1->datarefs, 0, i, bi)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1414 {
111
kono
parents: 67
diff changeset
1415 unsigned start = (partition1 == partition2) ? i + 1 : 0;
kono
parents: 67
diff changeset
1416
kono
parents: 67
diff changeset
1417 dr1 = datarefs_vec[i];
kono
parents: 67
diff changeset
1418 EXECUTE_IF_SET_IN_BITMAP (partition2->datarefs, start, j, bj)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1419 {
111
kono
parents: 67
diff changeset
1420 dr2 = datarefs_vec[j];
kono
parents: 67
diff changeset
1421 if (DR_IS_READ (dr1) && DR_IS_READ (dr2))
kono
parents: 67
diff changeset
1422 continue;
kono
parents: 67
diff changeset
1423
kono
parents: 67
diff changeset
1424 /* Partition can only be executed sequentially if there is any
kono
parents: 67
diff changeset
1425 data dependence cycle. */
kono
parents: 67
diff changeset
1426 if (data_dep_in_cycle_p (rdg, dr1, dr2))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1427 {
111
kono
parents: 67
diff changeset
1428 partition1->type = PTYPE_SEQUENTIAL;
kono
parents: 67
diff changeset
1429 return;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1430 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1431 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1432 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1433 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1434
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1435 partition *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1436 loop_distribution::build_rdg_partition_for_vertex (struct graph *rdg, int v)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1437 {
111
kono
parents: 67
diff changeset
1438 partition *partition = partition_alloc ();
kono
parents: 67
diff changeset
1439 auto_vec<int, 3> nodes;
kono
parents: 67
diff changeset
1440 unsigned i, j;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1441 int x;
111
kono
parents: 67
diff changeset
1442 data_reference_p dr;
kono
parents: 67
diff changeset
1443
kono
parents: 67
diff changeset
1444 graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
kono
parents: 67
diff changeset
1445
kono
parents: 67
diff changeset
1446 FOR_EACH_VEC_ELT (nodes, i, x)
kono
parents: 67
diff changeset
1447 {
kono
parents: 67
diff changeset
1448 bitmap_set_bit (partition->stmts, x);
kono
parents: 67
diff changeset
1449
kono
parents: 67
diff changeset
1450 for (j = 0; RDG_DATAREFS (rdg, x).iterate (j, &dr); ++j)
kono
parents: 67
diff changeset
1451 {
kono
parents: 67
diff changeset
1452 unsigned idx = (unsigned) DR_INDEX (dr);
kono
parents: 67
diff changeset
1453 gcc_assert (idx < datarefs_vec.length ());
kono
parents: 67
diff changeset
1454
kono
parents: 67
diff changeset
1455 /* Partition can only be executed sequentially if there is any
kono
parents: 67
diff changeset
1456 unknown data reference. */
kono
parents: 67
diff changeset
1457 if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr)
kono
parents: 67
diff changeset
1458 || !DR_INIT (dr) || !DR_STEP (dr))
kono
parents: 67
diff changeset
1459 partition->type = PTYPE_SEQUENTIAL;
kono
parents: 67
diff changeset
1460
kono
parents: 67
diff changeset
1461 bitmap_set_bit (partition->datarefs, idx);
kono
parents: 67
diff changeset
1462 }
kono
parents: 67
diff changeset
1463 }
kono
parents: 67
diff changeset
1464
kono
parents: 67
diff changeset
1465 if (partition->type == PTYPE_SEQUENTIAL)
kono
parents: 67
diff changeset
1466 return partition;
kono
parents: 67
diff changeset
1467
kono
parents: 67
diff changeset
1468 /* Further check if any data dependence prevents us from executing the
kono
parents: 67
diff changeset
1469 partition parallelly. */
kono
parents: 67
diff changeset
1470 update_type_for_merge (rdg, partition, partition);
kono
parents: 67
diff changeset
1471
kono
parents: 67
diff changeset
1472 return partition;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1473 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1474
111
kono
parents: 67
diff changeset
1475 /* Given PARTITION of LOOP and RDG, record single load/store data references
kono
parents: 67
diff changeset
1476 for builtin partition in SRC_DR/DST_DR, return false if there is no such
kono
parents: 67
diff changeset
1477 data references. */
kono
parents: 67
diff changeset
1478
kono
parents: 67
diff changeset
1479 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1480 find_single_drs (class loop *loop, struct graph *rdg, partition *partition,
111
kono
parents: 67
diff changeset
1481 data_reference_p *dst_dr, data_reference_p *src_dr)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1482 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1483 unsigned i;
111
kono
parents: 67
diff changeset
1484 data_reference_p single_ld = NULL, single_st = NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1485 bitmap_iterator bi;
111
kono
parents: 67
diff changeset
1486
kono
parents: 67
diff changeset
1487 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1488 {
111
kono
parents: 67
diff changeset
1489 gimple *stmt = RDG_STMT (rdg, i);
kono
parents: 67
diff changeset
1490 data_reference_p dr;
kono
parents: 67
diff changeset
1491
kono
parents: 67
diff changeset
1492 if (gimple_code (stmt) == GIMPLE_PHI)
kono
parents: 67
diff changeset
1493 continue;
kono
parents: 67
diff changeset
1494
kono
parents: 67
diff changeset
1495 /* Any scalar stmts are ok. */
kono
parents: 67
diff changeset
1496 if (!gimple_vuse (stmt))
kono
parents: 67
diff changeset
1497 continue;
kono
parents: 67
diff changeset
1498
kono
parents: 67
diff changeset
1499 /* Otherwise just regular loads/stores. */
kono
parents: 67
diff changeset
1500 if (!gimple_assign_single_p (stmt))
kono
parents: 67
diff changeset
1501 return false;
kono
parents: 67
diff changeset
1502
kono
parents: 67
diff changeset
1503 /* But exactly one store and/or load. */
kono
parents: 67
diff changeset
1504 for (unsigned j = 0; RDG_DATAREFS (rdg, i).iterate (j, &dr); ++j)
kono
parents: 67
diff changeset
1505 {
kono
parents: 67
diff changeset
1506 tree type = TREE_TYPE (DR_REF (dr));
kono
parents: 67
diff changeset
1507
kono
parents: 67
diff changeset
1508 /* The memset, memcpy and memmove library calls are only
kono
parents: 67
diff changeset
1509 able to deal with generic address space. */
kono
parents: 67
diff changeset
1510 if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)))
kono
parents: 67
diff changeset
1511 return false;
kono
parents: 67
diff changeset
1512
kono
parents: 67
diff changeset
1513 if (DR_IS_READ (dr))
kono
parents: 67
diff changeset
1514 {
kono
parents: 67
diff changeset
1515 if (single_ld != NULL)
kono
parents: 67
diff changeset
1516 return false;
kono
parents: 67
diff changeset
1517 single_ld = dr;
kono
parents: 67
diff changeset
1518 }
kono
parents: 67
diff changeset
1519 else
kono
parents: 67
diff changeset
1520 {
kono
parents: 67
diff changeset
1521 if (single_st != NULL)
kono
parents: 67
diff changeset
1522 return false;
kono
parents: 67
diff changeset
1523 single_st = dr;
kono
parents: 67
diff changeset
1524 }
kono
parents: 67
diff changeset
1525 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1526 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1527
111
kono
parents: 67
diff changeset
1528 if (!single_st)
kono
parents: 67
diff changeset
1529 return false;
kono
parents: 67
diff changeset
1530
kono
parents: 67
diff changeset
1531 /* Bail out if this is a bitfield memory reference. */
kono
parents: 67
diff changeset
1532 if (TREE_CODE (DR_REF (single_st)) == COMPONENT_REF
kono
parents: 67
diff changeset
1533 && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_st), 1)))
kono
parents: 67
diff changeset
1534 return false;
kono
parents: 67
diff changeset
1535
kono
parents: 67
diff changeset
1536 /* Data reference must be executed exactly once per iteration of each
kono
parents: 67
diff changeset
1537 loop in the loop nest. We only need to check dominance information
kono
parents: 67
diff changeset
1538 against the outermost one in a perfect loop nest because a bb can't
kono
parents: 67
diff changeset
1539 dominate outermost loop's latch without dominating inner loop's. */
kono
parents: 67
diff changeset
1540 basic_block bb_st = gimple_bb (DR_STMT (single_st));
kono
parents: 67
diff changeset
1541 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_st))
kono
parents: 67
diff changeset
1542 return false;
kono
parents: 67
diff changeset
1543
kono
parents: 67
diff changeset
1544 if (single_ld)
kono
parents: 67
diff changeset
1545 {
kono
parents: 67
diff changeset
1546 gimple *store = DR_STMT (single_st), *load = DR_STMT (single_ld);
kono
parents: 67
diff changeset
1547 /* Direct aggregate copy or via an SSA name temporary. */
kono
parents: 67
diff changeset
1548 if (load != store
kono
parents: 67
diff changeset
1549 && gimple_assign_lhs (load) != gimple_assign_rhs1 (store))
kono
parents: 67
diff changeset
1550 return false;
kono
parents: 67
diff changeset
1551
kono
parents: 67
diff changeset
1552 /* Bail out if this is a bitfield memory reference. */
kono
parents: 67
diff changeset
1553 if (TREE_CODE (DR_REF (single_ld)) == COMPONENT_REF
kono
parents: 67
diff changeset
1554 && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_ld), 1)))
kono
parents: 67
diff changeset
1555 return false;
kono
parents: 67
diff changeset
1556
kono
parents: 67
diff changeset
1557 /* Load and store must be in the same loop nest. */
kono
parents: 67
diff changeset
1558 basic_block bb_ld = gimple_bb (DR_STMT (single_ld));
kono
parents: 67
diff changeset
1559 if (bb_st->loop_father != bb_ld->loop_father)
kono
parents: 67
diff changeset
1560 return false;
kono
parents: 67
diff changeset
1561
kono
parents: 67
diff changeset
1562 /* Data reference must be executed exactly once per iteration.
kono
parents: 67
diff changeset
1563 Same as single_st, we only need to check against the outermost
kono
parents: 67
diff changeset
1564 loop. */
kono
parents: 67
diff changeset
1565 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_ld))
kono
parents: 67
diff changeset
1566 return false;
kono
parents: 67
diff changeset
1567
kono
parents: 67
diff changeset
1568 edge e = single_exit (bb_st->loop_father);
kono
parents: 67
diff changeset
1569 bool dom_ld = dominated_by_p (CDI_DOMINATORS, e->src, bb_ld);
kono
parents: 67
diff changeset
1570 bool dom_st = dominated_by_p (CDI_DOMINATORS, e->src, bb_st);
kono
parents: 67
diff changeset
1571 if (dom_ld != dom_st)
kono
parents: 67
diff changeset
1572 return false;
kono
parents: 67
diff changeset
1573 }
kono
parents: 67
diff changeset
1574
kono
parents: 67
diff changeset
1575 *src_dr = single_ld;
kono
parents: 67
diff changeset
1576 *dst_dr = single_st;
kono
parents: 67
diff changeset
1577 return true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1578 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1579
111
kono
parents: 67
diff changeset
1580 /* Given data reference DR in LOOP_NEST, this function checks the enclosing
kono
parents: 67
diff changeset
1581 loops from inner to outer to see if loop's step equals to access size at
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1582 each level of loop. Return 2 if we can prove this at all level loops;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1583 record access base and size in BASE and SIZE; save loop's step at each
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1584 level of loop in STEPS if it is not null. For example:
111
kono
parents: 67
diff changeset
1585
kono
parents: 67
diff changeset
1586 int arr[100][100][100];
kono
parents: 67
diff changeset
1587 for (i = 0; i < 100; i++) ;steps[2] = 40000
kono
parents: 67
diff changeset
1588 for (j = 100; j > 0; j--) ;steps[1] = -400
kono
parents: 67
diff changeset
1589 for (k = 0; k < 100; k++) ;steps[0] = 4
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1590 arr[i][j - 1][k] = 0; ;base = &arr, size = 4000000
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1591
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1592 Return 1 if we can prove the equality at the innermost loop, but not all
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1593 level loops. In this case, no information is recorded.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1594
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1595 Return 0 if no equality can be proven at any level loops. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1596
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1597 static int
111
kono
parents: 67
diff changeset
1598 compute_access_range (loop_p loop_nest, data_reference_p dr, tree *base,
kono
parents: 67
diff changeset
1599 tree *size, vec<tree> *steps = NULL)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1600 {
111
kono
parents: 67
diff changeset
1601 location_t loc = gimple_location (DR_STMT (dr));
kono
parents: 67
diff changeset
1602 basic_block bb = gimple_bb (DR_STMT (dr));
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1603 class loop *loop = bb->loop_father;
111
kono
parents: 67
diff changeset
1604 tree ref = DR_REF (dr);
kono
parents: 67
diff changeset
1605 tree access_base = build_fold_addr_expr (ref);
kono
parents: 67
diff changeset
1606 tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (ref));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1607 int res = 0;
111
kono
parents: 67
diff changeset
1608
kono
parents: 67
diff changeset
1609 do {
kono
parents: 67
diff changeset
1610 tree scev_fn = analyze_scalar_evolution (loop, access_base);
kono
parents: 67
diff changeset
1611 if (TREE_CODE (scev_fn) != POLYNOMIAL_CHREC)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1612 return res;
111
kono
parents: 67
diff changeset
1613
kono
parents: 67
diff changeset
1614 access_base = CHREC_LEFT (scev_fn);
kono
parents: 67
diff changeset
1615 if (tree_contains_chrecs (access_base, NULL))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1616 return res;
111
kono
parents: 67
diff changeset
1617
kono
parents: 67
diff changeset
1618 tree scev_step = CHREC_RIGHT (scev_fn);
kono
parents: 67
diff changeset
1619 /* Only support constant steps. */
kono
parents: 67
diff changeset
1620 if (TREE_CODE (scev_step) != INTEGER_CST)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1621 return res;
111
kono
parents: 67
diff changeset
1622
kono
parents: 67
diff changeset
1623 enum ev_direction access_dir = scev_direction (scev_fn);
kono
parents: 67
diff changeset
1624 if (access_dir == EV_DIR_UNKNOWN)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1625 return res;
111
kono
parents: 67
diff changeset
1626
kono
parents: 67
diff changeset
1627 if (steps != NULL)
kono
parents: 67
diff changeset
1628 steps->safe_push (scev_step);
kono
parents: 67
diff changeset
1629
kono
parents: 67
diff changeset
1630 scev_step = fold_convert_loc (loc, sizetype, scev_step);
kono
parents: 67
diff changeset
1631 /* Compute absolute value of scev step. */
kono
parents: 67
diff changeset
1632 if (access_dir == EV_DIR_DECREASES)
kono
parents: 67
diff changeset
1633 scev_step = fold_build1_loc (loc, NEGATE_EXPR, sizetype, scev_step);
kono
parents: 67
diff changeset
1634
kono
parents: 67
diff changeset
1635 /* At each level of loop, scev step must equal to access size. In other
kono
parents: 67
diff changeset
1636 words, DR must access consecutive memory between loop iterations. */
kono
parents: 67
diff changeset
1637 if (!operand_equal_p (scev_step, access_size, 0))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1638 return res;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1639
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1640 /* Access stride can be computed for data reference at least for the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1641 innermost loop. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642 res = 1;
111
kono
parents: 67
diff changeset
1643
kono
parents: 67
diff changeset
1644 /* Compute DR's execution times in loop. */
kono
parents: 67
diff changeset
1645 tree niters = number_of_latch_executions (loop);
kono
parents: 67
diff changeset
1646 niters = fold_convert_loc (loc, sizetype, niters);
kono
parents: 67
diff changeset
1647 if (dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src, bb))
kono
parents: 67
diff changeset
1648 niters = size_binop_loc (loc, PLUS_EXPR, niters, size_one_node);
kono
parents: 67
diff changeset
1649
kono
parents: 67
diff changeset
1650 /* Compute DR's overall access size in loop. */
kono
parents: 67
diff changeset
1651 access_size = fold_build2_loc (loc, MULT_EXPR, sizetype,
kono
parents: 67
diff changeset
1652 niters, scev_step);
kono
parents: 67
diff changeset
1653 /* Adjust base address in case of negative step. */
kono
parents: 67
diff changeset
1654 if (access_dir == EV_DIR_DECREASES)
kono
parents: 67
diff changeset
1655 {
kono
parents: 67
diff changeset
1656 tree adj = fold_build2_loc (loc, MINUS_EXPR, sizetype,
kono
parents: 67
diff changeset
1657 scev_step, access_size);
kono
parents: 67
diff changeset
1658 access_base = fold_build_pointer_plus_loc (loc, access_base, adj);
kono
parents: 67
diff changeset
1659 }
kono
parents: 67
diff changeset
1660 } while (loop != loop_nest && (loop = loop_outer (loop)) != NULL);
kono
parents: 67
diff changeset
1661
kono
parents: 67
diff changeset
1662 *base = access_base;
kono
parents: 67
diff changeset
1663 *size = access_size;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1664 /* Access stride can be computed for data reference at each level loop. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1665 return 2;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1666 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1667
111
kono
parents: 67
diff changeset
1668 /* Allocate and return builtin struct. Record information like DST_DR,
kono
parents: 67
diff changeset
1669 SRC_DR, DST_BASE, SRC_BASE and SIZE in the allocated struct. */
kono
parents: 67
diff changeset
1670
kono
parents: 67
diff changeset
1671 static struct builtin_info *
kono
parents: 67
diff changeset
1672 alloc_builtin (data_reference_p dst_dr, data_reference_p src_dr,
kono
parents: 67
diff changeset
1673 tree dst_base, tree src_base, tree size)
kono
parents: 67
diff changeset
1674 {
kono
parents: 67
diff changeset
1675 struct builtin_info *builtin = XNEW (struct builtin_info);
kono
parents: 67
diff changeset
1676 builtin->dst_dr = dst_dr;
kono
parents: 67
diff changeset
1677 builtin->src_dr = src_dr;
kono
parents: 67
diff changeset
1678 builtin->dst_base = dst_base;
kono
parents: 67
diff changeset
1679 builtin->src_base = src_base;
kono
parents: 67
diff changeset
1680 builtin->size = size;
kono
parents: 67
diff changeset
1681 return builtin;
kono
parents: 67
diff changeset
1682 }
kono
parents: 67
diff changeset
1683
kono
parents: 67
diff changeset
1684 /* Given data reference DR in loop nest LOOP, classify if it forms builtin
kono
parents: 67
diff changeset
1685 memset call. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1686
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1687 static void
111
kono
parents: 67
diff changeset
1688 classify_builtin_st (loop_p loop, partition *partition, data_reference_p dr)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1689 {
111
kono
parents: 67
diff changeset
1690 gimple *stmt = DR_STMT (dr);
kono
parents: 67
diff changeset
1691 tree base, size, rhs = gimple_assign_rhs1 (stmt);
kono
parents: 67
diff changeset
1692
kono
parents: 67
diff changeset
1693 if (const_with_all_bytes_same (rhs) == -1
kono
parents: 67
diff changeset
1694 && (!INTEGRAL_TYPE_P (TREE_TYPE (rhs))
kono
parents: 67
diff changeset
1695 || (TYPE_MODE (TREE_TYPE (rhs))
kono
parents: 67
diff changeset
1696 != TYPE_MODE (unsigned_char_type_node))))
kono
parents: 67
diff changeset
1697 return;
kono
parents: 67
diff changeset
1698
kono
parents: 67
diff changeset
1699 if (TREE_CODE (rhs) == SSA_NAME
kono
parents: 67
diff changeset
1700 && !SSA_NAME_IS_DEFAULT_DEF (rhs)
kono
parents: 67
diff changeset
1701 && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
kono
parents: 67
diff changeset
1702 return;
kono
parents: 67
diff changeset
1703
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1704 int res = compute_access_range (loop, dr, &base, &size);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1705 if (res == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1706 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1707 if (res == 1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1708 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1709 partition->kind = PKIND_PARTIAL_MEMSET;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1710 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1711 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1712
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1713 poly_uint64 base_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1714 unsigned HOST_WIDE_INT const_base_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1715 tree base_base = strip_offset (base, &base_offset);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1716 if (!base_offset.is_constant (&const_base_offset))
111
kono
parents: 67
diff changeset
1717 return;
kono
parents: 67
diff changeset
1718
kono
parents: 67
diff changeset
1719 struct builtin_info *builtin;
kono
parents: 67
diff changeset
1720 builtin = alloc_builtin (dr, NULL, base, NULL_TREE, size);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1721 builtin->dst_base_base = base_base;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1722 builtin->dst_base_offset = const_base_offset;
111
kono
parents: 67
diff changeset
1723 partition->builtin = builtin;
kono
parents: 67
diff changeset
1724 partition->kind = PKIND_MEMSET;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1725 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1726
111
kono
parents: 67
diff changeset
1727 /* Given data references DST_DR and SRC_DR in loop nest LOOP and RDG, classify
kono
parents: 67
diff changeset
1728 if it forms builtin memcpy or memmove call. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1729
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1730 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1731 loop_distribution::classify_builtin_ldst (loop_p loop, struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1732 partition *partition,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1733 data_reference_p dst_dr,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1734 data_reference_p src_dr)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1735 {
111
kono
parents: 67
diff changeset
1736 tree base, size, src_base, src_size;
kono
parents: 67
diff changeset
1737 auto_vec<tree> dst_steps, src_steps;
kono
parents: 67
diff changeset
1738
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1739 /* Compute access range of both load and store. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1740 int res = compute_access_range (loop, dst_dr, &base, &size, &dst_steps);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1741 if (res != 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1742 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1743 res = compute_access_range (loop, src_dr, &src_base, &src_size, &src_steps);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1744 if (res != 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1745 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1746
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1747 /* They much have the same access size. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1748 if (!operand_equal_p (size, src_size, 0))
111
kono
parents: 67
diff changeset
1749 return;
kono
parents: 67
diff changeset
1750
kono
parents: 67
diff changeset
1751 /* Load and store in loop nest must access memory in the same way, i.e,
kono
parents: 67
diff changeset
1752 their must have the same steps in each loop of the nest. */
kono
parents: 67
diff changeset
1753 if (dst_steps.length () != src_steps.length ())
kono
parents: 67
diff changeset
1754 return;
kono
parents: 67
diff changeset
1755 for (unsigned i = 0; i < dst_steps.length (); ++i)
kono
parents: 67
diff changeset
1756 if (!operand_equal_p (dst_steps[i], src_steps[i], 0))
kono
parents: 67
diff changeset
1757 return;
kono
parents: 67
diff changeset
1758
kono
parents: 67
diff changeset
1759 /* Now check that if there is a dependence. */
kono
parents: 67
diff changeset
1760 ddr_p ddr = get_data_dependence (rdg, src_dr, dst_dr);
kono
parents: 67
diff changeset
1761
kono
parents: 67
diff changeset
1762 /* Classify as memcpy if no dependence between load and store. */
kono
parents: 67
diff changeset
1763 if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
kono
parents: 67
diff changeset
1764 {
kono
parents: 67
diff changeset
1765 partition->builtin = alloc_builtin (dst_dr, src_dr, base, src_base, size);
kono
parents: 67
diff changeset
1766 partition->kind = PKIND_MEMCPY;
kono
parents: 67
diff changeset
1767 return;
kono
parents: 67
diff changeset
1768 }
kono
parents: 67
diff changeset
1769
kono
parents: 67
diff changeset
1770 /* Can't do memmove in case of unknown dependence or dependence without
kono
parents: 67
diff changeset
1771 classical distance vector. */
kono
parents: 67
diff changeset
1772 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
kono
parents: 67
diff changeset
1773 || DDR_NUM_DIST_VECTS (ddr) == 0)
kono
parents: 67
diff changeset
1774 return;
kono
parents: 67
diff changeset
1775
kono
parents: 67
diff changeset
1776 unsigned i;
kono
parents: 67
diff changeset
1777 lambda_vector dist_v;
kono
parents: 67
diff changeset
1778 int num_lev = (DDR_LOOP_NEST (ddr)).length ();
kono
parents: 67
diff changeset
1779 FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1780 {
111
kono
parents: 67
diff changeset
1781 unsigned dep_lev = dependence_level (dist_v, num_lev);
kono
parents: 67
diff changeset
1782 /* Can't do memmove if load depends on store. */
kono
parents: 67
diff changeset
1783 if (dep_lev > 0 && dist_v[dep_lev - 1] > 0 && !DDR_REVERSED_P (ddr))
kono
parents: 67
diff changeset
1784 return;
kono
parents: 67
diff changeset
1785 }
kono
parents: 67
diff changeset
1786
kono
parents: 67
diff changeset
1787 partition->builtin = alloc_builtin (dst_dr, src_dr, base, src_base, size);
kono
parents: 67
diff changeset
1788 partition->kind = PKIND_MEMMOVE;
kono
parents: 67
diff changeset
1789 return;
kono
parents: 67
diff changeset
1790 }
kono
parents: 67
diff changeset
1791
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1792 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1793 loop_distribution::classify_partition (loop_p loop,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1794 struct graph *rdg, partition *partition,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1795 bitmap stmt_in_all_partitions)
111
kono
parents: 67
diff changeset
1796 {
kono
parents: 67
diff changeset
1797 bitmap_iterator bi;
kono
parents: 67
diff changeset
1798 unsigned i;
kono
parents: 67
diff changeset
1799 data_reference_p single_ld = NULL, single_st = NULL;
kono
parents: 67
diff changeset
1800 bool volatiles_p = false, has_reduction = false;
kono
parents: 67
diff changeset
1801
kono
parents: 67
diff changeset
1802 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
kono
parents: 67
diff changeset
1803 {
kono
parents: 67
diff changeset
1804 gimple *stmt = RDG_STMT (rdg, i);
kono
parents: 67
diff changeset
1805
kono
parents: 67
diff changeset
1806 if (gimple_has_volatile_ops (stmt))
kono
parents: 67
diff changeset
1807 volatiles_p = true;
kono
parents: 67
diff changeset
1808
kono
parents: 67
diff changeset
1809 /* If the stmt is not included by all partitions and there is uses
kono
parents: 67
diff changeset
1810 outside of the loop, then mark the partition as reduction. */
kono
parents: 67
diff changeset
1811 if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1812 {
111
kono
parents: 67
diff changeset
1813 /* Due to limitation in the transform phase we have to fuse all
kono
parents: 67
diff changeset
1814 reduction partitions. As a result, this could cancel valid
kono
parents: 67
diff changeset
1815 loop distribution especially for loop that induction variable
kono
parents: 67
diff changeset
1816 is used outside of loop. To workaround this issue, we skip
kono
parents: 67
diff changeset
1817 marking partition as reudction if the reduction stmt belongs
kono
parents: 67
diff changeset
1818 to all partitions. In such case, reduction will be computed
kono
parents: 67
diff changeset
1819 correctly no matter how partitions are fused/distributed. */
kono
parents: 67
diff changeset
1820 if (!bitmap_bit_p (stmt_in_all_partitions, i))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1821 partition->reduction_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1822 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1823 has_reduction = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1824 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1825 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1826
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1827 /* Simple workaround to prevent classifying the partition as builtin
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1828 if it contains any use outside of loop. For the case where all
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1829 partitions have the reduction this simple workaround is delayed
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1830 to only affect the last partition. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1831 if (partition->reduction_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1832 return has_reduction;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1833
111
kono
parents: 67
diff changeset
1834 /* Perform general partition disqualification for builtins. */
kono
parents: 67
diff changeset
1835 if (volatiles_p
kono
parents: 67
diff changeset
1836 || !flag_tree_loop_distribute_patterns)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1837 return has_reduction;
111
kono
parents: 67
diff changeset
1838
kono
parents: 67
diff changeset
1839 /* Find single load/store data references for builtin partition. */
kono
parents: 67
diff changeset
1840 if (!find_single_drs (loop, rdg, partition, &single_st, &single_ld))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1841 return has_reduction;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1842
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1843 partition->loc = gimple_location (DR_STMT (single_st));
111
kono
parents: 67
diff changeset
1844
kono
parents: 67
diff changeset
1845 /* Classify the builtin kind. */
kono
parents: 67
diff changeset
1846 if (single_ld == NULL)
kono
parents: 67
diff changeset
1847 classify_builtin_st (loop, partition, single_st);
kono
parents: 67
diff changeset
1848 else
kono
parents: 67
diff changeset
1849 classify_builtin_ldst (loop, rdg, partition, single_st, single_ld);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1850 return has_reduction;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1851 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1852
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1853 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1854 loop_distribution::share_memory_accesses (struct graph *rdg,
111
kono
parents: 67
diff changeset
1855 partition *partition1, partition *partition2)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1856 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1857 unsigned i, j;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1858 bitmap_iterator bi, bj;
111
kono
parents: 67
diff changeset
1859 data_reference_p dr1, dr2;
kono
parents: 67
diff changeset
1860
kono
parents: 67
diff changeset
1861 /* First check whether in the intersection of the two partitions are
kono
parents: 67
diff changeset
1862 any loads or stores. Common loads are the situation that happens
kono
parents: 67
diff changeset
1863 most often. */
kono
parents: 67
diff changeset
1864 EXECUTE_IF_AND_IN_BITMAP (partition1->stmts, partition2->stmts, 0, i, bi)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1865 if (RDG_MEM_WRITE_STMT (rdg, i)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1866 || RDG_MEM_READS_STMT (rdg, i))
111
kono
parents: 67
diff changeset
1867 return true;
kono
parents: 67
diff changeset
1868
kono
parents: 67
diff changeset
1869 /* Then check whether the two partitions access the same memory object. */
kono
parents: 67
diff changeset
1870 EXECUTE_IF_SET_IN_BITMAP (partition1->datarefs, 0, i, bi)
kono
parents: 67
diff changeset
1871 {
kono
parents: 67
diff changeset
1872 dr1 = datarefs_vec[i];
kono
parents: 67
diff changeset
1873
kono
parents: 67
diff changeset
1874 if (!DR_BASE_ADDRESS (dr1)
kono
parents: 67
diff changeset
1875 || !DR_OFFSET (dr1) || !DR_INIT (dr1) || !DR_STEP (dr1))
kono
parents: 67
diff changeset
1876 continue;
kono
parents: 67
diff changeset
1877
kono
parents: 67
diff changeset
1878 EXECUTE_IF_SET_IN_BITMAP (partition2->datarefs, 0, j, bj)
kono
parents: 67
diff changeset
1879 {
kono
parents: 67
diff changeset
1880 dr2 = datarefs_vec[j];
kono
parents: 67
diff changeset
1881
kono
parents: 67
diff changeset
1882 if (!DR_BASE_ADDRESS (dr2)
kono
parents: 67
diff changeset
1883 || !DR_OFFSET (dr2) || !DR_INIT (dr2) || !DR_STEP (dr2))
kono
parents: 67
diff changeset
1884 continue;
kono
parents: 67
diff changeset
1885
kono
parents: 67
diff changeset
1886 if (operand_equal_p (DR_BASE_ADDRESS (dr1), DR_BASE_ADDRESS (dr2), 0)
kono
parents: 67
diff changeset
1887 && operand_equal_p (DR_OFFSET (dr1), DR_OFFSET (dr2), 0)
kono
parents: 67
diff changeset
1888 && operand_equal_p (DR_INIT (dr1), DR_INIT (dr2), 0)
kono
parents: 67
diff changeset
1889 && operand_equal_p (DR_STEP (dr1), DR_STEP (dr2), 0))
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1890 return true;
111
kono
parents: 67
diff changeset
1891 }
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1892 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1893
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1894 return false;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1895 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1896
111
kono
parents: 67
diff changeset
1897 /* For each seed statement in STARTING_STMTS, this function builds
kono
parents: 67
diff changeset
1898 partition for it by adding depended statements according to RDG.
kono
parents: 67
diff changeset
1899 All partitions are recorded in PARTITIONS. */
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1900
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1901 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1902 loop_distribution::rdg_build_partitions (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1903 vec<gimple *> starting_stmts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1904 vec<partition *> *partitions)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1905 {
111
kono
parents: 67
diff changeset
1906 auto_bitmap processed;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1907 int i;
111
kono
parents: 67
diff changeset
1908 gimple *stmt;
kono
parents: 67
diff changeset
1909
kono
parents: 67
diff changeset
1910 FOR_EACH_VEC_ELT (starting_stmts, i, stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1911 {
111
kono
parents: 67
diff changeset
1912 int v = rdg_vertex_for_stmt (rdg, stmt);
kono
parents: 67
diff changeset
1913
kono
parents: 67
diff changeset
1914 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
1915 fprintf (dump_file,
kono
parents: 67
diff changeset
1916 "ldist asked to generate code for vertex %d\n", v);
kono
parents: 67
diff changeset
1917
kono
parents: 67
diff changeset
1918 /* If the vertex is already contained in another partition so
kono
parents: 67
diff changeset
1919 is the partition rooted at it. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1920 if (bitmap_bit_p (processed, v))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1921 continue;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1922
111
kono
parents: 67
diff changeset
1923 partition *partition = build_rdg_partition_for_vertex (rdg, v);
kono
parents: 67
diff changeset
1924 bitmap_ior_into (processed, partition->stmts);
kono
parents: 67
diff changeset
1925
kono
parents: 67
diff changeset
1926 if (dump_file && (dump_flags & TDF_DETAILS))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1927 {
111
kono
parents: 67
diff changeset
1928 fprintf (dump_file, "ldist creates useful %s partition:\n",
kono
parents: 67
diff changeset
1929 partition->type == PTYPE_PARALLEL ? "parallel" : "sequent");
kono
parents: 67
diff changeset
1930 bitmap_print (dump_file, partition->stmts, " ", "\n");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1931 }
111
kono
parents: 67
diff changeset
1932
kono
parents: 67
diff changeset
1933 partitions->safe_push (partition);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1934 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1935
111
kono
parents: 67
diff changeset
1936 /* All vertices should have been assigned to at least one partition now,
kono
parents: 67
diff changeset
1937 other than vertices belonging to dead code. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1938 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1939
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1940 /* Dump to FILE the PARTITIONS. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1941
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1942 static void
111
kono
parents: 67
diff changeset
1943 dump_rdg_partitions (FILE *file, vec<partition *> partitions)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1944 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1945 int i;
111
kono
parents: 67
diff changeset
1946 partition *partition;
kono
parents: 67
diff changeset
1947
kono
parents: 67
diff changeset
1948 FOR_EACH_VEC_ELT (partitions, i, partition)
kono
parents: 67
diff changeset
1949 debug_bitmap_file (file, partition->stmts);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1950 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1951
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1952 /* Debug PARTITIONS. */
111
kono
parents: 67
diff changeset
1953 extern void debug_rdg_partitions (vec<partition *> );
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1954
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1955 DEBUG_FUNCTION void
111
kono
parents: 67
diff changeset
1956 debug_rdg_partitions (vec<partition *> partitions)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1957 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1958 dump_rdg_partitions (stderr, partitions);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1959 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1960
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1961 /* Returns the number of read and write operations in the RDG. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1962
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1963 static int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1964 number_of_rw_in_rdg (struct graph *rdg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1965 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1966 int i, res = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1967
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1968 for (i = 0; i < rdg->n_vertices; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1969 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1970 if (RDG_MEM_WRITE_STMT (rdg, i))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1971 ++res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1972
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1973 if (RDG_MEM_READS_STMT (rdg, i))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1974 ++res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1975 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1976
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1977 return res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1978 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1979
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1980 /* Returns the number of read and write operations in a PARTITION of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1981 the RDG. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1982
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1983 static int
111
kono
parents: 67
diff changeset
1984 number_of_rw_in_partition (struct graph *rdg, partition *partition)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1985 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1986 int res = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1987 unsigned i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1988 bitmap_iterator ii;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1989
111
kono
parents: 67
diff changeset
1990 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, ii)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1991 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1992 if (RDG_MEM_WRITE_STMT (rdg, i))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1993 ++res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1994
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1995 if (RDG_MEM_READS_STMT (rdg, i))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1996 ++res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1997 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1998
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1999 return res;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2000 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2001
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2002 /* Returns true when one of the PARTITIONS contains all the read or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2003 write operations of RDG. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2004
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2005 static bool
111
kono
parents: 67
diff changeset
2006 partition_contains_all_rw (struct graph *rdg,
kono
parents: 67
diff changeset
2007 vec<partition *> partitions)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2008 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2009 int i;
111
kono
parents: 67
diff changeset
2010 partition *partition;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2011 int nrw = number_of_rw_in_rdg (rdg);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2012
111
kono
parents: 67
diff changeset
2013 FOR_EACH_VEC_ELT (partitions, i, partition)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2014 if (nrw == number_of_rw_in_partition (rdg, partition))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2015 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2016
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2017 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2018 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2019
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2020 int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2021 loop_distribution::pg_add_dependence_edges (struct graph *rdg, int dir,
111
kono
parents: 67
diff changeset
2022 bitmap drs1, bitmap drs2, vec<ddr_p> *alias_ddrs)
kono
parents: 67
diff changeset
2023 {
kono
parents: 67
diff changeset
2024 unsigned i, j;
kono
parents: 67
diff changeset
2025 bitmap_iterator bi, bj;
kono
parents: 67
diff changeset
2026 data_reference_p dr1, dr2, saved_dr1;
kono
parents: 67
diff changeset
2027
kono
parents: 67
diff changeset
2028 /* dependence direction - 0 is no dependence, -1 is back,
kono
parents: 67
diff changeset
2029 1 is forth, 2 is both (we can stop then, merging will occur). */
kono
parents: 67
diff changeset
2030 EXECUTE_IF_SET_IN_BITMAP (drs1, 0, i, bi)
kono
parents: 67
diff changeset
2031 {
kono
parents: 67
diff changeset
2032 dr1 = datarefs_vec[i];
kono
parents: 67
diff changeset
2033
kono
parents: 67
diff changeset
2034 EXECUTE_IF_SET_IN_BITMAP (drs2, 0, j, bj)
kono
parents: 67
diff changeset
2035 {
kono
parents: 67
diff changeset
2036 int res, this_dir = 1;
kono
parents: 67
diff changeset
2037 ddr_p ddr;
kono
parents: 67
diff changeset
2038
kono
parents: 67
diff changeset
2039 dr2 = datarefs_vec[j];
kono
parents: 67
diff changeset
2040
kono
parents: 67
diff changeset
2041 /* Skip all <read, read> data dependence. */
kono
parents: 67
diff changeset
2042 if (DR_IS_READ (dr1) && DR_IS_READ (dr2))
kono
parents: 67
diff changeset
2043 continue;
kono
parents: 67
diff changeset
2044
kono
parents: 67
diff changeset
2045 saved_dr1 = dr1;
kono
parents: 67
diff changeset
2046 /* Re-shuffle data-refs to be in topological order. */
kono
parents: 67
diff changeset
2047 if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
kono
parents: 67
diff changeset
2048 > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
kono
parents: 67
diff changeset
2049 {
kono
parents: 67
diff changeset
2050 std::swap (dr1, dr2);
kono
parents: 67
diff changeset
2051 this_dir = -this_dir;
kono
parents: 67
diff changeset
2052 }
kono
parents: 67
diff changeset
2053 ddr = get_data_dependence (rdg, dr1, dr2);
kono
parents: 67
diff changeset
2054 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
kono
parents: 67
diff changeset
2055 {
kono
parents: 67
diff changeset
2056 this_dir = 0;
kono
parents: 67
diff changeset
2057 res = data_ref_compare_tree (DR_BASE_ADDRESS (dr1),
kono
parents: 67
diff changeset
2058 DR_BASE_ADDRESS (dr2));
kono
parents: 67
diff changeset
2059 /* Be conservative. If data references are not well analyzed,
kono
parents: 67
diff changeset
2060 or the two data references have the same base address and
kono
parents: 67
diff changeset
2061 offset, add dependence and consider it alias to each other.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2062 In other words, the dependence cannot be resolved by
111
kono
parents: 67
diff changeset
2063 runtime alias check. */
kono
parents: 67
diff changeset
2064 if (!DR_BASE_ADDRESS (dr1) || !DR_BASE_ADDRESS (dr2)
kono
parents: 67
diff changeset
2065 || !DR_OFFSET (dr1) || !DR_OFFSET (dr2)
kono
parents: 67
diff changeset
2066 || !DR_INIT (dr1) || !DR_INIT (dr2)
kono
parents: 67
diff changeset
2067 || !DR_STEP (dr1) || !tree_fits_uhwi_p (DR_STEP (dr1))
kono
parents: 67
diff changeset
2068 || !DR_STEP (dr2) || !tree_fits_uhwi_p (DR_STEP (dr2))
kono
parents: 67
diff changeset
2069 || res == 0)
kono
parents: 67
diff changeset
2070 this_dir = 2;
kono
parents: 67
diff changeset
2071 /* Data dependence could be resolved by runtime alias check,
kono
parents: 67
diff changeset
2072 record it in ALIAS_DDRS. */
kono
parents: 67
diff changeset
2073 else if (alias_ddrs != NULL)
kono
parents: 67
diff changeset
2074 alias_ddrs->safe_push (ddr);
kono
parents: 67
diff changeset
2075 /* Or simply ignore it. */
kono
parents: 67
diff changeset
2076 }
kono
parents: 67
diff changeset
2077 else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
kono
parents: 67
diff changeset
2078 {
kono
parents: 67
diff changeset
2079 if (DDR_REVERSED_P (ddr))
kono
parents: 67
diff changeset
2080 this_dir = -this_dir;
kono
parents: 67
diff changeset
2081
kono
parents: 67
diff changeset
2082 /* Known dependences can still be unordered througout the
kono
parents: 67
diff changeset
2083 iteration space, see gcc.dg/tree-ssa/ldist-16.c. */
kono
parents: 67
diff changeset
2084 if (DDR_NUM_DIST_VECTS (ddr) != 1)
kono
parents: 67
diff changeset
2085 this_dir = 2;
kono
parents: 67
diff changeset
2086 /* If the overlap is exact preserve stmt order. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2087 else if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2088 DDR_NB_LOOPS (ddr)))
111
kono
parents: 67
diff changeset
2089 ;
kono
parents: 67
diff changeset
2090 /* Else as the distance vector is lexicographic positive swap
kono
parents: 67
diff changeset
2091 the dependence direction. */
kono
parents: 67
diff changeset
2092 else
kono
parents: 67
diff changeset
2093 this_dir = -this_dir;
kono
parents: 67
diff changeset
2094 }
kono
parents: 67
diff changeset
2095 else
kono
parents: 67
diff changeset
2096 this_dir = 0;
kono
parents: 67
diff changeset
2097 if (this_dir == 2)
kono
parents: 67
diff changeset
2098 return 2;
kono
parents: 67
diff changeset
2099 else if (dir == 0)
kono
parents: 67
diff changeset
2100 dir = this_dir;
kono
parents: 67
diff changeset
2101 else if (this_dir != 0 && dir != this_dir)
kono
parents: 67
diff changeset
2102 return 2;
kono
parents: 67
diff changeset
2103 /* Shuffle "back" dr1. */
kono
parents: 67
diff changeset
2104 dr1 = saved_dr1;
kono
parents: 67
diff changeset
2105 }
kono
parents: 67
diff changeset
2106 }
kono
parents: 67
diff changeset
2107 return dir;
kono
parents: 67
diff changeset
2108 }
kono
parents: 67
diff changeset
2109
kono
parents: 67
diff changeset
2110 /* Compare postorder number of the partition graph vertices V1 and V2. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2111
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2112 static int
111
kono
parents: 67
diff changeset
2113 pgcmp (const void *v1_, const void *v2_)
kono
parents: 67
diff changeset
2114 {
kono
parents: 67
diff changeset
2115 const vertex *v1 = (const vertex *)v1_;
kono
parents: 67
diff changeset
2116 const vertex *v2 = (const vertex *)v2_;
kono
parents: 67
diff changeset
2117 return v2->post - v1->post;
kono
parents: 67
diff changeset
2118 }
kono
parents: 67
diff changeset
2119
kono
parents: 67
diff changeset
2120 /* Data attached to vertices of partition dependence graph. */
kono
parents: 67
diff changeset
2121 struct pg_vdata
kono
parents: 67
diff changeset
2122 {
kono
parents: 67
diff changeset
2123 /* ID of the corresponding partition. */
kono
parents: 67
diff changeset
2124 int id;
kono
parents: 67
diff changeset
2125 /* The partition. */
kono
parents: 67
diff changeset
2126 struct partition *partition;
kono
parents: 67
diff changeset
2127 };
kono
parents: 67
diff changeset
2128
kono
parents: 67
diff changeset
2129 /* Data attached to edges of partition dependence graph. */
kono
parents: 67
diff changeset
2130 struct pg_edata
kono
parents: 67
diff changeset
2131 {
kono
parents: 67
diff changeset
2132 /* If the dependence edge can be resolved by runtime alias check,
kono
parents: 67
diff changeset
2133 this vector contains data dependence relations for runtime alias
kono
parents: 67
diff changeset
2134 check. On the other hand, if the dependence edge is introduced
kono
parents: 67
diff changeset
2135 because of compilation time known data dependence, this vector
kono
parents: 67
diff changeset
2136 contains nothing. */
kono
parents: 67
diff changeset
2137 vec<ddr_p> alias_ddrs;
kono
parents: 67
diff changeset
2138 };
kono
parents: 67
diff changeset
2139
kono
parents: 67
diff changeset
2140 /* Callback data for traversing edges in graph. */
kono
parents: 67
diff changeset
2141 struct pg_edge_callback_data
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2142 {
111
kono
parents: 67
diff changeset
2143 /* Bitmap contains strong connected components should be merged. */
kono
parents: 67
diff changeset
2144 bitmap sccs_to_merge;
kono
parents: 67
diff changeset
2145 /* Array constains component information for all vertices. */
kono
parents: 67
diff changeset
2146 int *vertices_component;
kono
parents: 67
diff changeset
2147 /* Vector to record all data dependence relations which are needed
kono
parents: 67
diff changeset
2148 to break strong connected components by runtime alias checks. */
kono
parents: 67
diff changeset
2149 vec<ddr_p> *alias_ddrs;
kono
parents: 67
diff changeset
2150 };
kono
parents: 67
diff changeset
2151
kono
parents: 67
diff changeset
2152 /* Initialize vertice's data for partition dependence graph PG with
kono
parents: 67
diff changeset
2153 PARTITIONS. */
kono
parents: 67
diff changeset
2154
kono
parents: 67
diff changeset
2155 static void
kono
parents: 67
diff changeset
2156 init_partition_graph_vertices (struct graph *pg,
kono
parents: 67
diff changeset
2157 vec<struct partition *> *partitions)
kono
parents: 67
diff changeset
2158 {
kono
parents: 67
diff changeset
2159 int i;
kono
parents: 67
diff changeset
2160 partition *partition;
kono
parents: 67
diff changeset
2161 struct pg_vdata *data;
kono
parents: 67
diff changeset
2162
kono
parents: 67
diff changeset
2163 for (i = 0; partitions->iterate (i, &partition); ++i)
kono
parents: 67
diff changeset
2164 {
kono
parents: 67
diff changeset
2165 data = new pg_vdata;
kono
parents: 67
diff changeset
2166 pg->vertices[i].data = data;
kono
parents: 67
diff changeset
2167 data->id = i;
kono
parents: 67
diff changeset
2168 data->partition = partition;
kono
parents: 67
diff changeset
2169 }
kono
parents: 67
diff changeset
2170 }
kono
parents: 67
diff changeset
2171
kono
parents: 67
diff changeset
2172 /* Add edge <I, J> to partition dependence graph PG. Attach vector of data
kono
parents: 67
diff changeset
2173 dependence relations to the EDGE if DDRS isn't NULL. */
kono
parents: 67
diff changeset
2174
kono
parents: 67
diff changeset
2175 static void
kono
parents: 67
diff changeset
2176 add_partition_graph_edge (struct graph *pg, int i, int j, vec<ddr_p> *ddrs)
kono
parents: 67
diff changeset
2177 {
kono
parents: 67
diff changeset
2178 struct graph_edge *e = add_edge (pg, i, j);
kono
parents: 67
diff changeset
2179
kono
parents: 67
diff changeset
2180 /* If the edge is attached with data dependence relations, it means this
kono
parents: 67
diff changeset
2181 dependence edge can be resolved by runtime alias checks. */
kono
parents: 67
diff changeset
2182 if (ddrs != NULL)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2183 {
111
kono
parents: 67
diff changeset
2184 struct pg_edata *data = new pg_edata;
kono
parents: 67
diff changeset
2185
kono
parents: 67
diff changeset
2186 gcc_assert (ddrs->length () > 0);
kono
parents: 67
diff changeset
2187 e->data = data;
kono
parents: 67
diff changeset
2188 data->alias_ddrs = vNULL;
kono
parents: 67
diff changeset
2189 data->alias_ddrs.safe_splice (*ddrs);
kono
parents: 67
diff changeset
2190 }
kono
parents: 67
diff changeset
2191 }
kono
parents: 67
diff changeset
2192
kono
parents: 67
diff changeset
2193 /* Callback function for graph travesal algorithm. It returns true
kono
parents: 67
diff changeset
2194 if edge E should skipped when traversing the graph. */
kono
parents: 67
diff changeset
2195
kono
parents: 67
diff changeset
2196 static bool
kono
parents: 67
diff changeset
2197 pg_skip_alias_edge (struct graph_edge *e)
kono
parents: 67
diff changeset
2198 {
kono
parents: 67
diff changeset
2199 struct pg_edata *data = (struct pg_edata *)e->data;
kono
parents: 67
diff changeset
2200 return (data != NULL && data->alias_ddrs.length () > 0);
kono
parents: 67
diff changeset
2201 }
kono
parents: 67
diff changeset
2202
kono
parents: 67
diff changeset
2203 /* Callback function freeing data attached to edge E of graph. */
kono
parents: 67
diff changeset
2204
kono
parents: 67
diff changeset
2205 static void
kono
parents: 67
diff changeset
2206 free_partition_graph_edata_cb (struct graph *, struct graph_edge *e, void *)
kono
parents: 67
diff changeset
2207 {
kono
parents: 67
diff changeset
2208 if (e->data != NULL)
kono
parents: 67
diff changeset
2209 {
kono
parents: 67
diff changeset
2210 struct pg_edata *data = (struct pg_edata *)e->data;
kono
parents: 67
diff changeset
2211 data->alias_ddrs.release ();
kono
parents: 67
diff changeset
2212 delete data;
kono
parents: 67
diff changeset
2213 }
kono
parents: 67
diff changeset
2214 }
kono
parents: 67
diff changeset
2215
kono
parents: 67
diff changeset
2216 /* Free data attached to vertice of partition dependence graph PG. */
kono
parents: 67
diff changeset
2217
kono
parents: 67
diff changeset
2218 static void
kono
parents: 67
diff changeset
2219 free_partition_graph_vdata (struct graph *pg)
kono
parents: 67
diff changeset
2220 {
kono
parents: 67
diff changeset
2221 int i;
kono
parents: 67
diff changeset
2222 struct pg_vdata *data;
kono
parents: 67
diff changeset
2223
kono
parents: 67
diff changeset
2224 for (i = 0; i < pg->n_vertices; ++i)
kono
parents: 67
diff changeset
2225 {
kono
parents: 67
diff changeset
2226 data = (struct pg_vdata *)pg->vertices[i].data;
kono
parents: 67
diff changeset
2227 delete data;
kono
parents: 67
diff changeset
2228 }
kono
parents: 67
diff changeset
2229 }
kono
parents: 67
diff changeset
2230
kono
parents: 67
diff changeset
2231 /* Build and return partition dependence graph for PARTITIONS. RDG is
kono
parents: 67
diff changeset
2232 reduced dependence graph for the loop to be distributed. If IGNORE_ALIAS_P
kono
parents: 67
diff changeset
2233 is true, data dependence caused by possible alias between references
kono
parents: 67
diff changeset
2234 is ignored, as if it doesn't exist at all; otherwise all depdendences
kono
parents: 67
diff changeset
2235 are considered. */
kono
parents: 67
diff changeset
2236
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2237 struct graph *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2238 loop_distribution::build_partition_graph (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2239 vec<struct partition *> *partitions,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2240 bool ignore_alias_p)
111
kono
parents: 67
diff changeset
2241 {
kono
parents: 67
diff changeset
2242 int i, j;
kono
parents: 67
diff changeset
2243 struct partition *partition1, *partition2;
kono
parents: 67
diff changeset
2244 graph *pg = new_graph (partitions->length ());
kono
parents: 67
diff changeset
2245 auto_vec<ddr_p> alias_ddrs, *alias_ddrs_p;
kono
parents: 67
diff changeset
2246
kono
parents: 67
diff changeset
2247 alias_ddrs_p = ignore_alias_p ? NULL : &alias_ddrs;
kono
parents: 67
diff changeset
2248
kono
parents: 67
diff changeset
2249 init_partition_graph_vertices (pg, partitions);
kono
parents: 67
diff changeset
2250
kono
parents: 67
diff changeset
2251 for (i = 0; partitions->iterate (i, &partition1); ++i)
kono
parents: 67
diff changeset
2252 {
kono
parents: 67
diff changeset
2253 for (j = i + 1; partitions->iterate (j, &partition2); ++j)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2254 {
111
kono
parents: 67
diff changeset
2255 /* dependence direction - 0 is no dependence, -1 is back,
kono
parents: 67
diff changeset
2256 1 is forth, 2 is both (we can stop then, merging will occur). */
kono
parents: 67
diff changeset
2257 int dir = 0;
kono
parents: 67
diff changeset
2258
kono
parents: 67
diff changeset
2259 /* If the first partition has reduction, add back edge; if the
kono
parents: 67
diff changeset
2260 second partition has reduction, add forth edge. This makes
kono
parents: 67
diff changeset
2261 sure that reduction partition will be sorted as the last one. */
kono
parents: 67
diff changeset
2262 if (partition_reduction_p (partition1))
kono
parents: 67
diff changeset
2263 dir = -1;
kono
parents: 67
diff changeset
2264 else if (partition_reduction_p (partition2))
kono
parents: 67
diff changeset
2265 dir = 1;
kono
parents: 67
diff changeset
2266
kono
parents: 67
diff changeset
2267 /* Cleanup the temporary vector. */
kono
parents: 67
diff changeset
2268 alias_ddrs.truncate (0);
kono
parents: 67
diff changeset
2269
kono
parents: 67
diff changeset
2270 dir = pg_add_dependence_edges (rdg, dir, partition1->datarefs,
kono
parents: 67
diff changeset
2271 partition2->datarefs, alias_ddrs_p);
kono
parents: 67
diff changeset
2272
kono
parents: 67
diff changeset
2273 /* Add edge to partition graph if there exists dependence. There
kono
parents: 67
diff changeset
2274 are two types of edges. One type edge is caused by compilation
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2275 time known dependence, this type cannot be resolved by runtime
111
kono
parents: 67
diff changeset
2276 alias check. The other type can be resolved by runtime alias
kono
parents: 67
diff changeset
2277 check. */
kono
parents: 67
diff changeset
2278 if (dir == 1 || dir == 2
kono
parents: 67
diff changeset
2279 || alias_ddrs.length () > 0)
kono
parents: 67
diff changeset
2280 {
kono
parents: 67
diff changeset
2281 /* Attach data dependence relations to edge that can be resolved
kono
parents: 67
diff changeset
2282 by runtime alias check. */
kono
parents: 67
diff changeset
2283 bool alias_edge_p = (dir != 1 && dir != 2);
kono
parents: 67
diff changeset
2284 add_partition_graph_edge (pg, i, j,
kono
parents: 67
diff changeset
2285 (alias_edge_p) ? &alias_ddrs : NULL);
kono
parents: 67
diff changeset
2286 }
kono
parents: 67
diff changeset
2287 if (dir == -1 || dir == 2
kono
parents: 67
diff changeset
2288 || alias_ddrs.length () > 0)
kono
parents: 67
diff changeset
2289 {
kono
parents: 67
diff changeset
2290 /* Attach data dependence relations to edge that can be resolved
kono
parents: 67
diff changeset
2291 by runtime alias check. */
kono
parents: 67
diff changeset
2292 bool alias_edge_p = (dir != -1 && dir != 2);
kono
parents: 67
diff changeset
2293 add_partition_graph_edge (pg, j, i,
kono
parents: 67
diff changeset
2294 (alias_edge_p) ? &alias_ddrs : NULL);
kono
parents: 67
diff changeset
2295 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2296 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2297 }
111
kono
parents: 67
diff changeset
2298 return pg;
kono
parents: 67
diff changeset
2299 }
kono
parents: 67
diff changeset
2300
kono
parents: 67
diff changeset
2301 /* Sort partitions in PG in descending post order and store them in
kono
parents: 67
diff changeset
2302 PARTITIONS. */
kono
parents: 67
diff changeset
2303
kono
parents: 67
diff changeset
2304 static void
kono
parents: 67
diff changeset
2305 sort_partitions_by_post_order (struct graph *pg,
kono
parents: 67
diff changeset
2306 vec<struct partition *> *partitions)
kono
parents: 67
diff changeset
2307 {
kono
parents: 67
diff changeset
2308 int i;
kono
parents: 67
diff changeset
2309 struct pg_vdata *data;
kono
parents: 67
diff changeset
2310
kono
parents: 67
diff changeset
2311 /* Now order the remaining nodes in descending postorder. */
kono
parents: 67
diff changeset
2312 qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp);
kono
parents: 67
diff changeset
2313 partitions->truncate (0);
kono
parents: 67
diff changeset
2314 for (i = 0; i < pg->n_vertices; ++i)
kono
parents: 67
diff changeset
2315 {
kono
parents: 67
diff changeset
2316 data = (struct pg_vdata *)pg->vertices[i].data;
kono
parents: 67
diff changeset
2317 if (data->partition)
kono
parents: 67
diff changeset
2318 partitions->safe_push (data->partition);
kono
parents: 67
diff changeset
2319 }
kono
parents: 67
diff changeset
2320 }
kono
parents: 67
diff changeset
2321
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2322 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2323 loop_distribution::merge_dep_scc_partitions (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2324 vec<struct partition *> *partitions,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2325 bool ignore_alias_p)
111
kono
parents: 67
diff changeset
2326 {
kono
parents: 67
diff changeset
2327 struct partition *partition1, *partition2;
kono
parents: 67
diff changeset
2328 struct pg_vdata *data;
kono
parents: 67
diff changeset
2329 graph *pg = build_partition_graph (rdg, partitions, ignore_alias_p);
kono
parents: 67
diff changeset
2330 int i, j, num_sccs = graphds_scc (pg, NULL);
kono
parents: 67
diff changeset
2331
kono
parents: 67
diff changeset
2332 /* Strong connected compoenent means dependence cycle, we cannot distribute
kono
parents: 67
diff changeset
2333 them. So fuse them together. */
kono
parents: 67
diff changeset
2334 if ((unsigned) num_sccs < partitions->length ())
kono
parents: 67
diff changeset
2335 {
kono
parents: 67
diff changeset
2336 for (i = 0; i < num_sccs; ++i)
kono
parents: 67
diff changeset
2337 {
kono
parents: 67
diff changeset
2338 for (j = 0; partitions->iterate (j, &partition1); ++j)
kono
parents: 67
diff changeset
2339 if (pg->vertices[j].component == i)
kono
parents: 67
diff changeset
2340 break;
kono
parents: 67
diff changeset
2341 for (j = j + 1; partitions->iterate (j, &partition2); ++j)
kono
parents: 67
diff changeset
2342 if (pg->vertices[j].component == i)
kono
parents: 67
diff changeset
2343 {
kono
parents: 67
diff changeset
2344 partition_merge_into (NULL, partition1,
kono
parents: 67
diff changeset
2345 partition2, FUSE_SAME_SCC);
kono
parents: 67
diff changeset
2346 partition1->type = PTYPE_SEQUENTIAL;
kono
parents: 67
diff changeset
2347 (*partitions)[j] = NULL;
kono
parents: 67
diff changeset
2348 partition_free (partition2);
kono
parents: 67
diff changeset
2349 data = (struct pg_vdata *)pg->vertices[j].data;
kono
parents: 67
diff changeset
2350 data->partition = NULL;
kono
parents: 67
diff changeset
2351 }
kono
parents: 67
diff changeset
2352 }
kono
parents: 67
diff changeset
2353 }
kono
parents: 67
diff changeset
2354
kono
parents: 67
diff changeset
2355 sort_partitions_by_post_order (pg, partitions);
kono
parents: 67
diff changeset
2356 gcc_assert (partitions->length () == (unsigned)num_sccs);
kono
parents: 67
diff changeset
2357 free_partition_graph_vdata (pg);
kono
parents: 67
diff changeset
2358 free_graph (pg);
kono
parents: 67
diff changeset
2359 }
kono
parents: 67
diff changeset
2360
kono
parents: 67
diff changeset
2361 /* Callback function for traversing edge E in graph G. DATA is private
kono
parents: 67
diff changeset
2362 callback data. */
kono
parents: 67
diff changeset
2363
kono
parents: 67
diff changeset
2364 static void
kono
parents: 67
diff changeset
2365 pg_collect_alias_ddrs (struct graph *g, struct graph_edge *e, void *data)
kono
parents: 67
diff changeset
2366 {
kono
parents: 67
diff changeset
2367 int i, j, component;
kono
parents: 67
diff changeset
2368 struct pg_edge_callback_data *cbdata;
kono
parents: 67
diff changeset
2369 struct pg_edata *edata = (struct pg_edata *) e->data;
kono
parents: 67
diff changeset
2370
kono
parents: 67
diff changeset
2371 /* If the edge doesn't have attached data dependence, it represents
kono
parents: 67
diff changeset
2372 compilation time known dependences. This type dependence cannot
kono
parents: 67
diff changeset
2373 be resolved by runtime alias check. */
kono
parents: 67
diff changeset
2374 if (edata == NULL || edata->alias_ddrs.length () == 0)
kono
parents: 67
diff changeset
2375 return;
kono
parents: 67
diff changeset
2376
kono
parents: 67
diff changeset
2377 cbdata = (struct pg_edge_callback_data *) data;
kono
parents: 67
diff changeset
2378 i = e->src;
kono
parents: 67
diff changeset
2379 j = e->dest;
kono
parents: 67
diff changeset
2380 component = cbdata->vertices_component[i];
kono
parents: 67
diff changeset
2381 /* Vertices are topologically sorted according to compilation time
kono
parents: 67
diff changeset
2382 known dependences, so we can break strong connected components
kono
parents: 67
diff changeset
2383 by removing edges of the opposite direction, i.e, edges pointing
kono
parents: 67
diff changeset
2384 from vertice with smaller post number to vertice with bigger post
kono
parents: 67
diff changeset
2385 number. */
kono
parents: 67
diff changeset
2386 if (g->vertices[i].post < g->vertices[j].post
kono
parents: 67
diff changeset
2387 /* We only need to remove edges connecting vertices in the same
kono
parents: 67
diff changeset
2388 strong connected component to break it. */
kono
parents: 67
diff changeset
2389 && component == cbdata->vertices_component[j]
kono
parents: 67
diff changeset
2390 /* Check if we want to break the strong connected component or not. */
kono
parents: 67
diff changeset
2391 && !bitmap_bit_p (cbdata->sccs_to_merge, component))
kono
parents: 67
diff changeset
2392 cbdata->alias_ddrs->safe_splice (edata->alias_ddrs);
kono
parents: 67
diff changeset
2393 }
kono
parents: 67
diff changeset
2394
kono
parents: 67
diff changeset
2395 /* This is the main function breaking strong conected components in
kono
parents: 67
diff changeset
2396 PARTITIONS giving reduced depdendence graph RDG. Store data dependence
kono
parents: 67
diff changeset
2397 relations for runtime alias check in ALIAS_DDRS. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2398 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2399 loop_distribution::break_alias_scc_partitions (struct graph *rdg,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2400 vec<struct partition *> *partitions,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2401 vec<ddr_p> *alias_ddrs)
111
kono
parents: 67
diff changeset
2402 {
kono
parents: 67
diff changeset
2403 int i, j, k, num_sccs, num_sccs_no_alias;
kono
parents: 67
diff changeset
2404 /* Build partition dependence graph. */
kono
parents: 67
diff changeset
2405 graph *pg = build_partition_graph (rdg, partitions, false);
kono
parents: 67
diff changeset
2406
kono
parents: 67
diff changeset
2407 alias_ddrs->truncate (0);
kono
parents: 67
diff changeset
2408 /* Find strong connected components in the graph, with all dependence edges
kono
parents: 67
diff changeset
2409 considered. */
kono
parents: 67
diff changeset
2410 num_sccs = graphds_scc (pg, NULL);
kono
parents: 67
diff changeset
2411 /* All SCCs now can be broken by runtime alias checks because SCCs caused by
kono
parents: 67
diff changeset
2412 compilation time known dependences are merged before this function. */
kono
parents: 67
diff changeset
2413 if ((unsigned) num_sccs < partitions->length ())
kono
parents: 67
diff changeset
2414 {
kono
parents: 67
diff changeset
2415 struct pg_edge_callback_data cbdata;
kono
parents: 67
diff changeset
2416 auto_bitmap sccs_to_merge;
kono
parents: 67
diff changeset
2417 auto_vec<enum partition_type> scc_types;
kono
parents: 67
diff changeset
2418 struct partition *partition, *first;
kono
parents: 67
diff changeset
2419
kono
parents: 67
diff changeset
2420 /* If all partitions in a SCC have the same type, we can simply merge the
kono
parents: 67
diff changeset
2421 SCC. This loop finds out such SCCS and record them in bitmap. */
kono
parents: 67
diff changeset
2422 bitmap_set_range (sccs_to_merge, 0, (unsigned) num_sccs);
kono
parents: 67
diff changeset
2423 for (i = 0; i < num_sccs; ++i)
kono
parents: 67
diff changeset
2424 {
kono
parents: 67
diff changeset
2425 for (j = 0; partitions->iterate (j, &first); ++j)
kono
parents: 67
diff changeset
2426 if (pg->vertices[j].component == i)
kono
parents: 67
diff changeset
2427 break;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2428
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2429 bool same_type = true, all_builtins = partition_builtin_p (first);
111
kono
parents: 67
diff changeset
2430 for (++j; partitions->iterate (j, &partition); ++j)
kono
parents: 67
diff changeset
2431 {
kono
parents: 67
diff changeset
2432 if (pg->vertices[j].component != i)
kono
parents: 67
diff changeset
2433 continue;
kono
parents: 67
diff changeset
2434
kono
parents: 67
diff changeset
2435 if (first->type != partition->type)
kono
parents: 67
diff changeset
2436 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2437 same_type = false;
111
kono
parents: 67
diff changeset
2438 break;
kono
parents: 67
diff changeset
2439 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2440 all_builtins &= partition_builtin_p (partition);
111
kono
parents: 67
diff changeset
2441 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2442 /* Merge SCC if all partitions in SCC have the same type, though the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2443 result partition is sequential, because vectorizer can do better
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2444 runtime alias check. One expecption is all partitions in SCC are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2445 builtins. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2446 if (!same_type || all_builtins)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2447 bitmap_clear_bit (sccs_to_merge, i);
111
kono
parents: 67
diff changeset
2448 }
kono
parents: 67
diff changeset
2449
kono
parents: 67
diff changeset
2450 /* Initialize callback data for traversing. */
kono
parents: 67
diff changeset
2451 cbdata.sccs_to_merge = sccs_to_merge;
kono
parents: 67
diff changeset
2452 cbdata.alias_ddrs = alias_ddrs;
kono
parents: 67
diff changeset
2453 cbdata.vertices_component = XNEWVEC (int, pg->n_vertices);
kono
parents: 67
diff changeset
2454 /* Record the component information which will be corrupted by next
kono
parents: 67
diff changeset
2455 graph scc finding call. */
kono
parents: 67
diff changeset
2456 for (i = 0; i < pg->n_vertices; ++i)
kono
parents: 67
diff changeset
2457 cbdata.vertices_component[i] = pg->vertices[i].component;
kono
parents: 67
diff changeset
2458
kono
parents: 67
diff changeset
2459 /* Collect data dependences for runtime alias checks to break SCCs. */
kono
parents: 67
diff changeset
2460 if (bitmap_count_bits (sccs_to_merge) != (unsigned) num_sccs)
kono
parents: 67
diff changeset
2461 {
kono
parents: 67
diff changeset
2462 /* Run SCC finding algorithm again, with alias dependence edges
kono
parents: 67
diff changeset
2463 skipped. This is to topologically sort partitions according to
kono
parents: 67
diff changeset
2464 compilation time known dependence. Note the topological order
kono
parents: 67
diff changeset
2465 is stored in the form of pg's post order number. */
kono
parents: 67
diff changeset
2466 num_sccs_no_alias = graphds_scc (pg, NULL, pg_skip_alias_edge);
kono
parents: 67
diff changeset
2467 gcc_assert (partitions->length () == (unsigned) num_sccs_no_alias);
kono
parents: 67
diff changeset
2468 /* With topological order, we can construct two subgraphs L and R.
kono
parents: 67
diff changeset
2469 L contains edge <x, y> where x < y in terms of post order, while
kono
parents: 67
diff changeset
2470 R contains edge <x, y> where x > y. Edges for compilation time
kono
parents: 67
diff changeset
2471 known dependence all fall in R, so we break SCCs by removing all
kono
parents: 67
diff changeset
2472 (alias) edges of in subgraph L. */
kono
parents: 67
diff changeset
2473 for_each_edge (pg, pg_collect_alias_ddrs, &cbdata);
kono
parents: 67
diff changeset
2474 }
kono
parents: 67
diff changeset
2475
kono
parents: 67
diff changeset
2476 /* For SCC that doesn't need to be broken, merge it. */
kono
parents: 67
diff changeset
2477 for (i = 0; i < num_sccs; ++i)
kono
parents: 67
diff changeset
2478 {
kono
parents: 67
diff changeset
2479 if (!bitmap_bit_p (sccs_to_merge, i))
kono
parents: 67
diff changeset
2480 continue;
kono
parents: 67
diff changeset
2481
kono
parents: 67
diff changeset
2482 for (j = 0; partitions->iterate (j, &first); ++j)
kono
parents: 67
diff changeset
2483 if (cbdata.vertices_component[j] == i)
kono
parents: 67
diff changeset
2484 break;
kono
parents: 67
diff changeset
2485 for (k = j + 1; partitions->iterate (k, &partition); ++k)
kono
parents: 67
diff changeset
2486 {
kono
parents: 67
diff changeset
2487 struct pg_vdata *data;
kono
parents: 67
diff changeset
2488
kono
parents: 67
diff changeset
2489 if (cbdata.vertices_component[k] != i)
kono
parents: 67
diff changeset
2490 continue;
kono
parents: 67
diff changeset
2491
kono
parents: 67
diff changeset
2492 /* Update postorder number so that merged reduction partition is
kono
parents: 67
diff changeset
2493 sorted after other partitions. */
kono
parents: 67
diff changeset
2494 if (!partition_reduction_p (first)
kono
parents: 67
diff changeset
2495 && partition_reduction_p (partition))
kono
parents: 67
diff changeset
2496 {
kono
parents: 67
diff changeset
2497 gcc_assert (pg->vertices[k].post < pg->vertices[j].post);
kono
parents: 67
diff changeset
2498 pg->vertices[j].post = pg->vertices[k].post;
kono
parents: 67
diff changeset
2499 }
kono
parents: 67
diff changeset
2500 partition_merge_into (NULL, first, partition, FUSE_SAME_SCC);
kono
parents: 67
diff changeset
2501 (*partitions)[k] = NULL;
kono
parents: 67
diff changeset
2502 partition_free (partition);
kono
parents: 67
diff changeset
2503 data = (struct pg_vdata *)pg->vertices[k].data;
kono
parents: 67
diff changeset
2504 gcc_assert (data->id == k);
kono
parents: 67
diff changeset
2505 data->partition = NULL;
kono
parents: 67
diff changeset
2506 /* The result partition of merged SCC must be sequential. */
kono
parents: 67
diff changeset
2507 first->type = PTYPE_SEQUENTIAL;
kono
parents: 67
diff changeset
2508 }
kono
parents: 67
diff changeset
2509 }
kono
parents: 67
diff changeset
2510 }
kono
parents: 67
diff changeset
2511
kono
parents: 67
diff changeset
2512 sort_partitions_by_post_order (pg, partitions);
kono
parents: 67
diff changeset
2513 free_partition_graph_vdata (pg);
kono
parents: 67
diff changeset
2514 for_each_edge (pg, free_partition_graph_edata_cb, NULL);
kono
parents: 67
diff changeset
2515 free_graph (pg);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2516
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2517 if (dump_file && (dump_flags & TDF_DETAILS))
111
kono
parents: 67
diff changeset
2518 {
kono
parents: 67
diff changeset
2519 fprintf (dump_file, "Possible alias data dependence to break:\n");
kono
parents: 67
diff changeset
2520 dump_data_dependence_relations (dump_file, *alias_ddrs);
kono
parents: 67
diff changeset
2521 }
kono
parents: 67
diff changeset
2522 }
kono
parents: 67
diff changeset
2523
kono
parents: 67
diff changeset
2524 /* Compute and return an expression whose value is the segment length which
kono
parents: 67
diff changeset
2525 will be accessed by DR in NITERS iterations. */
kono
parents: 67
diff changeset
2526
kono
parents: 67
diff changeset
2527 static tree
kono
parents: 67
diff changeset
2528 data_ref_segment_size (struct data_reference *dr, tree niters)
kono
parents: 67
diff changeset
2529 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2530 niters = size_binop (MINUS_EXPR,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2531 fold_convert (sizetype, niters),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2532 size_one_node);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2533 return size_binop (MULT_EXPR,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2534 fold_convert (sizetype, DR_STEP (dr)),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2535 fold_convert (sizetype, niters));
111
kono
parents: 67
diff changeset
2536 }
kono
parents: 67
diff changeset
2537
kono
parents: 67
diff changeset
2538 /* Return true if LOOP's latch is dominated by statement for data reference
kono
parents: 67
diff changeset
2539 DR. */
kono
parents: 67
diff changeset
2540
kono
parents: 67
diff changeset
2541 static inline bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2542 latch_dominated_by_data_ref (class loop *loop, data_reference *dr)
111
kono
parents: 67
diff changeset
2543 {
kono
parents: 67
diff changeset
2544 return dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
kono
parents: 67
diff changeset
2545 gimple_bb (DR_STMT (dr)));
kono
parents: 67
diff changeset
2546 }
kono
parents: 67
diff changeset
2547
kono
parents: 67
diff changeset
2548 /* Compute alias check pairs and store them in COMP_ALIAS_PAIRS for LOOP's
kono
parents: 67
diff changeset
2549 data dependence relations ALIAS_DDRS. */
kono
parents: 67
diff changeset
2550
kono
parents: 67
diff changeset
2551 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2552 compute_alias_check_pairs (class loop *loop, vec<ddr_p> *alias_ddrs,
111
kono
parents: 67
diff changeset
2553 vec<dr_with_seg_len_pair_t> *comp_alias_pairs)
kono
parents: 67
diff changeset
2554 {
kono
parents: 67
diff changeset
2555 unsigned int i;
kono
parents: 67
diff changeset
2556 unsigned HOST_WIDE_INT factor = 1;
kono
parents: 67
diff changeset
2557 tree niters_plus_one, niters = number_of_latch_executions (loop);
kono
parents: 67
diff changeset
2558
kono
parents: 67
diff changeset
2559 gcc_assert (niters != NULL_TREE && niters != chrec_dont_know);
kono
parents: 67
diff changeset
2560 niters = fold_convert (sizetype, niters);
kono
parents: 67
diff changeset
2561 niters_plus_one = size_binop (PLUS_EXPR, niters, size_one_node);
kono
parents: 67
diff changeset
2562
kono
parents: 67
diff changeset
2563 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
2564 fprintf (dump_file, "Creating alias check pairs:\n");
kono
parents: 67
diff changeset
2565
kono
parents: 67
diff changeset
2566 /* Iterate all data dependence relations and compute alias check pairs. */
kono
parents: 67
diff changeset
2567 for (i = 0; i < alias_ddrs->length (); i++)
kono
parents: 67
diff changeset
2568 {
kono
parents: 67
diff changeset
2569 ddr_p ddr = (*alias_ddrs)[i];
kono
parents: 67
diff changeset
2570 struct data_reference *dr_a = DDR_A (ddr);
kono
parents: 67
diff changeset
2571 struct data_reference *dr_b = DDR_B (ddr);
kono
parents: 67
diff changeset
2572 tree seg_length_a, seg_length_b;
kono
parents: 67
diff changeset
2573
kono
parents: 67
diff changeset
2574 if (latch_dominated_by_data_ref (loop, dr_a))
kono
parents: 67
diff changeset
2575 seg_length_a = data_ref_segment_size (dr_a, niters_plus_one);
kono
parents: 67
diff changeset
2576 else
kono
parents: 67
diff changeset
2577 seg_length_a = data_ref_segment_size (dr_a, niters);
kono
parents: 67
diff changeset
2578
kono
parents: 67
diff changeset
2579 if (latch_dominated_by_data_ref (loop, dr_b))
kono
parents: 67
diff changeset
2580 seg_length_b = data_ref_segment_size (dr_b, niters_plus_one);
kono
parents: 67
diff changeset
2581 else
kono
parents: 67
diff changeset
2582 seg_length_b = data_ref_segment_size (dr_b, niters);
kono
parents: 67
diff changeset
2583
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2584 unsigned HOST_WIDE_INT access_size_a
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2585 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a))));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2586 unsigned HOST_WIDE_INT access_size_b
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2587 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_b))));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2588 unsigned int align_a = TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_a)));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2589 unsigned int align_b = TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_b)));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2590
111
kono
parents: 67
diff changeset
2591 dr_with_seg_len_pair_t dr_with_seg_len_pair
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2592 (dr_with_seg_len (dr_a, seg_length_a, access_size_a, align_a),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2593 dr_with_seg_len (dr_b, seg_length_b, access_size_b, align_b),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2594 /* ??? Would WELL_ORDERED be safe? */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2595 dr_with_seg_len_pair_t::REORDERED);
111
kono
parents: 67
diff changeset
2596
kono
parents: 67
diff changeset
2597 comp_alias_pairs->safe_push (dr_with_seg_len_pair);
kono
parents: 67
diff changeset
2598 }
kono
parents: 67
diff changeset
2599
kono
parents: 67
diff changeset
2600 if (tree_fits_uhwi_p (niters))
kono
parents: 67
diff changeset
2601 factor = tree_to_uhwi (niters);
kono
parents: 67
diff changeset
2602
kono
parents: 67
diff changeset
2603 /* Prune alias check pairs. */
kono
parents: 67
diff changeset
2604 prune_runtime_alias_test_list (comp_alias_pairs, factor);
kono
parents: 67
diff changeset
2605 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
2606 fprintf (dump_file,
kono
parents: 67
diff changeset
2607 "Improved number of alias checks from %d to %d\n",
kono
parents: 67
diff changeset
2608 alias_ddrs->length (), comp_alias_pairs->length ());
kono
parents: 67
diff changeset
2609 }
kono
parents: 67
diff changeset
2610
kono
parents: 67
diff changeset
2611 /* Given data dependence relations in ALIAS_DDRS, generate runtime alias
kono
parents: 67
diff changeset
2612 checks and version LOOP under condition of these runtime alias checks. */
kono
parents: 67
diff changeset
2613
kono
parents: 67
diff changeset
2614 static void
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2615 version_loop_by_alias_check (vec<struct partition *> *partitions,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2616 class loop *loop, vec<ddr_p> *alias_ddrs)
111
kono
parents: 67
diff changeset
2617 {
kono
parents: 67
diff changeset
2618 profile_probability prob;
kono
parents: 67
diff changeset
2619 basic_block cond_bb;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2620 class loop *nloop;
111
kono
parents: 67
diff changeset
2621 tree lhs, arg0, cond_expr = NULL_TREE;
kono
parents: 67
diff changeset
2622 gimple_seq cond_stmts = NULL;
kono
parents: 67
diff changeset
2623 gimple *call_stmt = NULL;
kono
parents: 67
diff changeset
2624 auto_vec<dr_with_seg_len_pair_t> comp_alias_pairs;
kono
parents: 67
diff changeset
2625
kono
parents: 67
diff changeset
2626 /* Generate code for runtime alias checks if necessary. */
kono
parents: 67
diff changeset
2627 gcc_assert (alias_ddrs->length () > 0);
kono
parents: 67
diff changeset
2628
kono
parents: 67
diff changeset
2629 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
2630 fprintf (dump_file,
kono
parents: 67
diff changeset
2631 "Version loop <%d> with runtime alias check\n", loop->num);
kono
parents: 67
diff changeset
2632
kono
parents: 67
diff changeset
2633 compute_alias_check_pairs (loop, alias_ddrs, &comp_alias_pairs);
kono
parents: 67
diff changeset
2634 create_runtime_alias_checks (loop, &comp_alias_pairs, &cond_expr);
kono
parents: 67
diff changeset
2635 cond_expr = force_gimple_operand_1 (cond_expr, &cond_stmts,
kono
parents: 67
diff changeset
2636 is_gimple_val, NULL_TREE);
kono
parents: 67
diff changeset
2637
kono
parents: 67
diff changeset
2638 /* Depend on vectorizer to fold IFN_LOOP_DIST_ALIAS. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2639 bool cancelable_p = flag_tree_loop_vectorize;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2640 if (cancelable_p)
111
kono
parents: 67
diff changeset
2641 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2642 unsigned i = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2643 struct partition *partition;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2644 for (; partitions->iterate (i, &partition); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2645 if (!partition_builtin_p (partition))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2646 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2647
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2648 /* If all partitions are builtins, distributing it would be profitable and
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2649 we don't want to cancel the runtime alias checks. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2650 if (i == partitions->length ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2651 cancelable_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2652 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2653
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2654 /* Generate internal function call for loop distribution alias check if the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2655 runtime alias check should be cancelable. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2656 if (cancelable_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2657 {
111
kono
parents: 67
diff changeset
2658 call_stmt = gimple_build_call_internal (IFN_LOOP_DIST_ALIAS,
kono
parents: 67
diff changeset
2659 2, NULL_TREE, cond_expr);
kono
parents: 67
diff changeset
2660 lhs = make_ssa_name (boolean_type_node);
kono
parents: 67
diff changeset
2661 gimple_call_set_lhs (call_stmt, lhs);
kono
parents: 67
diff changeset
2662 }
kono
parents: 67
diff changeset
2663 else
kono
parents: 67
diff changeset
2664 lhs = cond_expr;
kono
parents: 67
diff changeset
2665
kono
parents: 67
diff changeset
2666 prob = profile_probability::guessed_always ().apply_scale (9, 10);
kono
parents: 67
diff changeset
2667 initialize_original_copy_tables ();
kono
parents: 67
diff changeset
2668 nloop = loop_version (loop, lhs, &cond_bb, prob, prob.invert (),
kono
parents: 67
diff changeset
2669 prob, prob.invert (), true);
kono
parents: 67
diff changeset
2670 free_original_copy_tables ();
kono
parents: 67
diff changeset
2671 /* Record the original loop number in newly generated loops. In case of
kono
parents: 67
diff changeset
2672 distribution, the original loop will be distributed and the new loop
kono
parents: 67
diff changeset
2673 is kept. */
kono
parents: 67
diff changeset
2674 loop->orig_loop_num = nloop->num;
kono
parents: 67
diff changeset
2675 nloop->orig_loop_num = nloop->num;
kono
parents: 67
diff changeset
2676 nloop->dont_vectorize = true;
kono
parents: 67
diff changeset
2677 nloop->force_vectorize = false;
kono
parents: 67
diff changeset
2678
kono
parents: 67
diff changeset
2679 if (call_stmt)
kono
parents: 67
diff changeset
2680 {
kono
parents: 67
diff changeset
2681 /* Record new loop's num in IFN_LOOP_DIST_ALIAS because the original
kono
parents: 67
diff changeset
2682 loop could be destroyed. */
kono
parents: 67
diff changeset
2683 arg0 = build_int_cst (integer_type_node, loop->orig_loop_num);
kono
parents: 67
diff changeset
2684 gimple_call_set_arg (call_stmt, 0, arg0);
kono
parents: 67
diff changeset
2685 gimple_seq_add_stmt_without_update (&cond_stmts, call_stmt);
kono
parents: 67
diff changeset
2686 }
kono
parents: 67
diff changeset
2687
kono
parents: 67
diff changeset
2688 if (cond_stmts)
kono
parents: 67
diff changeset
2689 {
kono
parents: 67
diff changeset
2690 gimple_stmt_iterator cond_gsi = gsi_last_bb (cond_bb);
kono
parents: 67
diff changeset
2691 gsi_insert_seq_before (&cond_gsi, cond_stmts, GSI_SAME_STMT);
kono
parents: 67
diff changeset
2692 }
kono
parents: 67
diff changeset
2693 update_ssa (TODO_update_ssa);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2694 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2695
111
kono
parents: 67
diff changeset
2696 /* Return true if loop versioning is needed to distrubute PARTITIONS.
kono
parents: 67
diff changeset
2697 ALIAS_DDRS are data dependence relations for runtime alias check. */
kono
parents: 67
diff changeset
2698
kono
parents: 67
diff changeset
2699 static inline bool
kono
parents: 67
diff changeset
2700 version_for_distribution_p (vec<struct partition *> *partitions,
kono
parents: 67
diff changeset
2701 vec<ddr_p> *alias_ddrs)
kono
parents: 67
diff changeset
2702 {
kono
parents: 67
diff changeset
2703 /* No need to version loop if we have only one partition. */
kono
parents: 67
diff changeset
2704 if (partitions->length () == 1)
kono
parents: 67
diff changeset
2705 return false;
kono
parents: 67
diff changeset
2706
kono
parents: 67
diff changeset
2707 /* Need to version loop if runtime alias check is necessary. */
kono
parents: 67
diff changeset
2708 return (alias_ddrs->length () > 0);
kono
parents: 67
diff changeset
2709 }
kono
parents: 67
diff changeset
2710
kono
parents: 67
diff changeset
2711 /* Compare base offset of builtin mem* partitions P1 and P2. */
kono
parents: 67
diff changeset
2712
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2713 static int
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2714 offset_cmp (const void *vp1, const void *vp2)
111
kono
parents: 67
diff changeset
2715 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2716 struct partition *p1 = *(struct partition *const *) vp1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2717 struct partition *p2 = *(struct partition *const *) vp2;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2718 unsigned HOST_WIDE_INT o1 = p1->builtin->dst_base_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2719 unsigned HOST_WIDE_INT o2 = p2->builtin->dst_base_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2720 return (o2 < o1) - (o1 < o2);
111
kono
parents: 67
diff changeset
2721 }
kono
parents: 67
diff changeset
2722
kono
parents: 67
diff changeset
2723 /* Fuse adjacent memset builtin PARTITIONS if possible. This is a special
kono
parents: 67
diff changeset
2724 case optimization transforming below code:
kono
parents: 67
diff changeset
2725
kono
parents: 67
diff changeset
2726 __builtin_memset (&obj, 0, 100);
kono
parents: 67
diff changeset
2727 _1 = &obj + 100;
kono
parents: 67
diff changeset
2728 __builtin_memset (_1, 0, 200);
kono
parents: 67
diff changeset
2729 _2 = &obj + 300;
kono
parents: 67
diff changeset
2730 __builtin_memset (_2, 0, 100);
kono
parents: 67
diff changeset
2731
kono
parents: 67
diff changeset
2732 into:
kono
parents: 67
diff changeset
2733
kono
parents: 67
diff changeset
2734 __builtin_memset (&obj, 0, 400);
kono
parents: 67
diff changeset
2735
kono
parents: 67
diff changeset
2736 Note we don't have dependence information between different partitions
kono
parents: 67
diff changeset
2737 at this point, as a result, we can't handle nonadjacent memset builtin
kono
parents: 67
diff changeset
2738 partitions since dependence might be broken. */
kono
parents: 67
diff changeset
2739
kono
parents: 67
diff changeset
2740 static void
kono
parents: 67
diff changeset
2741 fuse_memset_builtins (vec<struct partition *> *partitions)
kono
parents: 67
diff changeset
2742 {
kono
parents: 67
diff changeset
2743 unsigned i, j;
kono
parents: 67
diff changeset
2744 struct partition *part1, *part2;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2745 tree rhs1, rhs2;
111
kono
parents: 67
diff changeset
2746
kono
parents: 67
diff changeset
2747 for (i = 0; partitions->iterate (i, &part1);)
kono
parents: 67
diff changeset
2748 {
kono
parents: 67
diff changeset
2749 if (part1->kind != PKIND_MEMSET)
kono
parents: 67
diff changeset
2750 {
kono
parents: 67
diff changeset
2751 i++;
kono
parents: 67
diff changeset
2752 continue;
kono
parents: 67
diff changeset
2753 }
kono
parents: 67
diff changeset
2754
kono
parents: 67
diff changeset
2755 /* Find sub-array of memset builtins of the same base. Index range
kono
parents: 67
diff changeset
2756 of the sub-array is [i, j) with "j > i". */
kono
parents: 67
diff changeset
2757 for (j = i + 1; partitions->iterate (j, &part2); ++j)
kono
parents: 67
diff changeset
2758 {
kono
parents: 67
diff changeset
2759 if (part2->kind != PKIND_MEMSET
kono
parents: 67
diff changeset
2760 || !operand_equal_p (part1->builtin->dst_base_base,
kono
parents: 67
diff changeset
2761 part2->builtin->dst_base_base, 0))
kono
parents: 67
diff changeset
2762 break;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2763
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2764 /* Memset calls setting different values can't be merged. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2765 rhs1 = gimple_assign_rhs1 (DR_STMT (part1->builtin->dst_dr));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2766 rhs2 = gimple_assign_rhs1 (DR_STMT (part2->builtin->dst_dr));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2767 if (!operand_equal_p (rhs1, rhs2, 0))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2768 break;
111
kono
parents: 67
diff changeset
2769 }
kono
parents: 67
diff changeset
2770
kono
parents: 67
diff changeset
2771 /* Stable sort is required in order to avoid breaking dependence. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2772 gcc_stablesort (&(*partitions)[i], j - i, sizeof (*partitions)[i],
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2773 offset_cmp);
111
kono
parents: 67
diff changeset
2774 /* Continue with next partition. */
kono
parents: 67
diff changeset
2775 i = j;
kono
parents: 67
diff changeset
2776 }
kono
parents: 67
diff changeset
2777
kono
parents: 67
diff changeset
2778 /* Merge all consecutive memset builtin partitions. */
kono
parents: 67
diff changeset
2779 for (i = 0; i < partitions->length () - 1;)
kono
parents: 67
diff changeset
2780 {
kono
parents: 67
diff changeset
2781 part1 = (*partitions)[i];
kono
parents: 67
diff changeset
2782 if (part1->kind != PKIND_MEMSET)
kono
parents: 67
diff changeset
2783 {
kono
parents: 67
diff changeset
2784 i++;
kono
parents: 67
diff changeset
2785 continue;
kono
parents: 67
diff changeset
2786 }
kono
parents: 67
diff changeset
2787
kono
parents: 67
diff changeset
2788 part2 = (*partitions)[i + 1];
kono
parents: 67
diff changeset
2789 /* Only merge memset partitions of the same base and with constant
kono
parents: 67
diff changeset
2790 access sizes. */
kono
parents: 67
diff changeset
2791 if (part2->kind != PKIND_MEMSET
kono
parents: 67
diff changeset
2792 || TREE_CODE (part1->builtin->size) != INTEGER_CST
kono
parents: 67
diff changeset
2793 || TREE_CODE (part2->builtin->size) != INTEGER_CST
kono
parents: 67
diff changeset
2794 || !operand_equal_p (part1->builtin->dst_base_base,
kono
parents: 67
diff changeset
2795 part2->builtin->dst_base_base, 0))
kono
parents: 67
diff changeset
2796 {
kono
parents: 67
diff changeset
2797 i++;
kono
parents: 67
diff changeset
2798 continue;
kono
parents: 67
diff changeset
2799 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2800 rhs1 = gimple_assign_rhs1 (DR_STMT (part1->builtin->dst_dr));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2801 rhs2 = gimple_assign_rhs1 (DR_STMT (part2->builtin->dst_dr));
111
kono
parents: 67
diff changeset
2802 int bytev1 = const_with_all_bytes_same (rhs1);
kono
parents: 67
diff changeset
2803 int bytev2 = const_with_all_bytes_same (rhs2);
kono
parents: 67
diff changeset
2804 /* Only merge memset partitions of the same value. */
kono
parents: 67
diff changeset
2805 if (bytev1 != bytev2 || bytev1 == -1)
kono
parents: 67
diff changeset
2806 {
kono
parents: 67
diff changeset
2807 i++;
kono
parents: 67
diff changeset
2808 continue;
kono
parents: 67
diff changeset
2809 }
kono
parents: 67
diff changeset
2810 wide_int end1 = wi::add (part1->builtin->dst_base_offset,
kono
parents: 67
diff changeset
2811 wi::to_wide (part1->builtin->size));
kono
parents: 67
diff changeset
2812 /* Only merge adjacent memset partitions. */
kono
parents: 67
diff changeset
2813 if (wi::ne_p (end1, part2->builtin->dst_base_offset))
kono
parents: 67
diff changeset
2814 {
kono
parents: 67
diff changeset
2815 i++;
kono
parents: 67
diff changeset
2816 continue;
kono
parents: 67
diff changeset
2817 }
kono
parents: 67
diff changeset
2818 /* Merge partitions[i] and partitions[i+1]. */
kono
parents: 67
diff changeset
2819 part1->builtin->size = fold_build2 (PLUS_EXPR, sizetype,
kono
parents: 67
diff changeset
2820 part1->builtin->size,
kono
parents: 67
diff changeset
2821 part2->builtin->size);
kono
parents: 67
diff changeset
2822 partition_free (part2);
kono
parents: 67
diff changeset
2823 partitions->ordered_remove (i + 1);
kono
parents: 67
diff changeset
2824 }
kono
parents: 67
diff changeset
2825 }
kono
parents: 67
diff changeset
2826
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2827 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2828 loop_distribution::finalize_partitions (class loop *loop,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2829 vec<struct partition *> *partitions,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2830 vec<ddr_p> *alias_ddrs)
111
kono
parents: 67
diff changeset
2831 {
kono
parents: 67
diff changeset
2832 unsigned i;
kono
parents: 67
diff changeset
2833 struct partition *partition, *a;
kono
parents: 67
diff changeset
2834
kono
parents: 67
diff changeset
2835 if (partitions->length () == 1
kono
parents: 67
diff changeset
2836 || alias_ddrs->length () > 0)
kono
parents: 67
diff changeset
2837 return;
kono
parents: 67
diff changeset
2838
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2839 unsigned num_builtin = 0, num_normal = 0, num_partial_memset = 0;
111
kono
parents: 67
diff changeset
2840 bool same_type_p = true;
kono
parents: 67
diff changeset
2841 enum partition_type type = ((*partitions)[0])->type;
kono
parents: 67
diff changeset
2842 for (i = 0; partitions->iterate (i, &partition); ++i)
kono
parents: 67
diff changeset
2843 {
kono
parents: 67
diff changeset
2844 same_type_p &= (type == partition->type);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2845 if (partition_builtin_p (partition))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2846 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2847 num_builtin++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2848 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2849 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2850 num_normal++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2851 if (partition->kind == PKIND_PARTIAL_MEMSET)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2852 num_partial_memset++;
111
kono
parents: 67
diff changeset
2853 }
kono
parents: 67
diff changeset
2854
kono
parents: 67
diff changeset
2855 /* Don't distribute current loop into too many loops given we don't have
kono
parents: 67
diff changeset
2856 memory stream cost model. Be even more conservative in case of loop
kono
parents: 67
diff changeset
2857 nest distribution. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2858 if ((same_type_p && num_builtin == 0
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2859 && (loop->inner == NULL || num_normal != 2 || num_partial_memset != 1))
111
kono
parents: 67
diff changeset
2860 || (loop->inner != NULL
kono
parents: 67
diff changeset
2861 && i >= NUM_PARTITION_THRESHOLD && num_normal > 1)
kono
parents: 67
diff changeset
2862 || (loop->inner == NULL
kono
parents: 67
diff changeset
2863 && i >= NUM_PARTITION_THRESHOLD && num_normal > num_builtin))
kono
parents: 67
diff changeset
2864 {
kono
parents: 67
diff changeset
2865 a = (*partitions)[0];
kono
parents: 67
diff changeset
2866 for (i = 1; partitions->iterate (i, &partition); ++i)
kono
parents: 67
diff changeset
2867 {
kono
parents: 67
diff changeset
2868 partition_merge_into (NULL, a, partition, FUSE_FINALIZE);
kono
parents: 67
diff changeset
2869 partition_free (partition);
kono
parents: 67
diff changeset
2870 }
kono
parents: 67
diff changeset
2871 partitions->truncate (1);
kono
parents: 67
diff changeset
2872 }
kono
parents: 67
diff changeset
2873
kono
parents: 67
diff changeset
2874 /* Fuse memset builtins if possible. */
kono
parents: 67
diff changeset
2875 if (partitions->length () > 1)
kono
parents: 67
diff changeset
2876 fuse_memset_builtins (partitions);
kono
parents: 67
diff changeset
2877 }
kono
parents: 67
diff changeset
2878
kono
parents: 67
diff changeset
2879 /* Distributes the code from LOOP in such a way that producer statements
kono
parents: 67
diff changeset
2880 are placed before consumer statements. Tries to separate only the
kono
parents: 67
diff changeset
2881 statements from STMTS into separate loops. Returns the number of
kono
parents: 67
diff changeset
2882 distributed loops. Set NB_CALLS to number of generated builtin calls.
kono
parents: 67
diff changeset
2883 Set *DESTROY_P to whether LOOP needs to be destroyed. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2884
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2885 int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2886 loop_distribution::distribute_loop (class loop *loop, vec<gimple *> stmts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2887 control_dependences *cd, int *nb_calls, bool *destroy_p,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2888 bool only_patterns_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2889 {
111
kono
parents: 67
diff changeset
2890 ddrs_table = new hash_table<ddr_hasher> (389);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2891 struct graph *rdg;
111
kono
parents: 67
diff changeset
2892 partition *partition;
kono
parents: 67
diff changeset
2893 int i, nbp;
kono
parents: 67
diff changeset
2894
kono
parents: 67
diff changeset
2895 *destroy_p = false;
kono
parents: 67
diff changeset
2896 *nb_calls = 0;
kono
parents: 67
diff changeset
2897 loop_nest.create (0);
kono
parents: 67
diff changeset
2898 if (!find_loop_nest (loop, &loop_nest))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2899 {
111
kono
parents: 67
diff changeset
2900 loop_nest.release ();
kono
parents: 67
diff changeset
2901 delete ddrs_table;
kono
parents: 67
diff changeset
2902 return 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2903 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2904
111
kono
parents: 67
diff changeset
2905 datarefs_vec.create (20);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2906 has_nonaddressable_dataref_p = false;
111
kono
parents: 67
diff changeset
2907 rdg = build_rdg (loop, cd);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2908 if (!rdg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2909 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2910 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2911 fprintf (dump_file,
111
kono
parents: 67
diff changeset
2912 "Loop %d not distributed: failed to build the RDG.\n",
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2913 loop->num);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2914
111
kono
parents: 67
diff changeset
2915 loop_nest.release ();
kono
parents: 67
diff changeset
2916 free_data_refs (datarefs_vec);
kono
parents: 67
diff changeset
2917 delete ddrs_table;
kono
parents: 67
diff changeset
2918 return 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2919 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2920
111
kono
parents: 67
diff changeset
2921 if (datarefs_vec.length () > MAX_DATAREFS_NUM)
kono
parents: 67
diff changeset
2922 {
kono
parents: 67
diff changeset
2923 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
2924 fprintf (dump_file,
kono
parents: 67
diff changeset
2925 "Loop %d not distributed: too many memory references.\n",
kono
parents: 67
diff changeset
2926 loop->num);
kono
parents: 67
diff changeset
2927
kono
parents: 67
diff changeset
2928 free_rdg (rdg);
kono
parents: 67
diff changeset
2929 loop_nest.release ();
kono
parents: 67
diff changeset
2930 free_data_refs (datarefs_vec);
kono
parents: 67
diff changeset
2931 delete ddrs_table;
kono
parents: 67
diff changeset
2932 return 0;
kono
parents: 67
diff changeset
2933 }
kono
parents: 67
diff changeset
2934
kono
parents: 67
diff changeset
2935 data_reference_p dref;
kono
parents: 67
diff changeset
2936 for (i = 0; datarefs_vec.iterate (i, &dref); ++i)
kono
parents: 67
diff changeset
2937 dref->aux = (void *) (uintptr_t) i;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2938
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2939 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2940 dump_rdg (dump_file, rdg);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2941
111
kono
parents: 67
diff changeset
2942 auto_vec<struct partition *, 3> partitions;
kono
parents: 67
diff changeset
2943 rdg_build_partitions (rdg, stmts, &partitions);
kono
parents: 67
diff changeset
2944
kono
parents: 67
diff changeset
2945 auto_vec<ddr_p> alias_ddrs;
kono
parents: 67
diff changeset
2946
kono
parents: 67
diff changeset
2947 auto_bitmap stmt_in_all_partitions;
kono
parents: 67
diff changeset
2948 bitmap_copy (stmt_in_all_partitions, partitions[0]->stmts);
kono
parents: 67
diff changeset
2949 for (i = 1; partitions.iterate (i, &partition); ++i)
kono
parents: 67
diff changeset
2950 bitmap_and_into (stmt_in_all_partitions, partitions[i]->stmts);
kono
parents: 67
diff changeset
2951
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2952 bool any_builtin = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2953 bool reduction_in_all = false;
111
kono
parents: 67
diff changeset
2954 FOR_EACH_VEC_ELT (partitions, i, partition)
kono
parents: 67
diff changeset
2955 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2956 reduction_in_all
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2957 |= classify_partition (loop, rdg, partition, stmt_in_all_partitions);
111
kono
parents: 67
diff changeset
2958 any_builtin |= partition_builtin_p (partition);
kono
parents: 67
diff changeset
2959 }
kono
parents: 67
diff changeset
2960
kono
parents: 67
diff changeset
2961 /* If we are only distributing patterns but did not detect any,
kono
parents: 67
diff changeset
2962 simply bail out. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2963 if (only_patterns_p
111
kono
parents: 67
diff changeset
2964 && !any_builtin)
kono
parents: 67
diff changeset
2965 {
kono
parents: 67
diff changeset
2966 nbp = 0;
kono
parents: 67
diff changeset
2967 goto ldist_done;
kono
parents: 67
diff changeset
2968 }
kono
parents: 67
diff changeset
2969
kono
parents: 67
diff changeset
2970 /* If we are only distributing patterns fuse all partitions that
kono
parents: 67
diff changeset
2971 were not classified as builtins. This also avoids chopping
kono
parents: 67
diff changeset
2972 a loop into pieces, separated by builtin calls. That is, we
kono
parents: 67
diff changeset
2973 only want no or a single loop body remaining. */
kono
parents: 67
diff changeset
2974 struct partition *into;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2975 if (only_patterns_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2976 {
111
kono
parents: 67
diff changeset
2977 for (i = 0; partitions.iterate (i, &into); ++i)
kono
parents: 67
diff changeset
2978 if (!partition_builtin_p (into))
kono
parents: 67
diff changeset
2979 break;
kono
parents: 67
diff changeset
2980 for (++i; partitions.iterate (i, &partition); ++i)
kono
parents: 67
diff changeset
2981 if (!partition_builtin_p (partition))
kono
parents: 67
diff changeset
2982 {
kono
parents: 67
diff changeset
2983 partition_merge_into (NULL, into, partition, FUSE_NON_BUILTIN);
kono
parents: 67
diff changeset
2984 partitions.unordered_remove (i);
kono
parents: 67
diff changeset
2985 partition_free (partition);
kono
parents: 67
diff changeset
2986 i--;
kono
parents: 67
diff changeset
2987 }
kono
parents: 67
diff changeset
2988 }
kono
parents: 67
diff changeset
2989
kono
parents: 67
diff changeset
2990 /* Due to limitations in the transform phase we have to fuse all
kono
parents: 67
diff changeset
2991 reduction partitions into the last partition so the existing
kono
parents: 67
diff changeset
2992 loop will contain all loop-closed PHI nodes. */
kono
parents: 67
diff changeset
2993 for (i = 0; partitions.iterate (i, &into); ++i)
kono
parents: 67
diff changeset
2994 if (partition_reduction_p (into))
kono
parents: 67
diff changeset
2995 break;
kono
parents: 67
diff changeset
2996 for (i = i + 1; partitions.iterate (i, &partition); ++i)
kono
parents: 67
diff changeset
2997 if (partition_reduction_p (partition))
kono
parents: 67
diff changeset
2998 {
kono
parents: 67
diff changeset
2999 partition_merge_into (rdg, into, partition, FUSE_REDUCTION);
kono
parents: 67
diff changeset
3000 partitions.unordered_remove (i);
kono
parents: 67
diff changeset
3001 partition_free (partition);
kono
parents: 67
diff changeset
3002 i--;
kono
parents: 67
diff changeset
3003 }
kono
parents: 67
diff changeset
3004
kono
parents: 67
diff changeset
3005 /* Apply our simple cost model - fuse partitions with similar
kono
parents: 67
diff changeset
3006 memory accesses. */
kono
parents: 67
diff changeset
3007 for (i = 0; partitions.iterate (i, &into); ++i)
kono
parents: 67
diff changeset
3008 {
kono
parents: 67
diff changeset
3009 bool changed = false;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3010 if (partition_builtin_p (into) || into->kind == PKIND_PARTIAL_MEMSET)
111
kono
parents: 67
diff changeset
3011 continue;
kono
parents: 67
diff changeset
3012 for (int j = i + 1;
kono
parents: 67
diff changeset
3013 partitions.iterate (j, &partition); ++j)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3014 {
111
kono
parents: 67
diff changeset
3015 if (share_memory_accesses (rdg, into, partition))
kono
parents: 67
diff changeset
3016 {
kono
parents: 67
diff changeset
3017 partition_merge_into (rdg, into, partition, FUSE_SHARE_REF);
kono
parents: 67
diff changeset
3018 partitions.unordered_remove (j);
kono
parents: 67
diff changeset
3019 partition_free (partition);
kono
parents: 67
diff changeset
3020 j--;
kono
parents: 67
diff changeset
3021 changed = true;
kono
parents: 67
diff changeset
3022 }
kono
parents: 67
diff changeset
3023 }
kono
parents: 67
diff changeset
3024 /* If we fused 0 1 2 in step 1 to 0,2 1 as 0 and 2 have similar
kono
parents: 67
diff changeset
3025 accesses when 1 and 2 have similar accesses but not 0 and 1
kono
parents: 67
diff changeset
3026 then in the next iteration we will fail to consider merging
kono
parents: 67
diff changeset
3027 1 into 0,2. So try again if we did any merging into 0. */
kono
parents: 67
diff changeset
3028 if (changed)
kono
parents: 67
diff changeset
3029 i--;
kono
parents: 67
diff changeset
3030 }
kono
parents: 67
diff changeset
3031
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3032 /* Put a non-builtin partition last if we need to preserve a reduction.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3033 ??? This is a workaround that makes sort_partitions_by_post_order do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3034 the correct thing while in reality it should sort each component
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3035 separately and then put the component with a reduction or a non-builtin
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3036 last. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3037 if (reduction_in_all
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3038 && partition_builtin_p (partitions.last()))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3039 FOR_EACH_VEC_ELT (partitions, i, partition)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3040 if (!partition_builtin_p (partition))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3041 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3042 partitions.unordered_remove (i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3043 partitions.quick_push (partition);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3044 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3045 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3046
111
kono
parents: 67
diff changeset
3047 /* Build the partition dependency graph and fuse partitions in strong
kono
parents: 67
diff changeset
3048 connected component. */
kono
parents: 67
diff changeset
3049 if (partitions.length () > 1)
kono
parents: 67
diff changeset
3050 {
kono
parents: 67
diff changeset
3051 /* Don't support loop nest distribution under runtime alias check
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3052 since it's not likely to enable many vectorization opportunities.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3053 Also if loop has any data reference which may be not addressable
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3054 since alias check needs to take, compare address of the object. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3055 if (loop->inner || has_nonaddressable_dataref_p)
111
kono
parents: 67
diff changeset
3056 merge_dep_scc_partitions (rdg, &partitions, false);
kono
parents: 67
diff changeset
3057 else
kono
parents: 67
diff changeset
3058 {
kono
parents: 67
diff changeset
3059 merge_dep_scc_partitions (rdg, &partitions, true);
kono
parents: 67
diff changeset
3060 if (partitions.length () > 1)
kono
parents: 67
diff changeset
3061 break_alias_scc_partitions (rdg, &partitions, &alias_ddrs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3062 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3063 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3064
111
kono
parents: 67
diff changeset
3065 finalize_partitions (loop, &partitions, &alias_ddrs);
kono
parents: 67
diff changeset
3066
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3067 /* If there is a reduction in all partitions make sure the last one
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3068 is not classified for builtin code generation. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3069 if (reduction_in_all)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3070 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3071 partition = partitions.last ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3072 if (only_patterns_p
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3073 && partition_builtin_p (partition)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3074 && !partition_builtin_p (partitions[0]))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3075 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3076 nbp = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3077 goto ldist_done;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3078 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3079 partition->kind = PKIND_NORMAL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3080 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3081
111
kono
parents: 67
diff changeset
3082 nbp = partitions.length ();
kono
parents: 67
diff changeset
3083 if (nbp == 0
kono
parents: 67
diff changeset
3084 || (nbp == 1 && !partition_builtin_p (partitions[0]))
kono
parents: 67
diff changeset
3085 || (nbp > 1 && partition_contains_all_rw (rdg, partitions)))
kono
parents: 67
diff changeset
3086 {
kono
parents: 67
diff changeset
3087 nbp = 0;
kono
parents: 67
diff changeset
3088 goto ldist_done;
kono
parents: 67
diff changeset
3089 }
kono
parents: 67
diff changeset
3090
kono
parents: 67
diff changeset
3091 if (version_for_distribution_p (&partitions, &alias_ddrs))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3092 version_loop_by_alias_check (&partitions, loop, &alias_ddrs);
111
kono
parents: 67
diff changeset
3093
kono
parents: 67
diff changeset
3094 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
3095 {
kono
parents: 67
diff changeset
3096 fprintf (dump_file,
kono
parents: 67
diff changeset
3097 "distribute loop <%d> into partitions:\n", loop->num);
kono
parents: 67
diff changeset
3098 dump_rdg_partitions (dump_file, partitions);
kono
parents: 67
diff changeset
3099 }
kono
parents: 67
diff changeset
3100
kono
parents: 67
diff changeset
3101 FOR_EACH_VEC_ELT (partitions, i, partition)
kono
parents: 67
diff changeset
3102 {
kono
parents: 67
diff changeset
3103 if (partition_builtin_p (partition))
kono
parents: 67
diff changeset
3104 (*nb_calls)++;
kono
parents: 67
diff changeset
3105 *destroy_p |= generate_code_for_partition (loop, partition, i < nbp - 1);
kono
parents: 67
diff changeset
3106 }
kono
parents: 67
diff changeset
3107
kono
parents: 67
diff changeset
3108 ldist_done:
kono
parents: 67
diff changeset
3109 loop_nest.release ();
kono
parents: 67
diff changeset
3110 free_data_refs (datarefs_vec);
kono
parents: 67
diff changeset
3111 for (hash_table<ddr_hasher>::iterator iter = ddrs_table->begin ();
kono
parents: 67
diff changeset
3112 iter != ddrs_table->end (); ++iter)
kono
parents: 67
diff changeset
3113 {
kono
parents: 67
diff changeset
3114 free_dependence_relation (*iter);
kono
parents: 67
diff changeset
3115 *iter = NULL;
kono
parents: 67
diff changeset
3116 }
kono
parents: 67
diff changeset
3117 delete ddrs_table;
kono
parents: 67
diff changeset
3118
kono
parents: 67
diff changeset
3119 FOR_EACH_VEC_ELT (partitions, i, partition)
kono
parents: 67
diff changeset
3120 partition_free (partition);
kono
parents: 67
diff changeset
3121
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3122 free_rdg (rdg);
111
kono
parents: 67
diff changeset
3123 return nbp - *nb_calls;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3124 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3125
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3126
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3127 void loop_distribution::bb_top_order_init (void)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3128 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3129 int rpo_num;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3130 int *rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3131
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3132 bb_top_order_index = XNEWVEC (int, last_basic_block_for_fn (cfun));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3133 bb_top_order_index_size = last_basic_block_for_fn (cfun);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3134 rpo_num = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, true);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3135 for (int i = 0; i < rpo_num; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3136 bb_top_order_index[rpo[i]] = i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3137
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3138 free (rpo);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3139 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3140
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3141 void loop_distribution::bb_top_order_destroy ()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3142 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3143 free (bb_top_order_index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3144 bb_top_order_index = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3145 bb_top_order_index_size = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3146 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3147
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3148
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3149 /* Given LOOP, this function records seed statements for distribution in
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3150 WORK_LIST. Return false if there is nothing for distribution. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3151
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3152 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3153 find_seed_stmts_for_distribution (class loop *loop, vec<gimple *> *work_list)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3154 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3155 basic_block *bbs = get_loop_body_in_dom_order (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3156
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3157 /* Initialize the worklist with stmts we seed the partitions with. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3158 for (unsigned i = 0; i < loop->num_nodes; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3159 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3160 for (gphi_iterator gsi = gsi_start_phis (bbs[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3161 !gsi_end_p (gsi); gsi_next (&gsi))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3162 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3163 gphi *phi = gsi.phi ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3164 if (virtual_operand_p (gimple_phi_result (phi)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3165 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3166 /* Distribute stmts which have defs that are used outside of
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3167 the loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3168 if (!stmt_has_scalar_dependences_outside_loop (loop, phi))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3169 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3170 work_list->safe_push (phi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3171 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3172 for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3173 !gsi_end_p (gsi); gsi_next (&gsi))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3174 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3175 gimple *stmt = gsi_stmt (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3176
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3177 /* Ignore clobbers, they do not have true side effects. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3178 if (gimple_clobber_p (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3179 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3180
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3181 /* If there is a stmt with side-effects bail out - we
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3182 cannot and should not distribute this loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3183 if (gimple_has_side_effects (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3184 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3185 free (bbs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3186 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3187 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3188
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3189 /* Distribute stmts which have defs that are used outside of
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3190 the loop. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3191 if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3192 ;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3193 /* Otherwise only distribute stores for now. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3194 else if (!gimple_vdef (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3195 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3196
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3197 work_list->safe_push (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3198 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3199 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3200 free (bbs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3201 return work_list->length () > 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3202 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3203
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3204 /* Given innermost LOOP, return the outermost enclosing loop that forms a
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3205 perfect loop nest. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3206
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3207 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3208 prepare_perfect_loop_nest (class loop *loop)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3209 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3210 class loop *outer = loop_outer (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3211 tree niters = number_of_latch_executions (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3212
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3213 /* TODO: We only support the innermost 3-level loop nest distribution
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3214 because of compilation time issue for now. This should be relaxed
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3215 in the future. Note we only allow 3-level loop nest distribution
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3216 when parallelizing loops. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3217 while ((loop->inner == NULL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3218 || (loop->inner->inner == NULL && flag_tree_parallelize_loops > 1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3219 && loop_outer (outer)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3220 && outer->inner == loop && loop->next == NULL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3221 && single_exit (outer)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3222 && !chrec_contains_symbols_defined_in_loop (niters, outer->num)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3223 && (niters = number_of_latch_executions (outer)) != NULL_TREE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3224 && niters != chrec_dont_know)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3225 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3226 loop = outer;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3227 outer = loop_outer (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3228 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3229
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3230 return loop;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3231 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3232
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3233
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3234 unsigned int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3235 loop_distribution::execute (function *fun)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3236 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3237 class loop *loop;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3238 bool changed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3239 basic_block bb;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3240 control_dependences *cd = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3241 auto_vec<loop_p> loops_to_be_destroyed;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3242
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3243 if (number_of_loops (fun) <= 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3244 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3245
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3246 bb_top_order_init ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3247
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3248 FOR_ALL_BB_FN (bb, fun)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3249 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3250 gimple_stmt_iterator gsi;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3251 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3252 gimple_set_uid (gsi_stmt (gsi), -1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3253 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3254 gimple_set_uid (gsi_stmt (gsi), -1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3255 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3256
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3257 /* We can at the moment only distribute non-nested loops, thus restrict
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3258 walking to innermost loops. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3259 FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3260 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3261 /* Don't distribute multiple exit edges loop, or cold loop when
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3262 not doing pattern detection. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3263 if (!single_exit (loop)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3264 || (!flag_tree_loop_distribute_patterns
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3265 && !optimize_loop_for_speed_p (loop)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3266 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3267
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3268 /* Don't distribute loop if niters is unknown. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3269 tree niters = number_of_latch_executions (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3270 if (niters == NULL_TREE || niters == chrec_dont_know)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3271 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3272
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3273 /* Get the perfect loop nest for distribution. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3274 loop = prepare_perfect_loop_nest (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3275 for (; loop; loop = loop->inner)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3276 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3277 auto_vec<gimple *> work_list;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3278 if (!find_seed_stmts_for_distribution (loop, &work_list))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3279 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3280
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3281 const char *str = loop->inner ? " nest" : "";
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3282 dump_user_location_t loc = find_loop_location (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3283 if (!cd)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3284 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3285 calculate_dominance_info (CDI_DOMINATORS);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3286 calculate_dominance_info (CDI_POST_DOMINATORS);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3287 cd = new control_dependences ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3288 free_dominance_info (CDI_POST_DOMINATORS);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3289 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3290
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3291 bool destroy_p;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3292 int nb_generated_loops, nb_generated_calls;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3293 nb_generated_loops
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3294 = distribute_loop (loop, work_list, cd, &nb_generated_calls,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3295 &destroy_p, (!optimize_loop_for_speed_p (loop)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3296 || !flag_tree_loop_distribution));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3297 if (destroy_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3298 loops_to_be_destroyed.safe_push (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3299
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3300 if (nb_generated_loops + nb_generated_calls > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3301 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3302 changed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3303 if (dump_enabled_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3304 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3305 loc, "Loop%s %d distributed: split to %d loops "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3306 "and %d library calls.\n", str, loop->num,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3307 nb_generated_loops, nb_generated_calls);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3308
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3309 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3310 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3311
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3312 if (dump_file && (dump_flags & TDF_DETAILS))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3313 fprintf (dump_file, "Loop%s %d not distributed.\n", str, loop->num);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3314 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3315 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3316
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3317 if (cd)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3318 delete cd;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3319
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3320 if (bb_top_order_index != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3321 bb_top_order_destroy ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3322
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3323 if (changed)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3324 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3325 /* Destroy loop bodies that could not be reused. Do this late as we
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3326 otherwise can end up refering to stale data in control dependences. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3327 unsigned i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3328 FOR_EACH_VEC_ELT (loops_to_be_destroyed, i, loop)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3329 destroy_loop (loop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3330
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3331 /* Cached scalar evolutions now may refer to wrong or non-existing
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3332 loops. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3333 scev_reset_htab ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3334 mark_virtual_operands_for_renaming (fun);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3335 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3336 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3337
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3338 checking_verify_loop_structure ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3339
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3340 return changed ? TODO_cleanup_cfg : 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3341 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3342
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3343
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3344 /* Distribute all loops in the current function. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3345
111
kono
parents: 67
diff changeset
3346 namespace {
kono
parents: 67
diff changeset
3347
kono
parents: 67
diff changeset
3348 const pass_data pass_data_loop_distribution =
kono
parents: 67
diff changeset
3349 {
kono
parents: 67
diff changeset
3350 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
3351 "ldist", /* name */
kono
parents: 67
diff changeset
3352 OPTGROUP_LOOP, /* optinfo_flags */
kono
parents: 67
diff changeset
3353 TV_TREE_LOOP_DISTRIBUTION, /* tv_id */
kono
parents: 67
diff changeset
3354 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
3355 0, /* properties_provided */
kono
parents: 67
diff changeset
3356 0, /* properties_destroyed */
kono
parents: 67
diff changeset
3357 0, /* todo_flags_start */
kono
parents: 67
diff changeset
3358 0, /* todo_flags_finish */
kono
parents: 67
diff changeset
3359 };
kono
parents: 67
diff changeset
3360
kono
parents: 67
diff changeset
3361 class pass_loop_distribution : public gimple_opt_pass
kono
parents: 67
diff changeset
3362 {
kono
parents: 67
diff changeset
3363 public:
kono
parents: 67
diff changeset
3364 pass_loop_distribution (gcc::context *ctxt)
kono
parents: 67
diff changeset
3365 : gimple_opt_pass (pass_data_loop_distribution, ctxt)
kono
parents: 67
diff changeset
3366 {}
kono
parents: 67
diff changeset
3367
kono
parents: 67
diff changeset
3368 /* opt_pass methods: */
kono
parents: 67
diff changeset
3369 virtual bool gate (function *)
kono
parents: 67
diff changeset
3370 {
kono
parents: 67
diff changeset
3371 return flag_tree_loop_distribution
kono
parents: 67
diff changeset
3372 || flag_tree_loop_distribute_patterns;
kono
parents: 67
diff changeset
3373 }
kono
parents: 67
diff changeset
3374
kono
parents: 67
diff changeset
3375 virtual unsigned int execute (function *);
kono
parents: 67
diff changeset
3376
kono
parents: 67
diff changeset
3377 }; // class pass_loop_distribution
kono
parents: 67
diff changeset
3378
kono
parents: 67
diff changeset
3379 unsigned int
kono
parents: 67
diff changeset
3380 pass_loop_distribution::execute (function *fun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3381 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3382 return loop_distribution ().execute (fun);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3383 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3384
111
kono
parents: 67
diff changeset
3385 } // anon namespace
kono
parents: 67
diff changeset
3386
kono
parents: 67
diff changeset
3387 gimple_opt_pass *
kono
parents: 67
diff changeset
3388 make_pass_loop_distribution (gcc::context *ctxt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3389 {
111
kono
parents: 67
diff changeset
3390 return new pass_loop_distribution (ctxt);
kono
parents: 67
diff changeset
3391 }