xref: /dflybsd-src/contrib/gcc-8.0/gcc/lra-eliminations.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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 < &reg_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 < &reg_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 < &reg_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 < &reg_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 < &reg_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 < &reg_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 = &REG_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 < &reg_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 < &reg_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, &reg_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 < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
1200*38fd1498Szrj     self_elim_offsets[ep->from] = 0;
1201*38fd1498Szrj   for (ep = reg_eliminate; ep < &reg_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 < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
1235*38fd1498Szrj 	    if (ep1->can_eliminate && ep1->from == ep->from)
1236*38fd1498Szrj 	      break;
1237*38fd1498Szrj 	  if (ep1 < &reg_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 < &reg_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 < &reg_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 < &reg_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 < &reg_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, &reg_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 < &reg_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