annotate gcc/gimple-loop-jam.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* Loop unroll-and-jam.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
3
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 Free Software Foundation; either version 3, or (at your option) any
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 later version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #include "tree-pass.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 #include "backend.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "tree.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "gimple.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 #include "ssa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 #include "fold-const.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 #include "tree-cfg.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 #include "tree-ssa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 #include "tree-ssa-loop-niter.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 #include "tree-ssa-loop.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 #include "tree-ssa-loop-manip.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 #include "cfgloop.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 #include "tree-scalar-evolution.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 #include "gimple-iterator.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 #include "cfghooks.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 #include "tree-data-ref.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 #include "tree-ssa-loop-ivopts.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 #include "tree-vectorizer.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 /* Unroll and Jam transformation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44 This is a combination of two transformations, where the second
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 is not always valid. It's applicable if a loop nest has redundancies
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46 over the iterations of an outer loop while not having that with
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 an inner loop.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 Given this nest:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 for (i) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 B(i,j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 first unroll:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 for (i by 2) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 B(i,j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 B(i+1,j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 then fuse the two adjacent inner loops resulting from that:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67 for (i by 2) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69 B(i,j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 B(i+1,j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 As the order of evaluations of the body B changes this is valid
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 only in certain situations: all distance vectors need to be forward.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 Additionally if there are multiple induction variables than just
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 a counting control IV (j above) we can also deal with some situations.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79 The validity is checked by unroll_jam_possible_p, and the data-dep
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80 testing below.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 A trivial example where the fusion is wrong would be when
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 B(i,j) == x[j-1] = x[j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 for (i by 2) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 x[j-1] = x[j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 x[j-1] = x[j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 } effect: move content to front by two elements
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92 -->
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 for (i by 2) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 for (j) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 x[j-1] = x[j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 x[j-1] = x[j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98 } effect: move content to front by one element
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99 */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 /* Modify the loop tree for the fact that all code once belonging
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 to the OLD loop or the outer loop of OLD now is inside LOOP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
105 merge_loop_tree (class loop *loop, class loop *old)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 basic_block *bbs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 int i, n;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
109 class loop *subloop;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 edge e;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111 edge_iterator ei;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113 /* Find its nodes. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115 n = get_loop_body_with_size (loop, bbs, n_basic_blocks_for_fn (cfun));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 for (i = 0; i < n; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119 /* If the block was direct child of OLD loop it's now part
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
120 of LOOP. If it was outside OLD, then it moved into LOOP
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121 as well. This avoids changing the loop father for BBs
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 in inner loops of OLD. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 if (bbs[i]->loop_father == old
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 || loop_depth (bbs[i]->loop_father) < loop_depth (old))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126 remove_bb_from_loops (bbs[i]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 add_bb_to_loop (bbs[i], loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 /* If we find a direct subloop of OLD, move it to LOOP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 subloop = bbs[i]->loop_father;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133 if (loop_outer (subloop) == old && subloop->header == bbs[i])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 flow_loop_tree_node_remove (subloop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 flow_loop_tree_node_add (loop, subloop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
139
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
140 /* Update the information about loop exit edges. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141 for (i = 0; i < n; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143 FOR_EACH_EDGE (e, ei, bbs[i]->succs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145 rescan_loop_exit (e, false, false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 loop->num_nodes = n;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151 free (bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154 /* BB is part of the outer loop of an unroll-and-jam situation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 Check if any statements therein would prevent the transformation. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158 bb_prevents_fusion_p (basic_block bb)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 gimple_stmt_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161 /* BB is duplicated by outer unrolling and then all N-1 first copies
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 move into the body of the fused inner loop. If BB exits the outer loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163 the last copy still does so, and the first N-1 copies are cancelled
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164 by loop unrolling, so also after fusion it's the exit block.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 But there might be other reasons that prevent fusion:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 * stores or unknown side-effects prevent fusion
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167 * loads don't
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 * computations into SSA names: these aren't problematic. Their
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
169 result will be unused on the exit edges of the first N-1 copies
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 (those aren't taken after unrolling). If they are used on the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 other edge (the one leading to the outer latch block) they are
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 loop-carried (on the outer loop) and the Nth copy of BB will
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 compute them again (i.e. the first N-1 copies will be dead). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176 gimple *g = gsi_stmt (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177 if (gimple_vdef (g) || gimple_has_side_effects (g))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 /* Given an inner loop LOOP (of some OUTER loop) determine if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 we can safely fuse copies of it (generated by outer unrolling).
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 If so return true, otherwise return false. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
188 unroll_jam_possible_p (class loop *outer, class loop *loop)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 basic_block *bbs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191 int i, n;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
192 class tree_niter_desc niter;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194 /* When fusing the loops we skip the latch block
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 of the first one, so it mustn't have any effects to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 preserve. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 if (!empty_block_p (loop->latch))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 if (!single_exit (loop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203 /* We need a perfect nest. Quick check for adjacent inner loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204 if (outer->inner != loop || loop->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 /* Prevent head-controlled inner loops, that we usually have.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208 The guard block would need to be accepted
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 (invariant condition either entering or skipping the loop),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210 without also accepting arbitrary control flow. When unswitching
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 ran before us (as with -O3) this won't be a problem because its
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212 outer loop unswitching will have moved out the invariant condition.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 If we do that we need to extend fuse_loops() to cope with this
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 by threading through the (still invariant) copied condition
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216 between the two loop copies. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 if (!dominated_by_p (CDI_DOMINATORS, outer->latch, loop->header))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 /* The number of iterations of the inner loop must be loop invariant
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
221 with respect to the outer loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222 if (!number_of_iterations_exit (loop, single_exit (loop), &niter,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223 false, true)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
224 || niter.cmp == ERROR_MARK
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225 || !integer_zerop (niter.may_be_zero)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 || !expr_invariant_in_loop_p (outer, niter.niter))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229 /* If the inner loop produces any values that are used inside the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 outer loop (except the virtual op) then it can flow
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 back (perhaps indirectly) into the inner loop. This prevents
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 fusion: without fusion the value at the last iteration is used,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233 with fusion the value after the initial iteration is used.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 If all uses are outside the outer loop this doesn't prevent fusion;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 the value of the last iteration is still used (and the values from
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237 all intermediate iterations are dead). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 gphi_iterator psi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 for (psi = gsi_start_phis (single_exit (loop)->dest);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 !gsi_end_p (psi); gsi_next (&psi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 imm_use_iterator imm_iter;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
243 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 tree op = gimple_phi_result (psi.phi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 if (virtual_operand_p (op))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 gimple *use_stmt = USE_STMT (use_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250 if (!is_gimple_debug (use_stmt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 && flow_bb_inside_loop_p (outer, gimple_bb (use_stmt)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256 /* And check blocks belonging to just outer loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 for (i = 0; i < n; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 if (bbs[i]->loop_father == outer && bb_prevents_fusion_p (bbs[i]))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 free (bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264 if (i != n)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 /* For now we can safely fuse copies of LOOP only if all
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268 loop carried variables are inductions (or the virtual op).
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270 We could handle reductions as well (the initial value in the second
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 body would be the after-iter value of the first body) if it's over
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
272 an associative and commutative operation. We wouldn't
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 be able to handle unknown cycles. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274 for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 affine_iv iv;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277 tree op = gimple_phi_result (psi.phi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279 if (virtual_operand_p (op))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 if (!simple_iv (loop, loop, op, &iv, true))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 /* The inductions must be regular, loop invariant step and initial
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
284 value. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 if (!expr_invariant_in_loop_p (outer, iv.step)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286 || !expr_invariant_in_loop_p (outer, iv.base))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288 /* XXX With more effort we could also be able to deal with inductions
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
289 where the initial value is loop variant but a simple IV in the
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290 outer loop. The initial value for the second body would be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291 the original initial value plus iv.base.step. The next value
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
292 for the fused loop would be the original next value of the first
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293 copy, _not_ the next value of the second body. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
294 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
295
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 /* Fuse LOOP with all further neighbors. The loops are expected to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 be in appropriate form. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
303 fuse_loops (class loop *loop)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
305 class loop *next = loop->next;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307 while (next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309 edge e;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
310
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311 remove_branch (single_pred_edge (loop->latch));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312 /* Make delete_basic_block not fiddle with the loop structure. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
313 basic_block oldlatch = loop->latch;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
314 loop->latch = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
315 delete_basic_block (oldlatch);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
316 e = redirect_edge_and_branch (loop_latch_edge (next),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
317 loop->header);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
318 loop->latch = e->src;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
319 flush_pending_stmts (e);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
320
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
321 gcc_assert (EDGE_COUNT (next->header->preds) == 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
322
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
323 /* The PHI nodes of the second body (single-argument now)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
324 need adjustments to use the right values: either directly
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
325 the value of the corresponding PHI in the first copy or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 the one leaving the first body which unrolling did for us.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
327
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
328 See also unroll_jam_possible_p() for further possibilities. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
329 gphi_iterator psi_first, psi_second;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 e = single_pred_edge (next->header);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
331 for (psi_first = gsi_start_phis (loop->header),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
332 psi_second = gsi_start_phis (next->header);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
333 !gsi_end_p (psi_first);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
334 gsi_next (&psi_first), gsi_next (&psi_second))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
335 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
336 gphi *phi_first = psi_first.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
337 gphi *phi_second = psi_second.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
338 tree firstop = gimple_phi_result (phi_first);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
339 /* The virtual operand is correct already as it's
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
340 always live at exit, hence has a LCSSA node and outer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
341 loop unrolling updated SSA form. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
342 if (virtual_operand_p (firstop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
343 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
344
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
345 /* Due to unroll_jam_possible_p() we know that this is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
346 an induction. The second body goes over the same
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
347 iteration space. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
348 add_phi_arg (phi_second, firstop, e,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
349 gimple_location (phi_first));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
350 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
351 gcc_assert (gsi_end_p (psi_second));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
352
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
353 merge_loop_tree (loop, next);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
354 gcc_assert (!next->num_nodes);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
355 class loop *ln = next->next;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
356 delete_loop (next);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
357 next = ln;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
358 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
359 rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_USE, loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
360 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
361
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
362 /* Return true if any of the access functions for dataref A
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
363 isn't invariant with respect to loop LOOP_NEST. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
364 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
365 any_access_function_variant_p (const struct data_reference *a,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
366 const class loop *loop_nest)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
367 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
368 unsigned int i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
369 vec<tree> fns = DR_ACCESS_FNS (a);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
370 tree t;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
371
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
372 FOR_EACH_VEC_ELT (fns, i, t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
373 if (!evolution_function_is_invariant_p (t, loop_nest->num))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
374 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
375
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
376 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
377 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
378
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379 /* Returns true if the distance in DDR can be determined and adjusts
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 the unroll factor in *UNROLL to make unrolling valid for that distance.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
381 Otherwise return false. DDR is with respect to the outer loop of INNER.
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
382
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383 If this data dep can lead to a removed memory reference, increment
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
384 *REMOVED and adjust *PROFIT_UNROLL to be the necessary unroll factor
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385 for this to happen. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
387 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
388 adjust_unroll_factor (class loop *inner, struct data_dependence_relation *ddr,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
389 unsigned *unroll, unsigned *profit_unroll,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
390 unsigned *removed)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
391 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
392 bool ret = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393 if (DDR_ARE_DEPENDENT (ddr) != chrec_known)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 if (DDR_NUM_DIST_VECTS (ddr) == 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
397 unsigned i;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
398 lambda_vector dist_v;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399 FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
400 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401 /* A distance (a,b) is at worst transformed into (a/N,b) by the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402 unrolling (factor N), so the transformation is valid if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403 a >= N, or b > 0, or b is zero and a > 0. Otherwise the unroll
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 factor needs to be limited so that the first condition holds.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 That may limit the factor down to zero in the worst case. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406 int dist = dist_v[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407 if (dist < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 gcc_unreachable ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 else if ((unsigned)dist >= *unroll)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
410 ;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
411 else if (lambda_vector_zerop (dist_v + 1, DDR_NB_LOOPS (ddr) - 1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
412 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
413 /* We have (a,0) with a < N, so this will be transformed into
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
414 (0,0) after unrolling by N. This might potentially be a
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
415 problem, if it's not a read-read dependency. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
416 if (DR_IS_READ (DDR_A (ddr)) && DR_IS_READ (DDR_B (ddr)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
417 ;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
418 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
419 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
420 /* So, at least one is a write, and we might reduce the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
421 distance vector to (0,0). This is still no problem
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
422 if both data-refs are affine with respect to the inner
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
423 loops. But if one of them is invariant with respect
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
424 to an inner loop our reordering implicit in loop fusion
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
425 corrupts the program, as our data dependences don't
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
426 capture this. E.g. for:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
427 for (0 <= i < n)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
428 for (0 <= j < m)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
429 a[i][0] = a[i+1][0] + 2; // (1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
430 b[i][j] = b[i+1][j] + 2; // (2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
431 the distance vector for both statements is (-1,0),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
432 but exchanging the order for (2) is okay, while
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
433 for (1) it is not. To see this, write out the original
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
434 accesses (assume m is 2):
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
435 a i j original
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
436 0 0 0 r a[1][0] b[1][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
437 1 0 0 w a[0][0] b[0][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
438 2 0 1 r a[1][0] b[1][1]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
439 3 0 1 w a[0][0] b[0][1]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
440 4 1 0 r a[2][0] b[2][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
441 5 1 0 w a[1][0] b[1][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
442 after unroll-by-2 and fusion the accesses are done in
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
443 this order (from column a): 0,1, 4,5, 2,3, i.e. this:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
444 a i j transformed
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
445 0 0 0 r a[1][0] b[1][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
446 1 0 0 w a[0][0] b[0][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
447 4 1 0 r a[2][0] b[2][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
448 5 1 0 w a[1][0] b[1][0]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
449 2 0 1 r a[1][0] b[1][1]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
450 3 0 1 w a[0][0] b[0][1]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
451 Note how access 2 accesses the same element as access 5
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
452 for array 'a' but not for array 'b'. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
453 if (any_access_function_variant_p (DDR_A (ddr), inner)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
454 && any_access_function_variant_p (DDR_B (ddr), inner))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
455 ;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
456 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
457 /* And if any dataref of this pair is invariant with
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
458 respect to the inner loop, we have no chance than
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
459 to reduce the unroll factor. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
460 *unroll = dist;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
461 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
462 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
463 else if (lambda_vector_lexico_pos (dist_v + 1, DDR_NB_LOOPS (ddr) - 1))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 ;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466 *unroll = dist;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
467
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
468 /* With a distance (a,0) it's always profitable to unroll-and-jam
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
469 (by a+1), because one memory reference will go away. With
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
470 (a,b) and b != 0 that's less clear. We will increase the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
471 number of streams without lowering the number of mem refs.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
472 So for now only handle the first situation. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
473 if (lambda_vector_zerop (dist_v + 1, DDR_NB_LOOPS (ddr) - 1))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
474 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
475 *profit_unroll = MAX (*profit_unroll, (unsigned)dist + 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
476 (*removed)++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
477 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
478
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
479 ret = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
480 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
481 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
482 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
483 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
484
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
485 /* Main entry point for the unroll-and-jam transformation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
486 described above. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
487
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
488 static unsigned int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
489 tree_loop_unroll_and_jam (void)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
490 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
491 class loop *loop;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
492 bool changed = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
493
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
494 gcc_assert (scev_initialized_p ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
495
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
496 /* Go through all innermost loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
497 FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
498 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
499 class loop *outer = loop_outer (loop);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
500
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
501 if (loop_depth (loop) < 2
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
502 || optimize_loop_nest_for_size_p (outer))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
503 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
504
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
505 if (!unroll_jam_possible_p (outer, loop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
506 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
507
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
508 vec<data_reference_p> datarefs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
509 vec<ddr_p> dependences;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
510 unsigned unroll_factor, profit_unroll, removed;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 class tree_niter_desc desc;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
512 bool unroll = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
513
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
514 auto_vec<loop_p, 3> loop_nest;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
515 dependences.create (10);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
516 datarefs.create (10);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
517 if (!compute_data_dependences_for_loop (outer, true, &loop_nest,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
518 &datarefs, &dependences))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
519 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
520 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
521 fprintf (dump_file, "Cannot analyze data dependencies\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
522 free_data_refs (datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
523 free_dependence_relations (dependences);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 continue;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
525 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
526 if (!datarefs.length ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
527 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
528
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
529 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
530 dump_data_dependence_relations (dump_file, dependences);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
531
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
532 unroll_factor = (unsigned)-1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
533 profit_unroll = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
534 removed = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
535
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
536 /* Check all dependencies. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
537 unsigned i;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
538 struct data_dependence_relation *ddr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
539 FOR_EACH_VEC_ELT (dependences, i, ddr)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
540 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
541 struct data_reference *dra, *drb;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
542
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
543 /* If the refs are independend there's nothing to do. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
544 if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
545 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
546 dra = DDR_A (ddr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
547 drb = DDR_B (ddr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
548 /* Nothing interesting for the self dependencies. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
549 if (dra == drb)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
550 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
551
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
552 /* Now check the distance vector, for determining a sensible
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
553 outer unroll factor, and for validity of merging the inner
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
554 loop copies. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
555 if (!adjust_unroll_factor (loop, ddr, &unroll_factor, &profit_unroll,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
556 &removed))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
557 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
558 /* Couldn't get the distance vector. For two reads that's
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
559 harmless (we assume we should unroll). For at least
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
560 one write this means we can't check the dependence direction
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
561 and hence can't determine safety. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
562
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
563 if (DR_IS_WRITE (dra) || DR_IS_WRITE (drb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
564 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
565 unroll_factor = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
566 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
567 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
568 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
569 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
570
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
571 /* We regard a user-specified minimum percentage of zero as a request
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
572 to ignore all profitability concerns and apply the transformation
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
573 always. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
574 if (!param_unroll_jam_min_percent)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
575 profit_unroll = MAX(2, profit_unroll);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
576 else if (removed * 100 / datarefs.length ()
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
577 < (unsigned)param_unroll_jam_min_percent)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
578 profit_unroll = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
579 if (unroll_factor > profit_unroll)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
580 unroll_factor = profit_unroll;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
581 if (unroll_factor > (unsigned)param_unroll_jam_max_unroll)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
582 unroll_factor = param_unroll_jam_max_unroll;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
583 unroll = (unroll_factor > 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
584 && can_unroll_loop_p (outer, unroll_factor, &desc));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
585
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
586 if (unroll)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
587 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
588 if (dump_enabled_p ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
589 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
590 find_loop_location (outer),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
591 "applying unroll and jam with factor %d\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
592 unroll_factor);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
593 initialize_original_copy_tables ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
594 tree_unroll_loop (outer, unroll_factor, single_dom_exit (outer),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
595 &desc);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
596 free_original_copy_tables ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
597 fuse_loops (outer->inner);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
598 changed = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
599 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
600
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
601 loop_nest.release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
602 free_dependence_relations (dependences);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
603 free_data_refs (datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
604 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
605
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
606 if (changed)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
607 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
608 scev_reset ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
609 free_dominance_info (CDI_DOMINATORS);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
610 return TODO_cleanup_cfg;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
611 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
612 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
613 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
614
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
615 /* Pass boilerplate */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
616
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
617 namespace {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
618
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
619 const pass_data pass_data_loop_jam =
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
620 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
621 GIMPLE_PASS, /* type */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
622 "unrolljam", /* name */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
623 OPTGROUP_LOOP, /* optinfo_flags */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
624 TV_LOOP_JAM, /* tv_id */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
625 PROP_cfg, /* properties_required */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
626 0, /* properties_provided */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
627 0, /* properties_destroyed */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
628 0, /* todo_flags_start */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
629 0, /* todo_flags_finish */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
630 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
631
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
632 class pass_loop_jam : public gimple_opt_pass
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
633 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
634 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
635 pass_loop_jam (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
636 : gimple_opt_pass (pass_data_loop_jam, ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
637 {}
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
638
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
639 /* opt_pass methods: */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
640 virtual bool gate (function *) { return flag_unroll_jam != 0; }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
641 virtual unsigned int execute (function *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
642
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
643 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
644
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
645 unsigned int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
646 pass_loop_jam::execute (function *fun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
647 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
648 if (number_of_loops (fun) <= 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
649 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
650
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
651 return tree_loop_unroll_and_jam ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
652 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
653
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
654 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
655
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
656 gimple_opt_pass *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
657 make_pass_loop_jam (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
658 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
659 return new pass_loop_jam (ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
660 }