annotate gcc/lra-remat.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Rematerialize pseudos values.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Vladimir Makarov <vmakarov@redhat.com>.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 /* This code objective is to rematerialize spilled pseudo values. To
kono
parents:
diff changeset
22 do this we calculate available insn candidates. The candidate is
kono
parents:
diff changeset
23 available at some point if there is dominated set of insns with the
kono
parents:
diff changeset
24 same pattern, the insn inputs are not dying or modified on any path
kono
parents:
diff changeset
25 from the set, the outputs are not modified.
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 The insns containing memory or spilled pseudos (except for the
kono
parents:
diff changeset
28 rematerialized pseudo) are not considered as such insns are not
kono
parents:
diff changeset
29 profitable in comparison with regular loads of spilled pseudo
kono
parents:
diff changeset
30 values. That simplifies the implementation as we don't need to
kono
parents:
diff changeset
31 deal with memory aliasing.
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 To speed up available candidate calculation, we calculate partially
kono
parents:
diff changeset
34 available candidates first and use them for initialization of the
kono
parents:
diff changeset
35 availability. That is because (partial) availability sets are
kono
parents:
diff changeset
36 sparse.
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 The rematerialization sub-pass could be improved further in the
kono
parents:
diff changeset
39 following ways:
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 o We could make longer live ranges of inputs in the
kono
parents:
diff changeset
42 rematerialization candidates if their hard registers are not used
kono
parents:
diff changeset
43 for other purposes. This could be complicated if we need to
kono
parents:
diff changeset
44 update BB live info information as LRA does not use
kono
parents:
diff changeset
45 DF-infrastructure for compile-time reasons. This problem could
kono
parents:
diff changeset
46 be overcome if constrain making live ranges longer only in BB/EBB
kono
parents:
diff changeset
47 scope.
kono
parents:
diff changeset
48 o We could use cost-based decision to choose rematerialization insn
kono
parents:
diff changeset
49 (currently all insns without memory is can be used).
kono
parents:
diff changeset
50 o We could use other free hard regs for unused output pseudos in
kono
parents:
diff changeset
51 rematerialization candidates although such cases probably will
kono
parents:
diff changeset
52 be very rare. */
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 #include "config.h"
kono
parents:
diff changeset
56 #include "system.h"
kono
parents:
diff changeset
57 #include "coretypes.h"
kono
parents:
diff changeset
58 #include "backend.h"
kono
parents:
diff changeset
59 #include "rtl.h"
kono
parents:
diff changeset
60 #include "df.h"
kono
parents:
diff changeset
61 #include "insn-config.h"
kono
parents:
diff changeset
62 #include "regs.h"
kono
parents:
diff changeset
63 #include "memmodel.h"
kono
parents:
diff changeset
64 #include "ira.h"
kono
parents:
diff changeset
65 #include "recog.h"
kono
parents:
diff changeset
66 #include "lra.h"
kono
parents:
diff changeset
67 #include "lra-int.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
68 #include "function-abi.h"
111
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 /* Number of candidates for rematerialization. */
kono
parents:
diff changeset
71 static unsigned int cands_num;
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 /* Bitmap used for different calculations. */
kono
parents:
diff changeset
74 static bitmap_head temp_bitmap;
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 /* Registers accessed via subreg_p. */
kono
parents:
diff changeset
77 static bitmap_head subreg_regs;
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 typedef struct cand *cand_t;
kono
parents:
diff changeset
80 typedef const struct cand *const_cand_t;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 /* Insn candidates for rematerialization. The candidate insn should
kono
parents:
diff changeset
83 have the following properies:
kono
parents:
diff changeset
84 o no any memory (as access to memory is non-profitable)
kono
parents:
diff changeset
85 o no INOUT regs (it means no non-paradoxical subreg of output reg)
kono
parents:
diff changeset
86 o one output spilled pseudo (or reload pseudo of a spilled pseudo)
kono
parents:
diff changeset
87 o all other pseudos are with assigned hard regs. */
kono
parents:
diff changeset
88 struct cand
kono
parents:
diff changeset
89 {
kono
parents:
diff changeset
90 /* Index of the candidates in all_cands. */
kono
parents:
diff changeset
91 int index;
kono
parents:
diff changeset
92 /* Insn pseudo regno for rematerialization. */
kono
parents:
diff changeset
93 int regno;
kono
parents:
diff changeset
94 /* The candidate insn. */
kono
parents:
diff changeset
95 rtx_insn *insn;
kono
parents:
diff changeset
96 /* Non-negative if a reload pseudo is in the insn instead of the
kono
parents:
diff changeset
97 pseudo for rematerialization. */
kono
parents:
diff changeset
98 int reload_regno;
kono
parents:
diff changeset
99 /* Number of the operand containing the regno or its reload
kono
parents:
diff changeset
100 regno. */
kono
parents:
diff changeset
101 int nop;
kono
parents:
diff changeset
102 /* Next candidate for the same regno. */
kono
parents:
diff changeset
103 cand_t next_regno_cand;
kono
parents:
diff changeset
104 };
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 /* Vector containing all candidates. */
kono
parents:
diff changeset
107 static vec<cand_t> all_cands;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
108 /* Map: insn -> candidate representing it. It is null if the insn cannot
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
109 be used for rematerialization. */
111
kono
parents:
diff changeset
110 static cand_t *insn_to_cand;
kono
parents:
diff changeset
111 /* A secondary map, for candidates that involve two insns, where the
kono
parents:
diff changeset
112 second one makes the equivalence. The candidate must not be used
kono
parents:
diff changeset
113 before seeing this activation insn. */
kono
parents:
diff changeset
114 static cand_t *insn_to_cand_activation;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 /* Map regno -> candidates can be used for the regno
kono
parents:
diff changeset
117 rematerialization. */
kono
parents:
diff changeset
118 static cand_t *regno_cands;
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 /* Data about basic blocks used for the rematerialization
kono
parents:
diff changeset
121 sub-pass. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
122 class remat_bb_data
111
kono
parents:
diff changeset
123 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
124 public:
111
kono
parents:
diff changeset
125 /* Basic block about which the below data are. */
kono
parents:
diff changeset
126 basic_block bb;
kono
parents:
diff changeset
127 /* Registers changed in the basic block: */
kono
parents:
diff changeset
128 bitmap_head changed_regs;
kono
parents:
diff changeset
129 /* Registers becoming dead in the BB. */
kono
parents:
diff changeset
130 bitmap_head dead_regs;
kono
parents:
diff changeset
131 /* Cands present in the BB whose in/out regs are not changed after
kono
parents:
diff changeset
132 the cands occurence and are not dead (except the reload
kono
parents:
diff changeset
133 regno). */
kono
parents:
diff changeset
134 bitmap_head gen_cands;
kono
parents:
diff changeset
135 bitmap_head livein_cands; /* cands whose inputs live at the BB start. */
kono
parents:
diff changeset
136 bitmap_head pavin_cands; /* cands partially available at BB entry. */
kono
parents:
diff changeset
137 bitmap_head pavout_cands; /* cands partially available at BB exit. */
kono
parents:
diff changeset
138 bitmap_head avin_cands; /* cands available at the entry of the BB. */
kono
parents:
diff changeset
139 bitmap_head avout_cands; /* cands available at the exit of the BB. */
kono
parents:
diff changeset
140 };
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 /* Array for all BB data. Indexed by the corresponding BB index. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
143 typedef class remat_bb_data *remat_bb_data_t;
111
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 /* Basic blocks for data flow problems -- all bocks except the special
kono
parents:
diff changeset
146 ones. */
kono
parents:
diff changeset
147 static bitmap_head all_blocks;
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 /* All basic block data are referred through the following array. */
kono
parents:
diff changeset
150 static remat_bb_data_t remat_bb_data;
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 /* Two small functions for access to the bb data. */
kono
parents:
diff changeset
153 static inline remat_bb_data_t
kono
parents:
diff changeset
154 get_remat_bb_data (basic_block bb)
kono
parents:
diff changeset
155 {
kono
parents:
diff changeset
156 return &remat_bb_data[(bb)->index];
kono
parents:
diff changeset
157 }
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 static inline remat_bb_data_t
kono
parents:
diff changeset
160 get_remat_bb_data_by_index (int index)
kono
parents:
diff changeset
161 {
kono
parents:
diff changeset
162 return &remat_bb_data[index];
kono
parents:
diff changeset
163 }
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 /* Hash table for the candidates. Different insns (e.g. structurally
kono
parents:
diff changeset
168 the same insns or even insns with different unused output regs) can
kono
parents:
diff changeset
169 be represented by the same candidate in the table. */
kono
parents:
diff changeset
170 static htab_t cand_table;
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 /* Hash function for candidate CAND. */
kono
parents:
diff changeset
173 static hashval_t
kono
parents:
diff changeset
174 cand_hash (const void *cand)
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 const_cand_t c = (const_cand_t) cand;
kono
parents:
diff changeset
177 lra_insn_recog_data_t id = lra_get_insn_recog_data (c->insn);
kono
parents:
diff changeset
178 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
179 int nops = static_id->n_operands;
kono
parents:
diff changeset
180 hashval_t hash = 0;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 for (int i = 0; i < nops; i++)
kono
parents:
diff changeset
183 if (i == c->nop)
kono
parents:
diff changeset
184 hash = iterative_hash_object (c->regno, hash);
kono
parents:
diff changeset
185 else if (static_id->operand[i].type == OP_IN)
kono
parents:
diff changeset
186 hash = iterative_hash_object (*id->operand_loc[i], hash);
kono
parents:
diff changeset
187 return hash;
kono
parents:
diff changeset
188 }
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 /* Equal function for candidates CAND1 and CAND2. They are equal if
kono
parents:
diff changeset
191 the corresponding candidate insns have the same code, the same
kono
parents:
diff changeset
192 regno for rematerialization, the same input operands. */
kono
parents:
diff changeset
193 static int
kono
parents:
diff changeset
194 cand_eq_p (const void *cand1, const void *cand2)
kono
parents:
diff changeset
195 {
kono
parents:
diff changeset
196 const_cand_t c1 = (const_cand_t) cand1;
kono
parents:
diff changeset
197 const_cand_t c2 = (const_cand_t) cand2;
kono
parents:
diff changeset
198 lra_insn_recog_data_t id1 = lra_get_insn_recog_data (c1->insn);
kono
parents:
diff changeset
199 lra_insn_recog_data_t id2 = lra_get_insn_recog_data (c2->insn);
kono
parents:
diff changeset
200 struct lra_static_insn_data *static_id1 = id1->insn_static_data;
kono
parents:
diff changeset
201 int nops = static_id1->n_operands;
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 if (c1->regno != c2->regno
kono
parents:
diff changeset
204 || INSN_CODE (c1->insn) < 0
kono
parents:
diff changeset
205 || INSN_CODE (c1->insn) != INSN_CODE (c2->insn))
kono
parents:
diff changeset
206 return false;
kono
parents:
diff changeset
207 gcc_assert (c1->nop == c2->nop);
kono
parents:
diff changeset
208 for (int i = 0; i < nops; i++)
kono
parents:
diff changeset
209 if (i != c1->nop && static_id1->operand[i].type == OP_IN
kono
parents:
diff changeset
210 && *id1->operand_loc[i] != *id2->operand_loc[i])
kono
parents:
diff changeset
211 return false;
kono
parents:
diff changeset
212 return true;
kono
parents:
diff changeset
213 }
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 /* Insert candidate CAND into the table if it is not there yet.
kono
parents:
diff changeset
216 Return candidate which is in the table. */
kono
parents:
diff changeset
217 static cand_t
kono
parents:
diff changeset
218 insert_cand (cand_t cand)
kono
parents:
diff changeset
219 {
kono
parents:
diff changeset
220 void **entry_ptr;
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 entry_ptr = htab_find_slot (cand_table, cand, INSERT);
kono
parents:
diff changeset
223 if (*entry_ptr == NULL)
kono
parents:
diff changeset
224 *entry_ptr = (void *) cand;
kono
parents:
diff changeset
225 return (cand_t) *entry_ptr;
kono
parents:
diff changeset
226 }
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 /* Free candidate CAND memory. */
kono
parents:
diff changeset
229 static void
kono
parents:
diff changeset
230 free_cand (void *cand)
kono
parents:
diff changeset
231 {
kono
parents:
diff changeset
232 free (cand);
kono
parents:
diff changeset
233 }
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 /* Initiate the candidate table. */
kono
parents:
diff changeset
236 static void
kono
parents:
diff changeset
237 initiate_cand_table (void)
kono
parents:
diff changeset
238 {
kono
parents:
diff changeset
239 cand_table = htab_create (8000, cand_hash, cand_eq_p,
kono
parents:
diff changeset
240 (htab_del) free_cand);
kono
parents:
diff changeset
241 }
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* Finish the candidate table. */
kono
parents:
diff changeset
244 static void
kono
parents:
diff changeset
245 finish_cand_table (void)
kono
parents:
diff changeset
246 {
kono
parents:
diff changeset
247 htab_delete (cand_table);
kono
parents:
diff changeset
248 }
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250
kono
parents:
diff changeset
251
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
252 /* Return true if X contains memory or some UNSPEC. We cannot just
111
kono
parents:
diff changeset
253 check insn operands as memory or unspec might be not an operand
kono
parents:
diff changeset
254 itself but contain an operand. Insn with memory access is not
kono
parents:
diff changeset
255 profitable for rematerialization. Rematerialization of UNSPEC
kono
parents:
diff changeset
256 might result in wrong code generation as the UNPEC effect is
kono
parents:
diff changeset
257 unknown (e.g. generating a label). */
kono
parents:
diff changeset
258 static bool
kono
parents:
diff changeset
259 bad_for_rematerialization_p (rtx x)
kono
parents:
diff changeset
260 {
kono
parents:
diff changeset
261 int i, j;
kono
parents:
diff changeset
262 const char *fmt;
kono
parents:
diff changeset
263 enum rtx_code code;
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 if (MEM_P (x) || GET_CODE (x) == UNSPEC || GET_CODE (x) == UNSPEC_VOLATILE)
kono
parents:
diff changeset
266 return true;
kono
parents:
diff changeset
267 code = GET_CODE (x);
kono
parents:
diff changeset
268 fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
269 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
kono
parents:
diff changeset
270 {
kono
parents:
diff changeset
271 if (fmt[i] == 'e')
kono
parents:
diff changeset
272 {
kono
parents:
diff changeset
273 if (bad_for_rematerialization_p (XEXP (x, i)))
kono
parents:
diff changeset
274 return true;
kono
parents:
diff changeset
275 }
kono
parents:
diff changeset
276 else if (fmt[i] == 'E')
kono
parents:
diff changeset
277 {
kono
parents:
diff changeset
278 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
kono
parents:
diff changeset
279 if (bad_for_rematerialization_p (XVECEXP (x, i, j)))
kono
parents:
diff changeset
280 return true;
kono
parents:
diff changeset
281 }
kono
parents:
diff changeset
282 }
kono
parents:
diff changeset
283 return false;
kono
parents:
diff changeset
284 }
kono
parents:
diff changeset
285
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
286 /* If INSN cannot be used for rematerialization, return negative
111
kono
parents:
diff changeset
287 value. If INSN can be considered as a candidate for
kono
parents:
diff changeset
288 rematerialization, return value which is the operand number of the
kono
parents:
diff changeset
289 pseudo for which the insn can be used for rematerialization. Here
kono
parents:
diff changeset
290 we consider the insns without any memory, spilled pseudo (except
kono
parents:
diff changeset
291 for the rematerialization pseudo), or dying or unused regs. */
kono
parents:
diff changeset
292 static int
kono
parents:
diff changeset
293 operand_to_remat (rtx_insn *insn)
kono
parents:
diff changeset
294 {
kono
parents:
diff changeset
295 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
296 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
297 struct lra_insn_reg *reg, *found_reg = NULL;
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299 /* Don't rematerialize insns which can change PC. */
kono
parents:
diff changeset
300 if (JUMP_P (insn) || CALL_P (insn))
kono
parents:
diff changeset
301 return -1;
kono
parents:
diff changeset
302 /* First find a pseudo which can be rematerialized. */
kono
parents:
diff changeset
303 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
304 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
305 /* True FRAME_POINTER_NEEDED might be because we cannot follow
111
kono
parents:
diff changeset
306 changing sp offsets, e.g. alloca is used. If the insn contains
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
307 stack pointer in such case, we cannot rematerialize it as we
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
308 cannot know sp offset at a rematerialization place. */
111
kono
parents:
diff changeset
309 if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed)
kono
parents:
diff changeset
310 return -1;
kono
parents:
diff changeset
311 else if (reg->type == OP_OUT && ! reg->subreg_p
kono
parents:
diff changeset
312 && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
kono
parents:
diff changeset
313 {
kono
parents:
diff changeset
314 /* We permits only one spilled reg. */
kono
parents:
diff changeset
315 if (found_reg != NULL)
kono
parents:
diff changeset
316 return -1;
kono
parents:
diff changeset
317 found_reg = reg;
kono
parents:
diff changeset
318 }
kono
parents:
diff changeset
319 /* IRA calculates conflicts separately for subregs of two words
kono
parents:
diff changeset
320 pseudo. Even if the pseudo lives, e.g. one its subreg can be
kono
parents:
diff changeset
321 used lately, another subreg hard register can be already used
kono
parents:
diff changeset
322 for something else. In such case, it is not safe to
kono
parents:
diff changeset
323 rematerialize the insn. */
kono
parents:
diff changeset
324 if (reg->regno >= FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
325 && bitmap_bit_p (&subreg_regs, reg->regno))
kono
parents:
diff changeset
326 return -1;
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 /* Don't allow hard registers to be rematerialized. */
kono
parents:
diff changeset
329 if (reg->regno < FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
330 return -1;
kono
parents:
diff changeset
331 }
kono
parents:
diff changeset
332 if (found_reg == NULL)
kono
parents:
diff changeset
333 return -1;
kono
parents:
diff changeset
334 if (found_reg->regno < FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
335 return -1;
kono
parents:
diff changeset
336 if (bad_for_rematerialization_p (PATTERN (insn)))
kono
parents:
diff changeset
337 return -1;
kono
parents:
diff changeset
338 /* Check the other regs are not spilled. */
kono
parents:
diff changeset
339 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
340 if (found_reg == reg)
kono
parents:
diff changeset
341 continue;
kono
parents:
diff changeset
342 else if (reg->type == OP_INOUT)
kono
parents:
diff changeset
343 return -1;
kono
parents:
diff changeset
344 else if (reg->regno >= FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
345 && reg_renumber[reg->regno] < 0)
kono
parents:
diff changeset
346 /* Another spilled reg. */
kono
parents:
diff changeset
347 return -1;
kono
parents:
diff changeset
348 else if (reg->type == OP_IN)
kono
parents:
diff changeset
349 {
kono
parents:
diff changeset
350 if (find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
kono
parents:
diff changeset
351 /* We don't want to make live ranges longer. */
kono
parents:
diff changeset
352 return -1;
kono
parents:
diff changeset
353 /* Check that there is no output reg as the input one. */
kono
parents:
diff changeset
354 for (struct lra_insn_reg *reg2 = id->regs;
kono
parents:
diff changeset
355 reg2 != NULL;
kono
parents:
diff changeset
356 reg2 = reg2->next)
kono
parents:
diff changeset
357 if (reg2->type == OP_OUT && reg->regno == reg2->regno)
kono
parents:
diff changeset
358 return -1;
kono
parents:
diff changeset
359 if (reg->regno < FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
360 for (struct lra_insn_reg *reg2 = static_id->hard_regs;
kono
parents:
diff changeset
361 reg2 != NULL;
kono
parents:
diff changeset
362 reg2 = reg2->next)
kono
parents:
diff changeset
363 if (reg2->type == OP_OUT
kono
parents:
diff changeset
364 && reg->regno <= reg2->regno
kono
parents:
diff changeset
365 && (reg2->regno
kono
parents:
diff changeset
366 < (int) end_hard_regno (reg->biggest_mode, reg->regno)))
kono
parents:
diff changeset
367 return -1;
kono
parents:
diff changeset
368 }
kono
parents:
diff changeset
369 /* Check hard coded insn registers. */
kono
parents:
diff changeset
370 for (struct lra_insn_reg *reg = static_id->hard_regs;
kono
parents:
diff changeset
371 reg != NULL;
kono
parents:
diff changeset
372 reg = reg->next)
kono
parents:
diff changeset
373 if (reg->type == OP_INOUT)
kono
parents:
diff changeset
374 return -1;
kono
parents:
diff changeset
375 else if (reg->type == OP_IN)
kono
parents:
diff changeset
376 {
kono
parents:
diff changeset
377 /* Check that there is no output hard reg as the input
kono
parents:
diff changeset
378 one. */
kono
parents:
diff changeset
379 for (struct lra_insn_reg *reg2 = static_id->hard_regs;
kono
parents:
diff changeset
380 reg2 != NULL;
kono
parents:
diff changeset
381 reg2 = reg2->next)
kono
parents:
diff changeset
382 if (reg2->type == OP_OUT && reg->regno == reg2->regno)
kono
parents:
diff changeset
383 return -1;
kono
parents:
diff changeset
384 }
kono
parents:
diff changeset
385 /* Find the rematerialization operand. */
kono
parents:
diff changeset
386 int nop = static_id->n_operands;
kono
parents:
diff changeset
387 for (int i = 0; i < nop; i++)
kono
parents:
diff changeset
388 if (REG_P (*id->operand_loc[i])
kono
parents:
diff changeset
389 && (int) REGNO (*id->operand_loc[i]) == found_reg->regno)
kono
parents:
diff changeset
390 return i;
kono
parents:
diff changeset
391 return -1;
kono
parents:
diff changeset
392 }
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 /* Create candidate for INSN with rematerialization operand NOP and
kono
parents:
diff changeset
395 REGNO. Insert the candidate into the table and set up the
kono
parents:
diff changeset
396 corresponding INSN_TO_CAND element. */
kono
parents:
diff changeset
397 static void
kono
parents:
diff changeset
398 create_cand (rtx_insn *insn, int nop, int regno, rtx_insn *activation = NULL)
kono
parents:
diff changeset
399 {
kono
parents:
diff changeset
400 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
401 rtx reg = *id->operand_loc[nop];
kono
parents:
diff changeset
402 gcc_assert (REG_P (reg));
kono
parents:
diff changeset
403 int op_regno = REGNO (reg);
kono
parents:
diff changeset
404 gcc_assert (op_regno >= FIRST_PSEUDO_REGISTER);
kono
parents:
diff changeset
405 cand_t cand = XNEW (struct cand);
kono
parents:
diff changeset
406 cand->insn = insn;
kono
parents:
diff changeset
407 cand->nop = nop;
kono
parents:
diff changeset
408 cand->regno = regno;
kono
parents:
diff changeset
409 cand->reload_regno = op_regno == regno ? -1 : op_regno;
kono
parents:
diff changeset
410 gcc_assert (cand->regno >= 0);
kono
parents:
diff changeset
411 cand_t cand_in_table = insert_cand (cand);
kono
parents:
diff changeset
412 insn_to_cand[INSN_UID (insn)] = cand_in_table;
kono
parents:
diff changeset
413 if (cand != cand_in_table)
kono
parents:
diff changeset
414 free (cand);
kono
parents:
diff changeset
415 else
kono
parents:
diff changeset
416 {
kono
parents:
diff changeset
417 /* A new cand. */
kono
parents:
diff changeset
418 cand->index = all_cands.length ();
kono
parents:
diff changeset
419 all_cands.safe_push (cand);
kono
parents:
diff changeset
420 cand->next_regno_cand = regno_cands[cand->regno];
kono
parents:
diff changeset
421 regno_cands[cand->regno] = cand;
kono
parents:
diff changeset
422 }
kono
parents:
diff changeset
423 if (activation)
kono
parents:
diff changeset
424 insn_to_cand_activation[INSN_UID (activation)] = cand_in_table;
kono
parents:
diff changeset
425 }
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 /* Create rematerialization candidates (inserting them into the
kono
parents:
diff changeset
428 table). */
kono
parents:
diff changeset
429 static void
kono
parents:
diff changeset
430 create_cands (void)
kono
parents:
diff changeset
431 {
kono
parents:
diff changeset
432 rtx_insn *insn;
kono
parents:
diff changeset
433 struct potential_cand
kono
parents:
diff changeset
434 {
kono
parents:
diff changeset
435 rtx_insn *insn;
kono
parents:
diff changeset
436 int nop;
kono
parents:
diff changeset
437 };
kono
parents:
diff changeset
438 struct potential_cand *regno_potential_cand;
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 /* Create candidates. */
kono
parents:
diff changeset
441 regno_potential_cand = XCNEWVEC (struct potential_cand, max_reg_num ());
kono
parents:
diff changeset
442 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
kono
parents:
diff changeset
443 if (NONDEBUG_INSN_P (insn))
kono
parents:
diff changeset
444 {
kono
parents:
diff changeset
445 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
446 int keep_regno = -1;
kono
parents:
diff changeset
447 rtx set = single_set (insn);
kono
parents:
diff changeset
448 int nop;
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 /* See if this is an output reload for a previous insn. */
kono
parents:
diff changeset
451 if (set != NULL
kono
parents:
diff changeset
452 && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
kono
parents:
diff changeset
453 {
kono
parents:
diff changeset
454 rtx dstreg = SET_DEST (set);
kono
parents:
diff changeset
455 int src_regno = REGNO (SET_SRC (set));
kono
parents:
diff changeset
456 int dst_regno = REGNO (dstreg);
kono
parents:
diff changeset
457 rtx_insn *insn2 = regno_potential_cand[src_regno].insn;
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 if (insn2 != NULL
kono
parents:
diff changeset
460 && dst_regno >= FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
461 && reg_renumber[dst_regno] < 0
kono
parents:
diff changeset
462 && BLOCK_FOR_INSN (insn2) == BLOCK_FOR_INSN (insn))
kono
parents:
diff changeset
463 {
kono
parents:
diff changeset
464 create_cand (insn2, regno_potential_cand[src_regno].nop,
kono
parents:
diff changeset
465 dst_regno, insn);
kono
parents:
diff changeset
466 goto done;
kono
parents:
diff changeset
467 }
kono
parents:
diff changeset
468 }
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 nop = operand_to_remat (insn);
kono
parents:
diff changeset
471 if (nop >= 0)
kono
parents:
diff changeset
472 {
kono
parents:
diff changeset
473 gcc_assert (REG_P (*id->operand_loc[nop]));
kono
parents:
diff changeset
474 int regno = REGNO (*id->operand_loc[nop]);
kono
parents:
diff changeset
475 gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
kono
parents:
diff changeset
476 /* If we're setting an unrenumbered pseudo, make a candidate immediately.
kono
parents:
diff changeset
477 If it's an output reload register, save it for later; the code above
kono
parents:
diff changeset
478 looks for output reload insns later on. */
kono
parents:
diff changeset
479 if (reg_renumber[regno] < 0)
kono
parents:
diff changeset
480 create_cand (insn, nop, regno);
kono
parents:
diff changeset
481 else if (regno >= lra_constraint_new_regno_start)
kono
parents:
diff changeset
482 {
kono
parents:
diff changeset
483 regno_potential_cand[regno].insn = insn;
kono
parents:
diff changeset
484 regno_potential_cand[regno].nop = nop;
kono
parents:
diff changeset
485 keep_regno = regno;
kono
parents:
diff changeset
486 }
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 done:
kono
parents:
diff changeset
490 for (struct lra_insn_reg *reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
491 if (reg->type != OP_IN && reg->regno != keep_regno
kono
parents:
diff changeset
492 && reg->regno >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
493 regno_potential_cand[reg->regno].insn = NULL;
kono
parents:
diff changeset
494 }
kono
parents:
diff changeset
495 cands_num = all_cands.length ();
kono
parents:
diff changeset
496 free (regno_potential_cand);
kono
parents:
diff changeset
497 }
kono
parents:
diff changeset
498
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 /* Create and initialize BB data. */
kono
parents:
diff changeset
502 static void
kono
parents:
diff changeset
503 create_remat_bb_data (void)
kono
parents:
diff changeset
504 {
kono
parents:
diff changeset
505 basic_block bb;
kono
parents:
diff changeset
506 remat_bb_data_t bb_info;
kono
parents:
diff changeset
507
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
508 remat_bb_data = XNEWVEC (class remat_bb_data,
111
kono
parents:
diff changeset
509 last_basic_block_for_fn (cfun));
kono
parents:
diff changeset
510 FOR_ALL_BB_FN (bb, cfun)
kono
parents:
diff changeset
511 {
kono
parents:
diff changeset
512 gcc_checking_assert (bb->index >= 0
kono
parents:
diff changeset
513 && bb->index < last_basic_block_for_fn (cfun));
kono
parents:
diff changeset
514 bb_info = get_remat_bb_data (bb);
kono
parents:
diff changeset
515 bb_info->bb = bb;
kono
parents:
diff changeset
516 bitmap_initialize (&bb_info->changed_regs, &reg_obstack);
kono
parents:
diff changeset
517 bitmap_initialize (&bb_info->dead_regs, &reg_obstack);
kono
parents:
diff changeset
518 bitmap_initialize (&bb_info->gen_cands, &reg_obstack);
kono
parents:
diff changeset
519 bitmap_initialize (&bb_info->livein_cands, &reg_obstack);
kono
parents:
diff changeset
520 bitmap_initialize (&bb_info->pavin_cands, &reg_obstack);
kono
parents:
diff changeset
521 bitmap_initialize (&bb_info->pavout_cands, &reg_obstack);
kono
parents:
diff changeset
522 bitmap_initialize (&bb_info->avin_cands, &reg_obstack);
kono
parents:
diff changeset
523 bitmap_initialize (&bb_info->avout_cands, &reg_obstack);
kono
parents:
diff changeset
524 }
kono
parents:
diff changeset
525 }
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 /* Dump all candidates to DUMP_FILE. */
kono
parents:
diff changeset
528 static void
kono
parents:
diff changeset
529 dump_cands (FILE *dump_file)
kono
parents:
diff changeset
530 {
kono
parents:
diff changeset
531 int i;
kono
parents:
diff changeset
532 cand_t cand;
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 fprintf (dump_file, "\nCands:\n");
kono
parents:
diff changeset
535 for (i = 0; i < (int) cands_num; i++)
kono
parents:
diff changeset
536 {
kono
parents:
diff changeset
537 cand = all_cands[i];
kono
parents:
diff changeset
538 fprintf (dump_file, "%d (nop=%d, remat_regno=%d, reload_regno=%d):\n",
kono
parents:
diff changeset
539 i, cand->nop, cand->regno, cand->reload_regno);
kono
parents:
diff changeset
540 print_inline_rtx (dump_file, cand->insn, 6);
kono
parents:
diff changeset
541 fprintf (dump_file, "\n");
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543 }
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 /* Dump all candidates and BB data. */
kono
parents:
diff changeset
546 static void
kono
parents:
diff changeset
547 dump_candidates_and_remat_bb_data (void)
kono
parents:
diff changeset
548 {
kono
parents:
diff changeset
549 basic_block bb;
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 if (lra_dump_file == NULL)
kono
parents:
diff changeset
552 return;
kono
parents:
diff changeset
553 dump_cands (lra_dump_file);
kono
parents:
diff changeset
554 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
555 {
kono
parents:
diff changeset
556 fprintf (lra_dump_file, "\nBB %d:\n", bb->index);
kono
parents:
diff changeset
557 /* Livein */
kono
parents:
diff changeset
558 fprintf (lra_dump_file, " register live in:");
kono
parents:
diff changeset
559 dump_regset (df_get_live_in (bb), lra_dump_file);
kono
parents:
diff changeset
560 putc ('\n', lra_dump_file);
kono
parents:
diff changeset
561 /* Liveout */
kono
parents:
diff changeset
562 fprintf (lra_dump_file, " register live out:");
kono
parents:
diff changeset
563 dump_regset (df_get_live_out (bb), lra_dump_file);
kono
parents:
diff changeset
564 putc ('\n', lra_dump_file);
kono
parents:
diff changeset
565 /* Changed/dead regs: */
kono
parents:
diff changeset
566 fprintf (lra_dump_file, " changed regs:");
kono
parents:
diff changeset
567 dump_regset (&get_remat_bb_data (bb)->changed_regs, lra_dump_file);
kono
parents:
diff changeset
568 putc ('\n', lra_dump_file);
kono
parents:
diff changeset
569 fprintf (lra_dump_file, " dead regs:");
kono
parents:
diff changeset
570 dump_regset (&get_remat_bb_data (bb)->dead_regs, lra_dump_file);
kono
parents:
diff changeset
571 putc ('\n', lra_dump_file);
kono
parents:
diff changeset
572 lra_dump_bitmap_with_title ("cands generated in BB",
kono
parents:
diff changeset
573 &get_remat_bb_data (bb)->gen_cands, bb->index);
kono
parents:
diff changeset
574 lra_dump_bitmap_with_title ("livein cands in BB",
kono
parents:
diff changeset
575 &get_remat_bb_data (bb)->livein_cands, bb->index);
kono
parents:
diff changeset
576 lra_dump_bitmap_with_title ("pavin cands in BB",
kono
parents:
diff changeset
577 &get_remat_bb_data (bb)->pavin_cands, bb->index);
kono
parents:
diff changeset
578 lra_dump_bitmap_with_title ("pavout cands in BB",
kono
parents:
diff changeset
579 &get_remat_bb_data (bb)->pavout_cands, bb->index);
kono
parents:
diff changeset
580 lra_dump_bitmap_with_title ("avin cands in BB",
kono
parents:
diff changeset
581 &get_remat_bb_data (bb)->avin_cands, bb->index);
kono
parents:
diff changeset
582 lra_dump_bitmap_with_title ("avout cands in BB",
kono
parents:
diff changeset
583 &get_remat_bb_data (bb)->avout_cands, bb->index);
kono
parents:
diff changeset
584 }
kono
parents:
diff changeset
585 fprintf (lra_dump_file, "subreg regs:");
kono
parents:
diff changeset
586 dump_regset (&subreg_regs, lra_dump_file);
kono
parents:
diff changeset
587 putc ('\n', lra_dump_file);
kono
parents:
diff changeset
588 }
kono
parents:
diff changeset
589
kono
parents:
diff changeset
590 /* Free all BB data. */
kono
parents:
diff changeset
591 static void
kono
parents:
diff changeset
592 finish_remat_bb_data (void)
kono
parents:
diff changeset
593 {
kono
parents:
diff changeset
594 basic_block bb;
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
597 {
kono
parents:
diff changeset
598 bitmap_clear (&get_remat_bb_data (bb)->avout_cands);
kono
parents:
diff changeset
599 bitmap_clear (&get_remat_bb_data (bb)->avin_cands);
kono
parents:
diff changeset
600 bitmap_clear (&get_remat_bb_data (bb)->pavout_cands);
kono
parents:
diff changeset
601 bitmap_clear (&get_remat_bb_data (bb)->pavin_cands);
kono
parents:
diff changeset
602 bitmap_clear (&get_remat_bb_data (bb)->livein_cands);
kono
parents:
diff changeset
603 bitmap_clear (&get_remat_bb_data (bb)->gen_cands);
kono
parents:
diff changeset
604 bitmap_clear (&get_remat_bb_data (bb)->dead_regs);
kono
parents:
diff changeset
605 bitmap_clear (&get_remat_bb_data (bb)->changed_regs);
kono
parents:
diff changeset
606 }
kono
parents:
diff changeset
607 free (remat_bb_data);
kono
parents:
diff changeset
608 }
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 /* Update changed_regs, dead_regs, subreg_regs of BB from INSN. */
kono
parents:
diff changeset
613 static void
kono
parents:
diff changeset
614 set_bb_regs (basic_block bb, rtx_insn *insn)
kono
parents:
diff changeset
615 {
kono
parents:
diff changeset
616 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
617 remat_bb_data_t bb_info = get_remat_bb_data (bb);
kono
parents:
diff changeset
618 struct lra_insn_reg *reg;
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
621 {
kono
parents:
diff changeset
622 unsigned regno = reg->regno;
kono
parents:
diff changeset
623 if (reg->type != OP_IN)
kono
parents:
diff changeset
624 bitmap_set_bit (&bb_info->changed_regs, regno);
kono
parents:
diff changeset
625 else if (find_regno_note (insn, REG_DEAD, regno) != NULL)
kono
parents:
diff changeset
626 bitmap_set_bit (&bb_info->dead_regs, regno);
kono
parents:
diff changeset
627 if (regno >= FIRST_PSEUDO_REGISTER && reg->subreg_p)
kono
parents:
diff changeset
628 bitmap_set_bit (&subreg_regs, regno);
kono
parents:
diff changeset
629 }
kono
parents:
diff changeset
630 if (CALL_P (insn))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
631 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
632 /* Partially-clobbered registers might still be live. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
633 HARD_REG_SET clobbers = insn_callee_abi (insn).full_reg_clobbers ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
634 bitmap_ior_into (&get_remat_bb_data (bb)->dead_regs,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
635 bitmap_view<HARD_REG_SET> (clobbers));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
636 }
111
kono
parents:
diff changeset
637 }
kono
parents:
diff changeset
638
kono
parents:
diff changeset
639 /* Calculate changed_regs and dead_regs for each BB. */
kono
parents:
diff changeset
640 static void
kono
parents:
diff changeset
641 calculate_local_reg_remat_bb_data (void)
kono
parents:
diff changeset
642 {
kono
parents:
diff changeset
643 basic_block bb;
kono
parents:
diff changeset
644 rtx_insn *insn;
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
647 FOR_BB_INSNS (bb, insn)
kono
parents:
diff changeset
648 if (NONDEBUG_INSN_P (insn))
kono
parents:
diff changeset
649 set_bb_regs (bb, insn);
kono
parents:
diff changeset
650 }
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653
kono
parents:
diff changeset
654 /* Return true if REG overlaps an input operand of INSN. */
kono
parents:
diff changeset
655 static bool
kono
parents:
diff changeset
656 reg_overlap_for_remat_p (lra_insn_reg *reg, rtx_insn *insn)
kono
parents:
diff changeset
657 {
kono
parents:
diff changeset
658 int iter;
kono
parents:
diff changeset
659 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
660 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
661 unsigned regno = reg->regno;
kono
parents:
diff changeset
662 int nregs;
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
kono
parents:
diff changeset
665 regno = reg_renumber[regno];
kono
parents:
diff changeset
666 if (regno >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
667 nregs = 1;
kono
parents:
diff changeset
668 else
kono
parents:
diff changeset
669 nregs = hard_regno_nregs (regno, reg->biggest_mode);
kono
parents:
diff changeset
670
kono
parents:
diff changeset
671 struct lra_insn_reg *reg2;
kono
parents:
diff changeset
672
kono
parents:
diff changeset
673 for (iter = 0; iter < 2; iter++)
kono
parents:
diff changeset
674 for (reg2 = (iter == 0 ? id->regs : static_id->hard_regs);
kono
parents:
diff changeset
675 reg2 != NULL;
kono
parents:
diff changeset
676 reg2 = reg2->next)
kono
parents:
diff changeset
677 {
kono
parents:
diff changeset
678 if (reg2->type != OP_IN)
kono
parents:
diff changeset
679 continue;
kono
parents:
diff changeset
680 unsigned regno2 = reg2->regno;
kono
parents:
diff changeset
681 int nregs2;
kono
parents:
diff changeset
682
kono
parents:
diff changeset
683 if (regno2 >= FIRST_PSEUDO_REGISTER && reg_renumber[regno2] >= 0)
kono
parents:
diff changeset
684 regno2 = reg_renumber[regno2];
kono
parents:
diff changeset
685 if (regno2 >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
686 nregs2 = 1;
kono
parents:
diff changeset
687 else
kono
parents:
diff changeset
688 nregs2 = hard_regno_nregs (regno2, reg->biggest_mode);
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 if ((regno2 + nregs2 - 1 >= regno && regno2 < regno + nregs)
kono
parents:
diff changeset
691 || (regno + nregs - 1 >= regno2 && regno < regno2 + nregs2))
kono
parents:
diff changeset
692 return true;
kono
parents:
diff changeset
693 }
kono
parents:
diff changeset
694 return false;
kono
parents:
diff changeset
695 }
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 /* Return true if a call used register is an input operand of INSN. */
kono
parents:
diff changeset
698 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
699 call_used_input_regno_present_p (const function_abi &abi, rtx_insn *insn)
111
kono
parents:
diff changeset
700 {
kono
parents:
diff changeset
701 int iter;
kono
parents:
diff changeset
702 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
703 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
704 struct lra_insn_reg *reg;
kono
parents:
diff changeset
705
kono
parents:
diff changeset
706 for (iter = 0; iter < 2; iter++)
kono
parents:
diff changeset
707 for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
kono
parents:
diff changeset
708 reg != NULL;
kono
parents:
diff changeset
709 reg = reg->next)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
710 if (reg->type == OP_IN
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
711 && reg->regno < FIRST_PSEUDO_REGISTER
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
712 && abi.clobbers_reg_p (reg->biggest_mode, reg->regno))
111
kono
parents:
diff changeset
713 return true;
kono
parents:
diff changeset
714 return false;
kono
parents:
diff changeset
715 }
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 /* Calculate livein_cands for each BB. */
kono
parents:
diff changeset
718 static void
kono
parents:
diff changeset
719 calculate_livein_cands (void)
kono
parents:
diff changeset
720 {
kono
parents:
diff changeset
721 basic_block bb;
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
724 {
kono
parents:
diff changeset
725 bitmap livein_regs = df_get_live_in (bb);
kono
parents:
diff changeset
726 bitmap livein_cands = &get_remat_bb_data (bb)->livein_cands;
kono
parents:
diff changeset
727 for (unsigned int i = 0; i < cands_num; i++)
kono
parents:
diff changeset
728 {
kono
parents:
diff changeset
729 cand_t cand = all_cands[i];
kono
parents:
diff changeset
730 lra_insn_recog_data_t id = lra_get_insn_recog_data (cand->insn);
kono
parents:
diff changeset
731 struct lra_insn_reg *reg;
kono
parents:
diff changeset
732
kono
parents:
diff changeset
733 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
734 if (reg->type == OP_IN && ! bitmap_bit_p (livein_regs, reg->regno))
kono
parents:
diff changeset
735 break;
kono
parents:
diff changeset
736 if (reg == NULL)
kono
parents:
diff changeset
737 bitmap_set_bit (livein_cands, i);
kono
parents:
diff changeset
738 }
kono
parents:
diff changeset
739 }
kono
parents:
diff changeset
740 }
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 /* Calculate gen_cands for each BB. */
kono
parents:
diff changeset
743 static void
kono
parents:
diff changeset
744 calculate_gen_cands (void)
kono
parents:
diff changeset
745 {
kono
parents:
diff changeset
746 basic_block bb;
kono
parents:
diff changeset
747 bitmap gen_cands;
kono
parents:
diff changeset
748 rtx_insn *insn;
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
751 {
kono
parents:
diff changeset
752 gen_cands = &get_remat_bb_data (bb)->gen_cands;
kono
parents:
diff changeset
753 auto_bitmap gen_insns (&reg_obstack);
kono
parents:
diff changeset
754 FOR_BB_INSNS (bb, insn)
kono
parents:
diff changeset
755 if (INSN_P (insn))
kono
parents:
diff changeset
756 {
kono
parents:
diff changeset
757 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
758 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
759 struct lra_insn_reg *reg;
kono
parents:
diff changeset
760 unsigned int uid;
kono
parents:
diff changeset
761 bitmap_iterator bi;
kono
parents:
diff changeset
762 cand_t cand;
kono
parents:
diff changeset
763 rtx set;
kono
parents:
diff changeset
764 int iter;
kono
parents:
diff changeset
765 int src_regno = -1, dst_regno = -1;
kono
parents:
diff changeset
766
kono
parents:
diff changeset
767 if ((set = single_set (insn)) != NULL
kono
parents:
diff changeset
768 && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
kono
parents:
diff changeset
769 {
kono
parents:
diff changeset
770 src_regno = REGNO (SET_SRC (set));
kono
parents:
diff changeset
771 dst_regno = REGNO (SET_DEST (set));
kono
parents:
diff changeset
772 }
kono
parents:
diff changeset
773
kono
parents:
diff changeset
774 /* Update gen_cands: */
kono
parents:
diff changeset
775 bitmap_clear (&temp_bitmap);
kono
parents:
diff changeset
776 for (iter = 0; iter < 2; iter++)
kono
parents:
diff changeset
777 for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
kono
parents:
diff changeset
778 reg != NULL;
kono
parents:
diff changeset
779 reg = reg->next)
kono
parents:
diff changeset
780 if (reg->type != OP_IN
kono
parents:
diff changeset
781 || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
kono
parents:
diff changeset
782 EXECUTE_IF_SET_IN_BITMAP (gen_insns, 0, uid, bi)
kono
parents:
diff changeset
783 {
kono
parents:
diff changeset
784 rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 cand = insn_to_cand[INSN_UID (insn2)];
kono
parents:
diff changeset
787 gcc_assert (cand != NULL);
kono
parents:
diff changeset
788 /* Ignore the reload insn. */
kono
parents:
diff changeset
789 if (src_regno == cand->reload_regno
kono
parents:
diff changeset
790 && dst_regno == cand->regno)
kono
parents:
diff changeset
791 continue;
kono
parents:
diff changeset
792 if (cand->regno == reg->regno
kono
parents:
diff changeset
793 || reg_overlap_for_remat_p (reg, insn2))
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 bitmap_clear_bit (gen_cands, cand->index);
kono
parents:
diff changeset
796 bitmap_set_bit (&temp_bitmap, uid);
kono
parents:
diff changeset
797 }
kono
parents:
diff changeset
798 }
kono
parents:
diff changeset
799
kono
parents:
diff changeset
800 if (CALL_P (insn))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
801 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
802 function_abi callee_abi = insn_callee_abi (insn);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
803 EXECUTE_IF_SET_IN_BITMAP (gen_insns, 0, uid, bi)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
804 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
805 rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
111
kono
parents:
diff changeset
806
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
807 cand = insn_to_cand[INSN_UID (insn2)];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
808 gcc_assert (cand != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
809 if (call_used_input_regno_present_p (callee_abi, insn2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
810 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
811 bitmap_clear_bit (gen_cands, cand->index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
812 bitmap_set_bit (&temp_bitmap, uid);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
813 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
814 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
815 }
111
kono
parents:
diff changeset
816 bitmap_and_compl_into (gen_insns, &temp_bitmap);
kono
parents:
diff changeset
817
kono
parents:
diff changeset
818 cand = insn_to_cand[INSN_UID (insn)];
kono
parents:
diff changeset
819 if (cand != NULL)
kono
parents:
diff changeset
820 {
kono
parents:
diff changeset
821 bitmap_set_bit (gen_cands, cand->index);
kono
parents:
diff changeset
822 bitmap_set_bit (gen_insns, INSN_UID (insn));
kono
parents:
diff changeset
823 }
kono
parents:
diff changeset
824 }
kono
parents:
diff changeset
825 }
kono
parents:
diff changeset
826 }
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 /* The common transfer function used by the DF equation solver to
kono
parents:
diff changeset
831 propagate (partial) availability info BB_IN to BB_OUT through block
kono
parents:
diff changeset
832 with BB_INDEX according to the following equation:
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 bb.out = ((bb.in & bb.livein) - bb.killed) OR bb.gen
kono
parents:
diff changeset
835 */
kono
parents:
diff changeset
836 static bool
kono
parents:
diff changeset
837 cand_trans_fun (int bb_index, bitmap bb_in, bitmap bb_out)
kono
parents:
diff changeset
838 {
kono
parents:
diff changeset
839 remat_bb_data_t bb_info;
kono
parents:
diff changeset
840 bitmap bb_livein, bb_changed_regs, bb_dead_regs;
kono
parents:
diff changeset
841 unsigned int cid;
kono
parents:
diff changeset
842 bitmap_iterator bi;
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 bb_info = get_remat_bb_data_by_index (bb_index);
kono
parents:
diff changeset
845 bb_livein = &bb_info->livein_cands;
kono
parents:
diff changeset
846 bb_changed_regs = &bb_info->changed_regs;
kono
parents:
diff changeset
847 bb_dead_regs = &bb_info->dead_regs;
kono
parents:
diff changeset
848 /* Calculate killed avin cands -- cands whose regs are changed or
kono
parents:
diff changeset
849 becoming dead in the BB. We calculate it here as we hope that
kono
parents:
diff changeset
850 repeated calculations are compensated by smaller size of BB_IN in
kono
parents:
diff changeset
851 comparison with all candidates number. */
kono
parents:
diff changeset
852 bitmap_clear (&temp_bitmap);
kono
parents:
diff changeset
853 EXECUTE_IF_SET_IN_BITMAP (bb_in, 0, cid, bi)
kono
parents:
diff changeset
854 {
kono
parents:
diff changeset
855 cand_t cand = all_cands[cid];
kono
parents:
diff changeset
856 lra_insn_recog_data_t id = lra_get_insn_recog_data (cand->insn);
kono
parents:
diff changeset
857 struct lra_insn_reg *reg;
kono
parents:
diff changeset
858
kono
parents:
diff changeset
859 if (! bitmap_bit_p (bb_livein, cid))
kono
parents:
diff changeset
860 {
kono
parents:
diff changeset
861 bitmap_set_bit (&temp_bitmap, cid);
kono
parents:
diff changeset
862 continue;
kono
parents:
diff changeset
863 }
kono
parents:
diff changeset
864 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
865 /* Ignore all outputs which are not the regno for
kono
parents:
diff changeset
866 rematerialization. */
kono
parents:
diff changeset
867 if (reg->type == OP_OUT && reg->regno != cand->regno)
kono
parents:
diff changeset
868 continue;
kono
parents:
diff changeset
869 else if (bitmap_bit_p (bb_changed_regs, reg->regno)
kono
parents:
diff changeset
870 || bitmap_bit_p (bb_dead_regs, reg->regno))
kono
parents:
diff changeset
871 {
kono
parents:
diff changeset
872 bitmap_set_bit (&temp_bitmap, cid);
kono
parents:
diff changeset
873 break;
kono
parents:
diff changeset
874 }
kono
parents:
diff changeset
875 /* Check regno for rematerialization. */
kono
parents:
diff changeset
876 if (bitmap_bit_p (bb_changed_regs, cand->regno)
kono
parents:
diff changeset
877 || bitmap_bit_p (bb_dead_regs, cand->regno))
kono
parents:
diff changeset
878 bitmap_set_bit (&temp_bitmap, cid);
kono
parents:
diff changeset
879 }
kono
parents:
diff changeset
880 return bitmap_ior_and_compl (bb_out,
kono
parents:
diff changeset
881 &bb_info->gen_cands, bb_in, &temp_bitmap);
kono
parents:
diff changeset
882 }
kono
parents:
diff changeset
883
kono
parents:
diff changeset
884
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 /* The transfer function used by the DF equation solver to propagate
kono
parents:
diff changeset
887 partial candidate availability info through block with BB_INDEX
kono
parents:
diff changeset
888 according to the following equation:
kono
parents:
diff changeset
889
kono
parents:
diff changeset
890 bb.pavout = ((bb.pavin & bb.livein) - bb.killed) OR bb.gen
kono
parents:
diff changeset
891 */
kono
parents:
diff changeset
892 static bool
kono
parents:
diff changeset
893 cand_pav_trans_fun (int bb_index)
kono
parents:
diff changeset
894 {
kono
parents:
diff changeset
895 remat_bb_data_t bb_info;
kono
parents:
diff changeset
896
kono
parents:
diff changeset
897 bb_info = get_remat_bb_data_by_index (bb_index);
kono
parents:
diff changeset
898 return cand_trans_fun (bb_index, &bb_info->pavin_cands,
kono
parents:
diff changeset
899 &bb_info->pavout_cands);
kono
parents:
diff changeset
900 }
kono
parents:
diff changeset
901
kono
parents:
diff changeset
902 /* The confluence function used by the DF equation solver to set up
kono
parents:
diff changeset
903 cand_pav info for a block BB without predecessor. */
kono
parents:
diff changeset
904 static void
kono
parents:
diff changeset
905 cand_pav_con_fun_0 (basic_block bb)
kono
parents:
diff changeset
906 {
kono
parents:
diff changeset
907 bitmap_clear (&get_remat_bb_data (bb)->pavin_cands);
kono
parents:
diff changeset
908 }
kono
parents:
diff changeset
909
kono
parents:
diff changeset
910 /* The confluence function used by the DF equation solver to propagate
kono
parents:
diff changeset
911 partial candidate availability info from predecessor to successor
kono
parents:
diff changeset
912 on edge E (pred->bb) according to the following equation:
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 bb.pavin_cands = 0 for entry block | OR (pavout_cands of predecessors)
kono
parents:
diff changeset
915 */
kono
parents:
diff changeset
916 static bool
kono
parents:
diff changeset
917 cand_pav_con_fun_n (edge e)
kono
parents:
diff changeset
918 {
kono
parents:
diff changeset
919 basic_block pred = e->src;
kono
parents:
diff changeset
920 basic_block bb = e->dest;
kono
parents:
diff changeset
921 remat_bb_data_t bb_info;
kono
parents:
diff changeset
922 bitmap bb_pavin, pred_pavout;
kono
parents:
diff changeset
923
kono
parents:
diff changeset
924 bb_info = get_remat_bb_data (bb);
kono
parents:
diff changeset
925 bb_pavin = &bb_info->pavin_cands;
kono
parents:
diff changeset
926 pred_pavout = &get_remat_bb_data (pred)->pavout_cands;
kono
parents:
diff changeset
927 return bitmap_ior_into (bb_pavin, pred_pavout);
kono
parents:
diff changeset
928 }
kono
parents:
diff changeset
929
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931
kono
parents:
diff changeset
932 /* The transfer function used by the DF equation solver to propagate
kono
parents:
diff changeset
933 candidate availability info through block with BB_INDEX according
kono
parents:
diff changeset
934 to the following equation:
kono
parents:
diff changeset
935
kono
parents:
diff changeset
936 bb.avout = ((bb.avin & bb.livein) - bb.killed) OR bb.gen
kono
parents:
diff changeset
937 */
kono
parents:
diff changeset
938 static bool
kono
parents:
diff changeset
939 cand_av_trans_fun (int bb_index)
kono
parents:
diff changeset
940 {
kono
parents:
diff changeset
941 remat_bb_data_t bb_info;
kono
parents:
diff changeset
942
kono
parents:
diff changeset
943 bb_info = get_remat_bb_data_by_index (bb_index);
kono
parents:
diff changeset
944 return cand_trans_fun (bb_index, &bb_info->avin_cands,
kono
parents:
diff changeset
945 &bb_info->avout_cands);
kono
parents:
diff changeset
946 }
kono
parents:
diff changeset
947
kono
parents:
diff changeset
948 /* The confluence function used by the DF equation solver to set up
kono
parents:
diff changeset
949 cand_av info for a block BB without predecessor. */
kono
parents:
diff changeset
950 static void
kono
parents:
diff changeset
951 cand_av_con_fun_0 (basic_block bb)
kono
parents:
diff changeset
952 {
kono
parents:
diff changeset
953 bitmap_clear (&get_remat_bb_data (bb)->avin_cands);
kono
parents:
diff changeset
954 }
kono
parents:
diff changeset
955
kono
parents:
diff changeset
956 /* The confluence function used by the DF equation solver to propagate
kono
parents:
diff changeset
957 cand_av info from predecessor to successor on edge E (pred->bb)
kono
parents:
diff changeset
958 according to the following equation:
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 bb.avin_cands = 0 for entry block | AND (avout_cands of predecessors)
kono
parents:
diff changeset
961 */
kono
parents:
diff changeset
962 static bool
kono
parents:
diff changeset
963 cand_av_con_fun_n (edge e)
kono
parents:
diff changeset
964 {
kono
parents:
diff changeset
965 basic_block pred = e->src;
kono
parents:
diff changeset
966 basic_block bb = e->dest;
kono
parents:
diff changeset
967 remat_bb_data_t bb_info;
kono
parents:
diff changeset
968 bitmap bb_avin, pred_avout;
kono
parents:
diff changeset
969
kono
parents:
diff changeset
970 bb_info = get_remat_bb_data (bb);
kono
parents:
diff changeset
971 bb_avin = &bb_info->avin_cands;
kono
parents:
diff changeset
972 pred_avout = &get_remat_bb_data (pred)->avout_cands;
kono
parents:
diff changeset
973 return bitmap_and_into (bb_avin, pred_avout);
kono
parents:
diff changeset
974 }
kono
parents:
diff changeset
975
kono
parents:
diff changeset
976 /* Calculate available candidates for each BB. */
kono
parents:
diff changeset
977 static void
kono
parents:
diff changeset
978 calculate_global_remat_bb_data (void)
kono
parents:
diff changeset
979 {
kono
parents:
diff changeset
980 basic_block bb;
kono
parents:
diff changeset
981
kono
parents:
diff changeset
982 df_simple_dataflow
kono
parents:
diff changeset
983 (DF_FORWARD, NULL, cand_pav_con_fun_0, cand_pav_con_fun_n,
kono
parents:
diff changeset
984 cand_pav_trans_fun, &all_blocks,
kono
parents:
diff changeset
985 df_get_postorder (DF_FORWARD), df_get_n_blocks (DF_FORWARD));
kono
parents:
diff changeset
986 /* Initialize avin by pavin. */
kono
parents:
diff changeset
987 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
988 bitmap_copy (&get_remat_bb_data (bb)->avin_cands,
kono
parents:
diff changeset
989 &get_remat_bb_data (bb)->pavin_cands);
kono
parents:
diff changeset
990 df_simple_dataflow
kono
parents:
diff changeset
991 (DF_FORWARD, NULL, cand_av_con_fun_0, cand_av_con_fun_n,
kono
parents:
diff changeset
992 cand_av_trans_fun, &all_blocks,
kono
parents:
diff changeset
993 df_get_postorder (DF_FORWARD), df_get_n_blocks (DF_FORWARD));
kono
parents:
diff changeset
994 }
kono
parents:
diff changeset
995
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 /* Setup sp offset attribute to SP_OFFSET for all INSNS. */
kono
parents:
diff changeset
999 static void
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1000 change_sp_offset (rtx_insn *insns, poly_int64 sp_offset)
111
kono
parents:
diff changeset
1001 {
kono
parents:
diff changeset
1002 for (rtx_insn *insn = insns; insn != NULL; insn = NEXT_INSN (insn))
kono
parents:
diff changeset
1003 eliminate_regs_in_insn (insn, false, false, sp_offset);
kono
parents:
diff changeset
1004 }
kono
parents:
diff changeset
1005
kono
parents:
diff changeset
1006 /* Return start hard register of REG (can be a hard or a pseudo reg)
kono
parents:
diff changeset
1007 or -1 (if it is a spilled pseudo). Return number of hard registers
kono
parents:
diff changeset
1008 occupied by REG through parameter NREGS if the start hard reg is
kono
parents:
diff changeset
1009 not negative. */
kono
parents:
diff changeset
1010 static int
kono
parents:
diff changeset
1011 get_hard_regs (struct lra_insn_reg *reg, int &nregs)
kono
parents:
diff changeset
1012 {
kono
parents:
diff changeset
1013 int regno = reg->regno;
kono
parents:
diff changeset
1014 int hard_regno = regno < FIRST_PSEUDO_REGISTER ? regno : reg_renumber[regno];
kono
parents:
diff changeset
1015
kono
parents:
diff changeset
1016 if (hard_regno >= 0)
kono
parents:
diff changeset
1017 nregs = hard_regno_nregs (hard_regno, reg->biggest_mode);
kono
parents:
diff changeset
1018 return hard_regno;
kono
parents:
diff changeset
1019 }
kono
parents:
diff changeset
1020
kono
parents:
diff changeset
1021 /* Make copy of and register scratch pseudos in rematerialized insn
kono
parents:
diff changeset
1022 REMAT_INSN. */
kono
parents:
diff changeset
1023 static void
kono
parents:
diff changeset
1024 update_scratch_ops (rtx_insn *remat_insn)
kono
parents:
diff changeset
1025 {
kono
parents:
diff changeset
1026 lra_insn_recog_data_t id = lra_get_insn_recog_data (remat_insn);
kono
parents:
diff changeset
1027 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
1028 for (int i = 0; i < static_id->n_operands; i++)
kono
parents:
diff changeset
1029 {
kono
parents:
diff changeset
1030 rtx *loc = id->operand_loc[i];
kono
parents:
diff changeset
1031 if (! REG_P (*loc))
kono
parents:
diff changeset
1032 continue;
kono
parents:
diff changeset
1033 int regno = REGNO (*loc);
kono
parents:
diff changeset
1034 if (! lra_former_scratch_p (regno))
kono
parents:
diff changeset
1035 continue;
kono
parents:
diff changeset
1036 *loc = lra_create_new_reg (GET_MODE (*loc), *loc,
kono
parents:
diff changeset
1037 lra_get_allocno_class (regno),
kono
parents:
diff changeset
1038 "scratch pseudo copy");
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1039 lra_register_new_scratch_op (remat_insn, i, id->icode);
111
kono
parents:
diff changeset
1040 }
kono
parents:
diff changeset
1041
kono
parents:
diff changeset
1042 }
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 /* Insert rematerialization insns using the data-flow data calculated
kono
parents:
diff changeset
1045 earlier. */
kono
parents:
diff changeset
1046 static bool
kono
parents:
diff changeset
1047 do_remat (void)
kono
parents:
diff changeset
1048 {
kono
parents:
diff changeset
1049 unsigned regno;
kono
parents:
diff changeset
1050 rtx_insn *insn;
kono
parents:
diff changeset
1051 basic_block bb;
kono
parents:
diff changeset
1052 bool changed_p = false;
kono
parents:
diff changeset
1053 /* Living hard regs and hard registers of living pseudos. */
kono
parents:
diff changeset
1054 HARD_REG_SET live_hard_regs;
kono
parents:
diff changeset
1055 bitmap_iterator bi;
kono
parents:
diff changeset
1056
kono
parents:
diff changeset
1057 auto_bitmap avail_cands (&reg_obstack);
kono
parents:
diff changeset
1058 auto_bitmap active_cands (&reg_obstack);
kono
parents:
diff changeset
1059 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
1060 {
kono
parents:
diff changeset
1061 CLEAR_HARD_REG_SET (live_hard_regs);
kono
parents:
diff changeset
1062 EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), 0, regno, bi)
kono
parents:
diff changeset
1063 {
kono
parents:
diff changeset
1064 int hard_regno = regno < FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
1065 ? regno
kono
parents:
diff changeset
1066 : reg_renumber[regno];
kono
parents:
diff changeset
1067 if (hard_regno >= 0)
kono
parents:
diff changeset
1068 SET_HARD_REG_BIT (live_hard_regs, hard_regno);
kono
parents:
diff changeset
1069 }
kono
parents:
diff changeset
1070 bitmap_and (avail_cands, &get_remat_bb_data (bb)->avin_cands,
kono
parents:
diff changeset
1071 &get_remat_bb_data (bb)->livein_cands);
kono
parents:
diff changeset
1072 /* Activating insns are always in the same block as their corresponding
kono
parents:
diff changeset
1073 remat insn, so at the start of a block the two bitsets are equal. */
kono
parents:
diff changeset
1074 bitmap_copy (active_cands, avail_cands);
kono
parents:
diff changeset
1075 FOR_BB_INSNS (bb, insn)
kono
parents:
diff changeset
1076 {
kono
parents:
diff changeset
1077 if (!NONDEBUG_INSN_P (insn))
kono
parents:
diff changeset
1078 continue;
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
1081 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
1082 struct lra_insn_reg *reg;
kono
parents:
diff changeset
1083 cand_t cand;
kono
parents:
diff changeset
1084 unsigned int cid;
kono
parents:
diff changeset
1085 bitmap_iterator bi;
kono
parents:
diff changeset
1086 rtx set;
kono
parents:
diff changeset
1087 int iter;
kono
parents:
diff changeset
1088 int src_regno = -1, dst_regno = -1;
kono
parents:
diff changeset
1089
kono
parents:
diff changeset
1090 if ((set = single_set (insn)) != NULL
kono
parents:
diff changeset
1091 && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
kono
parents:
diff changeset
1092 {
kono
parents:
diff changeset
1093 src_regno = REGNO (SET_SRC (set));
kono
parents:
diff changeset
1094 dst_regno = REGNO (SET_DEST (set));
kono
parents:
diff changeset
1095 }
kono
parents:
diff changeset
1096
kono
parents:
diff changeset
1097 cand = NULL;
kono
parents:
diff changeset
1098 /* Check possibility of rematerialization (hard reg or
kono
parents:
diff changeset
1099 unpsilled pseudo <- spilled pseudo): */
kono
parents:
diff changeset
1100 if (dst_regno >= 0 && src_regno >= FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
1101 && reg_renumber[src_regno] < 0
kono
parents:
diff changeset
1102 && (dst_regno < FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
1103 || reg_renumber[dst_regno] >= 0))
kono
parents:
diff changeset
1104 {
kono
parents:
diff changeset
1105 for (cand = regno_cands[src_regno];
kono
parents:
diff changeset
1106 cand != NULL;
kono
parents:
diff changeset
1107 cand = cand->next_regno_cand)
kono
parents:
diff changeset
1108 if (bitmap_bit_p (avail_cands, cand->index)
kono
parents:
diff changeset
1109 && bitmap_bit_p (active_cands, cand->index))
kono
parents:
diff changeset
1110 break;
kono
parents:
diff changeset
1111 }
kono
parents:
diff changeset
1112 int i, hard_regno, nregs;
kono
parents:
diff changeset
1113 int dst_hard_regno, dst_nregs;
kono
parents:
diff changeset
1114 rtx_insn *remat_insn = NULL;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1115 poly_int64 cand_sp_offset = 0;
111
kono
parents:
diff changeset
1116 if (cand != NULL)
kono
parents:
diff changeset
1117 {
kono
parents:
diff changeset
1118 lra_insn_recog_data_t cand_id
kono
parents:
diff changeset
1119 = lra_get_insn_recog_data (cand->insn);
kono
parents:
diff changeset
1120 struct lra_static_insn_data *static_cand_id
kono
parents:
diff changeset
1121 = cand_id->insn_static_data;
kono
parents:
diff changeset
1122 rtx saved_op = *cand_id->operand_loc[cand->nop];
kono
parents:
diff changeset
1123
kono
parents:
diff changeset
1124 /* Check clobbers do not kill something living. */
kono
parents:
diff changeset
1125 gcc_assert (REG_P (saved_op));
kono
parents:
diff changeset
1126 int ignore_regno = REGNO (saved_op);
kono
parents:
diff changeset
1127
kono
parents:
diff changeset
1128 dst_hard_regno = dst_regno < FIRST_PSEUDO_REGISTER
kono
parents:
diff changeset
1129 ? dst_regno : reg_renumber[dst_regno];
kono
parents:
diff changeset
1130 gcc_assert (dst_hard_regno >= 0);
kono
parents:
diff changeset
1131 machine_mode mode = GET_MODE (SET_DEST (set));
kono
parents:
diff changeset
1132 dst_nregs = hard_regno_nregs (dst_hard_regno, mode);
kono
parents:
diff changeset
1133
kono
parents:
diff changeset
1134 for (reg = cand_id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
1135 if (reg->type != OP_IN && reg->regno != ignore_regno)
kono
parents:
diff changeset
1136 {
kono
parents:
diff changeset
1137 hard_regno = get_hard_regs (reg, nregs);
kono
parents:
diff changeset
1138 gcc_assert (hard_regno >= 0);
kono
parents:
diff changeset
1139 for (i = 0; i < nregs; i++)
kono
parents:
diff changeset
1140 if (TEST_HARD_REG_BIT (live_hard_regs, hard_regno + i))
kono
parents:
diff changeset
1141 break;
kono
parents:
diff changeset
1142 if (i < nregs)
kono
parents:
diff changeset
1143 break;
kono
parents:
diff changeset
1144 /* Ensure the clobber also doesn't overlap dst_regno. */
kono
parents:
diff changeset
1145 if (hard_regno + nregs > dst_hard_regno
kono
parents:
diff changeset
1146 && hard_regno < dst_hard_regno + dst_nregs)
kono
parents:
diff changeset
1147 break;
kono
parents:
diff changeset
1148 }
kono
parents:
diff changeset
1149
kono
parents:
diff changeset
1150 if (reg == NULL)
kono
parents:
diff changeset
1151 {
kono
parents:
diff changeset
1152 for (reg = static_cand_id->hard_regs;
kono
parents:
diff changeset
1153 reg != NULL;
kono
parents:
diff changeset
1154 reg = reg->next)
kono
parents:
diff changeset
1155 if (reg->type != OP_IN)
kono
parents:
diff changeset
1156 {
kono
parents:
diff changeset
1157 if (TEST_HARD_REG_BIT (live_hard_regs, reg->regno))
kono
parents:
diff changeset
1158 break;
kono
parents:
diff changeset
1159 if (reg->regno >= dst_hard_regno
kono
parents:
diff changeset
1160 && reg->regno < dst_hard_regno + dst_nregs)
kono
parents:
diff changeset
1161 break;
kono
parents:
diff changeset
1162 }
kono
parents:
diff changeset
1163 }
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 if (reg == NULL)
kono
parents:
diff changeset
1166 {
kono
parents:
diff changeset
1167 *cand_id->operand_loc[cand->nop] = SET_DEST (set);
kono
parents:
diff changeset
1168 lra_update_insn_regno_info (cand->insn);
kono
parents:
diff changeset
1169 bool ok_p = lra_constrain_insn (cand->insn);
kono
parents:
diff changeset
1170 if (ok_p)
kono
parents:
diff changeset
1171 {
kono
parents:
diff changeset
1172 rtx remat_pat = copy_insn (PATTERN (cand->insn));
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 start_sequence ();
kono
parents:
diff changeset
1175 emit_insn (remat_pat);
kono
parents:
diff changeset
1176 remat_insn = get_insns ();
kono
parents:
diff changeset
1177 end_sequence ();
kono
parents:
diff changeset
1178 if (recog_memoized (remat_insn) < 0)
kono
parents:
diff changeset
1179 remat_insn = NULL;
kono
parents:
diff changeset
1180 cand_sp_offset = cand_id->sp_offset;
kono
parents:
diff changeset
1181 }
kono
parents:
diff changeset
1182 *cand_id->operand_loc[cand->nop] = saved_op;
kono
parents:
diff changeset
1183 lra_update_insn_regno_info (cand->insn);
kono
parents:
diff changeset
1184 }
kono
parents:
diff changeset
1185 }
kono
parents:
diff changeset
1186
kono
parents:
diff changeset
1187 bitmap_clear (&temp_bitmap);
kono
parents:
diff changeset
1188 /* Update avail_cands (see analogous code for
kono
parents:
diff changeset
1189 calculate_gen_cands). */
kono
parents:
diff changeset
1190 for (iter = 0; iter < 2; iter++)
kono
parents:
diff changeset
1191 for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
kono
parents:
diff changeset
1192 reg != NULL;
kono
parents:
diff changeset
1193 reg = reg->next)
kono
parents:
diff changeset
1194 if (reg->type != OP_IN
kono
parents:
diff changeset
1195 || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
kono
parents:
diff changeset
1196 EXECUTE_IF_SET_IN_BITMAP (avail_cands, 0, cid, bi)
kono
parents:
diff changeset
1197 {
kono
parents:
diff changeset
1198 cand = all_cands[cid];
kono
parents:
diff changeset
1199
kono
parents:
diff changeset
1200 /* Ignore the reload insn. */
kono
parents:
diff changeset
1201 if (src_regno == cand->reload_regno
kono
parents:
diff changeset
1202 && dst_regno == cand->regno)
kono
parents:
diff changeset
1203 continue;
kono
parents:
diff changeset
1204 if (cand->regno == reg->regno
kono
parents:
diff changeset
1205 || reg_overlap_for_remat_p (reg, cand->insn))
kono
parents:
diff changeset
1206 bitmap_set_bit (&temp_bitmap, cand->index);
kono
parents:
diff changeset
1207 }
kono
parents:
diff changeset
1208
kono
parents:
diff changeset
1209 if (CALL_P (insn))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1210 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1211 function_abi callee_abi = insn_callee_abi (insn);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1212 EXECUTE_IF_SET_IN_BITMAP (avail_cands, 0, cid, bi)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1213 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1214 cand = all_cands[cid];
111
kono
parents:
diff changeset
1215
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1216 if (call_used_input_regno_present_p (callee_abi, cand->insn))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1217 bitmap_set_bit (&temp_bitmap, cand->index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1218 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1219 }
111
kono
parents:
diff changeset
1220
kono
parents:
diff changeset
1221 bitmap_and_compl_into (avail_cands, &temp_bitmap);
kono
parents:
diff changeset
1222
kono
parents:
diff changeset
1223 /* Now see whether a candidate is made active or available
kono
parents:
diff changeset
1224 by this insn. */
kono
parents:
diff changeset
1225 cand = insn_to_cand_activation[INSN_UID (insn)];
kono
parents:
diff changeset
1226 if (cand)
kono
parents:
diff changeset
1227 bitmap_set_bit (active_cands, cand->index);
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 cand = insn_to_cand[INSN_UID (insn)];
kono
parents:
diff changeset
1230 if (cand != NULL)
kono
parents:
diff changeset
1231 {
kono
parents:
diff changeset
1232 bitmap_set_bit (avail_cands, cand->index);
kono
parents:
diff changeset
1233 if (cand->reload_regno == -1)
kono
parents:
diff changeset
1234 bitmap_set_bit (active_cands, cand->index);
kono
parents:
diff changeset
1235 else
kono
parents:
diff changeset
1236 bitmap_clear_bit (active_cands, cand->index);
kono
parents:
diff changeset
1237 }
kono
parents:
diff changeset
1238
kono
parents:
diff changeset
1239 if (remat_insn != NULL)
kono
parents:
diff changeset
1240 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1241 poly_int64 sp_offset_change = cand_sp_offset - id->sp_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1242 if (maybe_ne (sp_offset_change, 0))
111
kono
parents:
diff changeset
1243 change_sp_offset (remat_insn, sp_offset_change);
kono
parents:
diff changeset
1244 update_scratch_ops (remat_insn);
kono
parents:
diff changeset
1245 lra_process_new_insns (insn, remat_insn, NULL,
kono
parents:
diff changeset
1246 "Inserting rematerialization insn");
kono
parents:
diff changeset
1247 lra_set_insn_deleted (insn);
kono
parents:
diff changeset
1248 changed_p = true;
kono
parents:
diff changeset
1249 continue;
kono
parents:
diff changeset
1250 }
kono
parents:
diff changeset
1251
kono
parents:
diff changeset
1252 /* Update live hard regs: */
kono
parents:
diff changeset
1253 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
1254 if (reg->type == OP_IN
kono
parents:
diff changeset
1255 && find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
kono
parents:
diff changeset
1256 {
kono
parents:
diff changeset
1257 if ((hard_regno = get_hard_regs (reg, nregs)) < 0)
kono
parents:
diff changeset
1258 continue;
kono
parents:
diff changeset
1259 for (i = 0; i < nregs; i++)
kono
parents:
diff changeset
1260 CLEAR_HARD_REG_BIT (live_hard_regs, hard_regno + i);
kono
parents:
diff changeset
1261 }
kono
parents:
diff changeset
1262 /* Process also hard regs (e.g. CC register) which are part
kono
parents:
diff changeset
1263 of insn definition. */
kono
parents:
diff changeset
1264 for (reg = static_id->hard_regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
1265 if (reg->type == OP_IN
kono
parents:
diff changeset
1266 && find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
kono
parents:
diff changeset
1267 CLEAR_HARD_REG_BIT (live_hard_regs, reg->regno);
kono
parents:
diff changeset
1268 /* Inputs have been processed, now process outputs. */
kono
parents:
diff changeset
1269 for (reg = id->regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
1270 if (reg->type != OP_IN
kono
parents:
diff changeset
1271 && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
kono
parents:
diff changeset
1272 {
kono
parents:
diff changeset
1273 if ((hard_regno = get_hard_regs (reg, nregs)) < 0)
kono
parents:
diff changeset
1274 continue;
kono
parents:
diff changeset
1275 for (i = 0; i < nregs; i++)
kono
parents:
diff changeset
1276 SET_HARD_REG_BIT (live_hard_regs, hard_regno + i);
kono
parents:
diff changeset
1277 }
kono
parents:
diff changeset
1278 for (reg = static_id->hard_regs; reg != NULL; reg = reg->next)
kono
parents:
diff changeset
1279 if (reg->type != OP_IN
kono
parents:
diff changeset
1280 && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
kono
parents:
diff changeset
1281 SET_HARD_REG_BIT (live_hard_regs, reg->regno);
kono
parents:
diff changeset
1282 }
kono
parents:
diff changeset
1283 }
kono
parents:
diff changeset
1284 return changed_p;
kono
parents:
diff changeset
1285 }
kono
parents:
diff changeset
1286
kono
parents:
diff changeset
1287
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 /* Current number of rematerialization iteration. */
kono
parents:
diff changeset
1290 int lra_rematerialization_iter;
kono
parents:
diff changeset
1291
kono
parents:
diff changeset
1292 /* Entry point of the rematerialization sub-pass. Return true if we
kono
parents:
diff changeset
1293 did any rematerialization. */
kono
parents:
diff changeset
1294 bool
kono
parents:
diff changeset
1295 lra_remat (void)
kono
parents:
diff changeset
1296 {
kono
parents:
diff changeset
1297 basic_block bb;
kono
parents:
diff changeset
1298 bool result;
kono
parents:
diff changeset
1299 int max_regno = max_reg_num ();
kono
parents:
diff changeset
1300
kono
parents:
diff changeset
1301 if (! flag_lra_remat)
kono
parents:
diff changeset
1302 return false;
kono
parents:
diff changeset
1303 lra_rematerialization_iter++;
kono
parents:
diff changeset
1304 if (lra_rematerialization_iter > LRA_MAX_REMATERIALIZATION_PASSES)
kono
parents:
diff changeset
1305 return false;
kono
parents:
diff changeset
1306 if (lra_dump_file != NULL)
kono
parents:
diff changeset
1307 fprintf (lra_dump_file,
kono
parents:
diff changeset
1308 "\n******** Rematerialization #%d: ********\n\n",
kono
parents:
diff changeset
1309 lra_rematerialization_iter);
kono
parents:
diff changeset
1310 timevar_push (TV_LRA_REMAT);
kono
parents:
diff changeset
1311 insn_to_cand = XCNEWVEC (cand_t, get_max_uid ());
kono
parents:
diff changeset
1312 insn_to_cand_activation = XCNEWVEC (cand_t, get_max_uid ());
kono
parents:
diff changeset
1313 regno_cands = XCNEWVEC (cand_t, max_regno);
kono
parents:
diff changeset
1314 all_cands.create (8000);
kono
parents:
diff changeset
1315 initiate_cand_table ();
kono
parents:
diff changeset
1316 create_remat_bb_data ();
kono
parents:
diff changeset
1317 bitmap_initialize (&temp_bitmap, &reg_obstack);
kono
parents:
diff changeset
1318 bitmap_initialize (&subreg_regs, &reg_obstack);
kono
parents:
diff changeset
1319 calculate_local_reg_remat_bb_data ();
kono
parents:
diff changeset
1320 create_cands ();
kono
parents:
diff changeset
1321 calculate_livein_cands ();
kono
parents:
diff changeset
1322 calculate_gen_cands ();
kono
parents:
diff changeset
1323 bitmap_initialize (&all_blocks, &reg_obstack);
kono
parents:
diff changeset
1324 FOR_ALL_BB_FN (bb, cfun)
kono
parents:
diff changeset
1325 bitmap_set_bit (&all_blocks, bb->index);
kono
parents:
diff changeset
1326 calculate_global_remat_bb_data ();
kono
parents:
diff changeset
1327 dump_candidates_and_remat_bb_data ();
kono
parents:
diff changeset
1328 result = do_remat ();
kono
parents:
diff changeset
1329 all_cands.release ();
kono
parents:
diff changeset
1330 bitmap_clear (&temp_bitmap);
kono
parents:
diff changeset
1331 bitmap_clear (&subreg_regs);
kono
parents:
diff changeset
1332 finish_remat_bb_data ();
kono
parents:
diff changeset
1333 finish_cand_table ();
kono
parents:
diff changeset
1334 bitmap_clear (&all_blocks);
kono
parents:
diff changeset
1335 free (regno_cands);
kono
parents:
diff changeset
1336 free (insn_to_cand);
kono
parents:
diff changeset
1337 free (insn_to_cand_activation);
kono
parents:
diff changeset
1338 timevar_pop (TV_LRA_REMAT);
kono
parents:
diff changeset
1339 return result;
kono
parents:
diff changeset
1340 }