annotate gcc/tree-loop-distribution.c @ 136:4627f235cf2a

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