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