annotate gcc/gimple-loop-interchange.cc @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* Loop interchange.
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 Contributed by ARM Ltd.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 under the terms of the GNU General Public License as published by the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 Free Software Foundation; either version 3, or (at your option) any
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10 later version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15 for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 #include "backend.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "is-a.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "tree.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 #include "gimple.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 #include "tree-pass.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 #include "ssa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 #include "gimple-pretty-print.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 #include "fold-const.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 #include "gimplify.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 #include "gimple-iterator.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 #include "gimplify-me.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 #include "cfgloop.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 #include "tree-ssa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 #include "tree-scalar-evolution.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 #include "tree-ssa-loop-manip.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 #include "tree-ssa-loop-niter.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 #include "tree-ssa-loop-ivopts.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41 #include "tree-ssa-dce.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 #include "tree-data-ref.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 #include "tree-vectorizer.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 /* This pass performs loop interchange: for example, the loop nest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 for (int j = 0; j < N; j++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48 for (int k = 0; k < N; k++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 for (int i = 0; i < N; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 c[i][j] = c[i][j] + a[i][k]*b[k][j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 is transformed to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54 for (int i = 0; i < N; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 for (int j = 0; j < N; j++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 for (int k = 0; k < N; k++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 c[i][j] = c[i][j] + a[i][k]*b[k][j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 This pass implements loop interchange in the following steps:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 1) Find perfect loop nest for each innermost loop and compute data
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 dependence relations for it. For above example, loop nest is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 <loop_j, loop_k, loop_i>.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 2) From innermost to outermost loop, this pass tries to interchange
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 each loop pair. For above case, it firstly tries to interchange
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 <loop_k, loop_i> and loop nest becomes <loop_j, loop_i, loop_k>.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67 Then it tries to interchange <loop_j, loop_i> and loop nest becomes
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 <loop_i, loop_j, loop_k>. The overall effect is to move innermost
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69 loop to the outermost position. For loop pair <loop_i, loop_j>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 to be interchanged, we:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 3) Check if data dependence relations are valid for loop interchange.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72 4) Check if both loops can be interchanged in terms of transformation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73 5) Check if interchanging the two loops is profitable.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 6) Interchange the two loops by mapping induction variables.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 This pass also handles reductions in loop nest. So far we only support
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 simple reduction of inner loop and double reduction of the loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79 /* Maximum number of stmts in each loop that should be interchanged. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
80 #define MAX_NUM_STMT (param_loop_interchange_max_num_stmts)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81 /* Maximum number of data references in loop nest. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
82 #define MAX_DATAREFS (param_loop_max_datarefs_for_datadeps)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 /* Comparison ratio of access stride between inner/outer loops to be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85 interchanged. This is the minimum stride ratio for loop interchange
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 to be profitable. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
87 #define OUTER_STRIDE_RATIO (param_loop_interchange_stride_ratio)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88 /* The same as above, but we require higher ratio for interchanging the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 innermost two loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 #define INNER_STRIDE_RATIO ((OUTER_STRIDE_RATIO) + 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92 /* Comparison ratio of stmt cost between inner/outer loops. Loops won't
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 be interchanged if outer loop has too many stmts. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 #define STMT_COST_RATIO (3)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 /* Vector of strides that DR accesses in each level loop of a loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 #define DR_ACCESS_STRIDE(dr) ((vec<tree> *) dr->aux)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99 /* Structure recording loop induction variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 typedef struct induction
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 /* IV itself. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103 tree var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 /* IV's initializing value, which is the init arg of the IV PHI node. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 tree init_val;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106 /* IV's initializing expr, which is (the expanded result of) init_val. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 tree init_expr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 /* IV's step. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109 tree step;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 } *induction_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112 /* Enum type for loop reduction variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113 enum reduction_type
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115 UNKNOWN_RTYPE = 0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116 SIMPLE_RTYPE,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 DOUBLE_RTYPE
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120 /* Structure recording loop reduction variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121 typedef struct reduction
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 /* Reduction itself. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 tree var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 /* PHI node defining reduction variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126 gphi *phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 /* Init and next variables of the reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128 tree init;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 tree next;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130 /* Lcssa PHI node if reduction is used outside of its definition loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 gphi *lcssa_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 /* Stmts defining init and next. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133 gimple *producer;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 gimple *consumer;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 /* If init is loaded from memory, this is the loading memory reference. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 tree init_ref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 /* If reduction is finally stored to memory, this is the stored memory
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138 reference. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
139 tree fini_ref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
140 enum reduction_type type;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141 } *reduction_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 /* Dump reduction RE. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147 dump_reduction (reduction_p re)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 if (re->type == SIMPLE_RTYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 fprintf (dump_file, " Simple reduction: ");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151 else if (re->type == DOUBLE_RTYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 fprintf (dump_file, " Double reduction: ");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154 fprintf (dump_file, " Unknown reduction: ");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156 print_gimple_stmt (dump_file, re->phi, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 /* Dump LOOP's induction IV. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
161 dump_induction (class loop *loop, induction_p iv)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163 fprintf (dump_file, " Induction: ");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164 print_generic_expr (dump_file, iv->var, TDF_SLIM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 fprintf (dump_file, " = {");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 print_generic_expr (dump_file, iv->init_expr, TDF_SLIM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167 fprintf (dump_file, ", ");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 print_generic_expr (dump_file, iv->step, TDF_SLIM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169 fprintf (dump_file, "}_%d\n", loop->num);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 /* Loop candidate for interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
174 class loop_cand
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
176 public:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
177 loop_cand (class loop *, class loop *);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 ~loop_cand ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 reduction_p find_reduction_by_stmt (gimple *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181 void classify_simple_reduction (reduction_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182 bool analyze_iloop_reduction_var (tree);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 bool analyze_oloop_reduction_var (loop_cand *, tree);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 bool analyze_induction_var (tree, tree);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 bool analyze_carried_vars (loop_cand *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186 bool analyze_lcssa_phis (void);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187 bool can_interchange_p (loop_cand *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188 void undo_simple_reduction (reduction_p, bitmap);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 /* The loop itself. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
191 class loop *m_loop;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192 /* The outer loop for interchange. It equals to loop if this loop cand
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193 itself represents the outer loop. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
194 class loop *m_outer;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 /* Vector of induction variables in loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 vec<induction_p> m_inductions;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 /* Vector of reduction variables in loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 vec<reduction_p> m_reductions;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199 /* Lcssa PHI nodes of this loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 vec<gphi *> m_lcssa_nodes;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201 /* Single exit edge of this loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202 edge m_exit;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203 /* Basic blocks of this loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204 basic_block *m_bbs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205 /* Number of stmts of this loop. Inner loops' stmts are not included. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206 int m_num_stmts;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 /* Number of constant initialized simple reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208 int m_const_init_reduc;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 /* Constructor. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
213 loop_cand::loop_cand (class loop *loop, class loop *outer)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 : m_loop (loop), m_outer (outer), m_exit (single_exit (loop)),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 m_bbs (get_loop_body (loop)), m_num_stmts (0), m_const_init_reduc (0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 m_inductions.create (3);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218 m_reductions.create (3);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219 m_lcssa_nodes.create (3);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
221
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222 /* Destructor. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
224 loop_cand::~loop_cand ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 induction_p iv;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 for (unsigned i = 0; m_inductions.iterate (i, &iv); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 free (iv);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 reduction_p re;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 for (unsigned i = 0; m_reductions.iterate (i, &re); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 free (re);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 m_inductions.release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 m_reductions.release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 m_lcssa_nodes.release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237 free (m_bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 /* Return single use stmt of VAR in LOOP, otherwise return NULL. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 static gimple *
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
243 single_use_in_loop (tree var, class loop *loop)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 gimple *stmt, *res = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247 imm_use_iterator iterator;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 FOR_EACH_IMM_USE_FAST (use_p, iterator, var)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 stmt = USE_STMT (use_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 if (is_gimple_debug (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255 if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 if (res)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 res = stmt;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 return res;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266 /* Return true if E is unsupported in loop interchange, i.e, E is a complex
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 edge or part of irreducible loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 static inline bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270 unsupported_edge (edge e)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
272 return (e->flags & (EDGE_COMPLEX | EDGE_IRREDUCIBLE_LOOP));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 /* Return the reduction if STMT is one of its lcssa PHI, producer or consumer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 stmt. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 reduction_p
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279 loop_cand::find_reduction_by_stmt (gimple *stmt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 gphi *phi = dyn_cast <gphi *> (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 reduction_p re;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 for (unsigned i = 0; m_reductions.iterate (i, &re); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 if ((phi != NULL && phi == re->lcssa_phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286 || (stmt == re->producer || stmt == re->consumer))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 return re;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
289 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
292 /* Return true if current loop_cand be interchanged. ILOOP is not NULL if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293 current loop_cand is outer loop in loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
294
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
295 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296 loop_cand::can_interchange_p (loop_cand *iloop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298 /* For now we only support at most one reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 unsigned allowed_reduction_num = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301 /* Only support reduction if the loop nest to be interchanged is the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 innermostin two loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 if ((iloop == NULL && m_loop->inner != NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304 || (iloop != NULL && iloop->m_loop->inner != NULL))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 allowed_reduction_num = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307 if (m_reductions.length () > allowed_reduction_num
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 || (m_reductions.length () == 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309 && m_reductions[0]->type == UNKNOWN_RTYPE))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
310 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312 /* Only support lcssa PHI node which is for reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
313 if (m_lcssa_nodes.length () > allowed_reduction_num)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
314 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
315
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
316 /* Check if basic block has any unsupported operation. Note basic blocks
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
317 of inner loops are not checked here. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
318 for (unsigned i = 0; i < m_loop->num_nodes; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
319 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
320 basic_block bb = m_bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
321 gphi_iterator psi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
322 gimple_stmt_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
323
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
324 /* Skip basic blocks of inner loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
325 if (bb->loop_father != m_loop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
327
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
328 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
329 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 gimple *stmt = gsi_stmt (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
331 if (is_gimple_debug (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
332 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
333
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
334 if (gimple_has_side_effects (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
335 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
336
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
337 m_num_stmts++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
338 if (gcall *call = dyn_cast <gcall *> (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
339 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
340 /* In basic block of outer loop, the call should be cheap since
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
341 it will be moved to inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
342 if (iloop != NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
343 && !gimple_inexpensive_call_p (call))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
344 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
345 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
346 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
347
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
348 if (!iloop || !gimple_vuse (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
349 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
350
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
351 /* Support stmt accessing memory in outer loop only if it is for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
352 inner loop's reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
353 if (iloop->find_reduction_by_stmt (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
354 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
355
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
356 tree lhs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
357 /* Support loop invariant memory reference if it's only used once by
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
358 inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
359 /* ??? How's this checking for invariantness? */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
360 if (gimple_assign_single_p (stmt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
361 && (lhs = gimple_assign_lhs (stmt)) != NULL_TREE
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
362 && TREE_CODE (lhs) == SSA_NAME
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
363 && single_use_in_loop (lhs, iloop->m_loop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
364 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
365
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
366 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
367 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
368 /* Check if loop has too many stmts. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
369 if (m_num_stmts > MAX_NUM_STMT)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
370 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
371
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
372 /* Allow PHI nodes in any basic block of inner loop, PHI nodes in outer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
373 loop's header, or PHI nodes in dest bb of inner loop's exit edge. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
374 if (!iloop || bb == m_loop->header
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
375 || bb == iloop->m_exit->dest)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
376 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
377
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
378 /* Don't allow any other PHI nodes. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379 for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 if (!virtual_operand_p (PHI_RESULT (psi.phi ())))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
381 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
382 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
384 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
387 /* Programmers and optimizers (like loop store motion) may optimize code:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
388
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
389 for (int i = 0; i < N; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
390 for (int j = 0; j < N; j++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
391 a[i] += b[j][i] * c[j][i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
392
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393 into reduction:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 for (int i = 0; i < N; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
397 // producer. Note sum can be intitialized to a constant.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
398 int sum = a[i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399 for (int j = 0; j < N; j++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
400 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401 sum += b[j][i] * c[j][i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403 // consumer.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 a[i] = sum;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407 The result code can't be interchanged without undoing the optimization.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 This function classifies this kind reduction and records information so
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 that we can undo the store motion during interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
410
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
411 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
412 loop_cand::classify_simple_reduction (reduction_p re)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
413 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
414 gimple *producer, *consumer;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
415
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
416 /* Check init variable of reduction and how it is initialized. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
417 if (TREE_CODE (re->init) == SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
418 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
419 producer = SSA_NAME_DEF_STMT (re->init);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
420 re->producer = producer;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
421 basic_block bb = gimple_bb (producer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
422 if (!bb || bb->loop_father != m_outer)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
423 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
424
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
425 if (!gimple_assign_load_p (producer))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
426 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
427
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
428 re->init_ref = gimple_assign_rhs1 (producer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
429 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
430 else if (CONSTANT_CLASS_P (re->init))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
431 m_const_init_reduc++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
432 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
433 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
434
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
435 /* Check how reduction variable is used. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
436 consumer = single_use_in_loop (PHI_RESULT (re->lcssa_phi), m_outer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
437 if (!consumer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
438 || !gimple_store_p (consumer))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
439 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
440
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
441 re->fini_ref = gimple_get_lhs (consumer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
442 re->consumer = consumer;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
443
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
444 /* Simple reduction with constant initializer. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
445 if (!re->init_ref)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
446 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
447 gcc_assert (CONSTANT_CLASS_P (re->init));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
448 re->init_ref = unshare_expr (re->fini_ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
449 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
450
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
451 /* Require memory references in producer and consumer are the same so
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
452 that we can undo reduction during interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
453 if (re->init_ref && !operand_equal_p (re->init_ref, re->fini_ref, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
454 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
455
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
456 re->type = SIMPLE_RTYPE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
457 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
458
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
459 /* Analyze reduction variable VAR for inner loop of the loop nest to be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
460 interchanged. Return true if analysis succeeds. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
461
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
462 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
463 loop_cand::analyze_iloop_reduction_var (tree var)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465 gphi *phi = as_a <gphi *> (SSA_NAME_DEF_STMT (var));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466 gphi *lcssa_phi = NULL, *use_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
467 tree init = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (m_loop));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
468 tree next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (m_loop));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
469 reduction_p re;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
470 gimple *stmt, *next_def, *single_use = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
471 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
472 imm_use_iterator iterator;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
473
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
474 if (TREE_CODE (next) != SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
475 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
476
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
477 next_def = SSA_NAME_DEF_STMT (next);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
478 basic_block bb = gimple_bb (next_def);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
479 if (!bb || !flow_bb_inside_loop_p (m_loop, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
480 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
481
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
482 /* In restricted reduction, the var is (and must be) used in defining
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
483 the updated var. The process can be depicted as below:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
484
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
485 var ;; = PHI<init, next>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
486 |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
487 |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
488 v
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
489 +---------------------+
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
490 | reduction operators | <-- other operands
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
491 +---------------------+
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
492 |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
493 |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
494 v
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
495 next
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
496
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
497 In terms loop interchange, we don't change how NEXT is computed based
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
498 on VAR and OTHER OPERANDS. In case of double reduction in loop nest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
499 to be interchanged, we don't changed it at all. In the case of simple
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
500 reduction in inner loop, we only make change how VAR/NEXT is loaded or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
501 stored. With these conditions, we can relax restrictions on reduction
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
502 in a way that reduction operation is seen as black box. In general,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
503 we can ignore reassociation of reduction operator; we can handle fake
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
504 reductions in which VAR is not even used to compute NEXT. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
505 if (! single_imm_use (var, &use_p, &single_use)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
506 || ! flow_bb_inside_loop_p (m_loop, gimple_bb (single_use)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
507 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
508
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
509 /* Check the reduction operation. We require a left-associative operation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
510 For FP math we also need to be allowed to associate operations. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
511 if (gassign *ass = dyn_cast <gassign *> (single_use))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
512 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
513 enum tree_code code = gimple_assign_rhs_code (ass);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
514 if (! (associative_tree_code (code)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
515 || (code == MINUS_EXPR
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
516 && use_p->use == gimple_assign_rhs1_ptr (ass)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
517 || (FLOAT_TYPE_P (TREE_TYPE (var))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
518 && ! flag_associative_math))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
519 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
520 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
521 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
522 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
523
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
524 /* Handle and verify a series of stmts feeding the reduction op. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
525 if (single_use != next_def
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
526 && !check_reduction_path (dump_user_location_t (), m_loop, phi, next,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
527 gimple_assign_rhs_code (single_use)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
528 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
529
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
530 /* Only support cases in which INIT is used in inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
531 if (TREE_CODE (init) == SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
532 FOR_EACH_IMM_USE_FAST (use_p, iterator, init)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
533 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
534 stmt = USE_STMT (use_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
535 if (is_gimple_debug (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
536 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
537
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
538 if (!flow_bb_inside_loop_p (m_loop, gimple_bb (stmt)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
539 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
540 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
541
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
542 FOR_EACH_IMM_USE_FAST (use_p, iterator, next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
543 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
544 stmt = USE_STMT (use_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
545 if (is_gimple_debug (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
546 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
547
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
548 /* Or else it's used in PHI itself. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
549 use_phi = dyn_cast <gphi *> (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
550 if (use_phi == phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
551 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
552
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
553 if (use_phi != NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
554 && lcssa_phi == NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
555 && gimple_bb (stmt) == m_exit->dest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
556 && PHI_ARG_DEF_FROM_EDGE (use_phi, m_exit) == next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
557 lcssa_phi = use_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
558 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
559 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
560 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
561 if (!lcssa_phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
562 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
563
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
564 re = XCNEW (struct reduction);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
565 re->var = var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
566 re->init = init;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
567 re->next = next;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
568 re->phi = phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
569 re->lcssa_phi = lcssa_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
570
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
571 classify_simple_reduction (re);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
572
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
573 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
574 dump_reduction (re);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
575
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
576 m_reductions.safe_push (re);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
577 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
578 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
579
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
580 /* Analyze reduction variable VAR for outer loop of the loop nest to be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
581 interchanged. ILOOP is not NULL and points to inner loop. For the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
582 moment, we only support double reduction for outer loop, like:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
583
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
584 for (int i = 0; i < n; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
585 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
586 int sum = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
587
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
588 for (int j = 0; j < n; j++) // outer loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
589 for (int k = 0; k < n; k++) // inner loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
590 sum += a[i][k]*b[k][j];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
591
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
592 s[i] = sum;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
593 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
594
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
595 Note the innermost two loops are the loop nest to be interchanged.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
596 Return true if analysis succeeds. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
597
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
598 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
599 loop_cand::analyze_oloop_reduction_var (loop_cand *iloop, tree var)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
600 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
601 gphi *phi = as_a <gphi *> (SSA_NAME_DEF_STMT (var));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
602 gphi *lcssa_phi = NULL, *use_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
603 tree init = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (m_loop));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
604 tree next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (m_loop));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
605 reduction_p re;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
606 gimple *stmt, *next_def;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
607 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
608 imm_use_iterator iterator;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
609
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
610 if (TREE_CODE (next) != SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
611 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
612
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
613 next_def = SSA_NAME_DEF_STMT (next);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
614 basic_block bb = gimple_bb (next_def);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
615 if (!bb || !flow_bb_inside_loop_p (m_loop, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
616 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
617
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
618 /* Find inner loop's simple reduction that uses var as initializer. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
619 reduction_p inner_re = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
620 for (unsigned i = 0; iloop->m_reductions.iterate (i, &inner_re); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
621 if (inner_re->init == var || operand_equal_p (inner_re->init, var, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
622 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
623
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
624 if (inner_re == NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
625 || inner_re->type != UNKNOWN_RTYPE
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
626 || inner_re->producer != phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
627 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
628
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
629 /* In case of double reduction, outer loop's reduction should be updated
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
630 by inner loop's simple reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
631 if (next_def != inner_re->lcssa_phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
632 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
633
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
634 /* Outer loop's reduction should only be used to initialize inner loop's
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
635 simple reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
636 if (! single_imm_use (var, &use_p, &stmt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
637 || stmt != inner_re->phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
638 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
639
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
640 /* Check this reduction is correctly used outside of loop via lcssa phi. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
641 FOR_EACH_IMM_USE_FAST (use_p, iterator, next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
642 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
643 stmt = USE_STMT (use_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
644 if (is_gimple_debug (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
645 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
646
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
647 /* Or else it's used in PHI itself. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
648 use_phi = dyn_cast <gphi *> (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
649 if (use_phi == phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
650 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
651
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
652 if (lcssa_phi == NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
653 && use_phi != NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
654 && gimple_bb (stmt) == m_exit->dest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
655 && PHI_ARG_DEF_FROM_EDGE (use_phi, m_exit) == next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
656 lcssa_phi = use_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
657 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
658 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
659 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
660 if (!lcssa_phi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
661 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
662
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
663 re = XCNEW (struct reduction);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
664 re->var = var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
665 re->init = init;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
666 re->next = next;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
667 re->phi = phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
668 re->lcssa_phi = lcssa_phi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
669 re->type = DOUBLE_RTYPE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
670 inner_re->type = DOUBLE_RTYPE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
671
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
672 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
673 dump_reduction (re);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
674
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
675 m_reductions.safe_push (re);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
676 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
677 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
678
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
679 /* Return true if VAR is induction variable of current loop whose scev is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
680 specified by CHREC. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
681
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
682 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
683 loop_cand::analyze_induction_var (tree var, tree chrec)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
684 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
685 gphi *phi = as_a <gphi *> (SSA_NAME_DEF_STMT (var));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
686 tree init = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (m_loop));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
687
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
688 /* Var is loop invariant, though it's unlikely to happen. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
689 if (tree_does_not_contain_chrecs (chrec))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
690 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
691 /* Punt on floating point invariants if honoring signed zeros,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
692 representing that as + 0.0 would change the result if init
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
693 is -0.0. Similarly for SNaNs it can raise exception. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
694 if (HONOR_SIGNED_ZEROS (chrec) || HONOR_SNANS (chrec))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
695 return false;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
696 struct induction *iv = XCNEW (struct induction);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
697 iv->var = var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
698 iv->init_val = init;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
699 iv->init_expr = chrec;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
700 iv->step = build_zero_cst (TREE_TYPE (chrec));
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
701 m_inductions.safe_push (iv);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
702 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
703 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
704
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
705 if (TREE_CODE (chrec) != POLYNOMIAL_CHREC
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
706 || CHREC_VARIABLE (chrec) != (unsigned) m_loop->num
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
707 || tree_contains_chrecs (CHREC_LEFT (chrec), NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
708 || tree_contains_chrecs (CHREC_RIGHT (chrec), NULL))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
709 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
710
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
711 struct induction *iv = XCNEW (struct induction);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
712 iv->var = var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
713 iv->init_val = init;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
714 iv->init_expr = CHREC_LEFT (chrec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
715 iv->step = CHREC_RIGHT (chrec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
716
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
717 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
718 dump_induction (m_loop, iv);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
719
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
720 m_inductions.safe_push (iv);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
721 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
722 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
723
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
724 /* Return true if all loop carried variables defined in loop header can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
725 be successfully analyzed. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
726
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
727 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
728 loop_cand::analyze_carried_vars (loop_cand *iloop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
729 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
730 edge e = loop_preheader_edge (m_outer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
731 gphi_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
732
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
733 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
734 fprintf (dump_file, "\nLoop(%d) carried vars:\n", m_loop->num);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
735
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
736 for (gsi = gsi_start_phis (m_loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
737 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
738 gphi *phi = gsi.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
739
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
740 tree var = PHI_RESULT (phi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
741 if (virtual_operand_p (var))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
742 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
743
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
744 tree chrec = analyze_scalar_evolution (m_loop, var);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
745 chrec = instantiate_scev (e, m_loop, chrec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
746
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
747 /* Analyze var as reduction variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
748 if (chrec_contains_undetermined (chrec)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
749 || chrec_contains_symbols_defined_in_loop (chrec, m_outer->num))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
750 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
751 if (iloop && !analyze_oloop_reduction_var (iloop, var))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
752 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
753 if (!iloop && !analyze_iloop_reduction_var (var))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
754 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
755 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
756 /* Analyze var as induction variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
757 else if (!analyze_induction_var (var, chrec))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
758 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
759 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
760
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
761 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
762 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
763
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
764 /* Return TRUE if loop closed PHI nodes can be analyzed successfully. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
765
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
766 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
767 loop_cand::analyze_lcssa_phis (void)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
768 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
769 gphi_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
770 for (gsi = gsi_start_phis (m_exit->dest); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
771 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
772 gphi *phi = gsi.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
773
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
774 if (virtual_operand_p (PHI_RESULT (phi)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
775 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
776
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
777 /* TODO: We only support lcssa phi for reduction for now. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
778 if (!find_reduction_by_stmt (phi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
779 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
780 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
781
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
782 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
783 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
784
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
785 /* CONSUMER is a stmt in BB storing reduction result into memory object.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
786 When the reduction is intialized from constant value, we need to add
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
787 a stmt loading from the memory object to target basic block in inner
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
788 loop during undoing the reduction. Problem is that memory reference
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
789 may use ssa variables not dominating the target basic block. This
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
790 function finds all stmts on which CONSUMER depends in basic block BB,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
791 records and returns them via STMTS. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
792
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
793 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
794 find_deps_in_bb_for_stmt (gimple_seq *stmts, basic_block bb, gimple *consumer)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
795 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
796 auto_vec<gimple *, 4> worklist;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
797 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
798 ssa_op_iter iter;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
799 gimple *stmt, *def_stmt;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
800 gimple_stmt_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
801
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
802 /* First clear flag for stmts in bb. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
803 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
804 gimple_set_plf (gsi_stmt (gsi), GF_PLF_1, false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
805
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
806 /* DFS search all depended stmts in bb and mark flag for these stmts. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
807 worklist.safe_push (consumer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
808 while (!worklist.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
809 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
810 stmt = worklist.pop ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
811 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
812 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
813 def_stmt = SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
814
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
815 if (is_a <gphi *> (def_stmt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
816 || gimple_bb (def_stmt) != bb
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
817 || gimple_plf (def_stmt, GF_PLF_1))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
818 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
819
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
820 worklist.safe_push (def_stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
821 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
822 gimple_set_plf (stmt, GF_PLF_1, true);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
823 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
824 for (gsi = gsi_start_nondebug_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
825 !gsi_end_p (gsi) && (stmt = gsi_stmt (gsi)) != consumer;)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
826 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
827 /* Move dep stmts to sequence STMTS. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
828 if (gimple_plf (stmt, GF_PLF_1))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
829 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
830 gsi_remove (&gsi, false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
831 gimple_seq_add_stmt_without_update (stmts, stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
832 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
833 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
834 gsi_next_nondebug (&gsi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
835 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
836 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
837
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
838 /* User can write, optimizers can generate simple reduction RE for inner
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
839 loop. In order to make interchange valid, we have to undo reduction by
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
840 moving producer and consumer stmts into the inner loop. For example,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
841 below code:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
842
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
843 init = MEM_REF[idx]; //producer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
844 loop:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
845 var = phi<init, next>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
846 next = var op ...
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
847 reduc_sum = phi<next>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
848 MEM_REF[idx] = reduc_sum //consumer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
849
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
850 is transformed into:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
851
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
852 loop:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
853 new_var = MEM_REF[idx]; //producer after moving
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
854 next = new_var op ...
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
855 MEM_REF[idx] = next; //consumer after moving
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
856
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
857 Note if the reduction variable is initialized to constant, like:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
858
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
859 var = phi<0.0, next>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
860
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
861 we compute new_var as below:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
862
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
863 loop:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
864 tmp = MEM_REF[idx];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
865 new_var = !first_iteration ? tmp : 0.0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
866
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
867 so that the initial const is used in the first iteration of loop. Also
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
868 record ssa variables for dead code elimination in DCE_SEEDS. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
869
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
870 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
871 loop_cand::undo_simple_reduction (reduction_p re, bitmap dce_seeds)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
872 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
873 gimple *stmt;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
874 gimple_stmt_iterator from, to = gsi_after_labels (m_loop->header);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
875 gimple_seq stmts = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
876 tree new_var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
877
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
878 /* Prepare the initialization stmts and insert it to inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
879 if (re->producer != NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
880 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
881 gimple_set_vuse (re->producer, NULL_TREE);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
882 update_stmt (re->producer);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
883 from = gsi_for_stmt (re->producer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
884 gsi_remove (&from, false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
885 gimple_seq_add_stmt_without_update (&stmts, re->producer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
886 new_var = re->init;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
887 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
888 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
889 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
890 /* Find all stmts on which expression "MEM_REF[idx]" depends. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
891 find_deps_in_bb_for_stmt (&stmts, gimple_bb (re->consumer), re->consumer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
892 /* Because we generate new stmt loading from the MEM_REF to TMP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
893 tree cond, tmp = copy_ssa_name (re->var);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
894 stmt = gimple_build_assign (tmp, re->init_ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
895 gimple_seq_add_stmt_without_update (&stmts, stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
896
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
897 /* Init new_var to MEM_REF or CONST depending on if it is the first
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
898 iteration. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
899 induction_p iv = m_inductions[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
900 cond = fold_build2 (NE_EXPR, boolean_type_node, iv->var, iv->init_val);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
901 new_var = copy_ssa_name (re->var);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
902 stmt = gimple_build_assign (new_var, COND_EXPR, cond, tmp, re->init);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
903 gimple_seq_add_stmt_without_update (&stmts, stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
904 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
905 gsi_insert_seq_before (&to, stmts, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
906
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
907 /* Replace all uses of reduction var with new variable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
908 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
909 imm_use_iterator iterator;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
910 FOR_EACH_IMM_USE_STMT (stmt, iterator, re->var)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
911 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
912 FOR_EACH_IMM_USE_ON_STMT (use_p, iterator)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
913 SET_USE (use_p, new_var);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
914
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
915 update_stmt (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
916 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
917
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
918 /* Move consumer stmt into inner loop, just after reduction next's def. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
919 unlink_stmt_vdef (re->consumer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
920 release_ssa_name (gimple_vdef (re->consumer));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
921 gimple_set_vdef (re->consumer, NULL_TREE);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
922 gimple_set_vuse (re->consumer, NULL_TREE);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
923 gimple_assign_set_rhs1 (re->consumer, re->next);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
924 update_stmt (re->consumer);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
925 from = gsi_for_stmt (re->consumer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
926 to = gsi_for_stmt (SSA_NAME_DEF_STMT (re->next));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
927 gsi_move_after (&from, &to);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
928
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
929 /* Mark the reduction variables for DCE. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
930 bitmap_set_bit (dce_seeds, SSA_NAME_VERSION (re->var));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
931 bitmap_set_bit (dce_seeds, SSA_NAME_VERSION (PHI_RESULT (re->lcssa_phi)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
932 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
933
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
934 /* Free DATAREFS and its auxiliary memory. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
935
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
936 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
937 free_data_refs_with_aux (vec<data_reference_p> datarefs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
938 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
939 data_reference_p dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
940 for (unsigned i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
941 if (dr->aux != NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
942 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
943 DR_ACCESS_STRIDE (dr)->release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
944 delete (vec<tree> *) dr->aux;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
945 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
946
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
947 free_data_refs (datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
948 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
949
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
950 /* Class for loop interchange transformation. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
951
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
952 class tree_loop_interchange
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
953 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
954 public:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
955 tree_loop_interchange (vec<class loop *> loop_nest)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
956 : m_loop_nest (loop_nest), m_niters_iv_var (NULL_TREE),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
957 m_dce_seeds (BITMAP_ALLOC (NULL)) { }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
958 ~tree_loop_interchange () { BITMAP_FREE (m_dce_seeds); }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
959 bool interchange (vec<data_reference_p>, vec<ddr_p>);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
960
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
961 private:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
962 void update_data_info (unsigned, unsigned, vec<data_reference_p>, vec<ddr_p>);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
963 bool valid_data_dependences (unsigned, unsigned, vec<ddr_p>);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
964 void interchange_loops (loop_cand &, loop_cand &);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
965 void map_inductions_to_loop (loop_cand &, loop_cand &);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
966 void move_code_to_inner_loop (class loop *, class loop *, basic_block *);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
967
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
968 /* The whole loop nest in which interchange is ongoing. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
969 vec<class loop *> m_loop_nest;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
970 /* We create new IV which is only used in loop's exit condition check.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
971 In case of 3-level loop nest interchange, when we interchange the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
972 innermost two loops, new IV created in the middle level loop does
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
973 not need to be preserved in interchanging the outermost two loops
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
974 later. We record the IV so that it can be skipped. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
975 tree m_niters_iv_var;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
976 /* Bitmap of seed variables for dead code elimination after interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
977 bitmap m_dce_seeds;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
978 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
979
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
980 /* Update data refs' access stride and dependence information after loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
981 interchange. I_IDX/O_IDX gives indices of interchanged loops in loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
982 nest. DATAREFS are data references. DDRS are data dependences. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
983
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
984 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
985 tree_loop_interchange::update_data_info (unsigned i_idx, unsigned o_idx,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
986 vec<data_reference_p> datarefs,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
987 vec<ddr_p> ddrs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
988 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
989 struct data_reference *dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
990 struct data_dependence_relation *ddr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
991
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
992 /* Update strides of data references. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
993 for (unsigned i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
994 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
995 vec<tree> *stride = DR_ACCESS_STRIDE (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
996 gcc_assert (stride->length () > i_idx);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
997 std::swap ((*stride)[i_idx], (*stride)[o_idx]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
998 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
999 /* Update data dependences. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1000 for (unsigned i = 0; ddrs.iterate (i, &ddr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1001 if (DDR_ARE_DEPENDENT (ddr) != chrec_known)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1002 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1003 for (unsigned j = 0; j < DDR_NUM_DIST_VECTS (ddr); ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1004 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1005 lambda_vector dist_vect = DDR_DIST_VECT (ddr, j);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1006 std::swap (dist_vect[i_idx], dist_vect[o_idx]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1007 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1008 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1009 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1010
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1011 /* Check data dependence relations, return TRUE if it's valid to interchange
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1012 two loops specified by I_IDX/O_IDX. Theoretically, interchanging the two
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1013 loops is valid only if dist vector, after interchanging, doesn't have '>'
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1014 as the leftmost non-'=' direction. Practically, this function have been
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1015 conservative here by not checking some valid cases. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1016
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1017 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1018 tree_loop_interchange::valid_data_dependences (unsigned i_idx, unsigned o_idx,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1019 vec<ddr_p> ddrs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1020 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1021 struct data_dependence_relation *ddr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1022
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1023 for (unsigned i = 0; ddrs.iterate (i, &ddr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1024 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1025 /* Skip no-dependence case. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1026 if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1027 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1028
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1029 for (unsigned j = 0; j < DDR_NUM_DIST_VECTS (ddr); ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1030 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1031 lambda_vector dist_vect = DDR_DIST_VECT (ddr, j);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1032 unsigned level = dependence_level (dist_vect, m_loop_nest.length ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1033
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1034 /* If there is no carried dependence. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1035 if (level == 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1036 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1037
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1038 level --;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1039
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1040 /* If dependence is not carried by any loop in between the two
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1041 loops [oloop, iloop] to interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1042 if (level < o_idx || level > i_idx)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1043 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1044
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1045 /* Be conservative, skip case if either direction at i_idx/o_idx
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1046 levels is not '=' or '<'. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1047 if (dist_vect[i_idx] < 0 || dist_vect[o_idx] < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1048 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1049 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1050 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1051
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1052 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1053 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1054
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1055 /* Interchange two loops specified by ILOOP and OLOOP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1056
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1057 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1058 tree_loop_interchange::interchange_loops (loop_cand &iloop, loop_cand &oloop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1059 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1060 reduction_p re;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1061 gimple_stmt_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1062 tree i_niters, o_niters, var_after;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1063
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1064 /* Undo inner loop's simple reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1065 for (unsigned i = 0; iloop.m_reductions.iterate (i, &re); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1066 if (re->type != DOUBLE_RTYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1067 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1068 if (re->producer)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1069 reset_debug_uses (re->producer);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1070
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1071 iloop.undo_simple_reduction (re, m_dce_seeds);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1072 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1073
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1074 /* Only need to reset debug uses for double reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1075 for (unsigned i = 0; oloop.m_reductions.iterate (i, &re); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1076 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1077 gcc_assert (re->type == DOUBLE_RTYPE);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1078 reset_debug_uses (SSA_NAME_DEF_STMT (re->var));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1079 reset_debug_uses (SSA_NAME_DEF_STMT (re->next));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1080 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1081
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1082 /* Prepare niters for both loops. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1083 class loop *loop_nest = m_loop_nest[0];
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1084 edge instantiate_below = loop_preheader_edge (loop_nest);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1085 gsi = gsi_last_bb (loop_preheader_edge (loop_nest)->src);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1086 i_niters = number_of_latch_executions (iloop.m_loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1087 i_niters = analyze_scalar_evolution (loop_outer (iloop.m_loop), i_niters);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1088 i_niters = instantiate_scev (instantiate_below, loop_outer (iloop.m_loop),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1089 i_niters);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1090 i_niters = force_gimple_operand_gsi (&gsi, unshare_expr (i_niters), true,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1091 NULL_TREE, false, GSI_CONTINUE_LINKING);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1092 o_niters = number_of_latch_executions (oloop.m_loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1093 if (oloop.m_loop != loop_nest)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1094 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1095 o_niters = analyze_scalar_evolution (loop_outer (oloop.m_loop), o_niters);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1096 o_niters = instantiate_scev (instantiate_below, loop_outer (oloop.m_loop),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1097 o_niters);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1098 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1099 o_niters = force_gimple_operand_gsi (&gsi, unshare_expr (o_niters), true,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1100 NULL_TREE, false, GSI_CONTINUE_LINKING);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1101
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1102 /* Move src's code to tgt loop. This is necessary when src is the outer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1103 loop and tgt is the inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1104 move_code_to_inner_loop (oloop.m_loop, iloop.m_loop, oloop.m_bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1105
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1106 /* Map outer loop's IV to inner loop, and vice versa. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1107 map_inductions_to_loop (oloop, iloop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1108 map_inductions_to_loop (iloop, oloop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1109
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1110 /* Create canonical IV for both loops. Note canonical IV for outer/inner
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1111 loop is actually from inner/outer loop. Also we record the new IV
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1112 created for the outer loop so that it can be skipped in later loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1113 interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1114 create_canonical_iv (oloop.m_loop, oloop.m_exit,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1115 i_niters, &m_niters_iv_var, &var_after);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1116 bitmap_set_bit (m_dce_seeds, SSA_NAME_VERSION (var_after));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1117 create_canonical_iv (iloop.m_loop, iloop.m_exit,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1118 o_niters, NULL, &var_after);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1119 bitmap_set_bit (m_dce_seeds, SSA_NAME_VERSION (var_after));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1120
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1121 /* Scrap niters estimation of interchanged loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1122 iloop.m_loop->any_upper_bound = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1123 iloop.m_loop->any_likely_upper_bound = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1124 free_numbers_of_iterations_estimates (iloop.m_loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1125 oloop.m_loop->any_upper_bound = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1126 oloop.m_loop->any_likely_upper_bound = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1127 free_numbers_of_iterations_estimates (oloop.m_loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1128
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1129 /* Clear all cached scev information. This is expensive but shouldn't be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1130 a problem given we interchange in very limited times. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1131 scev_reset_htab ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1132
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1133 /* ??? The association between the loop data structure and the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1134 CFG changed, so what was loop N at the source level is now
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1135 loop M. We should think of retaining the association or breaking
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1136 it fully by creating a new loop instead of re-using the "wrong" one. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1137 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1138
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1139 /* Map induction variables of SRC loop to TGT loop. The function firstly
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1140 creates the same IV of SRC loop in TGT loop, then deletes the original
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1141 IV and re-initialize it using the newly created IV. For example, loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1142 nest:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1143
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1144 for (i = 0; i < N; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1145 for (j = 0; j < M; j++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1146 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1147 //use of i;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1148 //use of j;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1149 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1150
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1151 will be transformed into:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1152
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1153 for (jj = 0; jj < M; jj++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1154 for (ii = 0; ii < N; ii++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1155 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1156 //use of ii;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1157 //use of jj;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1158 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1159
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1160 after loop interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1161
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1162 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1163 tree_loop_interchange::map_inductions_to_loop (loop_cand &src, loop_cand &tgt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1164 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1165 induction_p iv;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1166 edge e = tgt.m_exit;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1167 gimple_stmt_iterator incr_pos = gsi_last_bb (e->src), gsi;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1168
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1169 /* Map source loop's IV to target loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1170 for (unsigned i = 0; src.m_inductions.iterate (i, &iv); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1171 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1172 gimple *use_stmt, *stmt = SSA_NAME_DEF_STMT (iv->var);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1173 gcc_assert (is_a <gphi *> (stmt));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1174
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1175 use_operand_p use_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1176 /* Only map original IV to target loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1177 if (m_niters_iv_var != iv->var)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1178 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1179 /* Map the IV by creating the same one in target loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1180 tree var_before, var_after;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1181 tree base = unshare_expr (iv->init_expr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1182 tree step = unshare_expr (iv->step);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1183 create_iv (base, step, SSA_NAME_VAR (iv->var),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1184 tgt.m_loop, &incr_pos, false, &var_before, &var_after);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1185 bitmap_set_bit (m_dce_seeds, SSA_NAME_VERSION (var_before));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1186 bitmap_set_bit (m_dce_seeds, SSA_NAME_VERSION (var_after));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1187
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1188 /* Replace uses of the original IV var with newly created IV var. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1189 imm_use_iterator imm_iter;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1190 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, iv->var)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1191 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1192 FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1193 SET_USE (use_p, var_before);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1194
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1195 update_stmt (use_stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1196 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1197 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1198
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1199 /* Mark all uses for DCE. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1200 ssa_op_iter op_iter;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1201 FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, op_iter, SSA_OP_USE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1202 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1203 tree use = USE_FROM_PTR (use_p);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1204 if (TREE_CODE (use) == SSA_NAME
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1205 && ! SSA_NAME_IS_DEFAULT_DEF (use))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1206 bitmap_set_bit (m_dce_seeds, SSA_NAME_VERSION (use));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1207 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1208
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1209 /* Delete definition of the original IV in the source loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1210 gsi = gsi_for_stmt (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1211 remove_phi_node (&gsi, true);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1212 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1213 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1214
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1215 /* Move stmts of outer loop to inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1216
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1217 void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1218 tree_loop_interchange::move_code_to_inner_loop (class loop *outer,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1219 class loop *inner,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1220 basic_block *outer_bbs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1221 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1222 basic_block oloop_exit_bb = single_exit (outer)->src;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1223 gimple_stmt_iterator gsi, to;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1224
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1225 for (unsigned i = 0; i < outer->num_nodes; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1226 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1227 basic_block bb = outer_bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1228
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1229 /* Skip basic blocks of inner loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1230 if (flow_bb_inside_loop_p (inner, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1231 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1232
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1233 /* Move code from header/latch to header/latch. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1234 if (bb == outer->header)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1235 to = gsi_after_labels (inner->header);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1236 else if (bb == outer->latch)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1237 to = gsi_after_labels (inner->latch);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1238 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1239 /* Otherwise, simply move to exit->src. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1240 to = gsi_last_bb (single_exit (inner)->src);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1241
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1242 for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1243 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1244 gimple *stmt = gsi_stmt (gsi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1245
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1246 if (oloop_exit_bb == bb
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1247 && stmt == gsi_stmt (gsi_last_bb (oloop_exit_bb)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1248 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1249 gsi_next (&gsi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1250 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1251 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1252
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1253 if (gimple_vdef (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1254 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1255 unlink_stmt_vdef (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1256 release_ssa_name (gimple_vdef (stmt));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1257 gimple_set_vdef (stmt, NULL_TREE);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1258 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1259 if (gimple_vuse (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1260 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1261 gimple_set_vuse (stmt, NULL_TREE);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1262 update_stmt (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1263 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1264
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1265 reset_debug_uses (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1266 gsi_move_before (&gsi, &to);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1267 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1268 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1269 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1270
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1271 /* Given data reference DR in LOOP_NEST, the function computes DR's access
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1272 stride at each level of loop from innermost LOOP to outer. On success,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1273 it saves access stride at each level loop in a vector which is pointed
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1274 by DR->aux. For example:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1275
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1276 int arr[100][100][100];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1277 for (i = 0; i < 100; i++) ;(DR->aux)strides[0] = 40000
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1278 for (j = 100; j > 0; j--) ;(DR->aux)strides[1] = 400
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1279 for (k = 0; k < 100; k++) ;(DR->aux)strides[2] = 4
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1280 arr[i][j - 1][k] = 0; */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1281
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1282 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1283 compute_access_stride (class loop *loop_nest, class loop *loop,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1284 data_reference_p dr)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1285 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1286 vec<tree> *strides = new vec<tree> ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1287 basic_block bb = gimple_bb (DR_STMT (dr));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1288
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1289 while (!flow_bb_inside_loop_p (loop, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1290 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1291 strides->safe_push (build_int_cst (sizetype, 0));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1292 loop = loop_outer (loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1293 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1294 gcc_assert (loop == bb->loop_father);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1295
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1296 tree ref = DR_REF (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1297 if (TREE_CODE (ref) == COMPONENT_REF
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1298 && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1299 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1300 /* We can't take address of bitfields. If the bitfield is at constant
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1301 offset from the start of the struct, just use address of the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1302 struct, for analysis of the strides that shouldn't matter. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1303 if (!TREE_OPERAND (ref, 2)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1304 || TREE_CODE (TREE_OPERAND (ref, 2)) == INTEGER_CST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1305 ref = TREE_OPERAND (ref, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1306 /* Otherwise, if we have a bit field representative, use that. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1307 else if (DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (ref, 1))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1308 != NULL_TREE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1309 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1310 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (ref, 1));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1311 ref = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (ref, 0),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1312 repr, TREE_OPERAND (ref, 2));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1313 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1314 /* Otherwise punt. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1315 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1316 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1317 dr->aux = strides;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1318 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1319 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1320 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1321 tree scev_base = build_fold_addr_expr (ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1322 tree scev = analyze_scalar_evolution (loop, scev_base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1323 scev = instantiate_scev (loop_preheader_edge (loop_nest), loop, scev);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1324 if (! chrec_contains_undetermined (scev))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1325 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1326 tree sl = scev;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1327 class loop *expected = loop;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1328 while (TREE_CODE (sl) == POLYNOMIAL_CHREC)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1329 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1330 class loop *sl_loop = get_chrec_loop (sl);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1331 while (sl_loop != expected)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1332 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1333 strides->safe_push (size_int (0));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1334 expected = loop_outer (expected);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1335 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1336 strides->safe_push (CHREC_RIGHT (sl));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1337 sl = CHREC_LEFT (sl);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1338 expected = loop_outer (expected);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1339 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1340 if (! tree_contains_chrecs (sl, NULL))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1341 while (expected != loop_outer (loop_nest))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1342 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1343 strides->safe_push (size_int (0));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1344 expected = loop_outer (expected);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1345 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1346 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1347
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1348 dr->aux = strides;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1349 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1350
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1351 /* Given loop nest LOOP_NEST with innermost LOOP, the function computes
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1352 access strides with respect to each level loop for all data refs in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1353 DATAREFS from inner loop to outer loop. On success, it returns the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1354 outermost loop that access strides can be computed successfully for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1355 all data references. If access strides cannot be computed at least
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1356 for two levels of loop for any data reference, it returns NULL. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1357
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1358 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1359 compute_access_strides (class loop *loop_nest, class loop *loop,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1360 vec<data_reference_p> datarefs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1361 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1362 unsigned i, j, num_loops = (unsigned) -1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1363 data_reference_p dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1364 vec<tree> *stride;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1365
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1366 for (i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1367 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1368 compute_access_stride (loop_nest, loop, dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1369 stride = DR_ACCESS_STRIDE (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1370 if (stride->length () < num_loops)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1371 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1372 num_loops = stride->length ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1373 if (num_loops < 2)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1374 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1375 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1376 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1377
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1378 for (i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1379 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1380 stride = DR_ACCESS_STRIDE (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1381 if (stride->length () > num_loops)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1382 stride->truncate (num_loops);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1383
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1384 for (j = 0; j < (num_loops >> 1); ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1385 std::swap ((*stride)[j], (*stride)[num_loops - j - 1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1386 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1387
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1388 loop = superloop_at_depth (loop, loop_depth (loop) + 1 - num_loops);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1389 gcc_assert (loop_nest == loop || flow_loop_nested_p (loop_nest, loop));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1390 return loop;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1391 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1392
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1393 /* Prune access strides for data references in DATAREFS by removing strides
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1394 of loops that isn't in current LOOP_NEST. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1395
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1396 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1397 prune_access_strides_not_in_loop (class loop *loop_nest,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1398 class loop *innermost,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1399 vec<data_reference_p> datarefs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1400 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1401 data_reference_p dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1402 unsigned num_loops = loop_depth (innermost) - loop_depth (loop_nest) + 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1403 gcc_assert (num_loops > 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1404
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1405 /* Block remove strides of loops that is not in current loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1406 for (unsigned i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1407 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1408 vec<tree> *stride = DR_ACCESS_STRIDE (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1409 if (stride->length () > num_loops)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1410 stride->block_remove (0, stride->length () - num_loops);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1411 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1412 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1413
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1414 /* Dump access strides for all DATAREFS. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1415
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1416 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1417 dump_access_strides (vec<data_reference_p> datarefs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1418 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1419 data_reference_p dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1420 fprintf (dump_file, "Access Strides for DRs:\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1421 for (unsigned i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1422 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1423 fprintf (dump_file, " ");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1424 print_generic_expr (dump_file, DR_REF (dr), TDF_SLIM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1425 fprintf (dump_file, ":\t\t<");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1426
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1427 vec<tree> *stride = DR_ACCESS_STRIDE (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1428 unsigned num_loops = stride->length ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1429 for (unsigned j = 0; j < num_loops; ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1430 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1431 print_generic_expr (dump_file, (*stride)[j], TDF_SLIM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1432 fprintf (dump_file, "%s", (j < num_loops - 1) ? ",\t" : ">\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1433 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1434 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1435 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1436
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1437 /* Return true if it's profitable to interchange two loops whose index
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1438 in whole loop nest vector are I_IDX/O_IDX respectively. The function
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1439 computes and compares three types information from all DATAREFS:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1440 1) Access stride for loop I_IDX and O_IDX.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1441 2) Number of invariant memory references with respect to I_IDX before
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1442 and after loop interchange.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1443 3) Flags indicating if all memory references access sequential memory
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1444 in ILOOP, before and after loop interchange.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1445 If INNMOST_LOOP_P is true, the two loops for interchanging are the two
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1446 innermost loops in loop nest. This function also dumps information if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1447 DUMP_INFO_P is true. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1448
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1449 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1450 should_interchange_loops (unsigned i_idx, unsigned o_idx,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1451 vec<data_reference_p> datarefs,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1452 unsigned i_stmt_cost, unsigned o_stmt_cost,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1453 bool innermost_loops_p, bool dump_info_p = true)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1454 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1455 unsigned HOST_WIDE_INT ratio;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1456 unsigned i, j, num_old_inv_drs = 0, num_new_inv_drs = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1457 struct data_reference *dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1458 bool all_seq_dr_before_p = true, all_seq_dr_after_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1459 widest_int iloop_strides = 0, oloop_strides = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1460 unsigned num_unresolved_drs = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1461 unsigned num_resolved_ok_drs = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1462 unsigned num_resolved_not_ok_drs = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1463
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1464 if (dump_info_p && dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1465 fprintf (dump_file, "\nData ref strides:\n\tmem_ref:\t\tiloop\toloop\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1466
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1467 for (i = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1468 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1469 vec<tree> *stride = DR_ACCESS_STRIDE (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1470 tree iloop_stride = (*stride)[i_idx], oloop_stride = (*stride)[o_idx];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1471
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1472 bool subloop_stride_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1473 /* Data ref can't be invariant or sequential access at current loop if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1474 its address changes with respect to any subloops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1475 for (j = i_idx + 1; j < stride->length (); ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1476 if (!integer_zerop ((*stride)[j]))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1477 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1478 subloop_stride_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1479 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1480 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1481
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1482 if (integer_zerop (iloop_stride))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1483 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1484 if (!subloop_stride_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1485 num_old_inv_drs++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1486 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1487 if (integer_zerop (oloop_stride))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1488 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1489 if (!subloop_stride_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1490 num_new_inv_drs++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1491 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1492
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1493 if (TREE_CODE (iloop_stride) == INTEGER_CST
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1494 && TREE_CODE (oloop_stride) == INTEGER_CST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1495 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1496 iloop_strides = wi::add (iloop_strides, wi::to_widest (iloop_stride));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1497 oloop_strides = wi::add (oloop_strides, wi::to_widest (oloop_stride));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1498 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1499 else if (multiple_of_p (TREE_TYPE (iloop_stride),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1500 iloop_stride, oloop_stride))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1501 num_resolved_ok_drs++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1502 else if (multiple_of_p (TREE_TYPE (iloop_stride),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1503 oloop_stride, iloop_stride))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1504 num_resolved_not_ok_drs++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1505 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1506 num_unresolved_drs++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1507
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1508 /* Data ref can't be sequential access if its address changes in sub
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1509 loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1510 if (subloop_stride_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1511 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1512 all_seq_dr_before_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1513 all_seq_dr_after_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1514 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1515 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1516 /* Track if all data references are sequential accesses before/after loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1517 interchange. Note invariant is considered sequential here. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1518 tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1519 if (all_seq_dr_before_p
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1520 && ! (integer_zerop (iloop_stride)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1521 || operand_equal_p (access_size, iloop_stride, 0)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1522 all_seq_dr_before_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1523 if (all_seq_dr_after_p
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1524 && ! (integer_zerop (oloop_stride)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1525 || operand_equal_p (access_size, oloop_stride, 0)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1526 all_seq_dr_after_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1527 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1528
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1529 if (dump_info_p && dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1530 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1531 fprintf (dump_file, "\toverall:\t\t");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1532 print_decu (iloop_strides, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1533 fprintf (dump_file, "\t");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1534 print_decu (oloop_strides, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1535 fprintf (dump_file, "\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1536
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1537 fprintf (dump_file, "Invariant data ref: before(%d), after(%d)\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1538 num_old_inv_drs, num_new_inv_drs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1539 fprintf (dump_file, "All consecutive stride: before(%s), after(%s)\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1540 all_seq_dr_before_p ? "true" : "false",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1541 all_seq_dr_after_p ? "true" : "false");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1542 fprintf (dump_file, "OK to interchage with variable strides: %d\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1543 num_resolved_ok_drs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1544 fprintf (dump_file, "Not OK to interchage with variable strides: %d\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1545 num_resolved_not_ok_drs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1546 fprintf (dump_file, "Variable strides we cannot decide: %d\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1547 num_unresolved_drs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1548 fprintf (dump_file, "Stmt cost of inner loop: %d\n", i_stmt_cost);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1549 fprintf (dump_file, "Stmt cost of outer loop: %d\n", o_stmt_cost);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1550 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1551
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1552 if (num_unresolved_drs != 0 || num_resolved_not_ok_drs != 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1553 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1554
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1555 /* Stmts of outer loop will be moved to inner loop. If there are two many
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1556 such stmts, it could make inner loop costly. Here we compare stmt cost
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1557 between outer and inner loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1558 if (i_stmt_cost && o_stmt_cost
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1559 && num_old_inv_drs + o_stmt_cost > num_new_inv_drs
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1560 && o_stmt_cost * STMT_COST_RATIO > i_stmt_cost)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1561 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1562
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1563 /* We use different stride comparison ratio for interchanging innermost
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1564 two loops or not. The idea is to be conservative in interchange for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1565 the innermost loops. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1566 ratio = innermost_loops_p ? INNER_STRIDE_RATIO : OUTER_STRIDE_RATIO;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1567 /* Do interchange if it gives better data locality behavior. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1568 if (wi::gtu_p (iloop_strides, wi::mul (oloop_strides, ratio)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1569 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1570 if (wi::gtu_p (iloop_strides, oloop_strides))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1571 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1572 /* Or it creates more invariant memory references. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1573 if ((!all_seq_dr_before_p || all_seq_dr_after_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1574 && num_new_inv_drs > num_old_inv_drs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1575 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1576 /* Or it makes all memory references sequential. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1577 if (num_new_inv_drs >= num_old_inv_drs
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1578 && !all_seq_dr_before_p && all_seq_dr_after_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1579 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1580 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1581
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1582 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1583 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1584
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1585 /* Try to interchange inner loop of a loop nest to outer level. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1586
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1587 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1588 tree_loop_interchange::interchange (vec<data_reference_p> datarefs,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1589 vec<ddr_p> ddrs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1590 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1591 dump_user_location_t loc = find_loop_location (m_loop_nest[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1592 bool changed_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1593 /* In each iteration we try to interchange I-th loop with (I+1)-th loop.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1594 The overall effect is to push inner loop to outermost level in whole
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1595 loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1596 for (unsigned i = m_loop_nest.length (); i > 1; --i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1597 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1598 unsigned i_idx = i - 1, o_idx = i - 2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1599
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1600 /* Check validity for loop interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1601 if (!valid_data_dependences (i_idx, o_idx, ddrs))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1602 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1603
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1604 loop_cand iloop (m_loop_nest[i_idx], m_loop_nest[o_idx]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1605 loop_cand oloop (m_loop_nest[o_idx], m_loop_nest[o_idx]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1606
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1607 /* Check if we can do transformation for loop interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1608 if (!iloop.analyze_carried_vars (NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1609 || !iloop.analyze_lcssa_phis ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1610 || !oloop.analyze_carried_vars (&iloop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1611 || !oloop.analyze_lcssa_phis ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1612 || !iloop.can_interchange_p (NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1613 || !oloop.can_interchange_p (&iloop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1614 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1615
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1616 /* Outer loop's stmts will be moved to inner loop during interchange.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1617 If there are many of them, it may make inner loop very costly. We
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1618 need to check number of outer loop's stmts in profit cost model of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1619 interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1620 int stmt_cost = oloop.m_num_stmts;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1621 /* Count out the exit checking stmt of outer loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1622 stmt_cost --;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1623 /* Count out IV's increasing stmt, IVOPTs takes care if it. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1624 stmt_cost -= oloop.m_inductions.length ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1625 /* Count in the additional load and cond_expr stmts caused by inner
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1626 loop's constant initialized reduction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1627 stmt_cost += iloop.m_const_init_reduc * 2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1628 if (stmt_cost < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1629 stmt_cost = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1630
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1631 /* Check profitability for loop interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1632 if (should_interchange_loops (i_idx, o_idx, datarefs,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1633 (unsigned) iloop.m_num_stmts,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1634 (unsigned) stmt_cost,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1635 iloop.m_loop->inner == NULL))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1636 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1637 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1638 fprintf (dump_file,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1639 "Loop_pair<outer:%d, inner:%d> is interchanged\n\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1640 oloop.m_loop->num, iloop.m_loop->num);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1641
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1642 changed_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1643 interchange_loops (iloop, oloop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1644 /* No need to update if there is no further loop interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1645 if (o_idx > 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1646 update_data_info (i_idx, o_idx, datarefs, ddrs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1647 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1648 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1649 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1650 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1651 fprintf (dump_file,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1652 "Loop_pair<outer:%d, inner:%d> is not interchanged\n\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1653 oloop.m_loop->num, iloop.m_loop->num);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1654 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1655 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1656 simple_dce_from_worklist (m_dce_seeds);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1657
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1658 if (changed_p && dump_enabled_p ())
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1659 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1660 "loops interchanged in loop nest\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1661
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1662 return changed_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1663 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1664
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1665
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1666 /* Loop interchange pass. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1667
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1668 namespace {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1669
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1670 const pass_data pass_data_linterchange =
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1671 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1672 GIMPLE_PASS, /* type */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1673 "linterchange", /* name */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1674 OPTGROUP_LOOP, /* optinfo_flags */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1675 TV_LINTERCHANGE, /* tv_id */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1676 PROP_cfg, /* properties_required */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1677 0, /* properties_provided */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1678 0, /* properties_destroyed */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1679 0, /* todo_flags_start */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1680 0, /* todo_flags_finish */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1681 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1682
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1683 class pass_linterchange : public gimple_opt_pass
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1684 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1685 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1686 pass_linterchange (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1687 : gimple_opt_pass (pass_data_linterchange, ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1688 {}
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1689
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1690 /* opt_pass methods: */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1691 opt_pass * clone () { return new pass_linterchange (m_ctxt); }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1692 virtual bool gate (function *) { return flag_loop_interchange; }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1693 virtual unsigned int execute (function *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1694
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1695 }; // class pass_linterchange
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1696
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1697
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1698 /* Return true if LOOP has proper form for interchange. We check three
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1699 conditions in the function:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1700 1) In general, a loop can be interchanged only if it doesn't have
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1701 basic blocks other than header, exit and latch besides possible
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1702 inner loop nest. This basically restricts loop interchange to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1703 below form loop nests:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1704
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1705 header<---+
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1706 | |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1707 v |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1708 INNER_LOOP |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1709 | |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1710 v |
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1711 exit--->latch
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1712
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1713 2) Data reference in basic block that executes in different times
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1714 than loop head/exit is not allowed.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1715 3) Record the innermost outer loop that doesn't form rectangle loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1716 nest with LOOP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1717
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1718 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1719 proper_loop_form_for_interchange (class loop *loop, class loop **min_outer)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1720 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1721 edge e0, e1, exit;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1722
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1723 /* Don't interchange if loop has unsupported information for the moment. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1724 if (loop->safelen > 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1725 || loop->constraints != 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1726 || loop->can_be_parallel
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1727 || loop->dont_vectorize
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1728 || loop->force_vectorize
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1729 || loop->in_oacc_kernels_region
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1730 || loop->orig_loop_num != 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1731 || loop->simduid != NULL_TREE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1732 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1733
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1734 /* Don't interchange if outer loop has basic block other than header, exit
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1735 and latch. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1736 if (loop->inner != NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1737 && loop->num_nodes != loop->inner->num_nodes + 3)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1738 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1739
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1740 if ((exit = single_dom_exit (loop)) == NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1741 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1742
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1743 /* Check control flow on loop header/exit blocks. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1744 if (loop->header == exit->src
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1745 && (EDGE_COUNT (loop->header->preds) != 2
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1746 || EDGE_COUNT (loop->header->succs) != 2))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1747 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1748 else if (loop->header != exit->src
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1749 && (EDGE_COUNT (loop->header->preds) != 2
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1750 || !single_succ_p (loop->header)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1751 || unsupported_edge (single_succ_edge (loop->header))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1752 || EDGE_COUNT (exit->src->succs) != 2
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1753 || !single_pred_p (exit->src)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1754 || unsupported_edge (single_pred_edge (exit->src))))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1755 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1756
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1757 e0 = EDGE_PRED (loop->header, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1758 e1 = EDGE_PRED (loop->header, 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1759 if (unsupported_edge (e0) || unsupported_edge (e1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1760 || (e0->src != loop->latch && e1->src != loop->latch)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1761 || (e0->src->loop_father == loop && e1->src->loop_father == loop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1762 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1763
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1764 e0 = EDGE_SUCC (exit->src, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1765 e1 = EDGE_SUCC (exit->src, 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1766 if (unsupported_edge (e0) || unsupported_edge (e1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1767 || (e0->dest != loop->latch && e1->dest != loop->latch)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1768 || (e0->dest->loop_father == loop && e1->dest->loop_father == loop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1769 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1770
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1771 /* Don't interchange if any reference is in basic block that doesn't
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1772 dominate exit block. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1773 basic_block *bbs = get_loop_body (loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1774 for (unsigned i = 0; i < loop->num_nodes; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1775 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1776 basic_block bb = bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1777
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1778 if (bb->loop_father != loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1779 || bb == loop->header || bb == exit->src
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1780 || dominated_by_p (CDI_DOMINATORS, exit->src, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1781 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1782
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1783 for (gimple_stmt_iterator gsi = gsi_start_nondebug_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1784 !gsi_end_p (gsi); gsi_next_nondebug (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1785 if (gimple_vuse (gsi_stmt (gsi)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1786 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1787 free (bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1788 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1789 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1790 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1791 free (bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1792
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1793 tree niters = number_of_latch_executions (loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1794 niters = analyze_scalar_evolution (loop_outer (loop), niters);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1795 if (!niters || chrec_contains_undetermined (niters))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1796 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1797
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1798 /* Record the innermost outer loop that doesn't form rectangle loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1799 for (loop_p loop2 = loop_outer (loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1800 loop2 && flow_loop_nested_p (*min_outer, loop2);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1801 loop2 = loop_outer (loop2))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1802 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1803 niters = instantiate_scev (loop_preheader_edge (loop2),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1804 loop_outer (loop), niters);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1805 if (!evolution_function_is_invariant_p (niters, loop2->num))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1806 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1807 *min_outer = loop2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1808 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1809 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1810 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1811 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1812 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1813
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1814 /* Return true if any two adjacent loops in loop nest [INNERMOST, LOOP_NEST]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1815 should be interchanged by looking into all DATAREFS. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1816
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1817 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1818 should_interchange_loop_nest (class loop *loop_nest, class loop *innermost,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1819 vec<data_reference_p> datarefs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1820 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1821 unsigned idx = loop_depth (innermost) - loop_depth (loop_nest);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1822 gcc_assert (idx > 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1823
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1824 /* Check if any two adjacent loops should be interchanged. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1825 for (class loop *loop = innermost;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1826 loop != loop_nest; loop = loop_outer (loop), idx--)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1827 if (should_interchange_loops (idx, idx - 1, datarefs, 0, 0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1828 loop == innermost, false))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1829 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1830
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1831 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1832 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1833
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1834 /* Given loop nest LOOP_NEST and data references DATAREFS, compute data
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1835 dependences for loop interchange and store it in DDRS. Note we compute
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1836 dependences directly rather than call generic interface so that we can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1837 return on unknown dependence instantly. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1838
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1839 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1840 tree_loop_interchange_compute_ddrs (vec<loop_p> loop_nest,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1841 vec<data_reference_p> datarefs,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1842 vec<ddr_p> *ddrs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1843 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1844 struct data_reference *a, *b;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1845 class loop *innermost = loop_nest.last ();
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1846
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1847 for (unsigned i = 0; datarefs.iterate (i, &a); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1848 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1849 bool a_outer_p = gimple_bb (DR_STMT (a))->loop_father != innermost;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1850 for (unsigned j = i + 1; datarefs.iterate (j, &b); ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1851 if (DR_IS_WRITE (a) || DR_IS_WRITE (b))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1852 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1853 bool b_outer_p = gimple_bb (DR_STMT (b))->loop_father != innermost;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1854 /* Don't support multiple write references in outer loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1855 if (a_outer_p && b_outer_p && DR_IS_WRITE (a) && DR_IS_WRITE (b))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1856 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1857
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1858 ddr_p ddr = initialize_data_dependence_relation (a, b, loop_nest);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1859 ddrs->safe_push (ddr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1860 compute_affine_dependence (ddr, loop_nest[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1861
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1862 /* Give up if ddr is unknown dependence or classic direct vector
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1863 is not available. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1864 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1865 || (DDR_ARE_DEPENDENT (ddr) == NULL_TREE
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1866 && DDR_NUM_DIR_VECTS (ddr) == 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1867 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1868
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1869 /* If either data references is in outer loop of nest, we require
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1870 no dependence here because the data reference need to be moved
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1871 into inner loop during interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1872 if (a_outer_p && b_outer_p
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1873 && operand_equal_p (DR_REF (a), DR_REF (b), 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1874 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1875 if (DDR_ARE_DEPENDENT (ddr) != chrec_known
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1876 && (a_outer_p || b_outer_p))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1877 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1878 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1879 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1880
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1881 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1882 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1883
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1884 /* Prune DATAREFS by removing any data reference not inside of LOOP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1885
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1886 static inline void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1887 prune_datarefs_not_in_loop (class loop *loop, vec<data_reference_p> datarefs)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1888 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1889 unsigned i, j;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1890 struct data_reference *dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1891
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1892 for (i = 0, j = 0; datarefs.iterate (i, &dr); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1893 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1894 if (flow_bb_inside_loop_p (loop, gimple_bb (DR_STMT (dr))))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1895 datarefs[j++] = dr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1896 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1897 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1898 if (dr->aux)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1899 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1900 DR_ACCESS_STRIDE (dr)->release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1901 delete (vec<tree> *) dr->aux;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1902 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1903 free_data_ref (dr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1904 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1905 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1906 datarefs.truncate (j);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1907 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1908
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1909 /* Find and store data references in DATAREFS for LOOP nest. If there's
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1910 difficult data reference in a basic block, we shrink the loop nest to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1911 inner loop of that basic block's father loop. On success, return the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1912 outer loop of the result loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1913
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1914 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1915 prepare_data_references (class loop *loop, vec<data_reference_p> *datarefs)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1916 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1917 class loop *loop_nest = loop;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1918 vec<data_reference_p> *bb_refs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1919 basic_block bb, *bbs = get_loop_body_in_dom_order (loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1920
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1921 for (unsigned i = 0; i < loop->num_nodes; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1922 bbs[i]->aux = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1923
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1924 /* Find data references for all basic blocks. Shrink loop nest on difficult
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1925 data reference. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1926 for (unsigned i = 0; loop_nest && i < loop->num_nodes; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1927 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1928 bb = bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1929 if (!flow_bb_inside_loop_p (loop_nest, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1930 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1931
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1932 bb_refs = new vec<data_reference_p> ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1933 if (find_data_references_in_bb (loop, bb, bb_refs) == chrec_dont_know)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1934 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1935 loop_nest = bb->loop_father->inner;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1936 if (loop_nest && !loop_nest->inner)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1937 loop_nest = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1938
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1939 free_data_refs (*bb_refs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1940 delete bb_refs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1941 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1942 else if (bb_refs->is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1943 delete bb_refs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1944 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1945 bb->aux = bb_refs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1946 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1947
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1948 /* Collect all data references in loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1949 for (unsigned i = 0; i < loop->num_nodes; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1950 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1951 bb = bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1952 if (!bb->aux)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1953 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1954
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1955 bb_refs = (vec<data_reference_p> *) bb->aux;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1956 if (loop_nest && flow_bb_inside_loop_p (loop_nest, bb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1957 datarefs->safe_splice (*bb_refs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1958 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1959 free_data_refs (*bb_refs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1960
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1961 delete bb_refs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1962 bb->aux = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1963 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1964 free (bbs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1965
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1966 return loop_nest;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1967 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1968
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1969 /* Given innermost LOOP, return true if perfect loop nest can be found and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1970 data dependences can be computed. If succeed, record the perfect loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1971 nest in LOOP_NEST; record all data references in DATAREFS and record all
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1972 data dependence relations in DDRS.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1973
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1974 We do support a restricted form of imperfect loop nest, i.e, loop nest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1975 with load/store in outer loop initializing/finalizing simple reduction
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1976 of the innermost loop. For such outer loop reference, we require that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1977 it has no dependence with others sinve it will be moved to inner loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1978 in interchange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1979
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1980 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1981 prepare_perfect_loop_nest (class loop *loop, vec<loop_p> *loop_nest,
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1982 vec<data_reference_p> *datarefs, vec<ddr_p> *ddrs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1983 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1984 class loop *start_loop = NULL, *innermost = loop;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1985 class loop *outermost = loops_for_fn (cfun)->tree_root;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1986
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1987 /* Find loop nest from the innermost loop. The outermost is the innermost
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1988 outer*/
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1989 while (loop->num != 0 && loop->inner == start_loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1990 && flow_loop_nested_p (outermost, loop))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1991 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1992 if (!proper_loop_form_for_interchange (loop, &outermost))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1993 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1994
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1995 start_loop = loop;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1996 /* If this loop has sibling loop, the father loop won't be in perfect
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1997 loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1998 if (loop->next != NULL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1999 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2000
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2001 loop = loop_outer (loop);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2002 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2003 if (!start_loop || !start_loop->inner)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2004 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2005
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2006 /* Prepare the data reference vector for the loop nest, pruning outer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2007 loops we cannot handle. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2008 start_loop = prepare_data_references (start_loop, datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2009 if (!start_loop
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2010 /* Check if there is no data reference. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2011 || datarefs->is_empty ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2012 /* Check if there are too many of data references. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2013 || (int) datarefs->length () > MAX_DATAREFS)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2014 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2015
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2016 /* Compute access strides for all data references, pruning outer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2017 loops we cannot analyze refs in. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2018 start_loop = compute_access_strides (start_loop, innermost, *datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2019 if (!start_loop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2020 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2021
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2022 /* Check if any interchange is profitable in the loop nest. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2023 if (!should_interchange_loop_nest (start_loop, innermost, *datarefs))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2024 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2025
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2026 /* Check if data dependences can be computed for loop nest starting from
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2027 start_loop. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2028 loop = start_loop;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2029 do {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2030 loop_nest->truncate (0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2031
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2032 if (loop != start_loop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2033 prune_datarefs_not_in_loop (start_loop, *datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2034
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2035 if (find_loop_nest (start_loop, loop_nest)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2036 && tree_loop_interchange_compute_ddrs (*loop_nest, *datarefs, ddrs))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2037 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2038 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2039 fprintf (dump_file,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2040 "\nConsider loop interchange for loop_nest<%d - %d>\n",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2041 start_loop->num, innermost->num);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2042
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2043 if (loop != start_loop)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2044 prune_access_strides_not_in_loop (start_loop, innermost, *datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2045
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2046 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2047 dump_access_strides (*datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2048
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2049 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2050 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2051
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2052 free_dependence_relations (*ddrs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2053 *ddrs = vNULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2054 /* Try to compute data dependences with the outermost loop stripped. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2055 loop = start_loop;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2056 start_loop = start_loop->inner;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2057 } while (start_loop && start_loop->inner);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2058
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2059 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2060 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2061
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2062 /* Main entry for loop interchange pass. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2063
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2064 unsigned int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2065 pass_linterchange::execute (function *fun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2066 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2067 if (number_of_loops (fun) <= 2)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2068 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2069
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2070 bool changed_p = false;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2071 class loop *loop;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2072 FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2073 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2074 vec<loop_p> loop_nest = vNULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2075 vec<data_reference_p> datarefs = vNULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2076 vec<ddr_p> ddrs = vNULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2077 if (prepare_perfect_loop_nest (loop, &loop_nest, &datarefs, &ddrs))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2078 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2079 tree_loop_interchange loop_interchange (loop_nest);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2080 changed_p |= loop_interchange.interchange (datarefs, ddrs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2081 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2082 free_dependence_relations (ddrs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2083 free_data_refs_with_aux (datarefs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2084 loop_nest.release ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2085 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2086
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2087 return changed_p ? (TODO_update_ssa_only_virtuals) : 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2088 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2089
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2090 } // anon namespace
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2091
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2092 gimple_opt_pass *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2093 make_pass_linterchange (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2094 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2095 return new pass_linterchange (ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2096 }