138fd1498Szrj /* Register renaming for the GNU compiler.
238fd1498Szrj Copyright (C) 2000-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it
738fd1498Szrj under the terms of the GNU General Public License as published by
838fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj any later version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT
1238fd1498Szrj ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1338fd1498Szrj or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1438fd1498Szrj License for more details.
1538fd1498Szrj
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3. If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>. */
1938fd1498Szrj
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "backend.h"
2438fd1498Szrj #include "target.h"
2538fd1498Szrj #include "rtl.h"
2638fd1498Szrj #include "df.h"
2738fd1498Szrj #include "memmodel.h"
2838fd1498Szrj #include "tm_p.h"
2938fd1498Szrj #include "insn-config.h"
3038fd1498Szrj #include "regs.h"
3138fd1498Szrj #include "emit-rtl.h"
3238fd1498Szrj #include "recog.h"
3338fd1498Szrj #include "addresses.h"
3438fd1498Szrj #include "cfganal.h"
3538fd1498Szrj #include "tree-pass.h"
3638fd1498Szrj #include "regrename.h"
3738fd1498Szrj
3838fd1498Szrj /* This file implements the RTL register renaming pass of the compiler. It is
3938fd1498Szrj a semi-local pass whose goal is to maximize the usage of the register file
4038fd1498Szrj of the processor by substituting registers for others in the solution given
4138fd1498Szrj by the register allocator. The algorithm is as follows:
4238fd1498Szrj
4338fd1498Szrj 1. Local def/use chains are built: within each basic block, chains are
4438fd1498Szrj opened and closed; if a chain isn't closed at the end of the block,
4538fd1498Szrj it is dropped. We pre-open chains if we have already examined a
4638fd1498Szrj predecessor block and found chains live at the end which match
4738fd1498Szrj live registers at the start of the new block.
4838fd1498Szrj
4938fd1498Szrj 2. We try to combine the local chains across basic block boundaries by
5038fd1498Szrj comparing chains that were open at the start or end of a block to
5138fd1498Szrj those in successor/predecessor blocks.
5238fd1498Szrj
5338fd1498Szrj 3. For each chain, the set of possible renaming registers is computed.
5438fd1498Szrj This takes into account the renaming of previously processed chains.
5538fd1498Szrj Optionally, a preferred class is computed for the renaming register.
5638fd1498Szrj
5738fd1498Szrj 4. The best renaming register is computed for the chain in the above set,
5838fd1498Szrj using a round-robin allocation. If a preferred class exists, then the
5938fd1498Szrj round-robin allocation is done within the class first, if possible.
6038fd1498Szrj The round-robin allocation of renaming registers itself is global.
6138fd1498Szrj
6238fd1498Szrj 5. If a renaming register has been found, it is substituted in the chain.
6338fd1498Szrj
6438fd1498Szrj Targets can parameterize the pass by specifying a preferred class for the
6538fd1498Szrj renaming register for a given (super)class of registers to be renamed.
6638fd1498Szrj
6738fd1498Szrj DEBUG_INSNs are treated specially, in particular registers occurring inside
6838fd1498Szrj them are treated as requiring ALL_REGS as a class. */
6938fd1498Szrj
7038fd1498Szrj #if HOST_BITS_PER_WIDE_INT <= MAX_RECOG_OPERANDS
7138fd1498Szrj #error "Use a different bitmap implementation for untracked_operands."
7238fd1498Szrj #endif
7338fd1498Szrj
7438fd1498Szrj enum scan_actions
7538fd1498Szrj {
7638fd1498Szrj terminate_write,
7738fd1498Szrj terminate_dead,
7838fd1498Szrj mark_all_read,
7938fd1498Szrj mark_read,
8038fd1498Szrj mark_write,
8138fd1498Szrj /* mark_access is for marking the destination regs in
8238fd1498Szrj REG_FRAME_RELATED_EXPR notes (as if they were read) so that the
8338fd1498Szrj note is updated properly. */
8438fd1498Szrj mark_access
8538fd1498Szrj };
8638fd1498Szrj
8738fd1498Szrj static const char * const scan_actions_name[] =
8838fd1498Szrj {
8938fd1498Szrj "terminate_write",
9038fd1498Szrj "terminate_dead",
9138fd1498Szrj "mark_all_read",
9238fd1498Szrj "mark_read",
9338fd1498Szrj "mark_write",
9438fd1498Szrj "mark_access"
9538fd1498Szrj };
9638fd1498Szrj
9738fd1498Szrj /* TICK and THIS_TICK are used to record the last time we saw each
9838fd1498Szrj register. */
9938fd1498Szrj static int tick[FIRST_PSEUDO_REGISTER];
10038fd1498Szrj static int this_tick = 0;
10138fd1498Szrj
10238fd1498Szrj static struct obstack rename_obstack;
10338fd1498Szrj
10438fd1498Szrj /* If nonnull, the code calling into the register renamer requested
10538fd1498Szrj information about insn operands, and we store it here. */
10638fd1498Szrj vec<insn_rr_info> insn_rr;
10738fd1498Szrj
10838fd1498Szrj static void scan_rtx (rtx_insn *, rtx *, enum reg_class, enum scan_actions,
10938fd1498Szrj enum op_type);
11038fd1498Szrj static bool build_def_use (basic_block);
11138fd1498Szrj
11238fd1498Szrj /* The id to be given to the next opened chain. */
11338fd1498Szrj static unsigned current_id;
11438fd1498Szrj
11538fd1498Szrj /* A mapping of unique id numbers to chains. */
11638fd1498Szrj static vec<du_head_p> id_to_chain;
11738fd1498Szrj
11838fd1498Szrj /* List of currently open chains. */
11938fd1498Szrj static struct du_head *open_chains;
12038fd1498Szrj
12138fd1498Szrj /* Bitmap of open chains. The bits set always match the list found in
12238fd1498Szrj open_chains. */
12338fd1498Szrj static bitmap_head open_chains_set;
12438fd1498Szrj
12538fd1498Szrj /* Record the registers being tracked in open_chains. */
12638fd1498Szrj static HARD_REG_SET live_in_chains;
12738fd1498Szrj
12838fd1498Szrj /* Record the registers that are live but not tracked. The intersection
12938fd1498Szrj between this and live_in_chains is empty. */
13038fd1498Szrj static HARD_REG_SET live_hard_regs;
13138fd1498Szrj
13238fd1498Szrj /* Set while scanning RTL if INSN_RR is nonnull, i.e. if the current analysis
13338fd1498Szrj is for a caller that requires operand data. Used in
13438fd1498Szrj record_operand_use. */
13538fd1498Szrj static operand_rr_info *cur_operand;
13638fd1498Szrj
13738fd1498Szrj /* Set while scanning RTL if a register dies. Used to tie chains. */
13838fd1498Szrj static struct du_head *terminated_this_insn;
13938fd1498Szrj
14038fd1498Szrj /* Return the chain corresponding to id number ID. Take into account that
14138fd1498Szrj chains may have been merged. */
14238fd1498Szrj du_head_p
regrename_chain_from_id(unsigned int id)14338fd1498Szrj regrename_chain_from_id (unsigned int id)
14438fd1498Szrj {
14538fd1498Szrj du_head_p first_chain = id_to_chain[id];
14638fd1498Szrj du_head_p chain = first_chain;
14738fd1498Szrj while (chain->id != id)
14838fd1498Szrj {
14938fd1498Szrj id = chain->id;
15038fd1498Szrj chain = id_to_chain[id];
15138fd1498Szrj }
15238fd1498Szrj first_chain->id = id;
15338fd1498Szrj return chain;
15438fd1498Szrj }
15538fd1498Szrj
15638fd1498Szrj /* Dump all def/use chains, starting at id FROM. */
15738fd1498Szrj
15838fd1498Szrj static void
dump_def_use_chain(int from)15938fd1498Szrj dump_def_use_chain (int from)
16038fd1498Szrj {
16138fd1498Szrj du_head_p head;
16238fd1498Szrj int i;
16338fd1498Szrj FOR_EACH_VEC_ELT_FROM (id_to_chain, i, head, from)
16438fd1498Szrj {
16538fd1498Szrj struct du_chain *this_du = head->first;
16638fd1498Szrj
16738fd1498Szrj fprintf (dump_file, "Register %s (%d):",
16838fd1498Szrj reg_names[head->regno], head->nregs);
16938fd1498Szrj while (this_du)
17038fd1498Szrj {
17138fd1498Szrj fprintf (dump_file, " %d [%s]", INSN_UID (this_du->insn),
17238fd1498Szrj reg_class_names[this_du->cl]);
17338fd1498Szrj this_du = this_du->next_use;
17438fd1498Szrj }
17538fd1498Szrj fprintf (dump_file, "\n");
17638fd1498Szrj head = head->next_chain;
17738fd1498Szrj }
17838fd1498Szrj }
17938fd1498Szrj
18038fd1498Szrj static void
free_chain_data(void)18138fd1498Szrj free_chain_data (void)
18238fd1498Szrj {
18338fd1498Szrj int i;
18438fd1498Szrj du_head_p ptr;
18538fd1498Szrj for (i = 0; id_to_chain.iterate (i, &ptr); i++)
18638fd1498Szrj bitmap_clear (&ptr->conflicts);
18738fd1498Szrj
18838fd1498Szrj id_to_chain.release ();
18938fd1498Szrj }
19038fd1498Szrj
19138fd1498Szrj /* Walk all chains starting with CHAINS and record that they conflict with
19238fd1498Szrj another chain whose id is ID. */
19338fd1498Szrj
19438fd1498Szrj static void
mark_conflict(struct du_head * chains,unsigned id)19538fd1498Szrj mark_conflict (struct du_head *chains, unsigned id)
19638fd1498Szrj {
19738fd1498Szrj while (chains)
19838fd1498Szrj {
19938fd1498Szrj bitmap_set_bit (&chains->conflicts, id);
20038fd1498Szrj chains = chains->next_chain;
20138fd1498Szrj }
20238fd1498Szrj }
20338fd1498Szrj
20438fd1498Szrj /* Examine cur_operand, and if it is nonnull, record information about the
20538fd1498Szrj use THIS_DU which is part of the chain HEAD. */
20638fd1498Szrj
20738fd1498Szrj static void
record_operand_use(struct du_head * head,struct du_chain * this_du)20838fd1498Szrj record_operand_use (struct du_head *head, struct du_chain *this_du)
20938fd1498Szrj {
21038fd1498Szrj if (cur_operand == NULL || cur_operand->failed)
21138fd1498Szrj return;
21238fd1498Szrj if (head->cannot_rename)
21338fd1498Szrj {
21438fd1498Szrj cur_operand->failed = true;
21538fd1498Szrj return;
21638fd1498Szrj }
21738fd1498Szrj gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
21838fd1498Szrj cur_operand->heads[cur_operand->n_chains] = head;
21938fd1498Szrj cur_operand->chains[cur_operand->n_chains++] = this_du;
22038fd1498Szrj }
22138fd1498Szrj
22238fd1498Szrj /* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
22338fd1498Szrj and record its occurrence in *LOC, which is being written to in INSN.
22438fd1498Szrj This access requires a register of class CL. */
22538fd1498Szrj
22638fd1498Szrj static du_head_p
create_new_chain(unsigned this_regno,unsigned this_nregs,rtx * loc,rtx_insn * insn,enum reg_class cl)22738fd1498Szrj create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
22838fd1498Szrj rtx_insn *insn, enum reg_class cl)
22938fd1498Szrj {
23038fd1498Szrj struct du_head *head = XOBNEW (&rename_obstack, struct du_head);
23138fd1498Szrj struct du_chain *this_du;
23238fd1498Szrj int nregs;
23338fd1498Szrj
23438fd1498Szrj memset (head, 0, sizeof *head);
23538fd1498Szrj head->next_chain = open_chains;
23638fd1498Szrj head->regno = this_regno;
23738fd1498Szrj head->nregs = this_nregs;
23838fd1498Szrj
23938fd1498Szrj id_to_chain.safe_push (head);
24038fd1498Szrj head->id = current_id++;
24138fd1498Szrj
24238fd1498Szrj bitmap_initialize (&head->conflicts, &bitmap_default_obstack);
24338fd1498Szrj bitmap_copy (&head->conflicts, &open_chains_set);
24438fd1498Szrj mark_conflict (open_chains, head->id);
24538fd1498Szrj
24638fd1498Szrj /* Since we're tracking this as a chain now, remove it from the
24738fd1498Szrj list of conflicting live hard registers and track it in
24838fd1498Szrj live_in_chains instead. */
24938fd1498Szrj nregs = head->nregs;
25038fd1498Szrj while (nregs-- > 0)
25138fd1498Szrj {
25238fd1498Szrj SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
25338fd1498Szrj CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
25438fd1498Szrj }
25538fd1498Szrj
25638fd1498Szrj COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs);
25738fd1498Szrj bitmap_set_bit (&open_chains_set, head->id);
25838fd1498Szrj
25938fd1498Szrj open_chains = head;
26038fd1498Szrj
26138fd1498Szrj if (dump_file)
26238fd1498Szrj {
26338fd1498Szrj fprintf (dump_file, "Creating chain %s (%d)",
26438fd1498Szrj reg_names[head->regno], head->id);
26538fd1498Szrj if (insn != NULL_RTX)
26638fd1498Szrj fprintf (dump_file, " at insn %d", INSN_UID (insn));
26738fd1498Szrj fprintf (dump_file, "\n");
26838fd1498Szrj }
26938fd1498Szrj
27038fd1498Szrj if (insn == NULL_RTX)
27138fd1498Szrj {
27238fd1498Szrj head->first = head->last = NULL;
27338fd1498Szrj return head;
27438fd1498Szrj }
27538fd1498Szrj
27638fd1498Szrj this_du = XOBNEW (&rename_obstack, struct du_chain);
27738fd1498Szrj head->first = head->last = this_du;
27838fd1498Szrj
27938fd1498Szrj this_du->next_use = 0;
28038fd1498Szrj this_du->loc = loc;
28138fd1498Szrj this_du->insn = insn;
28238fd1498Szrj this_du->cl = cl;
28338fd1498Szrj record_operand_use (head, this_du);
28438fd1498Szrj return head;
28538fd1498Szrj }
28638fd1498Szrj
28738fd1498Szrj /* For a def-use chain HEAD, find which registers overlap its lifetime and
28838fd1498Szrj set the corresponding bits in *PSET. */
28938fd1498Szrj
29038fd1498Szrj static void
merge_overlapping_regs(HARD_REG_SET * pset,struct du_head * head)29138fd1498Szrj merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head)
29238fd1498Szrj {
29338fd1498Szrj bitmap_iterator bi;
29438fd1498Szrj unsigned i;
29538fd1498Szrj IOR_HARD_REG_SET (*pset, head->hard_conflicts);
29638fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi)
29738fd1498Szrj {
29838fd1498Szrj du_head_p other = regrename_chain_from_id (i);
29938fd1498Szrj unsigned j = other->nregs;
30038fd1498Szrj gcc_assert (other != head);
30138fd1498Szrj while (j-- > 0)
30238fd1498Szrj SET_HARD_REG_BIT (*pset, other->regno + j);
30338fd1498Szrj }
30438fd1498Szrj }
30538fd1498Szrj
30638fd1498Szrj /* Check if NEW_REG can be the candidate register to rename for
30738fd1498Szrj REG in THIS_HEAD chain. THIS_UNAVAILABLE is a set of unavailable hard
30838fd1498Szrj registers. */
30938fd1498Szrj
31038fd1498Szrj static bool
check_new_reg_p(int reg ATTRIBUTE_UNUSED,int new_reg,struct du_head * this_head,HARD_REG_SET this_unavailable)31138fd1498Szrj check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
31238fd1498Szrj struct du_head *this_head, HARD_REG_SET this_unavailable)
31338fd1498Szrj {
31438fd1498Szrj machine_mode mode = GET_MODE (*this_head->first->loc);
31538fd1498Szrj int nregs = hard_regno_nregs (new_reg, mode);
31638fd1498Szrj int i;
31738fd1498Szrj struct du_chain *tmp;
31838fd1498Szrj
31938fd1498Szrj for (i = nregs - 1; i >= 0; --i)
32038fd1498Szrj if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
32138fd1498Szrj || fixed_regs[new_reg + i]
32238fd1498Szrj || global_regs[new_reg + i]
32338fd1498Szrj /* Can't use regs which aren't saved by the prologue. */
32438fd1498Szrj || (! df_regs_ever_live_p (new_reg + i)
32538fd1498Szrj && ! call_used_regs[new_reg + i])
32638fd1498Szrj #ifdef LEAF_REGISTERS
32738fd1498Szrj /* We can't use a non-leaf register if we're in a
32838fd1498Szrj leaf function. */
32938fd1498Szrj || (crtl->is_leaf
33038fd1498Szrj && !LEAF_REGISTERS[new_reg + i])
33138fd1498Szrj #endif
33238fd1498Szrj || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i))
33338fd1498Szrj return false;
33438fd1498Szrj
33538fd1498Szrj /* See whether it accepts all modes that occur in
33638fd1498Szrj definition and uses. */
33738fd1498Szrj for (tmp = this_head->first; tmp; tmp = tmp->next_use)
33838fd1498Szrj if ((!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc))
33938fd1498Szrj && ! DEBUG_INSN_P (tmp->insn))
34038fd1498Szrj || (this_head->need_caller_save_reg
34138fd1498Szrj && ! (targetm.hard_regno_call_part_clobbered
34238fd1498Szrj (reg, GET_MODE (*tmp->loc)))
34338fd1498Szrj && (targetm.hard_regno_call_part_clobbered
34438fd1498Szrj (new_reg, GET_MODE (*tmp->loc)))))
34538fd1498Szrj return false;
34638fd1498Szrj
34738fd1498Szrj return true;
34838fd1498Szrj }
34938fd1498Szrj
35038fd1498Szrj /* For the chain THIS_HEAD, compute and return the best register to
35138fd1498Szrj rename to. SUPER_CLASS is the superunion of register classes in
35238fd1498Szrj the chain. UNAVAILABLE is a set of registers that cannot be used.
35338fd1498Szrj OLD_REG is the register currently used for the chain. BEST_RENAME
35438fd1498Szrj controls whether the register chosen must be better than the
35538fd1498Szrj current one or just respect the given constraint. */
35638fd1498Szrj
35738fd1498Szrj int
find_rename_reg(du_head_p this_head,enum reg_class super_class,HARD_REG_SET * unavailable,int old_reg,bool best_rename)35838fd1498Szrj find_rename_reg (du_head_p this_head, enum reg_class super_class,
35938fd1498Szrj HARD_REG_SET *unavailable, int old_reg, bool best_rename)
36038fd1498Szrj {
36138fd1498Szrj bool has_preferred_class;
36238fd1498Szrj enum reg_class preferred_class;
36338fd1498Szrj int pass;
36438fd1498Szrj int best_new_reg = old_reg;
36538fd1498Szrj
36638fd1498Szrj /* Further narrow the set of registers we can use for renaming.
36738fd1498Szrj If the chain needs a call-saved register, mark the call-used
36838fd1498Szrj registers as unavailable. */
36938fd1498Szrj if (this_head->need_caller_save_reg)
37038fd1498Szrj IOR_HARD_REG_SET (*unavailable, call_used_reg_set);
37138fd1498Szrj
37238fd1498Szrj /* Mark registers that overlap this chain's lifetime as unavailable. */
37338fd1498Szrj merge_overlapping_regs (unavailable, this_head);
37438fd1498Szrj
37538fd1498Szrj /* Compute preferred rename class of super union of all the classes
37638fd1498Szrj in the chain. */
37738fd1498Szrj preferred_class
37838fd1498Szrj = (enum reg_class) targetm.preferred_rename_class (super_class);
37938fd1498Szrj
38038fd1498Szrj /* Pick and check the register from the tied chain iff the tied chain
38138fd1498Szrj is not renamed. */
38238fd1498Szrj if (this_head->tied_chain && !this_head->tied_chain->renamed
38338fd1498Szrj && check_new_reg_p (old_reg, this_head->tied_chain->regno,
38438fd1498Szrj this_head, *unavailable))
38538fd1498Szrj return this_head->tied_chain->regno;
38638fd1498Szrj
38738fd1498Szrj /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
38838fd1498Szrj over registers that belong to PREFERRED_CLASS and try to find the
38938fd1498Szrj best register within the class. If that failed, we iterate in
39038fd1498Szrj the second pass over registers that don't belong to the class.
39138fd1498Szrj If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
39238fd1498Szrj ascending order without any preference. */
39338fd1498Szrj has_preferred_class = (preferred_class != NO_REGS);
39438fd1498Szrj for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
39538fd1498Szrj {
39638fd1498Szrj int new_reg;
39738fd1498Szrj for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
39838fd1498Szrj {
39938fd1498Szrj if (has_preferred_class
40038fd1498Szrj && (pass == 0)
40138fd1498Szrj != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
40238fd1498Szrj new_reg))
40338fd1498Szrj continue;
40438fd1498Szrj
40538fd1498Szrj if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
40638fd1498Szrj continue;
40738fd1498Szrj
40838fd1498Szrj if (!best_rename)
40938fd1498Szrj return new_reg;
41038fd1498Szrj
41138fd1498Szrj /* In the first pass, we force the renaming of registers that
41238fd1498Szrj don't belong to PREFERRED_CLASS to registers that do, even
41338fd1498Szrj though the latters were used not very long ago. */
41438fd1498Szrj if ((pass == 0
41538fd1498Szrj && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
41638fd1498Szrj best_new_reg))
41738fd1498Szrj || tick[best_new_reg] > tick[new_reg])
41838fd1498Szrj best_new_reg = new_reg;
41938fd1498Szrj }
42038fd1498Szrj if (pass == 0 && best_new_reg != old_reg)
42138fd1498Szrj break;
42238fd1498Szrj }
42338fd1498Szrj return best_new_reg;
42438fd1498Szrj }
42538fd1498Szrj
42638fd1498Szrj /* Iterate over elements in the chain HEAD in order to:
42738fd1498Szrj 1. Count number of uses, storing it in *PN_USES.
42838fd1498Szrj 2. Narrow the set of registers we can use for renaming, adding
42938fd1498Szrj unavailable registers to *PUNAVAILABLE, which must be
43038fd1498Szrj initialized by the caller.
43138fd1498Szrj 3. Compute the superunion of register classes in this chain
43238fd1498Szrj and return it. */
43338fd1498Szrj reg_class
regrename_find_superclass(du_head_p head,int * pn_uses,HARD_REG_SET * punavailable)43438fd1498Szrj regrename_find_superclass (du_head_p head, int *pn_uses,
43538fd1498Szrj HARD_REG_SET *punavailable)
43638fd1498Szrj {
43738fd1498Szrj int n_uses = 0;
43838fd1498Szrj reg_class super_class = NO_REGS;
43938fd1498Szrj for (du_chain *tmp = head->first; tmp; tmp = tmp->next_use)
44038fd1498Szrj {
44138fd1498Szrj if (DEBUG_INSN_P (tmp->insn))
44238fd1498Szrj continue;
44338fd1498Szrj n_uses++;
44438fd1498Szrj IOR_COMPL_HARD_REG_SET (*punavailable,
44538fd1498Szrj reg_class_contents[tmp->cl]);
44638fd1498Szrj super_class
44738fd1498Szrj = reg_class_superunion[(int) super_class][(int) tmp->cl];
44838fd1498Szrj }
44938fd1498Szrj *pn_uses = n_uses;
45038fd1498Szrj return super_class;
45138fd1498Szrj }
45238fd1498Szrj
45338fd1498Szrj /* Perform register renaming on the current function. */
45438fd1498Szrj static void
rename_chains(void)45538fd1498Szrj rename_chains (void)
45638fd1498Szrj {
45738fd1498Szrj HARD_REG_SET unavailable;
45838fd1498Szrj du_head_p this_head;
45938fd1498Szrj int i;
46038fd1498Szrj
46138fd1498Szrj memset (tick, 0, sizeof tick);
46238fd1498Szrj
46338fd1498Szrj CLEAR_HARD_REG_SET (unavailable);
46438fd1498Szrj /* Don't clobber traceback for noreturn functions. */
46538fd1498Szrj if (frame_pointer_needed)
46638fd1498Szrj {
46738fd1498Szrj add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
46838fd1498Szrj if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
46938fd1498Szrj add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
47038fd1498Szrj }
47138fd1498Szrj
47238fd1498Szrj FOR_EACH_VEC_ELT (id_to_chain, i, this_head)
47338fd1498Szrj {
47438fd1498Szrj int best_new_reg;
47538fd1498Szrj int n_uses;
47638fd1498Szrj HARD_REG_SET this_unavailable;
47738fd1498Szrj int reg = this_head->regno;
47838fd1498Szrj
47938fd1498Szrj if (this_head->cannot_rename)
48038fd1498Szrj continue;
48138fd1498Szrj
48238fd1498Szrj if (fixed_regs[reg] || global_regs[reg]
48338fd1498Szrj || (!HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed
48438fd1498Szrj && reg == HARD_FRAME_POINTER_REGNUM)
48538fd1498Szrj || (HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed
48638fd1498Szrj && reg == FRAME_POINTER_REGNUM))
48738fd1498Szrj continue;
48838fd1498Szrj
48938fd1498Szrj COPY_HARD_REG_SET (this_unavailable, unavailable);
49038fd1498Szrj
49138fd1498Szrj reg_class super_class = regrename_find_superclass (this_head, &n_uses,
49238fd1498Szrj &this_unavailable);
49338fd1498Szrj if (n_uses < 2)
49438fd1498Szrj continue;
49538fd1498Szrj
49638fd1498Szrj best_new_reg = find_rename_reg (this_head, super_class,
49738fd1498Szrj &this_unavailable, reg, true);
49838fd1498Szrj
49938fd1498Szrj if (dump_file)
50038fd1498Szrj {
50138fd1498Szrj fprintf (dump_file, "Register %s in insn %d",
50238fd1498Szrj reg_names[reg], INSN_UID (this_head->first->insn));
50338fd1498Szrj if (this_head->need_caller_save_reg)
50438fd1498Szrj fprintf (dump_file, " crosses a call");
50538fd1498Szrj }
50638fd1498Szrj
50738fd1498Szrj if (best_new_reg == reg)
50838fd1498Szrj {
50938fd1498Szrj tick[reg] = ++this_tick;
51038fd1498Szrj if (dump_file)
51138fd1498Szrj fprintf (dump_file, "; no available better choice\n");
51238fd1498Szrj continue;
51338fd1498Szrj }
51438fd1498Szrj
51538fd1498Szrj if (regrename_do_replace (this_head, best_new_reg))
51638fd1498Szrj {
51738fd1498Szrj if (dump_file)
51838fd1498Szrj fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
51938fd1498Szrj tick[best_new_reg] = ++this_tick;
52038fd1498Szrj df_set_regs_ever_live (best_new_reg, true);
52138fd1498Szrj }
52238fd1498Szrj else
52338fd1498Szrj {
52438fd1498Szrj if (dump_file)
52538fd1498Szrj fprintf (dump_file, ", renaming as %s failed\n",
52638fd1498Szrj reg_names[best_new_reg]);
52738fd1498Szrj tick[reg] = ++this_tick;
52838fd1498Szrj }
52938fd1498Szrj }
53038fd1498Szrj }
53138fd1498Szrj
53238fd1498Szrj /* A structure to record information for each hard register at the start of
53338fd1498Szrj a basic block. */
53438fd1498Szrj struct incoming_reg_info {
53538fd1498Szrj /* Holds the number of registers used in the chain that gave us information
53638fd1498Szrj about this register. Zero means no information known yet, while a
53738fd1498Szrj negative value is used for something that is part of, but not the first
53838fd1498Szrj register in a multi-register value. */
53938fd1498Szrj int nregs;
54038fd1498Szrj /* Set to true if we have accesses that conflict in the number of registers
54138fd1498Szrj used. */
54238fd1498Szrj bool unusable;
54338fd1498Szrj };
54438fd1498Szrj
54538fd1498Szrj /* A structure recording information about each basic block. It is saved
54638fd1498Szrj and restored around basic block boundaries.
54738fd1498Szrj A pointer to such a structure is stored in each basic block's aux field
54838fd1498Szrj during regrename_analyze, except for blocks we know can't be optimized
54938fd1498Szrj (such as entry and exit blocks). */
55038fd1498Szrj struct bb_rename_info
55138fd1498Szrj {
55238fd1498Szrj /* The basic block corresponding to this structure. */
55338fd1498Szrj basic_block bb;
55438fd1498Szrj /* Copies of the global information. */
55538fd1498Szrj bitmap_head open_chains_set;
55638fd1498Szrj bitmap_head incoming_open_chains_set;
55738fd1498Szrj struct incoming_reg_info incoming[FIRST_PSEUDO_REGISTER];
55838fd1498Szrj };
55938fd1498Szrj
56038fd1498Szrj /* Initialize a rename_info structure P for basic block BB, which starts a new
56138fd1498Szrj scan. */
56238fd1498Szrj static void
init_rename_info(struct bb_rename_info * p,basic_block bb)56338fd1498Szrj init_rename_info (struct bb_rename_info *p, basic_block bb)
56438fd1498Szrj {
56538fd1498Szrj int i;
56638fd1498Szrj df_ref def;
56738fd1498Szrj HARD_REG_SET start_chains_set;
56838fd1498Szrj
56938fd1498Szrj p->bb = bb;
57038fd1498Szrj bitmap_initialize (&p->open_chains_set, &bitmap_default_obstack);
57138fd1498Szrj bitmap_initialize (&p->incoming_open_chains_set, &bitmap_default_obstack);
57238fd1498Szrj
57338fd1498Szrj open_chains = NULL;
57438fd1498Szrj bitmap_clear (&open_chains_set);
57538fd1498Szrj
57638fd1498Szrj CLEAR_HARD_REG_SET (live_in_chains);
57738fd1498Szrj REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_in (bb));
57838fd1498Szrj FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
57938fd1498Szrj if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
58038fd1498Szrj SET_HARD_REG_BIT (live_hard_regs, DF_REF_REGNO (def));
58138fd1498Szrj
58238fd1498Szrj /* Open chains based on information from (at least one) predecessor
58338fd1498Szrj block. This gives us a chance later on to combine chains across
58438fd1498Szrj basic block boundaries. Inconsistencies (in access sizes) will
58538fd1498Szrj be caught normally and dealt with conservatively by disabling the
58638fd1498Szrj chain for renaming, and there is no risk of losing optimization
58738fd1498Szrj opportunities by opening chains either: if we did not open the
58838fd1498Szrj chains, we'd have to track the live register as a hard reg, and
58938fd1498Szrj we'd be unable to rename it in any case. */
59038fd1498Szrj CLEAR_HARD_REG_SET (start_chains_set);
59138fd1498Szrj for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
59238fd1498Szrj {
59338fd1498Szrj struct incoming_reg_info *iri = p->incoming + i;
59438fd1498Szrj if (iri->nregs > 0 && !iri->unusable
59538fd1498Szrj && range_in_hard_reg_set_p (live_hard_regs, i, iri->nregs))
59638fd1498Szrj {
59738fd1498Szrj SET_HARD_REG_BIT (start_chains_set, i);
59838fd1498Szrj remove_range_from_hard_reg_set (&live_hard_regs, i, iri->nregs);
59938fd1498Szrj }
60038fd1498Szrj }
60138fd1498Szrj for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
60238fd1498Szrj {
60338fd1498Szrj struct incoming_reg_info *iri = p->incoming + i;
60438fd1498Szrj if (TEST_HARD_REG_BIT (start_chains_set, i))
60538fd1498Szrj {
60638fd1498Szrj du_head_p chain;
60738fd1498Szrj if (dump_file)
60838fd1498Szrj fprintf (dump_file, "opening incoming chain\n");
60938fd1498Szrj chain = create_new_chain (i, iri->nregs, NULL, NULL, NO_REGS);
61038fd1498Szrj bitmap_set_bit (&p->incoming_open_chains_set, chain->id);
61138fd1498Szrj }
61238fd1498Szrj }
61338fd1498Szrj }
61438fd1498Szrj
61538fd1498Szrj /* Record in RI that the block corresponding to it has an incoming
61638fd1498Szrj live value, described by CHAIN. */
61738fd1498Szrj static void
set_incoming_from_chain(struct bb_rename_info * ri,du_head_p chain)61838fd1498Szrj set_incoming_from_chain (struct bb_rename_info *ri, du_head_p chain)
61938fd1498Szrj {
62038fd1498Szrj int i;
62138fd1498Szrj int incoming_nregs = ri->incoming[chain->regno].nregs;
62238fd1498Szrj int nregs;
62338fd1498Szrj
62438fd1498Szrj /* If we've recorded the same information before, everything is fine. */
62538fd1498Szrj if (incoming_nregs == chain->nregs)
62638fd1498Szrj {
62738fd1498Szrj if (dump_file)
62838fd1498Szrj fprintf (dump_file, "reg %d/%d already recorded\n",
62938fd1498Szrj chain->regno, chain->nregs);
63038fd1498Szrj return;
63138fd1498Szrj }
63238fd1498Szrj
63338fd1498Szrj /* If we have no information for any of the involved registers, update
63438fd1498Szrj the incoming array. */
63538fd1498Szrj nregs = chain->nregs;
63638fd1498Szrj while (nregs-- > 0)
63738fd1498Szrj if (ri->incoming[chain->regno + nregs].nregs != 0
63838fd1498Szrj || ri->incoming[chain->regno + nregs].unusable)
63938fd1498Szrj break;
64038fd1498Szrj if (nregs < 0)
64138fd1498Szrj {
64238fd1498Szrj nregs = chain->nregs;
64338fd1498Szrj ri->incoming[chain->regno].nregs = nregs;
64438fd1498Szrj while (nregs-- > 1)
64538fd1498Szrj ri->incoming[chain->regno + nregs].nregs = -nregs;
64638fd1498Szrj if (dump_file)
64738fd1498Szrj fprintf (dump_file, "recorded reg %d/%d\n",
64838fd1498Szrj chain->regno, chain->nregs);
64938fd1498Szrj return;
65038fd1498Szrj }
65138fd1498Szrj
65238fd1498Szrj /* There must be some kind of conflict. Prevent both the old and
65338fd1498Szrj new ranges from being used. */
65438fd1498Szrj if (incoming_nregs < 0)
65538fd1498Szrj ri->incoming[chain->regno + incoming_nregs].unusable = true;
65638fd1498Szrj for (i = 0; i < chain->nregs; i++)
65738fd1498Szrj ri->incoming[chain->regno + i].unusable = true;
65838fd1498Szrj }
65938fd1498Szrj
66038fd1498Szrj /* Merge the two chains C1 and C2 so that all conflict information is
66138fd1498Szrj recorded and C1, and the id of C2 is changed to that of C1. */
66238fd1498Szrj static void
merge_chains(du_head_p c1,du_head_p c2)66338fd1498Szrj merge_chains (du_head_p c1, du_head_p c2)
66438fd1498Szrj {
66538fd1498Szrj if (c1 == c2)
66638fd1498Szrj return;
66738fd1498Szrj
66838fd1498Szrj if (c2->first != NULL)
66938fd1498Szrj {
67038fd1498Szrj if (c1->first == NULL)
67138fd1498Szrj c1->first = c2->first;
67238fd1498Szrj else
67338fd1498Szrj c1->last->next_use = c2->first;
67438fd1498Szrj c1->last = c2->last;
67538fd1498Szrj }
67638fd1498Szrj
67738fd1498Szrj c2->first = c2->last = NULL;
67838fd1498Szrj c2->id = c1->id;
67938fd1498Szrj
68038fd1498Szrj IOR_HARD_REG_SET (c1->hard_conflicts, c2->hard_conflicts);
68138fd1498Szrj bitmap_ior_into (&c1->conflicts, &c2->conflicts);
68238fd1498Szrj
68338fd1498Szrj c1->need_caller_save_reg |= c2->need_caller_save_reg;
68438fd1498Szrj c1->cannot_rename |= c2->cannot_rename;
68538fd1498Szrj }
68638fd1498Szrj
68738fd1498Szrj /* Analyze the current function and build chains for renaming. */
68838fd1498Szrj
68938fd1498Szrj void
regrename_analyze(bitmap bb_mask)69038fd1498Szrj regrename_analyze (bitmap bb_mask)
69138fd1498Szrj {
69238fd1498Szrj struct bb_rename_info *rename_info;
69338fd1498Szrj int i;
69438fd1498Szrj basic_block bb;
69538fd1498Szrj int n_bbs;
69638fd1498Szrj int *inverse_postorder;
69738fd1498Szrj
69838fd1498Szrj inverse_postorder = XNEWVEC (int, last_basic_block_for_fn (cfun));
69938fd1498Szrj n_bbs = pre_and_rev_post_order_compute (NULL, inverse_postorder, false);
70038fd1498Szrj
70138fd1498Szrj /* Gather some information about the blocks in this function. */
70238fd1498Szrj rename_info = XCNEWVEC (struct bb_rename_info, n_basic_blocks_for_fn (cfun));
70338fd1498Szrj i = 0;
70438fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
70538fd1498Szrj {
70638fd1498Szrj struct bb_rename_info *ri = rename_info + i;
70738fd1498Szrj ri->bb = bb;
70838fd1498Szrj if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index))
70938fd1498Szrj bb->aux = NULL;
71038fd1498Szrj else
71138fd1498Szrj bb->aux = ri;
71238fd1498Szrj i++;
71338fd1498Szrj }
71438fd1498Szrj
71538fd1498Szrj current_id = 0;
71638fd1498Szrj id_to_chain.create (0);
71738fd1498Szrj bitmap_initialize (&open_chains_set, &bitmap_default_obstack);
71838fd1498Szrj
71938fd1498Szrj /* The order in which we visit blocks ensures that whenever
72038fd1498Szrj possible, we only process a block after at least one of its
72138fd1498Szrj predecessors, which provides a "seeding" effect to make the logic
72238fd1498Szrj in set_incoming_from_chain and init_rename_info useful. */
72338fd1498Szrj
72438fd1498Szrj for (i = 0; i < n_bbs; i++)
72538fd1498Szrj {
72638fd1498Szrj basic_block bb1 = BASIC_BLOCK_FOR_FN (cfun, inverse_postorder[i]);
72738fd1498Szrj struct bb_rename_info *this_info;
72838fd1498Szrj bool success;
72938fd1498Szrj edge e;
73038fd1498Szrj edge_iterator ei;
73138fd1498Szrj int old_length = id_to_chain.length ();
73238fd1498Szrj
73338fd1498Szrj this_info = (struct bb_rename_info *) bb1->aux;
73438fd1498Szrj if (this_info == NULL)
73538fd1498Szrj continue;
73638fd1498Szrj
73738fd1498Szrj if (dump_file)
73838fd1498Szrj fprintf (dump_file, "\nprocessing block %d:\n", bb1->index);
73938fd1498Szrj
74038fd1498Szrj init_rename_info (this_info, bb1);
74138fd1498Szrj
74238fd1498Szrj success = build_def_use (bb1);
74338fd1498Szrj if (!success)
74438fd1498Szrj {
74538fd1498Szrj if (dump_file)
74638fd1498Szrj fprintf (dump_file, "failed\n");
74738fd1498Szrj bb1->aux = NULL;
74838fd1498Szrj id_to_chain.truncate (old_length);
74938fd1498Szrj current_id = old_length;
75038fd1498Szrj bitmap_clear (&this_info->incoming_open_chains_set);
75138fd1498Szrj open_chains = NULL;
75238fd1498Szrj if (insn_rr.exists ())
75338fd1498Szrj {
75438fd1498Szrj rtx_insn *insn;
75538fd1498Szrj FOR_BB_INSNS (bb1, insn)
75638fd1498Szrj {
75738fd1498Szrj insn_rr_info *p = &insn_rr[INSN_UID (insn)];
75838fd1498Szrj p->op_info = NULL;
75938fd1498Szrj }
76038fd1498Szrj }
76138fd1498Szrj continue;
76238fd1498Szrj }
76338fd1498Szrj
76438fd1498Szrj if (dump_file)
76538fd1498Szrj dump_def_use_chain (old_length);
76638fd1498Szrj bitmap_copy (&this_info->open_chains_set, &open_chains_set);
76738fd1498Szrj
76838fd1498Szrj /* Add successor blocks to the worklist if necessary, and record
76938fd1498Szrj data about our own open chains at the end of this block, which
77038fd1498Szrj will be used to pre-open chains when processing the successors. */
77138fd1498Szrj FOR_EACH_EDGE (e, ei, bb1->succs)
77238fd1498Szrj {
77338fd1498Szrj struct bb_rename_info *dest_ri;
77438fd1498Szrj struct du_head *chain;
77538fd1498Szrj
77638fd1498Szrj if (dump_file)
77738fd1498Szrj fprintf (dump_file, "successor block %d\n", e->dest->index);
77838fd1498Szrj
77938fd1498Szrj if (e->flags & (EDGE_EH | EDGE_ABNORMAL))
78038fd1498Szrj continue;
78138fd1498Szrj dest_ri = (struct bb_rename_info *)e->dest->aux;
78238fd1498Szrj if (dest_ri == NULL)
78338fd1498Szrj continue;
78438fd1498Szrj for (chain = open_chains; chain; chain = chain->next_chain)
78538fd1498Szrj set_incoming_from_chain (dest_ri, chain);
78638fd1498Szrj }
78738fd1498Szrj }
78838fd1498Szrj
78938fd1498Szrj free (inverse_postorder);
79038fd1498Szrj
79138fd1498Szrj /* Now, combine the chains data we have gathered across basic block
79238fd1498Szrj boundaries.
79338fd1498Szrj
79438fd1498Szrj For every basic block, there may be chains open at the start, or at the
79538fd1498Szrj end. Rather than exclude them from renaming, we look for open chains
79638fd1498Szrj with matching registers at the other side of the CFG edge.
79738fd1498Szrj
79838fd1498Szrj For a given chain using register R, open at the start of block B, we
79938fd1498Szrj must find an open chain using R on the other side of every edge leading
80038fd1498Szrj to B, if the register is live across this edge. In the code below,
80138fd1498Szrj N_PREDS_USED counts the number of edges where the register is live, and
80238fd1498Szrj N_PREDS_JOINED counts those where we found an appropriate chain for
80338fd1498Szrj joining.
80438fd1498Szrj
80538fd1498Szrj We perform the analysis for both incoming and outgoing edges, but we
80638fd1498Szrj only need to merge once (in the second part, after verifying outgoing
80738fd1498Szrj edges). */
80838fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
80938fd1498Szrj {
81038fd1498Szrj struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux;
81138fd1498Szrj unsigned j;
81238fd1498Szrj bitmap_iterator bi;
81338fd1498Szrj
81438fd1498Szrj if (bb_ri == NULL)
81538fd1498Szrj continue;
81638fd1498Szrj
81738fd1498Szrj if (dump_file)
81838fd1498Szrj fprintf (dump_file, "processing bb %d in edges\n", bb->index);
81938fd1498Szrj
82038fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (&bb_ri->incoming_open_chains_set, 0, j, bi)
82138fd1498Szrj {
82238fd1498Szrj edge e;
82338fd1498Szrj edge_iterator ei;
82438fd1498Szrj struct du_head *chain = regrename_chain_from_id (j);
82538fd1498Szrj int n_preds_used = 0, n_preds_joined = 0;
82638fd1498Szrj
82738fd1498Szrj FOR_EACH_EDGE (e, ei, bb->preds)
82838fd1498Szrj {
82938fd1498Szrj struct bb_rename_info *src_ri;
83038fd1498Szrj unsigned k;
83138fd1498Szrj bitmap_iterator bi2;
83238fd1498Szrj HARD_REG_SET live;
83338fd1498Szrj bool success = false;
83438fd1498Szrj
83538fd1498Szrj REG_SET_TO_HARD_REG_SET (live, df_get_live_out (e->src));
83638fd1498Szrj if (!range_overlaps_hard_reg_set_p (live, chain->regno,
83738fd1498Szrj chain->nregs))
83838fd1498Szrj continue;
83938fd1498Szrj n_preds_used++;
84038fd1498Szrj
84138fd1498Szrj if (e->flags & (EDGE_EH | EDGE_ABNORMAL))
84238fd1498Szrj continue;
84338fd1498Szrj
84438fd1498Szrj src_ri = (struct bb_rename_info *)e->src->aux;
84538fd1498Szrj if (src_ri == NULL)
84638fd1498Szrj continue;
84738fd1498Szrj
84838fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set,
84938fd1498Szrj 0, k, bi2)
85038fd1498Szrj {
85138fd1498Szrj struct du_head *outgoing_chain = regrename_chain_from_id (k);
85238fd1498Szrj
85338fd1498Szrj if (outgoing_chain->regno == chain->regno
85438fd1498Szrj && outgoing_chain->nregs == chain->nregs)
85538fd1498Szrj {
85638fd1498Szrj n_preds_joined++;
85738fd1498Szrj success = true;
85838fd1498Szrj break;
85938fd1498Szrj }
86038fd1498Szrj }
86138fd1498Szrj if (!success && dump_file)
86238fd1498Szrj fprintf (dump_file, "failure to match with pred block %d\n",
86338fd1498Szrj e->src->index);
86438fd1498Szrj }
86538fd1498Szrj if (n_preds_joined < n_preds_used)
86638fd1498Szrj {
86738fd1498Szrj if (dump_file)
86838fd1498Szrj fprintf (dump_file, "cannot rename chain %d\n", j);
86938fd1498Szrj chain->cannot_rename = 1;
87038fd1498Szrj }
87138fd1498Szrj }
87238fd1498Szrj }
87338fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
87438fd1498Szrj {
87538fd1498Szrj struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux;
87638fd1498Szrj unsigned j;
87738fd1498Szrj bitmap_iterator bi;
87838fd1498Szrj
87938fd1498Szrj if (bb_ri == NULL)
88038fd1498Szrj continue;
88138fd1498Szrj
88238fd1498Szrj if (dump_file)
88338fd1498Szrj fprintf (dump_file, "processing bb %d out edges\n", bb->index);
88438fd1498Szrj
88538fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (&bb_ri->open_chains_set, 0, j, bi)
88638fd1498Szrj {
88738fd1498Szrj edge e;
88838fd1498Szrj edge_iterator ei;
88938fd1498Szrj struct du_head *chain = regrename_chain_from_id (j);
89038fd1498Szrj int n_succs_used = 0, n_succs_joined = 0;
89138fd1498Szrj
89238fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs)
89338fd1498Szrj {
89438fd1498Szrj bool printed = false;
89538fd1498Szrj struct bb_rename_info *dest_ri;
89638fd1498Szrj unsigned k;
89738fd1498Szrj bitmap_iterator bi2;
89838fd1498Szrj HARD_REG_SET live;
89938fd1498Szrj
90038fd1498Szrj REG_SET_TO_HARD_REG_SET (live, df_get_live_in (e->dest));
90138fd1498Szrj if (!range_overlaps_hard_reg_set_p (live, chain->regno,
90238fd1498Szrj chain->nregs))
90338fd1498Szrj continue;
90438fd1498Szrj
90538fd1498Szrj n_succs_used++;
90638fd1498Szrj
90738fd1498Szrj dest_ri = (struct bb_rename_info *)e->dest->aux;
90838fd1498Szrj if (dest_ri == NULL)
90938fd1498Szrj continue;
91038fd1498Szrj
91138fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set,
91238fd1498Szrj 0, k, bi2)
91338fd1498Szrj {
91438fd1498Szrj struct du_head *incoming_chain = regrename_chain_from_id (k);
91538fd1498Szrj
91638fd1498Szrj if (incoming_chain->regno == chain->regno
91738fd1498Szrj && incoming_chain->nregs == chain->nregs)
91838fd1498Szrj {
91938fd1498Szrj if (dump_file)
92038fd1498Szrj {
92138fd1498Szrj if (!printed)
92238fd1498Szrj fprintf (dump_file,
92338fd1498Szrj "merging blocks for edge %d -> %d\n",
92438fd1498Szrj e->src->index, e->dest->index);
92538fd1498Szrj printed = true;
92638fd1498Szrj fprintf (dump_file,
92738fd1498Szrj " merging chains %d (->%d) and %d (->%d) [%s]\n",
92838fd1498Szrj k, incoming_chain->id, j, chain->id,
92938fd1498Szrj reg_names[incoming_chain->regno]);
93038fd1498Szrj }
93138fd1498Szrj
93238fd1498Szrj merge_chains (chain, incoming_chain);
93338fd1498Szrj n_succs_joined++;
93438fd1498Szrj break;
93538fd1498Szrj }
93638fd1498Szrj }
93738fd1498Szrj }
93838fd1498Szrj if (n_succs_joined < n_succs_used)
93938fd1498Szrj {
94038fd1498Szrj if (dump_file)
94138fd1498Szrj fprintf (dump_file, "cannot rename chain %d\n",
94238fd1498Szrj j);
94338fd1498Szrj chain->cannot_rename = 1;
94438fd1498Szrj }
94538fd1498Szrj }
94638fd1498Szrj }
94738fd1498Szrj
94838fd1498Szrj free (rename_info);
94938fd1498Szrj
95038fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
95138fd1498Szrj bb->aux = NULL;
95238fd1498Szrj }
95338fd1498Szrj
95438fd1498Szrj /* Attempt to replace all uses of the register in the chain beginning with
95538fd1498Szrj HEAD with REG. Returns true on success and false if the replacement is
95638fd1498Szrj rejected because the insns would not validate. The latter can happen
95738fd1498Szrj e.g. if a match_parallel predicate enforces restrictions on register
95838fd1498Szrj numbering in its subpatterns. */
95938fd1498Szrj
96038fd1498Szrj bool
regrename_do_replace(struct du_head * head,int reg)96138fd1498Szrj regrename_do_replace (struct du_head *head, int reg)
96238fd1498Szrj {
96338fd1498Szrj struct du_chain *chain;
96438fd1498Szrj unsigned int base_regno = head->regno;
96538fd1498Szrj machine_mode mode;
96638fd1498Szrj rtx last_reg = NULL_RTX, last_repl = NULL_RTX;
96738fd1498Szrj
96838fd1498Szrj for (chain = head->first; chain; chain = chain->next_use)
96938fd1498Szrj {
97038fd1498Szrj unsigned int regno = ORIGINAL_REGNO (*chain->loc);
97138fd1498Szrj struct reg_attrs *attr = REG_ATTRS (*chain->loc);
97238fd1498Szrj int reg_ptr = REG_POINTER (*chain->loc);
97338fd1498Szrj
97438fd1498Szrj if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno)
97538fd1498Szrj validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC (chain->insn)),
97638fd1498Szrj gen_rtx_UNKNOWN_VAR_LOC (), true);
97738fd1498Szrj else
97838fd1498Szrj {
97938fd1498Szrj if (*chain->loc != last_reg)
98038fd1498Szrj {
98138fd1498Szrj last_repl = gen_raw_REG (GET_MODE (*chain->loc), reg);
98238fd1498Szrj if (regno >= FIRST_PSEUDO_REGISTER)
98338fd1498Szrj ORIGINAL_REGNO (last_repl) = regno;
98438fd1498Szrj REG_ATTRS (last_repl) = attr;
98538fd1498Szrj REG_POINTER (last_repl) = reg_ptr;
98638fd1498Szrj last_reg = *chain->loc;
98738fd1498Szrj }
98838fd1498Szrj validate_change (chain->insn, chain->loc, last_repl, true);
98938fd1498Szrj }
99038fd1498Szrj }
99138fd1498Szrj
99238fd1498Szrj if (!apply_change_group ())
99338fd1498Szrj return false;
99438fd1498Szrj
99538fd1498Szrj mode = GET_MODE (*head->first->loc);
99638fd1498Szrj head->renamed = 1;
99738fd1498Szrj head->regno = reg;
99838fd1498Szrj head->nregs = hard_regno_nregs (reg, mode);
99938fd1498Szrj return true;
100038fd1498Szrj }
100138fd1498Szrj
100238fd1498Szrj
100338fd1498Szrj /* True if we found a register with a size mismatch, which means that we
100438fd1498Szrj can't track its lifetime accurately. If so, we abort the current block
100538fd1498Szrj without renaming. */
100638fd1498Szrj static bool fail_current_block;
100738fd1498Szrj
100838fd1498Szrj /* Return true if OP is a reg for which all bits are set in PSET, false
100938fd1498Szrj if all bits are clear.
101038fd1498Szrj In other cases, set fail_current_block and return false. */
101138fd1498Szrj
101238fd1498Szrj static bool
verify_reg_in_set(rtx op,HARD_REG_SET * pset)101338fd1498Szrj verify_reg_in_set (rtx op, HARD_REG_SET *pset)
101438fd1498Szrj {
101538fd1498Szrj unsigned regno, nregs;
101638fd1498Szrj bool all_live, all_dead;
101738fd1498Szrj if (!REG_P (op))
101838fd1498Szrj return false;
101938fd1498Szrj
102038fd1498Szrj regno = REGNO (op);
102138fd1498Szrj nregs = REG_NREGS (op);
102238fd1498Szrj all_live = all_dead = true;
102338fd1498Szrj while (nregs-- > 0)
102438fd1498Szrj if (TEST_HARD_REG_BIT (*pset, regno + nregs))
102538fd1498Szrj all_dead = false;
102638fd1498Szrj else
102738fd1498Szrj all_live = false;
102838fd1498Szrj if (!all_dead && !all_live)
102938fd1498Szrj {
103038fd1498Szrj fail_current_block = true;
103138fd1498Szrj return false;
103238fd1498Szrj }
103338fd1498Szrj return all_live;
103438fd1498Szrj }
103538fd1498Szrj
103638fd1498Szrj /* Return true if OP is a reg that is being tracked already in some form.
103738fd1498Szrj May set fail_current_block if it sees an unhandled case of overlap. */
103838fd1498Szrj
103938fd1498Szrj static bool
verify_reg_tracked(rtx op)104038fd1498Szrj verify_reg_tracked (rtx op)
104138fd1498Szrj {
104238fd1498Szrj return (verify_reg_in_set (op, &live_hard_regs)
104338fd1498Szrj || verify_reg_in_set (op, &live_in_chains));
104438fd1498Szrj }
104538fd1498Szrj
104638fd1498Szrj /* Called through note_stores. DATA points to a rtx_code, either SET or
104738fd1498Szrj CLOBBER, which tells us which kind of rtx to look at. If we have a
104838fd1498Szrj match, record the set register in live_hard_regs and in the hard_conflicts
104938fd1498Szrj bitmap of open chains. */
105038fd1498Szrj
105138fd1498Szrj static void
note_sets_clobbers(rtx x,const_rtx set,void * data)105238fd1498Szrj note_sets_clobbers (rtx x, const_rtx set, void *data)
105338fd1498Szrj {
105438fd1498Szrj enum rtx_code code = *(enum rtx_code *)data;
105538fd1498Szrj struct du_head *chain;
105638fd1498Szrj
105738fd1498Szrj if (GET_CODE (x) == SUBREG)
105838fd1498Szrj x = SUBREG_REG (x);
105938fd1498Szrj if (!REG_P (x) || GET_CODE (set) != code)
106038fd1498Szrj return;
106138fd1498Szrj /* There must not be pseudos at this point. */
106238fd1498Szrj gcc_assert (HARD_REGISTER_P (x));
106338fd1498Szrj add_to_hard_reg_set (&live_hard_regs, GET_MODE (x), REGNO (x));
106438fd1498Szrj for (chain = open_chains; chain; chain = chain->next_chain)
106538fd1498Szrj add_to_hard_reg_set (&chain->hard_conflicts, GET_MODE (x), REGNO (x));
106638fd1498Szrj }
106738fd1498Szrj
106838fd1498Szrj static void
scan_rtx_reg(rtx_insn * insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum op_type type)106938fd1498Szrj scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
107038fd1498Szrj enum op_type type)
107138fd1498Szrj {
107238fd1498Szrj struct du_head **p;
107338fd1498Szrj rtx x = *loc;
107438fd1498Szrj unsigned this_regno = REGNO (x);
107538fd1498Szrj int this_nregs = REG_NREGS (x);
107638fd1498Szrj
107738fd1498Szrj if (action == mark_write)
107838fd1498Szrj {
107938fd1498Szrj if (type == OP_OUT)
108038fd1498Szrj {
108138fd1498Szrj du_head_p c;
108238fd1498Szrj rtx pat = PATTERN (insn);
108338fd1498Szrj
108438fd1498Szrj c = create_new_chain (this_regno, this_nregs, loc, insn, cl);
108538fd1498Szrj
108638fd1498Szrj /* We try to tie chains in a move instruction for
108738fd1498Szrj a single output. */
108838fd1498Szrj if (recog_data.n_operands == 2
108938fd1498Szrj && GET_CODE (pat) == SET
109038fd1498Szrj && GET_CODE (SET_DEST (pat)) == REG
109138fd1498Szrj && GET_CODE (SET_SRC (pat)) == REG
109238fd1498Szrj && terminated_this_insn
109338fd1498Szrj && terminated_this_insn->nregs
109438fd1498Szrj == REG_NREGS (recog_data.operand[1]))
109538fd1498Szrj {
109638fd1498Szrj gcc_assert (terminated_this_insn->regno
109738fd1498Szrj == REGNO (recog_data.operand[1]));
109838fd1498Szrj
109938fd1498Szrj c->tied_chain = terminated_this_insn;
110038fd1498Szrj terminated_this_insn->tied_chain = c;
110138fd1498Szrj
110238fd1498Szrj if (dump_file)
110338fd1498Szrj fprintf (dump_file, "Tying chain %s (%d) with %s (%d)\n",
110438fd1498Szrj reg_names[c->regno], c->id,
110538fd1498Szrj reg_names[terminated_this_insn->regno],
110638fd1498Szrj terminated_this_insn->id);
110738fd1498Szrj }
110838fd1498Szrj }
110938fd1498Szrj
111038fd1498Szrj return;
111138fd1498Szrj }
111238fd1498Szrj
111338fd1498Szrj if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
111438fd1498Szrj return;
111538fd1498Szrj
111638fd1498Szrj for (p = &open_chains; *p;)
111738fd1498Szrj {
111838fd1498Szrj struct du_head *head = *p;
111938fd1498Szrj struct du_head *next = head->next_chain;
112038fd1498Szrj int exact_match = (head->regno == this_regno
112138fd1498Szrj && head->nregs == this_nregs);
112238fd1498Szrj int superset = (this_regno <= head->regno
112338fd1498Szrj && this_regno + this_nregs >= head->regno + head->nregs);
112438fd1498Szrj int subset = (this_regno >= head->regno
112538fd1498Szrj && this_regno + this_nregs <= head->regno + head->nregs);
112638fd1498Szrj
112738fd1498Szrj if (!bitmap_bit_p (&open_chains_set, head->id)
112838fd1498Szrj || head->regno + head->nregs <= this_regno
112938fd1498Szrj || this_regno + this_nregs <= head->regno)
113038fd1498Szrj {
113138fd1498Szrj p = &head->next_chain;
113238fd1498Szrj continue;
113338fd1498Szrj }
113438fd1498Szrj
113538fd1498Szrj if (action == mark_read || action == mark_access)
113638fd1498Szrj {
113738fd1498Szrj /* ??? Class NO_REGS can happen if the md file makes use of
113838fd1498Szrj EXTRA_CONSTRAINTS to match registers. Which is arguably
113938fd1498Szrj wrong, but there we are. */
114038fd1498Szrj
114138fd1498Szrj if (cl == NO_REGS || (!exact_match && !DEBUG_INSN_P (insn)))
114238fd1498Szrj {
114338fd1498Szrj if (dump_file)
114438fd1498Szrj fprintf (dump_file,
114538fd1498Szrj "Cannot rename chain %s (%d) at insn %d (%s)\n",
114638fd1498Szrj reg_names[head->regno], head->id, INSN_UID (insn),
114738fd1498Szrj scan_actions_name[(int) action]);
114838fd1498Szrj head->cannot_rename = 1;
114938fd1498Szrj if (superset)
115038fd1498Szrj {
115138fd1498Szrj unsigned nregs = this_nregs;
115238fd1498Szrj head->regno = this_regno;
115338fd1498Szrj head->nregs = this_nregs;
115438fd1498Szrj while (nregs-- > 0)
115538fd1498Szrj SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
115638fd1498Szrj if (dump_file)
115738fd1498Szrj fprintf (dump_file,
115838fd1498Szrj "Widening register in chain %s (%d) at insn %d\n",
115938fd1498Szrj reg_names[head->regno], head->id, INSN_UID (insn));
116038fd1498Szrj }
116138fd1498Szrj else if (!subset)
116238fd1498Szrj {
116338fd1498Szrj fail_current_block = true;
116438fd1498Szrj if (dump_file)
116538fd1498Szrj fprintf (dump_file,
116638fd1498Szrj "Failing basic block due to unhandled overlap\n");
116738fd1498Szrj }
116838fd1498Szrj }
116938fd1498Szrj else
117038fd1498Szrj {
117138fd1498Szrj struct du_chain *this_du;
117238fd1498Szrj this_du = XOBNEW (&rename_obstack, struct du_chain);
117338fd1498Szrj this_du->next_use = 0;
117438fd1498Szrj this_du->loc = loc;
117538fd1498Szrj this_du->insn = insn;
117638fd1498Szrj this_du->cl = cl;
117738fd1498Szrj if (head->first == NULL)
117838fd1498Szrj head->first = this_du;
117938fd1498Szrj else
118038fd1498Szrj head->last->next_use = this_du;
118138fd1498Szrj record_operand_use (head, this_du);
118238fd1498Szrj head->last = this_du;
118338fd1498Szrj }
118438fd1498Szrj /* Avoid adding the same location in a DEBUG_INSN multiple times,
118538fd1498Szrj which could happen with non-exact overlap. */
118638fd1498Szrj if (DEBUG_INSN_P (insn))
118738fd1498Szrj return;
118838fd1498Szrj /* Otherwise, find any other chains that do not match exactly;
118938fd1498Szrj ensure they all get marked unrenamable. */
119038fd1498Szrj p = &head->next_chain;
119138fd1498Szrj continue;
119238fd1498Szrj }
119338fd1498Szrj
119438fd1498Szrj /* Whether the terminated chain can be used for renaming
119538fd1498Szrj depends on the action and this being an exact match.
119638fd1498Szrj In either case, we remove this element from open_chains. */
119738fd1498Szrj
119838fd1498Szrj if ((action == terminate_dead || action == terminate_write)
119938fd1498Szrj && (superset || subset))
120038fd1498Szrj {
120138fd1498Szrj unsigned nregs;
120238fd1498Szrj
120338fd1498Szrj if (subset && !superset)
120438fd1498Szrj head->cannot_rename = 1;
120538fd1498Szrj bitmap_clear_bit (&open_chains_set, head->id);
120638fd1498Szrj
120738fd1498Szrj nregs = head->nregs;
120838fd1498Szrj while (nregs-- > 0)
120938fd1498Szrj {
121038fd1498Szrj CLEAR_HARD_REG_BIT (live_in_chains, head->regno + nregs);
121138fd1498Szrj if (subset && !superset
121238fd1498Szrj && (head->regno + nregs < this_regno
121338fd1498Szrj || head->regno + nregs >= this_regno + this_nregs))
121438fd1498Szrj SET_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
121538fd1498Szrj }
121638fd1498Szrj
121738fd1498Szrj if (action == terminate_dead)
121838fd1498Szrj terminated_this_insn = *p;
121938fd1498Szrj *p = next;
122038fd1498Szrj if (dump_file)
122138fd1498Szrj fprintf (dump_file,
122238fd1498Szrj "Closing chain %s (%d) at insn %d (%s%s)\n",
122338fd1498Szrj reg_names[head->regno], head->id, INSN_UID (insn),
122438fd1498Szrj scan_actions_name[(int) action],
122538fd1498Szrj superset ? ", superset" : subset ? ", subset" : "");
122638fd1498Szrj }
122738fd1498Szrj else if (action == terminate_dead || action == terminate_write)
122838fd1498Szrj {
122938fd1498Szrj /* In this case, tracking liveness gets too hard. Fail the
123038fd1498Szrj entire basic block. */
123138fd1498Szrj if (dump_file)
123238fd1498Szrj fprintf (dump_file,
123338fd1498Szrj "Failing basic block due to unhandled overlap\n");
123438fd1498Szrj fail_current_block = true;
123538fd1498Szrj return;
123638fd1498Szrj }
123738fd1498Szrj else
123838fd1498Szrj {
123938fd1498Szrj head->cannot_rename = 1;
124038fd1498Szrj if (dump_file)
124138fd1498Szrj fprintf (dump_file,
124238fd1498Szrj "Cannot rename chain %s (%d) at insn %d (%s)\n",
124338fd1498Szrj reg_names[head->regno], head->id, INSN_UID (insn),
124438fd1498Szrj scan_actions_name[(int) action]);
124538fd1498Szrj p = &head->next_chain;
124638fd1498Szrj }
124738fd1498Szrj }
124838fd1498Szrj }
124938fd1498Szrj
125038fd1498Szrj /* A wrapper around base_reg_class which returns ALL_REGS if INSN is a
125138fd1498Szrj DEBUG_INSN. The arguments MODE, AS, CODE and INDEX_CODE are as for
125238fd1498Szrj base_reg_class. */
125338fd1498Szrj
125438fd1498Szrj static reg_class
base_reg_class_for_rename(rtx_insn * insn,machine_mode mode,addr_space_t as,rtx_code code,rtx_code index_code)125538fd1498Szrj base_reg_class_for_rename (rtx_insn *insn, machine_mode mode, addr_space_t as,
125638fd1498Szrj rtx_code code, rtx_code index_code)
125738fd1498Szrj {
125838fd1498Szrj if (DEBUG_INSN_P (insn))
125938fd1498Szrj return ALL_REGS;
126038fd1498Szrj return base_reg_class (mode, as, code, index_code);
126138fd1498Szrj }
126238fd1498Szrj
126338fd1498Szrj /* Adapted from find_reloads_address_1. CL is INDEX_REG_CLASS or
126438fd1498Szrj BASE_REG_CLASS depending on how the register is being considered. */
126538fd1498Szrj
126638fd1498Szrj static void
scan_rtx_address(rtx_insn * insn,rtx * loc,enum reg_class cl,enum scan_actions action,machine_mode mode,addr_space_t as)126738fd1498Szrj scan_rtx_address (rtx_insn *insn, rtx *loc, enum reg_class cl,
126838fd1498Szrj enum scan_actions action, machine_mode mode,
126938fd1498Szrj addr_space_t as)
127038fd1498Szrj {
127138fd1498Szrj rtx x = *loc;
127238fd1498Szrj RTX_CODE code = GET_CODE (x);
127338fd1498Szrj const char *fmt;
127438fd1498Szrj int i, j;
127538fd1498Szrj
127638fd1498Szrj if (action == mark_write || action == mark_access)
127738fd1498Szrj return;
127838fd1498Szrj
127938fd1498Szrj switch (code)
128038fd1498Szrj {
128138fd1498Szrj case PLUS:
128238fd1498Szrj {
128338fd1498Szrj rtx orig_op0 = XEXP (x, 0);
128438fd1498Szrj rtx orig_op1 = XEXP (x, 1);
128538fd1498Szrj RTX_CODE code0 = GET_CODE (orig_op0);
128638fd1498Szrj RTX_CODE code1 = GET_CODE (orig_op1);
128738fd1498Szrj rtx op0 = orig_op0;
128838fd1498Szrj rtx op1 = orig_op1;
128938fd1498Szrj rtx *locI = NULL;
129038fd1498Szrj rtx *locB = NULL;
129138fd1498Szrj enum rtx_code index_code = SCRATCH;
129238fd1498Szrj
129338fd1498Szrj if (GET_CODE (op0) == SUBREG)
129438fd1498Szrj {
129538fd1498Szrj op0 = SUBREG_REG (op0);
129638fd1498Szrj code0 = GET_CODE (op0);
129738fd1498Szrj }
129838fd1498Szrj
129938fd1498Szrj if (GET_CODE (op1) == SUBREG)
130038fd1498Szrj {
130138fd1498Szrj op1 = SUBREG_REG (op1);
130238fd1498Szrj code1 = GET_CODE (op1);
130338fd1498Szrj }
130438fd1498Szrj
130538fd1498Szrj if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
130638fd1498Szrj || code0 == ZERO_EXTEND || code1 == MEM)
130738fd1498Szrj {
130838fd1498Szrj locI = &XEXP (x, 0);
130938fd1498Szrj locB = &XEXP (x, 1);
131038fd1498Szrj index_code = GET_CODE (*locI);
131138fd1498Szrj }
131238fd1498Szrj else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
131338fd1498Szrj || code1 == ZERO_EXTEND || code0 == MEM)
131438fd1498Szrj {
131538fd1498Szrj locI = &XEXP (x, 1);
131638fd1498Szrj locB = &XEXP (x, 0);
131738fd1498Szrj index_code = GET_CODE (*locI);
131838fd1498Szrj }
131938fd1498Szrj else if (code0 == CONST_INT || code0 == CONST
132038fd1498Szrj || code0 == SYMBOL_REF || code0 == LABEL_REF)
132138fd1498Szrj {
132238fd1498Szrj locB = &XEXP (x, 1);
132338fd1498Szrj index_code = GET_CODE (XEXP (x, 0));
132438fd1498Szrj }
132538fd1498Szrj else if (code1 == CONST_INT || code1 == CONST
132638fd1498Szrj || code1 == SYMBOL_REF || code1 == LABEL_REF)
132738fd1498Szrj {
132838fd1498Szrj locB = &XEXP (x, 0);
132938fd1498Szrj index_code = GET_CODE (XEXP (x, 1));
133038fd1498Szrj }
133138fd1498Szrj else if (code0 == REG && code1 == REG)
133238fd1498Szrj {
133338fd1498Szrj int index_op;
133438fd1498Szrj unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
133538fd1498Szrj
133638fd1498Szrj if (REGNO_OK_FOR_INDEX_P (regno1)
133738fd1498Szrj && regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
133838fd1498Szrj index_op = 1;
133938fd1498Szrj else if (REGNO_OK_FOR_INDEX_P (regno0)
134038fd1498Szrj && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
134138fd1498Szrj index_op = 0;
134238fd1498Szrj else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
134338fd1498Szrj || REGNO_OK_FOR_INDEX_P (regno1))
134438fd1498Szrj index_op = 1;
134538fd1498Szrj else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
134638fd1498Szrj index_op = 0;
134738fd1498Szrj else
134838fd1498Szrj index_op = 1;
134938fd1498Szrj
135038fd1498Szrj locI = &XEXP (x, index_op);
135138fd1498Szrj locB = &XEXP (x, !index_op);
135238fd1498Szrj index_code = GET_CODE (*locI);
135338fd1498Szrj }
135438fd1498Szrj else if (code0 == REG)
135538fd1498Szrj {
135638fd1498Szrj locI = &XEXP (x, 0);
135738fd1498Szrj locB = &XEXP (x, 1);
135838fd1498Szrj index_code = GET_CODE (*locI);
135938fd1498Szrj }
136038fd1498Szrj else if (code1 == REG)
136138fd1498Szrj {
136238fd1498Szrj locI = &XEXP (x, 1);
136338fd1498Szrj locB = &XEXP (x, 0);
136438fd1498Szrj index_code = GET_CODE (*locI);
136538fd1498Szrj }
136638fd1498Szrj
136738fd1498Szrj if (locI)
136838fd1498Szrj {
136938fd1498Szrj reg_class iclass = DEBUG_INSN_P (insn) ? ALL_REGS : INDEX_REG_CLASS;
137038fd1498Szrj scan_rtx_address (insn, locI, iclass, action, mode, as);
137138fd1498Szrj }
137238fd1498Szrj if (locB)
137338fd1498Szrj {
137438fd1498Szrj reg_class bclass = base_reg_class_for_rename (insn, mode, as, PLUS,
137538fd1498Szrj index_code);
137638fd1498Szrj scan_rtx_address (insn, locB, bclass, action, mode, as);
137738fd1498Szrj }
137838fd1498Szrj return;
137938fd1498Szrj }
138038fd1498Szrj
138138fd1498Szrj case POST_INC:
138238fd1498Szrj case POST_DEC:
138338fd1498Szrj case POST_MODIFY:
138438fd1498Szrj case PRE_INC:
138538fd1498Szrj case PRE_DEC:
138638fd1498Szrj case PRE_MODIFY:
138738fd1498Szrj /* If the target doesn't claim to handle autoinc, this must be
138838fd1498Szrj something special, like a stack push. Kill this chain. */
138938fd1498Szrj if (!AUTO_INC_DEC)
139038fd1498Szrj action = mark_all_read;
139138fd1498Szrj
139238fd1498Szrj break;
139338fd1498Szrj
139438fd1498Szrj case MEM:
139538fd1498Szrj {
139638fd1498Szrj reg_class bclass = base_reg_class_for_rename (insn, GET_MODE (x),
139738fd1498Szrj MEM_ADDR_SPACE (x),
139838fd1498Szrj MEM, SCRATCH);
139938fd1498Szrj scan_rtx_address (insn, &XEXP (x, 0), bclass, action, GET_MODE (x),
140038fd1498Szrj MEM_ADDR_SPACE (x));
140138fd1498Szrj }
140238fd1498Szrj return;
140338fd1498Szrj
140438fd1498Szrj case REG:
140538fd1498Szrj scan_rtx_reg (insn, loc, cl, action, OP_IN);
140638fd1498Szrj return;
140738fd1498Szrj
140838fd1498Szrj default:
140938fd1498Szrj break;
141038fd1498Szrj }
141138fd1498Szrj
141238fd1498Szrj fmt = GET_RTX_FORMAT (code);
141338fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
141438fd1498Szrj {
141538fd1498Szrj if (fmt[i] == 'e')
141638fd1498Szrj scan_rtx_address (insn, &XEXP (x, i), cl, action, mode, as);
141738fd1498Szrj else if (fmt[i] == 'E')
141838fd1498Szrj for (j = XVECLEN (x, i) - 1; j >= 0; j--)
141938fd1498Szrj scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode, as);
142038fd1498Szrj }
142138fd1498Szrj }
142238fd1498Szrj
142338fd1498Szrj static void
scan_rtx(rtx_insn * insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum op_type type)142438fd1498Szrj scan_rtx (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
142538fd1498Szrj enum op_type type)
142638fd1498Szrj {
142738fd1498Szrj const char *fmt;
142838fd1498Szrj rtx x = *loc;
142938fd1498Szrj enum rtx_code code = GET_CODE (x);
143038fd1498Szrj int i, j;
143138fd1498Szrj
143238fd1498Szrj code = GET_CODE (x);
143338fd1498Szrj switch (code)
143438fd1498Szrj {
143538fd1498Szrj case CONST:
143638fd1498Szrj CASE_CONST_ANY:
143738fd1498Szrj case SYMBOL_REF:
143838fd1498Szrj case LABEL_REF:
143938fd1498Szrj case CC0:
144038fd1498Szrj case PC:
144138fd1498Szrj return;
144238fd1498Szrj
144338fd1498Szrj case REG:
144438fd1498Szrj scan_rtx_reg (insn, loc, cl, action, type);
144538fd1498Szrj return;
144638fd1498Szrj
144738fd1498Szrj case MEM:
144838fd1498Szrj {
144938fd1498Szrj reg_class bclass = base_reg_class_for_rename (insn, GET_MODE (x),
145038fd1498Szrj MEM_ADDR_SPACE (x),
145138fd1498Szrj MEM, SCRATCH);
145238fd1498Szrj
145338fd1498Szrj scan_rtx_address (insn, &XEXP (x, 0), bclass, action, GET_MODE (x),
145438fd1498Szrj MEM_ADDR_SPACE (x));
145538fd1498Szrj }
145638fd1498Szrj return;
145738fd1498Szrj
145838fd1498Szrj case SET:
145938fd1498Szrj scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN);
146038fd1498Szrj scan_rtx (insn, &SET_DEST (x), cl, action,
146138fd1498Szrj (GET_CODE (PATTERN (insn)) == COND_EXEC
146238fd1498Szrj && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
146338fd1498Szrj return;
146438fd1498Szrj
146538fd1498Szrj case STRICT_LOW_PART:
146638fd1498Szrj scan_rtx (insn, &XEXP (x, 0), cl, action,
146738fd1498Szrj verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT);
146838fd1498Szrj return;
146938fd1498Szrj
147038fd1498Szrj case ZERO_EXTRACT:
147138fd1498Szrj case SIGN_EXTRACT:
147238fd1498Szrj scan_rtx (insn, &XEXP (x, 0), cl, action,
147338fd1498Szrj (type == OP_IN ? OP_IN :
147438fd1498Szrj verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT));
147538fd1498Szrj scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN);
147638fd1498Szrj scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN);
147738fd1498Szrj return;
147838fd1498Szrj
147938fd1498Szrj case POST_INC:
148038fd1498Szrj case PRE_INC:
148138fd1498Szrj case POST_DEC:
148238fd1498Szrj case PRE_DEC:
148338fd1498Szrj case POST_MODIFY:
148438fd1498Szrj case PRE_MODIFY:
148538fd1498Szrj /* Should only happen inside MEM. */
148638fd1498Szrj gcc_unreachable ();
148738fd1498Szrj
148838fd1498Szrj case CLOBBER:
148938fd1498Szrj scan_rtx (insn, &SET_DEST (x), cl, action,
149038fd1498Szrj (GET_CODE (PATTERN (insn)) == COND_EXEC
149138fd1498Szrj && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
149238fd1498Szrj return;
149338fd1498Szrj
149438fd1498Szrj case EXPR_LIST:
149538fd1498Szrj scan_rtx (insn, &XEXP (x, 0), cl, action, type);
149638fd1498Szrj if (XEXP (x, 1))
149738fd1498Szrj scan_rtx (insn, &XEXP (x, 1), cl, action, type);
149838fd1498Szrj return;
149938fd1498Szrj
150038fd1498Szrj default:
150138fd1498Szrj break;
150238fd1498Szrj }
150338fd1498Szrj
150438fd1498Szrj fmt = GET_RTX_FORMAT (code);
150538fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
150638fd1498Szrj {
150738fd1498Szrj if (fmt[i] == 'e')
150838fd1498Szrj scan_rtx (insn, &XEXP (x, i), cl, action, type);
150938fd1498Szrj else if (fmt[i] == 'E')
151038fd1498Szrj for (j = XVECLEN (x, i) - 1; j >= 0; j--)
151138fd1498Szrj scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type);
151238fd1498Szrj }
151338fd1498Szrj }
151438fd1498Szrj
151538fd1498Szrj /* Hide operands of the current insn (of which there are N_OPS) by
151638fd1498Szrj substituting cc0 for them.
151738fd1498Szrj Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
151838fd1498Szrj For every bit set in DO_NOT_HIDE, we leave the operand alone.
151938fd1498Szrj If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
152038fd1498Szrj and earlyclobbers. */
152138fd1498Szrj
152238fd1498Szrj 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)152338fd1498Szrj hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
152438fd1498Szrj unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only)
152538fd1498Szrj {
152638fd1498Szrj int i;
152738fd1498Szrj const operand_alternative *op_alt = which_op_alt ();
152838fd1498Szrj for (i = 0; i < n_ops; i++)
152938fd1498Szrj {
153038fd1498Szrj old_operands[i] = recog_data.operand[i];
153138fd1498Szrj /* Don't squash match_operator or match_parallel here, since
153238fd1498Szrj we don't know that all of the contained registers are
153338fd1498Szrj reachable by proper operands. */
153438fd1498Szrj if (recog_data.constraints[i][0] == '\0')
153538fd1498Szrj continue;
153638fd1498Szrj if (do_not_hide & (1 << i))
153738fd1498Szrj continue;
153838fd1498Szrj if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT
153938fd1498Szrj || op_alt[i].earlyclobber)
154038fd1498Szrj *recog_data.operand_loc[i] = cc0_rtx;
154138fd1498Szrj }
154238fd1498Szrj for (i = 0; i < recog_data.n_dups; i++)
154338fd1498Szrj {
154438fd1498Szrj int opn = recog_data.dup_num[i];
154538fd1498Szrj old_dups[i] = *recog_data.dup_loc[i];
154638fd1498Szrj if (do_not_hide & (1 << opn))
154738fd1498Szrj continue;
154838fd1498Szrj if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT
154938fd1498Szrj || op_alt[opn].earlyclobber)
155038fd1498Szrj *recog_data.dup_loc[i] = cc0_rtx;
155138fd1498Szrj }
155238fd1498Szrj }
155338fd1498Szrj
155438fd1498Szrj /* Undo the substitution performed by hide_operands. INSN is the insn we
155538fd1498Szrj are processing; the arguments are the same as in hide_operands. */
155638fd1498Szrj
155738fd1498Szrj static void
restore_operands(rtx_insn * insn,int n_ops,rtx * old_operands,rtx * old_dups)155838fd1498Szrj restore_operands (rtx_insn *insn, int n_ops, rtx *old_operands, rtx *old_dups)
155938fd1498Szrj {
156038fd1498Szrj int i;
156138fd1498Szrj for (i = 0; i < recog_data.n_dups; i++)
156238fd1498Szrj *recog_data.dup_loc[i] = old_dups[i];
156338fd1498Szrj for (i = 0; i < n_ops; i++)
156438fd1498Szrj *recog_data.operand_loc[i] = old_operands[i];
156538fd1498Szrj if (recog_data.n_dups)
156638fd1498Szrj df_insn_rescan (insn);
156738fd1498Szrj }
156838fd1498Szrj
156938fd1498Szrj /* For each output operand of INSN, call scan_rtx to create a new
157038fd1498Szrj open chain. Do this only for normal or earlyclobber outputs,
157138fd1498Szrj depending on EARLYCLOBBER. If INSN_INFO is nonnull, use it to
157238fd1498Szrj record information about the operands in the insn. */
157338fd1498Szrj
157438fd1498Szrj static void
record_out_operands(rtx_insn * insn,bool earlyclobber,insn_rr_info * insn_info)157538fd1498Szrj record_out_operands (rtx_insn *insn, bool earlyclobber, insn_rr_info *insn_info)
157638fd1498Szrj {
157738fd1498Szrj int n_ops = recog_data.n_operands;
157838fd1498Szrj const operand_alternative *op_alt = which_op_alt ();
157938fd1498Szrj
158038fd1498Szrj int i;
158138fd1498Szrj
158238fd1498Szrj for (i = 0; i < n_ops + recog_data.n_dups; i++)
158338fd1498Szrj {
158438fd1498Szrj int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
158538fd1498Szrj rtx *loc = (i < n_ops
158638fd1498Szrj ? recog_data.operand_loc[opn]
158738fd1498Szrj : recog_data.dup_loc[i - n_ops]);
158838fd1498Szrj rtx op = *loc;
158938fd1498Szrj enum reg_class cl = alternative_class (op_alt, opn);
159038fd1498Szrj
159138fd1498Szrj struct du_head *prev_open;
159238fd1498Szrj
159338fd1498Szrj if (recog_data.operand_type[opn] != OP_OUT
159438fd1498Szrj || op_alt[opn].earlyclobber != earlyclobber)
159538fd1498Szrj continue;
159638fd1498Szrj
159738fd1498Szrj if (insn_info)
159838fd1498Szrj cur_operand = insn_info->op_info + i;
159938fd1498Szrj
160038fd1498Szrj prev_open = open_chains;
160138fd1498Szrj if (earlyclobber)
160238fd1498Szrj scan_rtx (insn, loc, cl, terminate_write, OP_OUT);
160338fd1498Szrj scan_rtx (insn, loc, cl, mark_write, OP_OUT);
160438fd1498Szrj
160538fd1498Szrj /* ??? Many targets have output constraints on the SET_DEST
160638fd1498Szrj of a call insn, which is stupid, since these are certainly
160738fd1498Szrj ABI defined hard registers. For these, and for asm operands
160838fd1498Szrj that originally referenced hard registers, we must record that
160938fd1498Szrj the chain cannot be renamed. */
161038fd1498Szrj if (CALL_P (insn)
161138fd1498Szrj || (asm_noperands (PATTERN (insn)) > 0
161238fd1498Szrj && REG_P (op)
161338fd1498Szrj && REGNO (op) == ORIGINAL_REGNO (op)))
161438fd1498Szrj {
161538fd1498Szrj if (prev_open != open_chains)
161638fd1498Szrj open_chains->cannot_rename = 1;
161738fd1498Szrj }
161838fd1498Szrj }
161938fd1498Szrj cur_operand = NULL;
162038fd1498Szrj }
162138fd1498Szrj
162238fd1498Szrj /* Build def/use chain. */
162338fd1498Szrj
162438fd1498Szrj static bool
build_def_use(basic_block bb)162538fd1498Szrj build_def_use (basic_block bb)
162638fd1498Szrj {
162738fd1498Szrj rtx_insn *insn;
162838fd1498Szrj unsigned HOST_WIDE_INT untracked_operands;
162938fd1498Szrj
163038fd1498Szrj fail_current_block = false;
163138fd1498Szrj
163238fd1498Szrj for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
163338fd1498Szrj {
163438fd1498Szrj if (NONDEBUG_INSN_P (insn))
163538fd1498Szrj {
163638fd1498Szrj int n_ops;
163738fd1498Szrj rtx note;
163838fd1498Szrj rtx old_operands[MAX_RECOG_OPERANDS];
163938fd1498Szrj rtx old_dups[MAX_DUP_OPERANDS];
164038fd1498Szrj int i;
164138fd1498Szrj int predicated;
164238fd1498Szrj enum rtx_code set_code = SET;
164338fd1498Szrj enum rtx_code clobber_code = CLOBBER;
164438fd1498Szrj insn_rr_info *insn_info = NULL;
164538fd1498Szrj terminated_this_insn = NULL;
164638fd1498Szrj
164738fd1498Szrj /* Process the insn, determining its effect on the def-use
164838fd1498Szrj chains and live hard registers. We perform the following
164938fd1498Szrj steps with the register references in the insn, simulating
165038fd1498Szrj its effect:
165138fd1498Szrj (1) Deal with earlyclobber operands and CLOBBERs of non-operands
165238fd1498Szrj by creating chains and marking hard regs live.
165338fd1498Szrj (2) Any read outside an operand causes any chain it overlaps
165438fd1498Szrj with to be marked unrenamable.
165538fd1498Szrj (3) Any read inside an operand is added if there's already
165638fd1498Szrj an open chain for it.
165738fd1498Szrj (4) For any REG_DEAD note we find, close open chains that
165838fd1498Szrj overlap it.
165938fd1498Szrj (5) For any non-earlyclobber write we find, close open chains
166038fd1498Szrj that overlap it.
166138fd1498Szrj (6) For any non-earlyclobber write we find in an operand, make
166238fd1498Szrj a new chain or mark the hard register as live.
166338fd1498Szrj (7) For any REG_UNUSED, close any chains we just opened.
1664*58e805e6Szrj (8) For any REG_CFA_RESTORE or REG_CFA_REGISTER, kill any chain
1665*58e805e6Szrj containing its dest.
166638fd1498Szrj
166738fd1498Szrj We cannot deal with situations where we track a reg in one mode
166838fd1498Szrj and see a reference in another mode; these will cause the chain
166938fd1498Szrj to be marked unrenamable or even cause us to abort the entire
167038fd1498Szrj basic block. */
167138fd1498Szrj
167238fd1498Szrj extract_constrain_insn (insn);
167338fd1498Szrj preprocess_constraints (insn);
167438fd1498Szrj const operand_alternative *op_alt = which_op_alt ();
167538fd1498Szrj n_ops = recog_data.n_operands;
167638fd1498Szrj untracked_operands = 0;
167738fd1498Szrj
167838fd1498Szrj if (insn_rr.exists ())
167938fd1498Szrj {
168038fd1498Szrj insn_info = &insn_rr[INSN_UID (insn)];
168138fd1498Szrj insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
168238fd1498Szrj recog_data.n_operands);
168338fd1498Szrj memset (insn_info->op_info, 0,
168438fd1498Szrj sizeof (operand_rr_info) * recog_data.n_operands);
168538fd1498Szrj }
168638fd1498Szrj
168738fd1498Szrj /* Simplify the code below by promoting OP_OUT to OP_INOUT in
168838fd1498Szrj predicated instructions, but only for register operands
168938fd1498Szrj that are already tracked, so that we can create a chain
169038fd1498Szrj when the first SET makes a register live. */
169138fd1498Szrj
169238fd1498Szrj predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
169338fd1498Szrj for (i = 0; i < n_ops; ++i)
169438fd1498Szrj {
169538fd1498Szrj rtx op = recog_data.operand[i];
169638fd1498Szrj int matches = op_alt[i].matches;
169738fd1498Szrj if (matches >= 0 || op_alt[i].matched >= 0
169838fd1498Szrj || (predicated && recog_data.operand_type[i] == OP_OUT))
169938fd1498Szrj {
170038fd1498Szrj recog_data.operand_type[i] = OP_INOUT;
170138fd1498Szrj /* A special case to deal with instruction patterns that
170238fd1498Szrj have matching operands with different modes. If we're
170338fd1498Szrj not already tracking such a reg, we won't start here,
170438fd1498Szrj and we must instead make sure to make the operand visible
170538fd1498Szrj to the machinery that tracks hard registers. */
170638fd1498Szrj machine_mode i_mode = recog_data.operand_mode[i];
170738fd1498Szrj if (matches >= 0)
170838fd1498Szrj {
170938fd1498Szrj machine_mode matches_mode
171038fd1498Szrj = recog_data.operand_mode[matches];
171138fd1498Szrj
171238fd1498Szrj if (maybe_ne (GET_MODE_SIZE (i_mode),
171338fd1498Szrj GET_MODE_SIZE (matches_mode))
171438fd1498Szrj && !verify_reg_in_set (op, &live_in_chains))
171538fd1498Szrj {
171638fd1498Szrj untracked_operands |= 1 << i;
171738fd1498Szrj untracked_operands |= 1 << matches;
171838fd1498Szrj }
171938fd1498Szrj }
172038fd1498Szrj }
172138fd1498Szrj #ifdef STACK_REGS
172238fd1498Szrj if (regstack_completed
172338fd1498Szrj && REG_P (op)
172438fd1498Szrj && IN_RANGE (REGNO (op), FIRST_STACK_REG, LAST_STACK_REG))
172538fd1498Szrj untracked_operands |= 1 << i;
172638fd1498Szrj #endif
172738fd1498Szrj /* If there's an in-out operand with a register that is not
172838fd1498Szrj being tracked at all yet, open a chain. */
172938fd1498Szrj if (recog_data.operand_type[i] == OP_INOUT
173038fd1498Szrj && !(untracked_operands & (1 << i))
173138fd1498Szrj && REG_P (op)
173238fd1498Szrj && !verify_reg_tracked (op))
173338fd1498Szrj create_new_chain (REGNO (op), REG_NREGS (op), NULL, NULL,
173438fd1498Szrj NO_REGS);
173538fd1498Szrj }
173638fd1498Szrj
173738fd1498Szrj if (fail_current_block)
173838fd1498Szrj break;
173938fd1498Szrj
174038fd1498Szrj /* Step 1a: Mark hard registers that are clobbered in this insn,
174138fd1498Szrj outside an operand, as live. */
174238fd1498Szrj hide_operands (n_ops, old_operands, old_dups, untracked_operands,
174338fd1498Szrj false);
174438fd1498Szrj note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code);
174538fd1498Szrj restore_operands (insn, n_ops, old_operands, old_dups);
174638fd1498Szrj
174738fd1498Szrj /* Step 1b: Begin new chains for earlyclobbered writes inside
174838fd1498Szrj operands. */
174938fd1498Szrj record_out_operands (insn, true, insn_info);
175038fd1498Szrj
175138fd1498Szrj /* Step 2: Mark chains for which we have reads outside operands
175238fd1498Szrj as unrenamable.
175338fd1498Szrj We do this by munging all operands into CC0, and closing
175438fd1498Szrj everything remaining. */
175538fd1498Szrj
175638fd1498Szrj hide_operands (n_ops, old_operands, old_dups, untracked_operands,
175738fd1498Szrj false);
175838fd1498Szrj scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN);
175938fd1498Szrj restore_operands (insn, n_ops, old_operands, old_dups);
176038fd1498Szrj
176138fd1498Szrj /* Step 2B: Can't rename function call argument registers. */
176238fd1498Szrj if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
176338fd1498Szrj scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
176438fd1498Szrj NO_REGS, mark_all_read, OP_IN);
176538fd1498Szrj
176638fd1498Szrj /* Step 2C: Can't rename asm operands that were originally
176738fd1498Szrj hard registers. */
176838fd1498Szrj if (asm_noperands (PATTERN (insn)) > 0)
176938fd1498Szrj for (i = 0; i < n_ops; i++)
177038fd1498Szrj {
177138fd1498Szrj rtx *loc = recog_data.operand_loc[i];
177238fd1498Szrj rtx op = *loc;
177338fd1498Szrj
177438fd1498Szrj if (REG_P (op)
177538fd1498Szrj && REGNO (op) == ORIGINAL_REGNO (op)
177638fd1498Szrj && (recog_data.operand_type[i] == OP_IN
177738fd1498Szrj || recog_data.operand_type[i] == OP_INOUT))
177838fd1498Szrj scan_rtx (insn, loc, NO_REGS, mark_all_read, OP_IN);
177938fd1498Szrj }
178038fd1498Szrj
178138fd1498Szrj /* Step 3: Append to chains for reads inside operands. */
178238fd1498Szrj for (i = 0; i < n_ops + recog_data.n_dups; i++)
178338fd1498Szrj {
178438fd1498Szrj int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
178538fd1498Szrj rtx *loc = (i < n_ops
178638fd1498Szrj ? recog_data.operand_loc[opn]
178738fd1498Szrj : recog_data.dup_loc[i - n_ops]);
178838fd1498Szrj enum reg_class cl = alternative_class (op_alt, opn);
178938fd1498Szrj enum op_type type = recog_data.operand_type[opn];
179038fd1498Szrj
179138fd1498Szrj /* Don't scan match_operand here, since we've no reg class
179238fd1498Szrj information to pass down. Any operands that we could
179338fd1498Szrj substitute in will be represented elsewhere. */
179438fd1498Szrj if (recog_data.constraints[opn][0] == '\0'
179538fd1498Szrj || untracked_operands & (1 << opn))
179638fd1498Szrj continue;
179738fd1498Szrj
179838fd1498Szrj if (insn_info)
179938fd1498Szrj cur_operand = i == opn ? insn_info->op_info + i : NULL;
180038fd1498Szrj if (op_alt[opn].is_address)
180138fd1498Szrj scan_rtx_address (insn, loc, cl, mark_read,
180238fd1498Szrj VOIDmode, ADDR_SPACE_GENERIC);
180338fd1498Szrj else
180438fd1498Szrj scan_rtx (insn, loc, cl, mark_read, type);
180538fd1498Szrj }
180638fd1498Szrj cur_operand = NULL;
180738fd1498Szrj
180838fd1498Szrj /* Step 3B: Record updates for regs in REG_INC notes, and
180938fd1498Szrj source regs in REG_FRAME_RELATED_EXPR notes. */
181038fd1498Szrj for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
181138fd1498Szrj if (REG_NOTE_KIND (note) == REG_INC
181238fd1498Szrj || REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
181338fd1498Szrj scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
181438fd1498Szrj OP_INOUT);
181538fd1498Szrj
181638fd1498Szrj /* Step 4: Close chains for registers that die here, unless
181738fd1498Szrj the register is mentioned in a REG_UNUSED note. In that
181838fd1498Szrj case we keep the chain open until step #7 below to ensure
181938fd1498Szrj it conflicts with other output operands of this insn.
182038fd1498Szrj See PR 52573. Arguably the insn should not have both
182138fd1498Szrj notes; it has proven difficult to fix that without
182238fd1498Szrj other undesirable side effects. */
182338fd1498Szrj for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
182438fd1498Szrj if (REG_NOTE_KIND (note) == REG_DEAD
182538fd1498Szrj && !find_regno_note (insn, REG_UNUSED, REGNO (XEXP (note, 0))))
182638fd1498Szrj {
182738fd1498Szrj remove_from_hard_reg_set (&live_hard_regs,
182838fd1498Szrj GET_MODE (XEXP (note, 0)),
182938fd1498Szrj REGNO (XEXP (note, 0)));
183038fd1498Szrj scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
183138fd1498Szrj OP_IN);
183238fd1498Szrj }
183338fd1498Szrj
183438fd1498Szrj /* Step 4B: If this is a call, any chain live at this point
183538fd1498Szrj requires a caller-saved reg. */
183638fd1498Szrj if (CALL_P (insn))
183738fd1498Szrj {
183838fd1498Szrj struct du_head *p;
183938fd1498Szrj for (p = open_chains; p; p = p->next_chain)
184038fd1498Szrj p->need_caller_save_reg = 1;
184138fd1498Szrj }
184238fd1498Szrj
184338fd1498Szrj /* Step 5: Close open chains that overlap writes. Similar to
184438fd1498Szrj step 2, we hide in-out operands, since we do not want to
184538fd1498Szrj close these chains. We also hide earlyclobber operands,
184638fd1498Szrj since we've opened chains for them in step 1, and earlier
184738fd1498Szrj chains they would overlap with must have been closed at
184838fd1498Szrj the previous insn at the latest, as such operands cannot
184938fd1498Szrj possibly overlap with any input operands. */
185038fd1498Szrj
185138fd1498Szrj hide_operands (n_ops, old_operands, old_dups, untracked_operands,
185238fd1498Szrj true);
185338fd1498Szrj scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN);
185438fd1498Szrj restore_operands (insn, n_ops, old_operands, old_dups);
185538fd1498Szrj
185638fd1498Szrj /* Step 6a: Mark hard registers that are set in this insn,
185738fd1498Szrj outside an operand, as live. */
185838fd1498Szrj hide_operands (n_ops, old_operands, old_dups, untracked_operands,
185938fd1498Szrj false);
186038fd1498Szrj note_stores (PATTERN (insn), note_sets_clobbers, &set_code);
186138fd1498Szrj restore_operands (insn, n_ops, old_operands, old_dups);
186238fd1498Szrj
186338fd1498Szrj /* Step 6b: Begin new chains for writes inside operands. */
186438fd1498Szrj record_out_operands (insn, false, insn_info);
186538fd1498Szrj
186638fd1498Szrj /* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
186738fd1498Szrj notes for update. */
186838fd1498Szrj for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
186938fd1498Szrj if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
187038fd1498Szrj scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access,
187138fd1498Szrj OP_INOUT);
187238fd1498Szrj
187338fd1498Szrj /* Step 7: Close chains for registers that were never
187438fd1498Szrj really used here. */
187538fd1498Szrj for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
187638fd1498Szrj if (REG_NOTE_KIND (note) == REG_UNUSED)
187738fd1498Szrj {
187838fd1498Szrj remove_from_hard_reg_set (&live_hard_regs,
187938fd1498Szrj GET_MODE (XEXP (note, 0)),
188038fd1498Szrj REGNO (XEXP (note, 0)));
188138fd1498Szrj scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
188238fd1498Szrj OP_IN);
188338fd1498Szrj }
188438fd1498Szrj
188538fd1498Szrj /* Step 8: Kill the chains involving register restores. Those
1886*58e805e6Szrj should restore _that_ register. Similar for REG_CFA_REGISTER. */
188738fd1498Szrj for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1888*58e805e6Szrj if (REG_NOTE_KIND (note) == REG_CFA_RESTORE
1889*58e805e6Szrj || REG_NOTE_KIND (note) == REG_CFA_REGISTER)
1890*58e805e6Szrj {
1891*58e805e6Szrj rtx *x = &XEXP (note, 0);
1892*58e805e6Szrj if (!*x)
1893*58e805e6Szrj x = &PATTERN (insn);
1894*58e805e6Szrj if (GET_CODE (*x) == PARALLEL)
1895*58e805e6Szrj x = &XVECEXP (*x, 0, 0);
1896*58e805e6Szrj if (GET_CODE (*x) == SET)
1897*58e805e6Szrj x = &SET_DEST (*x);
1898*58e805e6Szrj scan_rtx (insn, x, NO_REGS, mark_all_read, OP_IN);
1899*58e805e6Szrj }
190038fd1498Szrj }
190138fd1498Szrj else if (DEBUG_BIND_INSN_P (insn)
190238fd1498Szrj && !VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)))
190338fd1498Szrj {
190438fd1498Szrj scan_rtx (insn, &INSN_VAR_LOCATION_LOC (insn),
190538fd1498Szrj ALL_REGS, mark_read, OP_IN);
190638fd1498Szrj }
190738fd1498Szrj if (insn == BB_END (bb))
190838fd1498Szrj break;
190938fd1498Szrj }
191038fd1498Szrj
191138fd1498Szrj if (fail_current_block)
191238fd1498Szrj return false;
191338fd1498Szrj
191438fd1498Szrj return true;
191538fd1498Szrj }
191638fd1498Szrj
191738fd1498Szrj /* Initialize the register renamer. If INSN_INFO is true, ensure that
191838fd1498Szrj insn_rr is nonnull. */
191938fd1498Szrj void
regrename_init(bool insn_info)192038fd1498Szrj regrename_init (bool insn_info)
192138fd1498Szrj {
192238fd1498Szrj gcc_obstack_init (&rename_obstack);
192338fd1498Szrj insn_rr.create (0);
192438fd1498Szrj if (insn_info)
192538fd1498Szrj insn_rr.safe_grow_cleared (get_max_uid ());
192638fd1498Szrj }
192738fd1498Szrj
192838fd1498Szrj /* Free all global data used by the register renamer. */
192938fd1498Szrj void
regrename_finish(void)193038fd1498Szrj regrename_finish (void)
193138fd1498Szrj {
193238fd1498Szrj insn_rr.release ();
193338fd1498Szrj free_chain_data ();
193438fd1498Szrj obstack_free (&rename_obstack, NULL);
193538fd1498Szrj }
193638fd1498Szrj
193738fd1498Szrj /* Perform register renaming on the current function. */
193838fd1498Szrj
193938fd1498Szrj static unsigned int
regrename_optimize(void)194038fd1498Szrj regrename_optimize (void)
194138fd1498Szrj {
194238fd1498Szrj df_set_flags (DF_LR_RUN_DCE);
194338fd1498Szrj df_note_add_problem ();
194438fd1498Szrj df_analyze ();
194538fd1498Szrj df_set_flags (DF_DEFER_INSN_RESCAN);
194638fd1498Szrj
194738fd1498Szrj regrename_init (false);
194838fd1498Szrj
194938fd1498Szrj regrename_analyze (NULL);
195038fd1498Szrj
195138fd1498Szrj rename_chains ();
195238fd1498Szrj
195338fd1498Szrj regrename_finish ();
195438fd1498Szrj
195538fd1498Szrj return 0;
195638fd1498Szrj }
195738fd1498Szrj
195838fd1498Szrj namespace {
195938fd1498Szrj
196038fd1498Szrj const pass_data pass_data_regrename =
196138fd1498Szrj {
196238fd1498Szrj RTL_PASS, /* type */
196338fd1498Szrj "rnreg", /* name */
196438fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */
196538fd1498Szrj TV_RENAME_REGISTERS, /* tv_id */
196638fd1498Szrj 0, /* properties_required */
196738fd1498Szrj 0, /* properties_provided */
196838fd1498Szrj 0, /* properties_destroyed */
196938fd1498Szrj 0, /* todo_flags_start */
197038fd1498Szrj TODO_df_finish, /* todo_flags_finish */
197138fd1498Szrj };
197238fd1498Szrj
197338fd1498Szrj class pass_regrename : public rtl_opt_pass
197438fd1498Szrj {
197538fd1498Szrj public:
pass_regrename(gcc::context * ctxt)197638fd1498Szrj pass_regrename (gcc::context *ctxt)
197738fd1498Szrj : rtl_opt_pass (pass_data_regrename, ctxt)
197838fd1498Szrj {}
197938fd1498Szrj
198038fd1498Szrj /* opt_pass methods: */
gate(function *)198138fd1498Szrj virtual bool gate (function *)
198238fd1498Szrj {
198338fd1498Szrj return (optimize > 0 && (flag_rename_registers));
198438fd1498Szrj }
198538fd1498Szrj
execute(function *)198638fd1498Szrj virtual unsigned int execute (function *) { return regrename_optimize (); }
198738fd1498Szrj
198838fd1498Szrj }; // class pass_regrename
198938fd1498Szrj
199038fd1498Szrj } // anon namespace
199138fd1498Szrj
199238fd1498Szrj rtl_opt_pass *
make_pass_regrename(gcc::context * ctxt)199338fd1498Szrj make_pass_regrename (gcc::context *ctxt)
199438fd1498Szrj {
199538fd1498Szrj return new pass_regrename (ctxt);
199638fd1498Szrj }
1997