annotate gcc/tree-loop-distribution.c @ 127:4c56639505ff

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