annotate gcc/lra-remat.c @ 16:04ced10e8804

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