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