xref: /dragonfly/contrib/gcc-4.7/gcc/postreload.c (revision e4b17023)
1*e4b17023SJohn Marino /* Perform simple optimizations to clean up the result of reload.
2*e4b17023SJohn Marino    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
3*e4b17023SJohn Marino    1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4*e4b17023SJohn Marino    2010, 2011 Free Software Foundation, Inc.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #include "machmode.h"
28*e4b17023SJohn Marino #include "hard-reg-set.h"
29*e4b17023SJohn Marino #include "rtl.h"
30*e4b17023SJohn Marino #include "tm_p.h"
31*e4b17023SJohn Marino #include "obstack.h"
32*e4b17023SJohn Marino #include "insn-config.h"
33*e4b17023SJohn Marino #include "flags.h"
34*e4b17023SJohn Marino #include "function.h"
35*e4b17023SJohn Marino #include "expr.h"
36*e4b17023SJohn Marino #include "optabs.h"
37*e4b17023SJohn Marino #include "regs.h"
38*e4b17023SJohn Marino #include "basic-block.h"
39*e4b17023SJohn Marino #include "reload.h"
40*e4b17023SJohn Marino #include "recog.h"
41*e4b17023SJohn Marino #include "output.h"
42*e4b17023SJohn Marino #include "cselib.h"
43*e4b17023SJohn Marino #include "diagnostic-core.h"
44*e4b17023SJohn Marino #include "except.h"
45*e4b17023SJohn Marino #include "tree.h"
46*e4b17023SJohn Marino #include "target.h"
47*e4b17023SJohn Marino #include "timevar.h"
48*e4b17023SJohn Marino #include "tree-pass.h"
49*e4b17023SJohn Marino #include "df.h"
50*e4b17023SJohn Marino #include "dbgcnt.h"
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino static int reload_cse_noop_set_p (rtx);
53*e4b17023SJohn Marino static void reload_cse_simplify (rtx, rtx);
54*e4b17023SJohn Marino static void reload_cse_regs_1 (rtx);
55*e4b17023SJohn Marino static int reload_cse_simplify_set (rtx, rtx);
56*e4b17023SJohn Marino static int reload_cse_simplify_operands (rtx, rtx);
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino static void reload_combine (void);
59*e4b17023SJohn Marino static void reload_combine_note_use (rtx *, rtx, int, rtx);
60*e4b17023SJohn Marino static void reload_combine_note_store (rtx, const_rtx, void *);
61*e4b17023SJohn Marino 
62*e4b17023SJohn Marino static bool reload_cse_move2add (rtx);
63*e4b17023SJohn Marino static void move2add_note_store (rtx, const_rtx, void *);
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino /* Call cse / combine like post-reload optimization phases.
66*e4b17023SJohn Marino    FIRST is the first instruction.  */
67*e4b17023SJohn Marino void
reload_cse_regs(rtx first ATTRIBUTE_UNUSED)68*e4b17023SJohn Marino reload_cse_regs (rtx first ATTRIBUTE_UNUSED)
69*e4b17023SJohn Marino {
70*e4b17023SJohn Marino   bool moves_converted;
71*e4b17023SJohn Marino   reload_cse_regs_1 (first);
72*e4b17023SJohn Marino   reload_combine ();
73*e4b17023SJohn Marino   moves_converted = reload_cse_move2add (first);
74*e4b17023SJohn Marino   if (flag_expensive_optimizations)
75*e4b17023SJohn Marino     {
76*e4b17023SJohn Marino       if (moves_converted)
77*e4b17023SJohn Marino 	reload_combine ();
78*e4b17023SJohn Marino       reload_cse_regs_1 (first);
79*e4b17023SJohn Marino     }
80*e4b17023SJohn Marino }
81*e4b17023SJohn Marino 
82*e4b17023SJohn Marino /* See whether a single set SET is a noop.  */
83*e4b17023SJohn Marino static int
reload_cse_noop_set_p(rtx set)84*e4b17023SJohn Marino reload_cse_noop_set_p (rtx set)
85*e4b17023SJohn Marino {
86*e4b17023SJohn Marino   if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set)))
87*e4b17023SJohn Marino     return 0;
88*e4b17023SJohn Marino 
89*e4b17023SJohn Marino   return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
90*e4b17023SJohn Marino }
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino /* Try to simplify INSN.  */
93*e4b17023SJohn Marino static void
reload_cse_simplify(rtx insn,rtx testreg)94*e4b17023SJohn Marino reload_cse_simplify (rtx insn, rtx testreg)
95*e4b17023SJohn Marino {
96*e4b17023SJohn Marino   rtx body = PATTERN (insn);
97*e4b17023SJohn Marino 
98*e4b17023SJohn Marino   if (GET_CODE (body) == SET)
99*e4b17023SJohn Marino     {
100*e4b17023SJohn Marino       int count = 0;
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino       /* Simplify even if we may think it is a no-op.
103*e4b17023SJohn Marino          We may think a memory load of a value smaller than WORD_SIZE
104*e4b17023SJohn Marino          is redundant because we haven't taken into account possible
105*e4b17023SJohn Marino          implicit extension.  reload_cse_simplify_set() will bring
106*e4b17023SJohn Marino          this out, so it's safer to simplify before we delete.  */
107*e4b17023SJohn Marino       count += reload_cse_simplify_set (body, insn);
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino       if (!count && reload_cse_noop_set_p (body))
110*e4b17023SJohn Marino 	{
111*e4b17023SJohn Marino 	  rtx value = SET_DEST (body);
112*e4b17023SJohn Marino 	  if (REG_P (value)
113*e4b17023SJohn Marino 	      && ! REG_FUNCTION_VALUE_P (value))
114*e4b17023SJohn Marino 	    value = 0;
115*e4b17023SJohn Marino 	  if (check_for_inc_dec (insn))
116*e4b17023SJohn Marino 	    delete_insn_and_edges (insn);
117*e4b17023SJohn Marino 	  return;
118*e4b17023SJohn Marino 	}
119*e4b17023SJohn Marino 
120*e4b17023SJohn Marino       if (count > 0)
121*e4b17023SJohn Marino 	apply_change_group ();
122*e4b17023SJohn Marino       else
123*e4b17023SJohn Marino 	reload_cse_simplify_operands (insn, testreg);
124*e4b17023SJohn Marino     }
125*e4b17023SJohn Marino   else if (GET_CODE (body) == PARALLEL)
126*e4b17023SJohn Marino     {
127*e4b17023SJohn Marino       int i;
128*e4b17023SJohn Marino       int count = 0;
129*e4b17023SJohn Marino       rtx value = NULL_RTX;
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino       /* Registers mentioned in the clobber list for an asm cannot be reused
132*e4b17023SJohn Marino 	 within the body of the asm.  Invalidate those registers now so that
133*e4b17023SJohn Marino 	 we don't try to substitute values for them.  */
134*e4b17023SJohn Marino       if (asm_noperands (body) >= 0)
135*e4b17023SJohn Marino 	{
136*e4b17023SJohn Marino 	  for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
137*e4b17023SJohn Marino 	    {
138*e4b17023SJohn Marino 	      rtx part = XVECEXP (body, 0, i);
139*e4b17023SJohn Marino 	      if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
140*e4b17023SJohn Marino 		cselib_invalidate_rtx (XEXP (part, 0));
141*e4b17023SJohn Marino 	    }
142*e4b17023SJohn Marino 	}
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino       /* If every action in a PARALLEL is a noop, we can delete
145*e4b17023SJohn Marino 	 the entire PARALLEL.  */
146*e4b17023SJohn Marino       for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
147*e4b17023SJohn Marino 	{
148*e4b17023SJohn Marino 	  rtx part = XVECEXP (body, 0, i);
149*e4b17023SJohn Marino 	  if (GET_CODE (part) == SET)
150*e4b17023SJohn Marino 	    {
151*e4b17023SJohn Marino 	      if (! reload_cse_noop_set_p (part))
152*e4b17023SJohn Marino 		break;
153*e4b17023SJohn Marino 	      if (REG_P (SET_DEST (part))
154*e4b17023SJohn Marino 		  && REG_FUNCTION_VALUE_P (SET_DEST (part)))
155*e4b17023SJohn Marino 		{
156*e4b17023SJohn Marino 		  if (value)
157*e4b17023SJohn Marino 		    break;
158*e4b17023SJohn Marino 		  value = SET_DEST (part);
159*e4b17023SJohn Marino 		}
160*e4b17023SJohn Marino 	    }
161*e4b17023SJohn Marino 	  else if (GET_CODE (part) != CLOBBER)
162*e4b17023SJohn Marino 	    break;
163*e4b17023SJohn Marino 	}
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino       if (i < 0)
166*e4b17023SJohn Marino 	{
167*e4b17023SJohn Marino 	  if (check_for_inc_dec (insn))
168*e4b17023SJohn Marino 	    delete_insn_and_edges (insn);
169*e4b17023SJohn Marino 	  /* We're done with this insn.  */
170*e4b17023SJohn Marino 	  return;
171*e4b17023SJohn Marino 	}
172*e4b17023SJohn Marino 
173*e4b17023SJohn Marino       /* It's not a no-op, but we can try to simplify it.  */
174*e4b17023SJohn Marino       for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
175*e4b17023SJohn Marino 	if (GET_CODE (XVECEXP (body, 0, i)) == SET)
176*e4b17023SJohn Marino 	  count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
177*e4b17023SJohn Marino 
178*e4b17023SJohn Marino       if (count > 0)
179*e4b17023SJohn Marino 	apply_change_group ();
180*e4b17023SJohn Marino       else
181*e4b17023SJohn Marino 	reload_cse_simplify_operands (insn, testreg);
182*e4b17023SJohn Marino     }
183*e4b17023SJohn Marino }
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino /* Do a very simple CSE pass over the hard registers.
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino    This function detects no-op moves where we happened to assign two
188*e4b17023SJohn Marino    different pseudo-registers to the same hard register, and then
189*e4b17023SJohn Marino    copied one to the other.  Reload will generate a useless
190*e4b17023SJohn Marino    instruction copying a register to itself.
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino    This function also detects cases where we load a value from memory
193*e4b17023SJohn Marino    into two different registers, and (if memory is more expensive than
194*e4b17023SJohn Marino    registers) changes it to simply copy the first register into the
195*e4b17023SJohn Marino    second register.
196*e4b17023SJohn Marino 
197*e4b17023SJohn Marino    Another optimization is performed that scans the operands of each
198*e4b17023SJohn Marino    instruction to see whether the value is already available in a
199*e4b17023SJohn Marino    hard register.  It then replaces the operand with the hard register
200*e4b17023SJohn Marino    if possible, much like an optional reload would.  */
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino static void
reload_cse_regs_1(rtx first)203*e4b17023SJohn Marino reload_cse_regs_1 (rtx first)
204*e4b17023SJohn Marino {
205*e4b17023SJohn Marino   rtx insn;
206*e4b17023SJohn Marino   rtx testreg = gen_rtx_REG (VOIDmode, -1);
207*e4b17023SJohn Marino 
208*e4b17023SJohn Marino   cselib_init (CSELIB_RECORD_MEMORY);
209*e4b17023SJohn Marino   init_alias_analysis ();
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino   for (insn = first; insn; insn = NEXT_INSN (insn))
212*e4b17023SJohn Marino     {
213*e4b17023SJohn Marino       if (INSN_P (insn))
214*e4b17023SJohn Marino 	reload_cse_simplify (insn, testreg);
215*e4b17023SJohn Marino 
216*e4b17023SJohn Marino       cselib_process_insn (insn);
217*e4b17023SJohn Marino     }
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   /* Clean up.  */
220*e4b17023SJohn Marino   end_alias_analysis ();
221*e4b17023SJohn Marino   cselib_finish ();
222*e4b17023SJohn Marino }
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino /* Try to simplify a single SET instruction.  SET is the set pattern.
225*e4b17023SJohn Marino    INSN is the instruction it came from.
226*e4b17023SJohn Marino    This function only handles one case: if we set a register to a value
227*e4b17023SJohn Marino    which is not a register, we try to find that value in some other register
228*e4b17023SJohn Marino    and change the set into a register copy.  */
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino static int
reload_cse_simplify_set(rtx set,rtx insn)231*e4b17023SJohn Marino reload_cse_simplify_set (rtx set, rtx insn)
232*e4b17023SJohn Marino {
233*e4b17023SJohn Marino   int did_change = 0;
234*e4b17023SJohn Marino   int dreg;
235*e4b17023SJohn Marino   rtx src;
236*e4b17023SJohn Marino   reg_class_t dclass;
237*e4b17023SJohn Marino   int old_cost;
238*e4b17023SJohn Marino   cselib_val *val;
239*e4b17023SJohn Marino   struct elt_loc_list *l;
240*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
241*e4b17023SJohn Marino   enum rtx_code extend_op = UNKNOWN;
242*e4b17023SJohn Marino #endif
243*e4b17023SJohn Marino   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino   dreg = true_regnum (SET_DEST (set));
246*e4b17023SJohn Marino   if (dreg < 0)
247*e4b17023SJohn Marino     return 0;
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino   src = SET_SRC (set);
250*e4b17023SJohn Marino   if (side_effects_p (src) || true_regnum (src) >= 0)
251*e4b17023SJohn Marino     return 0;
252*e4b17023SJohn Marino 
253*e4b17023SJohn Marino   dclass = REGNO_REG_CLASS (dreg);
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
256*e4b17023SJohn Marino   /* When replacing a memory with a register, we need to honor assumptions
257*e4b17023SJohn Marino      that combine made wrt the contents of sign bits.  We'll do this by
258*e4b17023SJohn Marino      generating an extend instruction instead of a reg->reg copy.  Thus
259*e4b17023SJohn Marino      the destination must be a register that we can widen.  */
260*e4b17023SJohn Marino   if (MEM_P (src)
261*e4b17023SJohn Marino       && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
262*e4b17023SJohn Marino       && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != UNKNOWN
263*e4b17023SJohn Marino       && !REG_P (SET_DEST (set)))
264*e4b17023SJohn Marino     return 0;
265*e4b17023SJohn Marino #endif
266*e4b17023SJohn Marino 
267*e4b17023SJohn Marino   val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0, VOIDmode);
268*e4b17023SJohn Marino   if (! val)
269*e4b17023SJohn Marino     return 0;
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino   /* If memory loads are cheaper than register copies, don't change them.  */
272*e4b17023SJohn Marino   if (MEM_P (src))
273*e4b17023SJohn Marino     old_cost = memory_move_cost (GET_MODE (src), dclass, true);
274*e4b17023SJohn Marino   else if (REG_P (src))
275*e4b17023SJohn Marino     old_cost = register_move_cost (GET_MODE (src),
276*e4b17023SJohn Marino 				   REGNO_REG_CLASS (REGNO (src)), dclass);
277*e4b17023SJohn Marino   else
278*e4b17023SJohn Marino     old_cost = set_src_cost (src, speed);
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino   for (l = val->locs; l; l = l->next)
281*e4b17023SJohn Marino     {
282*e4b17023SJohn Marino       rtx this_rtx = l->loc;
283*e4b17023SJohn Marino       int this_cost;
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino       if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
286*e4b17023SJohn Marino 	{
287*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
288*e4b17023SJohn Marino 	  if (extend_op != UNKNOWN)
289*e4b17023SJohn Marino 	    {
290*e4b17023SJohn Marino 	      HOST_WIDE_INT this_val;
291*e4b17023SJohn Marino 
292*e4b17023SJohn Marino 	      /* ??? I'm lazy and don't wish to handle CONST_DOUBLE.  Other
293*e4b17023SJohn Marino 		 constants, such as SYMBOL_REF, cannot be extended.  */
294*e4b17023SJohn Marino 	      if (!CONST_INT_P (this_rtx))
295*e4b17023SJohn Marino 		continue;
296*e4b17023SJohn Marino 
297*e4b17023SJohn Marino 	      this_val = INTVAL (this_rtx);
298*e4b17023SJohn Marino 	      switch (extend_op)
299*e4b17023SJohn Marino 		{
300*e4b17023SJohn Marino 		case ZERO_EXTEND:
301*e4b17023SJohn Marino 		  this_val &= GET_MODE_MASK (GET_MODE (src));
302*e4b17023SJohn Marino 		  break;
303*e4b17023SJohn Marino 		case SIGN_EXTEND:
304*e4b17023SJohn Marino 		  /* ??? In theory we're already extended.  */
305*e4b17023SJohn Marino 		  if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
306*e4b17023SJohn Marino 		    break;
307*e4b17023SJohn Marino 		default:
308*e4b17023SJohn Marino 		  gcc_unreachable ();
309*e4b17023SJohn Marino 		}
310*e4b17023SJohn Marino 	      this_rtx = GEN_INT (this_val);
311*e4b17023SJohn Marino 	    }
312*e4b17023SJohn Marino #endif
313*e4b17023SJohn Marino 	  this_cost = set_src_cost (this_rtx, speed);
314*e4b17023SJohn Marino 	}
315*e4b17023SJohn Marino       else if (REG_P (this_rtx))
316*e4b17023SJohn Marino 	{
317*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
318*e4b17023SJohn Marino 	  if (extend_op != UNKNOWN)
319*e4b17023SJohn Marino 	    {
320*e4b17023SJohn Marino 	      this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
321*e4b17023SJohn Marino 	      this_cost = set_src_cost (this_rtx, speed);
322*e4b17023SJohn Marino 	    }
323*e4b17023SJohn Marino 	  else
324*e4b17023SJohn Marino #endif
325*e4b17023SJohn Marino 	    this_cost = register_move_cost (GET_MODE (this_rtx),
326*e4b17023SJohn Marino 					    REGNO_REG_CLASS (REGNO (this_rtx)),
327*e4b17023SJohn Marino 					    dclass);
328*e4b17023SJohn Marino 	}
329*e4b17023SJohn Marino       else
330*e4b17023SJohn Marino 	continue;
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino       /* If equal costs, prefer registers over anything else.  That
333*e4b17023SJohn Marino 	 tends to lead to smaller instructions on some machines.  */
334*e4b17023SJohn Marino       if (this_cost < old_cost
335*e4b17023SJohn Marino 	  || (this_cost == old_cost
336*e4b17023SJohn Marino 	      && REG_P (this_rtx)
337*e4b17023SJohn Marino 	      && !REG_P (SET_SRC (set))))
338*e4b17023SJohn Marino 	{
339*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
340*e4b17023SJohn Marino 	  if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
341*e4b17023SJohn Marino 	      && extend_op != UNKNOWN
342*e4b17023SJohn Marino #ifdef CANNOT_CHANGE_MODE_CLASS
343*e4b17023SJohn Marino 	      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
344*e4b17023SJohn Marino 					    word_mode,
345*e4b17023SJohn Marino 					    REGNO_REG_CLASS (REGNO (SET_DEST (set))))
346*e4b17023SJohn Marino #endif
347*e4b17023SJohn Marino 	      )
348*e4b17023SJohn Marino 	    {
349*e4b17023SJohn Marino 	      rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
350*e4b17023SJohn Marino 	      ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
351*e4b17023SJohn Marino 	      validate_change (insn, &SET_DEST (set), wide_dest, 1);
352*e4b17023SJohn Marino 	    }
353*e4b17023SJohn Marino #endif
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino 	  validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1);
356*e4b17023SJohn Marino 	  old_cost = this_cost, did_change = 1;
357*e4b17023SJohn Marino 	}
358*e4b17023SJohn Marino     }
359*e4b17023SJohn Marino 
360*e4b17023SJohn Marino   return did_change;
361*e4b17023SJohn Marino }
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino /* Try to replace operands in INSN with equivalent values that are already
364*e4b17023SJohn Marino    in registers.  This can be viewed as optional reloading.
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino    For each non-register operand in the insn, see if any hard regs are
367*e4b17023SJohn Marino    known to be equivalent to that operand.  Record the alternatives which
368*e4b17023SJohn Marino    can accept these hard registers.  Among all alternatives, select the
369*e4b17023SJohn Marino    ones which are better or equal to the one currently matching, where
370*e4b17023SJohn Marino    "better" is in terms of '?' and '!' constraints.  Among the remaining
371*e4b17023SJohn Marino    alternatives, select the one which replaces most operands with
372*e4b17023SJohn Marino    hard registers.  */
373*e4b17023SJohn Marino 
374*e4b17023SJohn Marino static int
reload_cse_simplify_operands(rtx insn,rtx testreg)375*e4b17023SJohn Marino reload_cse_simplify_operands (rtx insn, rtx testreg)
376*e4b17023SJohn Marino {
377*e4b17023SJohn Marino   int i, j;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino   /* For each operand, all registers that are equivalent to it.  */
380*e4b17023SJohn Marino   HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS];
381*e4b17023SJohn Marino 
382*e4b17023SJohn Marino   const char *constraints[MAX_RECOG_OPERANDS];
383*e4b17023SJohn Marino 
384*e4b17023SJohn Marino   /* Vector recording how bad an alternative is.  */
385*e4b17023SJohn Marino   int *alternative_reject;
386*e4b17023SJohn Marino   /* Vector recording how many registers can be introduced by choosing
387*e4b17023SJohn Marino      this alternative.  */
388*e4b17023SJohn Marino   int *alternative_nregs;
389*e4b17023SJohn Marino   /* Array of vectors recording, for each operand and each alternative,
390*e4b17023SJohn Marino      which hard register to substitute, or -1 if the operand should be
391*e4b17023SJohn Marino      left as it is.  */
392*e4b17023SJohn Marino   int *op_alt_regno[MAX_RECOG_OPERANDS];
393*e4b17023SJohn Marino   /* Array of alternatives, sorted in order of decreasing desirability.  */
394*e4b17023SJohn Marino   int *alternative_order;
395*e4b17023SJohn Marino 
396*e4b17023SJohn Marino   extract_insn (insn);
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino   if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
399*e4b17023SJohn Marino     return 0;
400*e4b17023SJohn Marino 
401*e4b17023SJohn Marino   /* Figure out which alternative currently matches.  */
402*e4b17023SJohn Marino   if (! constrain_operands (1))
403*e4b17023SJohn Marino     fatal_insn_not_found (insn);
404*e4b17023SJohn Marino 
405*e4b17023SJohn Marino   alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives);
406*e4b17023SJohn Marino   alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives);
407*e4b17023SJohn Marino   alternative_order = XALLOCAVEC (int, recog_data.n_alternatives);
408*e4b17023SJohn Marino   memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
409*e4b17023SJohn Marino   memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
410*e4b17023SJohn Marino 
411*e4b17023SJohn Marino   /* For each operand, find out which regs are equivalent.  */
412*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
413*e4b17023SJohn Marino     {
414*e4b17023SJohn Marino       cselib_val *v;
415*e4b17023SJohn Marino       struct elt_loc_list *l;
416*e4b17023SJohn Marino       rtx op;
417*e4b17023SJohn Marino 
418*e4b17023SJohn Marino       CLEAR_HARD_REG_SET (equiv_regs[i]);
419*e4b17023SJohn Marino 
420*e4b17023SJohn Marino       /* cselib blows up on CODE_LABELs.  Trying to fix that doesn't seem
421*e4b17023SJohn Marino 	 right, so avoid the problem here.  Likewise if we have a constant
422*e4b17023SJohn Marino          and the insn pattern doesn't tell us the mode we need.  */
423*e4b17023SJohn Marino       if (LABEL_P (recog_data.operand[i])
424*e4b17023SJohn Marino 	  || (CONSTANT_P (recog_data.operand[i])
425*e4b17023SJohn Marino 	      && recog_data.operand_mode[i] == VOIDmode))
426*e4b17023SJohn Marino 	continue;
427*e4b17023SJohn Marino 
428*e4b17023SJohn Marino       op = recog_data.operand[i];
429*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
430*e4b17023SJohn Marino       if (MEM_P (op)
431*e4b17023SJohn Marino 	  && GET_MODE_BITSIZE (GET_MODE (op)) < BITS_PER_WORD
432*e4b17023SJohn Marino 	  && LOAD_EXTEND_OP (GET_MODE (op)) != UNKNOWN)
433*e4b17023SJohn Marino 	{
434*e4b17023SJohn Marino 	  rtx set = single_set (insn);
435*e4b17023SJohn Marino 
436*e4b17023SJohn Marino 	  /* We might have multiple sets, some of which do implicit
437*e4b17023SJohn Marino 	     extension.  Punt on this for now.  */
438*e4b17023SJohn Marino 	  if (! set)
439*e4b17023SJohn Marino 	    continue;
440*e4b17023SJohn Marino 	  /* If the destination is also a MEM or a STRICT_LOW_PART, no
441*e4b17023SJohn Marino 	     extension applies.
442*e4b17023SJohn Marino 	     Also, if there is an explicit extension, we don't have to
443*e4b17023SJohn Marino 	     worry about an implicit one.  */
444*e4b17023SJohn Marino 	  else if (MEM_P (SET_DEST (set))
445*e4b17023SJohn Marino 		   || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART
446*e4b17023SJohn Marino 		   || GET_CODE (SET_SRC (set)) == ZERO_EXTEND
447*e4b17023SJohn Marino 		   || GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
448*e4b17023SJohn Marino 	    ; /* Continue ordinary processing.  */
449*e4b17023SJohn Marino #ifdef CANNOT_CHANGE_MODE_CLASS
450*e4b17023SJohn Marino 	  /* If the register cannot change mode to word_mode, it follows that
451*e4b17023SJohn Marino 	     it cannot have been used in word_mode.  */
452*e4b17023SJohn Marino 	  else if (REG_P (SET_DEST (set))
453*e4b17023SJohn Marino 		   && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
454*e4b17023SJohn Marino 						word_mode,
455*e4b17023SJohn Marino 						REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
456*e4b17023SJohn Marino 	    ; /* Continue ordinary processing.  */
457*e4b17023SJohn Marino #endif
458*e4b17023SJohn Marino 	  /* If this is a straight load, make the extension explicit.  */
459*e4b17023SJohn Marino 	  else if (REG_P (SET_DEST (set))
460*e4b17023SJohn Marino 		   && recog_data.n_operands == 2
461*e4b17023SJohn Marino 		   && SET_SRC (set) == op
462*e4b17023SJohn Marino 		   && SET_DEST (set) == recog_data.operand[1-i])
463*e4b17023SJohn Marino 	    {
464*e4b17023SJohn Marino 	      validate_change (insn, recog_data.operand_loc[i],
465*e4b17023SJohn Marino 			       gen_rtx_fmt_e (LOAD_EXTEND_OP (GET_MODE (op)),
466*e4b17023SJohn Marino 					      word_mode, op),
467*e4b17023SJohn Marino 			       1);
468*e4b17023SJohn Marino 	      validate_change (insn, recog_data.operand_loc[1-i],
469*e4b17023SJohn Marino 			       gen_rtx_REG (word_mode, REGNO (SET_DEST (set))),
470*e4b17023SJohn Marino 			       1);
471*e4b17023SJohn Marino 	      if (! apply_change_group ())
472*e4b17023SJohn Marino 		return 0;
473*e4b17023SJohn Marino 	      return reload_cse_simplify_operands (insn, testreg);
474*e4b17023SJohn Marino 	    }
475*e4b17023SJohn Marino 	  else
476*e4b17023SJohn Marino 	    /* ??? There might be arithmetic operations with memory that are
477*e4b17023SJohn Marino 	       safe to optimize, but is it worth the trouble?  */
478*e4b17023SJohn Marino 	    continue;
479*e4b17023SJohn Marino 	}
480*e4b17023SJohn Marino #endif /* LOAD_EXTEND_OP */
481*e4b17023SJohn Marino       if (side_effects_p (op))
482*e4b17023SJohn Marino 	continue;
483*e4b17023SJohn Marino       v = cselib_lookup (op, recog_data.operand_mode[i], 0, VOIDmode);
484*e4b17023SJohn Marino       if (! v)
485*e4b17023SJohn Marino 	continue;
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino       for (l = v->locs; l; l = l->next)
488*e4b17023SJohn Marino 	if (REG_P (l->loc))
489*e4b17023SJohn Marino 	  SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
490*e4b17023SJohn Marino     }
491*e4b17023SJohn Marino 
492*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
493*e4b17023SJohn Marino     {
494*e4b17023SJohn Marino       enum machine_mode mode;
495*e4b17023SJohn Marino       int regno;
496*e4b17023SJohn Marino       const char *p;
497*e4b17023SJohn Marino 
498*e4b17023SJohn Marino       op_alt_regno[i] = XALLOCAVEC (int, recog_data.n_alternatives);
499*e4b17023SJohn Marino       for (j = 0; j < recog_data.n_alternatives; j++)
500*e4b17023SJohn Marino 	op_alt_regno[i][j] = -1;
501*e4b17023SJohn Marino 
502*e4b17023SJohn Marino       p = constraints[i] = recog_data.constraints[i];
503*e4b17023SJohn Marino       mode = recog_data.operand_mode[i];
504*e4b17023SJohn Marino 
505*e4b17023SJohn Marino       /* Add the reject values for each alternative given by the constraints
506*e4b17023SJohn Marino 	 for this operand.  */
507*e4b17023SJohn Marino       j = 0;
508*e4b17023SJohn Marino       while (*p != '\0')
509*e4b17023SJohn Marino 	{
510*e4b17023SJohn Marino 	  char c = *p++;
511*e4b17023SJohn Marino 	  if (c == ',')
512*e4b17023SJohn Marino 	    j++;
513*e4b17023SJohn Marino 	  else if (c == '?')
514*e4b17023SJohn Marino 	    alternative_reject[j] += 3;
515*e4b17023SJohn Marino 	  else if (c == '!')
516*e4b17023SJohn Marino 	    alternative_reject[j] += 300;
517*e4b17023SJohn Marino 	}
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino       /* We won't change operands which are already registers.  We
520*e4b17023SJohn Marino 	 also don't want to modify output operands.  */
521*e4b17023SJohn Marino       regno = true_regnum (recog_data.operand[i]);
522*e4b17023SJohn Marino       if (regno >= 0
523*e4b17023SJohn Marino 	  || constraints[i][0] == '='
524*e4b17023SJohn Marino 	  || constraints[i][0] == '+')
525*e4b17023SJohn Marino 	continue;
526*e4b17023SJohn Marino 
527*e4b17023SJohn Marino       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
528*e4b17023SJohn Marino 	{
529*e4b17023SJohn Marino 	  enum reg_class rclass = NO_REGS;
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino 	  if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
532*e4b17023SJohn Marino 	    continue;
533*e4b17023SJohn Marino 
534*e4b17023SJohn Marino 	  SET_REGNO_RAW (testreg, regno);
535*e4b17023SJohn Marino 	  PUT_MODE (testreg, mode);
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino 	  /* We found a register equal to this operand.  Now look for all
538*e4b17023SJohn Marino 	     alternatives that can accept this register and have not been
539*e4b17023SJohn Marino 	     assigned a register they can use yet.  */
540*e4b17023SJohn Marino 	  j = 0;
541*e4b17023SJohn Marino 	  p = constraints[i];
542*e4b17023SJohn Marino 	  for (;;)
543*e4b17023SJohn Marino 	    {
544*e4b17023SJohn Marino 	      char c = *p;
545*e4b17023SJohn Marino 
546*e4b17023SJohn Marino 	      switch (c)
547*e4b17023SJohn Marino 		{
548*e4b17023SJohn Marino 		case '=':  case '+':  case '?':
549*e4b17023SJohn Marino 		case '#':  case '&':  case '!':
550*e4b17023SJohn Marino 		case '*':  case '%':
551*e4b17023SJohn Marino 		case '0':  case '1':  case '2':  case '3':  case '4':
552*e4b17023SJohn Marino 		case '5':  case '6':  case '7':  case '8':  case '9':
553*e4b17023SJohn Marino 		case '<':  case '>':  case 'V':  case 'o':
554*e4b17023SJohn Marino 		case 'E':  case 'F':  case 'G':  case 'H':
555*e4b17023SJohn Marino 		case 's':  case 'i':  case 'n':
556*e4b17023SJohn Marino 		case 'I':  case 'J':  case 'K':  case 'L':
557*e4b17023SJohn Marino 		case 'M':  case 'N':  case 'O':  case 'P':
558*e4b17023SJohn Marino 		case 'p':  case 'X':  case TARGET_MEM_CONSTRAINT:
559*e4b17023SJohn Marino 		  /* These don't say anything we care about.  */
560*e4b17023SJohn Marino 		  break;
561*e4b17023SJohn Marino 
562*e4b17023SJohn Marino 		case 'g': case 'r':
563*e4b17023SJohn Marino 		  rclass = reg_class_subunion[(int) rclass][(int) GENERAL_REGS];
564*e4b17023SJohn Marino 		  break;
565*e4b17023SJohn Marino 
566*e4b17023SJohn Marino 		default:
567*e4b17023SJohn Marino 		  rclass
568*e4b17023SJohn Marino 		    = (reg_class_subunion
569*e4b17023SJohn Marino 		       [(int) rclass]
570*e4b17023SJohn Marino 		       [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
571*e4b17023SJohn Marino 		  break;
572*e4b17023SJohn Marino 
573*e4b17023SJohn Marino 		case ',': case '\0':
574*e4b17023SJohn Marino 		  /* See if REGNO fits this alternative, and set it up as the
575*e4b17023SJohn Marino 		     replacement register if we don't have one for this
576*e4b17023SJohn Marino 		     alternative yet and the operand being replaced is not
577*e4b17023SJohn Marino 		     a cheap CONST_INT.  */
578*e4b17023SJohn Marino 		  if (op_alt_regno[i][j] == -1
579*e4b17023SJohn Marino 		      && recog_data.alternative_enabled_p[j]
580*e4b17023SJohn Marino 		      && reg_fits_class_p (testreg, rclass, 0, mode)
581*e4b17023SJohn Marino 		      && (!CONST_INT_P (recog_data.operand[i])
582*e4b17023SJohn Marino 			  || (set_src_cost (recog_data.operand[i],
583*e4b17023SJohn Marino 					    optimize_bb_for_speed_p
584*e4b17023SJohn Marino 					     (BLOCK_FOR_INSN (insn)))
585*e4b17023SJohn Marino 			      > set_src_cost (testreg,
586*e4b17023SJohn Marino 					      optimize_bb_for_speed_p
587*e4b17023SJohn Marino 					       (BLOCK_FOR_INSN (insn))))))
588*e4b17023SJohn Marino 		    {
589*e4b17023SJohn Marino 		      alternative_nregs[j]++;
590*e4b17023SJohn Marino 		      op_alt_regno[i][j] = regno;
591*e4b17023SJohn Marino 		    }
592*e4b17023SJohn Marino 		  j++;
593*e4b17023SJohn Marino 		  rclass = NO_REGS;
594*e4b17023SJohn Marino 		  break;
595*e4b17023SJohn Marino 		}
596*e4b17023SJohn Marino 	      p += CONSTRAINT_LEN (c, p);
597*e4b17023SJohn Marino 
598*e4b17023SJohn Marino 	      if (c == '\0')
599*e4b17023SJohn Marino 		break;
600*e4b17023SJohn Marino 	    }
601*e4b17023SJohn Marino 	}
602*e4b17023SJohn Marino     }
603*e4b17023SJohn Marino 
604*e4b17023SJohn Marino   /* Record all alternatives which are better or equal to the currently
605*e4b17023SJohn Marino      matching one in the alternative_order array.  */
606*e4b17023SJohn Marino   for (i = j = 0; i < recog_data.n_alternatives; i++)
607*e4b17023SJohn Marino     if (alternative_reject[i] <= alternative_reject[which_alternative])
608*e4b17023SJohn Marino       alternative_order[j++] = i;
609*e4b17023SJohn Marino   recog_data.n_alternatives = j;
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino   /* Sort it.  Given a small number of alternatives, a dumb algorithm
612*e4b17023SJohn Marino      won't hurt too much.  */
613*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_alternatives - 1; i++)
614*e4b17023SJohn Marino     {
615*e4b17023SJohn Marino       int best = i;
616*e4b17023SJohn Marino       int best_reject = alternative_reject[alternative_order[i]];
617*e4b17023SJohn Marino       int best_nregs = alternative_nregs[alternative_order[i]];
618*e4b17023SJohn Marino       int tmp;
619*e4b17023SJohn Marino 
620*e4b17023SJohn Marino       for (j = i + 1; j < recog_data.n_alternatives; j++)
621*e4b17023SJohn Marino 	{
622*e4b17023SJohn Marino 	  int this_reject = alternative_reject[alternative_order[j]];
623*e4b17023SJohn Marino 	  int this_nregs = alternative_nregs[alternative_order[j]];
624*e4b17023SJohn Marino 
625*e4b17023SJohn Marino 	  if (this_reject < best_reject
626*e4b17023SJohn Marino 	      || (this_reject == best_reject && this_nregs > best_nregs))
627*e4b17023SJohn Marino 	    {
628*e4b17023SJohn Marino 	      best = j;
629*e4b17023SJohn Marino 	      best_reject = this_reject;
630*e4b17023SJohn Marino 	      best_nregs = this_nregs;
631*e4b17023SJohn Marino 	    }
632*e4b17023SJohn Marino 	}
633*e4b17023SJohn Marino 
634*e4b17023SJohn Marino       tmp = alternative_order[best];
635*e4b17023SJohn Marino       alternative_order[best] = alternative_order[i];
636*e4b17023SJohn Marino       alternative_order[i] = tmp;
637*e4b17023SJohn Marino     }
638*e4b17023SJohn Marino 
639*e4b17023SJohn Marino   /* Substitute the operands as determined by op_alt_regno for the best
640*e4b17023SJohn Marino      alternative.  */
641*e4b17023SJohn Marino   j = alternative_order[0];
642*e4b17023SJohn Marino 
643*e4b17023SJohn Marino   for (i = 0; i < recog_data.n_operands; i++)
644*e4b17023SJohn Marino     {
645*e4b17023SJohn Marino       enum machine_mode mode = recog_data.operand_mode[i];
646*e4b17023SJohn Marino       if (op_alt_regno[i][j] == -1)
647*e4b17023SJohn Marino 	continue;
648*e4b17023SJohn Marino 
649*e4b17023SJohn Marino       validate_change (insn, recog_data.operand_loc[i],
650*e4b17023SJohn Marino 		       gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
651*e4b17023SJohn Marino     }
652*e4b17023SJohn Marino 
653*e4b17023SJohn Marino   for (i = recog_data.n_dups - 1; i >= 0; i--)
654*e4b17023SJohn Marino     {
655*e4b17023SJohn Marino       int op = recog_data.dup_num[i];
656*e4b17023SJohn Marino       enum machine_mode mode = recog_data.operand_mode[op];
657*e4b17023SJohn Marino 
658*e4b17023SJohn Marino       if (op_alt_regno[op][j] == -1)
659*e4b17023SJohn Marino 	continue;
660*e4b17023SJohn Marino 
661*e4b17023SJohn Marino       validate_change (insn, recog_data.dup_loc[i],
662*e4b17023SJohn Marino 		       gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
663*e4b17023SJohn Marino     }
664*e4b17023SJohn Marino 
665*e4b17023SJohn Marino   return apply_change_group ();
666*e4b17023SJohn Marino }
667*e4b17023SJohn Marino 
668*e4b17023SJohn Marino /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
669*e4b17023SJohn Marino    addressing now.
670*e4b17023SJohn Marino    This code might also be useful when reload gave up on reg+reg addressing
671*e4b17023SJohn Marino    because of clashes between the return register and INDEX_REG_CLASS.  */
672*e4b17023SJohn Marino 
673*e4b17023SJohn Marino /* The maximum number of uses of a register we can keep track of to
674*e4b17023SJohn Marino    replace them with reg+reg addressing.  */
675*e4b17023SJohn Marino #define RELOAD_COMBINE_MAX_USES 16
676*e4b17023SJohn Marino 
677*e4b17023SJohn Marino /* Describes a recorded use of a register.  */
678*e4b17023SJohn Marino struct reg_use
679*e4b17023SJohn Marino {
680*e4b17023SJohn Marino   /* The insn where a register has been used.  */
681*e4b17023SJohn Marino   rtx insn;
682*e4b17023SJohn Marino   /* Points to the memory reference enclosing the use, if any, NULL_RTX
683*e4b17023SJohn Marino      otherwise.  */
684*e4b17023SJohn Marino   rtx containing_mem;
685*e4b17023SJohn Marino   /* Location of the register withing INSN.  */
686*e4b17023SJohn Marino   rtx *usep;
687*e4b17023SJohn Marino   /* The reverse uid of the insn.  */
688*e4b17023SJohn Marino   int ruid;
689*e4b17023SJohn Marino };
690*e4b17023SJohn Marino 
691*e4b17023SJohn Marino /* If the register is used in some unknown fashion, USE_INDEX is negative.
692*e4b17023SJohn Marino    If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
693*e4b17023SJohn Marino    indicates where it is first set or clobbered.
694*e4b17023SJohn Marino    Otherwise, USE_INDEX is the index of the last encountered use of the
695*e4b17023SJohn Marino    register (which is first among these we have seen since we scan backwards).
696*e4b17023SJohn Marino    USE_RUID indicates the first encountered, i.e. last, of these uses.
697*e4b17023SJohn Marino    If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS
698*e4b17023SJohn Marino    with a constant offset; OFFSET contains this constant in that case.
699*e4b17023SJohn Marino    STORE_RUID is always meaningful if we only want to use a value in a
700*e4b17023SJohn Marino    register in a different place: it denotes the next insn in the insn
701*e4b17023SJohn Marino    stream (i.e. the last encountered) that sets or clobbers the register.
702*e4b17023SJohn Marino    REAL_STORE_RUID is similar, but clobbers are ignored when updating it.  */
703*e4b17023SJohn Marino static struct
704*e4b17023SJohn Marino   {
705*e4b17023SJohn Marino     struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
706*e4b17023SJohn Marino     rtx offset;
707*e4b17023SJohn Marino     int use_index;
708*e4b17023SJohn Marino     int store_ruid;
709*e4b17023SJohn Marino     int real_store_ruid;
710*e4b17023SJohn Marino     int use_ruid;
711*e4b17023SJohn Marino     bool all_offsets_match;
712*e4b17023SJohn Marino   } reg_state[FIRST_PSEUDO_REGISTER];
713*e4b17023SJohn Marino 
714*e4b17023SJohn Marino /* Reverse linear uid.  This is increased in reload_combine while scanning
715*e4b17023SJohn Marino    the instructions from last to first.  It is used to set last_label_ruid
716*e4b17023SJohn Marino    and the store_ruid / use_ruid fields in reg_state.  */
717*e4b17023SJohn Marino static int reload_combine_ruid;
718*e4b17023SJohn Marino 
719*e4b17023SJohn Marino /* The RUID of the last label we encountered in reload_combine.  */
720*e4b17023SJohn Marino static int last_label_ruid;
721*e4b17023SJohn Marino 
722*e4b17023SJohn Marino /* The RUID of the last jump we encountered in reload_combine.  */
723*e4b17023SJohn Marino static int last_jump_ruid;
724*e4b17023SJohn Marino 
725*e4b17023SJohn Marino /* The register numbers of the first and last index register.  A value of
726*e4b17023SJohn Marino    -1 in LAST_INDEX_REG indicates that we've previously computed these
727*e4b17023SJohn Marino    values and found no suitable index registers.  */
728*e4b17023SJohn Marino static int first_index_reg = -1;
729*e4b17023SJohn Marino static int last_index_reg;
730*e4b17023SJohn Marino 
731*e4b17023SJohn Marino #define LABEL_LIVE(LABEL) \
732*e4b17023SJohn Marino   (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
733*e4b17023SJohn Marino 
734*e4b17023SJohn Marino /* Subroutine of reload_combine_split_ruids, called to fix up a single
735*e4b17023SJohn Marino    ruid pointed to by *PRUID if it is higher than SPLIT_RUID.  */
736*e4b17023SJohn Marino 
737*e4b17023SJohn Marino static inline void
reload_combine_split_one_ruid(int * pruid,int split_ruid)738*e4b17023SJohn Marino reload_combine_split_one_ruid (int *pruid, int split_ruid)
739*e4b17023SJohn Marino {
740*e4b17023SJohn Marino   if (*pruid > split_ruid)
741*e4b17023SJohn Marino     (*pruid)++;
742*e4b17023SJohn Marino }
743*e4b17023SJohn Marino 
744*e4b17023SJohn Marino /* Called when we insert a new insn in a position we've already passed in
745*e4b17023SJohn Marino    the scan.  Examine all our state, increasing all ruids that are higher
746*e4b17023SJohn Marino    than SPLIT_RUID by one in order to make room for a new insn.  */
747*e4b17023SJohn Marino 
748*e4b17023SJohn Marino static void
reload_combine_split_ruids(int split_ruid)749*e4b17023SJohn Marino reload_combine_split_ruids (int split_ruid)
750*e4b17023SJohn Marino {
751*e4b17023SJohn Marino   unsigned i;
752*e4b17023SJohn Marino 
753*e4b17023SJohn Marino   reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid);
754*e4b17023SJohn Marino   reload_combine_split_one_ruid (&last_label_ruid, split_ruid);
755*e4b17023SJohn Marino   reload_combine_split_one_ruid (&last_jump_ruid, split_ruid);
756*e4b17023SJohn Marino 
757*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
758*e4b17023SJohn Marino     {
759*e4b17023SJohn Marino       int j, idx = reg_state[i].use_index;
760*e4b17023SJohn Marino       reload_combine_split_one_ruid (&reg_state[i].use_ruid, split_ruid);
761*e4b17023SJohn Marino       reload_combine_split_one_ruid (&reg_state[i].store_ruid, split_ruid);
762*e4b17023SJohn Marino       reload_combine_split_one_ruid (&reg_state[i].real_store_ruid,
763*e4b17023SJohn Marino 				     split_ruid);
764*e4b17023SJohn Marino       if (idx < 0)
765*e4b17023SJohn Marino 	continue;
766*e4b17023SJohn Marino       for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++)
767*e4b17023SJohn Marino 	{
768*e4b17023SJohn Marino 	  reload_combine_split_one_ruid (&reg_state[i].reg_use[j].ruid,
769*e4b17023SJohn Marino 					 split_ruid);
770*e4b17023SJohn Marino 	}
771*e4b17023SJohn Marino     }
772*e4b17023SJohn Marino }
773*e4b17023SJohn Marino 
774*e4b17023SJohn Marino /* Called when we are about to rescan a previously encountered insn with
775*e4b17023SJohn Marino    reload_combine_note_use after modifying some part of it.  This clears all
776*e4b17023SJohn Marino    information about uses in that particular insn.  */
777*e4b17023SJohn Marino 
778*e4b17023SJohn Marino static void
reload_combine_purge_insn_uses(rtx insn)779*e4b17023SJohn Marino reload_combine_purge_insn_uses (rtx insn)
780*e4b17023SJohn Marino {
781*e4b17023SJohn Marino   unsigned i;
782*e4b17023SJohn Marino 
783*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
784*e4b17023SJohn Marino     {
785*e4b17023SJohn Marino       int j, k, idx = reg_state[i].use_index;
786*e4b17023SJohn Marino       if (idx < 0)
787*e4b17023SJohn Marino 	continue;
788*e4b17023SJohn Marino       j = k = RELOAD_COMBINE_MAX_USES;
789*e4b17023SJohn Marino       while (j-- > idx)
790*e4b17023SJohn Marino 	{
791*e4b17023SJohn Marino 	  if (reg_state[i].reg_use[j].insn != insn)
792*e4b17023SJohn Marino 	    {
793*e4b17023SJohn Marino 	      k--;
794*e4b17023SJohn Marino 	      if (k != j)
795*e4b17023SJohn Marino 		reg_state[i].reg_use[k] = reg_state[i].reg_use[j];
796*e4b17023SJohn Marino 	    }
797*e4b17023SJohn Marino 	}
798*e4b17023SJohn Marino       reg_state[i].use_index = k;
799*e4b17023SJohn Marino     }
800*e4b17023SJohn Marino }
801*e4b17023SJohn Marino 
802*e4b17023SJohn Marino /* Called when we need to forget about all uses of REGNO after an insn
803*e4b17023SJohn Marino    which is identified by RUID.  */
804*e4b17023SJohn Marino 
805*e4b17023SJohn Marino static void
reload_combine_purge_reg_uses_after_ruid(unsigned regno,int ruid)806*e4b17023SJohn Marino reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid)
807*e4b17023SJohn Marino {
808*e4b17023SJohn Marino   int j, k, idx = reg_state[regno].use_index;
809*e4b17023SJohn Marino   if (idx < 0)
810*e4b17023SJohn Marino     return;
811*e4b17023SJohn Marino   j = k = RELOAD_COMBINE_MAX_USES;
812*e4b17023SJohn Marino   while (j-- > idx)
813*e4b17023SJohn Marino     {
814*e4b17023SJohn Marino       if (reg_state[regno].reg_use[j].ruid >= ruid)
815*e4b17023SJohn Marino 	{
816*e4b17023SJohn Marino 	  k--;
817*e4b17023SJohn Marino 	  if (k != j)
818*e4b17023SJohn Marino 	    reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j];
819*e4b17023SJohn Marino 	}
820*e4b17023SJohn Marino     }
821*e4b17023SJohn Marino   reg_state[regno].use_index = k;
822*e4b17023SJohn Marino }
823*e4b17023SJohn Marino 
824*e4b17023SJohn Marino /* Find the use of REGNO with the ruid that is highest among those
825*e4b17023SJohn Marino    lower than RUID_LIMIT, and return it if it is the only use of this
826*e4b17023SJohn Marino    reg in the insn.  Return NULL otherwise.  */
827*e4b17023SJohn Marino 
828*e4b17023SJohn Marino static struct reg_use *
reload_combine_closest_single_use(unsigned regno,int ruid_limit)829*e4b17023SJohn Marino reload_combine_closest_single_use (unsigned regno, int ruid_limit)
830*e4b17023SJohn Marino {
831*e4b17023SJohn Marino   int i, best_ruid = 0;
832*e4b17023SJohn Marino   int use_idx = reg_state[regno].use_index;
833*e4b17023SJohn Marino   struct reg_use *retval;
834*e4b17023SJohn Marino 
835*e4b17023SJohn Marino   if (use_idx < 0)
836*e4b17023SJohn Marino     return NULL;
837*e4b17023SJohn Marino   retval = NULL;
838*e4b17023SJohn Marino   for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++)
839*e4b17023SJohn Marino     {
840*e4b17023SJohn Marino       struct reg_use *use = reg_state[regno].reg_use + i;
841*e4b17023SJohn Marino       int this_ruid = use->ruid;
842*e4b17023SJohn Marino       if (this_ruid >= ruid_limit)
843*e4b17023SJohn Marino 	continue;
844*e4b17023SJohn Marino       if (this_ruid > best_ruid)
845*e4b17023SJohn Marino 	{
846*e4b17023SJohn Marino 	  best_ruid = this_ruid;
847*e4b17023SJohn Marino 	  retval = use;
848*e4b17023SJohn Marino 	}
849*e4b17023SJohn Marino       else if (this_ruid == best_ruid)
850*e4b17023SJohn Marino 	retval = NULL;
851*e4b17023SJohn Marino     }
852*e4b17023SJohn Marino   if (last_label_ruid >= best_ruid)
853*e4b17023SJohn Marino     return NULL;
854*e4b17023SJohn Marino   return retval;
855*e4b17023SJohn Marino }
856*e4b17023SJohn Marino 
857*e4b17023SJohn Marino /* After we've moved an add insn, fix up any debug insns that occur
858*e4b17023SJohn Marino    between the old location of the add and the new location.  REG is
859*e4b17023SJohn Marino    the destination register of the add insn; REPLACEMENT is the
860*e4b17023SJohn Marino    SET_SRC of the add.  FROM and TO specify the range in which we
861*e4b17023SJohn Marino    should make this change on debug insns.  */
862*e4b17023SJohn Marino 
863*e4b17023SJohn Marino static void
fixup_debug_insns(rtx reg,rtx replacement,rtx from,rtx to)864*e4b17023SJohn Marino fixup_debug_insns (rtx reg, rtx replacement, rtx from, rtx to)
865*e4b17023SJohn Marino {
866*e4b17023SJohn Marino   rtx insn;
867*e4b17023SJohn Marino   for (insn = from; insn != to; insn = NEXT_INSN (insn))
868*e4b17023SJohn Marino     {
869*e4b17023SJohn Marino       rtx t;
870*e4b17023SJohn Marino 
871*e4b17023SJohn Marino       if (!DEBUG_INSN_P (insn))
872*e4b17023SJohn Marino 	continue;
873*e4b17023SJohn Marino 
874*e4b17023SJohn Marino       t = INSN_VAR_LOCATION_LOC (insn);
875*e4b17023SJohn Marino       t = simplify_replace_rtx (t, reg, replacement);
876*e4b17023SJohn Marino       validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0);
877*e4b17023SJohn Marino     }
878*e4b17023SJohn Marino }
879*e4b17023SJohn Marino 
880*e4b17023SJohn Marino /* Subroutine of reload_combine_recognize_const_pattern.  Try to replace REG
881*e4b17023SJohn Marino    with SRC in the insn described by USE, taking costs into account.  Return
882*e4b17023SJohn Marino    true if we made the replacement.  */
883*e4b17023SJohn Marino 
884*e4b17023SJohn Marino static bool
try_replace_in_use(struct reg_use * use,rtx reg,rtx src)885*e4b17023SJohn Marino try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
886*e4b17023SJohn Marino {
887*e4b17023SJohn Marino   rtx use_insn = use->insn;
888*e4b17023SJohn Marino   rtx mem = use->containing_mem;
889*e4b17023SJohn Marino   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
890*e4b17023SJohn Marino 
891*e4b17023SJohn Marino   if (mem != NULL_RTX)
892*e4b17023SJohn Marino     {
893*e4b17023SJohn Marino       addr_space_t as = MEM_ADDR_SPACE (mem);
894*e4b17023SJohn Marino       rtx oldaddr = XEXP (mem, 0);
895*e4b17023SJohn Marino       rtx newaddr = NULL_RTX;
896*e4b17023SJohn Marino       int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
897*e4b17023SJohn Marino       int new_cost;
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino       newaddr = simplify_replace_rtx (oldaddr, reg, src);
900*e4b17023SJohn Marino       if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
901*e4b17023SJohn Marino 	{
902*e4b17023SJohn Marino 	  XEXP (mem, 0) = newaddr;
903*e4b17023SJohn Marino 	  new_cost = address_cost (newaddr, GET_MODE (mem), as, speed);
904*e4b17023SJohn Marino 	  XEXP (mem, 0) = oldaddr;
905*e4b17023SJohn Marino 	  if (new_cost <= old_cost
906*e4b17023SJohn Marino 	      && validate_change (use_insn,
907*e4b17023SJohn Marino 				  &XEXP (mem, 0), newaddr, 0))
908*e4b17023SJohn Marino 	    return true;
909*e4b17023SJohn Marino 	}
910*e4b17023SJohn Marino     }
911*e4b17023SJohn Marino   else
912*e4b17023SJohn Marino     {
913*e4b17023SJohn Marino       rtx new_set = single_set (use_insn);
914*e4b17023SJohn Marino       if (new_set
915*e4b17023SJohn Marino 	  && REG_P (SET_DEST (new_set))
916*e4b17023SJohn Marino 	  && GET_CODE (SET_SRC (new_set)) == PLUS
917*e4b17023SJohn Marino 	  && REG_P (XEXP (SET_SRC (new_set), 0))
918*e4b17023SJohn Marino 	  && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
919*e4b17023SJohn Marino 	{
920*e4b17023SJohn Marino 	  rtx new_src;
921*e4b17023SJohn Marino 	  int old_cost = set_src_cost (SET_SRC (new_set), speed);
922*e4b17023SJohn Marino 
923*e4b17023SJohn Marino 	  gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
924*e4b17023SJohn Marino 	  new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
925*e4b17023SJohn Marino 
926*e4b17023SJohn Marino 	  if (set_src_cost (new_src, speed) <= old_cost
927*e4b17023SJohn Marino 	      && validate_change (use_insn, &SET_SRC (new_set),
928*e4b17023SJohn Marino 				  new_src, 0))
929*e4b17023SJohn Marino 	    return true;
930*e4b17023SJohn Marino 	}
931*e4b17023SJohn Marino     }
932*e4b17023SJohn Marino   return false;
933*e4b17023SJohn Marino }
934*e4b17023SJohn Marino 
935*e4b17023SJohn Marino /* Called by reload_combine when scanning INSN.  This function tries to detect
936*e4b17023SJohn Marino    patterns where a constant is added to a register, and the result is used
937*e4b17023SJohn Marino    in an address.
938*e4b17023SJohn Marino    Return true if no further processing is needed on INSN; false if it wasn't
939*e4b17023SJohn Marino    recognized and should be handled normally.  */
940*e4b17023SJohn Marino 
941*e4b17023SJohn Marino static bool
reload_combine_recognize_const_pattern(rtx insn)942*e4b17023SJohn Marino reload_combine_recognize_const_pattern (rtx insn)
943*e4b17023SJohn Marino {
944*e4b17023SJohn Marino   int from_ruid = reload_combine_ruid;
945*e4b17023SJohn Marino   rtx set, pat, reg, src, addreg;
946*e4b17023SJohn Marino   unsigned int regno;
947*e4b17023SJohn Marino   struct reg_use *use;
948*e4b17023SJohn Marino   bool must_move_add;
949*e4b17023SJohn Marino   rtx add_moved_after_insn = NULL_RTX;
950*e4b17023SJohn Marino   int add_moved_after_ruid = 0;
951*e4b17023SJohn Marino   int clobbered_regno = -1;
952*e4b17023SJohn Marino 
953*e4b17023SJohn Marino   set = single_set (insn);
954*e4b17023SJohn Marino   if (set == NULL_RTX)
955*e4b17023SJohn Marino     return false;
956*e4b17023SJohn Marino 
957*e4b17023SJohn Marino   reg = SET_DEST (set);
958*e4b17023SJohn Marino   src = SET_SRC (set);
959*e4b17023SJohn Marino   if (!REG_P (reg)
960*e4b17023SJohn Marino       || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1
961*e4b17023SJohn Marino       || GET_MODE (reg) != Pmode
962*e4b17023SJohn Marino       || reg == stack_pointer_rtx)
963*e4b17023SJohn Marino     return false;
964*e4b17023SJohn Marino 
965*e4b17023SJohn Marino   regno = REGNO (reg);
966*e4b17023SJohn Marino 
967*e4b17023SJohn Marino   /* We look for a REG1 = REG2 + CONSTANT insn, followed by either
968*e4b17023SJohn Marino      uses of REG1 inside an address, or inside another add insn.  If
969*e4b17023SJohn Marino      possible and profitable, merge the addition into subsequent
970*e4b17023SJohn Marino      uses.  */
971*e4b17023SJohn Marino   if (GET_CODE (src) != PLUS
972*e4b17023SJohn Marino       || !REG_P (XEXP (src, 0))
973*e4b17023SJohn Marino       || !CONSTANT_P (XEXP (src, 1)))
974*e4b17023SJohn Marino     return false;
975*e4b17023SJohn Marino 
976*e4b17023SJohn Marino   addreg = XEXP (src, 0);
977*e4b17023SJohn Marino   must_move_add = rtx_equal_p (reg, addreg);
978*e4b17023SJohn Marino 
979*e4b17023SJohn Marino   pat = PATTERN (insn);
980*e4b17023SJohn Marino   if (must_move_add && set != pat)
981*e4b17023SJohn Marino     {
982*e4b17023SJohn Marino       /* We have to be careful when moving the add; apart from the
983*e4b17023SJohn Marino 	 single_set there may also be clobbers.  Recognize one special
984*e4b17023SJohn Marino 	 case, that of one clobber alongside the set (likely a clobber
985*e4b17023SJohn Marino 	 of the CC register).  */
986*e4b17023SJohn Marino       gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL);
987*e4b17023SJohn Marino       if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set
988*e4b17023SJohn Marino 	  || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER
989*e4b17023SJohn Marino 	  || !REG_P (XEXP (XVECEXP (pat, 0, 1), 0)))
990*e4b17023SJohn Marino 	return false;
991*e4b17023SJohn Marino       clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 0));
992*e4b17023SJohn Marino     }
993*e4b17023SJohn Marino 
994*e4b17023SJohn Marino   do
995*e4b17023SJohn Marino     {
996*e4b17023SJohn Marino       use = reload_combine_closest_single_use (regno, from_ruid);
997*e4b17023SJohn Marino 
998*e4b17023SJohn Marino       if (use)
999*e4b17023SJohn Marino 	/* Start the search for the next use from here.  */
1000*e4b17023SJohn Marino 	from_ruid = use->ruid;
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino       if (use && GET_MODE (*use->usep) == Pmode)
1003*e4b17023SJohn Marino 	{
1004*e4b17023SJohn Marino 	  bool delete_add = false;
1005*e4b17023SJohn Marino 	  rtx use_insn = use->insn;
1006*e4b17023SJohn Marino 	  int use_ruid = use->ruid;
1007*e4b17023SJohn Marino 
1008*e4b17023SJohn Marino 	  /* Avoid moving the add insn past a jump.  */
1009*e4b17023SJohn Marino 	  if (must_move_add && use_ruid <= last_jump_ruid)
1010*e4b17023SJohn Marino 	    break;
1011*e4b17023SJohn Marino 
1012*e4b17023SJohn Marino 	  /* If the add clobbers another hard reg in parallel, don't move
1013*e4b17023SJohn Marino 	     it past a real set of this hard reg.  */
1014*e4b17023SJohn Marino 	  if (must_move_add && clobbered_regno >= 0
1015*e4b17023SJohn Marino 	      && reg_state[clobbered_regno].real_store_ruid >= use_ruid)
1016*e4b17023SJohn Marino 	    break;
1017*e4b17023SJohn Marino 
1018*e4b17023SJohn Marino #ifdef HAVE_cc0
1019*e4b17023SJohn Marino 	  /* Do not separate cc0 setter and cc0 user on HAVE_cc0 targets.  */
1020*e4b17023SJohn Marino 	  if (must_move_add && sets_cc0_p (PATTERN (use_insn)))
1021*e4b17023SJohn Marino 	    break;
1022*e4b17023SJohn Marino #endif
1023*e4b17023SJohn Marino 
1024*e4b17023SJohn Marino 	  gcc_assert (reg_state[regno].store_ruid <= use_ruid);
1025*e4b17023SJohn Marino 	  /* Avoid moving a use of ADDREG past a point where it is stored.  */
1026*e4b17023SJohn Marino 	  if (reg_state[REGNO (addreg)].store_ruid > use_ruid)
1027*e4b17023SJohn Marino 	    break;
1028*e4b17023SJohn Marino 
1029*e4b17023SJohn Marino 	  /* We also must not move the addition past an insn that sets
1030*e4b17023SJohn Marino 	     the same register, unless we can combine two add insns.  */
1031*e4b17023SJohn Marino 	  if (must_move_add && reg_state[regno].store_ruid == use_ruid)
1032*e4b17023SJohn Marino 	    {
1033*e4b17023SJohn Marino 	      if (use->containing_mem == NULL_RTX)
1034*e4b17023SJohn Marino 		delete_add = true;
1035*e4b17023SJohn Marino 	      else
1036*e4b17023SJohn Marino 		break;
1037*e4b17023SJohn Marino 	    }
1038*e4b17023SJohn Marino 
1039*e4b17023SJohn Marino 	  if (try_replace_in_use (use, reg, src))
1040*e4b17023SJohn Marino 	    {
1041*e4b17023SJohn Marino 	      reload_combine_purge_insn_uses (use_insn);
1042*e4b17023SJohn Marino 	      reload_combine_note_use (&PATTERN (use_insn), use_insn,
1043*e4b17023SJohn Marino 				       use_ruid, NULL_RTX);
1044*e4b17023SJohn Marino 
1045*e4b17023SJohn Marino 	      if (delete_add)
1046*e4b17023SJohn Marino 		{
1047*e4b17023SJohn Marino 		  fixup_debug_insns (reg, src, insn, use_insn);
1048*e4b17023SJohn Marino 		  delete_insn (insn);
1049*e4b17023SJohn Marino 		  return true;
1050*e4b17023SJohn Marino 		}
1051*e4b17023SJohn Marino 	      if (must_move_add)
1052*e4b17023SJohn Marino 		{
1053*e4b17023SJohn Marino 		  add_moved_after_insn = use_insn;
1054*e4b17023SJohn Marino 		  add_moved_after_ruid = use_ruid;
1055*e4b17023SJohn Marino 		}
1056*e4b17023SJohn Marino 	      continue;
1057*e4b17023SJohn Marino 	    }
1058*e4b17023SJohn Marino 	}
1059*e4b17023SJohn Marino       /* If we get here, we couldn't handle this use.  */
1060*e4b17023SJohn Marino       if (must_move_add)
1061*e4b17023SJohn Marino 	break;
1062*e4b17023SJohn Marino     }
1063*e4b17023SJohn Marino   while (use);
1064*e4b17023SJohn Marino 
1065*e4b17023SJohn Marino   if (!must_move_add || add_moved_after_insn == NULL_RTX)
1066*e4b17023SJohn Marino     /* Process the add normally.  */
1067*e4b17023SJohn Marino     return false;
1068*e4b17023SJohn Marino 
1069*e4b17023SJohn Marino   fixup_debug_insns (reg, src, insn, add_moved_after_insn);
1070*e4b17023SJohn Marino 
1071*e4b17023SJohn Marino   reorder_insns (insn, insn, add_moved_after_insn);
1072*e4b17023SJohn Marino   reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid);
1073*e4b17023SJohn Marino   reload_combine_split_ruids (add_moved_after_ruid - 1);
1074*e4b17023SJohn Marino   reload_combine_note_use (&PATTERN (insn), insn,
1075*e4b17023SJohn Marino 			   add_moved_after_ruid, NULL_RTX);
1076*e4b17023SJohn Marino   reg_state[regno].store_ruid = add_moved_after_ruid;
1077*e4b17023SJohn Marino 
1078*e4b17023SJohn Marino   return true;
1079*e4b17023SJohn Marino }
1080*e4b17023SJohn Marino 
1081*e4b17023SJohn Marino /* Called by reload_combine when scanning INSN.  Try to detect a pattern we
1082*e4b17023SJohn Marino    can handle and improve.  Return true if no further processing is needed on
1083*e4b17023SJohn Marino    INSN; false if it wasn't recognized and should be handled normally.  */
1084*e4b17023SJohn Marino 
1085*e4b17023SJohn Marino static bool
reload_combine_recognize_pattern(rtx insn)1086*e4b17023SJohn Marino reload_combine_recognize_pattern (rtx insn)
1087*e4b17023SJohn Marino {
1088*e4b17023SJohn Marino   rtx set, reg, src;
1089*e4b17023SJohn Marino   unsigned int regno;
1090*e4b17023SJohn Marino 
1091*e4b17023SJohn Marino   set = single_set (insn);
1092*e4b17023SJohn Marino   if (set == NULL_RTX)
1093*e4b17023SJohn Marino     return false;
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino   reg = SET_DEST (set);
1096*e4b17023SJohn Marino   src = SET_SRC (set);
1097*e4b17023SJohn Marino   if (!REG_P (reg)
1098*e4b17023SJohn Marino       || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1)
1099*e4b17023SJohn Marino     return false;
1100*e4b17023SJohn Marino 
1101*e4b17023SJohn Marino   regno = REGNO (reg);
1102*e4b17023SJohn Marino 
1103*e4b17023SJohn Marino   /* Look for (set (REGX) (CONST_INT))
1104*e4b17023SJohn Marino      (set (REGX) (PLUS (REGX) (REGY)))
1105*e4b17023SJohn Marino      ...
1106*e4b17023SJohn Marino      ... (MEM (REGX)) ...
1107*e4b17023SJohn Marino      and convert it to
1108*e4b17023SJohn Marino      (set (REGZ) (CONST_INT))
1109*e4b17023SJohn Marino      ...
1110*e4b17023SJohn Marino      ... (MEM (PLUS (REGZ) (REGY)))... .
1111*e4b17023SJohn Marino 
1112*e4b17023SJohn Marino      First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
1113*e4b17023SJohn Marino      and that we know all uses of REGX before it dies.
1114*e4b17023SJohn Marino      Also, explicitly check that REGX != REGY; our life information
1115*e4b17023SJohn Marino      does not yet show whether REGY changes in this insn.  */
1116*e4b17023SJohn Marino 
1117*e4b17023SJohn Marino   if (GET_CODE (src) == PLUS
1118*e4b17023SJohn Marino       && reg_state[regno].all_offsets_match
1119*e4b17023SJohn Marino       && last_index_reg != -1
1120*e4b17023SJohn Marino       && REG_P (XEXP (src, 1))
1121*e4b17023SJohn Marino       && rtx_equal_p (XEXP (src, 0), reg)
1122*e4b17023SJohn Marino       && !rtx_equal_p (XEXP (src, 1), reg)
1123*e4b17023SJohn Marino       && reg_state[regno].use_index >= 0
1124*e4b17023SJohn Marino       && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES
1125*e4b17023SJohn Marino       && last_label_ruid < reg_state[regno].use_ruid)
1126*e4b17023SJohn Marino     {
1127*e4b17023SJohn Marino       rtx base = XEXP (src, 1);
1128*e4b17023SJohn Marino       rtx prev = prev_nonnote_nondebug_insn (insn);
1129*e4b17023SJohn Marino       rtx prev_set = prev ? single_set (prev) : NULL_RTX;
1130*e4b17023SJohn Marino       rtx index_reg = NULL_RTX;
1131*e4b17023SJohn Marino       rtx reg_sum = NULL_RTX;
1132*e4b17023SJohn Marino       int i;
1133*e4b17023SJohn Marino 
1134*e4b17023SJohn Marino       /* Now we need to set INDEX_REG to an index register (denoted as
1135*e4b17023SJohn Marino 	 REGZ in the illustration above) and REG_SUM to the expression
1136*e4b17023SJohn Marino 	 register+register that we want to use to substitute uses of REG
1137*e4b17023SJohn Marino 	 (typically in MEMs) with.  First check REG and BASE for being
1138*e4b17023SJohn Marino 	 index registers; we can use them even if they are not dead.  */
1139*e4b17023SJohn Marino       if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
1140*e4b17023SJohn Marino 	  || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
1141*e4b17023SJohn Marino 				REGNO (base)))
1142*e4b17023SJohn Marino 	{
1143*e4b17023SJohn Marino 	  index_reg = reg;
1144*e4b17023SJohn Marino 	  reg_sum = src;
1145*e4b17023SJohn Marino 	}
1146*e4b17023SJohn Marino       else
1147*e4b17023SJohn Marino 	{
1148*e4b17023SJohn Marino 	  /* Otherwise, look for a free index register.  Since we have
1149*e4b17023SJohn Marino 	     checked above that neither REG nor BASE are index registers,
1150*e4b17023SJohn Marino 	     if we find anything at all, it will be different from these
1151*e4b17023SJohn Marino 	     two registers.  */
1152*e4b17023SJohn Marino 	  for (i = first_index_reg; i <= last_index_reg; i++)
1153*e4b17023SJohn Marino 	    {
1154*e4b17023SJohn Marino 	      if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
1155*e4b17023SJohn Marino 		  && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
1156*e4b17023SJohn Marino 		  && reg_state[i].store_ruid <= reg_state[regno].use_ruid
1157*e4b17023SJohn Marino 		  && (call_used_regs[i] || df_regs_ever_live_p (i))
1158*e4b17023SJohn Marino 		  && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM)
1159*e4b17023SJohn Marino 		  && !fixed_regs[i] && !global_regs[i]
1160*e4b17023SJohn Marino 		  && hard_regno_nregs[i][GET_MODE (reg)] == 1
1161*e4b17023SJohn Marino 		  && targetm.hard_regno_scratch_ok (i))
1162*e4b17023SJohn Marino 		{
1163*e4b17023SJohn Marino 		  index_reg = gen_rtx_REG (GET_MODE (reg), i);
1164*e4b17023SJohn Marino 		  reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
1165*e4b17023SJohn Marino 		  break;
1166*e4b17023SJohn Marino 		}
1167*e4b17023SJohn Marino 	    }
1168*e4b17023SJohn Marino 	}
1169*e4b17023SJohn Marino 
1170*e4b17023SJohn Marino       /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
1171*e4b17023SJohn Marino 	 (REGY), i.e. BASE, is not clobbered before the last use we'll
1172*e4b17023SJohn Marino 	 create.  */
1173*e4b17023SJohn Marino       if (reg_sum
1174*e4b17023SJohn Marino 	  && prev_set
1175*e4b17023SJohn Marino 	  && CONST_INT_P (SET_SRC (prev_set))
1176*e4b17023SJohn Marino 	  && rtx_equal_p (SET_DEST (prev_set), reg)
1177*e4b17023SJohn Marino 	  && (reg_state[REGNO (base)].store_ruid
1178*e4b17023SJohn Marino 	      <= reg_state[regno].use_ruid))
1179*e4b17023SJohn Marino 	{
1180*e4b17023SJohn Marino 	  /* Change destination register and, if necessary, the constant
1181*e4b17023SJohn Marino 	     value in PREV, the constant loading instruction.  */
1182*e4b17023SJohn Marino 	  validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
1183*e4b17023SJohn Marino 	  if (reg_state[regno].offset != const0_rtx)
1184*e4b17023SJohn Marino 	    validate_change (prev,
1185*e4b17023SJohn Marino 			     &SET_SRC (prev_set),
1186*e4b17023SJohn Marino 			     GEN_INT (INTVAL (SET_SRC (prev_set))
1187*e4b17023SJohn Marino 				      + INTVAL (reg_state[regno].offset)),
1188*e4b17023SJohn Marino 			     1);
1189*e4b17023SJohn Marino 
1190*e4b17023SJohn Marino 	  /* Now for every use of REG that we have recorded, replace REG
1191*e4b17023SJohn Marino 	     with REG_SUM.  */
1192*e4b17023SJohn Marino 	  for (i = reg_state[regno].use_index;
1193*e4b17023SJohn Marino 	       i < RELOAD_COMBINE_MAX_USES; i++)
1194*e4b17023SJohn Marino 	    validate_unshare_change (reg_state[regno].reg_use[i].insn,
1195*e4b17023SJohn Marino 				     reg_state[regno].reg_use[i].usep,
1196*e4b17023SJohn Marino 				     /* Each change must have its own
1197*e4b17023SJohn Marino 					replacement.  */
1198*e4b17023SJohn Marino 				     reg_sum, 1);
1199*e4b17023SJohn Marino 
1200*e4b17023SJohn Marino 	  if (apply_change_group ())
1201*e4b17023SJohn Marino 	    {
1202*e4b17023SJohn Marino 	      struct reg_use *lowest_ruid = NULL;
1203*e4b17023SJohn Marino 
1204*e4b17023SJohn Marino 	      /* For every new use of REG_SUM, we have to record the use
1205*e4b17023SJohn Marino 		 of BASE therein, i.e. operand 1.  */
1206*e4b17023SJohn Marino 	      for (i = reg_state[regno].use_index;
1207*e4b17023SJohn Marino 		   i < RELOAD_COMBINE_MAX_USES; i++)
1208*e4b17023SJohn Marino 		{
1209*e4b17023SJohn Marino 		  struct reg_use *use = reg_state[regno].reg_use + i;
1210*e4b17023SJohn Marino 		  reload_combine_note_use (&XEXP (*use->usep, 1), use->insn,
1211*e4b17023SJohn Marino 					   use->ruid, use->containing_mem);
1212*e4b17023SJohn Marino 		  if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid)
1213*e4b17023SJohn Marino 		    lowest_ruid = use;
1214*e4b17023SJohn Marino 		}
1215*e4b17023SJohn Marino 
1216*e4b17023SJohn Marino 	      fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->insn);
1217*e4b17023SJohn Marino 
1218*e4b17023SJohn Marino 	      /* Delete the reg-reg addition.  */
1219*e4b17023SJohn Marino 	      delete_insn (insn);
1220*e4b17023SJohn Marino 
1221*e4b17023SJohn Marino 	      if (reg_state[regno].offset != const0_rtx)
1222*e4b17023SJohn Marino 		/* Previous REG_EQUIV / REG_EQUAL notes for PREV
1223*e4b17023SJohn Marino 		   are now invalid.  */
1224*e4b17023SJohn Marino 		remove_reg_equal_equiv_notes (prev);
1225*e4b17023SJohn Marino 
1226*e4b17023SJohn Marino 	      reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
1227*e4b17023SJohn Marino 	      return true;
1228*e4b17023SJohn Marino 	    }
1229*e4b17023SJohn Marino 	}
1230*e4b17023SJohn Marino     }
1231*e4b17023SJohn Marino   return false;
1232*e4b17023SJohn Marino }
1233*e4b17023SJohn Marino 
1234*e4b17023SJohn Marino static void
reload_combine(void)1235*e4b17023SJohn Marino reload_combine (void)
1236*e4b17023SJohn Marino {
1237*e4b17023SJohn Marino   rtx insn, prev;
1238*e4b17023SJohn Marino   basic_block bb;
1239*e4b17023SJohn Marino   unsigned int r;
1240*e4b17023SJohn Marino   int min_labelno, n_labels;
1241*e4b17023SJohn Marino   HARD_REG_SET ever_live_at_start, *label_live;
1242*e4b17023SJohn Marino 
1243*e4b17023SJohn Marino   /* To avoid wasting too much time later searching for an index register,
1244*e4b17023SJohn Marino      determine the minimum and maximum index register numbers.  */
1245*e4b17023SJohn Marino   if (INDEX_REG_CLASS == NO_REGS)
1246*e4b17023SJohn Marino     last_index_reg = -1;
1247*e4b17023SJohn Marino   else if (first_index_reg == -1 && last_index_reg == 0)
1248*e4b17023SJohn Marino     {
1249*e4b17023SJohn Marino       for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1250*e4b17023SJohn Marino 	if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
1251*e4b17023SJohn Marino 	  {
1252*e4b17023SJohn Marino 	    if (first_index_reg == -1)
1253*e4b17023SJohn Marino 	      first_index_reg = r;
1254*e4b17023SJohn Marino 
1255*e4b17023SJohn Marino 	    last_index_reg = r;
1256*e4b17023SJohn Marino 	  }
1257*e4b17023SJohn Marino 
1258*e4b17023SJohn Marino       /* If no index register is available, we can quit now.  Set LAST_INDEX_REG
1259*e4b17023SJohn Marino 	 to -1 so we'll know to quit early the next time we get here.  */
1260*e4b17023SJohn Marino       if (first_index_reg == -1)
1261*e4b17023SJohn Marino 	{
1262*e4b17023SJohn Marino 	  last_index_reg = -1;
1263*e4b17023SJohn Marino 	  return;
1264*e4b17023SJohn Marino 	}
1265*e4b17023SJohn Marino     }
1266*e4b17023SJohn Marino 
1267*e4b17023SJohn Marino   /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
1268*e4b17023SJohn Marino      information is a bit fuzzy immediately after reload, but it's
1269*e4b17023SJohn Marino      still good enough to determine which registers are live at a jump
1270*e4b17023SJohn Marino      destination.  */
1271*e4b17023SJohn Marino   min_labelno = get_first_label_num ();
1272*e4b17023SJohn Marino   n_labels = max_label_num () - min_labelno;
1273*e4b17023SJohn Marino   label_live = XNEWVEC (HARD_REG_SET, n_labels);
1274*e4b17023SJohn Marino   CLEAR_HARD_REG_SET (ever_live_at_start);
1275*e4b17023SJohn Marino 
1276*e4b17023SJohn Marino   FOR_EACH_BB_REVERSE (bb)
1277*e4b17023SJohn Marino     {
1278*e4b17023SJohn Marino       insn = BB_HEAD (bb);
1279*e4b17023SJohn Marino       if (LABEL_P (insn))
1280*e4b17023SJohn Marino 	{
1281*e4b17023SJohn Marino 	  HARD_REG_SET live;
1282*e4b17023SJohn Marino 	  bitmap live_in = df_get_live_in (bb);
1283*e4b17023SJohn Marino 
1284*e4b17023SJohn Marino 	  REG_SET_TO_HARD_REG_SET (live, live_in);
1285*e4b17023SJohn Marino 	  compute_use_by_pseudos (&live, live_in);
1286*e4b17023SJohn Marino 	  COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
1287*e4b17023SJohn Marino 	  IOR_HARD_REG_SET (ever_live_at_start, live);
1288*e4b17023SJohn Marino 	}
1289*e4b17023SJohn Marino     }
1290*e4b17023SJohn Marino 
1291*e4b17023SJohn Marino   /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
1292*e4b17023SJohn Marino   last_label_ruid = last_jump_ruid = reload_combine_ruid = 0;
1293*e4b17023SJohn Marino   for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1294*e4b17023SJohn Marino     {
1295*e4b17023SJohn Marino       reg_state[r].store_ruid = 0;
1296*e4b17023SJohn Marino       reg_state[r].real_store_ruid = 0;
1297*e4b17023SJohn Marino       if (fixed_regs[r])
1298*e4b17023SJohn Marino 	reg_state[r].use_index = -1;
1299*e4b17023SJohn Marino       else
1300*e4b17023SJohn Marino 	reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
1301*e4b17023SJohn Marino     }
1302*e4b17023SJohn Marino 
1303*e4b17023SJohn Marino   for (insn = get_last_insn (); insn; insn = prev)
1304*e4b17023SJohn Marino     {
1305*e4b17023SJohn Marino       bool control_flow_insn;
1306*e4b17023SJohn Marino       rtx note;
1307*e4b17023SJohn Marino 
1308*e4b17023SJohn Marino       prev = PREV_INSN (insn);
1309*e4b17023SJohn Marino 
1310*e4b17023SJohn Marino       /* We cannot do our optimization across labels.  Invalidating all the use
1311*e4b17023SJohn Marino 	 information we have would be costly, so we just note where the label
1312*e4b17023SJohn Marino 	 is and then later disable any optimization that would cross it.  */
1313*e4b17023SJohn Marino       if (LABEL_P (insn))
1314*e4b17023SJohn Marino 	last_label_ruid = reload_combine_ruid;
1315*e4b17023SJohn Marino       else if (BARRIER_P (insn))
1316*e4b17023SJohn Marino 	{
1317*e4b17023SJohn Marino 	  /* Crossing a barrier resets all the use information.  */
1318*e4b17023SJohn Marino 	  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1319*e4b17023SJohn Marino 	    if (! fixed_regs[r])
1320*e4b17023SJohn Marino 	      reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
1321*e4b17023SJohn Marino 	}
1322*e4b17023SJohn Marino       else if (INSN_P (insn) && volatile_insn_p (PATTERN (insn)))
1323*e4b17023SJohn Marino 	/* Optimizations across insns being marked as volatile must be
1324*e4b17023SJohn Marino 	   prevented.  All the usage information is invalidated
1325*e4b17023SJohn Marino 	   here.  */
1326*e4b17023SJohn Marino 	for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1327*e4b17023SJohn Marino 	  if (! fixed_regs[r]
1328*e4b17023SJohn Marino 	      && reg_state[r].use_index != RELOAD_COMBINE_MAX_USES)
1329*e4b17023SJohn Marino 	    reg_state[r].use_index = -1;
1330*e4b17023SJohn Marino 
1331*e4b17023SJohn Marino       if (! NONDEBUG_INSN_P (insn))
1332*e4b17023SJohn Marino 	continue;
1333*e4b17023SJohn Marino 
1334*e4b17023SJohn Marino       reload_combine_ruid++;
1335*e4b17023SJohn Marino 
1336*e4b17023SJohn Marino       control_flow_insn = control_flow_insn_p (insn);
1337*e4b17023SJohn Marino       if (control_flow_insn)
1338*e4b17023SJohn Marino 	last_jump_ruid = reload_combine_ruid;
1339*e4b17023SJohn Marino 
1340*e4b17023SJohn Marino       if (reload_combine_recognize_const_pattern (insn)
1341*e4b17023SJohn Marino 	  || reload_combine_recognize_pattern (insn))
1342*e4b17023SJohn Marino 	continue;
1343*e4b17023SJohn Marino 
1344*e4b17023SJohn Marino       note_stores (PATTERN (insn), reload_combine_note_store, NULL);
1345*e4b17023SJohn Marino 
1346*e4b17023SJohn Marino       if (CALL_P (insn))
1347*e4b17023SJohn Marino 	{
1348*e4b17023SJohn Marino 	  rtx link;
1349*e4b17023SJohn Marino 
1350*e4b17023SJohn Marino 	  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1351*e4b17023SJohn Marino 	    if (call_used_regs[r])
1352*e4b17023SJohn Marino 	      {
1353*e4b17023SJohn Marino 		reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
1354*e4b17023SJohn Marino 		reg_state[r].store_ruid = reload_combine_ruid;
1355*e4b17023SJohn Marino 	      }
1356*e4b17023SJohn Marino 
1357*e4b17023SJohn Marino 	  for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
1358*e4b17023SJohn Marino 	       link = XEXP (link, 1))
1359*e4b17023SJohn Marino 	    {
1360*e4b17023SJohn Marino 	      rtx usage_rtx = XEXP (XEXP (link, 0), 0);
1361*e4b17023SJohn Marino 	      if (REG_P (usage_rtx))
1362*e4b17023SJohn Marino 	        {
1363*e4b17023SJohn Marino 		  unsigned int i;
1364*e4b17023SJohn Marino 		  unsigned int start_reg = REGNO (usage_rtx);
1365*e4b17023SJohn Marino 		  unsigned int num_regs
1366*e4b17023SJohn Marino 		    = hard_regno_nregs[start_reg][GET_MODE (usage_rtx)];
1367*e4b17023SJohn Marino 		  unsigned int end_reg = start_reg + num_regs - 1;
1368*e4b17023SJohn Marino 		  for (i = start_reg; i <= end_reg; i++)
1369*e4b17023SJohn Marino 		    if (GET_CODE (XEXP (link, 0)) == CLOBBER)
1370*e4b17023SJohn Marino 		      {
1371*e4b17023SJohn Marino 		        reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
1372*e4b17023SJohn Marino 		        reg_state[i].store_ruid = reload_combine_ruid;
1373*e4b17023SJohn Marino 		      }
1374*e4b17023SJohn Marino 		    else
1375*e4b17023SJohn Marino 		      reg_state[i].use_index = -1;
1376*e4b17023SJohn Marino 	         }
1377*e4b17023SJohn Marino 	     }
1378*e4b17023SJohn Marino 	}
1379*e4b17023SJohn Marino 
1380*e4b17023SJohn Marino       if (control_flow_insn && GET_CODE (PATTERN (insn)) != RETURN)
1381*e4b17023SJohn Marino 	{
1382*e4b17023SJohn Marino 	  /* Non-spill registers might be used at the call destination in
1383*e4b17023SJohn Marino 	     some unknown fashion, so we have to mark the unknown use.  */
1384*e4b17023SJohn Marino 	  HARD_REG_SET *live;
1385*e4b17023SJohn Marino 
1386*e4b17023SJohn Marino 	  if ((condjump_p (insn) || condjump_in_parallel_p (insn))
1387*e4b17023SJohn Marino 	      && JUMP_LABEL (insn))
1388*e4b17023SJohn Marino 	    live = &LABEL_LIVE (JUMP_LABEL (insn));
1389*e4b17023SJohn Marino 	  else
1390*e4b17023SJohn Marino 	    live = &ever_live_at_start;
1391*e4b17023SJohn Marino 
1392*e4b17023SJohn Marino 	  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1393*e4b17023SJohn Marino 	    if (TEST_HARD_REG_BIT (*live, r))
1394*e4b17023SJohn Marino 	      reg_state[r].use_index = -1;
1395*e4b17023SJohn Marino 	}
1396*e4b17023SJohn Marino 
1397*e4b17023SJohn Marino       reload_combine_note_use (&PATTERN (insn), insn, reload_combine_ruid,
1398*e4b17023SJohn Marino 			       NULL_RTX);
1399*e4b17023SJohn Marino 
1400*e4b17023SJohn Marino       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1401*e4b17023SJohn Marino 	{
1402*e4b17023SJohn Marino 	  if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0)))
1403*e4b17023SJohn Marino 	    {
1404*e4b17023SJohn Marino 	      int regno = REGNO (XEXP (note, 0));
1405*e4b17023SJohn Marino 	      reg_state[regno].store_ruid = reload_combine_ruid;
1406*e4b17023SJohn Marino 	      reg_state[regno].real_store_ruid = reload_combine_ruid;
1407*e4b17023SJohn Marino 	      reg_state[regno].use_index = -1;
1408*e4b17023SJohn Marino 	    }
1409*e4b17023SJohn Marino 	}
1410*e4b17023SJohn Marino     }
1411*e4b17023SJohn Marino 
1412*e4b17023SJohn Marino   free (label_live);
1413*e4b17023SJohn Marino }
1414*e4b17023SJohn Marino 
1415*e4b17023SJohn Marino /* Check if DST is a register or a subreg of a register; if it is,
1416*e4b17023SJohn Marino    update store_ruid, real_store_ruid and use_index in the reg_state
1417*e4b17023SJohn Marino    structure accordingly.  Called via note_stores from reload_combine.  */
1418*e4b17023SJohn Marino 
1419*e4b17023SJohn Marino static void
reload_combine_note_store(rtx dst,const_rtx set,void * data ATTRIBUTE_UNUSED)1420*e4b17023SJohn Marino reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED)
1421*e4b17023SJohn Marino {
1422*e4b17023SJohn Marino   int regno = 0;
1423*e4b17023SJohn Marino   int i;
1424*e4b17023SJohn Marino   enum machine_mode mode = GET_MODE (dst);
1425*e4b17023SJohn Marino 
1426*e4b17023SJohn Marino   if (GET_CODE (dst) == SUBREG)
1427*e4b17023SJohn Marino     {
1428*e4b17023SJohn Marino       regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
1429*e4b17023SJohn Marino 				   GET_MODE (SUBREG_REG (dst)),
1430*e4b17023SJohn Marino 				   SUBREG_BYTE (dst),
1431*e4b17023SJohn Marino 				   GET_MODE (dst));
1432*e4b17023SJohn Marino       dst = SUBREG_REG (dst);
1433*e4b17023SJohn Marino     }
1434*e4b17023SJohn Marino 
1435*e4b17023SJohn Marino   /* Some targets do argument pushes without adding REG_INC notes.  */
1436*e4b17023SJohn Marino 
1437*e4b17023SJohn Marino   if (MEM_P (dst))
1438*e4b17023SJohn Marino     {
1439*e4b17023SJohn Marino       dst = XEXP (dst, 0);
1440*e4b17023SJohn Marino       if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
1441*e4b17023SJohn Marino 	  || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC
1442*e4b17023SJohn Marino 	  || GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY)
1443*e4b17023SJohn Marino 	{
1444*e4b17023SJohn Marino 	  regno = REGNO (XEXP (dst, 0));
1445*e4b17023SJohn Marino 	  mode = GET_MODE (XEXP (dst, 0));
1446*e4b17023SJohn Marino 	  for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
1447*e4b17023SJohn Marino 	    {
1448*e4b17023SJohn Marino 	      /* We could probably do better, but for now mark the register
1449*e4b17023SJohn Marino 		 as used in an unknown fashion and set/clobbered at this
1450*e4b17023SJohn Marino 		 insn.  */
1451*e4b17023SJohn Marino 	      reg_state[i].use_index = -1;
1452*e4b17023SJohn Marino 	      reg_state[i].store_ruid = reload_combine_ruid;
1453*e4b17023SJohn Marino 	      reg_state[i].real_store_ruid = reload_combine_ruid;
1454*e4b17023SJohn Marino 	    }
1455*e4b17023SJohn Marino 	}
1456*e4b17023SJohn Marino       else
1457*e4b17023SJohn Marino         return;
1458*e4b17023SJohn Marino     }
1459*e4b17023SJohn Marino 
1460*e4b17023SJohn Marino   if (!REG_P (dst))
1461*e4b17023SJohn Marino     return;
1462*e4b17023SJohn Marino   regno += REGNO (dst);
1463*e4b17023SJohn Marino 
1464*e4b17023SJohn Marino   /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
1465*e4b17023SJohn Marino      careful with registers / register parts that are not full words.
1466*e4b17023SJohn Marino      Similarly for ZERO_EXTRACT.  */
1467*e4b17023SJohn Marino   if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
1468*e4b17023SJohn Marino       || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
1469*e4b17023SJohn Marino     {
1470*e4b17023SJohn Marino       for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
1471*e4b17023SJohn Marino 	{
1472*e4b17023SJohn Marino 	  reg_state[i].use_index = -1;
1473*e4b17023SJohn Marino 	  reg_state[i].store_ruid = reload_combine_ruid;
1474*e4b17023SJohn Marino 	  reg_state[i].real_store_ruid = reload_combine_ruid;
1475*e4b17023SJohn Marino 	}
1476*e4b17023SJohn Marino     }
1477*e4b17023SJohn Marino   else
1478*e4b17023SJohn Marino     {
1479*e4b17023SJohn Marino       for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
1480*e4b17023SJohn Marino 	{
1481*e4b17023SJohn Marino 	  reg_state[i].store_ruid = reload_combine_ruid;
1482*e4b17023SJohn Marino 	  if (GET_CODE (set) == SET)
1483*e4b17023SJohn Marino 	    reg_state[i].real_store_ruid = reload_combine_ruid;
1484*e4b17023SJohn Marino 	  reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
1485*e4b17023SJohn Marino 	}
1486*e4b17023SJohn Marino     }
1487*e4b17023SJohn Marino }
1488*e4b17023SJohn Marino 
1489*e4b17023SJohn Marino /* XP points to a piece of rtl that has to be checked for any uses of
1490*e4b17023SJohn Marino    registers.
1491*e4b17023SJohn Marino    *XP is the pattern of INSN, or a part of it.
1492*e4b17023SJohn Marino    Called from reload_combine, and recursively by itself.  */
1493*e4b17023SJohn Marino static void
reload_combine_note_use(rtx * xp,rtx insn,int ruid,rtx containing_mem)1494*e4b17023SJohn Marino reload_combine_note_use (rtx *xp, rtx insn, int ruid, rtx containing_mem)
1495*e4b17023SJohn Marino {
1496*e4b17023SJohn Marino   rtx x = *xp;
1497*e4b17023SJohn Marino   enum rtx_code code = x->code;
1498*e4b17023SJohn Marino   const char *fmt;
1499*e4b17023SJohn Marino   int i, j;
1500*e4b17023SJohn Marino   rtx offset = const0_rtx; /* For the REG case below.  */
1501*e4b17023SJohn Marino 
1502*e4b17023SJohn Marino   switch (code)
1503*e4b17023SJohn Marino     {
1504*e4b17023SJohn Marino     case SET:
1505*e4b17023SJohn Marino       if (REG_P (SET_DEST (x)))
1506*e4b17023SJohn Marino 	{
1507*e4b17023SJohn Marino 	  reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX);
1508*e4b17023SJohn Marino 	  return;
1509*e4b17023SJohn Marino 	}
1510*e4b17023SJohn Marino       break;
1511*e4b17023SJohn Marino 
1512*e4b17023SJohn Marino     case USE:
1513*e4b17023SJohn Marino       /* If this is the USE of a return value, we can't change it.  */
1514*e4b17023SJohn Marino       if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
1515*e4b17023SJohn Marino 	{
1516*e4b17023SJohn Marino 	/* Mark the return register as used in an unknown fashion.  */
1517*e4b17023SJohn Marino 	  rtx reg = XEXP (x, 0);
1518*e4b17023SJohn Marino 	  int regno = REGNO (reg);
1519*e4b17023SJohn Marino 	  int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
1520*e4b17023SJohn Marino 
1521*e4b17023SJohn Marino 	  while (--nregs >= 0)
1522*e4b17023SJohn Marino 	    reg_state[regno + nregs].use_index = -1;
1523*e4b17023SJohn Marino 	  return;
1524*e4b17023SJohn Marino 	}
1525*e4b17023SJohn Marino       break;
1526*e4b17023SJohn Marino 
1527*e4b17023SJohn Marino     case CLOBBER:
1528*e4b17023SJohn Marino       if (REG_P (SET_DEST (x)))
1529*e4b17023SJohn Marino 	{
1530*e4b17023SJohn Marino 	  /* No spurious CLOBBERs of pseudo registers may remain.  */
1531*e4b17023SJohn Marino 	  gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER);
1532*e4b17023SJohn Marino 	  return;
1533*e4b17023SJohn Marino 	}
1534*e4b17023SJohn Marino       break;
1535*e4b17023SJohn Marino 
1536*e4b17023SJohn Marino     case PLUS:
1537*e4b17023SJohn Marino       /* We are interested in (plus (reg) (const_int)) .  */
1538*e4b17023SJohn Marino       if (!REG_P (XEXP (x, 0))
1539*e4b17023SJohn Marino 	  || !CONST_INT_P (XEXP (x, 1)))
1540*e4b17023SJohn Marino 	break;
1541*e4b17023SJohn Marino       offset = XEXP (x, 1);
1542*e4b17023SJohn Marino       x = XEXP (x, 0);
1543*e4b17023SJohn Marino       /* Fall through.  */
1544*e4b17023SJohn Marino     case REG:
1545*e4b17023SJohn Marino       {
1546*e4b17023SJohn Marino 	int regno = REGNO (x);
1547*e4b17023SJohn Marino 	int use_index;
1548*e4b17023SJohn Marino 	int nregs;
1549*e4b17023SJohn Marino 
1550*e4b17023SJohn Marino 	/* No spurious USEs of pseudo registers may remain.  */
1551*e4b17023SJohn Marino 	gcc_assert (regno < FIRST_PSEUDO_REGISTER);
1552*e4b17023SJohn Marino 
1553*e4b17023SJohn Marino 	nregs = hard_regno_nregs[regno][GET_MODE (x)];
1554*e4b17023SJohn Marino 
1555*e4b17023SJohn Marino 	/* We can't substitute into multi-hard-reg uses.  */
1556*e4b17023SJohn Marino 	if (nregs > 1)
1557*e4b17023SJohn Marino 	  {
1558*e4b17023SJohn Marino 	    while (--nregs >= 0)
1559*e4b17023SJohn Marino 	      reg_state[regno + nregs].use_index = -1;
1560*e4b17023SJohn Marino 	    return;
1561*e4b17023SJohn Marino 	  }
1562*e4b17023SJohn Marino 
1563*e4b17023SJohn Marino 	/* We may be called to update uses in previously seen insns.
1564*e4b17023SJohn Marino 	   Don't add uses beyond the last store we saw.  */
1565*e4b17023SJohn Marino 	if (ruid < reg_state[regno].store_ruid)
1566*e4b17023SJohn Marino 	  return;
1567*e4b17023SJohn Marino 
1568*e4b17023SJohn Marino 	/* If this register is already used in some unknown fashion, we
1569*e4b17023SJohn Marino 	   can't do anything.
1570*e4b17023SJohn Marino 	   If we decrement the index from zero to -1, we can't store more
1571*e4b17023SJohn Marino 	   uses, so this register becomes used in an unknown fashion.  */
1572*e4b17023SJohn Marino 	use_index = --reg_state[regno].use_index;
1573*e4b17023SJohn Marino 	if (use_index < 0)
1574*e4b17023SJohn Marino 	  return;
1575*e4b17023SJohn Marino 
1576*e4b17023SJohn Marino 	if (use_index == RELOAD_COMBINE_MAX_USES - 1)
1577*e4b17023SJohn Marino 	  {
1578*e4b17023SJohn Marino 	    /* This is the first use of this register we have seen since we
1579*e4b17023SJohn Marino 	       marked it as dead.  */
1580*e4b17023SJohn Marino 	    reg_state[regno].offset = offset;
1581*e4b17023SJohn Marino 	    reg_state[regno].all_offsets_match = true;
1582*e4b17023SJohn Marino 	    reg_state[regno].use_ruid = ruid;
1583*e4b17023SJohn Marino 	  }
1584*e4b17023SJohn Marino 	else
1585*e4b17023SJohn Marino 	  {
1586*e4b17023SJohn Marino 	    if (reg_state[regno].use_ruid > ruid)
1587*e4b17023SJohn Marino 	      reg_state[regno].use_ruid = ruid;
1588*e4b17023SJohn Marino 
1589*e4b17023SJohn Marino 	    if (! rtx_equal_p (offset, reg_state[regno].offset))
1590*e4b17023SJohn Marino 	      reg_state[regno].all_offsets_match = false;
1591*e4b17023SJohn Marino 	  }
1592*e4b17023SJohn Marino 
1593*e4b17023SJohn Marino 	reg_state[regno].reg_use[use_index].insn = insn;
1594*e4b17023SJohn Marino 	reg_state[regno].reg_use[use_index].ruid = ruid;
1595*e4b17023SJohn Marino 	reg_state[regno].reg_use[use_index].containing_mem = containing_mem;
1596*e4b17023SJohn Marino 	reg_state[regno].reg_use[use_index].usep = xp;
1597*e4b17023SJohn Marino 	return;
1598*e4b17023SJohn Marino       }
1599*e4b17023SJohn Marino 
1600*e4b17023SJohn Marino     case MEM:
1601*e4b17023SJohn Marino       containing_mem = x;
1602*e4b17023SJohn Marino       break;
1603*e4b17023SJohn Marino 
1604*e4b17023SJohn Marino     default:
1605*e4b17023SJohn Marino       break;
1606*e4b17023SJohn Marino     }
1607*e4b17023SJohn Marino 
1608*e4b17023SJohn Marino   /* Recursively process the components of X.  */
1609*e4b17023SJohn Marino   fmt = GET_RTX_FORMAT (code);
1610*e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1611*e4b17023SJohn Marino     {
1612*e4b17023SJohn Marino       if (fmt[i] == 'e')
1613*e4b17023SJohn Marino 	reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem);
1614*e4b17023SJohn Marino       else if (fmt[i] == 'E')
1615*e4b17023SJohn Marino 	{
1616*e4b17023SJohn Marino 	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1617*e4b17023SJohn Marino 	    reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid,
1618*e4b17023SJohn Marino 				     containing_mem);
1619*e4b17023SJohn Marino 	}
1620*e4b17023SJohn Marino     }
1621*e4b17023SJohn Marino }
1622*e4b17023SJohn Marino 
1623*e4b17023SJohn Marino /* See if we can reduce the cost of a constant by replacing a move
1624*e4b17023SJohn Marino    with an add.  We track situations in which a register is set to a
1625*e4b17023SJohn Marino    constant or to a register plus a constant.  */
1626*e4b17023SJohn Marino /* We cannot do our optimization across labels.  Invalidating all the
1627*e4b17023SJohn Marino    information about register contents we have would be costly, so we
1628*e4b17023SJohn Marino    use move2add_last_label_luid to note where the label is and then
1629*e4b17023SJohn Marino    later disable any optimization that would cross it.
1630*e4b17023SJohn Marino    reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n]
1631*e4b17023SJohn Marino    are only valid if reg_set_luid[n] is greater than
1632*e4b17023SJohn Marino    move2add_last_label_luid.  */
1633*e4b17023SJohn Marino static int reg_set_luid[FIRST_PSEUDO_REGISTER];
1634*e4b17023SJohn Marino 
1635*e4b17023SJohn Marino /* If reg_base_reg[n] is negative, register n has been set to
1636*e4b17023SJohn Marino    reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n].
1637*e4b17023SJohn Marino    If reg_base_reg[n] is non-negative, register n has been set to the
1638*e4b17023SJohn Marino    sum of reg_offset[n] and the value of register reg_base_reg[n]
1639*e4b17023SJohn Marino    before reg_set_luid[n], calculated in mode reg_mode[n] .  */
1640*e4b17023SJohn Marino static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
1641*e4b17023SJohn Marino static int reg_base_reg[FIRST_PSEUDO_REGISTER];
1642*e4b17023SJohn Marino static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER];
1643*e4b17023SJohn Marino static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
1644*e4b17023SJohn Marino 
1645*e4b17023SJohn Marino /* move2add_luid is linearly increased while scanning the instructions
1646*e4b17023SJohn Marino    from first to last.  It is used to set reg_set_luid in
1647*e4b17023SJohn Marino    reload_cse_move2add and move2add_note_store.  */
1648*e4b17023SJohn Marino static int move2add_luid;
1649*e4b17023SJohn Marino 
1650*e4b17023SJohn Marino /* move2add_last_label_luid is set whenever a label is found.  Labels
1651*e4b17023SJohn Marino    invalidate all previously collected reg_offset data.  */
1652*e4b17023SJohn Marino static int move2add_last_label_luid;
1653*e4b17023SJohn Marino 
1654*e4b17023SJohn Marino /* ??? We don't know how zero / sign extension is handled, hence we
1655*e4b17023SJohn Marino    can't go from a narrower to a wider mode.  */
1656*e4b17023SJohn Marino #define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \
1657*e4b17023SJohn Marino   (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \
1658*e4b17023SJohn Marino    || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \
1659*e4b17023SJohn Marino        && TRULY_NOOP_TRUNCATION_MODES_P (OUTMODE, INMODE)))
1660*e4b17023SJohn Marino 
1661*e4b17023SJohn Marino /* This function is called with INSN that sets REG to (SYM + OFF),
1662*e4b17023SJohn Marino    while REG is known to already have value (SYM + offset).
1663*e4b17023SJohn Marino    This function tries to change INSN into an add instruction
1664*e4b17023SJohn Marino    (set (REG) (plus (REG) (OFF - offset))) using the known value.
1665*e4b17023SJohn Marino    It also updates the information about REG's known value.
1666*e4b17023SJohn Marino    Return true if we made a change.  */
1667*e4b17023SJohn Marino 
1668*e4b17023SJohn Marino static bool
move2add_use_add2_insn(rtx reg,rtx sym,rtx off,rtx insn)1669*e4b17023SJohn Marino move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
1670*e4b17023SJohn Marino {
1671*e4b17023SJohn Marino   rtx pat = PATTERN (insn);
1672*e4b17023SJohn Marino   rtx src = SET_SRC (pat);
1673*e4b17023SJohn Marino   int regno = REGNO (reg);
1674*e4b17023SJohn Marino   rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[regno],
1675*e4b17023SJohn Marino 			      GET_MODE (reg));
1676*e4b17023SJohn Marino   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
1677*e4b17023SJohn Marino   bool changed = false;
1678*e4b17023SJohn Marino 
1679*e4b17023SJohn Marino   /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
1680*e4b17023SJohn Marino      use (set (reg) (reg)) instead.
1681*e4b17023SJohn Marino      We don't delete this insn, nor do we convert it into a
1682*e4b17023SJohn Marino      note, to avoid losing register notes or the return
1683*e4b17023SJohn Marino      value flag.  jump2 already knows how to get rid of
1684*e4b17023SJohn Marino      no-op moves.  */
1685*e4b17023SJohn Marino   if (new_src == const0_rtx)
1686*e4b17023SJohn Marino     {
1687*e4b17023SJohn Marino       /* If the constants are different, this is a
1688*e4b17023SJohn Marino 	 truncation, that, if turned into (set (reg)
1689*e4b17023SJohn Marino 	 (reg)), would be discarded.  Maybe we should
1690*e4b17023SJohn Marino 	 try a truncMN pattern?  */
1691*e4b17023SJohn Marino       if (INTVAL (off) == reg_offset [regno])
1692*e4b17023SJohn Marino 	changed = validate_change (insn, &SET_SRC (pat), reg, 0);
1693*e4b17023SJohn Marino     }
1694*e4b17023SJohn Marino   else
1695*e4b17023SJohn Marino     {
1696*e4b17023SJohn Marino       struct full_rtx_costs oldcst, newcst;
1697*e4b17023SJohn Marino       rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
1698*e4b17023SJohn Marino 
1699*e4b17023SJohn Marino       get_full_set_rtx_cost (pat, &oldcst);
1700*e4b17023SJohn Marino       SET_SRC (pat) = tem;
1701*e4b17023SJohn Marino       get_full_set_rtx_cost (pat, &newcst);
1702*e4b17023SJohn Marino       SET_SRC (pat) = src;
1703*e4b17023SJohn Marino 
1704*e4b17023SJohn Marino       if (costs_lt_p (&newcst, &oldcst, speed)
1705*e4b17023SJohn Marino 	  && have_add2_insn (reg, new_src))
1706*e4b17023SJohn Marino 	changed = validate_change (insn, &SET_SRC (pat), tem, 0);
1707*e4b17023SJohn Marino       else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
1708*e4b17023SJohn Marino 	{
1709*e4b17023SJohn Marino 	  enum machine_mode narrow_mode;
1710*e4b17023SJohn Marino 	  for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
1711*e4b17023SJohn Marino 	       narrow_mode != VOIDmode
1712*e4b17023SJohn Marino 		 && narrow_mode != GET_MODE (reg);
1713*e4b17023SJohn Marino 	       narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
1714*e4b17023SJohn Marino 	    {
1715*e4b17023SJohn Marino 	      if (have_insn_for (STRICT_LOW_PART, narrow_mode)
1716*e4b17023SJohn Marino 		  && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
1717*e4b17023SJohn Marino 		      == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode))))
1718*e4b17023SJohn Marino 		{
1719*e4b17023SJohn Marino 		  rtx narrow_reg = gen_rtx_REG (narrow_mode,
1720*e4b17023SJohn Marino 						REGNO (reg));
1721*e4b17023SJohn Marino 		  rtx narrow_src = gen_int_mode (INTVAL (off),
1722*e4b17023SJohn Marino 						 narrow_mode);
1723*e4b17023SJohn Marino 		  rtx new_set
1724*e4b17023SJohn Marino 		    = gen_rtx_SET (VOIDmode,
1725*e4b17023SJohn Marino 				   gen_rtx_STRICT_LOW_PART (VOIDmode,
1726*e4b17023SJohn Marino 							    narrow_reg),
1727*e4b17023SJohn Marino 				   narrow_src);
1728*e4b17023SJohn Marino 		  changed = validate_change (insn, &PATTERN (insn),
1729*e4b17023SJohn Marino 					     new_set, 0);
1730*e4b17023SJohn Marino 		  if (changed)
1731*e4b17023SJohn Marino 		    break;
1732*e4b17023SJohn Marino 		}
1733*e4b17023SJohn Marino 	    }
1734*e4b17023SJohn Marino 	}
1735*e4b17023SJohn Marino     }
1736*e4b17023SJohn Marino   reg_set_luid[regno] = move2add_luid;
1737*e4b17023SJohn Marino   reg_base_reg[regno] = -1;
1738*e4b17023SJohn Marino   reg_mode[regno] = GET_MODE (reg);
1739*e4b17023SJohn Marino   reg_symbol_ref[regno] = sym;
1740*e4b17023SJohn Marino   reg_offset[regno] = INTVAL (off);
1741*e4b17023SJohn Marino   return changed;
1742*e4b17023SJohn Marino }
1743*e4b17023SJohn Marino 
1744*e4b17023SJohn Marino 
1745*e4b17023SJohn Marino /* This function is called with INSN that sets REG to (SYM + OFF),
1746*e4b17023SJohn Marino    but REG doesn't have known value (SYM + offset).  This function
1747*e4b17023SJohn Marino    tries to find another register which is known to already have
1748*e4b17023SJohn Marino    value (SYM + offset) and change INSN into an add instruction
1749*e4b17023SJohn Marino    (set (REG) (plus (the found register) (OFF - offset))) if such
1750*e4b17023SJohn Marino    a register is found.  It also updates the information about
1751*e4b17023SJohn Marino    REG's known value.
1752*e4b17023SJohn Marino    Return true iff we made a change.  */
1753*e4b17023SJohn Marino 
1754*e4b17023SJohn Marino static bool
move2add_use_add3_insn(rtx reg,rtx sym,rtx off,rtx insn)1755*e4b17023SJohn Marino move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
1756*e4b17023SJohn Marino {
1757*e4b17023SJohn Marino   rtx pat = PATTERN (insn);
1758*e4b17023SJohn Marino   rtx src = SET_SRC (pat);
1759*e4b17023SJohn Marino   int regno = REGNO (reg);
1760*e4b17023SJohn Marino   int min_regno = 0;
1761*e4b17023SJohn Marino   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
1762*e4b17023SJohn Marino   int i;
1763*e4b17023SJohn Marino   bool changed = false;
1764*e4b17023SJohn Marino   struct full_rtx_costs oldcst, newcst, mincst;
1765*e4b17023SJohn Marino   rtx plus_expr;
1766*e4b17023SJohn Marino 
1767*e4b17023SJohn Marino   init_costs_to_max (&mincst);
1768*e4b17023SJohn Marino   get_full_set_rtx_cost (pat, &oldcst);
1769*e4b17023SJohn Marino 
1770*e4b17023SJohn Marino   plus_expr = gen_rtx_PLUS (GET_MODE (reg), reg, const0_rtx);
1771*e4b17023SJohn Marino   SET_SRC (pat) = plus_expr;
1772*e4b17023SJohn Marino 
1773*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1774*e4b17023SJohn Marino     if (reg_set_luid[i] > move2add_last_label_luid
1775*e4b17023SJohn Marino 	&& reg_mode[i] == GET_MODE (reg)
1776*e4b17023SJohn Marino 	&& reg_base_reg[i] < 0
1777*e4b17023SJohn Marino 	&& reg_symbol_ref[i] != NULL_RTX
1778*e4b17023SJohn Marino 	&& rtx_equal_p (sym, reg_symbol_ref[i]))
1779*e4b17023SJohn Marino       {
1780*e4b17023SJohn Marino 	rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[i],
1781*e4b17023SJohn Marino 				    GET_MODE (reg));
1782*e4b17023SJohn Marino 	/* (set (reg) (plus (reg) (const_int 0))) is not canonical;
1783*e4b17023SJohn Marino 	   use (set (reg) (reg)) instead.
1784*e4b17023SJohn Marino 	   We don't delete this insn, nor do we convert it into a
1785*e4b17023SJohn Marino 	   note, to avoid losing register notes or the return
1786*e4b17023SJohn Marino 	   value flag.  jump2 already knows how to get rid of
1787*e4b17023SJohn Marino 	   no-op moves.  */
1788*e4b17023SJohn Marino 	if (new_src == const0_rtx)
1789*e4b17023SJohn Marino 	  {
1790*e4b17023SJohn Marino 	    init_costs_to_zero (&mincst);
1791*e4b17023SJohn Marino 	    min_regno = i;
1792*e4b17023SJohn Marino 	    break;
1793*e4b17023SJohn Marino 	  }
1794*e4b17023SJohn Marino 	else
1795*e4b17023SJohn Marino 	  {
1796*e4b17023SJohn Marino 	    XEXP (plus_expr, 1) = new_src;
1797*e4b17023SJohn Marino 	    get_full_set_rtx_cost (pat, &newcst);
1798*e4b17023SJohn Marino 
1799*e4b17023SJohn Marino 	    if (costs_lt_p (&newcst, &mincst, speed))
1800*e4b17023SJohn Marino 	      {
1801*e4b17023SJohn Marino 		mincst = newcst;
1802*e4b17023SJohn Marino 		min_regno = i;
1803*e4b17023SJohn Marino 	      }
1804*e4b17023SJohn Marino 	  }
1805*e4b17023SJohn Marino       }
1806*e4b17023SJohn Marino   SET_SRC (pat) = src;
1807*e4b17023SJohn Marino 
1808*e4b17023SJohn Marino   if (costs_lt_p (&mincst, &oldcst, speed))
1809*e4b17023SJohn Marino     {
1810*e4b17023SJohn Marino       rtx tem;
1811*e4b17023SJohn Marino 
1812*e4b17023SJohn Marino       tem = gen_rtx_REG (GET_MODE (reg), min_regno);
1813*e4b17023SJohn Marino       if (i != min_regno)
1814*e4b17023SJohn Marino 	{
1815*e4b17023SJohn Marino 	  rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[min_regno],
1816*e4b17023SJohn Marino 				      GET_MODE (reg));
1817*e4b17023SJohn Marino 	  tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src);
1818*e4b17023SJohn Marino 	}
1819*e4b17023SJohn Marino       if (validate_change (insn, &SET_SRC (pat), tem, 0))
1820*e4b17023SJohn Marino 	changed = true;
1821*e4b17023SJohn Marino     }
1822*e4b17023SJohn Marino   reg_set_luid[regno] = move2add_luid;
1823*e4b17023SJohn Marino   reg_base_reg[regno] = -1;
1824*e4b17023SJohn Marino   reg_mode[regno] = GET_MODE (reg);
1825*e4b17023SJohn Marino   reg_symbol_ref[regno] = sym;
1826*e4b17023SJohn Marino   reg_offset[regno] = INTVAL (off);
1827*e4b17023SJohn Marino   return changed;
1828*e4b17023SJohn Marino }
1829*e4b17023SJohn Marino 
1830*e4b17023SJohn Marino /* Convert move insns with constant inputs to additions if they are cheaper.
1831*e4b17023SJohn Marino    Return true if any changes were made.  */
1832*e4b17023SJohn Marino static bool
reload_cse_move2add(rtx first)1833*e4b17023SJohn Marino reload_cse_move2add (rtx first)
1834*e4b17023SJohn Marino {
1835*e4b17023SJohn Marino   int i;
1836*e4b17023SJohn Marino   rtx insn;
1837*e4b17023SJohn Marino   bool changed = false;
1838*e4b17023SJohn Marino 
1839*e4b17023SJohn Marino   for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
1840*e4b17023SJohn Marino     {
1841*e4b17023SJohn Marino       reg_set_luid[i] = 0;
1842*e4b17023SJohn Marino       reg_offset[i] = 0;
1843*e4b17023SJohn Marino       reg_base_reg[i] = 0;
1844*e4b17023SJohn Marino       reg_symbol_ref[i] = NULL_RTX;
1845*e4b17023SJohn Marino       reg_mode[i] = VOIDmode;
1846*e4b17023SJohn Marino     }
1847*e4b17023SJohn Marino 
1848*e4b17023SJohn Marino   move2add_last_label_luid = 0;
1849*e4b17023SJohn Marino   move2add_luid = 2;
1850*e4b17023SJohn Marino   for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
1851*e4b17023SJohn Marino     {
1852*e4b17023SJohn Marino       rtx pat, note;
1853*e4b17023SJohn Marino 
1854*e4b17023SJohn Marino       if (LABEL_P (insn))
1855*e4b17023SJohn Marino 	{
1856*e4b17023SJohn Marino 	  move2add_last_label_luid = move2add_luid;
1857*e4b17023SJohn Marino 	  /* We're going to increment move2add_luid twice after a
1858*e4b17023SJohn Marino 	     label, so that we can use move2add_last_label_luid + 1 as
1859*e4b17023SJohn Marino 	     the luid for constants.  */
1860*e4b17023SJohn Marino 	  move2add_luid++;
1861*e4b17023SJohn Marino 	  continue;
1862*e4b17023SJohn Marino 	}
1863*e4b17023SJohn Marino       if (! INSN_P (insn))
1864*e4b17023SJohn Marino 	continue;
1865*e4b17023SJohn Marino       pat = PATTERN (insn);
1866*e4b17023SJohn Marino       /* For simplicity, we only perform this optimization on
1867*e4b17023SJohn Marino 	 straightforward SETs.  */
1868*e4b17023SJohn Marino       if (GET_CODE (pat) == SET
1869*e4b17023SJohn Marino 	  && REG_P (SET_DEST (pat)))
1870*e4b17023SJohn Marino 	{
1871*e4b17023SJohn Marino 	  rtx reg = SET_DEST (pat);
1872*e4b17023SJohn Marino 	  int regno = REGNO (reg);
1873*e4b17023SJohn Marino 	  rtx src = SET_SRC (pat);
1874*e4b17023SJohn Marino 
1875*e4b17023SJohn Marino 	  /* Check if we have valid information on the contents of this
1876*e4b17023SJohn Marino 	     register in the mode of REG.  */
1877*e4b17023SJohn Marino 	  if (reg_set_luid[regno] > move2add_last_label_luid
1878*e4b17023SJohn Marino 	      && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
1879*e4b17023SJohn Marino               && dbg_cnt (cse2_move2add))
1880*e4b17023SJohn Marino 	    {
1881*e4b17023SJohn Marino 	      /* Try to transform (set (REGX) (CONST_INT A))
1882*e4b17023SJohn Marino 				  ...
1883*e4b17023SJohn Marino 				  (set (REGX) (CONST_INT B))
1884*e4b17023SJohn Marino 		 to
1885*e4b17023SJohn Marino 				  (set (REGX) (CONST_INT A))
1886*e4b17023SJohn Marino 				  ...
1887*e4b17023SJohn Marino 				  (set (REGX) (plus (REGX) (CONST_INT B-A)))
1888*e4b17023SJohn Marino 		 or
1889*e4b17023SJohn Marino 				  (set (REGX) (CONST_INT A))
1890*e4b17023SJohn Marino 				  ...
1891*e4b17023SJohn Marino 				  (set (STRICT_LOW_PART (REGX)) (CONST_INT B))
1892*e4b17023SJohn Marino 	      */
1893*e4b17023SJohn Marino 
1894*e4b17023SJohn Marino 	      if (CONST_INT_P (src)
1895*e4b17023SJohn Marino 		  && reg_base_reg[regno] < 0
1896*e4b17023SJohn Marino 		  && reg_symbol_ref[regno] == NULL_RTX)
1897*e4b17023SJohn Marino 		{
1898*e4b17023SJohn Marino 		  changed |= move2add_use_add2_insn (reg, NULL_RTX, src, insn);
1899*e4b17023SJohn Marino 		  continue;
1900*e4b17023SJohn Marino 		}
1901*e4b17023SJohn Marino 
1902*e4b17023SJohn Marino 	      /* Try to transform (set (REGX) (REGY))
1903*e4b17023SJohn Marino 				  (set (REGX) (PLUS (REGX) (CONST_INT A)))
1904*e4b17023SJohn Marino 				  ...
1905*e4b17023SJohn Marino 				  (set (REGX) (REGY))
1906*e4b17023SJohn Marino 				  (set (REGX) (PLUS (REGX) (CONST_INT B)))
1907*e4b17023SJohn Marino 		 to
1908*e4b17023SJohn Marino 				  (set (REGX) (REGY))
1909*e4b17023SJohn Marino 				  (set (REGX) (PLUS (REGX) (CONST_INT A)))
1910*e4b17023SJohn Marino 				  ...
1911*e4b17023SJohn Marino 				  (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
1912*e4b17023SJohn Marino 	      else if (REG_P (src)
1913*e4b17023SJohn Marino 		       && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
1914*e4b17023SJohn Marino 		       && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
1915*e4b17023SJohn Marino 		       && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg),
1916*e4b17023SJohn Marino 						 reg_mode[REGNO (src)]))
1917*e4b17023SJohn Marino 		{
1918*e4b17023SJohn Marino 		  rtx next = next_nonnote_nondebug_insn (insn);
1919*e4b17023SJohn Marino 		  rtx set = NULL_RTX;
1920*e4b17023SJohn Marino 		  if (next)
1921*e4b17023SJohn Marino 		    set = single_set (next);
1922*e4b17023SJohn Marino 		  if (set
1923*e4b17023SJohn Marino 		      && SET_DEST (set) == reg
1924*e4b17023SJohn Marino 		      && GET_CODE (SET_SRC (set)) == PLUS
1925*e4b17023SJohn Marino 		      && XEXP (SET_SRC (set), 0) == reg
1926*e4b17023SJohn Marino 		      && CONST_INT_P (XEXP (SET_SRC (set), 1)))
1927*e4b17023SJohn Marino 		    {
1928*e4b17023SJohn Marino 		      rtx src3 = XEXP (SET_SRC (set), 1);
1929*e4b17023SJohn Marino 		      HOST_WIDE_INT added_offset = INTVAL (src3);
1930*e4b17023SJohn Marino 		      HOST_WIDE_INT base_offset = reg_offset[REGNO (src)];
1931*e4b17023SJohn Marino 		      HOST_WIDE_INT regno_offset = reg_offset[regno];
1932*e4b17023SJohn Marino 		      rtx new_src =
1933*e4b17023SJohn Marino 			gen_int_mode (added_offset
1934*e4b17023SJohn Marino 				      + base_offset
1935*e4b17023SJohn Marino 				      - regno_offset,
1936*e4b17023SJohn Marino 				      GET_MODE (reg));
1937*e4b17023SJohn Marino 		      bool success = false;
1938*e4b17023SJohn Marino 		      bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
1939*e4b17023SJohn Marino 
1940*e4b17023SJohn Marino 		      if (new_src == const0_rtx)
1941*e4b17023SJohn Marino 			/* See above why we create (set (reg) (reg)) here.  */
1942*e4b17023SJohn Marino 			success
1943*e4b17023SJohn Marino 			  = validate_change (next, &SET_SRC (set), reg, 0);
1944*e4b17023SJohn Marino 		      else
1945*e4b17023SJohn Marino 			{
1946*e4b17023SJohn Marino 			  rtx old_src = SET_SRC (set);
1947*e4b17023SJohn Marino 			  struct full_rtx_costs oldcst, newcst;
1948*e4b17023SJohn Marino 			  rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
1949*e4b17023SJohn Marino 
1950*e4b17023SJohn Marino 			  get_full_set_rtx_cost (set, &oldcst);
1951*e4b17023SJohn Marino 			  SET_SRC (set) = tem;
1952*e4b17023SJohn Marino 			  get_full_set_src_cost (tem, &newcst);
1953*e4b17023SJohn Marino 			  SET_SRC (set) = old_src;
1954*e4b17023SJohn Marino 			  costs_add_n_insns (&oldcst, 1);
1955*e4b17023SJohn Marino 
1956*e4b17023SJohn Marino 			  if (costs_lt_p (&newcst, &oldcst, speed)
1957*e4b17023SJohn Marino 			      && have_add2_insn (reg, new_src))
1958*e4b17023SJohn Marino 			    {
1959*e4b17023SJohn Marino 			      rtx newpat = gen_rtx_SET (VOIDmode, reg, tem);
1960*e4b17023SJohn Marino 			      success
1961*e4b17023SJohn Marino 				= validate_change (next, &PATTERN (next),
1962*e4b17023SJohn Marino 						   newpat, 0);
1963*e4b17023SJohn Marino 			    }
1964*e4b17023SJohn Marino 			}
1965*e4b17023SJohn Marino 		      if (success)
1966*e4b17023SJohn Marino 			delete_insn (insn);
1967*e4b17023SJohn Marino 		      changed |= success;
1968*e4b17023SJohn Marino 		      insn = next;
1969*e4b17023SJohn Marino 		      reg_mode[regno] = GET_MODE (reg);
1970*e4b17023SJohn Marino 		      reg_offset[regno] =
1971*e4b17023SJohn Marino 			trunc_int_for_mode (added_offset + base_offset,
1972*e4b17023SJohn Marino 					    GET_MODE (reg));
1973*e4b17023SJohn Marino 		      continue;
1974*e4b17023SJohn Marino 		    }
1975*e4b17023SJohn Marino 		}
1976*e4b17023SJohn Marino 	    }
1977*e4b17023SJohn Marino 
1978*e4b17023SJohn Marino 	  /* Try to transform
1979*e4b17023SJohn Marino 	     (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
1980*e4b17023SJohn Marino 	     ...
1981*e4b17023SJohn Marino 	     (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B))))
1982*e4b17023SJohn Marino 	     to
1983*e4b17023SJohn Marino 	     (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
1984*e4b17023SJohn Marino 	     ...
1985*e4b17023SJohn Marino 	     (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A))))  */
1986*e4b17023SJohn Marino 	  if ((GET_CODE (src) == SYMBOL_REF
1987*e4b17023SJohn Marino 	       || (GET_CODE (src) == CONST
1988*e4b17023SJohn Marino 		   && GET_CODE (XEXP (src, 0)) == PLUS
1989*e4b17023SJohn Marino 		   && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF
1990*e4b17023SJohn Marino 		   && CONST_INT_P (XEXP (XEXP (src, 0), 1))))
1991*e4b17023SJohn Marino 	      && dbg_cnt (cse2_move2add))
1992*e4b17023SJohn Marino 	    {
1993*e4b17023SJohn Marino 	      rtx sym, off;
1994*e4b17023SJohn Marino 
1995*e4b17023SJohn Marino 	      if (GET_CODE (src) == SYMBOL_REF)
1996*e4b17023SJohn Marino 		{
1997*e4b17023SJohn Marino 		  sym = src;
1998*e4b17023SJohn Marino 		  off = const0_rtx;
1999*e4b17023SJohn Marino 		}
2000*e4b17023SJohn Marino 	      else
2001*e4b17023SJohn Marino 		{
2002*e4b17023SJohn Marino 		  sym = XEXP (XEXP (src, 0), 0);
2003*e4b17023SJohn Marino 		  off = XEXP (XEXP (src, 0), 1);
2004*e4b17023SJohn Marino 		}
2005*e4b17023SJohn Marino 
2006*e4b17023SJohn Marino 	      /* If the reg already contains the value which is sum of
2007*e4b17023SJohn Marino 		 sym and some constant value, we can use an add2 insn.  */
2008*e4b17023SJohn Marino 	      if (reg_set_luid[regno] > move2add_last_label_luid
2009*e4b17023SJohn Marino 		  && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
2010*e4b17023SJohn Marino 		  && reg_base_reg[regno] < 0
2011*e4b17023SJohn Marino 		  && reg_symbol_ref[regno] != NULL_RTX
2012*e4b17023SJohn Marino 		  && rtx_equal_p (sym, reg_symbol_ref[regno]))
2013*e4b17023SJohn Marino 		changed |= move2add_use_add2_insn (reg, sym, off, insn);
2014*e4b17023SJohn Marino 
2015*e4b17023SJohn Marino 	      /* Otherwise, we have to find a register whose value is sum
2016*e4b17023SJohn Marino 		 of sym and some constant value.  */
2017*e4b17023SJohn Marino 	      else
2018*e4b17023SJohn Marino 		changed |= move2add_use_add3_insn (reg, sym, off, insn);
2019*e4b17023SJohn Marino 
2020*e4b17023SJohn Marino 	      continue;
2021*e4b17023SJohn Marino 	    }
2022*e4b17023SJohn Marino 	}
2023*e4b17023SJohn Marino 
2024*e4b17023SJohn Marino       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
2025*e4b17023SJohn Marino 	{
2026*e4b17023SJohn Marino 	  if (REG_NOTE_KIND (note) == REG_INC
2027*e4b17023SJohn Marino 	      && REG_P (XEXP (note, 0)))
2028*e4b17023SJohn Marino 	    {
2029*e4b17023SJohn Marino 	      /* Reset the information about this register.  */
2030*e4b17023SJohn Marino 	      int regno = REGNO (XEXP (note, 0));
2031*e4b17023SJohn Marino 	      if (regno < FIRST_PSEUDO_REGISTER)
2032*e4b17023SJohn Marino 		reg_set_luid[regno] = 0;
2033*e4b17023SJohn Marino 	    }
2034*e4b17023SJohn Marino 	}
2035*e4b17023SJohn Marino       note_stores (PATTERN (insn), move2add_note_store, insn);
2036*e4b17023SJohn Marino 
2037*e4b17023SJohn Marino       /* If INSN is a conditional branch, we try to extract an
2038*e4b17023SJohn Marino 	 implicit set out of it.  */
2039*e4b17023SJohn Marino       if (any_condjump_p (insn))
2040*e4b17023SJohn Marino 	{
2041*e4b17023SJohn Marino 	  rtx cnd = fis_get_condition (insn);
2042*e4b17023SJohn Marino 
2043*e4b17023SJohn Marino 	  if (cnd != NULL_RTX
2044*e4b17023SJohn Marino 	      && GET_CODE (cnd) == NE
2045*e4b17023SJohn Marino 	      && REG_P (XEXP (cnd, 0))
2046*e4b17023SJohn Marino 	      && !reg_set_p (XEXP (cnd, 0), insn)
2047*e4b17023SJohn Marino 	      /* The following two checks, which are also in
2048*e4b17023SJohn Marino 		 move2add_note_store, are intended to reduce the
2049*e4b17023SJohn Marino 		 number of calls to gen_rtx_SET to avoid memory
2050*e4b17023SJohn Marino 		 allocation if possible.  */
2051*e4b17023SJohn Marino 	      && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0)))
2052*e4b17023SJohn Marino 	      && hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1
2053*e4b17023SJohn Marino 	      && CONST_INT_P (XEXP (cnd, 1)))
2054*e4b17023SJohn Marino 	    {
2055*e4b17023SJohn Marino 	      rtx implicit_set =
2056*e4b17023SJohn Marino 		gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1));
2057*e4b17023SJohn Marino 	      move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
2058*e4b17023SJohn Marino 	    }
2059*e4b17023SJohn Marino 	}
2060*e4b17023SJohn Marino 
2061*e4b17023SJohn Marino       /* If this is a CALL_INSN, all call used registers are stored with
2062*e4b17023SJohn Marino 	 unknown values.  */
2063*e4b17023SJohn Marino       if (CALL_P (insn))
2064*e4b17023SJohn Marino 	{
2065*e4b17023SJohn Marino 	  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
2066*e4b17023SJohn Marino 	    {
2067*e4b17023SJohn Marino 	      if (call_used_regs[i])
2068*e4b17023SJohn Marino 		/* Reset the information about this register.  */
2069*e4b17023SJohn Marino 		reg_set_luid[i] = 0;
2070*e4b17023SJohn Marino 	    }
2071*e4b17023SJohn Marino 	}
2072*e4b17023SJohn Marino     }
2073*e4b17023SJohn Marino   return changed;
2074*e4b17023SJohn Marino }
2075*e4b17023SJohn Marino 
2076*e4b17023SJohn Marino /* SET is a SET or CLOBBER that sets DST.  DATA is the insn which
2077*e4b17023SJohn Marino    contains SET.
2078*e4b17023SJohn Marino    Update reg_set_luid, reg_offset and reg_base_reg accordingly.
2079*e4b17023SJohn Marino    Called from reload_cse_move2add via note_stores.  */
2080*e4b17023SJohn Marino 
2081*e4b17023SJohn Marino static void
move2add_note_store(rtx dst,const_rtx set,void * data)2082*e4b17023SJohn Marino move2add_note_store (rtx dst, const_rtx set, void *data)
2083*e4b17023SJohn Marino {
2084*e4b17023SJohn Marino   rtx insn = (rtx) data;
2085*e4b17023SJohn Marino   unsigned int regno = 0;
2086*e4b17023SJohn Marino   unsigned int nregs = 0;
2087*e4b17023SJohn Marino   unsigned int i;
2088*e4b17023SJohn Marino   enum machine_mode mode = GET_MODE (dst);
2089*e4b17023SJohn Marino 
2090*e4b17023SJohn Marino   if (GET_CODE (dst) == SUBREG)
2091*e4b17023SJohn Marino     {
2092*e4b17023SJohn Marino       regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
2093*e4b17023SJohn Marino 				   GET_MODE (SUBREG_REG (dst)),
2094*e4b17023SJohn Marino 				   SUBREG_BYTE (dst),
2095*e4b17023SJohn Marino 				   GET_MODE (dst));
2096*e4b17023SJohn Marino       nregs = subreg_nregs (dst);
2097*e4b17023SJohn Marino       dst = SUBREG_REG (dst);
2098*e4b17023SJohn Marino     }
2099*e4b17023SJohn Marino 
2100*e4b17023SJohn Marino   /* Some targets do argument pushes without adding REG_INC notes.  */
2101*e4b17023SJohn Marino 
2102*e4b17023SJohn Marino   if (MEM_P (dst))
2103*e4b17023SJohn Marino     {
2104*e4b17023SJohn Marino       dst = XEXP (dst, 0);
2105*e4b17023SJohn Marino       if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
2106*e4b17023SJohn Marino 	  || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC)
2107*e4b17023SJohn Marino 	reg_set_luid[REGNO (XEXP (dst, 0))] = 0;
2108*e4b17023SJohn Marino       return;
2109*e4b17023SJohn Marino     }
2110*e4b17023SJohn Marino   if (!REG_P (dst))
2111*e4b17023SJohn Marino     return;
2112*e4b17023SJohn Marino 
2113*e4b17023SJohn Marino   regno += REGNO (dst);
2114*e4b17023SJohn Marino   if (!nregs)
2115*e4b17023SJohn Marino     nregs = hard_regno_nregs[regno][mode];
2116*e4b17023SJohn Marino 
2117*e4b17023SJohn Marino   if (SCALAR_INT_MODE_P (GET_MODE (dst))
2118*e4b17023SJohn Marino       && nregs == 1 && GET_CODE (set) == SET)
2119*e4b17023SJohn Marino     {
2120*e4b17023SJohn Marino       rtx note, sym = NULL_RTX;
2121*e4b17023SJohn Marino       HOST_WIDE_INT off;
2122*e4b17023SJohn Marino 
2123*e4b17023SJohn Marino       note = find_reg_equal_equiv_note (insn);
2124*e4b17023SJohn Marino       if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
2125*e4b17023SJohn Marino 	{
2126*e4b17023SJohn Marino 	  sym = XEXP (note, 0);
2127*e4b17023SJohn Marino 	  off = 0;
2128*e4b17023SJohn Marino 	}
2129*e4b17023SJohn Marino       else if (note && GET_CODE (XEXP (note, 0)) == CONST
2130*e4b17023SJohn Marino 	       && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
2131*e4b17023SJohn Marino 	       && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF
2132*e4b17023SJohn Marino 	       && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1)))
2133*e4b17023SJohn Marino 	{
2134*e4b17023SJohn Marino 	  sym = XEXP (XEXP (XEXP (note, 0), 0), 0);
2135*e4b17023SJohn Marino 	  off = INTVAL (XEXP (XEXP (XEXP (note, 0), 0), 1));
2136*e4b17023SJohn Marino 	}
2137*e4b17023SJohn Marino 
2138*e4b17023SJohn Marino       if (sym != NULL_RTX)
2139*e4b17023SJohn Marino 	{
2140*e4b17023SJohn Marino 	  reg_base_reg[regno] = -1;
2141*e4b17023SJohn Marino 	  reg_symbol_ref[regno] = sym;
2142*e4b17023SJohn Marino 	  reg_offset[regno] = off;
2143*e4b17023SJohn Marino 	  reg_mode[regno] = mode;
2144*e4b17023SJohn Marino 	  reg_set_luid[regno] = move2add_luid;
2145*e4b17023SJohn Marino 	  return;
2146*e4b17023SJohn Marino 	}
2147*e4b17023SJohn Marino     }
2148*e4b17023SJohn Marino 
2149*e4b17023SJohn Marino   if (SCALAR_INT_MODE_P (GET_MODE (dst))
2150*e4b17023SJohn Marino       && nregs == 1 && GET_CODE (set) == SET
2151*e4b17023SJohn Marino       && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
2152*e4b17023SJohn Marino       && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
2153*e4b17023SJohn Marino     {
2154*e4b17023SJohn Marino       rtx src = SET_SRC (set);
2155*e4b17023SJohn Marino       rtx base_reg;
2156*e4b17023SJohn Marino       HOST_WIDE_INT offset;
2157*e4b17023SJohn Marino       int base_regno;
2158*e4b17023SJohn Marino       /* This may be different from mode, if SET_DEST (set) is a
2159*e4b17023SJohn Marino 	 SUBREG.  */
2160*e4b17023SJohn Marino       enum machine_mode dst_mode = GET_MODE (dst);
2161*e4b17023SJohn Marino 
2162*e4b17023SJohn Marino       switch (GET_CODE (src))
2163*e4b17023SJohn Marino 	{
2164*e4b17023SJohn Marino 	case PLUS:
2165*e4b17023SJohn Marino 	  if (REG_P (XEXP (src, 0)))
2166*e4b17023SJohn Marino 	    {
2167*e4b17023SJohn Marino 	      base_reg = XEXP (src, 0);
2168*e4b17023SJohn Marino 
2169*e4b17023SJohn Marino 	      if (CONST_INT_P (XEXP (src, 1)))
2170*e4b17023SJohn Marino 		offset = INTVAL (XEXP (src, 1));
2171*e4b17023SJohn Marino 	      else if (REG_P (XEXP (src, 1))
2172*e4b17023SJohn Marino 		       && (reg_set_luid[REGNO (XEXP (src, 1))]
2173*e4b17023SJohn Marino 			   > move2add_last_label_luid)
2174*e4b17023SJohn Marino 		       && (MODES_OK_FOR_MOVE2ADD
2175*e4b17023SJohn Marino 			   (dst_mode, reg_mode[REGNO (XEXP (src, 1))])))
2176*e4b17023SJohn Marino 		{
2177*e4b17023SJohn Marino 		  if (reg_base_reg[REGNO (XEXP (src, 1))] < 0
2178*e4b17023SJohn Marino 		      && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX)
2179*e4b17023SJohn Marino 		    offset = reg_offset[REGNO (XEXP (src, 1))];
2180*e4b17023SJohn Marino 		  /* Maybe the first register is known to be a
2181*e4b17023SJohn Marino 		     constant.  */
2182*e4b17023SJohn Marino 		  else if (reg_set_luid[REGNO (base_reg)]
2183*e4b17023SJohn Marino 			   > move2add_last_label_luid
2184*e4b17023SJohn Marino 			   && (MODES_OK_FOR_MOVE2ADD
2185*e4b17023SJohn Marino 			       (dst_mode, reg_mode[REGNO (base_reg)]))
2186*e4b17023SJohn Marino 			   && reg_base_reg[REGNO (base_reg)] < 0
2187*e4b17023SJohn Marino 			   && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX)
2188*e4b17023SJohn Marino 		    {
2189*e4b17023SJohn Marino 		      offset = reg_offset[REGNO (base_reg)];
2190*e4b17023SJohn Marino 		      base_reg = XEXP (src, 1);
2191*e4b17023SJohn Marino 		    }
2192*e4b17023SJohn Marino 		  else
2193*e4b17023SJohn Marino 		    goto invalidate;
2194*e4b17023SJohn Marino 		}
2195*e4b17023SJohn Marino 	      else
2196*e4b17023SJohn Marino 		goto invalidate;
2197*e4b17023SJohn Marino 
2198*e4b17023SJohn Marino 	      break;
2199*e4b17023SJohn Marino 	    }
2200*e4b17023SJohn Marino 
2201*e4b17023SJohn Marino 	  goto invalidate;
2202*e4b17023SJohn Marino 
2203*e4b17023SJohn Marino 	case REG:
2204*e4b17023SJohn Marino 	  base_reg = src;
2205*e4b17023SJohn Marino 	  offset = 0;
2206*e4b17023SJohn Marino 	  break;
2207*e4b17023SJohn Marino 
2208*e4b17023SJohn Marino 	case CONST_INT:
2209*e4b17023SJohn Marino 	  /* Start tracking the register as a constant.  */
2210*e4b17023SJohn Marino 	  reg_base_reg[regno] = -1;
2211*e4b17023SJohn Marino 	  reg_symbol_ref[regno] = NULL_RTX;
2212*e4b17023SJohn Marino 	  reg_offset[regno] = INTVAL (SET_SRC (set));
2213*e4b17023SJohn Marino 	  /* We assign the same luid to all registers set to constants.  */
2214*e4b17023SJohn Marino 	  reg_set_luid[regno] = move2add_last_label_luid + 1;
2215*e4b17023SJohn Marino 	  reg_mode[regno] = mode;
2216*e4b17023SJohn Marino 	  return;
2217*e4b17023SJohn Marino 
2218*e4b17023SJohn Marino 	default:
2219*e4b17023SJohn Marino 	invalidate:
2220*e4b17023SJohn Marino 	  /* Invalidate the contents of the register.  */
2221*e4b17023SJohn Marino 	  reg_set_luid[regno] = 0;
2222*e4b17023SJohn Marino 	  return;
2223*e4b17023SJohn Marino 	}
2224*e4b17023SJohn Marino 
2225*e4b17023SJohn Marino       base_regno = REGNO (base_reg);
2226*e4b17023SJohn Marino       /* If information about the base register is not valid, set it
2227*e4b17023SJohn Marino 	 up as a new base register, pretending its value is known
2228*e4b17023SJohn Marino 	 starting from the current insn.  */
2229*e4b17023SJohn Marino       if (reg_set_luid[base_regno] <= move2add_last_label_luid)
2230*e4b17023SJohn Marino 	{
2231*e4b17023SJohn Marino 	  reg_base_reg[base_regno] = base_regno;
2232*e4b17023SJohn Marino 	  reg_symbol_ref[base_regno] = NULL_RTX;
2233*e4b17023SJohn Marino 	  reg_offset[base_regno] = 0;
2234*e4b17023SJohn Marino 	  reg_set_luid[base_regno] = move2add_luid;
2235*e4b17023SJohn Marino 	  reg_mode[base_regno] = mode;
2236*e4b17023SJohn Marino 	}
2237*e4b17023SJohn Marino       else if (! MODES_OK_FOR_MOVE2ADD (dst_mode,
2238*e4b17023SJohn Marino 					reg_mode[base_regno]))
2239*e4b17023SJohn Marino 	goto invalidate;
2240*e4b17023SJohn Marino 
2241*e4b17023SJohn Marino       reg_mode[regno] = mode;
2242*e4b17023SJohn Marino 
2243*e4b17023SJohn Marino       /* Copy base information from our base register.  */
2244*e4b17023SJohn Marino       reg_set_luid[regno] = reg_set_luid[base_regno];
2245*e4b17023SJohn Marino       reg_base_reg[regno] = reg_base_reg[base_regno];
2246*e4b17023SJohn Marino       reg_symbol_ref[regno] = reg_symbol_ref[base_regno];
2247*e4b17023SJohn Marino 
2248*e4b17023SJohn Marino       /* Compute the sum of the offsets or constants.  */
2249*e4b17023SJohn Marino       reg_offset[regno] = trunc_int_for_mode (offset
2250*e4b17023SJohn Marino 					      + reg_offset[base_regno],
2251*e4b17023SJohn Marino 					      dst_mode);
2252*e4b17023SJohn Marino     }
2253*e4b17023SJohn Marino   else
2254*e4b17023SJohn Marino     {
2255*e4b17023SJohn Marino       unsigned int endregno = regno + nregs;
2256*e4b17023SJohn Marino 
2257*e4b17023SJohn Marino       for (i = regno; i < endregno; i++)
2258*e4b17023SJohn Marino 	/* Reset the information about this register.  */
2259*e4b17023SJohn Marino 	reg_set_luid[i] = 0;
2260*e4b17023SJohn Marino     }
2261*e4b17023SJohn Marino }
2262*e4b17023SJohn Marino 
2263*e4b17023SJohn Marino static bool
gate_handle_postreload(void)2264*e4b17023SJohn Marino gate_handle_postreload (void)
2265*e4b17023SJohn Marino {
2266*e4b17023SJohn Marino   return (optimize > 0 && reload_completed);
2267*e4b17023SJohn Marino }
2268*e4b17023SJohn Marino 
2269*e4b17023SJohn Marino 
2270*e4b17023SJohn Marino static unsigned int
rest_of_handle_postreload(void)2271*e4b17023SJohn Marino rest_of_handle_postreload (void)
2272*e4b17023SJohn Marino {
2273*e4b17023SJohn Marino   if (!dbg_cnt (postreload_cse))
2274*e4b17023SJohn Marino     return 0;
2275*e4b17023SJohn Marino 
2276*e4b17023SJohn Marino   /* Do a very simple CSE pass over just the hard registers.  */
2277*e4b17023SJohn Marino   reload_cse_regs (get_insns ());
2278*e4b17023SJohn Marino   /* Reload_cse_regs can eliminate potentially-trapping MEMs.
2279*e4b17023SJohn Marino      Remove any EH edges associated with them.  */
2280*e4b17023SJohn Marino   if (cfun->can_throw_non_call_exceptions)
2281*e4b17023SJohn Marino     purge_all_dead_edges ();
2282*e4b17023SJohn Marino 
2283*e4b17023SJohn Marino   return 0;
2284*e4b17023SJohn Marino }
2285*e4b17023SJohn Marino 
2286*e4b17023SJohn Marino struct rtl_opt_pass pass_postreload_cse =
2287*e4b17023SJohn Marino {
2288*e4b17023SJohn Marino  {
2289*e4b17023SJohn Marino   RTL_PASS,
2290*e4b17023SJohn Marino   "postreload",                         /* name */
2291*e4b17023SJohn Marino   gate_handle_postreload,               /* gate */
2292*e4b17023SJohn Marino   rest_of_handle_postreload,            /* execute */
2293*e4b17023SJohn Marino   NULL,                                 /* sub */
2294*e4b17023SJohn Marino   NULL,                                 /* next */
2295*e4b17023SJohn Marino   0,                                    /* static_pass_number */
2296*e4b17023SJohn Marino   TV_RELOAD_CSE_REGS,                   /* tv_id */
2297*e4b17023SJohn Marino   0,                                    /* properties_required */
2298*e4b17023SJohn Marino   0,                                    /* properties_provided */
2299*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
2300*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
2301*e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
2302*e4b17023SJohn Marino   0                                     /* todo_flags_finish */
2303*e4b17023SJohn Marino  }
2304*e4b17023SJohn Marino };
2305