1*e4b17023SJohn Marino /* Register renaming for the GNU compiler.
2*e4b17023SJohn Marino Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3*e4b17023SJohn Marino 2010 Free Software Foundation, Inc.
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino any later version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14*e4b17023SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15*e4b17023SJohn Marino License for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "rtl-error.h"
26*e4b17023SJohn Marino #include "tm_p.h"
27*e4b17023SJohn Marino #include "insn-config.h"
28*e4b17023SJohn Marino #include "regs.h"
29*e4b17023SJohn Marino #include "addresses.h"
30*e4b17023SJohn Marino #include "hard-reg-set.h"
31*e4b17023SJohn Marino #include "basic-block.h"
32*e4b17023SJohn Marino #include "reload.h"
33*e4b17023SJohn Marino #include "output.h"
34*e4b17023SJohn Marino #include "function.h"
35*e4b17023SJohn Marino #include "recog.h"
36*e4b17023SJohn Marino #include "flags.h"
37*e4b17023SJohn Marino #include "obstack.h"
38*e4b17023SJohn Marino #include "timevar.h"
39*e4b17023SJohn Marino #include "tree-pass.h"
40*e4b17023SJohn Marino #include "df.h"
41*e4b17023SJohn Marino #include "target.h"
42*e4b17023SJohn Marino #include "emit-rtl.h"
43*e4b17023SJohn Marino #include "regrename.h"
44*e4b17023SJohn Marino
45*e4b17023SJohn Marino /* This file implements the RTL register renaming pass of the compiler. It is
46*e4b17023SJohn Marino a semi-local pass whose goal is to maximize the usage of the register file
47*e4b17023SJohn Marino of the processor by substituting registers for others in the solution given
48*e4b17023SJohn Marino by the register allocator. The algorithm is as follows:
49*e4b17023SJohn Marino
50*e4b17023SJohn Marino 1. Local def/use chains are built: within each basic block, chains are
51*e4b17023SJohn Marino opened and closed; if a chain isn't closed at the end of the block,
52*e4b17023SJohn Marino it is dropped. We pre-open chains if we have already examined a
53*e4b17023SJohn Marino predecessor block and found chains live at the end which match
54*e4b17023SJohn Marino live registers at the start of the new block.
55*e4b17023SJohn Marino
56*e4b17023SJohn Marino 2. We try to combine the local chains across basic block boundaries by
57*e4b17023SJohn Marino comparing chains that were open at the start or end of a block to
58*e4b17023SJohn Marino those in successor/predecessor blocks.
59*e4b17023SJohn Marino
60*e4b17023SJohn Marino 3. For each chain, the set of possible renaming registers is computed.
61*e4b17023SJohn Marino This takes into account the renaming of previously processed chains.
62*e4b17023SJohn Marino Optionally, a preferred class is computed for the renaming register.
63*e4b17023SJohn Marino
64*e4b17023SJohn Marino 4. The best renaming register is computed for the chain in the above set,
65*e4b17023SJohn Marino using a round-robin allocation. If a preferred class exists, then the
66*e4b17023SJohn Marino round-robin allocation is done within the class first, if possible.
67*e4b17023SJohn Marino The round-robin allocation of renaming registers itself is global.
68*e4b17023SJohn Marino
69*e4b17023SJohn Marino 5. If a renaming register has been found, it is substituted in the chain.
70*e4b17023SJohn Marino
71*e4b17023SJohn Marino Targets can parameterize the pass by specifying a preferred class for the
72*e4b17023SJohn Marino renaming register for a given (super)class of registers to be renamed. */
73*e4b17023SJohn Marino
74*e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT <= MAX_RECOG_OPERANDS
75*e4b17023SJohn Marino #error "Use a different bitmap implementation for untracked_operands."
76*e4b17023SJohn Marino #endif
77*e4b17023SJohn Marino
78*e4b17023SJohn Marino enum scan_actions
79*e4b17023SJohn Marino {
80*e4b17023SJohn Marino terminate_write,
81*e4b17023SJohn Marino terminate_dead,
82*e4b17023SJohn Marino mark_all_read,
83*e4b17023SJohn Marino mark_read,
84*e4b17023SJohn Marino mark_write,
85*e4b17023SJohn Marino /* mark_access is for marking the destination regs in
86*e4b17023SJohn Marino REG_FRAME_RELATED_EXPR notes (as if they were read) so that the
87*e4b17023SJohn Marino note is updated properly. */
88*e4b17023SJohn Marino mark_access
89*e4b17023SJohn Marino };
90*e4b17023SJohn Marino
91*e4b17023SJohn Marino static const char * const scan_actions_name[] =
92*e4b17023SJohn Marino {
93*e4b17023SJohn Marino "terminate_write",
94*e4b17023SJohn Marino "terminate_dead",
95*e4b17023SJohn Marino "mark_all_read",
96*e4b17023SJohn Marino "mark_read",
97*e4b17023SJohn Marino "mark_write",
98*e4b17023SJohn Marino "mark_access"
99*e4b17023SJohn Marino };
100*e4b17023SJohn Marino
101*e4b17023SJohn Marino /* TICK and THIS_TICK are used to record the last time we saw each
102*e4b17023SJohn Marino register. */
103*e4b17023SJohn Marino static int tick[FIRST_PSEUDO_REGISTER];
104*e4b17023SJohn Marino static int this_tick = 0;
105*e4b17023SJohn Marino
106*e4b17023SJohn Marino static struct obstack rename_obstack;
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino /* If nonnull, the code calling into the register renamer requested
109*e4b17023SJohn Marino information about insn operands, and we store it here. */
110*e4b17023SJohn Marino VEC(insn_rr_info, heap) *insn_rr;
111*e4b17023SJohn Marino
112*e4b17023SJohn Marino static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
113*e4b17023SJohn Marino enum op_type);
114*e4b17023SJohn Marino static bool build_def_use (basic_block);
115*e4b17023SJohn Marino
116*e4b17023SJohn Marino /* The id to be given to the next opened chain. */
117*e4b17023SJohn Marino static unsigned current_id;
118*e4b17023SJohn Marino
119*e4b17023SJohn Marino /* A mapping of unique id numbers to chains. */
120*e4b17023SJohn Marino static VEC(du_head_p, heap) *id_to_chain;
121*e4b17023SJohn Marino
122*e4b17023SJohn Marino /* List of currently open chains. */
123*e4b17023SJohn Marino static struct du_head *open_chains;
124*e4b17023SJohn Marino
125*e4b17023SJohn Marino /* Bitmap of open chains. The bits set always match the list found in
126*e4b17023SJohn Marino open_chains. */
127*e4b17023SJohn Marino static bitmap_head open_chains_set;
128*e4b17023SJohn Marino
129*e4b17023SJohn Marino /* Record the registers being tracked in open_chains. */
130*e4b17023SJohn Marino static HARD_REG_SET live_in_chains;
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino /* Record the registers that are live but not tracked. The intersection
133*e4b17023SJohn Marino between this and live_in_chains is empty. */
134*e4b17023SJohn Marino static HARD_REG_SET live_hard_regs;
135*e4b17023SJohn Marino
136*e4b17023SJohn Marino /* Set while scanning RTL if INSN_RR is nonnull, i.e. if the current analysis
137*e4b17023SJohn Marino is for a caller that requires operand data. Used in
138*e4b17023SJohn Marino record_operand_use. */
139*e4b17023SJohn Marino static operand_rr_info *cur_operand;
140*e4b17023SJohn Marino
141*e4b17023SJohn Marino /* Return the chain corresponding to id number ID. Take into account that
142*e4b17023SJohn Marino chains may have been merged. */
143*e4b17023SJohn Marino du_head_p
regrename_chain_from_id(unsigned int id)144*e4b17023SJohn Marino regrename_chain_from_id (unsigned int id)
145*e4b17023SJohn Marino {
146*e4b17023SJohn Marino du_head_p first_chain = VEC_index (du_head_p, id_to_chain, id);
147*e4b17023SJohn Marino du_head_p chain = first_chain;
148*e4b17023SJohn Marino while (chain->id != id)
149*e4b17023SJohn Marino {
150*e4b17023SJohn Marino id = chain->id;
151*e4b17023SJohn Marino chain = VEC_index (du_head_p, id_to_chain, id);
152*e4b17023SJohn Marino }
153*e4b17023SJohn Marino first_chain->id = id;
154*e4b17023SJohn Marino return chain;
155*e4b17023SJohn Marino }
156*e4b17023SJohn Marino
157*e4b17023SJohn Marino /* Dump all def/use chains, starting at id FROM. */
158*e4b17023SJohn Marino
159*e4b17023SJohn Marino static void
dump_def_use_chain(int from)160*e4b17023SJohn Marino dump_def_use_chain (int from)
161*e4b17023SJohn Marino {
162*e4b17023SJohn Marino du_head_p head;
163*e4b17023SJohn Marino int i;
164*e4b17023SJohn Marino FOR_EACH_VEC_ELT_FROM (du_head_p, id_to_chain, i, head, from)
165*e4b17023SJohn Marino {
166*e4b17023SJohn Marino struct du_chain *this_du = head->first;
167*e4b17023SJohn Marino
168*e4b17023SJohn Marino fprintf (dump_file, "Register %s (%d):",
169*e4b17023SJohn Marino reg_names[head->regno], head->nregs);
170*e4b17023SJohn Marino while (this_du)
171*e4b17023SJohn Marino {
172*e4b17023SJohn Marino fprintf (dump_file, " %d [%s]", INSN_UID (this_du->insn),
173*e4b17023SJohn Marino reg_class_names[this_du->cl]);
174*e4b17023SJohn Marino this_du = this_du->next_use;
175*e4b17023SJohn Marino }
176*e4b17023SJohn Marino fprintf (dump_file, "\n");
177*e4b17023SJohn Marino head = head->next_chain;
178*e4b17023SJohn Marino }
179*e4b17023SJohn Marino }
180*e4b17023SJohn Marino
181*e4b17023SJohn Marino static void
free_chain_data(void)182*e4b17023SJohn Marino free_chain_data (void)
183*e4b17023SJohn Marino {
184*e4b17023SJohn Marino int i;
185*e4b17023SJohn Marino du_head_p ptr;
186*e4b17023SJohn Marino for (i = 0; VEC_iterate(du_head_p, id_to_chain, i, ptr); i++)
187*e4b17023SJohn Marino bitmap_clear (&ptr->conflicts);
188*e4b17023SJohn Marino
189*e4b17023SJohn Marino VEC_free (du_head_p, heap, id_to_chain);
190*e4b17023SJohn Marino }
191*e4b17023SJohn Marino
192*e4b17023SJohn Marino /* Walk all chains starting with CHAINS and record that they conflict with
193*e4b17023SJohn Marino another chain whose id is ID. */
194*e4b17023SJohn Marino
195*e4b17023SJohn Marino static void
mark_conflict(struct du_head * chains,unsigned id)196*e4b17023SJohn Marino mark_conflict (struct du_head *chains, unsigned id)
197*e4b17023SJohn Marino {
198*e4b17023SJohn Marino while (chains)
199*e4b17023SJohn Marino {
200*e4b17023SJohn Marino bitmap_set_bit (&chains->conflicts, id);
201*e4b17023SJohn Marino chains = chains->next_chain;
202*e4b17023SJohn Marino }
203*e4b17023SJohn Marino }
204*e4b17023SJohn Marino
205*e4b17023SJohn Marino /* Examine cur_operand, and if it is nonnull, record information about the
206*e4b17023SJohn Marino use THIS_DU which is part of the chain HEAD. */
207*e4b17023SJohn Marino
208*e4b17023SJohn Marino static void
record_operand_use(struct du_head * head,struct du_chain * this_du)209*e4b17023SJohn Marino record_operand_use (struct du_head *head, struct du_chain *this_du)
210*e4b17023SJohn Marino {
211*e4b17023SJohn Marino if (cur_operand == NULL)
212*e4b17023SJohn Marino return;
213*e4b17023SJohn Marino gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
214*e4b17023SJohn Marino cur_operand->heads[cur_operand->n_chains] = head;
215*e4b17023SJohn Marino cur_operand->chains[cur_operand->n_chains++] = this_du;
216*e4b17023SJohn Marino }
217*e4b17023SJohn Marino
218*e4b17023SJohn Marino /* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
219*e4b17023SJohn Marino and record its occurrence in *LOC, which is being written to in INSN.
220*e4b17023SJohn Marino This access requires a register of class CL. */
221*e4b17023SJohn Marino
222*e4b17023SJohn Marino static du_head_p
create_new_chain(unsigned this_regno,unsigned this_nregs,rtx * loc,rtx insn,enum reg_class cl)223*e4b17023SJohn Marino create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
224*e4b17023SJohn Marino rtx insn, enum reg_class cl)
225*e4b17023SJohn Marino {
226*e4b17023SJohn Marino struct du_head *head = XOBNEW (&rename_obstack, struct du_head);
227*e4b17023SJohn Marino struct du_chain *this_du;
228*e4b17023SJohn Marino int nregs;
229*e4b17023SJohn Marino
230*e4b17023SJohn Marino head->next_chain = open_chains;
231*e4b17023SJohn Marino head->regno = this_regno;
232*e4b17023SJohn Marino head->nregs = this_nregs;
233*e4b17023SJohn Marino head->need_caller_save_reg = 0;
234*e4b17023SJohn Marino head->cannot_rename = 0;
235*e4b17023SJohn Marino
236*e4b17023SJohn Marino VEC_safe_push (du_head_p, heap, id_to_chain, head);
237*e4b17023SJohn Marino head->id = current_id++;
238*e4b17023SJohn Marino
239*e4b17023SJohn Marino bitmap_initialize (&head->conflicts, &bitmap_default_obstack);
240*e4b17023SJohn Marino bitmap_copy (&head->conflicts, &open_chains_set);
241*e4b17023SJohn Marino mark_conflict (open_chains, head->id);
242*e4b17023SJohn Marino
243*e4b17023SJohn Marino /* Since we're tracking this as a chain now, remove it from the
244*e4b17023SJohn Marino list of conflicting live hard registers and track it in
245*e4b17023SJohn Marino live_in_chains instead. */
246*e4b17023SJohn Marino nregs = head->nregs;
247*e4b17023SJohn Marino while (nregs-- > 0)
248*e4b17023SJohn Marino {
249*e4b17023SJohn Marino SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
250*e4b17023SJohn Marino CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
251*e4b17023SJohn Marino }
252*e4b17023SJohn Marino
253*e4b17023SJohn Marino COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs);
254*e4b17023SJohn Marino bitmap_set_bit (&open_chains_set, head->id);
255*e4b17023SJohn Marino
256*e4b17023SJohn Marino open_chains = head;
257*e4b17023SJohn Marino
258*e4b17023SJohn Marino if (dump_file)
259*e4b17023SJohn Marino {
260*e4b17023SJohn Marino fprintf (dump_file, "Creating chain %s (%d)",
261*e4b17023SJohn Marino reg_names[head->regno], head->id);
262*e4b17023SJohn Marino if (insn != NULL_RTX)
263*e4b17023SJohn Marino fprintf (dump_file, " at insn %d", INSN_UID (insn));
264*e4b17023SJohn Marino fprintf (dump_file, "\n");
265*e4b17023SJohn Marino }
266*e4b17023SJohn Marino
267*e4b17023SJohn Marino if (insn == NULL_RTX)
268*e4b17023SJohn Marino {
269*e4b17023SJohn Marino head->first = head->last = NULL;
270*e4b17023SJohn Marino return head;
271*e4b17023SJohn Marino }
272*e4b17023SJohn Marino
273*e4b17023SJohn Marino this_du = XOBNEW (&rename_obstack, struct du_chain);
274*e4b17023SJohn Marino head->first = head->last = this_du;
275*e4b17023SJohn Marino
276*e4b17023SJohn Marino this_du->next_use = 0;
277*e4b17023SJohn Marino this_du->loc = loc;
278*e4b17023SJohn Marino this_du->insn = insn;
279*e4b17023SJohn Marino this_du->cl = cl;
280*e4b17023SJohn Marino record_operand_use (head, this_du);
281*e4b17023SJohn Marino return head;
282*e4b17023SJohn Marino }
283*e4b17023SJohn Marino
284*e4b17023SJohn Marino /* For a def-use chain HEAD, find which registers overlap its lifetime and
285*e4b17023SJohn Marino set the corresponding bits in *PSET. */
286*e4b17023SJohn Marino
287*e4b17023SJohn Marino static void
merge_overlapping_regs(HARD_REG_SET * pset,struct du_head * head)288*e4b17023SJohn Marino merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head)
289*e4b17023SJohn Marino {
290*e4b17023SJohn Marino bitmap_iterator bi;
291*e4b17023SJohn Marino unsigned i;
292*e4b17023SJohn Marino IOR_HARD_REG_SET (*pset, head->hard_conflicts);
293*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi)
294*e4b17023SJohn Marino {
295*e4b17023SJohn Marino du_head_p other = regrename_chain_from_id (i);
296*e4b17023SJohn Marino unsigned j = other->nregs;
297*e4b17023SJohn Marino gcc_assert (other != head);
298*e4b17023SJohn Marino while (j-- > 0)
299*e4b17023SJohn Marino SET_HARD_REG_BIT (*pset, other->regno + j);
300*e4b17023SJohn Marino }
301*e4b17023SJohn Marino }
302*e4b17023SJohn Marino
303*e4b17023SJohn Marino /* Check if NEW_REG can be the candidate register to rename for
304*e4b17023SJohn Marino REG in THIS_HEAD chain. THIS_UNAVAILABLE is a set of unavailable hard
305*e4b17023SJohn Marino registers. */
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino static bool
check_new_reg_p(int reg ATTRIBUTE_UNUSED,int new_reg,struct du_head * this_head,HARD_REG_SET this_unavailable)308*e4b17023SJohn Marino check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
309*e4b17023SJohn Marino struct du_head *this_head, HARD_REG_SET this_unavailable)
310*e4b17023SJohn Marino {
311*e4b17023SJohn Marino enum machine_mode mode = GET_MODE (*this_head->first->loc);
312*e4b17023SJohn Marino int nregs = hard_regno_nregs[new_reg][mode];
313*e4b17023SJohn Marino int i;
314*e4b17023SJohn Marino struct du_chain *tmp;
315*e4b17023SJohn Marino
316*e4b17023SJohn Marino for (i = nregs - 1; i >= 0; --i)
317*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
318*e4b17023SJohn Marino || fixed_regs[new_reg + i]
319*e4b17023SJohn Marino || global_regs[new_reg + i]
320*e4b17023SJohn Marino /* Can't use regs which aren't saved by the prologue. */
321*e4b17023SJohn Marino || (! df_regs_ever_live_p (new_reg + i)
322*e4b17023SJohn Marino && ! call_used_regs[new_reg + i])
323*e4b17023SJohn Marino #ifdef LEAF_REGISTERS
324*e4b17023SJohn Marino /* We can't use a non-leaf register if we're in a
325*e4b17023SJohn Marino leaf function. */
326*e4b17023SJohn Marino || (current_function_is_leaf
327*e4b17023SJohn Marino && !LEAF_REGISTERS[new_reg + i])
328*e4b17023SJohn Marino #endif
329*e4b17023SJohn Marino #ifdef HARD_REGNO_RENAME_OK
330*e4b17023SJohn Marino || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i)
331*e4b17023SJohn Marino #endif
332*e4b17023SJohn Marino )
333*e4b17023SJohn Marino return false;
334*e4b17023SJohn Marino
335*e4b17023SJohn Marino /* See whether it accepts all modes that occur in
336*e4b17023SJohn Marino definition and uses. */
337*e4b17023SJohn Marino for (tmp = this_head->first; tmp; tmp = tmp->next_use)
338*e4b17023SJohn Marino if ((! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
339*e4b17023SJohn Marino && ! DEBUG_INSN_P (tmp->insn))
340*e4b17023SJohn Marino || (this_head->need_caller_save_reg
341*e4b17023SJohn Marino && ! (HARD_REGNO_CALL_PART_CLOBBERED
342*e4b17023SJohn Marino (reg, GET_MODE (*tmp->loc)))
343*e4b17023SJohn Marino && (HARD_REGNO_CALL_PART_CLOBBERED
344*e4b17023SJohn Marino (new_reg, GET_MODE (*tmp->loc)))))
345*e4b17023SJohn Marino return false;
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino return true;
348*e4b17023SJohn Marino }
349*e4b17023SJohn Marino
350*e4b17023SJohn Marino /* For the chain THIS_HEAD, compute and return the best register to
351*e4b17023SJohn Marino rename to. SUPER_CLASS is the superunion of register classes in
352*e4b17023SJohn Marino the chain. UNAVAILABLE is a set of registers that cannot be used.
353*e4b17023SJohn Marino OLD_REG is the register currently used for the chain. */
354*e4b17023SJohn Marino
355*e4b17023SJohn Marino int
find_best_rename_reg(du_head_p this_head,enum reg_class super_class,HARD_REG_SET * unavailable,int old_reg)356*e4b17023SJohn Marino find_best_rename_reg (du_head_p this_head, enum reg_class super_class,
357*e4b17023SJohn Marino HARD_REG_SET *unavailable, int old_reg)
358*e4b17023SJohn Marino {
359*e4b17023SJohn Marino bool has_preferred_class;
360*e4b17023SJohn Marino enum reg_class preferred_class;
361*e4b17023SJohn Marino int pass;
362*e4b17023SJohn Marino int best_new_reg = old_reg;
363*e4b17023SJohn Marino
364*e4b17023SJohn Marino /* Further narrow the set of registers we can use for renaming.
365*e4b17023SJohn Marino If the chain needs a call-saved register, mark the call-used
366*e4b17023SJohn Marino registers as unavailable. */
367*e4b17023SJohn Marino if (this_head->need_caller_save_reg)
368*e4b17023SJohn Marino IOR_HARD_REG_SET (*unavailable, call_used_reg_set);
369*e4b17023SJohn Marino
370*e4b17023SJohn Marino /* Mark registers that overlap this chain's lifetime as unavailable. */
371*e4b17023SJohn Marino merge_overlapping_regs (unavailable, this_head);
372*e4b17023SJohn Marino
373*e4b17023SJohn Marino /* Compute preferred rename class of super union of all the classes
374*e4b17023SJohn Marino in the chain. */
375*e4b17023SJohn Marino preferred_class
376*e4b17023SJohn Marino = (enum reg_class) targetm.preferred_rename_class (super_class);
377*e4b17023SJohn Marino
378*e4b17023SJohn Marino /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
379*e4b17023SJohn Marino over registers that belong to PREFERRED_CLASS and try to find the
380*e4b17023SJohn Marino best register within the class. If that failed, we iterate in
381*e4b17023SJohn Marino the second pass over registers that don't belong to the class.
382*e4b17023SJohn Marino If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
383*e4b17023SJohn Marino ascending order without any preference. */
384*e4b17023SJohn Marino has_preferred_class = (preferred_class != NO_REGS);
385*e4b17023SJohn Marino for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
386*e4b17023SJohn Marino {
387*e4b17023SJohn Marino int new_reg;
388*e4b17023SJohn Marino for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
389*e4b17023SJohn Marino {
390*e4b17023SJohn Marino if (has_preferred_class
391*e4b17023SJohn Marino && (pass == 0)
392*e4b17023SJohn Marino != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
393*e4b17023SJohn Marino new_reg))
394*e4b17023SJohn Marino continue;
395*e4b17023SJohn Marino
396*e4b17023SJohn Marino /* In the first pass, we force the renaming of registers that
397*e4b17023SJohn Marino don't belong to PREFERRED_CLASS to registers that do, even
398*e4b17023SJohn Marino though the latters were used not very long ago. */
399*e4b17023SJohn Marino if (check_new_reg_p (old_reg, new_reg, this_head,
400*e4b17023SJohn Marino *unavailable)
401*e4b17023SJohn Marino && ((pass == 0
402*e4b17023SJohn Marino && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
403*e4b17023SJohn Marino best_new_reg))
404*e4b17023SJohn Marino || tick[best_new_reg] > tick[new_reg]))
405*e4b17023SJohn Marino best_new_reg = new_reg;
406*e4b17023SJohn Marino }
407*e4b17023SJohn Marino if (pass == 0 && best_new_reg != old_reg)
408*e4b17023SJohn Marino break;
409*e4b17023SJohn Marino }
410*e4b17023SJohn Marino return best_new_reg;
411*e4b17023SJohn Marino }
412*e4b17023SJohn Marino
413*e4b17023SJohn Marino /* Perform register renaming on the current function. */
414*e4b17023SJohn Marino static void
rename_chains(void)415*e4b17023SJohn Marino rename_chains (void)
416*e4b17023SJohn Marino {
417*e4b17023SJohn Marino HARD_REG_SET unavailable;
418*e4b17023SJohn Marino du_head_p this_head;
419*e4b17023SJohn Marino int i;
420*e4b17023SJohn Marino
421*e4b17023SJohn Marino memset (tick, 0, sizeof tick);
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino CLEAR_HARD_REG_SET (unavailable);
424*e4b17023SJohn Marino /* Don't clobber traceback for noreturn functions. */
425*e4b17023SJohn Marino if (frame_pointer_needed)
426*e4b17023SJohn Marino {
427*e4b17023SJohn Marino add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
428*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
429*e4b17023SJohn Marino add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
430*e4b17023SJohn Marino #endif
431*e4b17023SJohn Marino }
432*e4b17023SJohn Marino
433*e4b17023SJohn Marino FOR_EACH_VEC_ELT (du_head_p, id_to_chain, i, this_head)
434*e4b17023SJohn Marino {
435*e4b17023SJohn Marino int best_new_reg;
436*e4b17023SJohn Marino int n_uses;
437*e4b17023SJohn Marino struct du_chain *tmp;
438*e4b17023SJohn Marino HARD_REG_SET this_unavailable;
439*e4b17023SJohn Marino int reg = this_head->regno;
440*e4b17023SJohn Marino enum reg_class super_class = NO_REGS;
441*e4b17023SJohn Marino
442*e4b17023SJohn Marino if (this_head->cannot_rename)
443*e4b17023SJohn Marino continue;
444*e4b17023SJohn Marino
445*e4b17023SJohn Marino if (fixed_regs[reg] || global_regs[reg]
446*e4b17023SJohn Marino #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
447*e4b17023SJohn Marino || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
448*e4b17023SJohn Marino #else
449*e4b17023SJohn Marino || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM)
450*e4b17023SJohn Marino #endif
451*e4b17023SJohn Marino )
452*e4b17023SJohn Marino continue;
453*e4b17023SJohn Marino
454*e4b17023SJohn Marino COPY_HARD_REG_SET (this_unavailable, unavailable);
455*e4b17023SJohn Marino
456*e4b17023SJohn Marino /* Iterate over elements in the chain in order to:
457*e4b17023SJohn Marino 1. Count number of uses, and narrow the set of registers we can
458*e4b17023SJohn Marino use for renaming.
459*e4b17023SJohn Marino 2. Compute the superunion of register classes in this chain. */
460*e4b17023SJohn Marino n_uses = 0;
461*e4b17023SJohn Marino super_class = NO_REGS;
462*e4b17023SJohn Marino for (tmp = this_head->first; tmp; tmp = tmp->next_use)
463*e4b17023SJohn Marino {
464*e4b17023SJohn Marino if (DEBUG_INSN_P (tmp->insn))
465*e4b17023SJohn Marino continue;
466*e4b17023SJohn Marino n_uses++;
467*e4b17023SJohn Marino IOR_COMPL_HARD_REG_SET (this_unavailable,
468*e4b17023SJohn Marino reg_class_contents[tmp->cl]);
469*e4b17023SJohn Marino super_class
470*e4b17023SJohn Marino = reg_class_superunion[(int) super_class][(int) tmp->cl];
471*e4b17023SJohn Marino }
472*e4b17023SJohn Marino
473*e4b17023SJohn Marino if (n_uses < 2)
474*e4b17023SJohn Marino continue;
475*e4b17023SJohn Marino
476*e4b17023SJohn Marino best_new_reg = find_best_rename_reg (this_head, super_class,
477*e4b17023SJohn Marino &this_unavailable, reg);
478*e4b17023SJohn Marino
479*e4b17023SJohn Marino if (dump_file)
480*e4b17023SJohn Marino {
481*e4b17023SJohn Marino fprintf (dump_file, "Register %s in insn %d",
482*e4b17023SJohn Marino reg_names[reg], INSN_UID (this_head->first->insn));
483*e4b17023SJohn Marino if (this_head->need_caller_save_reg)
484*e4b17023SJohn Marino fprintf (dump_file, " crosses a call");
485*e4b17023SJohn Marino }
486*e4b17023SJohn Marino
487*e4b17023SJohn Marino if (best_new_reg == reg)
488*e4b17023SJohn Marino {
489*e4b17023SJohn Marino tick[reg] = ++this_tick;
490*e4b17023SJohn Marino if (dump_file)
491*e4b17023SJohn Marino fprintf (dump_file, "; no available better choice\n");
492*e4b17023SJohn Marino continue;
493*e4b17023SJohn Marino }
494*e4b17023SJohn Marino
495*e4b17023SJohn Marino if (dump_file)
496*e4b17023SJohn Marino fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
497*e4b17023SJohn Marino
498*e4b17023SJohn Marino regrename_do_replace (this_head, best_new_reg);
499*e4b17023SJohn Marino tick[best_new_reg] = ++this_tick;
500*e4b17023SJohn Marino df_set_regs_ever_live (best_new_reg, true);
501*e4b17023SJohn Marino }
502*e4b17023SJohn Marino }
503*e4b17023SJohn Marino
504*e4b17023SJohn Marino /* A structure to record information for each hard register at the start of
505*e4b17023SJohn Marino a basic block. */
506*e4b17023SJohn Marino struct incoming_reg_info {
507*e4b17023SJohn Marino /* Holds the number of registers used in the chain that gave us information
508*e4b17023SJohn Marino about this register. Zero means no information known yet, while a
509*e4b17023SJohn Marino negative value is used for something that is part of, but not the first
510*e4b17023SJohn Marino register in a multi-register value. */
511*e4b17023SJohn Marino int nregs;
512*e4b17023SJohn Marino /* Set to true if we have accesses that conflict in the number of registers
513*e4b17023SJohn Marino used. */
514*e4b17023SJohn Marino bool unusable;
515*e4b17023SJohn Marino };
516*e4b17023SJohn Marino
517*e4b17023SJohn Marino /* A structure recording information about each basic block. It is saved
518*e4b17023SJohn Marino and restored around basic block boundaries.
519*e4b17023SJohn Marino A pointer to such a structure is stored in each basic block's aux field
520*e4b17023SJohn Marino during regrename_analyze, except for blocks we know can't be optimized
521*e4b17023SJohn Marino (such as entry and exit blocks). */
522*e4b17023SJohn Marino struct bb_rename_info
523*e4b17023SJohn Marino {
524*e4b17023SJohn Marino /* The basic block corresponding to this structure. */
525*e4b17023SJohn Marino basic_block bb;
526*e4b17023SJohn Marino /* Copies of the global information. */
527*e4b17023SJohn Marino bitmap_head open_chains_set;
528*e4b17023SJohn Marino bitmap_head incoming_open_chains_set;
529*e4b17023SJohn Marino struct incoming_reg_info incoming[FIRST_PSEUDO_REGISTER];
530*e4b17023SJohn Marino };
531*e4b17023SJohn Marino
532*e4b17023SJohn Marino /* Initialize a rename_info structure P for basic block BB, which starts a new
533*e4b17023SJohn Marino scan. */
534*e4b17023SJohn Marino static void
init_rename_info(struct bb_rename_info * p,basic_block bb)535*e4b17023SJohn Marino init_rename_info (struct bb_rename_info *p, basic_block bb)
536*e4b17023SJohn Marino {
537*e4b17023SJohn Marino int i;
538*e4b17023SJohn Marino df_ref *def_rec;
539*e4b17023SJohn Marino HARD_REG_SET start_chains_set;
540*e4b17023SJohn Marino
541*e4b17023SJohn Marino p->bb = bb;
542*e4b17023SJohn Marino bitmap_initialize (&p->open_chains_set, &bitmap_default_obstack);
543*e4b17023SJohn Marino bitmap_initialize (&p->incoming_open_chains_set, &bitmap_default_obstack);
544*e4b17023SJohn Marino
545*e4b17023SJohn Marino open_chains = NULL;
546*e4b17023SJohn Marino bitmap_clear (&open_chains_set);
547*e4b17023SJohn Marino
548*e4b17023SJohn Marino CLEAR_HARD_REG_SET (live_in_chains);
549*e4b17023SJohn Marino REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_in (bb));
550*e4b17023SJohn Marino for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
551*e4b17023SJohn Marino {
552*e4b17023SJohn Marino df_ref def = *def_rec;
553*e4b17023SJohn Marino if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
554*e4b17023SJohn Marino SET_HARD_REG_BIT (live_hard_regs, DF_REF_REGNO (def));
555*e4b17023SJohn Marino }
556*e4b17023SJohn Marino
557*e4b17023SJohn Marino /* Open chains based on information from (at least one) predecessor
558*e4b17023SJohn Marino block. This gives us a chance later on to combine chains across
559*e4b17023SJohn Marino basic block boundaries. Inconsistencies (in access sizes) will
560*e4b17023SJohn Marino be caught normally and dealt with conservatively by disabling the
561*e4b17023SJohn Marino chain for renaming, and there is no risk of losing optimization
562*e4b17023SJohn Marino opportunities by opening chains either: if we did not open the
563*e4b17023SJohn Marino chains, we'd have to track the live register as a hard reg, and
564*e4b17023SJohn Marino we'd be unable to rename it in any case. */
565*e4b17023SJohn Marino CLEAR_HARD_REG_SET (start_chains_set);
566*e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
567*e4b17023SJohn Marino {
568*e4b17023SJohn Marino struct incoming_reg_info *iri = p->incoming + i;
569*e4b17023SJohn Marino if (iri->nregs > 0 && !iri->unusable
570*e4b17023SJohn Marino && range_in_hard_reg_set_p (live_hard_regs, i, iri->nregs))
571*e4b17023SJohn Marino {
572*e4b17023SJohn Marino SET_HARD_REG_BIT (start_chains_set, i);
573*e4b17023SJohn Marino remove_range_from_hard_reg_set (&live_hard_regs, i, iri->nregs);
574*e4b17023SJohn Marino }
575*e4b17023SJohn Marino }
576*e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
577*e4b17023SJohn Marino {
578*e4b17023SJohn Marino struct incoming_reg_info *iri = p->incoming + i;
579*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (start_chains_set, i))
580*e4b17023SJohn Marino {
581*e4b17023SJohn Marino du_head_p chain;
582*e4b17023SJohn Marino if (dump_file)
583*e4b17023SJohn Marino fprintf (dump_file, "opening incoming chain\n");
584*e4b17023SJohn Marino chain = create_new_chain (i, iri->nregs, NULL, NULL_RTX, NO_REGS);
585*e4b17023SJohn Marino bitmap_set_bit (&p->incoming_open_chains_set, chain->id);
586*e4b17023SJohn Marino }
587*e4b17023SJohn Marino }
588*e4b17023SJohn Marino }
589*e4b17023SJohn Marino
590*e4b17023SJohn Marino /* Record in RI that the block corresponding to it has an incoming
591*e4b17023SJohn Marino live value, described by CHAIN. */
592*e4b17023SJohn Marino static void
set_incoming_from_chain(struct bb_rename_info * ri,du_head_p chain)593*e4b17023SJohn Marino set_incoming_from_chain (struct bb_rename_info *ri, du_head_p chain)
594*e4b17023SJohn Marino {
595*e4b17023SJohn Marino int i;
596*e4b17023SJohn Marino int incoming_nregs = ri->incoming[chain->regno].nregs;
597*e4b17023SJohn Marino int nregs;
598*e4b17023SJohn Marino
599*e4b17023SJohn Marino /* If we've recorded the same information before, everything is fine. */
600*e4b17023SJohn Marino if (incoming_nregs == chain->nregs)
601*e4b17023SJohn Marino {
602*e4b17023SJohn Marino if (dump_file)
603*e4b17023SJohn Marino fprintf (dump_file, "reg %d/%d already recorded\n",
604*e4b17023SJohn Marino chain->regno, chain->nregs);
605*e4b17023SJohn Marino return;
606*e4b17023SJohn Marino }
607*e4b17023SJohn Marino
608*e4b17023SJohn Marino /* If we have no information for any of the involved registers, update
609*e4b17023SJohn Marino the incoming array. */
610*e4b17023SJohn Marino nregs = chain->nregs;
611*e4b17023SJohn Marino while (nregs-- > 0)
612*e4b17023SJohn Marino if (ri->incoming[chain->regno + nregs].nregs != 0
613*e4b17023SJohn Marino || ri->incoming[chain->regno + nregs].unusable)
614*e4b17023SJohn Marino break;
615*e4b17023SJohn Marino if (nregs < 0)
616*e4b17023SJohn Marino {
617*e4b17023SJohn Marino nregs = chain->nregs;
618*e4b17023SJohn Marino ri->incoming[chain->regno].nregs = nregs;
619*e4b17023SJohn Marino while (nregs-- > 1)
620*e4b17023SJohn Marino ri->incoming[chain->regno + nregs].nregs = -nregs;
621*e4b17023SJohn Marino if (dump_file)
622*e4b17023SJohn Marino fprintf (dump_file, "recorded reg %d/%d\n",
623*e4b17023SJohn Marino chain->regno, chain->nregs);
624*e4b17023SJohn Marino return;
625*e4b17023SJohn Marino }
626*e4b17023SJohn Marino
627*e4b17023SJohn Marino /* There must be some kind of conflict. Prevent both the old and
628*e4b17023SJohn Marino new ranges from being used. */
629*e4b17023SJohn Marino if (incoming_nregs < 0)
630*e4b17023SJohn Marino ri->incoming[chain->regno + incoming_nregs].unusable = true;
631*e4b17023SJohn Marino for (i = 0; i < chain->nregs; i++)
632*e4b17023SJohn Marino ri->incoming[chain->regno + i].unusable = true;
633*e4b17023SJohn Marino }
634*e4b17023SJohn Marino
635*e4b17023SJohn Marino /* Merge the two chains C1 and C2 so that all conflict information is
636*e4b17023SJohn Marino recorded and C1, and the id of C2 is changed to that of C1. */
637*e4b17023SJohn Marino static void
merge_chains(du_head_p c1,du_head_p c2)638*e4b17023SJohn Marino merge_chains (du_head_p c1, du_head_p c2)
639*e4b17023SJohn Marino {
640*e4b17023SJohn Marino if (c1 == c2)
641*e4b17023SJohn Marino return;
642*e4b17023SJohn Marino
643*e4b17023SJohn Marino if (c2->first != NULL)
644*e4b17023SJohn Marino {
645*e4b17023SJohn Marino if (c1->first == NULL)
646*e4b17023SJohn Marino c1->first = c2->first;
647*e4b17023SJohn Marino else
648*e4b17023SJohn Marino c1->last->next_use = c2->first;
649*e4b17023SJohn Marino c1->last = c2->last;
650*e4b17023SJohn Marino }
651*e4b17023SJohn Marino
652*e4b17023SJohn Marino c2->first = c2->last = NULL;
653*e4b17023SJohn Marino c2->id = c1->id;
654*e4b17023SJohn Marino
655*e4b17023SJohn Marino IOR_HARD_REG_SET (c1->hard_conflicts, c2->hard_conflicts);
656*e4b17023SJohn Marino bitmap_ior_into (&c1->conflicts, &c2->conflicts);
657*e4b17023SJohn Marino
658*e4b17023SJohn Marino c1->need_caller_save_reg |= c2->need_caller_save_reg;
659*e4b17023SJohn Marino c1->cannot_rename |= c2->cannot_rename;
660*e4b17023SJohn Marino }
661*e4b17023SJohn Marino
662*e4b17023SJohn Marino /* Analyze the current function and build chains for renaming. */
663*e4b17023SJohn Marino
664*e4b17023SJohn Marino void
regrename_analyze(bitmap bb_mask)665*e4b17023SJohn Marino regrename_analyze (bitmap bb_mask)
666*e4b17023SJohn Marino {
667*e4b17023SJohn Marino struct bb_rename_info *rename_info;
668*e4b17023SJohn Marino int i;
669*e4b17023SJohn Marino basic_block bb;
670*e4b17023SJohn Marino int n_bbs;
671*e4b17023SJohn Marino int *inverse_postorder;
672*e4b17023SJohn Marino
673*e4b17023SJohn Marino inverse_postorder = XNEWVEC (int, last_basic_block);
674*e4b17023SJohn Marino n_bbs = pre_and_rev_post_order_compute (NULL, inverse_postorder, false);
675*e4b17023SJohn Marino
676*e4b17023SJohn Marino /* Gather some information about the blocks in this function. */
677*e4b17023SJohn Marino rename_info = XCNEWVEC (struct bb_rename_info, n_basic_blocks);
678*e4b17023SJohn Marino i = 0;
679*e4b17023SJohn Marino FOR_EACH_BB (bb)
680*e4b17023SJohn Marino {
681*e4b17023SJohn Marino struct bb_rename_info *ri = rename_info + i;
682*e4b17023SJohn Marino ri->bb = bb;
683*e4b17023SJohn Marino if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index))
684*e4b17023SJohn Marino bb->aux = NULL;
685*e4b17023SJohn Marino else
686*e4b17023SJohn Marino bb->aux = ri;
687*e4b17023SJohn Marino i++;
688*e4b17023SJohn Marino }
689*e4b17023SJohn Marino
690*e4b17023SJohn Marino current_id = 0;
691*e4b17023SJohn Marino id_to_chain = VEC_alloc (du_head_p, heap, 0);
692*e4b17023SJohn Marino bitmap_initialize (&open_chains_set, &bitmap_default_obstack);
693*e4b17023SJohn Marino
694*e4b17023SJohn Marino /* The order in which we visit blocks ensures that whenever
695*e4b17023SJohn Marino possible, we only process a block after at least one of its
696*e4b17023SJohn Marino predecessors, which provides a "seeding" effect to make the logic
697*e4b17023SJohn Marino in set_incoming_from_chain and init_rename_info useful. */
698*e4b17023SJohn Marino
699*e4b17023SJohn Marino for (i = 0; i < n_bbs; i++)
700*e4b17023SJohn Marino {
701*e4b17023SJohn Marino basic_block bb1 = BASIC_BLOCK (inverse_postorder[i]);
702*e4b17023SJohn Marino struct bb_rename_info *this_info;
703*e4b17023SJohn Marino bool success;
704*e4b17023SJohn Marino edge e;
705*e4b17023SJohn Marino edge_iterator ei;
706*e4b17023SJohn Marino int old_length = VEC_length (du_head_p, id_to_chain);
707*e4b17023SJohn Marino
708*e4b17023SJohn Marino this_info = (struct bb_rename_info *) bb1->aux;
709*e4b17023SJohn Marino if (this_info == NULL)
710*e4b17023SJohn Marino continue;
711*e4b17023SJohn Marino
712*e4b17023SJohn Marino if (dump_file)
713*e4b17023SJohn Marino fprintf (dump_file, "\nprocessing block %d:\n", bb1->index);
714*e4b17023SJohn Marino
715*e4b17023SJohn Marino init_rename_info (this_info, bb1);
716*e4b17023SJohn Marino
717*e4b17023SJohn Marino success = build_def_use (bb1);
718*e4b17023SJohn Marino if (!success)
719*e4b17023SJohn Marino {
720*e4b17023SJohn Marino if (dump_file)
721*e4b17023SJohn Marino fprintf (dump_file, "failed\n");
722*e4b17023SJohn Marino bb1->aux = NULL;
723*e4b17023SJohn Marino VEC_truncate (du_head_p, id_to_chain, old_length);
724*e4b17023SJohn Marino current_id = old_length;
725*e4b17023SJohn Marino bitmap_clear (&this_info->incoming_open_chains_set);
726*e4b17023SJohn Marino open_chains = NULL;
727*e4b17023SJohn Marino if (insn_rr != NULL)
728*e4b17023SJohn Marino {
729*e4b17023SJohn Marino rtx insn;
730*e4b17023SJohn Marino FOR_BB_INSNS (bb1, insn)
731*e4b17023SJohn Marino {
732*e4b17023SJohn Marino insn_rr_info *p = VEC_index (insn_rr_info, insn_rr,
733*e4b17023SJohn Marino INSN_UID (insn));
734*e4b17023SJohn Marino p->op_info = NULL;
735*e4b17023SJohn Marino }
736*e4b17023SJohn Marino }
737*e4b17023SJohn Marino continue;
738*e4b17023SJohn Marino }
739*e4b17023SJohn Marino
740*e4b17023SJohn Marino if (dump_file)
741*e4b17023SJohn Marino dump_def_use_chain (old_length);
742*e4b17023SJohn Marino bitmap_copy (&this_info->open_chains_set, &open_chains_set);
743*e4b17023SJohn Marino
744*e4b17023SJohn Marino /* Add successor blocks to the worklist if necessary, and record
745*e4b17023SJohn Marino data about our own open chains at the end of this block, which
746*e4b17023SJohn Marino will be used to pre-open chains when processing the successors. */
747*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb1->succs)
748*e4b17023SJohn Marino {
749*e4b17023SJohn Marino struct bb_rename_info *dest_ri;
750*e4b17023SJohn Marino struct du_head *chain;
751*e4b17023SJohn Marino
752*e4b17023SJohn Marino if (dump_file)
753*e4b17023SJohn Marino fprintf (dump_file, "successor block %d\n", e->dest->index);
754*e4b17023SJohn Marino
755*e4b17023SJohn Marino if (e->flags & (EDGE_EH | EDGE_ABNORMAL))
756*e4b17023SJohn Marino continue;
757*e4b17023SJohn Marino dest_ri = (struct bb_rename_info *)e->dest->aux;
758*e4b17023SJohn Marino if (dest_ri == NULL)
759*e4b17023SJohn Marino continue;
760*e4b17023SJohn Marino for (chain = open_chains; chain; chain = chain->next_chain)
761*e4b17023SJohn Marino set_incoming_from_chain (dest_ri, chain);
762*e4b17023SJohn Marino }
763*e4b17023SJohn Marino }
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino free (inverse_postorder);
766*e4b17023SJohn Marino
767*e4b17023SJohn Marino /* Now, combine the chains data we have gathered across basic block
768*e4b17023SJohn Marino boundaries.
769*e4b17023SJohn Marino
770*e4b17023SJohn Marino For every basic block, there may be chains open at the start, or at the
771*e4b17023SJohn Marino end. Rather than exclude them from renaming, we look for open chains
772*e4b17023SJohn Marino with matching registers at the other side of the CFG edge.
773*e4b17023SJohn Marino
774*e4b17023SJohn Marino For a given chain using register R, open at the start of block B, we
775*e4b17023SJohn Marino must find an open chain using R on the other side of every edge leading
776*e4b17023SJohn Marino to B, if the register is live across this edge. In the code below,
777*e4b17023SJohn Marino N_PREDS_USED counts the number of edges where the register is live, and
778*e4b17023SJohn Marino N_PREDS_JOINED counts those where we found an appropriate chain for
779*e4b17023SJohn Marino joining.
780*e4b17023SJohn Marino
781*e4b17023SJohn Marino We perform the analysis for both incoming and outgoing edges, but we
782*e4b17023SJohn Marino only need to merge once (in the second part, after verifying outgoing
783*e4b17023SJohn Marino edges). */
784*e4b17023SJohn Marino FOR_EACH_BB (bb)
785*e4b17023SJohn Marino {
786*e4b17023SJohn Marino struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux;
787*e4b17023SJohn Marino unsigned j;
788*e4b17023SJohn Marino bitmap_iterator bi;
789*e4b17023SJohn Marino
790*e4b17023SJohn Marino if (bb_ri == NULL)
791*e4b17023SJohn Marino continue;
792*e4b17023SJohn Marino
793*e4b17023SJohn Marino if (dump_file)
794*e4b17023SJohn Marino fprintf (dump_file, "processing bb %d in edges\n", bb->index);
795*e4b17023SJohn Marino
796*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (&bb_ri->incoming_open_chains_set, 0, j, bi)
797*e4b17023SJohn Marino {
798*e4b17023SJohn Marino edge e;
799*e4b17023SJohn Marino edge_iterator ei;
800*e4b17023SJohn Marino struct du_head *chain = regrename_chain_from_id (j);
801*e4b17023SJohn Marino int n_preds_used = 0, n_preds_joined = 0;
802*e4b17023SJohn Marino
803*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds)
804*e4b17023SJohn Marino {
805*e4b17023SJohn Marino struct bb_rename_info *src_ri;
806*e4b17023SJohn Marino unsigned k;
807*e4b17023SJohn Marino bitmap_iterator bi2;
808*e4b17023SJohn Marino HARD_REG_SET live;
809*e4b17023SJohn Marino bool success = false;
810*e4b17023SJohn Marino
811*e4b17023SJohn Marino REG_SET_TO_HARD_REG_SET (live, df_get_live_out (e->src));
812*e4b17023SJohn Marino if (!range_overlaps_hard_reg_set_p (live, chain->regno,
813*e4b17023SJohn Marino chain->nregs))
814*e4b17023SJohn Marino continue;
815*e4b17023SJohn Marino n_preds_used++;
816*e4b17023SJohn Marino
817*e4b17023SJohn Marino if (e->flags & (EDGE_EH | EDGE_ABNORMAL))
818*e4b17023SJohn Marino continue;
819*e4b17023SJohn Marino
820*e4b17023SJohn Marino src_ri = (struct bb_rename_info *)e->src->aux;
821*e4b17023SJohn Marino if (src_ri == NULL)
822*e4b17023SJohn Marino continue;
823*e4b17023SJohn Marino
824*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set,
825*e4b17023SJohn Marino 0, k, bi2)
826*e4b17023SJohn Marino {
827*e4b17023SJohn Marino struct du_head *outgoing_chain = regrename_chain_from_id (k);
828*e4b17023SJohn Marino
829*e4b17023SJohn Marino if (outgoing_chain->regno == chain->regno
830*e4b17023SJohn Marino && outgoing_chain->nregs == chain->nregs)
831*e4b17023SJohn Marino {
832*e4b17023SJohn Marino n_preds_joined++;
833*e4b17023SJohn Marino success = true;
834*e4b17023SJohn Marino break;
835*e4b17023SJohn Marino }
836*e4b17023SJohn Marino }
837*e4b17023SJohn Marino if (!success && dump_file)
838*e4b17023SJohn Marino fprintf (dump_file, "failure to match with pred block %d\n",
839*e4b17023SJohn Marino e->src->index);
840*e4b17023SJohn Marino }
841*e4b17023SJohn Marino if (n_preds_joined < n_preds_used)
842*e4b17023SJohn Marino {
843*e4b17023SJohn Marino if (dump_file)
844*e4b17023SJohn Marino fprintf (dump_file, "cannot rename chain %d\n", j);
845*e4b17023SJohn Marino chain->cannot_rename = 1;
846*e4b17023SJohn Marino }
847*e4b17023SJohn Marino }
848*e4b17023SJohn Marino }
849*e4b17023SJohn Marino FOR_EACH_BB (bb)
850*e4b17023SJohn Marino {
851*e4b17023SJohn Marino struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux;
852*e4b17023SJohn Marino unsigned j;
853*e4b17023SJohn Marino bitmap_iterator bi;
854*e4b17023SJohn Marino
855*e4b17023SJohn Marino if (bb_ri == NULL)
856*e4b17023SJohn Marino continue;
857*e4b17023SJohn Marino
858*e4b17023SJohn Marino if (dump_file)
859*e4b17023SJohn Marino fprintf (dump_file, "processing bb %d out edges\n", bb->index);
860*e4b17023SJohn Marino
861*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (&bb_ri->open_chains_set, 0, j, bi)
862*e4b17023SJohn Marino {
863*e4b17023SJohn Marino edge e;
864*e4b17023SJohn Marino edge_iterator ei;
865*e4b17023SJohn Marino struct du_head *chain = regrename_chain_from_id (j);
866*e4b17023SJohn Marino int n_succs_used = 0, n_succs_joined = 0;
867*e4b17023SJohn Marino
868*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
869*e4b17023SJohn Marino {
870*e4b17023SJohn Marino bool printed = false;
871*e4b17023SJohn Marino struct bb_rename_info *dest_ri;
872*e4b17023SJohn Marino unsigned k;
873*e4b17023SJohn Marino bitmap_iterator bi2;
874*e4b17023SJohn Marino HARD_REG_SET live;
875*e4b17023SJohn Marino
876*e4b17023SJohn Marino REG_SET_TO_HARD_REG_SET (live, df_get_live_in (e->dest));
877*e4b17023SJohn Marino if (!range_overlaps_hard_reg_set_p (live, chain->regno,
878*e4b17023SJohn Marino chain->nregs))
879*e4b17023SJohn Marino continue;
880*e4b17023SJohn Marino
881*e4b17023SJohn Marino n_succs_used++;
882*e4b17023SJohn Marino
883*e4b17023SJohn Marino dest_ri = (struct bb_rename_info *)e->dest->aux;
884*e4b17023SJohn Marino if (dest_ri == NULL)
885*e4b17023SJohn Marino continue;
886*e4b17023SJohn Marino
887*e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set,
888*e4b17023SJohn Marino 0, k, bi2)
889*e4b17023SJohn Marino {
890*e4b17023SJohn Marino struct du_head *incoming_chain = regrename_chain_from_id (k);
891*e4b17023SJohn Marino
892*e4b17023SJohn Marino if (incoming_chain->regno == chain->regno
893*e4b17023SJohn Marino && incoming_chain->nregs == chain->nregs)
894*e4b17023SJohn Marino {
895*e4b17023SJohn Marino if (dump_file)
896*e4b17023SJohn Marino {
897*e4b17023SJohn Marino if (!printed)
898*e4b17023SJohn Marino fprintf (dump_file,
899*e4b17023SJohn Marino "merging blocks for edge %d -> %d\n",
900*e4b17023SJohn Marino e->src->index, e->dest->index);
901*e4b17023SJohn Marino printed = true;
902*e4b17023SJohn Marino fprintf (dump_file,
903*e4b17023SJohn Marino " merging chains %d (->%d) and %d (->%d) [%s]\n",
904*e4b17023SJohn Marino k, incoming_chain->id, j, chain->id,
905*e4b17023SJohn Marino reg_names[incoming_chain->regno]);
906*e4b17023SJohn Marino }
907*e4b17023SJohn Marino
908*e4b17023SJohn Marino merge_chains (chain, incoming_chain);
909*e4b17023SJohn Marino n_succs_joined++;
910*e4b17023SJohn Marino break;
911*e4b17023SJohn Marino }
912*e4b17023SJohn Marino }
913*e4b17023SJohn Marino }
914*e4b17023SJohn Marino if (n_succs_joined < n_succs_used)
915*e4b17023SJohn Marino {
916*e4b17023SJohn Marino if (dump_file)
917*e4b17023SJohn Marino fprintf (dump_file, "cannot rename chain %d\n",
918*e4b17023SJohn Marino j);
919*e4b17023SJohn Marino chain->cannot_rename = 1;
920*e4b17023SJohn Marino }
921*e4b17023SJohn Marino }
922*e4b17023SJohn Marino }
923*e4b17023SJohn Marino
924*e4b17023SJohn Marino free (rename_info);
925*e4b17023SJohn Marino
926*e4b17023SJohn Marino FOR_EACH_BB (bb)
927*e4b17023SJohn Marino bb->aux = NULL;
928*e4b17023SJohn Marino }
929*e4b17023SJohn Marino
930*e4b17023SJohn Marino void
regrename_do_replace(struct du_head * head,int reg)931*e4b17023SJohn Marino regrename_do_replace (struct du_head *head, int reg)
932*e4b17023SJohn Marino {
933*e4b17023SJohn Marino struct du_chain *chain;
934*e4b17023SJohn Marino unsigned int base_regno = head->regno;
935*e4b17023SJohn Marino enum machine_mode mode;
936*e4b17023SJohn Marino
937*e4b17023SJohn Marino for (chain = head->first; chain; chain = chain->next_use)
938*e4b17023SJohn Marino {
939*e4b17023SJohn Marino unsigned int regno = ORIGINAL_REGNO (*chain->loc);
940*e4b17023SJohn Marino struct reg_attrs *attr = REG_ATTRS (*chain->loc);
941*e4b17023SJohn Marino int reg_ptr = REG_POINTER (*chain->loc);
942*e4b17023SJohn Marino
943*e4b17023SJohn Marino if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno)
944*e4b17023SJohn Marino INSN_VAR_LOCATION_LOC (chain->insn) = gen_rtx_UNKNOWN_VAR_LOC ();
945*e4b17023SJohn Marino else
946*e4b17023SJohn Marino {
947*e4b17023SJohn Marino *chain->loc = gen_raw_REG (GET_MODE (*chain->loc), reg);
948*e4b17023SJohn Marino if (regno >= FIRST_PSEUDO_REGISTER)
949*e4b17023SJohn Marino ORIGINAL_REGNO (*chain->loc) = regno;
950*e4b17023SJohn Marino REG_ATTRS (*chain->loc) = attr;
951*e4b17023SJohn Marino REG_POINTER (*chain->loc) = reg_ptr;
952*e4b17023SJohn Marino }
953*e4b17023SJohn Marino
954*e4b17023SJohn Marino df_insn_rescan (chain->insn);
955*e4b17023SJohn Marino }
956*e4b17023SJohn Marino
957*e4b17023SJohn Marino mode = GET_MODE (*head->first->loc);
958*e4b17023SJohn Marino head->regno = reg;
959*e4b17023SJohn Marino head->nregs = hard_regno_nregs[reg][mode];
960*e4b17023SJohn Marino }
961*e4b17023SJohn Marino
962*e4b17023SJohn Marino
963*e4b17023SJohn Marino /* True if we found a register with a size mismatch, which means that we
964*e4b17023SJohn Marino can't track its lifetime accurately. If so, we abort the current block
965*e4b17023SJohn Marino without renaming. */
966*e4b17023SJohn Marino static bool fail_current_block;
967*e4b17023SJohn Marino
968*e4b17023SJohn Marino /* Return true if OP is a reg for which all bits are set in PSET, false
969*e4b17023SJohn Marino if all bits are clear.
970*e4b17023SJohn Marino In other cases, set fail_current_block and return false. */
971*e4b17023SJohn Marino
972*e4b17023SJohn Marino static bool
verify_reg_in_set(rtx op,HARD_REG_SET * pset)973*e4b17023SJohn Marino verify_reg_in_set (rtx op, HARD_REG_SET *pset)
974*e4b17023SJohn Marino {
975*e4b17023SJohn Marino unsigned regno, nregs;
976*e4b17023SJohn Marino bool all_live, all_dead;
977*e4b17023SJohn Marino if (!REG_P (op))
978*e4b17023SJohn Marino return false;
979*e4b17023SJohn Marino
980*e4b17023SJohn Marino regno = REGNO (op);
981*e4b17023SJohn Marino nregs = hard_regno_nregs[regno][GET_MODE (op)];
982*e4b17023SJohn Marino all_live = all_dead = true;
983*e4b17023SJohn Marino while (nregs-- > 0)
984*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (*pset, regno + nregs))
985*e4b17023SJohn Marino all_dead = false;
986*e4b17023SJohn Marino else
987*e4b17023SJohn Marino all_live = false;
988*e4b17023SJohn Marino if (!all_dead && !all_live)
989*e4b17023SJohn Marino {
990*e4b17023SJohn Marino fail_current_block = true;
991*e4b17023SJohn Marino return false;
992*e4b17023SJohn Marino }
993*e4b17023SJohn Marino return all_live;
994*e4b17023SJohn Marino }
995*e4b17023SJohn Marino
996*e4b17023SJohn Marino /* Return true if OP is a reg that is being tracked already in some form.
997*e4b17023SJohn Marino May set fail_current_block if it sees an unhandled case of overlap. */
998*e4b17023SJohn Marino
999*e4b17023SJohn Marino static bool
verify_reg_tracked(rtx op)1000*e4b17023SJohn Marino verify_reg_tracked (rtx op)
1001*e4b17023SJohn Marino {
1002*e4b17023SJohn Marino return (verify_reg_in_set (op, &live_hard_regs)
1003*e4b17023SJohn Marino || verify_reg_in_set (op, &live_in_chains));
1004*e4b17023SJohn Marino }
1005*e4b17023SJohn Marino
1006*e4b17023SJohn Marino /* Called through note_stores. DATA points to a rtx_code, either SET or
1007*e4b17023SJohn Marino CLOBBER, which tells us which kind of rtx to look at. If we have a
1008*e4b17023SJohn Marino match, record the set register in live_hard_regs and in the hard_conflicts
1009*e4b17023SJohn Marino bitmap of open chains. */
1010*e4b17023SJohn Marino
1011*e4b17023SJohn Marino static void
note_sets_clobbers(rtx x,const_rtx set,void * data)1012*e4b17023SJohn Marino note_sets_clobbers (rtx x, const_rtx set, void *data)
1013*e4b17023SJohn Marino {
1014*e4b17023SJohn Marino enum rtx_code code = *(enum rtx_code *)data;
1015*e4b17023SJohn Marino struct du_head *chain;
1016*e4b17023SJohn Marino
1017*e4b17023SJohn Marino if (GET_CODE (x) == SUBREG)
1018*e4b17023SJohn Marino x = SUBREG_REG (x);
1019*e4b17023SJohn Marino if (!REG_P (x) || GET_CODE (set) != code)
1020*e4b17023SJohn Marino return;
1021*e4b17023SJohn Marino /* There must not be pseudos at this point. */
1022*e4b17023SJohn Marino gcc_assert (HARD_REGISTER_P (x));
1023*e4b17023SJohn Marino add_to_hard_reg_set (&live_hard_regs, GET_MODE (x), REGNO (x));
1024*e4b17023SJohn Marino for (chain = open_chains; chain; chain = chain->next_chain)
1025*e4b17023SJohn Marino add_to_hard_reg_set (&chain->hard_conflicts, GET_MODE (x), REGNO (x));
1026*e4b17023SJohn Marino }
1027*e4b17023SJohn Marino
1028*e4b17023SJohn Marino static void
scan_rtx_reg(rtx insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum op_type type)1029*e4b17023SJohn Marino scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
1030*e4b17023SJohn Marino enum op_type type)
1031*e4b17023SJohn Marino {
1032*e4b17023SJohn Marino struct du_head **p;
1033*e4b17023SJohn Marino rtx x = *loc;
1034*e4b17023SJohn Marino enum machine_mode mode = GET_MODE (x);
1035*e4b17023SJohn Marino unsigned this_regno = REGNO (x);
1036*e4b17023SJohn Marino int this_nregs = hard_regno_nregs[this_regno][mode];
1037*e4b17023SJohn Marino
1038*e4b17023SJohn Marino if (action == mark_write)
1039*e4b17023SJohn Marino {
1040*e4b17023SJohn Marino if (type == OP_OUT)
1041*e4b17023SJohn Marino create_new_chain (this_regno, this_nregs, loc, insn, cl);
1042*e4b17023SJohn Marino return;
1043*e4b17023SJohn Marino }
1044*e4b17023SJohn Marino
1045*e4b17023SJohn Marino if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
1046*e4b17023SJohn Marino return;
1047*e4b17023SJohn Marino
1048*e4b17023SJohn Marino for (p = &open_chains; *p;)
1049*e4b17023SJohn Marino {
1050*e4b17023SJohn Marino struct du_head *head = *p;
1051*e4b17023SJohn Marino struct du_head *next = head->next_chain;
1052*e4b17023SJohn Marino int exact_match = (head->regno == this_regno
1053*e4b17023SJohn Marino && head->nregs == this_nregs);
1054*e4b17023SJohn Marino int superset = (this_regno <= head->regno
1055*e4b17023SJohn Marino && this_regno + this_nregs >= head->regno + head->nregs);
1056*e4b17023SJohn Marino int subset = (this_regno >= head->regno
1057*e4b17023SJohn Marino && this_regno + this_nregs <= head->regno + head->nregs);
1058*e4b17023SJohn Marino
1059*e4b17023SJohn Marino if (!bitmap_bit_p (&open_chains_set, head->id)
1060*e4b17023SJohn Marino || head->regno + head->nregs <= this_regno
1061*e4b17023SJohn Marino || this_regno + this_nregs <= head->regno)
1062*e4b17023SJohn Marino {
1063*e4b17023SJohn Marino p = &head->next_chain;
1064*e4b17023SJohn Marino continue;
1065*e4b17023SJohn Marino }
1066*e4b17023SJohn Marino
1067*e4b17023SJohn Marino if (action == mark_read || action == mark_access)
1068*e4b17023SJohn Marino {
1069*e4b17023SJohn Marino /* ??? Class NO_REGS can happen if the md file makes use of
1070*e4b17023SJohn Marino EXTRA_CONSTRAINTS to match registers. Which is arguably
1071*e4b17023SJohn Marino wrong, but there we are. */
1072*e4b17023SJohn Marino
1073*e4b17023SJohn Marino if (cl == NO_REGS || (!exact_match && !DEBUG_INSN_P (insn)))
1074*e4b17023SJohn Marino {
1075*e4b17023SJohn Marino if (dump_file)
1076*e4b17023SJohn Marino fprintf (dump_file,
1077*e4b17023SJohn Marino "Cannot rename chain %s (%d) at insn %d (%s)\n",
1078*e4b17023SJohn Marino reg_names[head->regno], head->id, INSN_UID (insn),
1079*e4b17023SJohn Marino scan_actions_name[(int) action]);
1080*e4b17023SJohn Marino head->cannot_rename = 1;
1081*e4b17023SJohn Marino if (superset)
1082*e4b17023SJohn Marino {
1083*e4b17023SJohn Marino unsigned nregs = this_nregs;
1084*e4b17023SJohn Marino head->regno = this_regno;
1085*e4b17023SJohn Marino head->nregs = this_nregs;
1086*e4b17023SJohn Marino while (nregs-- > 0)
1087*e4b17023SJohn Marino SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
1088*e4b17023SJohn Marino if (dump_file)
1089*e4b17023SJohn Marino fprintf (dump_file,
1090*e4b17023SJohn Marino "Widening register in chain %s (%d) at insn %d\n",
1091*e4b17023SJohn Marino reg_names[head->regno], head->id, INSN_UID (insn));
1092*e4b17023SJohn Marino }
1093*e4b17023SJohn Marino else if (!subset)
1094*e4b17023SJohn Marino {
1095*e4b17023SJohn Marino fail_current_block = true;
1096*e4b17023SJohn Marino if (dump_file)
1097*e4b17023SJohn Marino fprintf (dump_file,
1098*e4b17023SJohn Marino "Failing basic block due to unhandled overlap\n");
1099*e4b17023SJohn Marino }
1100*e4b17023SJohn Marino }
1101*e4b17023SJohn Marino else
1102*e4b17023SJohn Marino {
1103*e4b17023SJohn Marino struct du_chain *this_du;
1104*e4b17023SJohn Marino this_du = XOBNEW (&rename_obstack, struct du_chain);
1105*e4b17023SJohn Marino this_du->next_use = 0;
1106*e4b17023SJohn Marino this_du->loc = loc;
1107*e4b17023SJohn Marino this_du->insn = insn;
1108*e4b17023SJohn Marino this_du->cl = cl;
1109*e4b17023SJohn Marino if (head->first == NULL)
1110*e4b17023SJohn Marino head->first = this_du;
1111*e4b17023SJohn Marino else
1112*e4b17023SJohn Marino head->last->next_use = this_du;
1113*e4b17023SJohn Marino record_operand_use (head, this_du);
1114*e4b17023SJohn Marino head->last = this_du;
1115*e4b17023SJohn Marino }
1116*e4b17023SJohn Marino /* Avoid adding the same location in a DEBUG_INSN multiple times,
1117*e4b17023SJohn Marino which could happen with non-exact overlap. */
1118*e4b17023SJohn Marino if (DEBUG_INSN_P (insn))
1119*e4b17023SJohn Marino return;
1120*e4b17023SJohn Marino /* Otherwise, find any other chains that do not match exactly;
1121*e4b17023SJohn Marino ensure they all get marked unrenamable. */
1122*e4b17023SJohn Marino p = &head->next_chain;
1123*e4b17023SJohn Marino continue;
1124*e4b17023SJohn Marino }
1125*e4b17023SJohn Marino
1126*e4b17023SJohn Marino /* Whether the terminated chain can be used for renaming
1127*e4b17023SJohn Marino depends on the action and this being an exact match.
1128*e4b17023SJohn Marino In either case, we remove this element from open_chains. */
1129*e4b17023SJohn Marino
1130*e4b17023SJohn Marino if ((action == terminate_dead || action == terminate_write)
1131*e4b17023SJohn Marino && (superset || subset))
1132*e4b17023SJohn Marino {
1133*e4b17023SJohn Marino unsigned nregs;
1134*e4b17023SJohn Marino
1135*e4b17023SJohn Marino if (subset && !superset)
1136*e4b17023SJohn Marino head->cannot_rename = 1;
1137*e4b17023SJohn Marino bitmap_clear_bit (&open_chains_set, head->id);
1138*e4b17023SJohn Marino
1139*e4b17023SJohn Marino nregs = head->nregs;
1140*e4b17023SJohn Marino while (nregs-- > 0)
1141*e4b17023SJohn Marino {
1142*e4b17023SJohn Marino CLEAR_HARD_REG_BIT (live_in_chains, head->regno + nregs);
1143*e4b17023SJohn Marino if (subset && !superset
1144*e4b17023SJohn Marino && (head->regno + nregs < this_regno
1145*e4b17023SJohn Marino || head->regno + nregs >= this_regno + this_nregs))
1146*e4b17023SJohn Marino SET_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
1147*e4b17023SJohn Marino }
1148*e4b17023SJohn Marino
1149*e4b17023SJohn Marino *p = next;
1150*e4b17023SJohn Marino if (dump_file)
1151*e4b17023SJohn Marino fprintf (dump_file,
1152*e4b17023SJohn Marino "Closing chain %s (%d) at insn %d (%s%s)\n",
1153*e4b17023SJohn Marino reg_names[head->regno], head->id, INSN_UID (insn),
1154*e4b17023SJohn Marino scan_actions_name[(int) action],
1155*e4b17023SJohn Marino superset ? ", superset" : subset ? ", subset" : "");
1156*e4b17023SJohn Marino }
1157*e4b17023SJohn Marino else if (action == terminate_dead || action == terminate_write)
1158*e4b17023SJohn Marino {
1159*e4b17023SJohn Marino /* In this case, tracking liveness gets too hard. Fail the
1160*e4b17023SJohn Marino entire basic block. */
1161*e4b17023SJohn Marino if (dump_file)
1162*e4b17023SJohn Marino fprintf (dump_file,
1163*e4b17023SJohn Marino "Failing basic block due to unhandled overlap\n");
1164*e4b17023SJohn Marino fail_current_block = true;
1165*e4b17023SJohn Marino return;
1166*e4b17023SJohn Marino }
1167*e4b17023SJohn Marino else
1168*e4b17023SJohn Marino {
1169*e4b17023SJohn Marino head->cannot_rename = 1;
1170*e4b17023SJohn Marino if (dump_file)
1171*e4b17023SJohn Marino fprintf (dump_file,
1172*e4b17023SJohn Marino "Cannot rename chain %s (%d) at insn %d (%s)\n",
1173*e4b17023SJohn Marino reg_names[head->regno], head->id, INSN_UID (insn),
1174*e4b17023SJohn Marino scan_actions_name[(int) action]);
1175*e4b17023SJohn Marino p = &head->next_chain;
1176*e4b17023SJohn Marino }
1177*e4b17023SJohn Marino }
1178*e4b17023SJohn Marino }
1179*e4b17023SJohn Marino
1180*e4b17023SJohn Marino /* Adapted from find_reloads_address_1. CL is INDEX_REG_CLASS or
1181*e4b17023SJohn Marino BASE_REG_CLASS depending on how the register is being considered. */
1182*e4b17023SJohn Marino
1183*e4b17023SJohn Marino static void
scan_rtx_address(rtx insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum machine_mode mode,addr_space_t as)1184*e4b17023SJohn Marino scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
1185*e4b17023SJohn Marino enum scan_actions action, enum machine_mode mode,
1186*e4b17023SJohn Marino addr_space_t as)
1187*e4b17023SJohn Marino {
1188*e4b17023SJohn Marino rtx x = *loc;
1189*e4b17023SJohn Marino RTX_CODE code = GET_CODE (x);
1190*e4b17023SJohn Marino const char *fmt;
1191*e4b17023SJohn Marino int i, j;
1192*e4b17023SJohn Marino
1193*e4b17023SJohn Marino if (action == mark_write || action == mark_access)
1194*e4b17023SJohn Marino return;
1195*e4b17023SJohn Marino
1196*e4b17023SJohn Marino switch (code)
1197*e4b17023SJohn Marino {
1198*e4b17023SJohn Marino case PLUS:
1199*e4b17023SJohn Marino {
1200*e4b17023SJohn Marino rtx orig_op0 = XEXP (x, 0);
1201*e4b17023SJohn Marino rtx orig_op1 = XEXP (x, 1);
1202*e4b17023SJohn Marino RTX_CODE code0 = GET_CODE (orig_op0);
1203*e4b17023SJohn Marino RTX_CODE code1 = GET_CODE (orig_op1);
1204*e4b17023SJohn Marino rtx op0 = orig_op0;
1205*e4b17023SJohn Marino rtx op1 = orig_op1;
1206*e4b17023SJohn Marino rtx *locI = NULL;
1207*e4b17023SJohn Marino rtx *locB = NULL;
1208*e4b17023SJohn Marino enum rtx_code index_code = SCRATCH;
1209*e4b17023SJohn Marino
1210*e4b17023SJohn Marino if (GET_CODE (op0) == SUBREG)
1211*e4b17023SJohn Marino {
1212*e4b17023SJohn Marino op0 = SUBREG_REG (op0);
1213*e4b17023SJohn Marino code0 = GET_CODE (op0);
1214*e4b17023SJohn Marino }
1215*e4b17023SJohn Marino
1216*e4b17023SJohn Marino if (GET_CODE (op1) == SUBREG)
1217*e4b17023SJohn Marino {
1218*e4b17023SJohn Marino op1 = SUBREG_REG (op1);
1219*e4b17023SJohn Marino code1 = GET_CODE (op1);
1220*e4b17023SJohn Marino }
1221*e4b17023SJohn Marino
1222*e4b17023SJohn Marino if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
1223*e4b17023SJohn Marino || code0 == ZERO_EXTEND || code1 == MEM)
1224*e4b17023SJohn Marino {
1225*e4b17023SJohn Marino locI = &XEXP (x, 0);
1226*e4b17023SJohn Marino locB = &XEXP (x, 1);
1227*e4b17023SJohn Marino index_code = GET_CODE (*locI);
1228*e4b17023SJohn Marino }
1229*e4b17023SJohn Marino else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
1230*e4b17023SJohn Marino || code1 == ZERO_EXTEND || code0 == MEM)
1231*e4b17023SJohn Marino {
1232*e4b17023SJohn Marino locI = &XEXP (x, 1);
1233*e4b17023SJohn Marino locB = &XEXP (x, 0);
1234*e4b17023SJohn Marino index_code = GET_CODE (*locI);
1235*e4b17023SJohn Marino }
1236*e4b17023SJohn Marino else if (code0 == CONST_INT || code0 == CONST
1237*e4b17023SJohn Marino || code0 == SYMBOL_REF || code0 == LABEL_REF)
1238*e4b17023SJohn Marino {
1239*e4b17023SJohn Marino locB = &XEXP (x, 1);
1240*e4b17023SJohn Marino index_code = GET_CODE (XEXP (x, 0));
1241*e4b17023SJohn Marino }
1242*e4b17023SJohn Marino else if (code1 == CONST_INT || code1 == CONST
1243*e4b17023SJohn Marino || code1 == SYMBOL_REF || code1 == LABEL_REF)
1244*e4b17023SJohn Marino {
1245*e4b17023SJohn Marino locB = &XEXP (x, 0);
1246*e4b17023SJohn Marino index_code = GET_CODE (XEXP (x, 1));
1247*e4b17023SJohn Marino }
1248*e4b17023SJohn Marino else if (code0 == REG && code1 == REG)
1249*e4b17023SJohn Marino {
1250*e4b17023SJohn Marino int index_op;
1251*e4b17023SJohn Marino unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
1252*e4b17023SJohn Marino
1253*e4b17023SJohn Marino if (REGNO_OK_FOR_INDEX_P (regno1)
1254*e4b17023SJohn Marino && regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
1255*e4b17023SJohn Marino index_op = 1;
1256*e4b17023SJohn Marino else if (REGNO_OK_FOR_INDEX_P (regno0)
1257*e4b17023SJohn Marino && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
1258*e4b17023SJohn Marino index_op = 0;
1259*e4b17023SJohn Marino else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
1260*e4b17023SJohn Marino || REGNO_OK_FOR_INDEX_P (regno1))
1261*e4b17023SJohn Marino index_op = 1;
1262*e4b17023SJohn Marino else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
1263*e4b17023SJohn Marino index_op = 0;
1264*e4b17023SJohn Marino else
1265*e4b17023SJohn Marino index_op = 1;
1266*e4b17023SJohn Marino
1267*e4b17023SJohn Marino locI = &XEXP (x, index_op);
1268*e4b17023SJohn Marino locB = &XEXP (x, !index_op);
1269*e4b17023SJohn Marino index_code = GET_CODE (*locI);
1270*e4b17023SJohn Marino }
1271*e4b17023SJohn Marino else if (code0 == REG)
1272*e4b17023SJohn Marino {
1273*e4b17023SJohn Marino locI = &XEXP (x, 0);
1274*e4b17023SJohn Marino locB = &XEXP (x, 1);
1275*e4b17023SJohn Marino index_code = GET_CODE (*locI);
1276*e4b17023SJohn Marino }
1277*e4b17023SJohn Marino else if (code1 == REG)
1278*e4b17023SJohn Marino {
1279*e4b17023SJohn Marino locI = &XEXP (x, 1);
1280*e4b17023SJohn Marino locB = &XEXP (x, 0);
1281*e4b17023SJohn Marino index_code = GET_CODE (*locI);
1282*e4b17023SJohn Marino }
1283*e4b17023SJohn Marino
1284*e4b17023SJohn Marino if (locI)
1285*e4b17023SJohn Marino scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode, as);
1286*e4b17023SJohn Marino if (locB)
1287*e4b17023SJohn Marino scan_rtx_address (insn, locB,
1288*e4b17023SJohn Marino base_reg_class (mode, as, PLUS, index_code),
1289*e4b17023SJohn Marino action, mode, as);
1290*e4b17023SJohn Marino
1291*e4b17023SJohn Marino return;
1292*e4b17023SJohn Marino }
1293*e4b17023SJohn Marino
1294*e4b17023SJohn Marino case POST_INC:
1295*e4b17023SJohn Marino case POST_DEC:
1296*e4b17023SJohn Marino case POST_MODIFY:
1297*e4b17023SJohn Marino case PRE_INC:
1298*e4b17023SJohn Marino case PRE_DEC:
1299*e4b17023SJohn Marino case PRE_MODIFY:
1300*e4b17023SJohn Marino #ifndef AUTO_INC_DEC
1301*e4b17023SJohn Marino /* If the target doesn't claim to handle autoinc, this must be
1302*e4b17023SJohn Marino something special, like a stack push. Kill this chain. */
1303*e4b17023SJohn Marino action = mark_all_read;
1304*e4b17023SJohn Marino #endif
1305*e4b17023SJohn Marino break;
1306*e4b17023SJohn Marino
1307*e4b17023SJohn Marino case MEM:
1308*e4b17023SJohn Marino scan_rtx_address (insn, &XEXP (x, 0),
1309*e4b17023SJohn Marino base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
1310*e4b17023SJohn Marino MEM, SCRATCH),
1311*e4b17023SJohn Marino action, GET_MODE (x), MEM_ADDR_SPACE (x));
1312*e4b17023SJohn Marino return;
1313*e4b17023SJohn Marino
1314*e4b17023SJohn Marino case REG:
1315*e4b17023SJohn Marino scan_rtx_reg (insn, loc, cl, action, OP_IN);
1316*e4b17023SJohn Marino return;
1317*e4b17023SJohn Marino
1318*e4b17023SJohn Marino default:
1319*e4b17023SJohn Marino break;
1320*e4b17023SJohn Marino }
1321*e4b17023SJohn Marino
1322*e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
1323*e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1324*e4b17023SJohn Marino {
1325*e4b17023SJohn Marino if (fmt[i] == 'e')
1326*e4b17023SJohn Marino scan_rtx_address (insn, &XEXP (x, i), cl, action, mode, as);
1327*e4b17023SJohn Marino else if (fmt[i] == 'E')
1328*e4b17023SJohn Marino for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1329*e4b17023SJohn Marino scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode, as);
1330*e4b17023SJohn Marino }
1331*e4b17023SJohn Marino }
1332*e4b17023SJohn Marino
1333*e4b17023SJohn Marino static void
scan_rtx(rtx insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum op_type type)1334*e4b17023SJohn Marino scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
1335*e4b17023SJohn Marino enum op_type type)
1336*e4b17023SJohn Marino {
1337*e4b17023SJohn Marino const char *fmt;
1338*e4b17023SJohn Marino rtx x = *loc;
1339*e4b17023SJohn Marino enum rtx_code code = GET_CODE (x);
1340*e4b17023SJohn Marino int i, j;
1341*e4b17023SJohn Marino
1342*e4b17023SJohn Marino code = GET_CODE (x);
1343*e4b17023SJohn Marino switch (code)
1344*e4b17023SJohn Marino {
1345*e4b17023SJohn Marino case CONST:
1346*e4b17023SJohn Marino case CONST_INT:
1347*e4b17023SJohn Marino case CONST_DOUBLE:
1348*e4b17023SJohn Marino case CONST_FIXED:
1349*e4b17023SJohn Marino case CONST_VECTOR:
1350*e4b17023SJohn Marino case SYMBOL_REF:
1351*e4b17023SJohn Marino case LABEL_REF:
1352*e4b17023SJohn Marino case CC0:
1353*e4b17023SJohn Marino case PC:
1354*e4b17023SJohn Marino return;
1355*e4b17023SJohn Marino
1356*e4b17023SJohn Marino case REG:
1357*e4b17023SJohn Marino scan_rtx_reg (insn, loc, cl, action, type);
1358*e4b17023SJohn Marino return;
1359*e4b17023SJohn Marino
1360*e4b17023SJohn Marino case MEM:
1361*e4b17023SJohn Marino scan_rtx_address (insn, &XEXP (x, 0),
1362*e4b17023SJohn Marino base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
1363*e4b17023SJohn Marino MEM, SCRATCH),
1364*e4b17023SJohn Marino action, GET_MODE (x), MEM_ADDR_SPACE (x));
1365*e4b17023SJohn Marino return;
1366*e4b17023SJohn Marino
1367*e4b17023SJohn Marino case SET:
1368*e4b17023SJohn Marino scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN);
1369*e4b17023SJohn Marino scan_rtx (insn, &SET_DEST (x), cl, action,
1370*e4b17023SJohn Marino (GET_CODE (PATTERN (insn)) == COND_EXEC
1371*e4b17023SJohn Marino && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
1372*e4b17023SJohn Marino return;
1373*e4b17023SJohn Marino
1374*e4b17023SJohn Marino case STRICT_LOW_PART:
1375*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, 0), cl, action,
1376*e4b17023SJohn Marino verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT);
1377*e4b17023SJohn Marino return;
1378*e4b17023SJohn Marino
1379*e4b17023SJohn Marino case ZERO_EXTRACT:
1380*e4b17023SJohn Marino case SIGN_EXTRACT:
1381*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, 0), cl, action,
1382*e4b17023SJohn Marino (type == OP_IN ? OP_IN :
1383*e4b17023SJohn Marino verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT));
1384*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN);
1385*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN);
1386*e4b17023SJohn Marino return;
1387*e4b17023SJohn Marino
1388*e4b17023SJohn Marino case POST_INC:
1389*e4b17023SJohn Marino case PRE_INC:
1390*e4b17023SJohn Marino case POST_DEC:
1391*e4b17023SJohn Marino case PRE_DEC:
1392*e4b17023SJohn Marino case POST_MODIFY:
1393*e4b17023SJohn Marino case PRE_MODIFY:
1394*e4b17023SJohn Marino /* Should only happen inside MEM. */
1395*e4b17023SJohn Marino gcc_unreachable ();
1396*e4b17023SJohn Marino
1397*e4b17023SJohn Marino case CLOBBER:
1398*e4b17023SJohn Marino scan_rtx (insn, &SET_DEST (x), cl, action,
1399*e4b17023SJohn Marino (GET_CODE (PATTERN (insn)) == COND_EXEC
1400*e4b17023SJohn Marino && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
1401*e4b17023SJohn Marino return;
1402*e4b17023SJohn Marino
1403*e4b17023SJohn Marino case EXPR_LIST:
1404*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, 0), cl, action, type);
1405*e4b17023SJohn Marino if (XEXP (x, 1))
1406*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, 1), cl, action, type);
1407*e4b17023SJohn Marino return;
1408*e4b17023SJohn Marino
1409*e4b17023SJohn Marino default:
1410*e4b17023SJohn Marino break;
1411*e4b17023SJohn Marino }
1412*e4b17023SJohn Marino
1413*e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
1414*e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1415*e4b17023SJohn Marino {
1416*e4b17023SJohn Marino if (fmt[i] == 'e')
1417*e4b17023SJohn Marino scan_rtx (insn, &XEXP (x, i), cl, action, type);
1418*e4b17023SJohn Marino else if (fmt[i] == 'E')
1419*e4b17023SJohn Marino for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1420*e4b17023SJohn Marino scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type);
1421*e4b17023SJohn Marino }
1422*e4b17023SJohn Marino }
1423*e4b17023SJohn Marino
1424*e4b17023SJohn Marino /* Hide operands of the current insn (of which there are N_OPS) by
1425*e4b17023SJohn Marino substituting cc0 for them.
1426*e4b17023SJohn Marino Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
1427*e4b17023SJohn Marino For every bit set in DO_NOT_HIDE, we leave the operand alone.
1428*e4b17023SJohn Marino If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
1429*e4b17023SJohn Marino and earlyclobbers. */
1430*e4b17023SJohn Marino
1431*e4b17023SJohn Marino static void
hide_operands(int n_ops,rtx * old_operands,rtx * old_dups,unsigned HOST_WIDE_INT do_not_hide,bool inout_and_ec_only)1432*e4b17023SJohn Marino hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
1433*e4b17023SJohn Marino unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only)
1434*e4b17023SJohn Marino {
1435*e4b17023SJohn Marino int i;
1436*e4b17023SJohn Marino int alt = which_alternative;
1437*e4b17023SJohn Marino for (i = 0; i < n_ops; i++)
1438*e4b17023SJohn Marino {
1439*e4b17023SJohn Marino old_operands[i] = recog_data.operand[i];
1440*e4b17023SJohn Marino /* Don't squash match_operator or match_parallel here, since
1441*e4b17023SJohn Marino we don't know that all of the contained registers are
1442*e4b17023SJohn Marino reachable by proper operands. */
1443*e4b17023SJohn Marino if (recog_data.constraints[i][0] == '\0')
1444*e4b17023SJohn Marino continue;
1445*e4b17023SJohn Marino if (do_not_hide & (1 << i))
1446*e4b17023SJohn Marino continue;
1447*e4b17023SJohn Marino if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT
1448*e4b17023SJohn Marino || recog_op_alt[i][alt].earlyclobber)
1449*e4b17023SJohn Marino *recog_data.operand_loc[i] = cc0_rtx;
1450*e4b17023SJohn Marino }
1451*e4b17023SJohn Marino for (i = 0; i < recog_data.n_dups; i++)
1452*e4b17023SJohn Marino {
1453*e4b17023SJohn Marino int opn = recog_data.dup_num[i];
1454*e4b17023SJohn Marino old_dups[i] = *recog_data.dup_loc[i];
1455*e4b17023SJohn Marino if (do_not_hide & (1 << opn))
1456*e4b17023SJohn Marino continue;
1457*e4b17023SJohn Marino if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT
1458*e4b17023SJohn Marino || recog_op_alt[opn][alt].earlyclobber)
1459*e4b17023SJohn Marino *recog_data.dup_loc[i] = cc0_rtx;
1460*e4b17023SJohn Marino }
1461*e4b17023SJohn Marino }
1462*e4b17023SJohn Marino
1463*e4b17023SJohn Marino /* Undo the substitution performed by hide_operands. INSN is the insn we
1464*e4b17023SJohn Marino are processing; the arguments are the same as in hide_operands. */
1465*e4b17023SJohn Marino
1466*e4b17023SJohn Marino static void
restore_operands(rtx insn,int n_ops,rtx * old_operands,rtx * old_dups)1467*e4b17023SJohn Marino restore_operands (rtx insn, int n_ops, rtx *old_operands, rtx *old_dups)
1468*e4b17023SJohn Marino {
1469*e4b17023SJohn Marino int i;
1470*e4b17023SJohn Marino for (i = 0; i < recog_data.n_dups; i++)
1471*e4b17023SJohn Marino *recog_data.dup_loc[i] = old_dups[i];
1472*e4b17023SJohn Marino for (i = 0; i < n_ops; i++)
1473*e4b17023SJohn Marino *recog_data.operand_loc[i] = old_operands[i];
1474*e4b17023SJohn Marino if (recog_data.n_dups)
1475*e4b17023SJohn Marino df_insn_rescan (insn);
1476*e4b17023SJohn Marino }
1477*e4b17023SJohn Marino
1478*e4b17023SJohn Marino /* For each output operand of INSN, call scan_rtx to create a new
1479*e4b17023SJohn Marino open chain. Do this only for normal or earlyclobber outputs,
1480*e4b17023SJohn Marino depending on EARLYCLOBBER. If INSN_INFO is nonnull, use it to
1481*e4b17023SJohn Marino record information about the operands in the insn. */
1482*e4b17023SJohn Marino
1483*e4b17023SJohn Marino static void
record_out_operands(rtx insn,bool earlyclobber,insn_rr_info * insn_info)1484*e4b17023SJohn Marino record_out_operands (rtx insn, bool earlyclobber, insn_rr_info *insn_info)
1485*e4b17023SJohn Marino {
1486*e4b17023SJohn Marino int n_ops = recog_data.n_operands;
1487*e4b17023SJohn Marino int alt = which_alternative;
1488*e4b17023SJohn Marino
1489*e4b17023SJohn Marino int i;
1490*e4b17023SJohn Marino
1491*e4b17023SJohn Marino for (i = 0; i < n_ops + recog_data.n_dups; i++)
1492*e4b17023SJohn Marino {
1493*e4b17023SJohn Marino int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
1494*e4b17023SJohn Marino rtx *loc = (i < n_ops
1495*e4b17023SJohn Marino ? recog_data.operand_loc[opn]
1496*e4b17023SJohn Marino : recog_data.dup_loc[i - n_ops]);
1497*e4b17023SJohn Marino rtx op = *loc;
1498*e4b17023SJohn Marino enum reg_class cl = recog_op_alt[opn][alt].cl;
1499*e4b17023SJohn Marino
1500*e4b17023SJohn Marino struct du_head *prev_open;
1501*e4b17023SJohn Marino
1502*e4b17023SJohn Marino if (recog_data.operand_type[opn] != OP_OUT
1503*e4b17023SJohn Marino || recog_op_alt[opn][alt].earlyclobber != earlyclobber)
1504*e4b17023SJohn Marino continue;
1505*e4b17023SJohn Marino
1506*e4b17023SJohn Marino if (insn_info)
1507*e4b17023SJohn Marino cur_operand = insn_info->op_info + i;
1508*e4b17023SJohn Marino
1509*e4b17023SJohn Marino prev_open = open_chains;
1510*e4b17023SJohn Marino scan_rtx (insn, loc, cl, mark_write, OP_OUT);
1511*e4b17023SJohn Marino
1512*e4b17023SJohn Marino /* ??? Many targets have output constraints on the SET_DEST
1513*e4b17023SJohn Marino of a call insn, which is stupid, since these are certainly
1514*e4b17023SJohn Marino ABI defined hard registers. For these, and for asm operands
1515*e4b17023SJohn Marino that originally referenced hard registers, we must record that
1516*e4b17023SJohn Marino the chain cannot be renamed. */
1517*e4b17023SJohn Marino if (CALL_P (insn)
1518*e4b17023SJohn Marino || (asm_noperands (PATTERN (insn)) > 0
1519*e4b17023SJohn Marino && REG_P (op)
1520*e4b17023SJohn Marino && REGNO (op) == ORIGINAL_REGNO (op)))
1521*e4b17023SJohn Marino {
1522*e4b17023SJohn Marino if (prev_open != open_chains)
1523*e4b17023SJohn Marino open_chains->cannot_rename = 1;
1524*e4b17023SJohn Marino }
1525*e4b17023SJohn Marino }
1526*e4b17023SJohn Marino cur_operand = NULL;
1527*e4b17023SJohn Marino }
1528*e4b17023SJohn Marino
1529*e4b17023SJohn Marino /* Build def/use chain. */
1530*e4b17023SJohn Marino
1531*e4b17023SJohn Marino static bool
build_def_use(basic_block bb)1532*e4b17023SJohn Marino build_def_use (basic_block bb)
1533*e4b17023SJohn Marino {
1534*e4b17023SJohn Marino rtx insn;
1535*e4b17023SJohn Marino unsigned HOST_WIDE_INT untracked_operands;
1536*e4b17023SJohn Marino
1537*e4b17023SJohn Marino fail_current_block = false;
1538*e4b17023SJohn Marino
1539*e4b17023SJohn Marino for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
1540*e4b17023SJohn Marino {
1541*e4b17023SJohn Marino if (NONDEBUG_INSN_P (insn))
1542*e4b17023SJohn Marino {
1543*e4b17023SJohn Marino int n_ops;
1544*e4b17023SJohn Marino rtx note;
1545*e4b17023SJohn Marino rtx old_operands[MAX_RECOG_OPERANDS];
1546*e4b17023SJohn Marino rtx old_dups[MAX_DUP_OPERANDS];
1547*e4b17023SJohn Marino int i;
1548*e4b17023SJohn Marino int alt;
1549*e4b17023SJohn Marino int predicated;
1550*e4b17023SJohn Marino enum rtx_code set_code = SET;
1551*e4b17023SJohn Marino enum rtx_code clobber_code = CLOBBER;
1552*e4b17023SJohn Marino insn_rr_info *insn_info = NULL;
1553*e4b17023SJohn Marino
1554*e4b17023SJohn Marino /* Process the insn, determining its effect on the def-use
1555*e4b17023SJohn Marino chains and live hard registers. We perform the following
1556*e4b17023SJohn Marino steps with the register references in the insn, simulating
1557*e4b17023SJohn Marino its effect:
1558*e4b17023SJohn Marino (1) Deal with earlyclobber operands and CLOBBERs of non-operands
1559*e4b17023SJohn Marino by creating chains and marking hard regs live.
1560*e4b17023SJohn Marino (2) Any read outside an operand causes any chain it overlaps
1561*e4b17023SJohn Marino with to be marked unrenamable.
1562*e4b17023SJohn Marino (3) Any read inside an operand is added if there's already
1563*e4b17023SJohn Marino an open chain for it.
1564*e4b17023SJohn Marino (4) For any REG_DEAD note we find, close open chains that
1565*e4b17023SJohn Marino overlap it.
1566*e4b17023SJohn Marino (5) For any non-earlyclobber write we find, close open chains
1567*e4b17023SJohn Marino that overlap it.
1568*e4b17023SJohn Marino (6) For any non-earlyclobber write we find in an operand, make
1569*e4b17023SJohn Marino a new chain or mark the hard register as live.
1570*e4b17023SJohn Marino (7) For any REG_UNUSED, close any chains we just opened.
1571*e4b17023SJohn Marino
1572*e4b17023SJohn Marino We cannot deal with situations where we track a reg in one mode
1573*e4b17023SJohn Marino and see a reference in another mode; these will cause the chain
1574*e4b17023SJohn Marino to be marked unrenamable or even cause us to abort the entire
1575*e4b17023SJohn Marino basic block. */
1576*e4b17023SJohn Marino
1577*e4b17023SJohn Marino extract_insn (insn);
1578*e4b17023SJohn Marino if (! constrain_operands (1))
1579*e4b17023SJohn Marino fatal_insn_not_found (insn);
1580*e4b17023SJohn Marino preprocess_constraints ();
1581*e4b17023SJohn Marino alt = which_alternative;
1582*e4b17023SJohn Marino n_ops = recog_data.n_operands;
1583*e4b17023SJohn Marino untracked_operands = 0;
1584*e4b17023SJohn Marino
1585*e4b17023SJohn Marino if (insn_rr != NULL)
1586*e4b17023SJohn Marino {
1587*e4b17023SJohn Marino insn_info = VEC_index (insn_rr_info, insn_rr, INSN_UID (insn));
1588*e4b17023SJohn Marino insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
1589*e4b17023SJohn Marino recog_data.n_operands);
1590*e4b17023SJohn Marino memset (insn_info->op_info, 0,
1591*e4b17023SJohn Marino sizeof (operand_rr_info) * recog_data.n_operands);
1592*e4b17023SJohn Marino }
1593*e4b17023SJohn Marino
1594*e4b17023SJohn Marino /* Simplify the code below by rewriting things to reflect
1595*e4b17023SJohn Marino matching constraints. Also promote OP_OUT to OP_INOUT in
1596*e4b17023SJohn Marino predicated instructions, but only for register operands
1597*e4b17023SJohn Marino that are already tracked, so that we can create a chain
1598*e4b17023SJohn Marino when the first SET makes a register live. */
1599*e4b17023SJohn Marino
1600*e4b17023SJohn Marino predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
1601*e4b17023SJohn Marino for (i = 0; i < n_ops; ++i)
1602*e4b17023SJohn Marino {
1603*e4b17023SJohn Marino rtx op = recog_data.operand[i];
1604*e4b17023SJohn Marino int matches = recog_op_alt[i][alt].matches;
1605*e4b17023SJohn Marino if (matches >= 0)
1606*e4b17023SJohn Marino recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl;
1607*e4b17023SJohn Marino if (matches >= 0 || recog_op_alt[i][alt].matched >= 0
1608*e4b17023SJohn Marino || (predicated && recog_data.operand_type[i] == OP_OUT))
1609*e4b17023SJohn Marino {
1610*e4b17023SJohn Marino recog_data.operand_type[i] = OP_INOUT;
1611*e4b17023SJohn Marino /* A special case to deal with instruction patterns that
1612*e4b17023SJohn Marino have matching operands with different modes. If we're
1613*e4b17023SJohn Marino not already tracking such a reg, we won't start here,
1614*e4b17023SJohn Marino and we must instead make sure to make the operand visible
1615*e4b17023SJohn Marino to the machinery that tracks hard registers. */
1616*e4b17023SJohn Marino if (matches >= 0
1617*e4b17023SJohn Marino && (GET_MODE_SIZE (recog_data.operand_mode[i])
1618*e4b17023SJohn Marino != GET_MODE_SIZE (recog_data.operand_mode[matches]))
1619*e4b17023SJohn Marino && !verify_reg_in_set (op, &live_in_chains))
1620*e4b17023SJohn Marino {
1621*e4b17023SJohn Marino untracked_operands |= 1 << i;
1622*e4b17023SJohn Marino untracked_operands |= 1 << matches;
1623*e4b17023SJohn Marino }
1624*e4b17023SJohn Marino }
1625*e4b17023SJohn Marino /* If there's an in-out operand with a register that is not
1626*e4b17023SJohn Marino being tracked at all yet, open a chain. */
1627*e4b17023SJohn Marino if (recog_data.operand_type[i] == OP_INOUT
1628*e4b17023SJohn Marino && !(untracked_operands & (1 << i))
1629*e4b17023SJohn Marino && REG_P (op)
1630*e4b17023SJohn Marino && !verify_reg_tracked (op))
1631*e4b17023SJohn Marino {
1632*e4b17023SJohn Marino enum machine_mode mode = GET_MODE (op);
1633*e4b17023SJohn Marino unsigned this_regno = REGNO (op);
1634*e4b17023SJohn Marino unsigned this_nregs = hard_regno_nregs[this_regno][mode];
1635*e4b17023SJohn Marino create_new_chain (this_regno, this_nregs, NULL, NULL_RTX,
1636*e4b17023SJohn Marino NO_REGS);
1637*e4b17023SJohn Marino }
1638*e4b17023SJohn Marino }
1639*e4b17023SJohn Marino
1640*e4b17023SJohn Marino if (fail_current_block)
1641*e4b17023SJohn Marino break;
1642*e4b17023SJohn Marino
1643*e4b17023SJohn Marino /* Step 1a: Mark hard registers that are clobbered in this insn,
1644*e4b17023SJohn Marino outside an operand, as live. */
1645*e4b17023SJohn Marino hide_operands (n_ops, old_operands, old_dups, untracked_operands,
1646*e4b17023SJohn Marino false);
1647*e4b17023SJohn Marino note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code);
1648*e4b17023SJohn Marino restore_operands (insn, n_ops, old_operands, old_dups);
1649*e4b17023SJohn Marino
1650*e4b17023SJohn Marino /* Step 1b: Begin new chains for earlyclobbered writes inside
1651*e4b17023SJohn Marino operands. */
1652*e4b17023SJohn Marino record_out_operands (insn, true, insn_info);
1653*e4b17023SJohn Marino
1654*e4b17023SJohn Marino /* Step 2: Mark chains for which we have reads outside operands
1655*e4b17023SJohn Marino as unrenamable.
1656*e4b17023SJohn Marino We do this by munging all operands into CC0, and closing
1657*e4b17023SJohn Marino everything remaining. */
1658*e4b17023SJohn Marino
1659*e4b17023SJohn Marino hide_operands (n_ops, old_operands, old_dups, untracked_operands,
1660*e4b17023SJohn Marino false);
1661*e4b17023SJohn Marino scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN);
1662*e4b17023SJohn Marino restore_operands (insn, n_ops, old_operands, old_dups);
1663*e4b17023SJohn Marino
1664*e4b17023SJohn Marino /* Step 2B: Can't rename function call argument registers. */
1665*e4b17023SJohn Marino if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
1666*e4b17023SJohn Marino scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
1667*e4b17023SJohn Marino NO_REGS, mark_all_read, OP_IN);
1668*e4b17023SJohn Marino
1669*e4b17023SJohn Marino /* Step 2C: Can't rename asm operands that were originally
1670*e4b17023SJohn Marino hard registers. */
1671*e4b17023SJohn Marino if (asm_noperands (PATTERN (insn)) > 0)
1672*e4b17023SJohn Marino for (i = 0; i < n_ops; i++)
1673*e4b17023SJohn Marino {
1674*e4b17023SJohn Marino rtx *loc = recog_data.operand_loc[i];
1675*e4b17023SJohn Marino rtx op = *loc;
1676*e4b17023SJohn Marino
1677*e4b17023SJohn Marino if (REG_P (op)
1678*e4b17023SJohn Marino && REGNO (op) == ORIGINAL_REGNO (op)
1679*e4b17023SJohn Marino && (recog_data.operand_type[i] == OP_IN
1680*e4b17023SJohn Marino || recog_data.operand_type[i] == OP_INOUT))
1681*e4b17023SJohn Marino scan_rtx (insn, loc, NO_REGS, mark_all_read, OP_IN);
1682*e4b17023SJohn Marino }
1683*e4b17023SJohn Marino
1684*e4b17023SJohn Marino /* Step 3: Append to chains for reads inside operands. */
1685*e4b17023SJohn Marino for (i = 0; i < n_ops + recog_data.n_dups; i++)
1686*e4b17023SJohn Marino {
1687*e4b17023SJohn Marino int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
1688*e4b17023SJohn Marino rtx *loc = (i < n_ops
1689*e4b17023SJohn Marino ? recog_data.operand_loc[opn]
1690*e4b17023SJohn Marino : recog_data.dup_loc[i - n_ops]);
1691*e4b17023SJohn Marino enum reg_class cl = recog_op_alt[opn][alt].cl;
1692*e4b17023SJohn Marino enum op_type type = recog_data.operand_type[opn];
1693*e4b17023SJohn Marino
1694*e4b17023SJohn Marino /* Don't scan match_operand here, since we've no reg class
1695*e4b17023SJohn Marino information to pass down. Any operands that we could
1696*e4b17023SJohn Marino substitute in will be represented elsewhere. */
1697*e4b17023SJohn Marino if (recog_data.constraints[opn][0] == '\0'
1698*e4b17023SJohn Marino || untracked_operands & (1 << opn))
1699*e4b17023SJohn Marino continue;
1700*e4b17023SJohn Marino
1701*e4b17023SJohn Marino if (insn_info)
1702*e4b17023SJohn Marino cur_operand = i == opn ? insn_info->op_info + i : NULL;
1703*e4b17023SJohn Marino if (recog_op_alt[opn][alt].is_address)
1704*e4b17023SJohn Marino scan_rtx_address (insn, loc, cl, mark_read,
1705*e4b17023SJohn Marino VOIDmode, ADDR_SPACE_GENERIC);
1706*e4b17023SJohn Marino else
1707*e4b17023SJohn Marino scan_rtx (insn, loc, cl, mark_read, type);
1708*e4b17023SJohn Marino }
1709*e4b17023SJohn Marino cur_operand = NULL;
1710*e4b17023SJohn Marino
1711*e4b17023SJohn Marino /* Step 3B: Record updates for regs in REG_INC notes, and
1712*e4b17023SJohn Marino source regs in REG_FRAME_RELATED_EXPR notes. */
1713*e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1714*e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_INC
1715*e4b17023SJohn Marino || REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
1716*e4b17023SJohn Marino scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
1717*e4b17023SJohn Marino OP_INOUT);
1718*e4b17023SJohn Marino
1719*e4b17023SJohn Marino /* Step 4: Close chains for registers that die here. */
1720*e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1721*e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_DEAD)
1722*e4b17023SJohn Marino {
1723*e4b17023SJohn Marino remove_from_hard_reg_set (&live_hard_regs,
1724*e4b17023SJohn Marino GET_MODE (XEXP (note, 0)),
1725*e4b17023SJohn Marino REGNO (XEXP (note, 0)));
1726*e4b17023SJohn Marino scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
1727*e4b17023SJohn Marino OP_IN);
1728*e4b17023SJohn Marino }
1729*e4b17023SJohn Marino
1730*e4b17023SJohn Marino /* Step 4B: If this is a call, any chain live at this point
1731*e4b17023SJohn Marino requires a caller-saved reg. */
1732*e4b17023SJohn Marino if (CALL_P (insn))
1733*e4b17023SJohn Marino {
1734*e4b17023SJohn Marino struct du_head *p;
1735*e4b17023SJohn Marino for (p = open_chains; p; p = p->next_chain)
1736*e4b17023SJohn Marino p->need_caller_save_reg = 1;
1737*e4b17023SJohn Marino }
1738*e4b17023SJohn Marino
1739*e4b17023SJohn Marino /* Step 5: Close open chains that overlap writes. Similar to
1740*e4b17023SJohn Marino step 2, we hide in-out operands, since we do not want to
1741*e4b17023SJohn Marino close these chains. We also hide earlyclobber operands,
1742*e4b17023SJohn Marino since we've opened chains for them in step 1, and earlier
1743*e4b17023SJohn Marino chains they would overlap with must have been closed at
1744*e4b17023SJohn Marino the previous insn at the latest, as such operands cannot
1745*e4b17023SJohn Marino possibly overlap with any input operands. */
1746*e4b17023SJohn Marino
1747*e4b17023SJohn Marino hide_operands (n_ops, old_operands, old_dups, untracked_operands,
1748*e4b17023SJohn Marino true);
1749*e4b17023SJohn Marino scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN);
1750*e4b17023SJohn Marino restore_operands (insn, n_ops, old_operands, old_dups);
1751*e4b17023SJohn Marino
1752*e4b17023SJohn Marino /* Step 6a: Mark hard registers that are set in this insn,
1753*e4b17023SJohn Marino outside an operand, as live. */
1754*e4b17023SJohn Marino hide_operands (n_ops, old_operands, old_dups, untracked_operands,
1755*e4b17023SJohn Marino false);
1756*e4b17023SJohn Marino note_stores (PATTERN (insn), note_sets_clobbers, &set_code);
1757*e4b17023SJohn Marino restore_operands (insn, n_ops, old_operands, old_dups);
1758*e4b17023SJohn Marino
1759*e4b17023SJohn Marino /* Step 6b: Begin new chains for writes inside operands. */
1760*e4b17023SJohn Marino record_out_operands (insn, false, insn_info);
1761*e4b17023SJohn Marino
1762*e4b17023SJohn Marino /* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
1763*e4b17023SJohn Marino notes for update. */
1764*e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1765*e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
1766*e4b17023SJohn Marino scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access,
1767*e4b17023SJohn Marino OP_INOUT);
1768*e4b17023SJohn Marino
1769*e4b17023SJohn Marino /* Step 7: Close chains for registers that were never
1770*e4b17023SJohn Marino really used here. */
1771*e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1772*e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_UNUSED)
1773*e4b17023SJohn Marino {
1774*e4b17023SJohn Marino remove_from_hard_reg_set (&live_hard_regs,
1775*e4b17023SJohn Marino GET_MODE (XEXP (note, 0)),
1776*e4b17023SJohn Marino REGNO (XEXP (note, 0)));
1777*e4b17023SJohn Marino scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
1778*e4b17023SJohn Marino OP_IN);
1779*e4b17023SJohn Marino }
1780*e4b17023SJohn Marino }
1781*e4b17023SJohn Marino else if (DEBUG_INSN_P (insn)
1782*e4b17023SJohn Marino && !VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)))
1783*e4b17023SJohn Marino {
1784*e4b17023SJohn Marino scan_rtx (insn, &INSN_VAR_LOCATION_LOC (insn),
1785*e4b17023SJohn Marino ALL_REGS, mark_read, OP_IN);
1786*e4b17023SJohn Marino }
1787*e4b17023SJohn Marino if (insn == BB_END (bb))
1788*e4b17023SJohn Marino break;
1789*e4b17023SJohn Marino }
1790*e4b17023SJohn Marino
1791*e4b17023SJohn Marino if (fail_current_block)
1792*e4b17023SJohn Marino return false;
1793*e4b17023SJohn Marino
1794*e4b17023SJohn Marino return true;
1795*e4b17023SJohn Marino }
1796*e4b17023SJohn Marino
1797*e4b17023SJohn Marino /* Initialize the register renamer. If INSN_INFO is true, ensure that
1798*e4b17023SJohn Marino insn_rr is nonnull. */
1799*e4b17023SJohn Marino void
regrename_init(bool insn_info)1800*e4b17023SJohn Marino regrename_init (bool insn_info)
1801*e4b17023SJohn Marino {
1802*e4b17023SJohn Marino gcc_obstack_init (&rename_obstack);
1803*e4b17023SJohn Marino insn_rr = NULL;
1804*e4b17023SJohn Marino if (insn_info)
1805*e4b17023SJohn Marino VEC_safe_grow_cleared (insn_rr_info, heap, insn_rr, get_max_uid ());
1806*e4b17023SJohn Marino }
1807*e4b17023SJohn Marino
1808*e4b17023SJohn Marino /* Free all global data used by the register renamer. */
1809*e4b17023SJohn Marino void
regrename_finish(void)1810*e4b17023SJohn Marino regrename_finish (void)
1811*e4b17023SJohn Marino {
1812*e4b17023SJohn Marino VEC_free (insn_rr_info, heap, insn_rr);
1813*e4b17023SJohn Marino free_chain_data ();
1814*e4b17023SJohn Marino obstack_free (&rename_obstack, NULL);
1815*e4b17023SJohn Marino }
1816*e4b17023SJohn Marino
1817*e4b17023SJohn Marino /* Perform register renaming on the current function. */
1818*e4b17023SJohn Marino
1819*e4b17023SJohn Marino static unsigned int
regrename_optimize(void)1820*e4b17023SJohn Marino regrename_optimize (void)
1821*e4b17023SJohn Marino {
1822*e4b17023SJohn Marino df_set_flags (DF_LR_RUN_DCE);
1823*e4b17023SJohn Marino df_note_add_problem ();
1824*e4b17023SJohn Marino df_analyze ();
1825*e4b17023SJohn Marino df_set_flags (DF_DEFER_INSN_RESCAN);
1826*e4b17023SJohn Marino
1827*e4b17023SJohn Marino regrename_init (false);
1828*e4b17023SJohn Marino
1829*e4b17023SJohn Marino regrename_analyze (NULL);
1830*e4b17023SJohn Marino
1831*e4b17023SJohn Marino rename_chains ();
1832*e4b17023SJohn Marino
1833*e4b17023SJohn Marino regrename_finish ();
1834*e4b17023SJohn Marino
1835*e4b17023SJohn Marino return 0;
1836*e4b17023SJohn Marino }
1837*e4b17023SJohn Marino
1838*e4b17023SJohn Marino static bool
gate_handle_regrename(void)1839*e4b17023SJohn Marino gate_handle_regrename (void)
1840*e4b17023SJohn Marino {
1841*e4b17023SJohn Marino return (optimize > 0 && (flag_rename_registers));
1842*e4b17023SJohn Marino }
1843*e4b17023SJohn Marino
1844*e4b17023SJohn Marino struct rtl_opt_pass pass_regrename =
1845*e4b17023SJohn Marino {
1846*e4b17023SJohn Marino {
1847*e4b17023SJohn Marino RTL_PASS,
1848*e4b17023SJohn Marino "rnreg", /* name */
1849*e4b17023SJohn Marino gate_handle_regrename, /* gate */
1850*e4b17023SJohn Marino regrename_optimize, /* execute */
1851*e4b17023SJohn Marino NULL, /* sub */
1852*e4b17023SJohn Marino NULL, /* next */
1853*e4b17023SJohn Marino 0, /* static_pass_number */
1854*e4b17023SJohn Marino TV_RENAME_REGISTERS, /* tv_id */
1855*e4b17023SJohn Marino 0, /* properties_required */
1856*e4b17023SJohn Marino 0, /* properties_provided */
1857*e4b17023SJohn Marino 0, /* properties_destroyed */
1858*e4b17023SJohn Marino 0, /* todo_flags_start */
1859*e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing |
1860*e4b17023SJohn Marino 0 /* todo_flags_finish */
1861*e4b17023SJohn Marino }
1862*e4b17023SJohn Marino };
1863