111
|
1 /* Code for RTL register eliminations.
|
131
|
2 Copyright (C) 2010-2018 Free Software Foundation, Inc.
|
111
|
3 Contributed by Vladimir Makarov <vmakarov@redhat.com>.
|
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
7 GCC is free software; you can redistribute it and/or modify it under
|
|
8 the terms of the GNU General Public License as published by the Free
|
|
9 Software Foundation; either version 3, or (at your option) any later
|
|
10 version.
|
|
11
|
|
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
15 for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with GCC; see the file COPYING3. If not see
|
|
19 <http://www.gnu.org/licenses/>. */
|
|
20
|
|
21 /* Eliminable registers (like a soft argument or frame pointer) are
|
|
22 widely used in RTL. These eliminable registers should be replaced
|
|
23 by real hard registers (like the stack pointer or hard frame
|
|
24 pointer) plus some offset. The offsets usually change whenever the
|
|
25 stack is expanded. We know the final offsets only at the very end
|
|
26 of LRA.
|
|
27
|
|
28 Within LRA, we usually keep the RTL in such a state that the
|
|
29 eliminable registers can be replaced by just the corresponding hard
|
|
30 register (without any offset). To achieve this we should add the
|
|
31 initial elimination offset at the beginning of LRA and update the
|
|
32 offsets whenever the stack is expanded. We need to do this before
|
|
33 every constraint pass because the choice of offset often affects
|
|
34 whether a particular address or memory constraint is satisfied.
|
|
35
|
|
36 We keep RTL code at most time in such state that the virtual
|
|
37 registers can be changed by just the corresponding hard registers
|
|
38 (with zero offsets) and we have the right RTL code. To achieve this
|
|
39 we should add initial offset at the beginning of LRA work and update
|
|
40 offsets after each stack expanding. But actually we update virtual
|
|
41 registers to the same virtual registers + corresponding offsets
|
|
42 before every constraint pass because it affects constraint
|
|
43 satisfaction (e.g. an address displacement became too big for some
|
|
44 target).
|
|
45
|
|
46 The final change of eliminable registers to the corresponding hard
|
|
47 registers are done at the very end of LRA when there were no change
|
|
48 in offsets anymore:
|
|
49
|
|
50 fp + 42 => sp + 42
|
|
51
|
|
52 */
|
|
53
|
|
54 #include "config.h"
|
|
55 #include "system.h"
|
|
56 #include "coretypes.h"
|
|
57 #include "backend.h"
|
|
58 #include "target.h"
|
|
59 #include "rtl.h"
|
|
60 #include "tree.h"
|
|
61 #include "df.h"
|
|
62 #include "memmodel.h"
|
|
63 #include "tm_p.h"
|
|
64 #include "optabs.h"
|
|
65 #include "regs.h"
|
|
66 #include "ira.h"
|
|
67 #include "recog.h"
|
|
68 #include "output.h"
|
|
69 #include "rtl-error.h"
|
|
70 #include "lra-int.h"
|
|
71
|
|
72 /* This structure is used to record information about hard register
|
|
73 eliminations. */
|
|
74 struct lra_elim_table
|
|
75 {
|
|
76 /* Hard register number to be eliminated. */
|
|
77 int from;
|
|
78 /* Hard register number used as replacement. */
|
|
79 int to;
|
|
80 /* Difference between values of the two hard registers above on
|
|
81 previous iteration. */
|
131
|
82 poly_int64 previous_offset;
|
111
|
83 /* Difference between the values on the current iteration. */
|
131
|
84 poly_int64 offset;
|
111
|
85 /* Nonzero if this elimination can be done. */
|
|
86 bool can_eliminate;
|
|
87 /* CAN_ELIMINATE since the last check. */
|
|
88 bool prev_can_eliminate;
|
|
89 /* REG rtx for the register to be eliminated. We cannot simply
|
|
90 compare the number since we might then spuriously replace a hard
|
|
91 register corresponding to a pseudo assigned to the reg to be
|
|
92 eliminated. */
|
|
93 rtx from_rtx;
|
|
94 /* REG rtx for the replacement. */
|
|
95 rtx to_rtx;
|
|
96 };
|
|
97
|
|
98 /* The elimination table. Each array entry describes one possible way
|
|
99 of eliminating a register in favor of another. If there is more
|
|
100 than one way of eliminating a particular register, the most
|
|
101 preferred should be specified first. */
|
|
102 static struct lra_elim_table *reg_eliminate = 0;
|
|
103
|
|
104 /* This is an intermediate structure to initialize the table. It has
|
|
105 exactly the members provided by ELIMINABLE_REGS. */
|
|
106 static const struct elim_table_1
|
|
107 {
|
|
108 const int from;
|
|
109 const int to;
|
|
110 } reg_eliminate_1[] =
|
|
111
|
|
112 ELIMINABLE_REGS;
|
|
113
|
|
114 #define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1)
|
|
115
|
|
116 /* Print info about elimination table to file F. */
|
|
117 static void
|
|
118 print_elim_table (FILE *f)
|
|
119 {
|
|
120 struct lra_elim_table *ep;
|
|
121
|
|
122 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
131
|
123 {
|
|
124 fprintf (f, "%s eliminate %d to %d (offset=",
|
|
125 ep->can_eliminate ? "Can" : "Can't", ep->from, ep->to);
|
|
126 print_dec (ep->offset, f);
|
|
127 fprintf (f, ", prev_offset=");
|
|
128 print_dec (ep->previous_offset, f);
|
|
129 fprintf (f, ")\n");
|
|
130 }
|
111
|
131 }
|
|
132
|
|
133 /* Print info about elimination table to stderr. */
|
|
134 void
|
|
135 lra_debug_elim_table (void)
|
|
136 {
|
|
137 print_elim_table (stderr);
|
|
138 }
|
|
139
|
|
140 /* Setup possibility of elimination in elimination table element EP to
|
|
141 VALUE. Setup FRAME_POINTER_NEEDED if elimination from frame
|
|
142 pointer to stack pointer is not possible anymore. */
|
|
143 static void
|
|
144 setup_can_eliminate (struct lra_elim_table *ep, bool value)
|
|
145 {
|
|
146 ep->can_eliminate = ep->prev_can_eliminate = value;
|
|
147 if (! value
|
|
148 && ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
|
|
149 frame_pointer_needed = 1;
|
|
150 if (!frame_pointer_needed)
|
|
151 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 0;
|
|
152 }
|
|
153
|
|
154 /* Map: eliminable "from" register -> its current elimination,
|
|
155 or NULL if none. The elimination table may contain more than
|
|
156 one elimination for the same hard register, but this map specifies
|
|
157 the one that we are currently using. */
|
|
158 static struct lra_elim_table *elimination_map[FIRST_PSEUDO_REGISTER];
|
|
159
|
|
160 /* When an eliminable hard register becomes not eliminable, we use the
|
|
161 following special structure to restore original offsets for the
|
|
162 register. */
|
|
163 static struct lra_elim_table self_elim_table;
|
|
164
|
|
165 /* Offsets should be used to restore original offsets for eliminable
|
|
166 hard register which just became not eliminable. Zero,
|
|
167 otherwise. */
|
131
|
168 static poly_int64_pod self_elim_offsets[FIRST_PSEUDO_REGISTER];
|
111
|
169
|
|
170 /* Map: hard regno -> RTL presentation. RTL presentations of all
|
|
171 potentially eliminable hard registers are stored in the map. */
|
|
172 static rtx eliminable_reg_rtx[FIRST_PSEUDO_REGISTER];
|
|
173
|
|
174 /* Set up ELIMINATION_MAP of the currently used eliminations. */
|
|
175 static void
|
|
176 setup_elimination_map (void)
|
|
177 {
|
|
178 int i;
|
|
179 struct lra_elim_table *ep;
|
|
180
|
|
181 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
|
182 elimination_map[i] = NULL;
|
|
183 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
184 if (ep->can_eliminate && elimination_map[ep->from] == NULL)
|
|
185 elimination_map[ep->from] = ep;
|
|
186 }
|
|
187
|
|
188
|
|
189
|
|
190 /* Compute the sum of X and Y, making canonicalizations assumed in an
|
|
191 address, namely: sum constant integers, surround the sum of two
|
|
192 constants with a CONST, put the constant as the second operand, and
|
|
193 group the constant on the outermost sum.
|
|
194
|
|
195 This routine assumes both inputs are already in canonical form. */
|
|
196 static rtx
|
|
197 form_sum (rtx x, rtx y)
|
|
198 {
|
|
199 machine_mode mode = GET_MODE (x);
|
131
|
200 poly_int64 offset;
|
111
|
201
|
|
202 if (mode == VOIDmode)
|
|
203 mode = GET_MODE (y);
|
|
204
|
|
205 if (mode == VOIDmode)
|
|
206 mode = Pmode;
|
|
207
|
131
|
208 if (poly_int_rtx_p (x, &offset))
|
|
209 return plus_constant (mode, y, offset);
|
|
210 else if (poly_int_rtx_p (y, &offset))
|
|
211 return plus_constant (mode, x, offset);
|
111
|
212 else if (CONSTANT_P (x))
|
|
213 std::swap (x, y);
|
|
214
|
|
215 if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
|
|
216 return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
|
|
217
|
|
218 /* Note that if the operands of Y are specified in the opposite
|
|
219 order in the recursive calls below, infinite recursion will
|
|
220 occur. */
|
|
221 if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
|
|
222 return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
|
|
223
|
|
224 /* If both constant, encapsulate sum. Otherwise, just form sum. A
|
|
225 constant will have been placed second. */
|
|
226 if (CONSTANT_P (x) && CONSTANT_P (y))
|
|
227 {
|
|
228 if (GET_CODE (x) == CONST)
|
|
229 x = XEXP (x, 0);
|
|
230 if (GET_CODE (y) == CONST)
|
|
231 y = XEXP (y, 0);
|
|
232
|
|
233 return gen_rtx_CONST (VOIDmode, gen_rtx_PLUS (mode, x, y));
|
|
234 }
|
|
235
|
|
236 return gen_rtx_PLUS (mode, x, y);
|
|
237 }
|
|
238
|
|
239 /* Return the current substitution hard register of the elimination of
|
|
240 HARD_REGNO. If HARD_REGNO is not eliminable, return itself. */
|
|
241 int
|
|
242 lra_get_elimination_hard_regno (int hard_regno)
|
|
243 {
|
|
244 struct lra_elim_table *ep;
|
|
245
|
|
246 if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
|
|
247 return hard_regno;
|
|
248 if ((ep = elimination_map[hard_regno]) == NULL)
|
|
249 return hard_regno;
|
|
250 return ep->to;
|
|
251 }
|
|
252
|
|
253 /* Return elimination which will be used for hard reg REG, NULL
|
|
254 otherwise. */
|
|
255 static struct lra_elim_table *
|
|
256 get_elimination (rtx reg)
|
|
257 {
|
|
258 int hard_regno;
|
|
259 struct lra_elim_table *ep;
|
|
260
|
|
261 lra_assert (REG_P (reg));
|
|
262 if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
|
|
263 return NULL;
|
|
264 if ((ep = elimination_map[hard_regno]) != NULL)
|
|
265 return ep->from_rtx != reg ? NULL : ep;
|
131
|
266 poly_int64 offset = self_elim_offsets[hard_regno];
|
|
267 if (known_eq (offset, 0))
|
111
|
268 return NULL;
|
|
269 /* This is an iteration to restore offsets just after HARD_REGNO
|
|
270 stopped to be eliminable. */
|
|
271 self_elim_table.from = self_elim_table.to = hard_regno;
|
|
272 self_elim_table.from_rtx
|
|
273 = self_elim_table.to_rtx
|
|
274 = eliminable_reg_rtx[hard_regno];
|
|
275 lra_assert (self_elim_table.from_rtx != NULL);
|
|
276 self_elim_table.offset = offset;
|
|
277 return &self_elim_table;
|
|
278 }
|
|
279
|
|
280 /* Transform (subreg (plus reg const)) to (plus (subreg reg) const)
|
|
281 when it is possible. Return X or the transformation result if the
|
|
282 transformation is done. */
|
|
283 static rtx
|
|
284 move_plus_up (rtx x)
|
|
285 {
|
|
286 rtx subreg_reg;
|
|
287 machine_mode x_mode, subreg_reg_mode;
|
|
288
|
|
289 if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
|
|
290 return x;
|
|
291 subreg_reg = SUBREG_REG (x);
|
|
292 x_mode = GET_MODE (x);
|
|
293 subreg_reg_mode = GET_MODE (subreg_reg);
|
|
294 if (!paradoxical_subreg_p (x)
|
|
295 && GET_CODE (subreg_reg) == PLUS
|
|
296 && CONSTANT_P (XEXP (subreg_reg, 1))
|
|
297 && GET_MODE_CLASS (x_mode) == MODE_INT
|
|
298 && GET_MODE_CLASS (subreg_reg_mode) == MODE_INT)
|
|
299 {
|
|
300 rtx cst = simplify_subreg (x_mode, XEXP (subreg_reg, 1), subreg_reg_mode,
|
|
301 subreg_lowpart_offset (x_mode,
|
|
302 subreg_reg_mode));
|
|
303 if (cst && CONSTANT_P (cst))
|
|
304 return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode,
|
|
305 XEXP (subreg_reg, 0),
|
|
306 subreg_reg_mode), cst);
|
|
307 }
|
|
308 return x;
|
|
309 }
|
|
310
|
|
311 /* Scan X and replace any eliminable registers (such as fp) with a
|
|
312 replacement (such as sp) if SUBST_P, plus an offset. The offset is
|
|
313 a change in the offset between the eliminable register and its
|
|
314 substitution if UPDATE_P, or the full offset if FULL_P, or
|
|
315 otherwise zero. If FULL_P, we also use the SP offsets for
|
|
316 elimination to SP. If UPDATE_P, use UPDATE_SP_OFFSET for updating
|
|
317 offsets of register elimnable to SP. If UPDATE_SP_OFFSET is
|
|
318 non-zero, don't use difference of the offset and the previous
|
|
319 offset.
|
|
320
|
|
321 MEM_MODE is the mode of an enclosing MEM. We need this to know how
|
|
322 much to adjust a register for, e.g., PRE_DEC. Also, if we are
|
|
323 inside a MEM, we are allowed to replace a sum of a hard register
|
|
324 and the constant zero with the hard register, which we cannot do
|
|
325 outside a MEM. In addition, we need to record the fact that a
|
|
326 hard register is referenced outside a MEM.
|
|
327
|
|
328 If we make full substitution to SP for non-null INSN, add the insn
|
|
329 sp offset. */
|
|
330 rtx
|
|
331 lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
|
|
332 bool subst_p, bool update_p,
|
131
|
333 poly_int64 update_sp_offset, bool full_p)
|
111
|
334 {
|
|
335 enum rtx_code code = GET_CODE (x);
|
|
336 struct lra_elim_table *ep;
|
|
337 rtx new_rtx;
|
|
338 int i, j;
|
|
339 const char *fmt;
|
|
340 int copied = 0;
|
|
341
|
|
342 lra_assert (!update_p || !full_p);
|
131
|
343 lra_assert (known_eq (update_sp_offset, 0)
|
|
344 || (!subst_p && update_p && !full_p));
|
111
|
345 if (! current_function_decl)
|
|
346 return x;
|
|
347
|
|
348 switch (code)
|
|
349 {
|
|
350 CASE_CONST_ANY:
|
|
351 case CONST:
|
|
352 case SYMBOL_REF:
|
|
353 case CODE_LABEL:
|
|
354 case PC:
|
|
355 case CC0:
|
|
356 case ASM_INPUT:
|
|
357 case ADDR_VEC:
|
|
358 case ADDR_DIFF_VEC:
|
|
359 case RETURN:
|
|
360 return x;
|
|
361
|
|
362 case REG:
|
|
363 /* First handle the case where we encounter a bare hard register
|
|
364 that is eliminable. Replace it with a PLUS. */
|
|
365 if ((ep = get_elimination (x)) != NULL)
|
|
366 {
|
|
367 rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
|
|
368
|
131
|
369 if (maybe_ne (update_sp_offset, 0))
|
111
|
370 {
|
|
371 if (ep->to_rtx == stack_pointer_rtx)
|
|
372 return plus_constant (Pmode, to, update_sp_offset);
|
|
373 return to;
|
|
374 }
|
|
375 else if (update_p)
|
|
376 return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
|
|
377 else if (full_p)
|
|
378 return plus_constant (Pmode, to,
|
|
379 ep->offset
|
|
380 - (insn != NULL_RTX
|
|
381 && ep->to_rtx == stack_pointer_rtx
|
|
382 ? lra_get_insn_recog_data (insn)->sp_offset
|
|
383 : 0));
|
|
384 else
|
|
385 return to;
|
|
386 }
|
|
387 return x;
|
|
388
|
|
389 case PLUS:
|
|
390 /* If this is the sum of an eliminable register and a constant, rework
|
|
391 the sum. */
|
|
392 if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
|
|
393 {
|
|
394 if ((ep = get_elimination (XEXP (x, 0))) != NULL)
|
|
395 {
|
131
|
396 poly_int64 offset, curr_offset;
|
111
|
397 rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
|
|
398
|
|
399 if (! update_p && ! full_p)
|
|
400 return gen_rtx_PLUS (Pmode, to, XEXP (x, 1));
|
|
401
|
131
|
402 if (maybe_ne (update_sp_offset, 0))
|
111
|
403 offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0;
|
|
404 else
|
|
405 offset = (update_p
|
|
406 ? ep->offset - ep->previous_offset : ep->offset);
|
|
407 if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
|
|
408 offset -= lra_get_insn_recog_data (insn)->sp_offset;
|
131
|
409 if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
|
|
410 && known_eq (curr_offset, -offset))
|
111
|
411 return to;
|
|
412 else
|
|
413 return gen_rtx_PLUS (Pmode, to,
|
|
414 plus_constant (Pmode,
|
|
415 XEXP (x, 1), offset));
|
|
416 }
|
|
417
|
|
418 /* If the hard register is not eliminable, we are done since
|
|
419 the other operand is a constant. */
|
|
420 return x;
|
|
421 }
|
|
422
|
|
423 /* If this is part of an address, we want to bring any constant
|
|
424 to the outermost PLUS. We will do this by doing hard
|
|
425 register replacement in our operands and seeing if a constant
|
|
426 shows up in one of them.
|
|
427
|
|
428 Note that there is no risk of modifying the structure of the
|
|
429 insn, since we only get called for its operands, thus we are
|
|
430 either modifying the address inside a MEM, or something like
|
|
431 an address operand of a load-address insn. */
|
|
432
|
|
433 {
|
|
434 rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
|
|
435 subst_p, update_p,
|
|
436 update_sp_offset, full_p);
|
|
437 rtx new1 = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
|
|
438 subst_p, update_p,
|
|
439 update_sp_offset, full_p);
|
|
440
|
|
441 new0 = move_plus_up (new0);
|
|
442 new1 = move_plus_up (new1);
|
|
443 if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
|
|
444 return form_sum (new0, new1);
|
|
445 }
|
|
446 return x;
|
|
447
|
|
448 case MULT:
|
|
449 /* If this is the product of an eliminable hard register and a
|
|
450 constant, apply the distribute law and move the constant out
|
|
451 so that we have (plus (mult ..) ..). This is needed in order
|
|
452 to keep load-address insns valid. This case is pathological.
|
|
453 We ignore the possibility of overflow here. */
|
|
454 if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
|
|
455 && (ep = get_elimination (XEXP (x, 0))) != NULL)
|
|
456 {
|
|
457 rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
|
|
458
|
131
|
459 if (maybe_ne (update_sp_offset, 0))
|
111
|
460 {
|
|
461 if (ep->to_rtx == stack_pointer_rtx)
|
|
462 return plus_constant (Pmode,
|
|
463 gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
|
|
464 update_sp_offset * INTVAL (XEXP (x, 1)));
|
|
465 return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
|
|
466 }
|
|
467 else if (update_p)
|
|
468 return plus_constant (Pmode,
|
|
469 gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
|
|
470 (ep->offset - ep->previous_offset)
|
|
471 * INTVAL (XEXP (x, 1)));
|
|
472 else if (full_p)
|
|
473 {
|
131
|
474 poly_int64 offset = ep->offset;
|
111
|
475
|
|
476 if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
|
|
477 offset -= lra_get_insn_recog_data (insn)->sp_offset;
|
|
478 return
|
|
479 plus_constant (Pmode,
|
|
480 gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
|
|
481 offset * INTVAL (XEXP (x, 1)));
|
|
482 }
|
|
483 else
|
|
484 return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
|
|
485 }
|
|
486
|
|
487 /* fall through */
|
|
488
|
|
489 case CALL:
|
|
490 case COMPARE:
|
|
491 /* See comments before PLUS about handling MINUS. */
|
|
492 case MINUS:
|
|
493 case DIV: case UDIV:
|
|
494 case MOD: case UMOD:
|
|
495 case AND: case IOR: case XOR:
|
|
496 case ROTATERT: case ROTATE:
|
|
497 case ASHIFTRT: case LSHIFTRT: case ASHIFT:
|
|
498 case NE: case EQ:
|
|
499 case GE: case GT: case GEU: case GTU:
|
|
500 case LE: case LT: case LEU: case LTU:
|
|
501 {
|
|
502 rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
|
|
503 subst_p, update_p,
|
|
504 update_sp_offset, full_p);
|
|
505 rtx new1 = XEXP (x, 1)
|
|
506 ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
|
|
507 subst_p, update_p,
|
|
508 update_sp_offset, full_p) : 0;
|
|
509
|
|
510 if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
|
|
511 return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
|
|
512 }
|
|
513 return x;
|
|
514
|
|
515 case EXPR_LIST:
|
|
516 /* If we have something in XEXP (x, 0), the usual case,
|
|
517 eliminate it. */
|
|
518 if (XEXP (x, 0))
|
|
519 {
|
|
520 new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
|
|
521 subst_p, update_p,
|
|
522 update_sp_offset, full_p);
|
|
523 if (new_rtx != XEXP (x, 0))
|
|
524 {
|
|
525 /* If this is a REG_DEAD note, it is not valid anymore.
|
|
526 Using the eliminated version could result in creating a
|
|
527 REG_DEAD note for the stack or frame pointer. */
|
|
528 if (REG_NOTE_KIND (x) == REG_DEAD)
|
|
529 return (XEXP (x, 1)
|
|
530 ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
|
|
531 subst_p, update_p,
|
|
532 update_sp_offset, full_p)
|
|
533 : NULL_RTX);
|
|
534
|
|
535 x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
|
|
536 }
|
|
537 }
|
|
538
|
|
539 /* fall through */
|
|
540
|
|
541 case INSN_LIST:
|
|
542 case INT_LIST:
|
|
543 /* Now do eliminations in the rest of the chain. If this was
|
|
544 an EXPR_LIST, this might result in allocating more memory than is
|
|
545 strictly needed, but it simplifies the code. */
|
|
546 if (XEXP (x, 1))
|
|
547 {
|
|
548 new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
|
|
549 subst_p, update_p,
|
|
550 update_sp_offset, full_p);
|
|
551 if (new_rtx != XEXP (x, 1))
|
|
552 return
|
|
553 gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x),
|
|
554 XEXP (x, 0), new_rtx);
|
|
555 }
|
|
556 return x;
|
|
557
|
|
558 case PRE_INC:
|
|
559 case POST_INC:
|
|
560 case PRE_DEC:
|
|
561 case POST_DEC:
|
|
562 /* We do not support elimination of a register that is modified.
|
|
563 elimination_effects has already make sure that this does not
|
|
564 happen. */
|
|
565 return x;
|
|
566
|
|
567 case PRE_MODIFY:
|
|
568 case POST_MODIFY:
|
|
569 /* We do not support elimination of a hard register that is
|
|
570 modified. LRA has already make sure that this does not
|
|
571 happen. The only remaining case we need to consider here is
|
|
572 that the increment value may be an eliminable register. */
|
|
573 if (GET_CODE (XEXP (x, 1)) == PLUS
|
|
574 && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
|
|
575 {
|
|
576 rtx new_rtx = lra_eliminate_regs_1 (insn, XEXP (XEXP (x, 1), 1),
|
|
577 mem_mode, subst_p, update_p,
|
|
578 update_sp_offset, full_p);
|
|
579
|
|
580 if (new_rtx != XEXP (XEXP (x, 1), 1))
|
|
581 return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
|
|
582 gen_rtx_PLUS (GET_MODE (x),
|
|
583 XEXP (x, 0), new_rtx));
|
|
584 }
|
|
585 return x;
|
|
586
|
|
587 case STRICT_LOW_PART:
|
|
588 case NEG: case NOT:
|
|
589 case SIGN_EXTEND: case ZERO_EXTEND:
|
|
590 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE:
|
|
591 case FLOAT: case FIX:
|
|
592 case UNSIGNED_FIX: case UNSIGNED_FLOAT:
|
|
593 case ABS:
|
|
594 case SQRT:
|
|
595 case FFS:
|
|
596 case CLZ:
|
|
597 case CTZ:
|
|
598 case POPCOUNT:
|
|
599 case PARITY:
|
|
600 case BSWAP:
|
|
601 new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
|
|
602 subst_p, update_p,
|
|
603 update_sp_offset, full_p);
|
|
604 if (new_rtx != XEXP (x, 0))
|
|
605 return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
|
|
606 return x;
|
|
607
|
|
608 case SUBREG:
|
|
609 new_rtx = lra_eliminate_regs_1 (insn, SUBREG_REG (x), mem_mode,
|
|
610 subst_p, update_p,
|
|
611 update_sp_offset, full_p);
|
|
612
|
|
613 if (new_rtx != SUBREG_REG (x))
|
|
614 {
|
|
615 if (MEM_P (new_rtx) && !paradoxical_subreg_p (x))
|
|
616 {
|
|
617 SUBREG_REG (x) = new_rtx;
|
|
618 alter_subreg (&x, false);
|
|
619 return x;
|
|
620 }
|
|
621 else if (! subst_p)
|
|
622 {
|
|
623 /* LRA can transform subregs itself. So don't call
|
|
624 simplify_gen_subreg until LRA transformations are
|
|
625 finished. Function simplify_gen_subreg can do
|
|
626 non-trivial transformations (like truncation) which
|
|
627 might make LRA work to fail. */
|
|
628 SUBREG_REG (x) = new_rtx;
|
|
629 return x;
|
|
630 }
|
|
631 else
|
|
632 return simplify_gen_subreg (GET_MODE (x), new_rtx,
|
|
633 GET_MODE (new_rtx), SUBREG_BYTE (x));
|
|
634 }
|
|
635
|
|
636 return x;
|
|
637
|
|
638 case MEM:
|
|
639 /* Our only special processing is to pass the mode of the MEM to our
|
|
640 recursive call and copy the flags. While we are here, handle this
|
|
641 case more efficiently. */
|
|
642 return
|
|
643 replace_equiv_address_nv
|
|
644 (x,
|
|
645 lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x),
|
|
646 subst_p, update_p, update_sp_offset, full_p));
|
|
647
|
|
648 case USE:
|
|
649 /* Handle insn_list USE that a call to a pure function may generate. */
|
|
650 new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode,
|
|
651 subst_p, update_p, update_sp_offset, full_p);
|
|
652 if (new_rtx != XEXP (x, 0))
|
|
653 return gen_rtx_USE (GET_MODE (x), new_rtx);
|
|
654 return x;
|
|
655
|
|
656 case CLOBBER:
|
131
|
657 case CLOBBER_HIGH:
|
111
|
658 case SET:
|
|
659 gcc_unreachable ();
|
|
660
|
|
661 default:
|
|
662 break;
|
|
663 }
|
|
664
|
|
665 /* Process each of our operands recursively. If any have changed, make a
|
|
666 copy of the rtx. */
|
|
667 fmt = GET_RTX_FORMAT (code);
|
|
668 for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
|
|
669 {
|
|
670 if (*fmt == 'e')
|
|
671 {
|
|
672 new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode,
|
|
673 subst_p, update_p,
|
|
674 update_sp_offset, full_p);
|
|
675 if (new_rtx != XEXP (x, i) && ! copied)
|
|
676 {
|
|
677 x = shallow_copy_rtx (x);
|
|
678 copied = 1;
|
|
679 }
|
|
680 XEXP (x, i) = new_rtx;
|
|
681 }
|
|
682 else if (*fmt == 'E')
|
|
683 {
|
|
684 int copied_vec = 0;
|
|
685 for (j = 0; j < XVECLEN (x, i); j++)
|
|
686 {
|
|
687 new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode,
|
|
688 subst_p, update_p,
|
|
689 update_sp_offset, full_p);
|
|
690 if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
|
|
691 {
|
|
692 rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
|
|
693 XVEC (x, i)->elem);
|
|
694 if (! copied)
|
|
695 {
|
|
696 x = shallow_copy_rtx (x);
|
|
697 copied = 1;
|
|
698 }
|
|
699 XVEC (x, i) = new_v;
|
|
700 copied_vec = 1;
|
|
701 }
|
|
702 XVECEXP (x, i, j) = new_rtx;
|
|
703 }
|
|
704 }
|
|
705 }
|
|
706
|
|
707 return x;
|
|
708 }
|
|
709
|
|
710 /* This function is used externally in subsequent passes of GCC. It
|
|
711 always does a full elimination of X. */
|
|
712 rtx
|
|
713 lra_eliminate_regs (rtx x, machine_mode mem_mode,
|
|
714 rtx insn ATTRIBUTE_UNUSED)
|
|
715 {
|
|
716 return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, 0, true);
|
|
717 }
|
|
718
|
|
719 /* Stack pointer offset before the current insn relative to one at the
|
|
720 func start. RTL insns can change SP explicitly. We keep the
|
|
721 changes from one insn to another through this variable. */
|
131
|
722 static poly_int64 curr_sp_change;
|
111
|
723
|
|
724 /* Scan rtx X for references to elimination source or target registers
|
|
725 in contexts that would prevent the elimination from happening.
|
|
726 Update the table of eliminables to reflect the changed state.
|
|
727 MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not
|
|
728 within a MEM. */
|
|
729 static void
|
|
730 mark_not_eliminable (rtx x, machine_mode mem_mode)
|
|
731 {
|
|
732 enum rtx_code code = GET_CODE (x);
|
|
733 struct lra_elim_table *ep;
|
|
734 int i, j;
|
|
735 const char *fmt;
|
131
|
736 poly_int64 offset = 0;
|
111
|
737
|
|
738 switch (code)
|
|
739 {
|
|
740 case PRE_INC:
|
|
741 case POST_INC:
|
|
742 case PRE_DEC:
|
|
743 case POST_DEC:
|
|
744 case POST_MODIFY:
|
|
745 case PRE_MODIFY:
|
|
746 if (XEXP (x, 0) == stack_pointer_rtx
|
|
747 && ((code != PRE_MODIFY && code != POST_MODIFY)
|
|
748 || (GET_CODE (XEXP (x, 1)) == PLUS
|
|
749 && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
|
131
|
750 && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
|
111
|
751 {
|
131
|
752 poly_int64 size = GET_MODE_SIZE (mem_mode);
|
111
|
753
|
|
754 #ifdef PUSH_ROUNDING
|
|
755 /* If more bytes than MEM_MODE are pushed, account for
|
|
756 them. */
|
|
757 size = PUSH_ROUNDING (size);
|
|
758 #endif
|
|
759 if (code == PRE_DEC || code == POST_DEC)
|
|
760 curr_sp_change -= size;
|
|
761 else if (code == PRE_INC || code == POST_INC)
|
|
762 curr_sp_change += size;
|
|
763 else if (code == PRE_MODIFY || code == POST_MODIFY)
|
131
|
764 curr_sp_change += offset;
|
111
|
765 }
|
|
766 else if (REG_P (XEXP (x, 0))
|
|
767 && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
|
|
768 {
|
|
769 /* If we modify the source of an elimination rule, disable
|
|
770 it. Do the same if it is the destination and not the
|
|
771 hard frame register. */
|
|
772 for (ep = reg_eliminate;
|
|
773 ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
|
774 ep++)
|
|
775 if (ep->from_rtx == XEXP (x, 0)
|
|
776 || (ep->to_rtx == XEXP (x, 0)
|
|
777 && ep->to_rtx != hard_frame_pointer_rtx))
|
|
778 setup_can_eliminate (ep, false);
|
|
779 }
|
|
780 return;
|
|
781
|
|
782 case USE:
|
|
783 if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
|
|
784 /* If using a hard register that is the source of an eliminate
|
|
785 we still think can be performed, note it cannot be
|
|
786 performed since we don't know how this hard register is
|
|
787 used. */
|
|
788 for (ep = reg_eliminate;
|
|
789 ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
|
790 ep++)
|
|
791 if (ep->from_rtx == XEXP (x, 0)
|
|
792 && ep->to_rtx != hard_frame_pointer_rtx)
|
|
793 setup_can_eliminate (ep, false);
|
|
794 return;
|
|
795
|
|
796 case CLOBBER:
|
|
797 if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
|
|
798 /* If clobbering a hard register that is the replacement
|
|
799 register for an elimination we still think can be
|
|
800 performed, note that it cannot be performed. Otherwise, we
|
|
801 need not be concerned about it. */
|
|
802 for (ep = reg_eliminate;
|
|
803 ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
|
804 ep++)
|
|
805 if (ep->to_rtx == XEXP (x, 0)
|
|
806 && ep->to_rtx != hard_frame_pointer_rtx)
|
|
807 setup_can_eliminate (ep, false);
|
|
808 return;
|
|
809
|
131
|
810 case CLOBBER_HIGH:
|
|
811 gcc_assert (REG_P (XEXP (x, 0)));
|
|
812 gcc_assert (REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER);
|
|
813 for (ep = reg_eliminate;
|
|
814 ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
|
815 ep++)
|
|
816 if (reg_is_clobbered_by_clobber_high (ep->to_rtx, XEXP (x, 0)))
|
|
817 setup_can_eliminate (ep, false);
|
|
818 return;
|
|
819
|
111
|
820 case SET:
|
|
821 if (SET_DEST (x) == stack_pointer_rtx
|
|
822 && GET_CODE (SET_SRC (x)) == PLUS
|
|
823 && XEXP (SET_SRC (x), 0) == SET_DEST (x)
|
131
|
824 && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
|
111
|
825 {
|
131
|
826 curr_sp_change += offset;
|
111
|
827 return;
|
|
828 }
|
|
829 if (! REG_P (SET_DEST (x))
|
|
830 || REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
|
|
831 mark_not_eliminable (SET_DEST (x), mem_mode);
|
|
832 else
|
|
833 {
|
|
834 /* See if this is setting the replacement hard register for
|
|
835 an elimination.
|
|
836
|
|
837 If DEST is the hard frame pointer, we do nothing because
|
|
838 we assume that all assignments to the frame pointer are
|
|
839 for non-local gotos and are being done at a time when
|
|
840 they are valid and do not disturb anything else. Some
|
|
841 machines want to eliminate a fake argument pointer (or
|
|
842 even a fake frame pointer) with either the real frame
|
|
843 pointer or the stack pointer. Assignments to the hard
|
|
844 frame pointer must not prevent this elimination. */
|
|
845 for (ep = reg_eliminate;
|
|
846 ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
|
847 ep++)
|
|
848 if (ep->to_rtx == SET_DEST (x)
|
|
849 && SET_DEST (x) != hard_frame_pointer_rtx)
|
|
850 setup_can_eliminate (ep, false);
|
|
851 }
|
|
852
|
|
853 mark_not_eliminable (SET_SRC (x), mem_mode);
|
|
854 return;
|
|
855
|
|
856 case MEM:
|
|
857 /* Our only special processing is to pass the mode of the MEM to
|
|
858 our recursive call. */
|
|
859 mark_not_eliminable (XEXP (x, 0), GET_MODE (x));
|
|
860 return;
|
|
861
|
|
862 default:
|
|
863 break;
|
|
864 }
|
|
865
|
|
866 fmt = GET_RTX_FORMAT (code);
|
|
867 for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
|
|
868 {
|
|
869 if (*fmt == 'e')
|
|
870 mark_not_eliminable (XEXP (x, i), mem_mode);
|
|
871 else if (*fmt == 'E')
|
|
872 for (j = 0; j < XVECLEN (x, i); j++)
|
|
873 mark_not_eliminable (XVECEXP (x, i, j), mem_mode);
|
|
874 }
|
|
875 }
|
|
876
|
|
877
|
|
878
|
|
879 #ifdef HARD_FRAME_POINTER_REGNUM
|
|
880
|
131
|
881 /* Search INSN's reg notes to see whether the destination is equal to
|
|
882 WHAT + C for some constant C. Return true if so, storing C in
|
|
883 *OFFSET_OUT and removing the reg note. */
|
|
884 static bool
|
|
885 remove_reg_equal_offset_note (rtx_insn *insn, rtx what, poly_int64 *offset_out)
|
111
|
886 {
|
|
887 rtx link, *link_loc;
|
|
888
|
|
889 for (link_loc = ®_NOTES (insn);
|
|
890 (link = *link_loc) != NULL_RTX;
|
|
891 link_loc = &XEXP (link, 1))
|
|
892 if (REG_NOTE_KIND (link) == REG_EQUAL
|
|
893 && GET_CODE (XEXP (link, 0)) == PLUS
|
|
894 && XEXP (XEXP (link, 0), 0) == what
|
131
|
895 && poly_int_rtx_p (XEXP (XEXP (link, 0), 1), offset_out))
|
111
|
896 {
|
|
897 *link_loc = XEXP (link, 1);
|
131
|
898 return true;
|
111
|
899 }
|
131
|
900 return false;
|
111
|
901 }
|
|
902
|
|
903 #endif
|
|
904
|
|
905 /* Scan INSN and eliminate all eliminable hard registers in it.
|
|
906
|
|
907 If REPLACE_P is true, do the replacement destructively. Also
|
|
908 delete the insn as dead it if it is setting an eliminable register.
|
|
909
|
|
910 If REPLACE_P is false, just update the offsets while keeping the
|
|
911 base register the same. If FIRST_P, use the sp offset for
|
|
912 elimination to sp. Otherwise, use UPDATE_SP_OFFSET for this. If
|
|
913 UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
|
|
914 and the previous offset. Attach the note about used elimination
|
|
915 for insns setting frame pointer to update elimination easy (without
|
|
916 parsing already generated elimination insns to find offset
|
|
917 previously used) in future. */
|
|
918
|
|
919 void
|
|
920 eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
|
131
|
921 poly_int64 update_sp_offset)
|
111
|
922 {
|
|
923 int icode = recog_memoized (insn);
|
|
924 rtx old_set = single_set (insn);
|
|
925 bool validate_p;
|
|
926 int i;
|
|
927 rtx substed_operand[MAX_RECOG_OPERANDS];
|
|
928 rtx orig_operand[MAX_RECOG_OPERANDS];
|
|
929 struct lra_elim_table *ep;
|
|
930 rtx plus_src, plus_cst_src;
|
|
931 lra_insn_recog_data_t id;
|
|
932 struct lra_static_insn_data *static_id;
|
|
933
|
|
934 if (icode < 0 && asm_noperands (PATTERN (insn)) < 0 && ! DEBUG_INSN_P (insn))
|
|
935 {
|
|
936 lra_assert (GET_CODE (PATTERN (insn)) == USE
|
|
937 || GET_CODE (PATTERN (insn)) == CLOBBER
|
|
938 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
|
|
939 return;
|
|
940 }
|
|
941
|
|
942 /* Check for setting an eliminable register. */
|
|
943 if (old_set != 0 && REG_P (SET_DEST (old_set))
|
|
944 && (ep = get_elimination (SET_DEST (old_set))) != NULL)
|
|
945 {
|
|
946 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
947 if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
|
|
948 {
|
|
949 bool delete_p = replace_p;
|
|
950
|
|
951 #ifdef HARD_FRAME_POINTER_REGNUM
|
|
952 if (ep->from == FRAME_POINTER_REGNUM
|
|
953 && ep->to == HARD_FRAME_POINTER_REGNUM)
|
|
954 /* If this is setting the frame pointer register to the
|
|
955 hardware frame pointer register and this is an
|
|
956 elimination that will be done (tested above), this
|
|
957 insn is really adjusting the frame pointer downward
|
|
958 to compensate for the adjustment done before a
|
|
959 nonlocal goto. */
|
|
960 {
|
|
961 rtx src = SET_SRC (old_set);
|
131
|
962 poly_int64 offset = 0;
|
|
963
|
111
|
964 /* We should never process such insn with non-zero
|
|
965 UPDATE_SP_OFFSET. */
|
131
|
966 lra_assert (known_eq (update_sp_offset, 0));
|
111
|
967
|
131
|
968 if (remove_reg_equal_offset_note (insn, ep->to_rtx, &offset)
|
|
969 || strip_offset (src, &offset) == ep->to_rtx)
|
111
|
970 {
|
|
971 if (replace_p)
|
|
972 {
|
|
973 SET_DEST (old_set) = ep->to_rtx;
|
|
974 lra_update_insn_recog_data (insn);
|
|
975 return;
|
|
976 }
|
|
977 offset -= (ep->offset - ep->previous_offset);
|
|
978 src = plus_constant (Pmode, ep->to_rtx, offset);
|
|
979
|
|
980 /* First see if this insn remains valid when we
|
|
981 make the change. If not, keep the INSN_CODE
|
|
982 the same and let the constraint pass fit it
|
|
983 up. */
|
|
984 validate_change (insn, &SET_SRC (old_set), src, 1);
|
|
985 validate_change (insn, &SET_DEST (old_set),
|
|
986 ep->from_rtx, 1);
|
|
987 if (! apply_change_group ())
|
|
988 {
|
|
989 SET_SRC (old_set) = src;
|
|
990 SET_DEST (old_set) = ep->from_rtx;
|
|
991 }
|
|
992 lra_update_insn_recog_data (insn);
|
|
993 /* Add offset note for future updates. */
|
|
994 add_reg_note (insn, REG_EQUAL, copy_rtx (src));
|
|
995 return;
|
|
996 }
|
|
997 }
|
|
998 #endif
|
|
999
|
|
1000 /* This insn isn't serving a useful purpose. We delete it
|
|
1001 when REPLACE is set. */
|
|
1002 if (delete_p)
|
|
1003 lra_delete_dead_insn (insn);
|
|
1004 return;
|
|
1005 }
|
|
1006 }
|
|
1007
|
|
1008 /* We allow one special case which happens to work on all machines we
|
|
1009 currently support: a single set with the source or a REG_EQUAL
|
|
1010 note being a PLUS of an eliminable register and a constant. */
|
|
1011 plus_src = plus_cst_src = 0;
|
131
|
1012 poly_int64 offset = 0;
|
111
|
1013 if (old_set && REG_P (SET_DEST (old_set)))
|
|
1014 {
|
|
1015 if (GET_CODE (SET_SRC (old_set)) == PLUS)
|
|
1016 plus_src = SET_SRC (old_set);
|
|
1017 /* First see if the source is of the form (plus (...) CST). */
|
131
|
1018 if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
|
111
|
1019 plus_cst_src = plus_src;
|
|
1020 /* Check that the first operand of the PLUS is a hard reg or
|
|
1021 the lowpart subreg of one. */
|
|
1022 if (plus_cst_src)
|
|
1023 {
|
|
1024 rtx reg = XEXP (plus_cst_src, 0);
|
|
1025
|
|
1026 if (GET_CODE (reg) == SUBREG && subreg_lowpart_p (reg))
|
|
1027 reg = SUBREG_REG (reg);
|
|
1028
|
|
1029 if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
|
|
1030 plus_cst_src = 0;
|
|
1031 }
|
|
1032 }
|
|
1033 if (plus_cst_src)
|
|
1034 {
|
|
1035 rtx reg = XEXP (plus_cst_src, 0);
|
|
1036
|
|
1037 if (GET_CODE (reg) == SUBREG)
|
|
1038 reg = SUBREG_REG (reg);
|
|
1039
|
|
1040 if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
|
|
1041 {
|
|
1042 rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
|
|
1043
|
|
1044 if (! replace_p)
|
|
1045 {
|
131
|
1046 if (known_eq (update_sp_offset, 0))
|
111
|
1047 offset += (ep->offset - ep->previous_offset);
|
|
1048 if (ep->to_rtx == stack_pointer_rtx)
|
|
1049 {
|
|
1050 if (first_p)
|
|
1051 offset -= lra_get_insn_recog_data (insn)->sp_offset;
|
|
1052 else
|
|
1053 offset += update_sp_offset;
|
|
1054 }
|
|
1055 offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
|
|
1056 }
|
|
1057
|
|
1058 if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
|
|
1059 to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), to_rtx);
|
|
1060 /* If we have a nonzero offset, and the source is already a
|
|
1061 simple REG, the following transformation would increase
|
|
1062 the cost of the insn by replacing a simple REG with (plus
|
|
1063 (reg sp) CST). So try only when we already had a PLUS
|
|
1064 before. */
|
131
|
1065 if (known_eq (offset, 0) || plus_src)
|
111
|
1066 {
|
|
1067 rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
|
|
1068
|
|
1069 old_set = single_set (insn);
|
|
1070
|
|
1071 /* First see if this insn remains valid when we make the
|
|
1072 change. If not, try to replace the whole pattern
|
|
1073 with a simple set (this may help if the original insn
|
|
1074 was a PARALLEL that was only recognized as single_set
|
|
1075 due to REG_UNUSED notes). If this isn't valid
|
|
1076 either, keep the INSN_CODE the same and let the
|
|
1077 constraint pass fix it up. */
|
|
1078 if (! validate_change (insn, &SET_SRC (old_set), new_src, 0))
|
|
1079 {
|
|
1080 rtx new_pat = gen_rtx_SET (SET_DEST (old_set), new_src);
|
|
1081
|
|
1082 if (! validate_change (insn, &PATTERN (insn), new_pat, 0))
|
|
1083 SET_SRC (old_set) = new_src;
|
|
1084 }
|
|
1085 lra_update_insn_recog_data (insn);
|
|
1086 /* This can't have an effect on elimination offsets, so skip
|
|
1087 right to the end. */
|
|
1088 return;
|
|
1089 }
|
|
1090 }
|
|
1091 }
|
|
1092
|
|
1093 /* Eliminate all eliminable registers occurring in operands that
|
|
1094 can be handled by the constraint pass. */
|
|
1095 id = lra_get_insn_recog_data (insn);
|
|
1096 static_id = id->insn_static_data;
|
|
1097 validate_p = false;
|
|
1098 for (i = 0; i < static_id->n_operands; i++)
|
|
1099 {
|
|
1100 orig_operand[i] = *id->operand_loc[i];
|
|
1101 substed_operand[i] = *id->operand_loc[i];
|
|
1102
|
|
1103 /* For an asm statement, every operand is eliminable. */
|
|
1104 if (icode < 0 || insn_data[icode].operand[i].eliminable)
|
|
1105 {
|
|
1106 /* Check for setting a hard register that we know about. */
|
|
1107 if (static_id->operand[i].type != OP_IN
|
|
1108 && REG_P (orig_operand[i]))
|
|
1109 {
|
|
1110 /* If we are assigning to a hard register that can be
|
|
1111 eliminated, it must be as part of a PARALLEL, since
|
|
1112 the code above handles single SETs. This reg can not
|
|
1113 be longer eliminated -- it is forced by
|
|
1114 mark_not_eliminable. */
|
|
1115 for (ep = reg_eliminate;
|
|
1116 ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
|
1117 ep++)
|
|
1118 lra_assert (ep->from_rtx != orig_operand[i]
|
|
1119 || ! ep->can_eliminate);
|
|
1120 }
|
|
1121
|
|
1122 /* Companion to the above plus substitution, we can allow
|
|
1123 invariants as the source of a plain move. */
|
|
1124 substed_operand[i]
|
|
1125 = lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode,
|
|
1126 replace_p, ! replace_p && ! first_p,
|
|
1127 update_sp_offset, first_p);
|
|
1128 if (substed_operand[i] != orig_operand[i])
|
|
1129 validate_p = true;
|
|
1130 }
|
|
1131 }
|
|
1132
|
|
1133 if (! validate_p)
|
|
1134 return;
|
|
1135
|
|
1136 /* Substitute the operands; the new values are in the substed_operand
|
|
1137 array. */
|
|
1138 for (i = 0; i < static_id->n_operands; i++)
|
|
1139 *id->operand_loc[i] = substed_operand[i];
|
|
1140 for (i = 0; i < static_id->n_dups; i++)
|
|
1141 *id->dup_loc[i] = substed_operand[(int) static_id->dup_num[i]];
|
|
1142
|
|
1143 /* If we had a move insn but now we don't, re-recognize it.
|
|
1144 This will cause spurious re-recognition if the old move had a
|
|
1145 PARALLEL since the new one still will, but we can't call
|
|
1146 single_set without having put new body into the insn and the
|
|
1147 re-recognition won't hurt in this rare case. */
|
|
1148 id = lra_update_insn_recog_data (insn);
|
|
1149 static_id = id->insn_static_data;
|
|
1150 }
|
|
1151
|
|
1152 /* Spill pseudos which are assigned to hard registers in SET. Add
|
|
1153 affected insns for processing in the subsequent constraint
|
|
1154 pass. */
|
|
1155 static void
|
|
1156 spill_pseudos (HARD_REG_SET set)
|
|
1157 {
|
|
1158 int i;
|
|
1159 bitmap_head to_process;
|
|
1160 rtx_insn *insn;
|
|
1161
|
|
1162 if (hard_reg_set_empty_p (set))
|
|
1163 return;
|
|
1164 if (lra_dump_file != NULL)
|
|
1165 {
|
|
1166 fprintf (lra_dump_file, " Spilling non-eliminable hard regs:");
|
|
1167 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
|
1168 if (TEST_HARD_REG_BIT (set, i))
|
|
1169 fprintf (lra_dump_file, " %d", i);
|
|
1170 fprintf (lra_dump_file, "\n");
|
|
1171 }
|
|
1172 bitmap_initialize (&to_process, ®_obstack);
|
|
1173 for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
|
|
1174 if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
|
|
1175 && overlaps_hard_reg_set_p (set,
|
|
1176 PSEUDO_REGNO_MODE (i), reg_renumber[i]))
|
|
1177 {
|
|
1178 if (lra_dump_file != NULL)
|
|
1179 fprintf (lra_dump_file, " Spilling r%d(%d)\n",
|
|
1180 i, reg_renumber[i]);
|
|
1181 reg_renumber[i] = -1;
|
|
1182 bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
|
|
1183 }
|
|
1184 IOR_HARD_REG_SET (lra_no_alloc_regs, set);
|
|
1185 for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
|
|
1186 if (bitmap_bit_p (&to_process, INSN_UID (insn)))
|
|
1187 {
|
|
1188 lra_push_insn (insn);
|
131
|
1189 lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
|
111
|
1190 }
|
|
1191 bitmap_clear (&to_process);
|
|
1192 }
|
|
1193
|
|
1194 /* Update all offsets and possibility for elimination on eliminable
|
|
1195 registers. Spill pseudos assigned to registers which are
|
|
1196 uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET. Add
|
|
1197 insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
|
|
1198 registers whose offsets should be changed. Return true if any
|
|
1199 elimination offset changed. */
|
|
1200 static bool
|
|
1201 update_reg_eliminate (bitmap insns_with_changed_offsets)
|
|
1202 {
|
|
1203 bool prev, result;
|
|
1204 struct lra_elim_table *ep, *ep1;
|
|
1205 HARD_REG_SET temp_hard_reg_set;
|
|
1206
|
|
1207 targetm.compute_frame_layout ();
|
|
1208
|
|
1209 /* Clear self elimination offsets. */
|
|
1210 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
1211 self_elim_offsets[ep->from] = 0;
|
|
1212 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
1213 {
|
|
1214 /* If it is a currently used elimination: update the previous
|
|
1215 offset. */
|
|
1216 if (elimination_map[ep->from] == ep)
|
|
1217 ep->previous_offset = ep->offset;
|
|
1218
|
|
1219 prev = ep->prev_can_eliminate;
|
|
1220 setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to));
|
|
1221 if (ep->can_eliminate && ! prev)
|
|
1222 {
|
|
1223 /* It is possible that not eliminable register becomes
|
|
1224 eliminable because we took other reasons into account to
|
|
1225 set up eliminable regs in the initial set up. Just
|
|
1226 ignore new eliminable registers. */
|
|
1227 setup_can_eliminate (ep, false);
|
|
1228 continue;
|
|
1229 }
|
|
1230 if (ep->can_eliminate != prev && elimination_map[ep->from] == ep)
|
|
1231 {
|
|
1232 /* We cannot use this elimination anymore -- find another
|
|
1233 one. */
|
|
1234 if (lra_dump_file != NULL)
|
|
1235 fprintf (lra_dump_file,
|
|
1236 " Elimination %d to %d is not possible anymore\n",
|
|
1237 ep->from, ep->to);
|
|
1238 /* If after processing RTL we decides that SP can be used as
|
|
1239 a result of elimination, it can not be changed. */
|
|
1240 gcc_assert ((ep->to_rtx != stack_pointer_rtx)
|
|
1241 || (ep->from < FIRST_PSEUDO_REGISTER
|
|
1242 && fixed_regs [ep->from]));
|
|
1243 /* Mark that is not eliminable anymore. */
|
|
1244 elimination_map[ep->from] = NULL;
|
|
1245 for (ep1 = ep + 1; ep1 < ®_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
|
|
1246 if (ep1->can_eliminate && ep1->from == ep->from)
|
|
1247 break;
|
|
1248 if (ep1 < ®_eliminate[NUM_ELIMINABLE_REGS])
|
|
1249 {
|
|
1250 if (lra_dump_file != NULL)
|
|
1251 fprintf (lra_dump_file, " Using elimination %d to %d now\n",
|
|
1252 ep1->from, ep1->to);
|
131
|
1253 lra_assert (known_eq (ep1->previous_offset, 0));
|
111
|
1254 ep1->previous_offset = ep->offset;
|
|
1255 }
|
|
1256 else
|
|
1257 {
|
|
1258 /* There is no elimination anymore just use the hard
|
|
1259 register `from' itself. Setup self elimination
|
|
1260 offset to restore the original offset values. */
|
|
1261 if (lra_dump_file != NULL)
|
|
1262 fprintf (lra_dump_file, " %d is not eliminable at all\n",
|
|
1263 ep->from);
|
|
1264 self_elim_offsets[ep->from] = -ep->offset;
|
131
|
1265 if (maybe_ne (ep->offset, 0))
|
111
|
1266 bitmap_ior_into (insns_with_changed_offsets,
|
|
1267 &lra_reg_info[ep->from].insn_bitmap);
|
|
1268 }
|
|
1269 }
|
|
1270
|
|
1271 INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->offset);
|
|
1272 }
|
|
1273 setup_elimination_map ();
|
|
1274 result = false;
|
|
1275 CLEAR_HARD_REG_SET (temp_hard_reg_set);
|
|
1276 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
1277 if (elimination_map[ep->from] == NULL)
|
131
|
1278 add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->from);
|
111
|
1279 else if (elimination_map[ep->from] == ep)
|
|
1280 {
|
|
1281 /* Prevent the hard register into which we eliminate from
|
|
1282 the usage for pseudos. */
|
|
1283 if (ep->from != ep->to)
|
131
|
1284 add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->to);
|
|
1285 if (maybe_ne (ep->previous_offset, ep->offset))
|
111
|
1286 {
|
|
1287 bitmap_ior_into (insns_with_changed_offsets,
|
|
1288 &lra_reg_info[ep->from].insn_bitmap);
|
|
1289
|
|
1290 /* Update offset when the eliminate offset have been
|
|
1291 changed. */
|
|
1292 lra_update_reg_val_offset (lra_reg_info[ep->from].val,
|
|
1293 ep->offset - ep->previous_offset);
|
|
1294 result = true;
|
|
1295 }
|
|
1296 }
|
|
1297 IOR_HARD_REG_SET (lra_no_alloc_regs, temp_hard_reg_set);
|
|
1298 AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set);
|
|
1299 spill_pseudos (temp_hard_reg_set);
|
|
1300 return result;
|
|
1301 }
|
|
1302
|
|
1303 /* Initialize the table of hard registers to eliminate.
|
|
1304 Pre-condition: global flag frame_pointer_needed has been set before
|
|
1305 calling this function. */
|
|
1306 static void
|
|
1307 init_elim_table (void)
|
|
1308 {
|
|
1309 struct lra_elim_table *ep;
|
|
1310 bool value_p;
|
|
1311 const struct elim_table_1 *ep1;
|
|
1312
|
|
1313 if (!reg_eliminate)
|
|
1314 reg_eliminate = XCNEWVEC (struct lra_elim_table, NUM_ELIMINABLE_REGS);
|
|
1315
|
|
1316 memset (self_elim_offsets, 0, sizeof (self_elim_offsets));
|
|
1317 /* Initiate member values which will be never changed. */
|
|
1318 self_elim_table.can_eliminate = self_elim_table.prev_can_eliminate = true;
|
|
1319 self_elim_table.previous_offset = 0;
|
|
1320
|
|
1321 for (ep = reg_eliminate, ep1 = reg_eliminate_1;
|
|
1322 ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
|
|
1323 {
|
|
1324 ep->offset = ep->previous_offset = 0;
|
|
1325 ep->from = ep1->from;
|
|
1326 ep->to = ep1->to;
|
|
1327 value_p = (targetm.can_eliminate (ep->from, ep->to)
|
|
1328 && ! (ep->to == STACK_POINTER_REGNUM
|
|
1329 && frame_pointer_needed
|
|
1330 && (! SUPPORTS_STACK_ALIGNMENT
|
|
1331 || ! stack_realign_fp)));
|
|
1332 setup_can_eliminate (ep, value_p);
|
|
1333 }
|
|
1334
|
|
1335 /* Build the FROM and TO REG rtx's. Note that code in gen_rtx_REG
|
|
1336 will cause, e.g., gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to
|
|
1337 equal stack_pointer_rtx. We depend on this. Threfore we switch
|
|
1338 off that we are in LRA temporarily. */
|
|
1339 lra_in_progress = 0;
|
|
1340 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
1341 {
|
|
1342 ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
|
|
1343 ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
|
|
1344 eliminable_reg_rtx[ep->from] = ep->from_rtx;
|
|
1345 }
|
|
1346 lra_in_progress = 1;
|
|
1347 }
|
|
1348
|
|
1349 /* Function for initialization of elimination once per function. It
|
|
1350 sets up sp offset for each insn. */
|
|
1351 static void
|
|
1352 init_elimination (void)
|
|
1353 {
|
|
1354 bool stop_to_sp_elimination_p;
|
|
1355 basic_block bb;
|
|
1356 rtx_insn *insn;
|
|
1357 struct lra_elim_table *ep;
|
|
1358
|
|
1359 init_elim_table ();
|
|
1360 FOR_EACH_BB_FN (bb, cfun)
|
|
1361 {
|
|
1362 curr_sp_change = 0;
|
|
1363 stop_to_sp_elimination_p = false;
|
|
1364 FOR_BB_INSNS (bb, insn)
|
|
1365 if (INSN_P (insn))
|
|
1366 {
|
|
1367 lra_get_insn_recog_data (insn)->sp_offset = curr_sp_change;
|
|
1368 if (NONDEBUG_INSN_P (insn))
|
|
1369 {
|
|
1370 mark_not_eliminable (PATTERN (insn), VOIDmode);
|
131
|
1371 if (maybe_ne (curr_sp_change, 0)
|
111
|
1372 && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
|
|
1373 stop_to_sp_elimination_p = true;
|
|
1374 }
|
|
1375 }
|
|
1376 if (! frame_pointer_needed
|
131
|
1377 && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
|
111
|
1378 && bb->succs && bb->succs->length () != 0)
|
|
1379 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
1380 if (ep->to == STACK_POINTER_REGNUM)
|
|
1381 setup_can_eliminate (ep, false);
|
|
1382 }
|
|
1383 setup_elimination_map ();
|
|
1384 }
|
|
1385
|
|
1386 /* Eliminate hard reg given by its location LOC. */
|
|
1387 void
|
|
1388 lra_eliminate_reg_if_possible (rtx *loc)
|
|
1389 {
|
|
1390 int regno;
|
|
1391 struct lra_elim_table *ep;
|
|
1392
|
|
1393 lra_assert (REG_P (*loc));
|
|
1394 if ((regno = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
|
|
1395 || ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
|
|
1396 return;
|
|
1397 if ((ep = get_elimination (*loc)) != NULL)
|
|
1398 *loc = ep->to_rtx;
|
|
1399 }
|
|
1400
|
|
1401 /* Do (final if FINAL_P or first if FIRST_P) elimination in INSN. Add
|
|
1402 the insn for subsequent processing in the constraint pass, update
|
|
1403 the insn info. */
|
|
1404 static void
|
|
1405 process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
|
|
1406 {
|
|
1407 eliminate_regs_in_insn (insn, final_p, first_p, 0);
|
|
1408 if (! final_p)
|
|
1409 {
|
|
1410 /* Check that insn changed its code. This is a case when a move
|
|
1411 insn becomes an add insn and we do not want to process the
|
|
1412 insn as a move anymore. */
|
|
1413 int icode = recog (PATTERN (insn), insn, 0);
|
|
1414
|
|
1415 if (icode >= 0 && icode != INSN_CODE (insn))
|
|
1416 {
|
|
1417 INSN_CODE (insn) = icode;
|
|
1418 lra_update_insn_recog_data (insn);
|
|
1419 }
|
|
1420 lra_update_insn_regno_info (insn);
|
|
1421 lra_push_insn (insn);
|
131
|
1422 lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
|
111
|
1423 }
|
|
1424 }
|
|
1425
|
|
1426 /* Entry function to do final elimination if FINAL_P or to update
|
|
1427 elimination register offsets (FIRST_P if we are doing it the first
|
|
1428 time). */
|
|
1429 void
|
|
1430 lra_eliminate (bool final_p, bool first_p)
|
|
1431 {
|
|
1432 unsigned int uid;
|
|
1433 bitmap_head insns_with_changed_offsets;
|
|
1434 bitmap_iterator bi;
|
|
1435 struct lra_elim_table *ep;
|
|
1436
|
|
1437 gcc_assert (! final_p || ! first_p);
|
|
1438
|
|
1439 timevar_push (TV_LRA_ELIMINATE);
|
|
1440
|
|
1441 if (first_p)
|
|
1442 init_elimination ();
|
|
1443
|
|
1444 bitmap_initialize (&insns_with_changed_offsets, ®_obstack);
|
|
1445 if (final_p)
|
|
1446 {
|
|
1447 if (flag_checking)
|
|
1448 {
|
|
1449 update_reg_eliminate (&insns_with_changed_offsets);
|
|
1450 gcc_assert (bitmap_empty_p (&insns_with_changed_offsets));
|
|
1451 }
|
|
1452 /* We change eliminable hard registers in insns so we should do
|
|
1453 this for all insns containing any eliminable hard
|
|
1454 register. */
|
|
1455 for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
|
1456 if (elimination_map[ep->from] != NULL)
|
|
1457 bitmap_ior_into (&insns_with_changed_offsets,
|
|
1458 &lra_reg_info[ep->from].insn_bitmap);
|
|
1459 }
|
|
1460 else if (! update_reg_eliminate (&insns_with_changed_offsets))
|
|
1461 goto lra_eliminate_done;
|
|
1462 if (lra_dump_file != NULL)
|
|
1463 {
|
|
1464 fprintf (lra_dump_file, "New elimination table:\n");
|
|
1465 print_elim_table (lra_dump_file);
|
|
1466 }
|
|
1467 EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
|
|
1468 /* A dead insn can be deleted in process_insn_for_elimination. */
|
|
1469 if (lra_insn_recog_data[uid] != NULL)
|
|
1470 process_insn_for_elimination (lra_insn_recog_data[uid]->insn,
|
|
1471 final_p, first_p);
|
|
1472 bitmap_clear (&insns_with_changed_offsets);
|
|
1473
|
|
1474 lra_eliminate_done:
|
|
1475 timevar_pop (TV_LRA_ELIMINATE);
|
|
1476 }
|