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 (®_state[i].use_ruid, split_ruid);
761*e4b17023SJohn Marino reload_combine_split_one_ruid (®_state[i].store_ruid, split_ruid);
762*e4b17023SJohn Marino reload_combine_split_one_ruid (®_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 (®_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