1132718Skan/* Perform simple optimizations to clean up the result of reload.
2132718Skan   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3169689Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4132718Skan
5132718SkanThis file is part of GCC.
6132718Skan
7132718SkanGCC is free software; you can redistribute it and/or modify it under
8132718Skanthe terms of the GNU General Public License as published by the Free
9132718SkanSoftware Foundation; either version 2, or (at your option) any later
10132718Skanversion.
11132718Skan
12132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14132718SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15132718Skanfor more details.
16132718Skan
17132718SkanYou should have received a copy of the GNU General Public License
18132718Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21132718Skan
22132718Skan#include "config.h"
23132718Skan#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
26132718Skan
27132718Skan#include "machmode.h"
28132718Skan#include "hard-reg-set.h"
29132718Skan#include "rtl.h"
30132718Skan#include "tm_p.h"
31132718Skan#include "obstack.h"
32132718Skan#include "insn-config.h"
33132718Skan#include "flags.h"
34132718Skan#include "function.h"
35132718Skan#include "expr.h"
36132718Skan#include "optabs.h"
37132718Skan#include "regs.h"
38132718Skan#include "basic-block.h"
39132718Skan#include "reload.h"
40132718Skan#include "recog.h"
41132718Skan#include "output.h"
42132718Skan#include "cselib.h"
43132718Skan#include "real.h"
44132718Skan#include "toplev.h"
45132718Skan#include "except.h"
46132718Skan#include "tree.h"
47169689Skan#include "timevar.h"
48169689Skan#include "tree-pass.h"
49132718Skan
50132718Skanstatic int reload_cse_noop_set_p (rtx);
51132718Skanstatic void reload_cse_simplify (rtx, rtx);
52132718Skanstatic void reload_cse_regs_1 (rtx);
53132718Skanstatic int reload_cse_simplify_set (rtx, rtx);
54132718Skanstatic int reload_cse_simplify_operands (rtx, rtx);
55132718Skan
56132718Skanstatic void reload_combine (void);
57132718Skanstatic void reload_combine_note_use (rtx *, rtx);
58132718Skanstatic void reload_combine_note_store (rtx, rtx, void *);
59132718Skan
60132718Skanstatic void reload_cse_move2add (rtx);
61132718Skanstatic void move2add_note_store (rtx, rtx, void *);
62132718Skan
63132718Skan/* Call cse / combine like post-reload optimization phases.
64132718Skan   FIRST is the first instruction.  */
65132718Skanvoid
66132718Skanreload_cse_regs (rtx first ATTRIBUTE_UNUSED)
67132718Skan{
68132718Skan  reload_cse_regs_1 (first);
69132718Skan  reload_combine ();
70132718Skan  reload_cse_move2add (first);
71132718Skan  if (flag_expensive_optimizations)
72132718Skan    reload_cse_regs_1 (first);
73132718Skan}
74132718Skan
75132718Skan/* See whether a single set SET is a noop.  */
76132718Skanstatic int
77132718Skanreload_cse_noop_set_p (rtx set)
78132718Skan{
79132718Skan  if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set)))
80132718Skan    return 0;
81132718Skan
82132718Skan  return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
83132718Skan}
84132718Skan
85132718Skan/* Try to simplify INSN.  */
86132718Skanstatic void
87132718Skanreload_cse_simplify (rtx insn, rtx testreg)
88132718Skan{
89132718Skan  rtx body = PATTERN (insn);
90132718Skan
91132718Skan  if (GET_CODE (body) == SET)
92132718Skan    {
93132718Skan      int count = 0;
94132718Skan
95132718Skan      /* Simplify even if we may think it is a no-op.
96132718Skan         We may think a memory load of a value smaller than WORD_SIZE
97132718Skan         is redundant because we haven't taken into account possible
98132718Skan         implicit extension.  reload_cse_simplify_set() will bring
99132718Skan         this out, so it's safer to simplify before we delete.  */
100132718Skan      count += reload_cse_simplify_set (body, insn);
101132718Skan
102132718Skan      if (!count && reload_cse_noop_set_p (body))
103132718Skan	{
104132718Skan	  rtx value = SET_DEST (body);
105132718Skan	  if (REG_P (value)
106132718Skan	      && ! REG_FUNCTION_VALUE_P (value))
107132718Skan	    value = 0;
108132718Skan	  delete_insn_and_edges (insn);
109132718Skan	  return;
110132718Skan	}
111132718Skan
112132718Skan      if (count > 0)
113132718Skan	apply_change_group ();
114132718Skan      else
115132718Skan	reload_cse_simplify_operands (insn, testreg);
116132718Skan    }
117132718Skan  else if (GET_CODE (body) == PARALLEL)
118132718Skan    {
119132718Skan      int i;
120132718Skan      int count = 0;
121132718Skan      rtx value = NULL_RTX;
122132718Skan
123146895Skan      /* Registers mentioned in the clobber list for an asm cannot be reused
124146895Skan	 within the body of the asm.  Invalidate those registers now so that
125146895Skan	 we don't try to substitute values for them.  */
126146895Skan      if (asm_noperands (body) >= 0)
127146895Skan	{
128146895Skan	  for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
129146895Skan	    {
130146895Skan	      rtx part = XVECEXP (body, 0, i);
131146895Skan	      if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
132146895Skan		cselib_invalidate_rtx (XEXP (part, 0));
133146895Skan	    }
134146895Skan	}
135146895Skan
136132718Skan      /* If every action in a PARALLEL is a noop, we can delete
137132718Skan	 the entire PARALLEL.  */
138132718Skan      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
139132718Skan	{
140132718Skan	  rtx part = XVECEXP (body, 0, i);
141132718Skan	  if (GET_CODE (part) == SET)
142132718Skan	    {
143132718Skan	      if (! reload_cse_noop_set_p (part))
144132718Skan		break;
145132718Skan	      if (REG_P (SET_DEST (part))
146132718Skan		  && REG_FUNCTION_VALUE_P (SET_DEST (part)))
147132718Skan		{
148132718Skan		  if (value)
149132718Skan		    break;
150132718Skan		  value = SET_DEST (part);
151132718Skan		}
152132718Skan	    }
153132718Skan	  else if (GET_CODE (part) != CLOBBER)
154132718Skan	    break;
155132718Skan	}
156132718Skan
157132718Skan      if (i < 0)
158132718Skan	{
159132718Skan	  delete_insn_and_edges (insn);
160132718Skan	  /* We're done with this insn.  */
161132718Skan	  return;
162132718Skan	}
163132718Skan
164132718Skan      /* It's not a no-op, but we can try to simplify it.  */
165132718Skan      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
166132718Skan	if (GET_CODE (XVECEXP (body, 0, i)) == SET)
167132718Skan	  count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
168132718Skan
169132718Skan      if (count > 0)
170132718Skan	apply_change_group ();
171132718Skan      else
172132718Skan	reload_cse_simplify_operands (insn, testreg);
173132718Skan    }
174132718Skan}
175132718Skan
176132718Skan/* Do a very simple CSE pass over the hard registers.
177132718Skan
178132718Skan   This function detects no-op moves where we happened to assign two
179132718Skan   different pseudo-registers to the same hard register, and then
180132718Skan   copied one to the other.  Reload will generate a useless
181132718Skan   instruction copying a register to itself.
182132718Skan
183132718Skan   This function also detects cases where we load a value from memory
184132718Skan   into two different registers, and (if memory is more expensive than
185132718Skan   registers) changes it to simply copy the first register into the
186132718Skan   second register.
187132718Skan
188132718Skan   Another optimization is performed that scans the operands of each
189132718Skan   instruction to see whether the value is already available in a
190132718Skan   hard register.  It then replaces the operand with the hard register
191132718Skan   if possible, much like an optional reload would.  */
192132718Skan
193132718Skanstatic void
194132718Skanreload_cse_regs_1 (rtx first)
195132718Skan{
196132718Skan  rtx insn;
197132718Skan  rtx testreg = gen_rtx_REG (VOIDmode, -1);
198132718Skan
199169689Skan  cselib_init (true);
200132718Skan  init_alias_analysis ();
201132718Skan
202132718Skan  for (insn = first; insn; insn = NEXT_INSN (insn))
203132718Skan    {
204132718Skan      if (INSN_P (insn))
205132718Skan	reload_cse_simplify (insn, testreg);
206132718Skan
207132718Skan      cselib_process_insn (insn);
208132718Skan    }
209132718Skan
210132718Skan  /* Clean up.  */
211132718Skan  end_alias_analysis ();
212132718Skan  cselib_finish ();
213132718Skan}
214132718Skan
215132718Skan/* Try to simplify a single SET instruction.  SET is the set pattern.
216132718Skan   INSN is the instruction it came from.
217132718Skan   This function only handles one case: if we set a register to a value
218132718Skan   which is not a register, we try to find that value in some other register
219132718Skan   and change the set into a register copy.  */
220132718Skan
221132718Skanstatic int
222132718Skanreload_cse_simplify_set (rtx set, rtx insn)
223132718Skan{
224132718Skan  int did_change = 0;
225132718Skan  int dreg;
226132718Skan  rtx src;
227132718Skan  enum reg_class dclass;
228132718Skan  int old_cost;
229132718Skan  cselib_val *val;
230132718Skan  struct elt_loc_list *l;
231132718Skan#ifdef LOAD_EXTEND_OP
232169689Skan  enum rtx_code extend_op = UNKNOWN;
233132718Skan#endif
234132718Skan
235132718Skan  dreg = true_regnum (SET_DEST (set));
236132718Skan  if (dreg < 0)
237132718Skan    return 0;
238132718Skan
239132718Skan  src = SET_SRC (set);
240132718Skan  if (side_effects_p (src) || true_regnum (src) >= 0)
241132718Skan    return 0;
242132718Skan
243132718Skan  dclass = REGNO_REG_CLASS (dreg);
244132718Skan
245132718Skan#ifdef LOAD_EXTEND_OP
246132718Skan  /* When replacing a memory with a register, we need to honor assumptions
247132718Skan     that combine made wrt the contents of sign bits.  We'll do this by
248132718Skan     generating an extend instruction instead of a reg->reg copy.  Thus
249132718Skan     the destination must be a register that we can widen.  */
250169689Skan  if (MEM_P (src)
251132718Skan      && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
252169689Skan      && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != UNKNOWN
253169689Skan      && !REG_P (SET_DEST (set)))
254132718Skan    return 0;
255132718Skan#endif
256132718Skan
257132718Skan  val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0);
258132718Skan  if (! val)
259132718Skan    return 0;
260132718Skan
261132718Skan  /* If memory loads are cheaper than register copies, don't change them.  */
262169689Skan  if (MEM_P (src))
263132718Skan    old_cost = MEMORY_MOVE_COST (GET_MODE (src), dclass, 1);
264169689Skan  else if (REG_P (src))
265132718Skan    old_cost = REGISTER_MOVE_COST (GET_MODE (src),
266132718Skan				   REGNO_REG_CLASS (REGNO (src)), dclass);
267132718Skan  else
268132718Skan    old_cost = rtx_cost (src, SET);
269132718Skan
270132718Skan  for (l = val->locs; l; l = l->next)
271132718Skan    {
272132718Skan      rtx this_rtx = l->loc;
273132718Skan      int this_cost;
274132718Skan
275132718Skan      if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
276132718Skan	{
277132718Skan#ifdef LOAD_EXTEND_OP
278169689Skan	  if (extend_op != UNKNOWN)
279132718Skan	    {
280132718Skan	      HOST_WIDE_INT this_val;
281132718Skan
282132718Skan	      /* ??? I'm lazy and don't wish to handle CONST_DOUBLE.  Other
283132718Skan		 constants, such as SYMBOL_REF, cannot be extended.  */
284132718Skan	      if (GET_CODE (this_rtx) != CONST_INT)
285132718Skan		continue;
286132718Skan
287132718Skan	      this_val = INTVAL (this_rtx);
288132718Skan	      switch (extend_op)
289132718Skan		{
290132718Skan		case ZERO_EXTEND:
291132718Skan		  this_val &= GET_MODE_MASK (GET_MODE (src));
292132718Skan		  break;
293132718Skan		case SIGN_EXTEND:
294132718Skan		  /* ??? In theory we're already extended.  */
295132718Skan		  if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
296132718Skan		    break;
297132718Skan		default:
298169689Skan		  gcc_unreachable ();
299132718Skan		}
300132718Skan	      this_rtx = GEN_INT (this_val);
301132718Skan	    }
302132718Skan#endif
303132718Skan	  this_cost = rtx_cost (this_rtx, SET);
304132718Skan	}
305169689Skan      else if (REG_P (this_rtx))
306132718Skan	{
307132718Skan#ifdef LOAD_EXTEND_OP
308169689Skan	  if (extend_op != UNKNOWN)
309132718Skan	    {
310132718Skan	      this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
311132718Skan	      this_cost = rtx_cost (this_rtx, SET);
312132718Skan	    }
313132718Skan	  else
314132718Skan#endif
315132718Skan	    this_cost = REGISTER_MOVE_COST (GET_MODE (this_rtx),
316132718Skan					    REGNO_REG_CLASS (REGNO (this_rtx)),
317132718Skan					    dclass);
318132718Skan	}
319132718Skan      else
320132718Skan	continue;
321132718Skan
322132718Skan      /* If equal costs, prefer registers over anything else.  That
323132718Skan	 tends to lead to smaller instructions on some machines.  */
324132718Skan      if (this_cost < old_cost
325132718Skan	  || (this_cost == old_cost
326169689Skan	      && REG_P (this_rtx)
327169689Skan	      && !REG_P (SET_SRC (set))))
328132718Skan	{
329132718Skan#ifdef LOAD_EXTEND_OP
330132718Skan	  if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
331169689Skan	      && extend_op != UNKNOWN
332132718Skan#ifdef CANNOT_CHANGE_MODE_CLASS
333132718Skan	      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
334132718Skan					    word_mode,
335132718Skan					    REGNO_REG_CLASS (REGNO (SET_DEST (set))))
336132718Skan#endif
337132718Skan	      )
338132718Skan	    {
339132718Skan	      rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
340132718Skan	      ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
341132718Skan	      validate_change (insn, &SET_DEST (set), wide_dest, 1);
342132718Skan	    }
343132718Skan#endif
344132718Skan
345132718Skan	  validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1);
346132718Skan	  old_cost = this_cost, did_change = 1;
347132718Skan	}
348132718Skan    }
349132718Skan
350132718Skan  return did_change;
351132718Skan}
352132718Skan
353132718Skan/* Try to replace operands in INSN with equivalent values that are already
354132718Skan   in registers.  This can be viewed as optional reloading.
355132718Skan
356132718Skan   For each non-register operand in the insn, see if any hard regs are
357132718Skan   known to be equivalent to that operand.  Record the alternatives which
358132718Skan   can accept these hard registers.  Among all alternatives, select the
359132718Skan   ones which are better or equal to the one currently matching, where
360132718Skan   "better" is in terms of '?' and '!' constraints.  Among the remaining
361132718Skan   alternatives, select the one which replaces most operands with
362132718Skan   hard registers.  */
363132718Skan
364132718Skanstatic int
365132718Skanreload_cse_simplify_operands (rtx insn, rtx testreg)
366132718Skan{
367132718Skan  int i, j;
368132718Skan
369132718Skan  /* For each operand, all registers that are equivalent to it.  */
370132718Skan  HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS];
371132718Skan
372132718Skan  const char *constraints[MAX_RECOG_OPERANDS];
373132718Skan
374132718Skan  /* Vector recording how bad an alternative is.  */
375132718Skan  int *alternative_reject;
376132718Skan  /* Vector recording how many registers can be introduced by choosing
377132718Skan     this alternative.  */
378132718Skan  int *alternative_nregs;
379132718Skan  /* Array of vectors recording, for each operand and each alternative,
380132718Skan     which hard register to substitute, or -1 if the operand should be
381132718Skan     left as it is.  */
382132718Skan  int *op_alt_regno[MAX_RECOG_OPERANDS];
383132718Skan  /* Array of alternatives, sorted in order of decreasing desirability.  */
384132718Skan  int *alternative_order;
385132718Skan
386132718Skan  extract_insn (insn);
387132718Skan
388132718Skan  if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
389132718Skan    return 0;
390132718Skan
391132718Skan  /* Figure out which alternative currently matches.  */
392132718Skan  if (! constrain_operands (1))
393132718Skan    fatal_insn_not_found (insn);
394132718Skan
395132718Skan  alternative_reject = alloca (recog_data.n_alternatives * sizeof (int));
396132718Skan  alternative_nregs = alloca (recog_data.n_alternatives * sizeof (int));
397132718Skan  alternative_order = alloca (recog_data.n_alternatives * sizeof (int));
398132718Skan  memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
399132718Skan  memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
400132718Skan
401132718Skan  /* For each operand, find out which regs are equivalent.  */
402132718Skan  for (i = 0; i < recog_data.n_operands; i++)
403132718Skan    {
404132718Skan      cselib_val *v;
405132718Skan      struct elt_loc_list *l;
406132718Skan      rtx op;
407132718Skan      enum machine_mode mode;
408132718Skan
409132718Skan      CLEAR_HARD_REG_SET (equiv_regs[i]);
410132718Skan
411132718Skan      /* cselib blows up on CODE_LABELs.  Trying to fix that doesn't seem
412132718Skan	 right, so avoid the problem here.  Likewise if we have a constant
413132718Skan         and the insn pattern doesn't tell us the mode we need.  */
414169689Skan      if (LABEL_P (recog_data.operand[i])
415132718Skan	  || (CONSTANT_P (recog_data.operand[i])
416132718Skan	      && recog_data.operand_mode[i] == VOIDmode))
417132718Skan	continue;
418132718Skan
419132718Skan      op = recog_data.operand[i];
420132718Skan      mode = GET_MODE (op);
421132718Skan#ifdef LOAD_EXTEND_OP
422169689Skan      if (MEM_P (op)
423132718Skan	  && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
424169689Skan	  && LOAD_EXTEND_OP (mode) != UNKNOWN)
425132718Skan	{
426132718Skan	  rtx set = single_set (insn);
427132718Skan
428169689Skan	  /* We might have multiple sets, some of which do implicit
429132718Skan	     extension.  Punt on this for now.  */
430132718Skan	  if (! set)
431132718Skan	    continue;
432169689Skan	  /* If the destination is also a MEM or a STRICT_LOW_PART, no
433132718Skan	     extension applies.
434132718Skan	     Also, if there is an explicit extension, we don't have to
435132718Skan	     worry about an implicit one.  */
436169689Skan	  else if (MEM_P (SET_DEST (set))
437132718Skan		   || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART
438132718Skan		   || GET_CODE (SET_SRC (set)) == ZERO_EXTEND
439132718Skan		   || GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
440132718Skan	    ; /* Continue ordinary processing.  */
441132718Skan#ifdef CANNOT_CHANGE_MODE_CLASS
442132718Skan	  /* If the register cannot change mode to word_mode, it follows that
443132718Skan	     it cannot have been used in word_mode.  */
444169689Skan	  else if (REG_P (SET_DEST (set))
445132718Skan		   && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
446132718Skan						word_mode,
447132718Skan						REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
448132718Skan	    ; /* Continue ordinary processing.  */
449132718Skan#endif
450132718Skan	  /* If this is a straight load, make the extension explicit.  */
451169689Skan	  else if (REG_P (SET_DEST (set))
452132718Skan		   && recog_data.n_operands == 2
453132718Skan		   && SET_SRC (set) == op
454132718Skan		   && SET_DEST (set) == recog_data.operand[1-i])
455132718Skan	    {
456132718Skan	      validate_change (insn, recog_data.operand_loc[i],
457132718Skan			       gen_rtx_fmt_e (LOAD_EXTEND_OP (mode),
458132718Skan					      word_mode, op),
459132718Skan			       1);
460132718Skan	      validate_change (insn, recog_data.operand_loc[1-i],
461132718Skan			       gen_rtx_REG (word_mode, REGNO (SET_DEST (set))),
462132718Skan			       1);
463132718Skan	      if (! apply_change_group ())
464132718Skan		return 0;
465132718Skan	      return reload_cse_simplify_operands (insn, testreg);
466132718Skan	    }
467132718Skan	  else
468132718Skan	    /* ??? There might be arithmetic operations with memory that are
469132718Skan	       safe to optimize, but is it worth the trouble?  */
470132718Skan	    continue;
471132718Skan	}
472132718Skan#endif /* LOAD_EXTEND_OP */
473132718Skan      v = cselib_lookup (op, recog_data.operand_mode[i], 0);
474132718Skan      if (! v)
475132718Skan	continue;
476132718Skan
477132718Skan      for (l = v->locs; l; l = l->next)
478169689Skan	if (REG_P (l->loc))
479132718Skan	  SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
480132718Skan    }
481132718Skan
482132718Skan  for (i = 0; i < recog_data.n_operands; i++)
483132718Skan    {
484132718Skan      enum machine_mode mode;
485132718Skan      int regno;
486132718Skan      const char *p;
487132718Skan
488132718Skan      op_alt_regno[i] = alloca (recog_data.n_alternatives * sizeof (int));
489132718Skan      for (j = 0; j < recog_data.n_alternatives; j++)
490132718Skan	op_alt_regno[i][j] = -1;
491132718Skan
492132718Skan      p = constraints[i] = recog_data.constraints[i];
493132718Skan      mode = recog_data.operand_mode[i];
494132718Skan
495132718Skan      /* Add the reject values for each alternative given by the constraints
496132718Skan	 for this operand.  */
497132718Skan      j = 0;
498132718Skan      while (*p != '\0')
499132718Skan	{
500132718Skan	  char c = *p++;
501132718Skan	  if (c == ',')
502132718Skan	    j++;
503132718Skan	  else if (c == '?')
504132718Skan	    alternative_reject[j] += 3;
505132718Skan	  else if (c == '!')
506132718Skan	    alternative_reject[j] += 300;
507132718Skan	}
508132718Skan
509132718Skan      /* We won't change operands which are already registers.  We
510132718Skan	 also don't want to modify output operands.  */
511132718Skan      regno = true_regnum (recog_data.operand[i]);
512132718Skan      if (regno >= 0
513132718Skan	  || constraints[i][0] == '='
514132718Skan	  || constraints[i][0] == '+')
515132718Skan	continue;
516132718Skan
517132718Skan      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
518132718Skan	{
519132718Skan	  int class = (int) NO_REGS;
520132718Skan
521132718Skan	  if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
522132718Skan	    continue;
523132718Skan
524132718Skan	  REGNO (testreg) = regno;
525132718Skan	  PUT_MODE (testreg, mode);
526132718Skan
527132718Skan	  /* We found a register equal to this operand.  Now look for all
528132718Skan	     alternatives that can accept this register and have not been
529132718Skan	     assigned a register they can use yet.  */
530132718Skan	  j = 0;
531132718Skan	  p = constraints[i];
532132718Skan	  for (;;)
533132718Skan	    {
534132718Skan	      char c = *p;
535132718Skan
536132718Skan	      switch (c)
537132718Skan		{
538132718Skan		case '=':  case '+':  case '?':
539132718Skan		case '#':  case '&':  case '!':
540132718Skan		case '*':  case '%':
541132718Skan		case '0':  case '1':  case '2':  case '3':  case '4':
542132718Skan		case '5':  case '6':  case '7':  case '8':  case '9':
543132718Skan		case 'm':  case '<':  case '>':  case 'V':  case 'o':
544132718Skan		case 'E':  case 'F':  case 'G':  case 'H':
545132718Skan		case 's':  case 'i':  case 'n':
546132718Skan		case 'I':  case 'J':  case 'K':  case 'L':
547132718Skan		case 'M':  case 'N':  case 'O':  case 'P':
548132718Skan		case 'p': case 'X':
549132718Skan		  /* These don't say anything we care about.  */
550132718Skan		  break;
551132718Skan
552132718Skan		case 'g': case 'r':
553132718Skan		  class = reg_class_subunion[(int) class][(int) GENERAL_REGS];
554132718Skan		  break;
555132718Skan
556132718Skan		default:
557132718Skan		  class
558132718Skan		    = (reg_class_subunion
559132718Skan		       [(int) class]
560132718Skan		       [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
561132718Skan		  break;
562132718Skan
563132718Skan		case ',': case '\0':
564132718Skan		  /* See if REGNO fits this alternative, and set it up as the
565132718Skan		     replacement register if we don't have one for this
566132718Skan		     alternative yet and the operand being replaced is not
567132718Skan		     a cheap CONST_INT.  */
568132718Skan		  if (op_alt_regno[i][j] == -1
569132718Skan		      && reg_fits_class_p (testreg, class, 0, mode)
570132718Skan		      && (GET_CODE (recog_data.operand[i]) != CONST_INT
571132718Skan			  || (rtx_cost (recog_data.operand[i], SET)
572132718Skan			      > rtx_cost (testreg, SET))))
573132718Skan		    {
574132718Skan		      alternative_nregs[j]++;
575132718Skan		      op_alt_regno[i][j] = regno;
576132718Skan		    }
577132718Skan		  j++;
578169689Skan		  class = (int) NO_REGS;
579132718Skan		  break;
580132718Skan		}
581132718Skan	      p += CONSTRAINT_LEN (c, p);
582132718Skan
583132718Skan	      if (c == '\0')
584132718Skan		break;
585132718Skan	    }
586132718Skan	}
587132718Skan    }
588132718Skan
589132718Skan  /* Record all alternatives which are better or equal to the currently
590132718Skan     matching one in the alternative_order array.  */
591132718Skan  for (i = j = 0; i < recog_data.n_alternatives; i++)
592132718Skan    if (alternative_reject[i] <= alternative_reject[which_alternative])
593132718Skan      alternative_order[j++] = i;
594132718Skan  recog_data.n_alternatives = j;
595132718Skan
596132718Skan  /* Sort it.  Given a small number of alternatives, a dumb algorithm
597132718Skan     won't hurt too much.  */
598132718Skan  for (i = 0; i < recog_data.n_alternatives - 1; i++)
599132718Skan    {
600132718Skan      int best = i;
601132718Skan      int best_reject = alternative_reject[alternative_order[i]];
602132718Skan      int best_nregs = alternative_nregs[alternative_order[i]];
603132718Skan      int tmp;
604132718Skan
605132718Skan      for (j = i + 1; j < recog_data.n_alternatives; j++)
606132718Skan	{
607132718Skan	  int this_reject = alternative_reject[alternative_order[j]];
608132718Skan	  int this_nregs = alternative_nregs[alternative_order[j]];
609132718Skan
610132718Skan	  if (this_reject < best_reject
611169689Skan	      || (this_reject == best_reject && this_nregs > best_nregs))
612132718Skan	    {
613132718Skan	      best = j;
614132718Skan	      best_reject = this_reject;
615132718Skan	      best_nregs = this_nregs;
616132718Skan	    }
617132718Skan	}
618132718Skan
619132718Skan      tmp = alternative_order[best];
620132718Skan      alternative_order[best] = alternative_order[i];
621132718Skan      alternative_order[i] = tmp;
622132718Skan    }
623132718Skan
624132718Skan  /* Substitute the operands as determined by op_alt_regno for the best
625132718Skan     alternative.  */
626132718Skan  j = alternative_order[0];
627132718Skan
628132718Skan  for (i = 0; i < recog_data.n_operands; i++)
629132718Skan    {
630132718Skan      enum machine_mode mode = recog_data.operand_mode[i];
631132718Skan      if (op_alt_regno[i][j] == -1)
632132718Skan	continue;
633132718Skan
634132718Skan      validate_change (insn, recog_data.operand_loc[i],
635132718Skan		       gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
636132718Skan    }
637132718Skan
638132718Skan  for (i = recog_data.n_dups - 1; i >= 0; i--)
639132718Skan    {
640132718Skan      int op = recog_data.dup_num[i];
641132718Skan      enum machine_mode mode = recog_data.operand_mode[op];
642132718Skan
643132718Skan      if (op_alt_regno[op][j] == -1)
644132718Skan	continue;
645132718Skan
646132718Skan      validate_change (insn, recog_data.dup_loc[i],
647132718Skan		       gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
648132718Skan    }
649132718Skan
650132718Skan  return apply_change_group ();
651132718Skan}
652132718Skan
653132718Skan/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
654132718Skan   addressing now.
655132718Skan   This code might also be useful when reload gave up on reg+reg addressing
656132718Skan   because of clashes between the return register and INDEX_REG_CLASS.  */
657132718Skan
658132718Skan/* The maximum number of uses of a register we can keep track of to
659132718Skan   replace them with reg+reg addressing.  */
660132718Skan#define RELOAD_COMBINE_MAX_USES 6
661132718Skan
662132718Skan/* INSN is the insn where a register has ben used, and USEP points to the
663132718Skan   location of the register within the rtl.  */
664132718Skanstruct reg_use { rtx insn, *usep; };
665132718Skan
666132718Skan/* If the register is used in some unknown fashion, USE_INDEX is negative.
667132718Skan   If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
668132718Skan   indicates where it becomes live again.
669132718Skan   Otherwise, USE_INDEX is the index of the last encountered use of the
670132718Skan   register (which is first among these we have seen since we scan backwards),
671132718Skan   OFFSET contains the constant offset that is added to the register in
672132718Skan   all encountered uses, and USE_RUID indicates the first encountered, i.e.
673132718Skan   last, of these uses.
674132718Skan   STORE_RUID is always meaningful if we only want to use a value in a
675132718Skan   register in a different place: it denotes the next insn in the insn
676132718Skan   stream (i.e. the last encountered) that sets or clobbers the register.  */
677132718Skanstatic struct
678132718Skan  {
679132718Skan    struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
680132718Skan    int use_index;
681132718Skan    rtx offset;
682132718Skan    int store_ruid;
683132718Skan    int use_ruid;
684132718Skan  } reg_state[FIRST_PSEUDO_REGISTER];
685132718Skan
686132718Skan/* Reverse linear uid.  This is increased in reload_combine while scanning
687132718Skan   the instructions from last to first.  It is used to set last_label_ruid
688132718Skan   and the store_ruid / use_ruid fields in reg_state.  */
689132718Skanstatic int reload_combine_ruid;
690132718Skan
691132718Skan#define LABEL_LIVE(LABEL) \
692132718Skan  (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
693132718Skan
694132718Skanstatic void
695132718Skanreload_combine (void)
696132718Skan{
697132718Skan  rtx insn, set;
698132718Skan  int first_index_reg = -1;
699132718Skan  int last_index_reg = 0;
700132718Skan  int i;
701132718Skan  basic_block bb;
702132718Skan  unsigned int r;
703132718Skan  int last_label_ruid;
704132718Skan  int min_labelno, n_labels;
705132718Skan  HARD_REG_SET ever_live_at_start, *label_live;
706132718Skan
707132718Skan  /* If reg+reg can be used in offsetable memory addresses, the main chunk of
708132718Skan     reload has already used it where appropriate, so there is no use in
709132718Skan     trying to generate it now.  */
710132718Skan  if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
711132718Skan    return;
712132718Skan
713132718Skan  /* To avoid wasting too much time later searching for an index register,
714132718Skan     determine the minimum and maximum index register numbers.  */
715132718Skan  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
716132718Skan    if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
717132718Skan      {
718132718Skan	if (first_index_reg == -1)
719132718Skan	  first_index_reg = r;
720132718Skan
721132718Skan	last_index_reg = r;
722132718Skan      }
723132718Skan
724132718Skan  /* If no index register is available, we can quit now.  */
725132718Skan  if (first_index_reg == -1)
726132718Skan    return;
727132718Skan
728132718Skan  /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
729132718Skan     information is a bit fuzzy immediately after reload, but it's
730132718Skan     still good enough to determine which registers are live at a jump
731132718Skan     destination.  */
732132718Skan  min_labelno = get_first_label_num ();
733132718Skan  n_labels = max_label_num () - min_labelno;
734169689Skan  label_live = XNEWVEC (HARD_REG_SET, n_labels);
735132718Skan  CLEAR_HARD_REG_SET (ever_live_at_start);
736132718Skan
737132718Skan  FOR_EACH_BB_REVERSE (bb)
738132718Skan    {
739132718Skan      insn = BB_HEAD (bb);
740169689Skan      if (LABEL_P (insn))
741132718Skan	{
742132718Skan	  HARD_REG_SET live;
743132718Skan
744132718Skan	  REG_SET_TO_HARD_REG_SET (live,
745169689Skan				   bb->il.rtl->global_live_at_start);
746132718Skan	  compute_use_by_pseudos (&live,
747169689Skan				  bb->il.rtl->global_live_at_start);
748132718Skan	  COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
749132718Skan	  IOR_HARD_REG_SET (ever_live_at_start, live);
750132718Skan	}
751132718Skan    }
752132718Skan
753132718Skan  /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
754132718Skan  last_label_ruid = reload_combine_ruid = 0;
755132718Skan  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
756132718Skan    {
757132718Skan      reg_state[r].store_ruid = reload_combine_ruid;
758132718Skan      if (fixed_regs[r])
759132718Skan	reg_state[r].use_index = -1;
760132718Skan      else
761132718Skan	reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
762132718Skan    }
763132718Skan
764132718Skan  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
765132718Skan    {
766132718Skan      rtx note;
767132718Skan
768132718Skan      /* We cannot do our optimization across labels.  Invalidating all the use
769132718Skan	 information we have would be costly, so we just note where the label
770132718Skan	 is and then later disable any optimization that would cross it.  */
771169689Skan      if (LABEL_P (insn))
772132718Skan	last_label_ruid = reload_combine_ruid;
773169689Skan      else if (BARRIER_P (insn))
774132718Skan	for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
775132718Skan	  if (! fixed_regs[r])
776132718Skan	      reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
777132718Skan
778132718Skan      if (! INSN_P (insn))
779132718Skan	continue;
780132718Skan
781132718Skan      reload_combine_ruid++;
782132718Skan
783132718Skan      /* Look for (set (REGX) (CONST_INT))
784132718Skan	 (set (REGX) (PLUS (REGX) (REGY)))
785132718Skan	 ...
786132718Skan	 ... (MEM (REGX)) ...
787132718Skan	 and convert it to
788132718Skan	 (set (REGZ) (CONST_INT))
789132718Skan	 ...
790132718Skan	 ... (MEM (PLUS (REGZ) (REGY)))... .
791132718Skan
792132718Skan	 First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
793132718Skan	 and that we know all uses of REGX before it dies.
794132718Skan	 Also, explicitly check that REGX != REGY; our life information
795132718Skan	 does not yet show whether REGY changes in this insn.  */
796132718Skan      set = single_set (insn);
797132718Skan      if (set != NULL_RTX
798169689Skan	  && REG_P (SET_DEST (set))
799169689Skan	  && (hard_regno_nregs[REGNO (SET_DEST (set))]
800169689Skan			      [GET_MODE (SET_DEST (set))]
801132718Skan	      == 1)
802132718Skan	  && GET_CODE (SET_SRC (set)) == PLUS
803169689Skan	  && REG_P (XEXP (SET_SRC (set), 1))
804132718Skan	  && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
805132718Skan	  && !rtx_equal_p (XEXP (SET_SRC (set), 1), SET_DEST (set))
806132718Skan	  && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
807132718Skan	{
808132718Skan	  rtx reg = SET_DEST (set);
809132718Skan	  rtx plus = SET_SRC (set);
810132718Skan	  rtx base = XEXP (plus, 1);
811132718Skan	  rtx prev = prev_nonnote_insn (insn);
812132718Skan	  rtx prev_set = prev ? single_set (prev) : NULL_RTX;
813132718Skan	  unsigned int regno = REGNO (reg);
814132718Skan	  rtx const_reg = NULL_RTX;
815132718Skan	  rtx reg_sum = NULL_RTX;
816132718Skan
817132718Skan	  /* Now, we need an index register.
818132718Skan	     We'll set index_reg to this index register, const_reg to the
819132718Skan	     register that is to be loaded with the constant
820132718Skan	     (denoted as REGZ in the substitution illustration above),
821132718Skan	     and reg_sum to the register-register that we want to use to
822132718Skan	     substitute uses of REG (typically in MEMs) with.
823132718Skan	     First check REG and BASE for being index registers;
824132718Skan	     we can use them even if they are not dead.  */
825132718Skan	  if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
826132718Skan	      || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
827132718Skan				    REGNO (base)))
828132718Skan	    {
829132718Skan	      const_reg = reg;
830132718Skan	      reg_sum = plus;
831132718Skan	    }
832132718Skan	  else
833132718Skan	    {
834132718Skan	      /* Otherwise, look for a free index register.  Since we have
835132718Skan		 checked above that neither REG nor BASE are index registers,
836132718Skan		 if we find anything at all, it will be different from these
837132718Skan		 two registers.  */
838132718Skan	      for (i = first_index_reg; i <= last_index_reg; i++)
839132718Skan		{
840132718Skan		  if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
841132718Skan					 i)
842132718Skan		      && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
843132718Skan		      && reg_state[i].store_ruid <= reg_state[regno].use_ruid
844169689Skan		      && hard_regno_nregs[i][GET_MODE (reg)] == 1)
845132718Skan		    {
846132718Skan		      rtx index_reg = gen_rtx_REG (GET_MODE (reg), i);
847132718Skan
848132718Skan		      const_reg = index_reg;
849132718Skan		      reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
850132718Skan		      break;
851132718Skan		    }
852132718Skan		}
853132718Skan	    }
854132718Skan
855132718Skan	  /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
856132718Skan	     (REGY), i.e. BASE, is not clobbered before the last use we'll
857132718Skan	     create.  */
858132718Skan	  if (prev_set != 0
859132718Skan	      && GET_CODE (SET_SRC (prev_set)) == CONST_INT
860132718Skan	      && rtx_equal_p (SET_DEST (prev_set), reg)
861132718Skan	      && reg_state[regno].use_index >= 0
862132718Skan	      && (reg_state[REGNO (base)].store_ruid
863132718Skan		  <= reg_state[regno].use_ruid)
864132718Skan	      && reg_sum != 0)
865132718Skan	    {
866132718Skan	      int i;
867132718Skan
868132718Skan	      /* Change destination register and, if necessary, the
869132718Skan		 constant value in PREV, the constant loading instruction.  */
870132718Skan	      validate_change (prev, &SET_DEST (prev_set), const_reg, 1);
871132718Skan	      if (reg_state[regno].offset != const0_rtx)
872132718Skan		validate_change (prev,
873132718Skan				 &SET_SRC (prev_set),
874132718Skan				 GEN_INT (INTVAL (SET_SRC (prev_set))
875132718Skan					  + INTVAL (reg_state[regno].offset)),
876132718Skan				 1);
877132718Skan
878132718Skan	      /* Now for every use of REG that we have recorded, replace REG
879132718Skan		 with REG_SUM.  */
880132718Skan	      for (i = reg_state[regno].use_index;
881132718Skan		   i < RELOAD_COMBINE_MAX_USES; i++)
882132718Skan		validate_change (reg_state[regno].reg_use[i].insn,
883132718Skan				 reg_state[regno].reg_use[i].usep,
884132718Skan				 /* Each change must have its own
885132718Skan				    replacement.  */
886132718Skan				 copy_rtx (reg_sum), 1);
887132718Skan
888132718Skan	      if (apply_change_group ())
889132718Skan		{
890132718Skan		  rtx *np;
891132718Skan
892132718Skan		  /* Delete the reg-reg addition.  */
893132718Skan		  delete_insn (insn);
894132718Skan
895132718Skan		  if (reg_state[regno].offset != const0_rtx)
896132718Skan		    /* Previous REG_EQUIV / REG_EQUAL notes for PREV
897132718Skan		       are now invalid.  */
898132718Skan		    for (np = &REG_NOTES (prev); *np;)
899132718Skan		      {
900132718Skan			if (REG_NOTE_KIND (*np) == REG_EQUAL
901132718Skan			    || REG_NOTE_KIND (*np) == REG_EQUIV)
902132718Skan			  *np = XEXP (*np, 1);
903132718Skan			else
904132718Skan			  np = &XEXP (*np, 1);
905132718Skan		      }
906132718Skan
907132718Skan		  reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
908132718Skan		  reg_state[REGNO (const_reg)].store_ruid
909132718Skan		    = reload_combine_ruid;
910132718Skan		  continue;
911132718Skan		}
912132718Skan	    }
913132718Skan	}
914132718Skan
915132718Skan      note_stores (PATTERN (insn), reload_combine_note_store, NULL);
916132718Skan
917169689Skan      if (CALL_P (insn))
918132718Skan	{
919132718Skan	  rtx link;
920132718Skan
921132718Skan	  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
922132718Skan	    if (call_used_regs[r])
923132718Skan	      {
924132718Skan		reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
925132718Skan		reg_state[r].store_ruid = reload_combine_ruid;
926132718Skan	      }
927132718Skan
928132718Skan	  for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
929132718Skan	       link = XEXP (link, 1))
930132718Skan	    {
931132718Skan	      rtx usage_rtx = XEXP (XEXP (link, 0), 0);
932169689Skan	      if (REG_P (usage_rtx))
933132718Skan	        {
934132718Skan		  unsigned int i;
935132718Skan		  unsigned int start_reg = REGNO (usage_rtx);
936132718Skan		  unsigned int num_regs =
937169689Skan			hard_regno_nregs[start_reg][GET_MODE (usage_rtx)];
938132718Skan		  unsigned int end_reg  = start_reg + num_regs - 1;
939132718Skan		  for (i = start_reg; i <= end_reg; i++)
940132718Skan		    if (GET_CODE (XEXP (link, 0)) == CLOBBER)
941132718Skan		      {
942132718Skan		        reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
943132718Skan		        reg_state[i].store_ruid = reload_combine_ruid;
944132718Skan		      }
945132718Skan		    else
946132718Skan		      reg_state[i].use_index = -1;
947132718Skan	         }
948132718Skan	     }
949132718Skan
950132718Skan	}
951169689Skan      else if (JUMP_P (insn)
952132718Skan	       && GET_CODE (PATTERN (insn)) != RETURN)
953132718Skan	{
954132718Skan	  /* Non-spill registers might be used at the call destination in
955132718Skan	     some unknown fashion, so we have to mark the unknown use.  */
956132718Skan	  HARD_REG_SET *live;
957132718Skan
958132718Skan	  if ((condjump_p (insn) || condjump_in_parallel_p (insn))
959132718Skan	      && JUMP_LABEL (insn))
960132718Skan	    live = &LABEL_LIVE (JUMP_LABEL (insn));
961132718Skan	  else
962132718Skan	    live = &ever_live_at_start;
963132718Skan
964132718Skan	  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
965132718Skan	    if (TEST_HARD_REG_BIT (*live, i))
966132718Skan	      reg_state[i].use_index = -1;
967132718Skan	}
968132718Skan
969132718Skan      reload_combine_note_use (&PATTERN (insn), insn);
970132718Skan      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
971132718Skan	{
972132718Skan	  if (REG_NOTE_KIND (note) == REG_INC
973169689Skan	      && REG_P (XEXP (note, 0)))
974132718Skan	    {
975132718Skan	      int regno = REGNO (XEXP (note, 0));
976132718Skan
977132718Skan	      reg_state[regno].store_ruid = reload_combine_ruid;
978132718Skan	      reg_state[regno].use_index = -1;
979132718Skan	    }
980132718Skan	}
981132718Skan    }
982132718Skan
983132718Skan  free (label_live);
984132718Skan}
985132718Skan
986132718Skan/* Check if DST is a register or a subreg of a register; if it is,
987132718Skan   update reg_state[regno].store_ruid and reg_state[regno].use_index
988132718Skan   accordingly.  Called via note_stores from reload_combine.  */
989132718Skan
990132718Skanstatic void
991132718Skanreload_combine_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
992132718Skan{
993132718Skan  int regno = 0;
994132718Skan  int i;
995132718Skan  enum machine_mode mode = GET_MODE (dst);
996132718Skan
997132718Skan  if (GET_CODE (dst) == SUBREG)
998132718Skan    {
999132718Skan      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
1000132718Skan				   GET_MODE (SUBREG_REG (dst)),
1001132718Skan				   SUBREG_BYTE (dst),
1002132718Skan				   GET_MODE (dst));
1003132718Skan      dst = SUBREG_REG (dst);
1004132718Skan    }
1005169689Skan  if (!REG_P (dst))
1006132718Skan    return;
1007132718Skan  regno += REGNO (dst);
1008132718Skan
1009132718Skan  /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
1010132718Skan     careful with registers / register parts that are not full words.
1011169689Skan     Similarly for ZERO_EXTRACT.  */
1012132718Skan  if (GET_CODE (set) != SET
1013132718Skan      || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
1014132718Skan      || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
1015132718Skan    {
1016169689Skan      for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
1017132718Skan	{
1018132718Skan	  reg_state[i].use_index = -1;
1019132718Skan	  reg_state[i].store_ruid = reload_combine_ruid;
1020132718Skan	}
1021132718Skan    }
1022132718Skan  else
1023132718Skan    {
1024169689Skan      for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
1025132718Skan	{
1026132718Skan	  reg_state[i].store_ruid = reload_combine_ruid;
1027132718Skan	  reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
1028132718Skan	}
1029132718Skan    }
1030132718Skan}
1031132718Skan
1032132718Skan/* XP points to a piece of rtl that has to be checked for any uses of
1033132718Skan   registers.
1034132718Skan   *XP is the pattern of INSN, or a part of it.
1035132718Skan   Called from reload_combine, and recursively by itself.  */
1036132718Skanstatic void
1037132718Skanreload_combine_note_use (rtx *xp, rtx insn)
1038132718Skan{
1039132718Skan  rtx x = *xp;
1040132718Skan  enum rtx_code code = x->code;
1041132718Skan  const char *fmt;
1042132718Skan  int i, j;
1043132718Skan  rtx offset = const0_rtx; /* For the REG case below.  */
1044132718Skan
1045132718Skan  switch (code)
1046132718Skan    {
1047132718Skan    case SET:
1048169689Skan      if (REG_P (SET_DEST (x)))
1049132718Skan	{
1050132718Skan	  reload_combine_note_use (&SET_SRC (x), insn);
1051132718Skan	  return;
1052132718Skan	}
1053132718Skan      break;
1054132718Skan
1055132718Skan    case USE:
1056132718Skan      /* If this is the USE of a return value, we can't change it.  */
1057169689Skan      if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
1058132718Skan	{
1059132718Skan	/* Mark the return register as used in an unknown fashion.  */
1060132718Skan	  rtx reg = XEXP (x, 0);
1061132718Skan	  int regno = REGNO (reg);
1062169689Skan	  int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
1063132718Skan
1064132718Skan	  while (--nregs >= 0)
1065132718Skan	    reg_state[regno + nregs].use_index = -1;
1066132718Skan	  return;
1067132718Skan	}
1068132718Skan      break;
1069132718Skan
1070132718Skan    case CLOBBER:
1071169689Skan      if (REG_P (SET_DEST (x)))
1072132718Skan	{
1073132718Skan	  /* No spurious CLOBBERs of pseudo registers may remain.  */
1074169689Skan	  gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER);
1075132718Skan	  return;
1076132718Skan	}
1077132718Skan      break;
1078132718Skan
1079132718Skan    case PLUS:
1080132718Skan      /* We are interested in (plus (reg) (const_int)) .  */
1081169689Skan      if (!REG_P (XEXP (x, 0))
1082132718Skan	  || GET_CODE (XEXP (x, 1)) != CONST_INT)
1083132718Skan	break;
1084132718Skan      offset = XEXP (x, 1);
1085132718Skan      x = XEXP (x, 0);
1086132718Skan      /* Fall through.  */
1087132718Skan    case REG:
1088132718Skan      {
1089132718Skan	int regno = REGNO (x);
1090132718Skan	int use_index;
1091132718Skan	int nregs;
1092132718Skan
1093132718Skan	/* No spurious USEs of pseudo registers may remain.  */
1094169689Skan	gcc_assert (regno < FIRST_PSEUDO_REGISTER);
1095132718Skan
1096169689Skan	nregs = hard_regno_nregs[regno][GET_MODE (x)];
1097132718Skan
1098132718Skan	/* We can't substitute into multi-hard-reg uses.  */
1099132718Skan	if (nregs > 1)
1100132718Skan	  {
1101132718Skan	    while (--nregs >= 0)
1102132718Skan	      reg_state[regno + nregs].use_index = -1;
1103132718Skan	    return;
1104132718Skan	  }
1105132718Skan
1106132718Skan	/* If this register is already used in some unknown fashion, we
1107132718Skan	   can't do anything.
1108132718Skan	   If we decrement the index from zero to -1, we can't store more
1109132718Skan	   uses, so this register becomes used in an unknown fashion.  */
1110132718Skan	use_index = --reg_state[regno].use_index;
1111132718Skan	if (use_index < 0)
1112132718Skan	  return;
1113132718Skan
1114132718Skan	if (use_index != RELOAD_COMBINE_MAX_USES - 1)
1115132718Skan	  {
1116132718Skan	    /* We have found another use for a register that is already
1117132718Skan	       used later.  Check if the offsets match; if not, mark the
1118132718Skan	       register as used in an unknown fashion.  */
1119132718Skan	    if (! rtx_equal_p (offset, reg_state[regno].offset))
1120132718Skan	      {
1121132718Skan		reg_state[regno].use_index = -1;
1122132718Skan		return;
1123132718Skan	      }
1124132718Skan	  }
1125132718Skan	else
1126132718Skan	  {
1127132718Skan	    /* This is the first use of this register we have seen since we
1128132718Skan	       marked it as dead.  */
1129132718Skan	    reg_state[regno].offset = offset;
1130132718Skan	    reg_state[regno].use_ruid = reload_combine_ruid;
1131132718Skan	  }
1132132718Skan	reg_state[regno].reg_use[use_index].insn = insn;
1133132718Skan	reg_state[regno].reg_use[use_index].usep = xp;
1134132718Skan	return;
1135132718Skan      }
1136132718Skan
1137132718Skan    default:
1138132718Skan      break;
1139132718Skan    }
1140132718Skan
1141132718Skan  /* Recursively process the components of X.  */
1142132718Skan  fmt = GET_RTX_FORMAT (code);
1143132718Skan  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1144132718Skan    {
1145132718Skan      if (fmt[i] == 'e')
1146132718Skan	reload_combine_note_use (&XEXP (x, i), insn);
1147132718Skan      else if (fmt[i] == 'E')
1148132718Skan	{
1149132718Skan	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1150132718Skan	    reload_combine_note_use (&XVECEXP (x, i, j), insn);
1151132718Skan	}
1152132718Skan    }
1153132718Skan}
1154132718Skan
1155132718Skan/* See if we can reduce the cost of a constant by replacing a move
1156132718Skan   with an add.  We track situations in which a register is set to a
1157132718Skan   constant or to a register plus a constant.  */
1158132718Skan/* We cannot do our optimization across labels.  Invalidating all the
1159132718Skan   information about register contents we have would be costly, so we
1160132718Skan   use move2add_last_label_luid to note where the label is and then
1161132718Skan   later disable any optimization that would cross it.
1162132718Skan   reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
1163132718Skan   reg_set_luid[n] is greater than move2add_last_label_luid.  */
1164132718Skanstatic int reg_set_luid[FIRST_PSEUDO_REGISTER];
1165132718Skan
1166132718Skan/* If reg_base_reg[n] is negative, register n has been set to
1167132718Skan   reg_offset[n] in mode reg_mode[n] .
1168132718Skan   If reg_base_reg[n] is non-negative, register n has been set to the
1169132718Skan   sum of reg_offset[n] and the value of register reg_base_reg[n]
1170132718Skan   before reg_set_luid[n], calculated in mode reg_mode[n] .  */
1171132718Skanstatic HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
1172132718Skanstatic int reg_base_reg[FIRST_PSEUDO_REGISTER];
1173132718Skanstatic enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
1174132718Skan
1175132718Skan/* move2add_luid is linearly increased while scanning the instructions
1176132718Skan   from first to last.  It is used to set reg_set_luid in
1177132718Skan   reload_cse_move2add and move2add_note_store.  */
1178132718Skanstatic int move2add_luid;
1179132718Skan
1180132718Skan/* move2add_last_label_luid is set whenever a label is found.  Labels
1181132718Skan   invalidate all previously collected reg_offset data.  */
1182132718Skanstatic int move2add_last_label_luid;
1183132718Skan
1184132718Skan/* ??? We don't know how zero / sign extension is handled, hence we
1185132718Skan   can't go from a narrower to a wider mode.  */
1186132718Skan#define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \
1187132718Skan  (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \
1188132718Skan   || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \
1189132718Skan       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \
1190132718Skan				 GET_MODE_BITSIZE (INMODE))))
1191132718Skan
1192132718Skanstatic void
1193132718Skanreload_cse_move2add (rtx first)
1194132718Skan{
1195132718Skan  int i;
1196132718Skan  rtx insn;
1197132718Skan
1198132718Skan  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
1199132718Skan    reg_set_luid[i] = 0;
1200132718Skan
1201132718Skan  move2add_last_label_luid = 0;
1202132718Skan  move2add_luid = 2;
1203132718Skan  for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
1204132718Skan    {
1205132718Skan      rtx pat, note;
1206132718Skan
1207169689Skan      if (LABEL_P (insn))
1208132718Skan	{
1209132718Skan	  move2add_last_label_luid = move2add_luid;
1210132718Skan	  /* We're going to increment move2add_luid twice after a
1211132718Skan	     label, so that we can use move2add_last_label_luid + 1 as
1212132718Skan	     the luid for constants.  */
1213132718Skan	  move2add_luid++;
1214132718Skan	  continue;
1215132718Skan	}
1216132718Skan      if (! INSN_P (insn))
1217132718Skan	continue;
1218132718Skan      pat = PATTERN (insn);
1219132718Skan      /* For simplicity, we only perform this optimization on
1220132718Skan	 straightforward SETs.  */
1221132718Skan      if (GET_CODE (pat) == SET
1222169689Skan	  && REG_P (SET_DEST (pat)))
1223132718Skan	{
1224132718Skan	  rtx reg = SET_DEST (pat);
1225132718Skan	  int regno = REGNO (reg);
1226132718Skan	  rtx src = SET_SRC (pat);
1227132718Skan
1228132718Skan	  /* Check if we have valid information on the contents of this
1229132718Skan	     register in the mode of REG.  */
1230132718Skan	  if (reg_set_luid[regno] > move2add_last_label_luid
1231132718Skan	      && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]))
1232132718Skan	    {
1233132718Skan	      /* Try to transform (set (REGX) (CONST_INT A))
1234132718Skan				  ...
1235132718Skan				  (set (REGX) (CONST_INT B))
1236132718Skan		 to
1237132718Skan				  (set (REGX) (CONST_INT A))
1238132718Skan				  ...
1239132718Skan				  (set (REGX) (plus (REGX) (CONST_INT B-A)))
1240132718Skan		 or
1241132718Skan				  (set (REGX) (CONST_INT A))
1242132718Skan				  ...
1243132718Skan				  (set (STRICT_LOW_PART (REGX)) (CONST_INT B))
1244132718Skan	      */
1245132718Skan
1246132718Skan	      if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0)
1247132718Skan		{
1248169689Skan		  rtx new_src = gen_int_mode (INTVAL (src) - reg_offset[regno],
1249169689Skan					      GET_MODE (reg));
1250132718Skan		  /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
1251132718Skan		     use (set (reg) (reg)) instead.
1252132718Skan		     We don't delete this insn, nor do we convert it into a
1253132718Skan		     note, to avoid losing register notes or the return
1254132718Skan		     value flag.  jump2 already knows how to get rid of
1255132718Skan		     no-op moves.  */
1256132718Skan		  if (new_src == const0_rtx)
1257132718Skan		    {
1258132718Skan		      /* If the constants are different, this is a
1259132718Skan			 truncation, that, if turned into (set (reg)
1260132718Skan			 (reg)), would be discarded.  Maybe we should
1261132718Skan			 try a truncMN pattern?  */
1262132718Skan		      if (INTVAL (src) == reg_offset [regno])
1263132718Skan			validate_change (insn, &SET_SRC (pat), reg, 0);
1264132718Skan		    }
1265132718Skan		  else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET)
1266132718Skan			   && have_add2_insn (reg, new_src))
1267132718Skan		    {
1268169689Skan		      rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
1269169689Skan		      validate_change (insn, &SET_SRC (pat), tem, 0);
1270132718Skan		    }
1271169689Skan		  else if (GET_MODE (reg) != BImode)
1272132718Skan		    {
1273132718Skan		      enum machine_mode narrow_mode;
1274132718Skan		      for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
1275169689Skan			   narrow_mode != VOIDmode
1276169689Skan			   && narrow_mode != GET_MODE (reg);
1277132718Skan			   narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
1278132718Skan			{
1279132718Skan			  if (have_insn_for (STRICT_LOW_PART, narrow_mode)
1280132718Skan			      && ((reg_offset[regno]
1281132718Skan				   & ~GET_MODE_MASK (narrow_mode))
1282132718Skan				  == (INTVAL (src)
1283132718Skan				      & ~GET_MODE_MASK (narrow_mode))))
1284132718Skan			    {
1285132718Skan			      rtx narrow_reg = gen_rtx_REG (narrow_mode,
1286132718Skan							    REGNO (reg));
1287169689Skan			      rtx narrow_src = gen_int_mode (INTVAL (src),
1288169689Skan							     narrow_mode);
1289132718Skan			      rtx new_set =
1290132718Skan				gen_rtx_SET (VOIDmode,
1291132718Skan					     gen_rtx_STRICT_LOW_PART (VOIDmode,
1292132718Skan								      narrow_reg),
1293132718Skan					     narrow_src);
1294132718Skan			      if (validate_change (insn, &PATTERN (insn),
1295132718Skan						   new_set, 0))
1296132718Skan				break;
1297132718Skan			    }
1298132718Skan			}
1299132718Skan		    }
1300132718Skan		  reg_set_luid[regno] = move2add_luid;
1301132718Skan		  reg_mode[regno] = GET_MODE (reg);
1302132718Skan		  reg_offset[regno] = INTVAL (src);
1303132718Skan		  continue;
1304132718Skan		}
1305132718Skan
1306132718Skan	      /* Try to transform (set (REGX) (REGY))
1307132718Skan				  (set (REGX) (PLUS (REGX) (CONST_INT A)))
1308132718Skan				  ...
1309132718Skan				  (set (REGX) (REGY))
1310132718Skan				  (set (REGX) (PLUS (REGX) (CONST_INT B)))
1311132718Skan		 to
1312132718Skan				  (set (REGX) (REGY))
1313132718Skan				  (set (REGX) (PLUS (REGX) (CONST_INT A)))
1314132718Skan				  ...
1315132718Skan				  (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
1316169689Skan	      else if (REG_P (src)
1317132718Skan		       && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
1318132718Skan		       && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
1319132718Skan		       && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg),
1320132718Skan						 reg_mode[REGNO (src)]))
1321132718Skan		{
1322132718Skan		  rtx next = next_nonnote_insn (insn);
1323132718Skan		  rtx set = NULL_RTX;
1324132718Skan		  if (next)
1325132718Skan		    set = single_set (next);
1326132718Skan		  if (set
1327132718Skan		      && SET_DEST (set) == reg
1328132718Skan		      && GET_CODE (SET_SRC (set)) == PLUS
1329132718Skan		      && XEXP (SET_SRC (set), 0) == reg
1330132718Skan		      && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
1331132718Skan		    {
1332132718Skan		      rtx src3 = XEXP (SET_SRC (set), 1);
1333132718Skan		      HOST_WIDE_INT added_offset = INTVAL (src3);
1334132718Skan		      HOST_WIDE_INT base_offset = reg_offset[REGNO (src)];
1335132718Skan		      HOST_WIDE_INT regno_offset = reg_offset[regno];
1336132718Skan		      rtx new_src =
1337169689Skan			gen_int_mode (added_offset
1338169689Skan				      + base_offset
1339169689Skan				      - regno_offset,
1340169689Skan				      GET_MODE (reg));
1341132718Skan		      int success = 0;
1342132718Skan
1343132718Skan		      if (new_src == const0_rtx)
1344132718Skan			/* See above why we create (set (reg) (reg)) here.  */
1345132718Skan			success
1346132718Skan			  = validate_change (next, &SET_SRC (set), reg, 0);
1347132718Skan		      else if ((rtx_cost (new_src, PLUS)
1348132718Skan				< COSTS_N_INSNS (1) + rtx_cost (src3, SET))
1349132718Skan			       && have_add2_insn (reg, new_src))
1350132718Skan			{
1351132718Skan			  rtx newpat = gen_rtx_SET (VOIDmode,
1352132718Skan						    reg,
1353132718Skan						    gen_rtx_PLUS (GET_MODE (reg),
1354132718Skan						 		  reg,
1355132718Skan								  new_src));
1356132718Skan			  success
1357132718Skan			    = validate_change (next, &PATTERN (next),
1358132718Skan					       newpat, 0);
1359132718Skan			}
1360132718Skan		      if (success)
1361132718Skan			delete_insn (insn);
1362132718Skan		      insn = next;
1363132718Skan		      reg_mode[regno] = GET_MODE (reg);
1364132718Skan		      reg_offset[regno] =
1365132718Skan			trunc_int_for_mode (added_offset + base_offset,
1366132718Skan					    GET_MODE (reg));
1367132718Skan		      continue;
1368132718Skan		    }
1369132718Skan		}
1370132718Skan	    }
1371132718Skan	}
1372132718Skan
1373132718Skan      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1374132718Skan	{
1375132718Skan	  if (REG_NOTE_KIND (note) == REG_INC
1376169689Skan	      && REG_P (XEXP (note, 0)))
1377132718Skan	    {
1378132718Skan	      /* Reset the information about this register.  */
1379132718Skan	      int regno = REGNO (XEXP (note, 0));
1380132718Skan	      if (regno < FIRST_PSEUDO_REGISTER)
1381132718Skan		reg_set_luid[regno] = 0;
1382132718Skan	    }
1383132718Skan	}
1384132718Skan      note_stores (PATTERN (insn), move2add_note_store, NULL);
1385132718Skan
1386132718Skan      /* If INSN is a conditional branch, we try to extract an
1387132718Skan	 implicit set out of it.  */
1388169689Skan      if (any_condjump_p (insn))
1389132718Skan	{
1390132718Skan	  rtx cnd = fis_get_condition (insn);
1391132718Skan
1392132718Skan	  if (cnd != NULL_RTX
1393132718Skan	      && GET_CODE (cnd) == NE
1394169689Skan	      && REG_P (XEXP (cnd, 0))
1395169689Skan	      && !reg_set_p (XEXP (cnd, 0), insn)
1396132718Skan	      /* The following two checks, which are also in
1397132718Skan		 move2add_note_store, are intended to reduce the
1398132718Skan		 number of calls to gen_rtx_SET to avoid memory
1399132718Skan		 allocation if possible.  */
1400132718Skan	      && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0)))
1401169689Skan	      && hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1
1402132718Skan	      && GET_CODE (XEXP (cnd, 1)) == CONST_INT)
1403132718Skan	    {
1404132718Skan	      rtx implicit_set =
1405132718Skan		gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1));
1406132718Skan	      move2add_note_store (SET_DEST (implicit_set), implicit_set, 0);
1407132718Skan	    }
1408132718Skan	}
1409132718Skan
1410132718Skan      /* If this is a CALL_INSN, all call used registers are stored with
1411132718Skan	 unknown values.  */
1412169689Skan      if (CALL_P (insn))
1413132718Skan	{
1414132718Skan	  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
1415132718Skan	    {
1416132718Skan	      if (call_used_regs[i])
1417132718Skan		/* Reset the information about this register.  */
1418132718Skan		reg_set_luid[i] = 0;
1419132718Skan	    }
1420132718Skan	}
1421132718Skan    }
1422132718Skan}
1423132718Skan
1424132718Skan/* SET is a SET or CLOBBER that sets DST.
1425132718Skan   Update reg_set_luid, reg_offset and reg_base_reg accordingly.
1426132718Skan   Called from reload_cse_move2add via note_stores.  */
1427132718Skan
1428132718Skanstatic void
1429132718Skanmove2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
1430132718Skan{
1431132718Skan  unsigned int regno = 0;
1432132718Skan  unsigned int i;
1433132718Skan  enum machine_mode mode = GET_MODE (dst);
1434132718Skan
1435132718Skan  if (GET_CODE (dst) == SUBREG)
1436132718Skan    {
1437132718Skan      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
1438132718Skan				   GET_MODE (SUBREG_REG (dst)),
1439132718Skan				   SUBREG_BYTE (dst),
1440132718Skan				   GET_MODE (dst));
1441132718Skan      dst = SUBREG_REG (dst);
1442132718Skan    }
1443132718Skan
1444132718Skan  /* Some targets do argument pushes without adding REG_INC notes.  */
1445132718Skan
1446169689Skan  if (MEM_P (dst))
1447132718Skan    {
1448132718Skan      dst = XEXP (dst, 0);
1449132718Skan      if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
1450132718Skan	  || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC)
1451132718Skan	reg_set_luid[REGNO (XEXP (dst, 0))] = 0;
1452132718Skan      return;
1453132718Skan    }
1454169689Skan  if (!REG_P (dst))
1455132718Skan    return;
1456132718Skan
1457132718Skan  regno += REGNO (dst);
1458132718Skan
1459169689Skan  if (SCALAR_INT_MODE_P (GET_MODE (dst))
1460169689Skan      && hard_regno_nregs[regno][mode] == 1 && GET_CODE (set) == SET
1461132718Skan      && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
1462132718Skan      && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
1463132718Skan    {
1464132718Skan      rtx src = SET_SRC (set);
1465132718Skan      rtx base_reg;
1466132718Skan      HOST_WIDE_INT offset;
1467132718Skan      int base_regno;
1468132718Skan      /* This may be different from mode, if SET_DEST (set) is a
1469132718Skan	 SUBREG.  */
1470132718Skan      enum machine_mode dst_mode = GET_MODE (dst);
1471132718Skan
1472132718Skan      switch (GET_CODE (src))
1473132718Skan	{
1474132718Skan	case PLUS:
1475169689Skan	  if (REG_P (XEXP (src, 0)))
1476132718Skan	    {
1477132718Skan	      base_reg = XEXP (src, 0);
1478132718Skan
1479132718Skan	      if (GET_CODE (XEXP (src, 1)) == CONST_INT)
1480132718Skan		offset = INTVAL (XEXP (src, 1));
1481169689Skan	      else if (REG_P (XEXP (src, 1))
1482132718Skan		       && (reg_set_luid[REGNO (XEXP (src, 1))]
1483132718Skan			   > move2add_last_label_luid)
1484132718Skan		       && (MODES_OK_FOR_MOVE2ADD
1485132718Skan			   (dst_mode, reg_mode[REGNO (XEXP (src, 1))])))
1486132718Skan		{
1487132718Skan		  if (reg_base_reg[REGNO (XEXP (src, 1))] < 0)
1488132718Skan		    offset = reg_offset[REGNO (XEXP (src, 1))];
1489132718Skan		  /* Maybe the first register is known to be a
1490132718Skan		     constant.  */
1491132718Skan		  else if (reg_set_luid[REGNO (base_reg)]
1492132718Skan			   > move2add_last_label_luid
1493132718Skan			   && (MODES_OK_FOR_MOVE2ADD
1494132718Skan			       (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))
1495132718Skan			   && reg_base_reg[REGNO (base_reg)] < 0)
1496132718Skan		    {
1497132718Skan		      offset = reg_offset[REGNO (base_reg)];
1498132718Skan		      base_reg = XEXP (src, 1);
1499132718Skan		    }
1500132718Skan		  else
1501132718Skan		    goto invalidate;
1502132718Skan		}
1503132718Skan	      else
1504132718Skan		goto invalidate;
1505132718Skan
1506132718Skan	      break;
1507132718Skan	    }
1508132718Skan
1509132718Skan	  goto invalidate;
1510132718Skan
1511132718Skan	case REG:
1512132718Skan	  base_reg = src;
1513132718Skan	  offset = 0;
1514132718Skan	  break;
1515132718Skan
1516132718Skan	case CONST_INT:
1517132718Skan	  /* Start tracking the register as a constant.  */
1518132718Skan	  reg_base_reg[regno] = -1;
1519132718Skan	  reg_offset[regno] = INTVAL (SET_SRC (set));
1520132718Skan	  /* We assign the same luid to all registers set to constants.  */
1521132718Skan	  reg_set_luid[regno] = move2add_last_label_luid + 1;
1522132718Skan	  reg_mode[regno] = mode;
1523132718Skan	  return;
1524132718Skan
1525132718Skan	default:
1526132718Skan	invalidate:
1527132718Skan	  /* Invalidate the contents of the register.  */
1528132718Skan	  reg_set_luid[regno] = 0;
1529132718Skan	  return;
1530132718Skan	}
1531132718Skan
1532132718Skan      base_regno = REGNO (base_reg);
1533132718Skan      /* If information about the base register is not valid, set it
1534132718Skan	 up as a new base register, pretending its value is known
1535132718Skan	 starting from the current insn.  */
1536132718Skan      if (reg_set_luid[base_regno] <= move2add_last_label_luid)
1537132718Skan	{
1538132718Skan	  reg_base_reg[base_regno] = base_regno;
1539132718Skan	  reg_offset[base_regno] = 0;
1540132718Skan	  reg_set_luid[base_regno] = move2add_luid;
1541132718Skan	  reg_mode[base_regno] = mode;
1542132718Skan	}
1543132718Skan      else if (! MODES_OK_FOR_MOVE2ADD (dst_mode,
1544132718Skan					reg_mode[base_regno]))
1545132718Skan	goto invalidate;
1546132718Skan
1547132718Skan      reg_mode[regno] = mode;
1548132718Skan
1549132718Skan      /* Copy base information from our base register.  */
1550132718Skan      reg_set_luid[regno] = reg_set_luid[base_regno];
1551132718Skan      reg_base_reg[regno] = reg_base_reg[base_regno];
1552132718Skan
1553132718Skan      /* Compute the sum of the offsets or constants.  */
1554132718Skan      reg_offset[regno] = trunc_int_for_mode (offset
1555132718Skan					      + reg_offset[base_regno],
1556132718Skan					      dst_mode);
1557132718Skan    }
1558132718Skan  else
1559132718Skan    {
1560169689Skan      unsigned int endregno = regno + hard_regno_nregs[regno][mode];
1561132718Skan
1562132718Skan      for (i = regno; i < endregno; i++)
1563132718Skan	/* Reset the information about this register.  */
1564132718Skan	reg_set_luid[i] = 0;
1565132718Skan    }
1566132718Skan}
1567169689Skan
1568169689Skanstatic bool
1569169689Skangate_handle_postreload (void)
1570169689Skan{
1571169689Skan  return (optimize > 0);
1572169689Skan}
1573169689Skan
1574169689Skan
1575169689Skanstatic unsigned int
1576169689Skanrest_of_handle_postreload (void)
1577169689Skan{
1578169689Skan  /* Do a very simple CSE pass over just the hard registers.  */
1579169689Skan  reload_cse_regs (get_insns ());
1580169689Skan  /* reload_cse_regs can eliminate potentially-trapping MEMs.
1581169689Skan     Remove any EH edges associated with them.  */
1582169689Skan  if (flag_non_call_exceptions)
1583169689Skan    purge_all_dead_edges ();
1584169689Skan  return 0;
1585169689Skan}
1586169689Skan
1587169689Skanstruct tree_opt_pass pass_postreload_cse =
1588169689Skan{
1589169689Skan  "postreload",                         /* name */
1590169689Skan  gate_handle_postreload,               /* gate */
1591169689Skan  rest_of_handle_postreload,            /* execute */
1592169689Skan  NULL,                                 /* sub */
1593169689Skan  NULL,                                 /* next */
1594169689Skan  0,                                    /* static_pass_number */
1595169689Skan  TV_RELOAD_CSE_REGS,                   /* tv_id */
1596169689Skan  0,                                    /* properties_required */
1597169689Skan  0,                                    /* properties_provided */
1598169689Skan  0,                                    /* properties_destroyed */
1599169689Skan  0,                                    /* todo_flags_start */
1600169689Skan  TODO_dump_func,                       /* todo_flags_finish */
1601169689Skan  'o'                                   /* letter */
1602169689Skan};
1603169689Skan
1604