138fd1498Szrj /* LRA (local register allocator) driver and LRA utilities.
238fd1498Szrj Copyright (C) 2010-2018 Free Software Foundation, Inc.
338fd1498Szrj Contributed by Vladimir Makarov <vmakarov@redhat.com>.
438fd1498Szrj
538fd1498Szrj This file is part of GCC.
638fd1498Szrj
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3. If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>. */
2038fd1498Szrj
2138fd1498Szrj
2238fd1498Szrj /* The Local Register Allocator (LRA) is a replacement of former
2338fd1498Szrj reload pass. It is focused to simplify code solving the reload
2438fd1498Szrj pass tasks, to make the code maintenance easier, and to implement new
2538fd1498Szrj perspective optimizations.
2638fd1498Szrj
2738fd1498Szrj The major LRA design solutions are:
2838fd1498Szrj o division small manageable, separated sub-tasks
2938fd1498Szrj o reflection of all transformations and decisions in RTL as more
3038fd1498Szrj as possible
3138fd1498Szrj o insn constraints as a primary source of the info (minimizing
3238fd1498Szrj number of target-depended macros/hooks)
3338fd1498Szrj
3438fd1498Szrj In brief LRA works by iterative insn process with the final goal is
3538fd1498Szrj to satisfy all insn and address constraints:
3638fd1498Szrj o New reload insns (in brief reloads) and reload pseudos might be
3738fd1498Szrj generated;
3838fd1498Szrj o Some pseudos might be spilled to assign hard registers to
3938fd1498Szrj new reload pseudos;
4038fd1498Szrj o Recalculating spilled pseudo values (rematerialization);
4138fd1498Szrj o Changing spilled pseudos to stack memory or their equivalences;
4238fd1498Szrj o Allocation stack memory changes the address displacement and
4338fd1498Szrj new iteration is needed.
4438fd1498Szrj
4538fd1498Szrj Here is block diagram of LRA passes:
4638fd1498Szrj
4738fd1498Szrj ------------------------
4838fd1498Szrj --------------- | Undo inheritance for | ---------------
4938fd1498Szrj | Memory-memory | | spilled pseudos, | | New (and old) |
5038fd1498Szrj | move coalesce |<---| splits for pseudos got |<-- | pseudos |
5138fd1498Szrj --------------- | the same hard regs, | | assignment |
5238fd1498Szrj Start | | and optional reloads | ---------------
5338fd1498Szrj | | ------------------------ ^
5438fd1498Szrj V | ---------------- |
5538fd1498Szrj ----------- V | Update virtual | |
5638fd1498Szrj | Remove |----> ------------>| register | |
5738fd1498Szrj | scratches | ^ | displacements | |
5838fd1498Szrj ----------- | ---------------- |
5938fd1498Szrj | | |
6038fd1498Szrj | V New |
6138fd1498Szrj | ------------ pseudos -------------------
6238fd1498Szrj | |Constraints:| or insns | Inheritance/split |
6338fd1498Szrj | | RTL |--------->| transformations |
6438fd1498Szrj | | transfor- | | in EBB scope |
6538fd1498Szrj | substi- | mations | -------------------
6638fd1498Szrj | tutions ------------
6738fd1498Szrj | | No change
6838fd1498Szrj ---------------- V
6938fd1498Szrj | Spilled pseudo | -------------------
7038fd1498Szrj | to memory |<----| Rematerialization |
7138fd1498Szrj | substitution | -------------------
7238fd1498Szrj ----------------
7338fd1498Szrj | No susbtitions
7438fd1498Szrj V
7538fd1498Szrj -------------------------
7638fd1498Szrj | Hard regs substitution, |
7738fd1498Szrj | devirtalization, and |------> Finish
7838fd1498Szrj | restoring scratches got |
7938fd1498Szrj | memory |
8038fd1498Szrj -------------------------
8138fd1498Szrj
8238fd1498Szrj To speed up the process:
8338fd1498Szrj o We process only insns affected by changes on previous
8438fd1498Szrj iterations;
8538fd1498Szrj o We don't use DFA-infrastructure because it results in much slower
8638fd1498Szrj compiler speed than a special IR described below does;
8738fd1498Szrj o We use a special insn representation for quick access to insn
8838fd1498Szrj info which is always *synchronized* with the current RTL;
8938fd1498Szrj o Insn IR is minimized by memory. It is divided on three parts:
9038fd1498Szrj o one specific for each insn in RTL (only operand locations);
9138fd1498Szrj o one common for all insns in RTL with the same insn code
9238fd1498Szrj (different operand attributes from machine descriptions);
9338fd1498Szrj o one oriented for maintenance of live info (list of pseudos).
9438fd1498Szrj o Pseudo data:
9538fd1498Szrj o all insns where the pseudo is referenced;
9638fd1498Szrj o live info (conflicting hard regs, live ranges, # of
9738fd1498Szrj references etc);
9838fd1498Szrj o data used for assigning (preferred hard regs, costs etc).
9938fd1498Szrj
10038fd1498Szrj This file contains LRA driver, LRA utility functions and data, and
10138fd1498Szrj code for dealing with scratches. */
10238fd1498Szrj
10338fd1498Szrj #include "config.h"
10438fd1498Szrj #include "system.h"
10538fd1498Szrj #include "coretypes.h"
10638fd1498Szrj #include "backend.h"
10738fd1498Szrj #include "target.h"
10838fd1498Szrj #include "rtl.h"
10938fd1498Szrj #include "tree.h"
11038fd1498Szrj #include "predict.h"
11138fd1498Szrj #include "df.h"
11238fd1498Szrj #include "memmodel.h"
11338fd1498Szrj #include "tm_p.h"
11438fd1498Szrj #include "optabs.h"
11538fd1498Szrj #include "regs.h"
11638fd1498Szrj #include "ira.h"
11738fd1498Szrj #include "recog.h"
11838fd1498Szrj #include "expr.h"
11938fd1498Szrj #include "cfgrtl.h"
12038fd1498Szrj #include "cfgbuild.h"
12138fd1498Szrj #include "lra.h"
12238fd1498Szrj #include "lra-int.h"
12338fd1498Szrj #include "print-rtl.h"
12438fd1498Szrj
12538fd1498Szrj /* Dump bitmap SET with TITLE and BB INDEX. */
12638fd1498Szrj void
lra_dump_bitmap_with_title(const char * title,bitmap set,int index)12738fd1498Szrj lra_dump_bitmap_with_title (const char *title, bitmap set, int index)
12838fd1498Szrj {
12938fd1498Szrj unsigned int i;
13038fd1498Szrj int count;
13138fd1498Szrj bitmap_iterator bi;
13238fd1498Szrj static const int max_nums_on_line = 10;
13338fd1498Szrj
13438fd1498Szrj if (bitmap_empty_p (set))
13538fd1498Szrj return;
13638fd1498Szrj fprintf (lra_dump_file, " %s %d:", title, index);
13738fd1498Szrj fprintf (lra_dump_file, "\n");
13838fd1498Szrj count = max_nums_on_line + 1;
13938fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
14038fd1498Szrj {
14138fd1498Szrj if (count > max_nums_on_line)
14238fd1498Szrj {
14338fd1498Szrj fprintf (lra_dump_file, "\n ");
14438fd1498Szrj count = 0;
14538fd1498Szrj }
14638fd1498Szrj fprintf (lra_dump_file, " %4u", i);
14738fd1498Szrj count++;
14838fd1498Szrj }
14938fd1498Szrj fprintf (lra_dump_file, "\n");
15038fd1498Szrj }
15138fd1498Szrj
15238fd1498Szrj /* Hard registers currently not available for allocation. It can
15338fd1498Szrj changed after some hard registers become not eliminable. */
15438fd1498Szrj HARD_REG_SET lra_no_alloc_regs;
15538fd1498Szrj
15638fd1498Szrj static int get_new_reg_value (void);
15738fd1498Szrj static void expand_reg_info (void);
15838fd1498Szrj static void invalidate_insn_recog_data (int);
15938fd1498Szrj static int get_insn_freq (rtx_insn *);
16038fd1498Szrj static void invalidate_insn_data_regno_info (lra_insn_recog_data_t,
16138fd1498Szrj rtx_insn *, int);
16238fd1498Szrj
16338fd1498Szrj /* Expand all regno related info needed for LRA. */
16438fd1498Szrj static void
expand_reg_data(int old)16538fd1498Szrj expand_reg_data (int old)
16638fd1498Szrj {
16738fd1498Szrj resize_reg_info ();
16838fd1498Szrj expand_reg_info ();
16938fd1498Szrj ira_expand_reg_equiv ();
17038fd1498Szrj for (int i = (int) max_reg_num () - 1; i >= old; i--)
17138fd1498Szrj lra_change_class (i, ALL_REGS, " Set", true);
17238fd1498Szrj }
17338fd1498Szrj
17438fd1498Szrj /* Create and return a new reg of ORIGINAL mode. If ORIGINAL is NULL
17538fd1498Szrj or of VOIDmode, use MD_MODE for the new reg. Initialize its
17638fd1498Szrj register class to RCLASS. Print message about assigning class
17738fd1498Szrj RCLASS containing new register name TITLE unless it is NULL. Use
17838fd1498Szrj attributes of ORIGINAL if it is a register. The created register
17938fd1498Szrj will have unique held value. */
18038fd1498Szrj rtx
lra_create_new_reg_with_unique_value(machine_mode md_mode,rtx original,enum reg_class rclass,const char * title)18138fd1498Szrj lra_create_new_reg_with_unique_value (machine_mode md_mode, rtx original,
18238fd1498Szrj enum reg_class rclass, const char *title)
18338fd1498Szrj {
18438fd1498Szrj machine_mode mode;
18538fd1498Szrj rtx new_reg;
18638fd1498Szrj
18738fd1498Szrj if (original == NULL_RTX || (mode = GET_MODE (original)) == VOIDmode)
18838fd1498Szrj mode = md_mode;
18938fd1498Szrj lra_assert (mode != VOIDmode);
19038fd1498Szrj new_reg = gen_reg_rtx (mode);
19138fd1498Szrj if (original == NULL_RTX || ! REG_P (original))
19238fd1498Szrj {
19338fd1498Szrj if (lra_dump_file != NULL)
19438fd1498Szrj fprintf (lra_dump_file, " Creating newreg=%i", REGNO (new_reg));
19538fd1498Szrj }
19638fd1498Szrj else
19738fd1498Szrj {
19838fd1498Szrj if (ORIGINAL_REGNO (original) >= FIRST_PSEUDO_REGISTER)
19938fd1498Szrj ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original);
20038fd1498Szrj REG_USERVAR_P (new_reg) = REG_USERVAR_P (original);
20138fd1498Szrj REG_POINTER (new_reg) = REG_POINTER (original);
20238fd1498Szrj REG_ATTRS (new_reg) = REG_ATTRS (original);
20338fd1498Szrj if (lra_dump_file != NULL)
20438fd1498Szrj fprintf (lra_dump_file, " Creating newreg=%i from oldreg=%i",
20538fd1498Szrj REGNO (new_reg), REGNO (original));
20638fd1498Szrj }
20738fd1498Szrj if (lra_dump_file != NULL)
20838fd1498Szrj {
20938fd1498Szrj if (title != NULL)
21038fd1498Szrj fprintf (lra_dump_file, ", assigning class %s to%s%s r%d",
21138fd1498Szrj reg_class_names[rclass], *title == '\0' ? "" : " ",
21238fd1498Szrj title, REGNO (new_reg));
21338fd1498Szrj fprintf (lra_dump_file, "\n");
21438fd1498Szrj }
21538fd1498Szrj expand_reg_data (max_reg_num ());
21638fd1498Szrj setup_reg_classes (REGNO (new_reg), rclass, NO_REGS, rclass);
21738fd1498Szrj return new_reg;
21838fd1498Szrj }
21938fd1498Szrj
22038fd1498Szrj /* Analogous to the previous function but also inherits value of
22138fd1498Szrj ORIGINAL. */
22238fd1498Szrj rtx
lra_create_new_reg(machine_mode md_mode,rtx original,enum reg_class rclass,const char * title)22338fd1498Szrj lra_create_new_reg (machine_mode md_mode, rtx original,
22438fd1498Szrj enum reg_class rclass, const char *title)
22538fd1498Szrj {
22638fd1498Szrj rtx new_reg;
22738fd1498Szrj
22838fd1498Szrj new_reg
22938fd1498Szrj = lra_create_new_reg_with_unique_value (md_mode, original, rclass, title);
23038fd1498Szrj if (original != NULL_RTX && REG_P (original))
23138fd1498Szrj lra_assign_reg_val (REGNO (original), REGNO (new_reg));
23238fd1498Szrj return new_reg;
23338fd1498Szrj }
23438fd1498Szrj
23538fd1498Szrj /* Set up for REGNO unique hold value. */
23638fd1498Szrj void
lra_set_regno_unique_value(int regno)23738fd1498Szrj lra_set_regno_unique_value (int regno)
23838fd1498Szrj {
23938fd1498Szrj lra_reg_info[regno].val = get_new_reg_value ();
24038fd1498Szrj }
24138fd1498Szrj
24238fd1498Szrj /* Invalidate INSN related info used by LRA. The info should never be
24338fd1498Szrj used after that. */
24438fd1498Szrj void
lra_invalidate_insn_data(rtx_insn * insn)24538fd1498Szrj lra_invalidate_insn_data (rtx_insn *insn)
24638fd1498Szrj {
24738fd1498Szrj lra_invalidate_insn_regno_info (insn);
24838fd1498Szrj invalidate_insn_recog_data (INSN_UID (insn));
24938fd1498Szrj }
25038fd1498Szrj
25138fd1498Szrj /* Mark INSN deleted and invalidate the insn related info used by
25238fd1498Szrj LRA. */
25338fd1498Szrj void
lra_set_insn_deleted(rtx_insn * insn)25438fd1498Szrj lra_set_insn_deleted (rtx_insn *insn)
25538fd1498Szrj {
25638fd1498Szrj lra_invalidate_insn_data (insn);
25738fd1498Szrj SET_INSN_DELETED (insn);
25838fd1498Szrj }
25938fd1498Szrj
26038fd1498Szrj /* Delete an unneeded INSN and any previous insns who sole purpose is
26138fd1498Szrj loading data that is dead in INSN. */
26238fd1498Szrj void
lra_delete_dead_insn(rtx_insn * insn)26338fd1498Szrj lra_delete_dead_insn (rtx_insn *insn)
26438fd1498Szrj {
26538fd1498Szrj rtx_insn *prev = prev_real_insn (insn);
26638fd1498Szrj rtx prev_dest;
26738fd1498Szrj
26838fd1498Szrj /* If the previous insn sets a register that dies in our insn,
26938fd1498Szrj delete it too. */
27038fd1498Szrj if (prev && GET_CODE (PATTERN (prev)) == SET
27138fd1498Szrj && (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest))
27238fd1498Szrj && reg_mentioned_p (prev_dest, PATTERN (insn))
27338fd1498Szrj && find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
27438fd1498Szrj && ! side_effects_p (SET_SRC (PATTERN (prev))))
27538fd1498Szrj lra_delete_dead_insn (prev);
27638fd1498Szrj
27738fd1498Szrj lra_set_insn_deleted (insn);
27838fd1498Szrj }
27938fd1498Szrj
28038fd1498Szrj /* Emit insn x = y + z. Return NULL if we failed to do it.
28138fd1498Szrj Otherwise, return the insn. We don't use gen_add3_insn as it might
28238fd1498Szrj clobber CC. */
28338fd1498Szrj static rtx_insn *
emit_add3_insn(rtx x,rtx y,rtx z)28438fd1498Szrj emit_add3_insn (rtx x, rtx y, rtx z)
28538fd1498Szrj {
28638fd1498Szrj rtx_insn *last;
28738fd1498Szrj
28838fd1498Szrj last = get_last_insn ();
28938fd1498Szrj
29038fd1498Szrj if (have_addptr3_insn (x, y, z))
29138fd1498Szrj {
29238fd1498Szrj rtx_insn *insn = gen_addptr3_insn (x, y, z);
29338fd1498Szrj
29438fd1498Szrj /* If the target provides an "addptr" pattern it hopefully does
29538fd1498Szrj for a reason. So falling back to the normal add would be
29638fd1498Szrj a bug. */
29738fd1498Szrj lra_assert (insn != NULL_RTX);
29838fd1498Szrj emit_insn (insn);
29938fd1498Szrj return insn;
30038fd1498Szrj }
30138fd1498Szrj
30238fd1498Szrj rtx_insn *insn = emit_insn (gen_rtx_SET (x, gen_rtx_PLUS (GET_MODE (y),
30338fd1498Szrj y, z)));
30438fd1498Szrj if (recog_memoized (insn) < 0)
30538fd1498Szrj {
30638fd1498Szrj delete_insns_since (last);
30738fd1498Szrj insn = NULL;
30838fd1498Szrj }
30938fd1498Szrj return insn;
31038fd1498Szrj }
31138fd1498Szrj
31238fd1498Szrj /* Emit insn x = x + y. Return the insn. We use gen_add2_insn as the
31338fd1498Szrj last resort. */
31438fd1498Szrj static rtx_insn *
emit_add2_insn(rtx x,rtx y)31538fd1498Szrj emit_add2_insn (rtx x, rtx y)
31638fd1498Szrj {
31738fd1498Szrj rtx_insn *insn = emit_add3_insn (x, x, y);
31838fd1498Szrj if (insn == NULL_RTX)
31938fd1498Szrj {
32038fd1498Szrj insn = gen_add2_insn (x, y);
32138fd1498Szrj if (insn != NULL_RTX)
32238fd1498Szrj emit_insn (insn);
32338fd1498Szrj }
32438fd1498Szrj return insn;
32538fd1498Szrj }
32638fd1498Szrj
32738fd1498Szrj /* Target checks operands through operand predicates to recognize an
32838fd1498Szrj insn. We should have a special precaution to generate add insns
32938fd1498Szrj which are frequent results of elimination.
33038fd1498Szrj
33138fd1498Szrj Emit insns for x = y + z. X can be used to store intermediate
33238fd1498Szrj values and should be not in Y and Z when we use X to store an
33338fd1498Szrj intermediate value. Y + Z should form [base] [+ index[ * scale]] [
33438fd1498Szrj + disp] where base and index are registers, disp and scale are
33538fd1498Szrj constants. Y should contain base if it is present, Z should
33638fd1498Szrj contain disp if any. index[*scale] can be part of Y or Z. */
33738fd1498Szrj void
lra_emit_add(rtx x,rtx y,rtx z)33838fd1498Szrj lra_emit_add (rtx x, rtx y, rtx z)
33938fd1498Szrj {
34038fd1498Szrj int old;
34138fd1498Szrj rtx_insn *last;
34238fd1498Szrj rtx a1, a2, base, index, disp, scale, index_scale;
34338fd1498Szrj bool ok_p;
34438fd1498Szrj
34538fd1498Szrj rtx_insn *add3_insn = emit_add3_insn (x, y, z);
34638fd1498Szrj old = max_reg_num ();
34738fd1498Szrj if (add3_insn != NULL)
34838fd1498Szrj ;
34938fd1498Szrj else
35038fd1498Szrj {
35138fd1498Szrj disp = a2 = NULL_RTX;
35238fd1498Szrj if (GET_CODE (y) == PLUS)
35338fd1498Szrj {
35438fd1498Szrj a1 = XEXP (y, 0);
35538fd1498Szrj a2 = XEXP (y, 1);
35638fd1498Szrj disp = z;
35738fd1498Szrj }
35838fd1498Szrj else
35938fd1498Szrj {
36038fd1498Szrj a1 = y;
36138fd1498Szrj if (CONSTANT_P (z))
36238fd1498Szrj disp = z;
36338fd1498Szrj else
36438fd1498Szrj a2 = z;
36538fd1498Szrj }
36638fd1498Szrj index_scale = scale = NULL_RTX;
36738fd1498Szrj if (GET_CODE (a1) == MULT)
36838fd1498Szrj {
36938fd1498Szrj index_scale = a1;
37038fd1498Szrj index = XEXP (a1, 0);
37138fd1498Szrj scale = XEXP (a1, 1);
37238fd1498Szrj base = a2;
37338fd1498Szrj }
37438fd1498Szrj else if (a2 != NULL_RTX && GET_CODE (a2) == MULT)
37538fd1498Szrj {
37638fd1498Szrj index_scale = a2;
37738fd1498Szrj index = XEXP (a2, 0);
37838fd1498Szrj scale = XEXP (a2, 1);
37938fd1498Szrj base = a1;
38038fd1498Szrj }
38138fd1498Szrj else
38238fd1498Szrj {
38338fd1498Szrj base = a1;
38438fd1498Szrj index = a2;
38538fd1498Szrj }
38638fd1498Szrj if ((base != NULL_RTX && ! (REG_P (base) || GET_CODE (base) == SUBREG))
38738fd1498Szrj || (index != NULL_RTX
38838fd1498Szrj && ! (REG_P (index) || GET_CODE (index) == SUBREG))
38938fd1498Szrj || (disp != NULL_RTX && ! CONSTANT_P (disp))
39038fd1498Szrj || (scale != NULL_RTX && ! CONSTANT_P (scale)))
39138fd1498Szrj {
39238fd1498Szrj /* Probably we have no 3 op add. Last chance is to use 2-op
39338fd1498Szrj add insn. To succeed, don't move Z to X as an address
39438fd1498Szrj segment always comes in Y. Otherwise, we might fail when
39538fd1498Szrj adding the address segment to register. */
39638fd1498Szrj lra_assert (x != y && x != z);
39738fd1498Szrj emit_move_insn (x, y);
39838fd1498Szrj rtx_insn *insn = emit_add2_insn (x, z);
39938fd1498Szrj lra_assert (insn != NULL_RTX);
40038fd1498Szrj }
40138fd1498Szrj else
40238fd1498Szrj {
40338fd1498Szrj if (index_scale == NULL_RTX)
40438fd1498Szrj index_scale = index;
40538fd1498Szrj if (disp == NULL_RTX)
40638fd1498Szrj {
40738fd1498Szrj /* Generate x = index_scale; x = x + base. */
40838fd1498Szrj lra_assert (index_scale != NULL_RTX && base != NULL_RTX);
40938fd1498Szrj emit_move_insn (x, index_scale);
41038fd1498Szrj rtx_insn *insn = emit_add2_insn (x, base);
41138fd1498Szrj lra_assert (insn != NULL_RTX);
41238fd1498Szrj }
41338fd1498Szrj else if (scale == NULL_RTX)
41438fd1498Szrj {
41538fd1498Szrj /* Try x = base + disp. */
41638fd1498Szrj lra_assert (base != NULL_RTX);
41738fd1498Szrj last = get_last_insn ();
41838fd1498Szrj rtx_insn *move_insn =
41938fd1498Szrj emit_move_insn (x, gen_rtx_PLUS (GET_MODE (base), base, disp));
42038fd1498Szrj if (recog_memoized (move_insn) < 0)
42138fd1498Szrj {
42238fd1498Szrj delete_insns_since (last);
42338fd1498Szrj /* Generate x = disp; x = x + base. */
42438fd1498Szrj emit_move_insn (x, disp);
42538fd1498Szrj rtx_insn *add2_insn = emit_add2_insn (x, base);
42638fd1498Szrj lra_assert (add2_insn != NULL_RTX);
42738fd1498Szrj }
42838fd1498Szrj /* Generate x = x + index. */
42938fd1498Szrj if (index != NULL_RTX)
43038fd1498Szrj {
43138fd1498Szrj rtx_insn *insn = emit_add2_insn (x, index);
43238fd1498Szrj lra_assert (insn != NULL_RTX);
43338fd1498Szrj }
43438fd1498Szrj }
43538fd1498Szrj else
43638fd1498Szrj {
43738fd1498Szrj /* Try x = index_scale; x = x + disp; x = x + base. */
43838fd1498Szrj last = get_last_insn ();
43938fd1498Szrj rtx_insn *move_insn = emit_move_insn (x, index_scale);
44038fd1498Szrj ok_p = false;
44138fd1498Szrj if (recog_memoized (move_insn) >= 0)
44238fd1498Szrj {
44338fd1498Szrj rtx_insn *insn = emit_add2_insn (x, disp);
44438fd1498Szrj if (insn != NULL_RTX)
44538fd1498Szrj {
44638fd1498Szrj if (base == NULL_RTX)
44738fd1498Szrj ok_p = true;
44838fd1498Szrj else
44938fd1498Szrj {
45038fd1498Szrj insn = emit_add2_insn (x, base);
45138fd1498Szrj if (insn != NULL_RTX)
45238fd1498Szrj ok_p = true;
45338fd1498Szrj }
45438fd1498Szrj }
45538fd1498Szrj }
45638fd1498Szrj if (! ok_p)
45738fd1498Szrj {
45838fd1498Szrj rtx_insn *insn;
45938fd1498Szrj
46038fd1498Szrj delete_insns_since (last);
46138fd1498Szrj /* Generate x = disp; x = x + base; x = x + index_scale. */
46238fd1498Szrj emit_move_insn (x, disp);
46338fd1498Szrj if (base != NULL_RTX)
46438fd1498Szrj {
46538fd1498Szrj insn = emit_add2_insn (x, base);
46638fd1498Szrj lra_assert (insn != NULL_RTX);
46738fd1498Szrj }
46838fd1498Szrj insn = emit_add2_insn (x, index_scale);
46938fd1498Szrj lra_assert (insn != NULL_RTX);
47038fd1498Szrj }
47138fd1498Szrj }
47238fd1498Szrj }
47338fd1498Szrj }
47438fd1498Szrj /* Functions emit_... can create pseudos -- so expand the pseudo
47538fd1498Szrj data. */
47638fd1498Szrj if (old != max_reg_num ())
47738fd1498Szrj expand_reg_data (old);
47838fd1498Szrj }
47938fd1498Szrj
48038fd1498Szrj /* The number of emitted reload insns so far. */
48138fd1498Szrj int lra_curr_reload_num;
48238fd1498Szrj
48338fd1498Szrj /* Emit x := y, processing special case when y = u + v or y = u + v *
48438fd1498Szrj scale + w through emit_add (Y can be an address which is base +
48538fd1498Szrj index reg * scale + displacement in general case). X may be used
48638fd1498Szrj as intermediate result therefore it should be not in Y. */
48738fd1498Szrj void
lra_emit_move(rtx x,rtx y)48838fd1498Szrj lra_emit_move (rtx x, rtx y)
48938fd1498Szrj {
49038fd1498Szrj int old;
49138fd1498Szrj
49238fd1498Szrj if (GET_CODE (y) != PLUS)
49338fd1498Szrj {
49438fd1498Szrj if (rtx_equal_p (x, y))
49538fd1498Szrj return;
49638fd1498Szrj old = max_reg_num ();
49738fd1498Szrj emit_move_insn (x, y);
49838fd1498Szrj if (REG_P (x))
49938fd1498Szrj lra_reg_info[ORIGINAL_REGNO (x)].last_reload = ++lra_curr_reload_num;
50038fd1498Szrj /* Function emit_move can create pseudos -- so expand the pseudo
50138fd1498Szrj data. */
50238fd1498Szrj if (old != max_reg_num ())
50338fd1498Szrj expand_reg_data (old);
50438fd1498Szrj return;
50538fd1498Szrj }
50638fd1498Szrj lra_emit_add (x, XEXP (y, 0), XEXP (y, 1));
50738fd1498Szrj }
50838fd1498Szrj
50938fd1498Szrj /* Update insn operands which are duplication of operands whose
51038fd1498Szrj numbers are in array of NOPS (with end marker -1). The insn is
51138fd1498Szrj represented by its LRA internal representation ID. */
51238fd1498Szrj void
lra_update_dups(lra_insn_recog_data_t id,signed char * nops)51338fd1498Szrj lra_update_dups (lra_insn_recog_data_t id, signed char *nops)
51438fd1498Szrj {
51538fd1498Szrj int i, j, nop;
51638fd1498Szrj struct lra_static_insn_data *static_id = id->insn_static_data;
51738fd1498Szrj
51838fd1498Szrj for (i = 0; i < static_id->n_dups; i++)
51938fd1498Szrj for (j = 0; (nop = nops[j]) >= 0; j++)
52038fd1498Szrj if (static_id->dup_num[i] == nop)
52138fd1498Szrj *id->dup_loc[i] = *id->operand_loc[nop];
52238fd1498Szrj }
52338fd1498Szrj
52438fd1498Szrj
52538fd1498Szrj
52638fd1498Szrj /* This page contains code dealing with info about registers in the
52738fd1498Szrj insns. */
52838fd1498Szrj
52938fd1498Szrj /* Pools for insn reg info. */
53038fd1498Szrj object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
53138fd1498Szrj
53238fd1498Szrj /* Create LRA insn related info about a reference to REGNO in INSN
53338fd1498Szrj with TYPE (in/out/inout), biggest reference mode MODE, flag that it
53438fd1498Szrj is reference through subreg (SUBREG_P), flag that is early
53538fd1498Szrj clobbered in the insn (EARLY_CLOBBER), and reference to the next
53638fd1498Szrj insn reg info (NEXT). If REGNO can be early clobbered,
53738fd1498Szrj alternatives in which it can be early clobbered are given by
53838fd1498Szrj EARLY_CLOBBER_ALTS. */
53938fd1498Szrj static struct lra_insn_reg *
new_insn_reg(rtx_insn * insn,int regno,enum op_type type,machine_mode mode,bool subreg_p,bool early_clobber,alternative_mask early_clobber_alts,struct lra_insn_reg * next)54038fd1498Szrj new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
54138fd1498Szrj machine_mode mode,
54238fd1498Szrj bool subreg_p, bool early_clobber,
54338fd1498Szrj alternative_mask early_clobber_alts,
54438fd1498Szrj struct lra_insn_reg *next)
54538fd1498Szrj {
54638fd1498Szrj lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
54738fd1498Szrj ir->type = type;
54838fd1498Szrj ir->biggest_mode = mode;
54938fd1498Szrj if (NONDEBUG_INSN_P (insn)
55038fd1498Szrj && partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
55138fd1498Szrj lra_reg_info[regno].biggest_mode = mode;
55238fd1498Szrj ir->subreg_p = subreg_p;
55338fd1498Szrj ir->early_clobber = early_clobber;
55438fd1498Szrj ir->early_clobber_alts = early_clobber_alts;
55538fd1498Szrj ir->regno = regno;
55638fd1498Szrj ir->next = next;
55738fd1498Szrj return ir;
55838fd1498Szrj }
55938fd1498Szrj
56038fd1498Szrj /* Free insn reg info list IR. */
56138fd1498Szrj static void
free_insn_regs(struct lra_insn_reg * ir)56238fd1498Szrj free_insn_regs (struct lra_insn_reg *ir)
56338fd1498Szrj {
56438fd1498Szrj struct lra_insn_reg *next_ir;
56538fd1498Szrj
56638fd1498Szrj for (; ir != NULL; ir = next_ir)
56738fd1498Szrj {
56838fd1498Szrj next_ir = ir->next;
56938fd1498Szrj lra_insn_reg_pool.remove (ir);
57038fd1498Szrj }
57138fd1498Szrj }
57238fd1498Szrj
57338fd1498Szrj /* Finish pool for insn reg info. */
57438fd1498Szrj static void
finish_insn_regs(void)57538fd1498Szrj finish_insn_regs (void)
57638fd1498Szrj {
57738fd1498Szrj lra_insn_reg_pool.release ();
57838fd1498Szrj }
57938fd1498Szrj
58038fd1498Szrj
58138fd1498Szrj
58238fd1498Szrj /* This page contains code dealing LRA insn info (or in other words
58338fd1498Szrj LRA internal insn representation). */
58438fd1498Szrj
58538fd1498Szrj /* Map INSN_CODE -> the static insn data. This info is valid during
58638fd1498Szrj all translation unit. */
58738fd1498Szrj struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES];
58838fd1498Szrj
58938fd1498Szrj /* Debug insns are represented as a special insn with one input
59038fd1498Szrj operand which is RTL expression in var_location. */
59138fd1498Szrj
59238fd1498Szrj /* The following data are used as static insn operand data for all
59338fd1498Szrj debug insns. If structure lra_operand_data is changed, the
59438fd1498Szrj initializer should be changed too. */
59538fd1498Szrj static struct lra_operand_data debug_operand_data =
59638fd1498Szrj {
59738fd1498Szrj NULL, /* alternative */
59838fd1498Szrj 0, /* early_clobber_alts */
59938fd1498Szrj E_VOIDmode, /* We are not interesting in the operand mode. */
60038fd1498Szrj OP_IN,
60138fd1498Szrj 0, 0, 0, 0
60238fd1498Szrj };
60338fd1498Szrj
60438fd1498Szrj /* The following data are used as static insn data for all debug
60538fd1498Szrj bind insns. If structure lra_static_insn_data is changed, the
60638fd1498Szrj initializer should be changed too. */
60738fd1498Szrj static struct lra_static_insn_data debug_bind_static_data =
60838fd1498Szrj {
60938fd1498Szrj &debug_operand_data,
61038fd1498Szrj 0, /* Duplication operands #. */
61138fd1498Szrj -1, /* Commutative operand #. */
61238fd1498Szrj 1, /* Operands #. There is only one operand which is debug RTL
61338fd1498Szrj expression. */
61438fd1498Szrj 0, /* Duplications #. */
61538fd1498Szrj 0, /* Alternatives #. We are not interesting in alternatives
61638fd1498Szrj because we does not proceed debug_insns for reloads. */
61738fd1498Szrj NULL, /* Hard registers referenced in machine description. */
61838fd1498Szrj NULL /* Descriptions of operands in alternatives. */
61938fd1498Szrj };
62038fd1498Szrj
62138fd1498Szrj /* The following data are used as static insn data for all debug
62238fd1498Szrj marker insns. If structure lra_static_insn_data is changed, the
62338fd1498Szrj initializer should be changed too. */
62438fd1498Szrj static struct lra_static_insn_data debug_marker_static_data =
62538fd1498Szrj {
62638fd1498Szrj &debug_operand_data,
62738fd1498Szrj 0, /* Duplication operands #. */
62838fd1498Szrj -1, /* Commutative operand #. */
62938fd1498Szrj 0, /* Operands #. There isn't any operand. */
63038fd1498Szrj 0, /* Duplications #. */
63138fd1498Szrj 0, /* Alternatives #. We are not interesting in alternatives
63238fd1498Szrj because we does not proceed debug_insns for reloads. */
63338fd1498Szrj NULL, /* Hard registers referenced in machine description. */
63438fd1498Szrj NULL /* Descriptions of operands in alternatives. */
63538fd1498Szrj };
63638fd1498Szrj
63738fd1498Szrj /* Called once per compiler work to initialize some LRA data related
63838fd1498Szrj to insns. */
63938fd1498Szrj static void
init_insn_code_data_once(void)64038fd1498Szrj init_insn_code_data_once (void)
64138fd1498Szrj {
64238fd1498Szrj memset (insn_code_data, 0, sizeof (insn_code_data));
64338fd1498Szrj }
64438fd1498Szrj
64538fd1498Szrj /* Called once per compiler work to finalize some LRA data related to
64638fd1498Szrj insns. */
64738fd1498Szrj static void
finish_insn_code_data_once(void)64838fd1498Szrj finish_insn_code_data_once (void)
64938fd1498Szrj {
65038fd1498Szrj for (unsigned int i = 0; i < NUM_INSN_CODES; i++)
65138fd1498Szrj {
65238fd1498Szrj if (insn_code_data[i] != NULL)
65338fd1498Szrj free (insn_code_data[i]);
65438fd1498Szrj }
65538fd1498Szrj }
65638fd1498Szrj
65738fd1498Szrj /* Return static insn data, allocate and setup if necessary. Although
65838fd1498Szrj dup_num is static data (it depends only on icode), to set it up we
65938fd1498Szrj need to extract insn first. So recog_data should be valid for
66038fd1498Szrj normal insn (ICODE >= 0) before the call. */
66138fd1498Szrj static struct lra_static_insn_data *
get_static_insn_data(int icode,int nop,int ndup,int nalt)66238fd1498Szrj get_static_insn_data (int icode, int nop, int ndup, int nalt)
66338fd1498Szrj {
66438fd1498Szrj struct lra_static_insn_data *data;
66538fd1498Szrj size_t n_bytes;
66638fd1498Szrj
66738fd1498Szrj lra_assert (icode < (int) NUM_INSN_CODES);
66838fd1498Szrj if (icode >= 0 && (data = insn_code_data[icode]) != NULL)
66938fd1498Szrj return data;
67038fd1498Szrj lra_assert (nop >= 0 && ndup >= 0 && nalt >= 0);
67138fd1498Szrj n_bytes = sizeof (struct lra_static_insn_data)
67238fd1498Szrj + sizeof (struct lra_operand_data) * nop
67338fd1498Szrj + sizeof (int) * ndup;
67438fd1498Szrj data = XNEWVAR (struct lra_static_insn_data, n_bytes);
67538fd1498Szrj data->operand_alternative = NULL;
67638fd1498Szrj data->n_operands = nop;
67738fd1498Szrj data->n_dups = ndup;
67838fd1498Szrj data->n_alternatives = nalt;
67938fd1498Szrj data->operand = ((struct lra_operand_data *)
68038fd1498Szrj ((char *) data + sizeof (struct lra_static_insn_data)));
68138fd1498Szrj data->dup_num = ((int *) ((char *) data->operand
68238fd1498Szrj + sizeof (struct lra_operand_data) * nop));
68338fd1498Szrj if (icode >= 0)
68438fd1498Szrj {
68538fd1498Szrj int i;
68638fd1498Szrj
68738fd1498Szrj insn_code_data[icode] = data;
68838fd1498Szrj for (i = 0; i < nop; i++)
68938fd1498Szrj {
69038fd1498Szrj data->operand[i].constraint
69138fd1498Szrj = insn_data[icode].operand[i].constraint;
69238fd1498Szrj data->operand[i].mode = insn_data[icode].operand[i].mode;
69338fd1498Szrj data->operand[i].strict_low = insn_data[icode].operand[i].strict_low;
69438fd1498Szrj data->operand[i].is_operator
69538fd1498Szrj = insn_data[icode].operand[i].is_operator;
69638fd1498Szrj data->operand[i].type
69738fd1498Szrj = (data->operand[i].constraint[0] == '=' ? OP_OUT
69838fd1498Szrj : data->operand[i].constraint[0] == '+' ? OP_INOUT
69938fd1498Szrj : OP_IN);
70038fd1498Szrj data->operand[i].is_address = false;
70138fd1498Szrj }
70238fd1498Szrj for (i = 0; i < ndup; i++)
70338fd1498Szrj data->dup_num[i] = recog_data.dup_num[i];
70438fd1498Szrj }
70538fd1498Szrj return data;
70638fd1498Szrj }
70738fd1498Szrj
70838fd1498Szrj /* The current length of the following array. */
70938fd1498Szrj int lra_insn_recog_data_len;
71038fd1498Szrj
71138fd1498Szrj /* Map INSN_UID -> the insn recog data (NULL if unknown). */
71238fd1498Szrj lra_insn_recog_data_t *lra_insn_recog_data;
71338fd1498Szrj
71438fd1498Szrj /* Initialize LRA data about insns. */
71538fd1498Szrj static void
init_insn_recog_data(void)71638fd1498Szrj init_insn_recog_data (void)
71738fd1498Szrj {
71838fd1498Szrj lra_insn_recog_data_len = 0;
71938fd1498Szrj lra_insn_recog_data = NULL;
72038fd1498Szrj }
72138fd1498Szrj
72238fd1498Szrj /* Expand, if necessary, LRA data about insns. */
72338fd1498Szrj static void
check_and_expand_insn_recog_data(int index)72438fd1498Szrj check_and_expand_insn_recog_data (int index)
72538fd1498Szrj {
72638fd1498Szrj int i, old;
72738fd1498Szrj
72838fd1498Szrj if (lra_insn_recog_data_len > index)
72938fd1498Szrj return;
73038fd1498Szrj old = lra_insn_recog_data_len;
73138fd1498Szrj lra_insn_recog_data_len = index * 3 / 2 + 1;
73238fd1498Szrj lra_insn_recog_data = XRESIZEVEC (lra_insn_recog_data_t,
73338fd1498Szrj lra_insn_recog_data,
73438fd1498Szrj lra_insn_recog_data_len);
73538fd1498Szrj for (i = old; i < lra_insn_recog_data_len; i++)
73638fd1498Szrj lra_insn_recog_data[i] = NULL;
73738fd1498Szrj }
73838fd1498Szrj
73938fd1498Szrj /* Finish LRA DATA about insn. */
74038fd1498Szrj static void
free_insn_recog_data(lra_insn_recog_data_t data)74138fd1498Szrj free_insn_recog_data (lra_insn_recog_data_t data)
74238fd1498Szrj {
74338fd1498Szrj if (data->operand_loc != NULL)
74438fd1498Szrj free (data->operand_loc);
74538fd1498Szrj if (data->dup_loc != NULL)
74638fd1498Szrj free (data->dup_loc);
74738fd1498Szrj if (data->arg_hard_regs != NULL)
74838fd1498Szrj free (data->arg_hard_regs);
74938fd1498Szrj if (data->icode < 0 && NONDEBUG_INSN_P (data->insn))
75038fd1498Szrj {
75138fd1498Szrj if (data->insn_static_data->operand_alternative != NULL)
75238fd1498Szrj free (const_cast <operand_alternative *>
75338fd1498Szrj (data->insn_static_data->operand_alternative));
75438fd1498Szrj free_insn_regs (data->insn_static_data->hard_regs);
75538fd1498Szrj free (data->insn_static_data);
75638fd1498Szrj }
75738fd1498Szrj free_insn_regs (data->regs);
75838fd1498Szrj data->regs = NULL;
75938fd1498Szrj free (data);
76038fd1498Szrj }
76138fd1498Szrj
76238fd1498Szrj /* Pools for copies. */
76338fd1498Szrj static object_allocator<lra_copy> lra_copy_pool ("lra copies");
76438fd1498Szrj
76538fd1498Szrj /* Finish LRA data about all insns. */
76638fd1498Szrj static void
finish_insn_recog_data(void)76738fd1498Szrj finish_insn_recog_data (void)
76838fd1498Szrj {
76938fd1498Szrj int i;
77038fd1498Szrj lra_insn_recog_data_t data;
77138fd1498Szrj
77238fd1498Szrj for (i = 0; i < lra_insn_recog_data_len; i++)
77338fd1498Szrj if ((data = lra_insn_recog_data[i]) != NULL)
77438fd1498Szrj free_insn_recog_data (data);
77538fd1498Szrj finish_insn_regs ();
77638fd1498Szrj lra_copy_pool.release ();
77738fd1498Szrj lra_insn_reg_pool.release ();
77838fd1498Szrj free (lra_insn_recog_data);
77938fd1498Szrj }
78038fd1498Szrj
78138fd1498Szrj /* Setup info about operands in alternatives of LRA DATA of insn. */
78238fd1498Szrj static void
setup_operand_alternative(lra_insn_recog_data_t data,const operand_alternative * op_alt)78338fd1498Szrj setup_operand_alternative (lra_insn_recog_data_t data,
78438fd1498Szrj const operand_alternative *op_alt)
78538fd1498Szrj {
78638fd1498Szrj int i, j, nop, nalt;
78738fd1498Szrj int icode = data->icode;
78838fd1498Szrj struct lra_static_insn_data *static_data = data->insn_static_data;
78938fd1498Szrj
79038fd1498Szrj static_data->commutative = -1;
79138fd1498Szrj nop = static_data->n_operands;
79238fd1498Szrj nalt = static_data->n_alternatives;
79338fd1498Szrj static_data->operand_alternative = op_alt;
79438fd1498Szrj for (i = 0; i < nop; i++)
79538fd1498Szrj {
79638fd1498Szrj static_data->operand[i].early_clobber_alts = 0;
79738fd1498Szrj static_data->operand[i].early_clobber = false;
79838fd1498Szrj static_data->operand[i].is_address = false;
79938fd1498Szrj if (static_data->operand[i].constraint[0] == '%')
80038fd1498Szrj {
80138fd1498Szrj /* We currently only support one commutative pair of operands. */
80238fd1498Szrj if (static_data->commutative < 0)
80338fd1498Szrj static_data->commutative = i;
80438fd1498Szrj else
80538fd1498Szrj lra_assert (icode < 0); /* Asm */
80638fd1498Szrj /* The last operand should not be marked commutative. */
80738fd1498Szrj lra_assert (i != nop - 1);
80838fd1498Szrj }
80938fd1498Szrj }
81038fd1498Szrj for (j = 0; j < nalt; j++)
81138fd1498Szrj for (i = 0; i < nop; i++, op_alt++)
81238fd1498Szrj {
81338fd1498Szrj static_data->operand[i].early_clobber |= op_alt->earlyclobber;
81438fd1498Szrj if (op_alt->earlyclobber)
81538fd1498Szrj static_data->operand[i].early_clobber_alts |= (alternative_mask) 1 << j;
81638fd1498Szrj static_data->operand[i].is_address |= op_alt->is_address;
81738fd1498Szrj }
81838fd1498Szrj }
81938fd1498Szrj
82038fd1498Szrj /* Recursively process X and collect info about registers, which are
82138fd1498Szrj not the insn operands, in X with TYPE (in/out/inout) and flag that
82238fd1498Szrj it is early clobbered in the insn (EARLY_CLOBBER) and add the info
82338fd1498Szrj to LIST. X is a part of insn given by DATA. Return the result
82438fd1498Szrj list. */
82538fd1498Szrj static struct lra_insn_reg *
collect_non_operand_hard_regs(rtx_insn * insn,rtx * x,lra_insn_recog_data_t data,struct lra_insn_reg * list,enum op_type type,bool early_clobber)82638fd1498Szrj collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
82738fd1498Szrj lra_insn_recog_data_t data,
82838fd1498Szrj struct lra_insn_reg *list,
82938fd1498Szrj enum op_type type, bool early_clobber)
83038fd1498Szrj {
83138fd1498Szrj int i, j, regno, last;
83238fd1498Szrj bool subreg_p;
83338fd1498Szrj machine_mode mode;
83438fd1498Szrj struct lra_insn_reg *curr;
83538fd1498Szrj rtx op = *x;
83638fd1498Szrj enum rtx_code code = GET_CODE (op);
83738fd1498Szrj const char *fmt = GET_RTX_FORMAT (code);
83838fd1498Szrj
83938fd1498Szrj for (i = 0; i < data->insn_static_data->n_operands; i++)
84038fd1498Szrj if (! data->insn_static_data->operand[i].is_operator
84138fd1498Szrj && x == data->operand_loc[i])
84238fd1498Szrj /* It is an operand loc. Stop here. */
84338fd1498Szrj return list;
84438fd1498Szrj for (i = 0; i < data->insn_static_data->n_dups; i++)
84538fd1498Szrj if (x == data->dup_loc[i])
84638fd1498Szrj /* It is a dup loc. Stop here. */
84738fd1498Szrj return list;
84838fd1498Szrj mode = GET_MODE (op);
84938fd1498Szrj subreg_p = false;
85038fd1498Szrj if (code == SUBREG)
85138fd1498Szrj {
85238fd1498Szrj mode = wider_subreg_mode (op);
85338fd1498Szrj if (read_modify_subreg_p (op))
85438fd1498Szrj subreg_p = true;
85538fd1498Szrj op = SUBREG_REG (op);
85638fd1498Szrj code = GET_CODE (op);
85738fd1498Szrj }
85838fd1498Szrj if (REG_P (op))
85938fd1498Szrj {
86038fd1498Szrj if ((regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER)
86138fd1498Szrj return list;
86238fd1498Szrj /* Process all regs even unallocatable ones as we need info
86338fd1498Szrj about all regs for rematerialization pass. */
86438fd1498Szrj for (last = end_hard_regno (mode, regno); regno < last; regno++)
86538fd1498Szrj {
86638fd1498Szrj for (curr = list; curr != NULL; curr = curr->next)
86738fd1498Szrj if (curr->regno == regno && curr->subreg_p == subreg_p
86838fd1498Szrj && curr->biggest_mode == mode)
86938fd1498Szrj {
87038fd1498Szrj if (curr->type != type)
87138fd1498Szrj curr->type = OP_INOUT;
87238fd1498Szrj if (early_clobber)
87338fd1498Szrj {
87438fd1498Szrj curr->early_clobber = true;
87538fd1498Szrj curr->early_clobber_alts = ALL_ALTERNATIVES;
87638fd1498Szrj }
87738fd1498Szrj break;
87838fd1498Szrj }
87938fd1498Szrj if (curr == NULL)
88038fd1498Szrj {
88138fd1498Szrj /* This is a new hard regno or the info can not be
88238fd1498Szrj integrated into the found structure. */
88338fd1498Szrj #ifdef STACK_REGS
88438fd1498Szrj early_clobber
88538fd1498Szrj = (early_clobber
88638fd1498Szrj /* This clobber is to inform popping floating
88738fd1498Szrj point stack only. */
88838fd1498Szrj && ! (FIRST_STACK_REG <= regno
88938fd1498Szrj && regno <= LAST_STACK_REG));
89038fd1498Szrj #endif
89138fd1498Szrj list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
89238fd1498Szrj early_clobber,
89338fd1498Szrj early_clobber ? ALL_ALTERNATIVES : 0, list);
89438fd1498Szrj }
89538fd1498Szrj }
89638fd1498Szrj return list;
89738fd1498Szrj }
89838fd1498Szrj switch (code)
89938fd1498Szrj {
90038fd1498Szrj case SET:
90138fd1498Szrj list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data,
90238fd1498Szrj list, OP_OUT, false);
90338fd1498Szrj list = collect_non_operand_hard_regs (insn, &SET_SRC (op), data,
90438fd1498Szrj list, OP_IN, false);
90538fd1498Szrj break;
90638fd1498Szrj case CLOBBER:
90738fd1498Szrj /* We treat clobber of non-operand hard registers as early clobber. */
90838fd1498Szrj list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
90938fd1498Szrj list, OP_OUT, true);
91038fd1498Szrj break;
91138fd1498Szrj case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
91238fd1498Szrj list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
91338fd1498Szrj list, OP_INOUT, false);
91438fd1498Szrj break;
91538fd1498Szrj case PRE_MODIFY: case POST_MODIFY:
91638fd1498Szrj list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
91738fd1498Szrj list, OP_INOUT, false);
91838fd1498Szrj list = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data,
91938fd1498Szrj list, OP_IN, false);
92038fd1498Szrj break;
92138fd1498Szrj default:
92238fd1498Szrj fmt = GET_RTX_FORMAT (code);
92338fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
92438fd1498Szrj {
92538fd1498Szrj if (fmt[i] == 'e')
92638fd1498Szrj list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data,
92738fd1498Szrj list, OP_IN, false);
92838fd1498Szrj else if (fmt[i] == 'E')
92938fd1498Szrj for (j = XVECLEN (op, i) - 1; j >= 0; j--)
93038fd1498Szrj list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, j),
93138fd1498Szrj data, list, OP_IN, false);
93238fd1498Szrj }
93338fd1498Szrj }
93438fd1498Szrj return list;
93538fd1498Szrj }
93638fd1498Szrj
93738fd1498Szrj /* Set up and return info about INSN. Set up the info if it is not set up
93838fd1498Szrj yet. */
93938fd1498Szrj lra_insn_recog_data_t
lra_set_insn_recog_data(rtx_insn * insn)94038fd1498Szrj lra_set_insn_recog_data (rtx_insn *insn)
94138fd1498Szrj {
94238fd1498Szrj lra_insn_recog_data_t data;
94338fd1498Szrj int i, n, icode;
94438fd1498Szrj rtx **locs;
94538fd1498Szrj unsigned int uid = INSN_UID (insn);
94638fd1498Szrj struct lra_static_insn_data *insn_static_data;
94738fd1498Szrj
94838fd1498Szrj check_and_expand_insn_recog_data (uid);
94938fd1498Szrj if (DEBUG_INSN_P (insn))
95038fd1498Szrj icode = -1;
95138fd1498Szrj else
95238fd1498Szrj {
95338fd1498Szrj icode = INSN_CODE (insn);
95438fd1498Szrj if (icode < 0)
95538fd1498Szrj /* It might be a new simple insn which is not recognized yet. */
95638fd1498Szrj INSN_CODE (insn) = icode = recog_memoized (insn);
95738fd1498Szrj }
95838fd1498Szrj data = XNEW (struct lra_insn_recog_data);
95938fd1498Szrj lra_insn_recog_data[uid] = data;
96038fd1498Szrj data->insn = insn;
96138fd1498Szrj data->used_insn_alternative = LRA_UNKNOWN_ALT;
96238fd1498Szrj data->icode = icode;
96338fd1498Szrj data->regs = NULL;
96438fd1498Szrj if (DEBUG_INSN_P (insn))
96538fd1498Szrj {
96638fd1498Szrj data->dup_loc = NULL;
96738fd1498Szrj data->arg_hard_regs = NULL;
96838fd1498Szrj data->preferred_alternatives = ALL_ALTERNATIVES;
96938fd1498Szrj if (DEBUG_BIND_INSN_P (insn))
97038fd1498Szrj {
97138fd1498Szrj data->insn_static_data = &debug_bind_static_data;
97238fd1498Szrj data->operand_loc = XNEWVEC (rtx *, 1);
97338fd1498Szrj data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
97438fd1498Szrj }
97538fd1498Szrj else if (DEBUG_MARKER_INSN_P (insn))
97638fd1498Szrj {
97738fd1498Szrj data->insn_static_data = &debug_marker_static_data;
97838fd1498Szrj data->operand_loc = NULL;
97938fd1498Szrj }
98038fd1498Szrj return data;
98138fd1498Szrj }
98238fd1498Szrj if (icode < 0)
98338fd1498Szrj {
98438fd1498Szrj int nop, nalt;
98538fd1498Szrj machine_mode operand_mode[MAX_RECOG_OPERANDS];
98638fd1498Szrj const char *constraints[MAX_RECOG_OPERANDS];
98738fd1498Szrj
98838fd1498Szrj nop = asm_noperands (PATTERN (insn));
98938fd1498Szrj data->operand_loc = data->dup_loc = NULL;
99038fd1498Szrj nalt = 1;
99138fd1498Szrj if (nop < 0)
99238fd1498Szrj {
99338fd1498Szrj /* It is a special insn like USE or CLOBBER. We should
99438fd1498Szrj recognize any regular insn otherwise LRA can do nothing
99538fd1498Szrj with this insn. */
99638fd1498Szrj gcc_assert (GET_CODE (PATTERN (insn)) == USE
99738fd1498Szrj || GET_CODE (PATTERN (insn)) == CLOBBER
99838fd1498Szrj || GET_CODE (PATTERN (insn)) == ASM_INPUT);
99938fd1498Szrj data->insn_static_data = insn_static_data
100038fd1498Szrj = get_static_insn_data (-1, 0, 0, nalt);
100138fd1498Szrj }
100238fd1498Szrj else
100338fd1498Szrj {
100438fd1498Szrj /* expand_asm_operands makes sure there aren't too many
100538fd1498Szrj operands. */
100638fd1498Szrj lra_assert (nop <= MAX_RECOG_OPERANDS);
100738fd1498Szrj if (nop != 0)
100838fd1498Szrj data->operand_loc = XNEWVEC (rtx *, nop);
100938fd1498Szrj /* Now get the operand values and constraints out of the
101038fd1498Szrj insn. */
101138fd1498Szrj decode_asm_operands (PATTERN (insn), NULL,
101238fd1498Szrj data->operand_loc,
101338fd1498Szrj constraints, operand_mode, NULL);
101438fd1498Szrj if (nop > 0)
101538fd1498Szrj {
101638fd1498Szrj const char *p = recog_data.constraints[0];
101738fd1498Szrj
101838fd1498Szrj for (p = constraints[0]; *p; p++)
101938fd1498Szrj nalt += *p == ',';
102038fd1498Szrj }
102138fd1498Szrj data->insn_static_data = insn_static_data
102238fd1498Szrj = get_static_insn_data (-1, nop, 0, nalt);
102338fd1498Szrj for (i = 0; i < nop; i++)
102438fd1498Szrj {
102538fd1498Szrj insn_static_data->operand[i].mode = operand_mode[i];
102638fd1498Szrj insn_static_data->operand[i].constraint = constraints[i];
102738fd1498Szrj insn_static_data->operand[i].strict_low = false;
102838fd1498Szrj insn_static_data->operand[i].is_operator = false;
102938fd1498Szrj insn_static_data->operand[i].is_address = false;
103038fd1498Szrj }
103138fd1498Szrj }
103238fd1498Szrj for (i = 0; i < insn_static_data->n_operands; i++)
103338fd1498Szrj insn_static_data->operand[i].type
103438fd1498Szrj = (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
103538fd1498Szrj : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
103638fd1498Szrj : OP_IN);
103738fd1498Szrj data->preferred_alternatives = ALL_ALTERNATIVES;
103838fd1498Szrj if (nop > 0)
103938fd1498Szrj {
104038fd1498Szrj operand_alternative *op_alt = XCNEWVEC (operand_alternative,
104138fd1498Szrj nalt * nop);
104238fd1498Szrj preprocess_constraints (nop, nalt, constraints, op_alt,
104338fd1498Szrj data->operand_loc);
104438fd1498Szrj setup_operand_alternative (data, op_alt);
104538fd1498Szrj }
104638fd1498Szrj }
104738fd1498Szrj else
104838fd1498Szrj {
104938fd1498Szrj insn_extract (insn);
105038fd1498Szrj data->insn_static_data = insn_static_data
105138fd1498Szrj = get_static_insn_data (icode, insn_data[icode].n_operands,
105238fd1498Szrj insn_data[icode].n_dups,
105338fd1498Szrj insn_data[icode].n_alternatives);
105438fd1498Szrj n = insn_static_data->n_operands;
105538fd1498Szrj if (n == 0)
105638fd1498Szrj locs = NULL;
105738fd1498Szrj else
105838fd1498Szrj {
105938fd1498Szrj locs = XNEWVEC (rtx *, n);
106038fd1498Szrj memcpy (locs, recog_data.operand_loc, n * sizeof (rtx *));
106138fd1498Szrj }
106238fd1498Szrj data->operand_loc = locs;
106338fd1498Szrj n = insn_static_data->n_dups;
106438fd1498Szrj if (n == 0)
106538fd1498Szrj locs = NULL;
106638fd1498Szrj else
106738fd1498Szrj {
106838fd1498Szrj locs = XNEWVEC (rtx *, n);
106938fd1498Szrj memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
107038fd1498Szrj }
107138fd1498Szrj data->dup_loc = locs;
107238fd1498Szrj data->preferred_alternatives = get_preferred_alternatives (insn);
107338fd1498Szrj const operand_alternative *op_alt = preprocess_insn_constraints (icode);
107438fd1498Szrj if (!insn_static_data->operand_alternative)
107538fd1498Szrj setup_operand_alternative (data, op_alt);
107638fd1498Szrj else if (op_alt != insn_static_data->operand_alternative)
107738fd1498Szrj insn_static_data->operand_alternative = op_alt;
107838fd1498Szrj }
107938fd1498Szrj if (GET_CODE (PATTERN (insn)) == CLOBBER || GET_CODE (PATTERN (insn)) == USE)
108038fd1498Szrj insn_static_data->hard_regs = NULL;
108138fd1498Szrj else
108238fd1498Szrj insn_static_data->hard_regs
108338fd1498Szrj = collect_non_operand_hard_regs (insn, &PATTERN (insn), data,
108438fd1498Szrj NULL, OP_IN, false);
108538fd1498Szrj data->arg_hard_regs = NULL;
108638fd1498Szrj if (CALL_P (insn))
108738fd1498Szrj {
108838fd1498Szrj bool use_p;
108938fd1498Szrj rtx link;
109038fd1498Szrj int n_hard_regs, regno, arg_hard_regs[FIRST_PSEUDO_REGISTER];
109138fd1498Szrj
109238fd1498Szrj n_hard_regs = 0;
109338fd1498Szrj /* Finding implicit hard register usage. We believe it will be
109438fd1498Szrj not changed whatever transformations are used. Call insns
109538fd1498Szrj are such example. */
109638fd1498Szrj for (link = CALL_INSN_FUNCTION_USAGE (insn);
109738fd1498Szrj link != NULL_RTX;
109838fd1498Szrj link = XEXP (link, 1))
109938fd1498Szrj if (((use_p = GET_CODE (XEXP (link, 0)) == USE)
110038fd1498Szrj || GET_CODE (XEXP (link, 0)) == CLOBBER)
110138fd1498Szrj && REG_P (XEXP (XEXP (link, 0), 0)))
110238fd1498Szrj {
110338fd1498Szrj regno = REGNO (XEXP (XEXP (link, 0), 0));
110438fd1498Szrj lra_assert (regno < FIRST_PSEUDO_REGISTER);
110538fd1498Szrj /* It is an argument register. */
110638fd1498Szrj for (i = REG_NREGS (XEXP (XEXP (link, 0), 0)) - 1; i >= 0; i--)
110738fd1498Szrj arg_hard_regs[n_hard_regs++]
110838fd1498Szrj = regno + i + (use_p ? 0 : FIRST_PSEUDO_REGISTER);
110938fd1498Szrj }
111038fd1498Szrj if (n_hard_regs != 0)
111138fd1498Szrj {
111238fd1498Szrj arg_hard_regs[n_hard_regs++] = -1;
111338fd1498Szrj data->arg_hard_regs = XNEWVEC (int, n_hard_regs);
111438fd1498Szrj memcpy (data->arg_hard_regs, arg_hard_regs,
111538fd1498Szrj sizeof (int) * n_hard_regs);
111638fd1498Szrj }
111738fd1498Szrj }
111838fd1498Szrj /* Some output operand can be recognized only from the context not
111938fd1498Szrj from the constraints which are empty in this case. Call insn may
112038fd1498Szrj contain a hard register in set destination with empty constraint
112138fd1498Szrj and extract_insn treats them as an input. */
112238fd1498Szrj for (i = 0; i < insn_static_data->n_operands; i++)
112338fd1498Szrj {
112438fd1498Szrj int j;
112538fd1498Szrj rtx pat, set;
112638fd1498Szrj struct lra_operand_data *operand = &insn_static_data->operand[i];
112738fd1498Szrj
112838fd1498Szrj /* ??? Should we treat 'X' the same way. It looks to me that
112938fd1498Szrj 'X' means anything and empty constraint means we do not
113038fd1498Szrj care. */
113138fd1498Szrj if (operand->type != OP_IN || *operand->constraint != '\0'
113238fd1498Szrj || operand->is_operator)
113338fd1498Szrj continue;
113438fd1498Szrj pat = PATTERN (insn);
113538fd1498Szrj if (GET_CODE (pat) == SET)
113638fd1498Szrj {
113738fd1498Szrj if (data->operand_loc[i] != &SET_DEST (pat))
113838fd1498Szrj continue;
113938fd1498Szrj }
114038fd1498Szrj else if (GET_CODE (pat) == PARALLEL)
114138fd1498Szrj {
114238fd1498Szrj for (j = XVECLEN (pat, 0) - 1; j >= 0; j--)
114338fd1498Szrj {
114438fd1498Szrj set = XVECEXP (PATTERN (insn), 0, j);
114538fd1498Szrj if (GET_CODE (set) == SET
114638fd1498Szrj && &SET_DEST (set) == data->operand_loc[i])
114738fd1498Szrj break;
114838fd1498Szrj }
114938fd1498Szrj if (j < 0)
115038fd1498Szrj continue;
115138fd1498Szrj }
115238fd1498Szrj else
115338fd1498Szrj continue;
115438fd1498Szrj operand->type = OP_OUT;
115538fd1498Szrj }
115638fd1498Szrj return data;
115738fd1498Szrj }
115838fd1498Szrj
115938fd1498Szrj /* Return info about insn give by UID. The info should be already set
116038fd1498Szrj up. */
116138fd1498Szrj static lra_insn_recog_data_t
get_insn_recog_data_by_uid(int uid)116238fd1498Szrj get_insn_recog_data_by_uid (int uid)
116338fd1498Szrj {
116438fd1498Szrj lra_insn_recog_data_t data;
116538fd1498Szrj
116638fd1498Szrj data = lra_insn_recog_data[uid];
116738fd1498Szrj lra_assert (data != NULL);
116838fd1498Szrj return data;
116938fd1498Szrj }
117038fd1498Szrj
117138fd1498Szrj /* Invalidate all info about insn given by its UID. */
117238fd1498Szrj static void
invalidate_insn_recog_data(int uid)117338fd1498Szrj invalidate_insn_recog_data (int uid)
117438fd1498Szrj {
117538fd1498Szrj lra_insn_recog_data_t data;
117638fd1498Szrj
117738fd1498Szrj data = lra_insn_recog_data[uid];
117838fd1498Szrj lra_assert (data != NULL);
117938fd1498Szrj free_insn_recog_data (data);
118038fd1498Szrj lra_insn_recog_data[uid] = NULL;
118138fd1498Szrj }
118238fd1498Szrj
118338fd1498Szrj /* Update all the insn info about INSN. It is usually called when
118438fd1498Szrj something in the insn was changed. Return the updated info. */
118538fd1498Szrj lra_insn_recog_data_t
lra_update_insn_recog_data(rtx_insn * insn)118638fd1498Szrj lra_update_insn_recog_data (rtx_insn *insn)
118738fd1498Szrj {
118838fd1498Szrj lra_insn_recog_data_t data;
118938fd1498Szrj int n;
119038fd1498Szrj unsigned int uid = INSN_UID (insn);
119138fd1498Szrj struct lra_static_insn_data *insn_static_data;
119238fd1498Szrj poly_int64 sp_offset = 0;
119338fd1498Szrj
119438fd1498Szrj check_and_expand_insn_recog_data (uid);
119538fd1498Szrj if ((data = lra_insn_recog_data[uid]) != NULL
119638fd1498Szrj && data->icode != INSN_CODE (insn))
119738fd1498Szrj {
119838fd1498Szrj sp_offset = data->sp_offset;
119938fd1498Szrj invalidate_insn_data_regno_info (data, insn, get_insn_freq (insn));
120038fd1498Szrj invalidate_insn_recog_data (uid);
120138fd1498Szrj data = NULL;
120238fd1498Szrj }
120338fd1498Szrj if (data == NULL)
120438fd1498Szrj {
120538fd1498Szrj data = lra_get_insn_recog_data (insn);
120638fd1498Szrj /* Initiate or restore SP offset. */
120738fd1498Szrj data->sp_offset = sp_offset;
120838fd1498Szrj return data;
120938fd1498Szrj }
121038fd1498Szrj insn_static_data = data->insn_static_data;
121138fd1498Szrj data->used_insn_alternative = LRA_UNKNOWN_ALT;
121238fd1498Szrj if (DEBUG_INSN_P (insn))
121338fd1498Szrj return data;
121438fd1498Szrj if (data->icode < 0)
121538fd1498Szrj {
121638fd1498Szrj int nop;
121738fd1498Szrj machine_mode operand_mode[MAX_RECOG_OPERANDS];
121838fd1498Szrj const char *constraints[MAX_RECOG_OPERANDS];
121938fd1498Szrj
122038fd1498Szrj nop = asm_noperands (PATTERN (insn));
122138fd1498Szrj if (nop >= 0)
122238fd1498Szrj {
122338fd1498Szrj lra_assert (nop == data->insn_static_data->n_operands);
122438fd1498Szrj /* Now get the operand values and constraints out of the
122538fd1498Szrj insn. */
122638fd1498Szrj decode_asm_operands (PATTERN (insn), NULL,
122738fd1498Szrj data->operand_loc,
122838fd1498Szrj constraints, operand_mode, NULL);
122938fd1498Szrj
123038fd1498Szrj if (flag_checking)
123138fd1498Szrj for (int i = 0; i < nop; i++)
123238fd1498Szrj lra_assert
123338fd1498Szrj (insn_static_data->operand[i].mode == operand_mode[i]
123438fd1498Szrj && insn_static_data->operand[i].constraint == constraints[i]
123538fd1498Szrj && ! insn_static_data->operand[i].is_operator);
123638fd1498Szrj }
123738fd1498Szrj
123838fd1498Szrj if (flag_checking)
123938fd1498Szrj for (int i = 0; i < insn_static_data->n_operands; i++)
124038fd1498Szrj lra_assert
124138fd1498Szrj (insn_static_data->operand[i].type
124238fd1498Szrj == (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
124338fd1498Szrj : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
124438fd1498Szrj : OP_IN));
124538fd1498Szrj }
124638fd1498Szrj else
124738fd1498Szrj {
124838fd1498Szrj insn_extract (insn);
124938fd1498Szrj n = insn_static_data->n_operands;
125038fd1498Szrj if (n != 0)
125138fd1498Szrj memcpy (data->operand_loc, recog_data.operand_loc, n * sizeof (rtx *));
125238fd1498Szrj n = insn_static_data->n_dups;
125338fd1498Szrj if (n != 0)
125438fd1498Szrj memcpy (data->dup_loc, recog_data.dup_loc, n * sizeof (rtx *));
125538fd1498Szrj lra_assert (check_bool_attrs (insn));
125638fd1498Szrj }
125738fd1498Szrj return data;
125838fd1498Szrj }
125938fd1498Szrj
126038fd1498Szrj /* Set up that INSN is using alternative ALT now. */
126138fd1498Szrj void
lra_set_used_insn_alternative(rtx_insn * insn,int alt)126238fd1498Szrj lra_set_used_insn_alternative (rtx_insn *insn, int alt)
126338fd1498Szrj {
126438fd1498Szrj lra_insn_recog_data_t data;
126538fd1498Szrj
126638fd1498Szrj data = lra_get_insn_recog_data (insn);
126738fd1498Szrj data->used_insn_alternative = alt;
126838fd1498Szrj }
126938fd1498Szrj
127038fd1498Szrj /* Set up that insn with UID is using alternative ALT now. The insn
127138fd1498Szrj info should be already set up. */
127238fd1498Szrj void
lra_set_used_insn_alternative_by_uid(int uid,int alt)127338fd1498Szrj lra_set_used_insn_alternative_by_uid (int uid, int alt)
127438fd1498Szrj {
127538fd1498Szrj lra_insn_recog_data_t data;
127638fd1498Szrj
127738fd1498Szrj check_and_expand_insn_recog_data (uid);
127838fd1498Szrj data = lra_insn_recog_data[uid];
127938fd1498Szrj lra_assert (data != NULL);
128038fd1498Szrj data->used_insn_alternative = alt;
128138fd1498Szrj }
128238fd1498Szrj
128338fd1498Szrj
128438fd1498Szrj
128538fd1498Szrj /* This page contains code dealing with common register info and
128638fd1498Szrj pseudo copies. */
128738fd1498Szrj
128838fd1498Szrj /* The size of the following array. */
128938fd1498Szrj static int reg_info_size;
129038fd1498Szrj /* Common info about each register. */
129138fd1498Szrj struct lra_reg *lra_reg_info;
129238fd1498Szrj
129338fd1498Szrj HARD_REG_SET hard_regs_spilled_into;
129438fd1498Szrj
129538fd1498Szrj /* Last register value. */
129638fd1498Szrj static int last_reg_value;
129738fd1498Szrj
129838fd1498Szrj /* Return new register value. */
129938fd1498Szrj static int
get_new_reg_value(void)130038fd1498Szrj get_new_reg_value (void)
130138fd1498Szrj {
130238fd1498Szrj return ++last_reg_value;
130338fd1498Szrj }
130438fd1498Szrj
130538fd1498Szrj /* Vec referring to pseudo copies. */
130638fd1498Szrj static vec<lra_copy_t> copy_vec;
130738fd1498Szrj
130838fd1498Szrj /* Initialize I-th element of lra_reg_info. */
130938fd1498Szrj static inline void
initialize_lra_reg_info_element(int i)131038fd1498Szrj initialize_lra_reg_info_element (int i)
131138fd1498Szrj {
131238fd1498Szrj bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack);
131338fd1498Szrj #ifdef STACK_REGS
131438fd1498Szrj lra_reg_info[i].no_stack_p = false;
131538fd1498Szrj #endif
131638fd1498Szrj CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
131738fd1498Szrj CLEAR_HARD_REG_SET (lra_reg_info[i].actual_call_used_reg_set);
131838fd1498Szrj lra_reg_info[i].preferred_hard_regno1 = -1;
131938fd1498Szrj lra_reg_info[i].preferred_hard_regno2 = -1;
132038fd1498Szrj lra_reg_info[i].preferred_hard_regno_profit1 = 0;
132138fd1498Szrj lra_reg_info[i].preferred_hard_regno_profit2 = 0;
132238fd1498Szrj lra_reg_info[i].biggest_mode = VOIDmode;
132338fd1498Szrj lra_reg_info[i].live_ranges = NULL;
132438fd1498Szrj lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
132538fd1498Szrj lra_reg_info[i].last_reload = 0;
132638fd1498Szrj lra_reg_info[i].restore_rtx = NULL_RTX;
132738fd1498Szrj lra_reg_info[i].val = get_new_reg_value ();
132838fd1498Szrj lra_reg_info[i].offset = 0;
132938fd1498Szrj lra_reg_info[i].copies = NULL;
133038fd1498Szrj }
133138fd1498Szrj
133238fd1498Szrj /* Initialize common reg info and copies. */
133338fd1498Szrj static void
init_reg_info(void)133438fd1498Szrj init_reg_info (void)
133538fd1498Szrj {
133638fd1498Szrj int i;
133738fd1498Szrj
133838fd1498Szrj last_reg_value = 0;
133938fd1498Szrj reg_info_size = max_reg_num () * 3 / 2 + 1;
134038fd1498Szrj lra_reg_info = XNEWVEC (struct lra_reg, reg_info_size);
134138fd1498Szrj for (i = 0; i < reg_info_size; i++)
134238fd1498Szrj initialize_lra_reg_info_element (i);
134338fd1498Szrj copy_vec.truncate (0);
134438fd1498Szrj CLEAR_HARD_REG_SET (hard_regs_spilled_into);
134538fd1498Szrj }
134638fd1498Szrj
134738fd1498Szrj
134838fd1498Szrj /* Finish common reg info and copies. */
134938fd1498Szrj static void
finish_reg_info(void)135038fd1498Szrj finish_reg_info (void)
135138fd1498Szrj {
135238fd1498Szrj int i;
135338fd1498Szrj
135438fd1498Szrj for (i = 0; i < reg_info_size; i++)
135538fd1498Szrj bitmap_clear (&lra_reg_info[i].insn_bitmap);
135638fd1498Szrj free (lra_reg_info);
135738fd1498Szrj reg_info_size = 0;
135838fd1498Szrj }
135938fd1498Szrj
136038fd1498Szrj /* Expand common reg info if it is necessary. */
136138fd1498Szrj static void
expand_reg_info(void)136238fd1498Szrj expand_reg_info (void)
136338fd1498Szrj {
136438fd1498Szrj int i, old = reg_info_size;
136538fd1498Szrj
136638fd1498Szrj if (reg_info_size > max_reg_num ())
136738fd1498Szrj return;
136838fd1498Szrj reg_info_size = max_reg_num () * 3 / 2 + 1;
136938fd1498Szrj lra_reg_info = XRESIZEVEC (struct lra_reg, lra_reg_info, reg_info_size);
137038fd1498Szrj for (i = old; i < reg_info_size; i++)
137138fd1498Szrj initialize_lra_reg_info_element (i);
137238fd1498Szrj }
137338fd1498Szrj
137438fd1498Szrj /* Free all copies. */
137538fd1498Szrj void
lra_free_copies(void)137638fd1498Szrj lra_free_copies (void)
137738fd1498Szrj {
137838fd1498Szrj lra_copy_t cp;
137938fd1498Szrj
138038fd1498Szrj while (copy_vec.length () != 0)
138138fd1498Szrj {
138238fd1498Szrj cp = copy_vec.pop ();
138338fd1498Szrj lra_reg_info[cp->regno1].copies = lra_reg_info[cp->regno2].copies = NULL;
138438fd1498Szrj lra_copy_pool.remove (cp);
138538fd1498Szrj }
138638fd1498Szrj }
138738fd1498Szrj
138838fd1498Szrj /* Create copy of two pseudos REGNO1 and REGNO2. The copy execution
138938fd1498Szrj frequency is FREQ. */
139038fd1498Szrj void
lra_create_copy(int regno1,int regno2,int freq)139138fd1498Szrj lra_create_copy (int regno1, int regno2, int freq)
139238fd1498Szrj {
139338fd1498Szrj bool regno1_dest_p;
139438fd1498Szrj lra_copy_t cp;
139538fd1498Szrj
139638fd1498Szrj lra_assert (regno1 != regno2);
139738fd1498Szrj regno1_dest_p = true;
139838fd1498Szrj if (regno1 > regno2)
139938fd1498Szrj {
140038fd1498Szrj std::swap (regno1, regno2);
140138fd1498Szrj regno1_dest_p = false;
140238fd1498Szrj }
140338fd1498Szrj cp = lra_copy_pool.allocate ();
140438fd1498Szrj copy_vec.safe_push (cp);
140538fd1498Szrj cp->regno1_dest_p = regno1_dest_p;
140638fd1498Szrj cp->freq = freq;
140738fd1498Szrj cp->regno1 = regno1;
140838fd1498Szrj cp->regno2 = regno2;
140938fd1498Szrj cp->regno1_next = lra_reg_info[regno1].copies;
141038fd1498Szrj lra_reg_info[regno1].copies = cp;
141138fd1498Szrj cp->regno2_next = lra_reg_info[regno2].copies;
141238fd1498Szrj lra_reg_info[regno2].copies = cp;
141338fd1498Szrj if (lra_dump_file != NULL)
141438fd1498Szrj fprintf (lra_dump_file, " Creating copy r%d%sr%d@%d\n",
141538fd1498Szrj regno1, regno1_dest_p ? "<-" : "->", regno2, freq);
141638fd1498Szrj }
141738fd1498Szrj
141838fd1498Szrj /* Return N-th (0, 1, ...) copy. If there is no copy, return
141938fd1498Szrj NULL. */
142038fd1498Szrj lra_copy_t
lra_get_copy(int n)142138fd1498Szrj lra_get_copy (int n)
142238fd1498Szrj {
142338fd1498Szrj if (n >= (int) copy_vec.length ())
142438fd1498Szrj return NULL;
142538fd1498Szrj return copy_vec[n];
142638fd1498Szrj }
142738fd1498Szrj
142838fd1498Szrj
142938fd1498Szrj
143038fd1498Szrj /* This page contains code dealing with info about registers in
143138fd1498Szrj insns. */
143238fd1498Szrj
143338fd1498Szrj /* Process X of INSN recursively and add info (operand type is
143438fd1498Szrj given by TYPE, flag of that it is early clobber is EARLY_CLOBBER)
143538fd1498Szrj about registers in X to the insn DATA. If X can be early clobbered,
143638fd1498Szrj alternatives in which it can be early clobbered are given by
143738fd1498Szrj EARLY_CLOBBER_ALTS. */
143838fd1498Szrj static void
add_regs_to_insn_regno_info(lra_insn_recog_data_t data,rtx x,rtx_insn * insn,enum op_type type,bool early_clobber,alternative_mask early_clobber_alts)143938fd1498Szrj add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
144038fd1498Szrj rtx_insn *insn,
144138fd1498Szrj enum op_type type, bool early_clobber,
144238fd1498Szrj alternative_mask early_clobber_alts)
144338fd1498Szrj {
144438fd1498Szrj int i, j, regno;
144538fd1498Szrj bool subreg_p;
144638fd1498Szrj machine_mode mode;
144738fd1498Szrj const char *fmt;
144838fd1498Szrj enum rtx_code code;
144938fd1498Szrj struct lra_insn_reg *curr;
145038fd1498Szrj
145138fd1498Szrj code = GET_CODE (x);
145238fd1498Szrj mode = GET_MODE (x);
145338fd1498Szrj subreg_p = false;
145438fd1498Szrj if (GET_CODE (x) == SUBREG)
145538fd1498Szrj {
145638fd1498Szrj mode = wider_subreg_mode (x);
145738fd1498Szrj if (read_modify_subreg_p (x))
145838fd1498Szrj subreg_p = true;
145938fd1498Szrj x = SUBREG_REG (x);
146038fd1498Szrj code = GET_CODE (x);
146138fd1498Szrj }
146238fd1498Szrj if (REG_P (x))
146338fd1498Szrj {
146438fd1498Szrj regno = REGNO (x);
146538fd1498Szrj /* Process all regs even unallocatable ones as we need info about
146638fd1498Szrj all regs for rematerialization pass. */
146738fd1498Szrj expand_reg_info ();
146838fd1498Szrj if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn)))
146938fd1498Szrj {
147038fd1498Szrj data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
147138fd1498Szrj early_clobber, early_clobber_alts,
147238fd1498Szrj data->regs);
147338fd1498Szrj return;
147438fd1498Szrj }
147538fd1498Szrj else
147638fd1498Szrj {
147738fd1498Szrj for (curr = data->regs; curr != NULL; curr = curr->next)
147838fd1498Szrj if (curr->regno == regno)
147938fd1498Szrj {
148038fd1498Szrj if (curr->subreg_p != subreg_p || curr->biggest_mode != mode)
148138fd1498Szrj /* The info can not be integrated into the found
148238fd1498Szrj structure. */
148338fd1498Szrj data->regs = new_insn_reg (data->insn, regno, type, mode,
148438fd1498Szrj subreg_p, early_clobber,
148538fd1498Szrj early_clobber_alts, data->regs);
148638fd1498Szrj else
148738fd1498Szrj {
148838fd1498Szrj if (curr->type != type)
148938fd1498Szrj curr->type = OP_INOUT;
149038fd1498Szrj if (curr->early_clobber != early_clobber)
149138fd1498Szrj curr->early_clobber = true;
149238fd1498Szrj curr->early_clobber_alts |= early_clobber_alts;
149338fd1498Szrj }
149438fd1498Szrj return;
149538fd1498Szrj }
149638fd1498Szrj gcc_unreachable ();
149738fd1498Szrj }
149838fd1498Szrj }
149938fd1498Szrj
150038fd1498Szrj switch (code)
150138fd1498Szrj {
150238fd1498Szrj case SET:
150338fd1498Szrj add_regs_to_insn_regno_info (data, SET_DEST (x), insn, OP_OUT, false, 0);
150438fd1498Szrj add_regs_to_insn_regno_info (data, SET_SRC (x), insn, OP_IN, false, 0);
150538fd1498Szrj break;
150638fd1498Szrj case CLOBBER:
150738fd1498Szrj /* We treat clobber of non-operand hard registers as early
150838fd1498Szrj clobber. */
150938fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
151038fd1498Szrj true, ALL_ALTERNATIVES);
151138fd1498Szrj break;
151238fd1498Szrj case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
151338fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0);
151438fd1498Szrj break;
151538fd1498Szrj case PRE_MODIFY: case POST_MODIFY:
151638fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0);
151738fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (x, 1), insn, OP_IN, false, 0);
151838fd1498Szrj break;
151938fd1498Szrj default:
152038fd1498Szrj if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT)
152138fd1498Szrj /* Some targets place small structures in registers for return
152238fd1498Szrj values of functions, and those registers are wrapped in
152338fd1498Szrj PARALLEL that we may see as the destination of a SET. Here
152438fd1498Szrj is an example:
152538fd1498Szrj
152638fd1498Szrj (call_insn 13 12 14 2 (set (parallel:BLK [
152738fd1498Szrj (expr_list:REG_DEP_TRUE (reg:DI 0 ax)
152838fd1498Szrj (const_int 0 [0]))
152938fd1498Szrj (expr_list:REG_DEP_TRUE (reg:DI 1 dx)
153038fd1498Szrj (const_int 8 [0x8]))
153138fd1498Szrj ])
153238fd1498Szrj (call (mem:QI (symbol_ref:DI (... */
153338fd1498Szrj type = OP_IN;
153438fd1498Szrj fmt = GET_RTX_FORMAT (code);
153538fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
153638fd1498Szrj {
153738fd1498Szrj if (fmt[i] == 'e')
153838fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (x, i), insn, type, false, 0);
153938fd1498Szrj else if (fmt[i] == 'E')
154038fd1498Szrj {
154138fd1498Szrj for (j = XVECLEN (x, i) - 1; j >= 0; j--)
154238fd1498Szrj add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), insn,
154338fd1498Szrj type, false, 0);
154438fd1498Szrj }
154538fd1498Szrj }
154638fd1498Szrj }
154738fd1498Szrj }
154838fd1498Szrj
154938fd1498Szrj /* Return execution frequency of INSN. */
155038fd1498Szrj static int
get_insn_freq(rtx_insn * insn)155138fd1498Szrj get_insn_freq (rtx_insn *insn)
155238fd1498Szrj {
155338fd1498Szrj basic_block bb = BLOCK_FOR_INSN (insn);
155438fd1498Szrj
155538fd1498Szrj gcc_checking_assert (bb != NULL);
155638fd1498Szrj return REG_FREQ_FROM_BB (bb);
155738fd1498Szrj }
155838fd1498Szrj
155938fd1498Szrj /* Invalidate all reg info of INSN with DATA and execution frequency
156038fd1498Szrj FREQ. Update common info about the invalidated registers. */
156138fd1498Szrj static void
invalidate_insn_data_regno_info(lra_insn_recog_data_t data,rtx_insn * insn,int freq)156238fd1498Szrj invalidate_insn_data_regno_info (lra_insn_recog_data_t data, rtx_insn *insn,
156338fd1498Szrj int freq)
156438fd1498Szrj {
156538fd1498Szrj int uid;
156638fd1498Szrj bool debug_p;
156738fd1498Szrj unsigned int i;
156838fd1498Szrj struct lra_insn_reg *ir, *next_ir;
156938fd1498Szrj
157038fd1498Szrj uid = INSN_UID (insn);
157138fd1498Szrj debug_p = DEBUG_INSN_P (insn);
157238fd1498Szrj for (ir = data->regs; ir != NULL; ir = next_ir)
157338fd1498Szrj {
157438fd1498Szrj i = ir->regno;
157538fd1498Szrj next_ir = ir->next;
157638fd1498Szrj lra_insn_reg_pool.remove (ir);
157738fd1498Szrj bitmap_clear_bit (&lra_reg_info[i].insn_bitmap, uid);
157838fd1498Szrj if (i >= FIRST_PSEUDO_REGISTER && ! debug_p)
157938fd1498Szrj {
158038fd1498Szrj lra_reg_info[i].nrefs--;
158138fd1498Szrj lra_reg_info[i].freq -= freq;
158238fd1498Szrj lra_assert (lra_reg_info[i].nrefs >= 0 && lra_reg_info[i].freq >= 0);
158338fd1498Szrj }
158438fd1498Szrj }
158538fd1498Szrj data->regs = NULL;
158638fd1498Szrj }
158738fd1498Szrj
158838fd1498Szrj /* Invalidate all reg info of INSN. Update common info about the
158938fd1498Szrj invalidated registers. */
159038fd1498Szrj void
lra_invalidate_insn_regno_info(rtx_insn * insn)159138fd1498Szrj lra_invalidate_insn_regno_info (rtx_insn *insn)
159238fd1498Szrj {
159338fd1498Szrj invalidate_insn_data_regno_info (lra_get_insn_recog_data (insn), insn,
159438fd1498Szrj get_insn_freq (insn));
159538fd1498Szrj }
159638fd1498Szrj
159738fd1498Szrj /* Update common reg info from reg info of insn given by its DATA and
159838fd1498Szrj execution frequency FREQ. */
159938fd1498Szrj static void
setup_insn_reg_info(lra_insn_recog_data_t data,int freq)160038fd1498Szrj setup_insn_reg_info (lra_insn_recog_data_t data, int freq)
160138fd1498Szrj {
160238fd1498Szrj unsigned int i;
160338fd1498Szrj struct lra_insn_reg *ir;
160438fd1498Szrj
160538fd1498Szrj for (ir = data->regs; ir != NULL; ir = ir->next)
160638fd1498Szrj if ((i = ir->regno) >= FIRST_PSEUDO_REGISTER)
160738fd1498Szrj {
160838fd1498Szrj lra_reg_info[i].nrefs++;
160938fd1498Szrj lra_reg_info[i].freq += freq;
161038fd1498Szrj }
161138fd1498Szrj }
161238fd1498Szrj
161338fd1498Szrj /* Set up insn reg info of INSN. Update common reg info from reg info
161438fd1498Szrj of INSN. */
161538fd1498Szrj void
lra_update_insn_regno_info(rtx_insn * insn)161638fd1498Szrj lra_update_insn_regno_info (rtx_insn *insn)
161738fd1498Szrj {
161838fd1498Szrj int i, freq;
161938fd1498Szrj lra_insn_recog_data_t data;
162038fd1498Szrj struct lra_static_insn_data *static_data;
162138fd1498Szrj enum rtx_code code;
162238fd1498Szrj rtx link;
162338fd1498Szrj
162438fd1498Szrj if (! INSN_P (insn))
162538fd1498Szrj return;
162638fd1498Szrj data = lra_get_insn_recog_data (insn);
162738fd1498Szrj static_data = data->insn_static_data;
162838fd1498Szrj freq = NONDEBUG_INSN_P (insn) ? get_insn_freq (insn) : 0;
162938fd1498Szrj invalidate_insn_data_regno_info (data, insn, freq);
163038fd1498Szrj for (i = static_data->n_operands - 1; i >= 0; i--)
163138fd1498Szrj add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn,
163238fd1498Szrj static_data->operand[i].type,
163338fd1498Szrj static_data->operand[i].early_clobber,
163438fd1498Szrj static_data->operand[i].early_clobber_alts);
163538fd1498Szrj if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE)
163638fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), insn,
163738fd1498Szrj code == USE ? OP_IN : OP_OUT, false, 0);
163838fd1498Szrj if (CALL_P (insn))
163938fd1498Szrj /* On some targets call insns can refer to pseudos in memory in
164038fd1498Szrj CALL_INSN_FUNCTION_USAGE list. Process them in order to
164138fd1498Szrj consider their occurrences in calls for different
164238fd1498Szrj transformations (e.g. inheritance) with given pseudos. */
164338fd1498Szrj for (link = CALL_INSN_FUNCTION_USAGE (insn);
164438fd1498Szrj link != NULL_RTX;
164538fd1498Szrj link = XEXP (link, 1))
164638fd1498Szrj if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER)
164738fd1498Szrj && MEM_P (XEXP (XEXP (link, 0), 0)))
164838fd1498Szrj add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
164938fd1498Szrj code == USE ? OP_IN : OP_OUT, false, 0);
165038fd1498Szrj if (NONDEBUG_INSN_P (insn))
165138fd1498Szrj setup_insn_reg_info (data, freq);
165238fd1498Szrj }
165338fd1498Szrj
165438fd1498Szrj /* Return reg info of insn given by it UID. */
165538fd1498Szrj struct lra_insn_reg *
lra_get_insn_regs(int uid)165638fd1498Szrj lra_get_insn_regs (int uid)
165738fd1498Szrj {
165838fd1498Szrj lra_insn_recog_data_t data;
165938fd1498Szrj
166038fd1498Szrj data = get_insn_recog_data_by_uid (uid);
166138fd1498Szrj return data->regs;
166238fd1498Szrj }
166338fd1498Szrj
166438fd1498Szrj
166538fd1498Szrj
166638fd1498Szrj /* Recursive hash function for RTL X. */
166738fd1498Szrj hashval_t
lra_rtx_hash(rtx x)166838fd1498Szrj lra_rtx_hash (rtx x)
166938fd1498Szrj {
167038fd1498Szrj int i, j;
167138fd1498Szrj enum rtx_code code;
167238fd1498Szrj const char *fmt;
167338fd1498Szrj hashval_t val = 0;
167438fd1498Szrj
167538fd1498Szrj if (x == 0)
167638fd1498Szrj return val;
167738fd1498Szrj
167838fd1498Szrj code = GET_CODE (x);
167938fd1498Szrj val += (int) code + 4095;
168038fd1498Szrj
168138fd1498Szrj /* Some RTL can be compared nonrecursively. */
168238fd1498Szrj switch (code)
168338fd1498Szrj {
168438fd1498Szrj case REG:
168538fd1498Szrj return val + REGNO (x);
168638fd1498Szrj
168738fd1498Szrj case LABEL_REF:
168838fd1498Szrj return iterative_hash_object (XEXP (x, 0), val);
168938fd1498Szrj
169038fd1498Szrj case SYMBOL_REF:
169138fd1498Szrj return iterative_hash_object (XSTR (x, 0), val);
169238fd1498Szrj
169338fd1498Szrj case SCRATCH:
169438fd1498Szrj case CONST_DOUBLE:
169538fd1498Szrj case CONST_VECTOR:
169638fd1498Szrj return val;
169738fd1498Szrj
1698*58e805e6Szrj case CONST_INT:
1699*58e805e6Szrj return val + UINTVAL (x);
1700*58e805e6Szrj
170138fd1498Szrj default:
170238fd1498Szrj break;
170338fd1498Szrj }
170438fd1498Szrj
170538fd1498Szrj /* Hash the elements. */
170638fd1498Szrj fmt = GET_RTX_FORMAT (code);
170738fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
170838fd1498Szrj {
170938fd1498Szrj switch (fmt[i])
171038fd1498Szrj {
171138fd1498Szrj case 'w':
171238fd1498Szrj val += XWINT (x, i);
171338fd1498Szrj break;
171438fd1498Szrj
171538fd1498Szrj case 'n':
171638fd1498Szrj case 'i':
171738fd1498Szrj val += XINT (x, i);
171838fd1498Szrj break;
171938fd1498Szrj
172038fd1498Szrj case 'V':
172138fd1498Szrj case 'E':
172238fd1498Szrj val += XVECLEN (x, i);
172338fd1498Szrj
172438fd1498Szrj for (j = 0; j < XVECLEN (x, i); j++)
172538fd1498Szrj val += lra_rtx_hash (XVECEXP (x, i, j));
172638fd1498Szrj break;
172738fd1498Szrj
172838fd1498Szrj case 'e':
172938fd1498Szrj val += lra_rtx_hash (XEXP (x, i));
173038fd1498Szrj break;
173138fd1498Szrj
173238fd1498Szrj case 'S':
173338fd1498Szrj case 's':
173438fd1498Szrj val += htab_hash_string (XSTR (x, i));
173538fd1498Szrj break;
173638fd1498Szrj
173738fd1498Szrj case 'u':
173838fd1498Szrj case '0':
173938fd1498Szrj case 't':
174038fd1498Szrj break;
174138fd1498Szrj
174238fd1498Szrj /* It is believed that rtx's at this level will never
174338fd1498Szrj contain anything but integers and other rtx's, except for
174438fd1498Szrj within LABEL_REFs and SYMBOL_REFs. */
174538fd1498Szrj default:
174638fd1498Szrj abort ();
174738fd1498Szrj }
174838fd1498Szrj }
174938fd1498Szrj return val;
175038fd1498Szrj }
175138fd1498Szrj
175238fd1498Szrj
175338fd1498Szrj
175438fd1498Szrj /* This page contains code dealing with stack of the insns which
175538fd1498Szrj should be processed by the next constraint pass. */
175638fd1498Szrj
175738fd1498Szrj /* Bitmap used to put an insn on the stack only in one exemplar. */
175838fd1498Szrj static sbitmap lra_constraint_insn_stack_bitmap;
175938fd1498Szrj
176038fd1498Szrj /* The stack itself. */
176138fd1498Szrj vec<rtx_insn *> lra_constraint_insn_stack;
176238fd1498Szrj
176338fd1498Szrj /* Put INSN on the stack. If ALWAYS_UPDATE is true, always update the reg
176438fd1498Szrj info for INSN, otherwise only update it if INSN is not already on the
176538fd1498Szrj stack. */
176638fd1498Szrj static inline void
lra_push_insn_1(rtx_insn * insn,bool always_update)176738fd1498Szrj lra_push_insn_1 (rtx_insn *insn, bool always_update)
176838fd1498Szrj {
176938fd1498Szrj unsigned int uid = INSN_UID (insn);
177038fd1498Szrj if (always_update)
177138fd1498Szrj lra_update_insn_regno_info (insn);
177238fd1498Szrj if (uid >= SBITMAP_SIZE (lra_constraint_insn_stack_bitmap))
177338fd1498Szrj lra_constraint_insn_stack_bitmap =
177438fd1498Szrj sbitmap_resize (lra_constraint_insn_stack_bitmap, 3 * uid / 2, 0);
177538fd1498Szrj if (bitmap_bit_p (lra_constraint_insn_stack_bitmap, uid))
177638fd1498Szrj return;
177738fd1498Szrj bitmap_set_bit (lra_constraint_insn_stack_bitmap, uid);
177838fd1498Szrj if (! always_update)
177938fd1498Szrj lra_update_insn_regno_info (insn);
178038fd1498Szrj lra_constraint_insn_stack.safe_push (insn);
178138fd1498Szrj }
178238fd1498Szrj
178338fd1498Szrj /* Put INSN on the stack. */
178438fd1498Szrj void
lra_push_insn(rtx_insn * insn)178538fd1498Szrj lra_push_insn (rtx_insn *insn)
178638fd1498Szrj {
178738fd1498Szrj lra_push_insn_1 (insn, false);
178838fd1498Szrj }
178938fd1498Szrj
179038fd1498Szrj /* Put INSN on the stack and update its reg info. */
179138fd1498Szrj void
lra_push_insn_and_update_insn_regno_info(rtx_insn * insn)179238fd1498Szrj lra_push_insn_and_update_insn_regno_info (rtx_insn *insn)
179338fd1498Szrj {
179438fd1498Szrj lra_push_insn_1 (insn, true);
179538fd1498Szrj }
179638fd1498Szrj
179738fd1498Szrj /* Put insn with UID on the stack. */
179838fd1498Szrj void
lra_push_insn_by_uid(unsigned int uid)179938fd1498Szrj lra_push_insn_by_uid (unsigned int uid)
180038fd1498Szrj {
180138fd1498Szrj lra_push_insn (lra_insn_recog_data[uid]->insn);
180238fd1498Szrj }
180338fd1498Szrj
180438fd1498Szrj /* Take the last-inserted insns off the stack and return it. */
180538fd1498Szrj rtx_insn *
lra_pop_insn(void)180638fd1498Szrj lra_pop_insn (void)
180738fd1498Szrj {
180838fd1498Szrj rtx_insn *insn = lra_constraint_insn_stack.pop ();
180938fd1498Szrj bitmap_clear_bit (lra_constraint_insn_stack_bitmap, INSN_UID (insn));
181038fd1498Szrj return insn;
181138fd1498Szrj }
181238fd1498Szrj
181338fd1498Szrj /* Return the current size of the insn stack. */
181438fd1498Szrj unsigned int
lra_insn_stack_length(void)181538fd1498Szrj lra_insn_stack_length (void)
181638fd1498Szrj {
181738fd1498Szrj return lra_constraint_insn_stack.length ();
181838fd1498Szrj }
181938fd1498Szrj
182038fd1498Szrj /* Push insns FROM to TO (excluding it) going in reverse order. */
182138fd1498Szrj static void
push_insns(rtx_insn * from,rtx_insn * to)182238fd1498Szrj push_insns (rtx_insn *from, rtx_insn *to)
182338fd1498Szrj {
182438fd1498Szrj rtx_insn *insn;
182538fd1498Szrj
182638fd1498Szrj if (from == NULL_RTX)
182738fd1498Szrj return;
182838fd1498Szrj for (insn = from; insn != to; insn = PREV_INSN (insn))
182938fd1498Szrj if (INSN_P (insn))
183038fd1498Szrj lra_push_insn (insn);
183138fd1498Szrj }
183238fd1498Szrj
183338fd1498Szrj /* Set up sp offset for insn in range [FROM, LAST]. The offset is
183438fd1498Szrj taken from the next BB insn after LAST or zero if there in such
183538fd1498Szrj insn. */
183638fd1498Szrj static void
setup_sp_offset(rtx_insn * from,rtx_insn * last)183738fd1498Szrj setup_sp_offset (rtx_insn *from, rtx_insn *last)
183838fd1498Szrj {
183938fd1498Szrj rtx_insn *before = next_nonnote_nondebug_insn_bb (last);
184038fd1498Szrj poly_int64 offset = (before == NULL_RTX || ! INSN_P (before)
184138fd1498Szrj ? 0 : lra_get_insn_recog_data (before)->sp_offset);
184238fd1498Szrj
184338fd1498Szrj for (rtx_insn *insn = from; insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
184438fd1498Szrj lra_get_insn_recog_data (insn)->sp_offset = offset;
184538fd1498Szrj }
184638fd1498Szrj
184738fd1498Szrj /* Emit insns BEFORE before INSN and insns AFTER after INSN. Put the
184838fd1498Szrj insns onto the stack. Print about emitting the insns with
184938fd1498Szrj TITLE. */
185038fd1498Szrj void
lra_process_new_insns(rtx_insn * insn,rtx_insn * before,rtx_insn * after,const char * title)185138fd1498Szrj lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
185238fd1498Szrj const char *title)
185338fd1498Szrj {
185438fd1498Szrj rtx_insn *last;
185538fd1498Szrj
185638fd1498Szrj if (before == NULL_RTX && after == NULL_RTX)
185738fd1498Szrj return;
185838fd1498Szrj if (lra_dump_file != NULL)
185938fd1498Szrj {
186038fd1498Szrj dump_insn_slim (lra_dump_file, insn);
186138fd1498Szrj if (before != NULL_RTX)
186238fd1498Szrj {
186338fd1498Szrj fprintf (lra_dump_file," %s before:\n", title);
186438fd1498Szrj dump_rtl_slim (lra_dump_file, before, NULL, -1, 0);
186538fd1498Szrj }
186638fd1498Szrj if (after != NULL_RTX)
186738fd1498Szrj {
186838fd1498Szrj fprintf (lra_dump_file, " %s after:\n", title);
186938fd1498Szrj dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
187038fd1498Szrj }
187138fd1498Szrj fprintf (lra_dump_file, "\n");
187238fd1498Szrj }
187338fd1498Szrj if (before != NULL_RTX)
187438fd1498Szrj {
187538fd1498Szrj if (cfun->can_throw_non_call_exceptions)
187638fd1498Szrj copy_reg_eh_region_note_forward (insn, before, NULL);
187738fd1498Szrj emit_insn_before (before, insn);
187838fd1498Szrj push_insns (PREV_INSN (insn), PREV_INSN (before));
187938fd1498Szrj setup_sp_offset (before, PREV_INSN (insn));
188038fd1498Szrj }
188138fd1498Szrj if (after != NULL_RTX)
188238fd1498Szrj {
188338fd1498Szrj if (cfun->can_throw_non_call_exceptions)
188438fd1498Szrj copy_reg_eh_region_note_forward (insn, after, NULL);
188538fd1498Szrj for (last = after; NEXT_INSN (last) != NULL_RTX; last = NEXT_INSN (last))
188638fd1498Szrj ;
188738fd1498Szrj emit_insn_after (after, insn);
188838fd1498Szrj push_insns (last, insn);
188938fd1498Szrj setup_sp_offset (after, last);
189038fd1498Szrj }
189138fd1498Szrj if (cfun->can_throw_non_call_exceptions)
189238fd1498Szrj {
189338fd1498Szrj rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
189438fd1498Szrj if (note && !insn_could_throw_p (insn))
189538fd1498Szrj remove_note (insn, note);
189638fd1498Szrj }
189738fd1498Szrj }
189838fd1498Szrj
189938fd1498Szrj
190038fd1498Szrj /* Replace all references to register OLD_REGNO in *LOC with pseudo
190138fd1498Szrj register NEW_REG. Try to simplify subreg of constant if SUBREG_P.
190238fd1498Szrj DEBUG_P is if LOC is within a DEBUG_INSN. Return true if any
190338fd1498Szrj change was made. */
190438fd1498Szrj bool
lra_substitute_pseudo(rtx * loc,int old_regno,rtx new_reg,bool subreg_p,bool debug_p)190538fd1498Szrj lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p,
190638fd1498Szrj bool debug_p)
190738fd1498Szrj {
190838fd1498Szrj rtx x = *loc;
190938fd1498Szrj bool result = false;
191038fd1498Szrj enum rtx_code code;
191138fd1498Szrj const char *fmt;
191238fd1498Szrj int i, j;
191338fd1498Szrj
191438fd1498Szrj if (x == NULL_RTX)
191538fd1498Szrj return false;
191638fd1498Szrj
191738fd1498Szrj code = GET_CODE (x);
191838fd1498Szrj if (code == SUBREG && subreg_p)
191938fd1498Szrj {
192038fd1498Szrj rtx subst, inner = SUBREG_REG (x);
192138fd1498Szrj /* Transform subreg of constant while we still have inner mode
192238fd1498Szrj of the subreg. The subreg internal should not be an insn
192338fd1498Szrj operand. */
192438fd1498Szrj if (REG_P (inner) && (int) REGNO (inner) == old_regno
192538fd1498Szrj && CONSTANT_P (new_reg)
192638fd1498Szrj && (subst = simplify_subreg (GET_MODE (x), new_reg, GET_MODE (inner),
192738fd1498Szrj SUBREG_BYTE (x))) != NULL_RTX)
192838fd1498Szrj {
192938fd1498Szrj *loc = subst;
193038fd1498Szrj return true;
193138fd1498Szrj }
193238fd1498Szrj
193338fd1498Szrj }
193438fd1498Szrj else if (code == REG && (int) REGNO (x) == old_regno)
193538fd1498Szrj {
193638fd1498Szrj machine_mode mode = GET_MODE (x);
193738fd1498Szrj machine_mode inner_mode = GET_MODE (new_reg);
193838fd1498Szrj
193938fd1498Szrj if (mode != inner_mode
194038fd1498Szrj && ! (CONST_INT_P (new_reg) && SCALAR_INT_MODE_P (mode)))
194138fd1498Szrj {
194238fd1498Szrj poly_uint64 offset = 0;
194338fd1498Szrj if (partial_subreg_p (mode, inner_mode)
194438fd1498Szrj && SCALAR_INT_MODE_P (inner_mode))
194538fd1498Szrj offset = subreg_lowpart_offset (mode, inner_mode);
194638fd1498Szrj if (debug_p)
194738fd1498Szrj new_reg = gen_rtx_raw_SUBREG (mode, new_reg, offset);
194838fd1498Szrj else
194938fd1498Szrj new_reg = gen_rtx_SUBREG (mode, new_reg, offset);
195038fd1498Szrj }
195138fd1498Szrj *loc = new_reg;
195238fd1498Szrj return true;
195338fd1498Szrj }
195438fd1498Szrj
195538fd1498Szrj /* Scan all the operand sub-expressions. */
195638fd1498Szrj fmt = GET_RTX_FORMAT (code);
195738fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
195838fd1498Szrj {
195938fd1498Szrj if (fmt[i] == 'e')
196038fd1498Szrj {
196138fd1498Szrj if (lra_substitute_pseudo (&XEXP (x, i), old_regno,
196238fd1498Szrj new_reg, subreg_p, debug_p))
196338fd1498Szrj result = true;
196438fd1498Szrj }
196538fd1498Szrj else if (fmt[i] == 'E')
196638fd1498Szrj {
196738fd1498Szrj for (j = XVECLEN (x, i) - 1; j >= 0; j--)
196838fd1498Szrj if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno,
196938fd1498Szrj new_reg, subreg_p, debug_p))
197038fd1498Szrj result = true;
197138fd1498Szrj }
197238fd1498Szrj }
197338fd1498Szrj return result;
197438fd1498Szrj }
197538fd1498Szrj
197638fd1498Szrj /* Call lra_substitute_pseudo within an insn. Try to simplify subreg
197738fd1498Szrj of constant if SUBREG_P. This won't update the insn ptr, just the
197838fd1498Szrj contents of the insn. */
197938fd1498Szrj bool
lra_substitute_pseudo_within_insn(rtx_insn * insn,int old_regno,rtx new_reg,bool subreg_p)198038fd1498Szrj lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno,
198138fd1498Szrj rtx new_reg, bool subreg_p)
198238fd1498Szrj {
198338fd1498Szrj rtx loc = insn;
198438fd1498Szrj return lra_substitute_pseudo (&loc, old_regno, new_reg, subreg_p,
198538fd1498Szrj DEBUG_INSN_P (insn));
198638fd1498Szrj }
198738fd1498Szrj
198838fd1498Szrj
198938fd1498Szrj
199038fd1498Szrj /* This page contains code dealing with scratches (changing them onto
199138fd1498Szrj pseudos and restoring them from the pseudos).
199238fd1498Szrj
199338fd1498Szrj We change scratches into pseudos at the beginning of LRA to
199438fd1498Szrj simplify dealing with them (conflicts, hard register assignments).
199538fd1498Szrj
199638fd1498Szrj If the pseudo denoting scratch was spilled it means that we do need
199738fd1498Szrj a hard register for it. Such pseudos are transformed back to
199838fd1498Szrj scratches at the end of LRA. */
199938fd1498Szrj
200038fd1498Szrj /* Description of location of a former scratch operand. */
200138fd1498Szrj struct sloc
200238fd1498Szrj {
200338fd1498Szrj rtx_insn *insn; /* Insn where the scratch was. */
200438fd1498Szrj int nop; /* Number of the operand which was a scratch. */
200538fd1498Szrj };
200638fd1498Szrj
200738fd1498Szrj typedef struct sloc *sloc_t;
200838fd1498Szrj
200938fd1498Szrj /* Locations of the former scratches. */
201038fd1498Szrj static vec<sloc_t> scratches;
201138fd1498Szrj
201238fd1498Szrj /* Bitmap of scratch regnos. */
201338fd1498Szrj static bitmap_head scratch_bitmap;
201438fd1498Szrj
201538fd1498Szrj /* Bitmap of scratch operands. */
201638fd1498Szrj static bitmap_head scratch_operand_bitmap;
201738fd1498Szrj
201838fd1498Szrj /* Return true if pseudo REGNO is made of SCRATCH. */
201938fd1498Szrj bool
lra_former_scratch_p(int regno)202038fd1498Szrj lra_former_scratch_p (int regno)
202138fd1498Szrj {
202238fd1498Szrj return bitmap_bit_p (&scratch_bitmap, regno);
202338fd1498Szrj }
202438fd1498Szrj
202538fd1498Szrj /* Return true if the operand NOP of INSN is a former scratch. */
202638fd1498Szrj bool
lra_former_scratch_operand_p(rtx_insn * insn,int nop)202738fd1498Szrj lra_former_scratch_operand_p (rtx_insn *insn, int nop)
202838fd1498Szrj {
202938fd1498Szrj return bitmap_bit_p (&scratch_operand_bitmap,
203038fd1498Szrj INSN_UID (insn) * MAX_RECOG_OPERANDS + nop) != 0;
203138fd1498Szrj }
203238fd1498Szrj
203338fd1498Szrj /* Register operand NOP in INSN as a former scratch. It will be
203438fd1498Szrj changed to scratch back, if it is necessary, at the LRA end. */
203538fd1498Szrj void
lra_register_new_scratch_op(rtx_insn * insn,int nop)203638fd1498Szrj lra_register_new_scratch_op (rtx_insn *insn, int nop)
203738fd1498Szrj {
203838fd1498Szrj lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
203938fd1498Szrj rtx op = *id->operand_loc[nop];
204038fd1498Szrj sloc_t loc = XNEW (struct sloc);
204138fd1498Szrj lra_assert (REG_P (op));
204238fd1498Szrj loc->insn = insn;
204338fd1498Szrj loc->nop = nop;
204438fd1498Szrj scratches.safe_push (loc);
204538fd1498Szrj bitmap_set_bit (&scratch_bitmap, REGNO (op));
204638fd1498Szrj bitmap_set_bit (&scratch_operand_bitmap,
204738fd1498Szrj INSN_UID (insn) * MAX_RECOG_OPERANDS + nop);
204838fd1498Szrj add_reg_note (insn, REG_UNUSED, op);
204938fd1498Szrj }
205038fd1498Szrj
205138fd1498Szrj /* Change scratches onto pseudos and save their location. */
205238fd1498Szrj static void
remove_scratches(void)205338fd1498Szrj remove_scratches (void)
205438fd1498Szrj {
205538fd1498Szrj int i;
205638fd1498Szrj bool insn_changed_p;
205738fd1498Szrj basic_block bb;
205838fd1498Szrj rtx_insn *insn;
205938fd1498Szrj rtx reg;
206038fd1498Szrj lra_insn_recog_data_t id;
206138fd1498Szrj struct lra_static_insn_data *static_id;
206238fd1498Szrj
206338fd1498Szrj scratches.create (get_max_uid ());
206438fd1498Szrj bitmap_initialize (&scratch_bitmap, ®_obstack);
206538fd1498Szrj bitmap_initialize (&scratch_operand_bitmap, ®_obstack);
206638fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
206738fd1498Szrj FOR_BB_INSNS (bb, insn)
206838fd1498Szrj if (INSN_P (insn))
206938fd1498Szrj {
207038fd1498Szrj id = lra_get_insn_recog_data (insn);
207138fd1498Szrj static_id = id->insn_static_data;
207238fd1498Szrj insn_changed_p = false;
207338fd1498Szrj for (i = 0; i < static_id->n_operands; i++)
207438fd1498Szrj if (GET_CODE (*id->operand_loc[i]) == SCRATCH
207538fd1498Szrj && GET_MODE (*id->operand_loc[i]) != VOIDmode)
207638fd1498Szrj {
207738fd1498Szrj insn_changed_p = true;
207838fd1498Szrj *id->operand_loc[i] = reg
207938fd1498Szrj = lra_create_new_reg (static_id->operand[i].mode,
208038fd1498Szrj *id->operand_loc[i], ALL_REGS, NULL);
208138fd1498Szrj lra_register_new_scratch_op (insn, i);
208238fd1498Szrj if (lra_dump_file != NULL)
208338fd1498Szrj fprintf (lra_dump_file,
208438fd1498Szrj "Removing SCRATCH in insn #%u (nop %d)\n",
208538fd1498Szrj INSN_UID (insn), i);
208638fd1498Szrj }
208738fd1498Szrj if (insn_changed_p)
208838fd1498Szrj /* Because we might use DF right after caller-saves sub-pass
208938fd1498Szrj we need to keep DF info up to date. */
209038fd1498Szrj df_insn_rescan (insn);
209138fd1498Szrj }
209238fd1498Szrj }
209338fd1498Szrj
209438fd1498Szrj /* Changes pseudos created by function remove_scratches onto scratches. */
209538fd1498Szrj static void
restore_scratches(void)209638fd1498Szrj restore_scratches (void)
209738fd1498Szrj {
209838fd1498Szrj int regno;
209938fd1498Szrj unsigned i;
210038fd1498Szrj sloc_t loc;
210138fd1498Szrj rtx_insn *last = NULL;
210238fd1498Szrj lra_insn_recog_data_t id = NULL;
210338fd1498Szrj
210438fd1498Szrj for (i = 0; scratches.iterate (i, &loc); i++)
210538fd1498Szrj {
210638fd1498Szrj /* Ignore already deleted insns. */
210738fd1498Szrj if (NOTE_P (loc->insn)
210838fd1498Szrj && NOTE_KIND (loc->insn) == NOTE_INSN_DELETED)
210938fd1498Szrj continue;
211038fd1498Szrj if (last != loc->insn)
211138fd1498Szrj {
211238fd1498Szrj last = loc->insn;
211338fd1498Szrj id = lra_get_insn_recog_data (last);
211438fd1498Szrj }
211538fd1498Szrj if (REG_P (*id->operand_loc[loc->nop])
211638fd1498Szrj && ((regno = REGNO (*id->operand_loc[loc->nop]))
211738fd1498Szrj >= FIRST_PSEUDO_REGISTER)
211838fd1498Szrj && lra_get_regno_hard_regno (regno) < 0)
211938fd1498Szrj {
212038fd1498Szrj /* It should be only case when scratch register with chosen
212138fd1498Szrj constraint 'X' did not get memory or hard register. */
212238fd1498Szrj lra_assert (lra_former_scratch_p (regno));
212338fd1498Szrj *id->operand_loc[loc->nop]
212438fd1498Szrj = gen_rtx_SCRATCH (GET_MODE (*id->operand_loc[loc->nop]));
212538fd1498Szrj lra_update_dup (id, loc->nop);
212638fd1498Szrj if (lra_dump_file != NULL)
212738fd1498Szrj fprintf (lra_dump_file, "Restoring SCRATCH in insn #%u(nop %d)\n",
212838fd1498Szrj INSN_UID (loc->insn), loc->nop);
212938fd1498Szrj }
213038fd1498Szrj }
213138fd1498Szrj for (i = 0; scratches.iterate (i, &loc); i++)
213238fd1498Szrj free (loc);
213338fd1498Szrj scratches.release ();
213438fd1498Szrj bitmap_clear (&scratch_bitmap);
213538fd1498Szrj bitmap_clear (&scratch_operand_bitmap);
213638fd1498Szrj }
213738fd1498Szrj
213838fd1498Szrj
213938fd1498Szrj
214038fd1498Szrj /* Function checks RTL for correctness. If FINAL_P is true, it is
214138fd1498Szrj done at the end of LRA and the check is more rigorous. */
214238fd1498Szrj static void
check_rtl(bool final_p)214338fd1498Szrj check_rtl (bool final_p)
214438fd1498Szrj {
214538fd1498Szrj basic_block bb;
214638fd1498Szrj rtx_insn *insn;
214738fd1498Szrj
214838fd1498Szrj lra_assert (! final_p || reload_completed);
214938fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
215038fd1498Szrj FOR_BB_INSNS (bb, insn)
215138fd1498Szrj if (NONDEBUG_INSN_P (insn)
215238fd1498Szrj && GET_CODE (PATTERN (insn)) != USE
215338fd1498Szrj && GET_CODE (PATTERN (insn)) != CLOBBER
215438fd1498Szrj && GET_CODE (PATTERN (insn)) != ASM_INPUT)
215538fd1498Szrj {
215638fd1498Szrj if (final_p)
215738fd1498Szrj {
215838fd1498Szrj extract_constrain_insn (insn);
215938fd1498Szrj continue;
216038fd1498Szrj }
216138fd1498Szrj /* LRA code is based on assumption that all addresses can be
216238fd1498Szrj correctly decomposed. LRA can generate reloads for
216338fd1498Szrj decomposable addresses. The decomposition code checks the
216438fd1498Szrj correctness of the addresses. So we don't need to check
216538fd1498Szrj the addresses here. Don't call insn_invalid_p here, it can
216638fd1498Szrj change the code at this stage. */
216738fd1498Szrj if (recog_memoized (insn) < 0 && asm_noperands (PATTERN (insn)) < 0)
216838fd1498Szrj fatal_insn_not_found (insn);
216938fd1498Szrj }
217038fd1498Szrj }
217138fd1498Szrj
217238fd1498Szrj /* Determine if the current function has an exception receiver block
217338fd1498Szrj that reaches the exit block via non-exceptional edges */
217438fd1498Szrj static bool
has_nonexceptional_receiver(void)217538fd1498Szrj has_nonexceptional_receiver (void)
217638fd1498Szrj {
217738fd1498Szrj edge e;
217838fd1498Szrj edge_iterator ei;
217938fd1498Szrj basic_block *tos, *worklist, bb;
218038fd1498Szrj
218138fd1498Szrj /* If we're not optimizing, then just err on the safe side. */
218238fd1498Szrj if (!optimize)
218338fd1498Szrj return true;
218438fd1498Szrj
218538fd1498Szrj /* First determine which blocks can reach exit via normal paths. */
218638fd1498Szrj tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
218738fd1498Szrj
218838fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
218938fd1498Szrj bb->flags &= ~BB_REACHABLE;
219038fd1498Szrj
219138fd1498Szrj /* Place the exit block on our worklist. */
219238fd1498Szrj EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_REACHABLE;
219338fd1498Szrj *tos++ = EXIT_BLOCK_PTR_FOR_FN (cfun);
219438fd1498Szrj
219538fd1498Szrj /* Iterate: find everything reachable from what we've already seen. */
219638fd1498Szrj while (tos != worklist)
219738fd1498Szrj {
219838fd1498Szrj bb = *--tos;
219938fd1498Szrj
220038fd1498Szrj FOR_EACH_EDGE (e, ei, bb->preds)
220138fd1498Szrj if (e->flags & EDGE_ABNORMAL)
220238fd1498Szrj {
220338fd1498Szrj free (worklist);
220438fd1498Szrj return true;
220538fd1498Szrj }
220638fd1498Szrj else
220738fd1498Szrj {
220838fd1498Szrj basic_block src = e->src;
220938fd1498Szrj
221038fd1498Szrj if (!(src->flags & BB_REACHABLE))
221138fd1498Szrj {
221238fd1498Szrj src->flags |= BB_REACHABLE;
221338fd1498Szrj *tos++ = src;
221438fd1498Szrj }
221538fd1498Szrj }
221638fd1498Szrj }
221738fd1498Szrj free (worklist);
221838fd1498Szrj /* No exceptional block reached exit unexceptionally. */
221938fd1498Szrj return false;
222038fd1498Szrj }
222138fd1498Szrj
222238fd1498Szrj
222338fd1498Szrj /* Process recursively X of INSN and add REG_INC notes if necessary. */
222438fd1498Szrj static void
add_auto_inc_notes(rtx_insn * insn,rtx x)222538fd1498Szrj add_auto_inc_notes (rtx_insn *insn, rtx x)
222638fd1498Szrj {
222738fd1498Szrj enum rtx_code code = GET_CODE (x);
222838fd1498Szrj const char *fmt;
222938fd1498Szrj int i, j;
223038fd1498Szrj
223138fd1498Szrj if (code == MEM && auto_inc_p (XEXP (x, 0)))
223238fd1498Szrj {
223338fd1498Szrj add_reg_note (insn, REG_INC, XEXP (XEXP (x, 0), 0));
223438fd1498Szrj return;
223538fd1498Szrj }
223638fd1498Szrj
223738fd1498Szrj /* Scan all X sub-expressions. */
223838fd1498Szrj fmt = GET_RTX_FORMAT (code);
223938fd1498Szrj for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
224038fd1498Szrj {
224138fd1498Szrj if (fmt[i] == 'e')
224238fd1498Szrj add_auto_inc_notes (insn, XEXP (x, i));
224338fd1498Szrj else if (fmt[i] == 'E')
224438fd1498Szrj for (j = XVECLEN (x, i) - 1; j >= 0; j--)
224538fd1498Szrj add_auto_inc_notes (insn, XVECEXP (x, i, j));
224638fd1498Szrj }
224738fd1498Szrj }
224838fd1498Szrj
224938fd1498Szrj
225038fd1498Szrj /* Remove all REG_DEAD and REG_UNUSED notes and regenerate REG_INC.
225138fd1498Szrj We change pseudos by hard registers without notification of DF and
225238fd1498Szrj that can make the notes obsolete. DF-infrastructure does not deal
225338fd1498Szrj with REG_INC notes -- so we should regenerate them here. */
225438fd1498Szrj static void
update_inc_notes(void)225538fd1498Szrj update_inc_notes (void)
225638fd1498Szrj {
225738fd1498Szrj rtx *pnote;
225838fd1498Szrj basic_block bb;
225938fd1498Szrj rtx_insn *insn;
226038fd1498Szrj
226138fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
226238fd1498Szrj FOR_BB_INSNS (bb, insn)
226338fd1498Szrj if (NONDEBUG_INSN_P (insn))
226438fd1498Szrj {
226538fd1498Szrj pnote = ®_NOTES (insn);
226638fd1498Szrj while (*pnote != 0)
226738fd1498Szrj {
226838fd1498Szrj if (REG_NOTE_KIND (*pnote) == REG_DEAD
226938fd1498Szrj || REG_NOTE_KIND (*pnote) == REG_UNUSED
227038fd1498Szrj || REG_NOTE_KIND (*pnote) == REG_INC)
227138fd1498Szrj *pnote = XEXP (*pnote, 1);
227238fd1498Szrj else
227338fd1498Szrj pnote = &XEXP (*pnote, 1);
227438fd1498Szrj }
227538fd1498Szrj
227638fd1498Szrj if (AUTO_INC_DEC)
227738fd1498Szrj add_auto_inc_notes (insn, PATTERN (insn));
227838fd1498Szrj }
227938fd1498Szrj }
228038fd1498Szrj
228138fd1498Szrj /* Set to 1 while in lra. */
228238fd1498Szrj int lra_in_progress;
228338fd1498Szrj
228438fd1498Szrj /* Start of pseudo regnos before the LRA. */
228538fd1498Szrj int lra_new_regno_start;
228638fd1498Szrj
228738fd1498Szrj /* Start of reload pseudo regnos before the new spill pass. */
228838fd1498Szrj int lra_constraint_new_regno_start;
228938fd1498Szrj
229038fd1498Szrj /* Avoid spilling pseudos with regno more than the following value if
229138fd1498Szrj it is possible. */
229238fd1498Szrj int lra_bad_spill_regno_start;
229338fd1498Szrj
229438fd1498Szrj /* Inheritance pseudo regnos before the new spill pass. */
229538fd1498Szrj bitmap_head lra_inheritance_pseudos;
229638fd1498Szrj
229738fd1498Szrj /* Split regnos before the new spill pass. */
229838fd1498Szrj bitmap_head lra_split_regs;
229938fd1498Szrj
230038fd1498Szrj /* Reload pseudo regnos before the new assignment pass which still can
230138fd1498Szrj be spilled after the assignment pass as memory is also accepted in
230238fd1498Szrj insns for the reload pseudos. */
230338fd1498Szrj bitmap_head lra_optional_reload_pseudos;
230438fd1498Szrj
230538fd1498Szrj /* Pseudo regnos used for subreg reloads before the new assignment
230638fd1498Szrj pass. Such pseudos still can be spilled after the assignment
230738fd1498Szrj pass. */
230838fd1498Szrj bitmap_head lra_subreg_reload_pseudos;
230938fd1498Szrj
231038fd1498Szrj /* File used for output of LRA debug information. */
231138fd1498Szrj FILE *lra_dump_file;
231238fd1498Szrj
231338fd1498Szrj /* True if we should try spill into registers of different classes
231438fd1498Szrj instead of memory. */
231538fd1498Szrj bool lra_reg_spill_p;
231638fd1498Szrj
231738fd1498Szrj /* Set up value LRA_REG_SPILL_P. */
231838fd1498Szrj static void
setup_reg_spill_flag(void)231938fd1498Szrj setup_reg_spill_flag (void)
232038fd1498Szrj {
232138fd1498Szrj int cl, mode;
232238fd1498Szrj
232338fd1498Szrj if (targetm.spill_class != NULL)
232438fd1498Szrj for (cl = 0; cl < (int) LIM_REG_CLASSES; cl++)
232538fd1498Szrj for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
232638fd1498Szrj if (targetm.spill_class ((enum reg_class) cl,
232738fd1498Szrj (machine_mode) mode) != NO_REGS)
232838fd1498Szrj {
232938fd1498Szrj lra_reg_spill_p = true;
233038fd1498Szrj return;
233138fd1498Szrj }
233238fd1498Szrj lra_reg_spill_p = false;
233338fd1498Szrj }
233438fd1498Szrj
233538fd1498Szrj /* True if the current function is too big to use regular algorithms
233638fd1498Szrj in LRA. In other words, we should use simpler and faster algorithms
233738fd1498Szrj in LRA. It also means we should not worry about generation code
233838fd1498Szrj for caller saves. The value is set up in IRA. */
233938fd1498Szrj bool lra_simple_p;
234038fd1498Szrj
234138fd1498Szrj /* Major LRA entry function. F is a file should be used to dump LRA
234238fd1498Szrj debug info. */
234338fd1498Szrj void
lra(FILE * f)234438fd1498Szrj lra (FILE *f)
234538fd1498Szrj {
234638fd1498Szrj int i;
234738fd1498Szrj bool live_p, inserted_p;
234838fd1498Szrj
234938fd1498Szrj lra_dump_file = f;
235038fd1498Szrj
235138fd1498Szrj timevar_push (TV_LRA);
235238fd1498Szrj
235338fd1498Szrj /* Make sure that the last insn is a note. Some subsequent passes
235438fd1498Szrj need it. */
235538fd1498Szrj emit_note (NOTE_INSN_DELETED);
235638fd1498Szrj
235738fd1498Szrj COPY_HARD_REG_SET (lra_no_alloc_regs, ira_no_alloc_regs);
235838fd1498Szrj
235938fd1498Szrj init_reg_info ();
236038fd1498Szrj expand_reg_info ();
236138fd1498Szrj
236238fd1498Szrj init_insn_recog_data ();
236338fd1498Szrj
236438fd1498Szrj /* Some quick check on RTL generated by previous passes. */
236538fd1498Szrj if (flag_checking)
236638fd1498Szrj check_rtl (false);
236738fd1498Szrj
236838fd1498Szrj lra_in_progress = 1;
236938fd1498Szrj
237038fd1498Szrj lra_live_range_iter = lra_coalesce_iter = lra_constraint_iter = 0;
237138fd1498Szrj lra_assignment_iter = lra_assignment_iter_after_spill = 0;
237238fd1498Szrj lra_inheritance_iter = lra_undo_inheritance_iter = 0;
237338fd1498Szrj lra_rematerialization_iter = 0;
237438fd1498Szrj
237538fd1498Szrj setup_reg_spill_flag ();
237638fd1498Szrj
237738fd1498Szrj /* Function remove_scratches can creates new pseudos for clobbers --
237838fd1498Szrj so set up lra_constraint_new_regno_start before its call to
237938fd1498Szrj permit changing reg classes for pseudos created by this
238038fd1498Szrj simplification. */
238138fd1498Szrj lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num ();
238238fd1498Szrj lra_bad_spill_regno_start = INT_MAX;
238338fd1498Szrj remove_scratches ();
238438fd1498Szrj
238538fd1498Szrj /* A function that has a non-local label that can reach the exit
238638fd1498Szrj block via non-exceptional paths must save all call-saved
238738fd1498Szrj registers. */
238838fd1498Szrj if (cfun->has_nonlocal_label && has_nonexceptional_receiver ())
238938fd1498Szrj crtl->saves_all_registers = 1;
239038fd1498Szrj
239138fd1498Szrj if (crtl->saves_all_registers)
239238fd1498Szrj for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
239338fd1498Szrj if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
239438fd1498Szrj df_set_regs_ever_live (i, true);
239538fd1498Szrj
239638fd1498Szrj /* We don't DF from now and avoid its using because it is to
239738fd1498Szrj expensive when a lot of RTL changes are made. */
239838fd1498Szrj df_set_flags (DF_NO_INSN_RESCAN);
239938fd1498Szrj lra_constraint_insn_stack.create (get_max_uid ());
240038fd1498Szrj lra_constraint_insn_stack_bitmap = sbitmap_alloc (get_max_uid ());
240138fd1498Szrj bitmap_clear (lra_constraint_insn_stack_bitmap);
240238fd1498Szrj lra_live_ranges_init ();
240338fd1498Szrj lra_constraints_init ();
240438fd1498Szrj lra_curr_reload_num = 0;
240538fd1498Szrj push_insns (get_last_insn (), NULL);
240638fd1498Szrj /* It is needed for the 1st coalescing. */
240738fd1498Szrj bitmap_initialize (&lra_inheritance_pseudos, ®_obstack);
240838fd1498Szrj bitmap_initialize (&lra_split_regs, ®_obstack);
240938fd1498Szrj bitmap_initialize (&lra_optional_reload_pseudos, ®_obstack);
241038fd1498Szrj bitmap_initialize (&lra_subreg_reload_pseudos, ®_obstack);
241138fd1498Szrj live_p = false;
241238fd1498Szrj if (maybe_ne (get_frame_size (), 0) && crtl->stack_alignment_needed)
241338fd1498Szrj /* If we have a stack frame, we must align it now. The stack size
241438fd1498Szrj may be a part of the offset computation for register
241538fd1498Szrj elimination. */
241638fd1498Szrj assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
241738fd1498Szrj lra_init_equiv ();
241838fd1498Szrj for (;;)
241938fd1498Szrj {
242038fd1498Szrj for (;;)
242138fd1498Szrj {
242238fd1498Szrj bool reloads_p = lra_constraints (lra_constraint_iter == 0);
242338fd1498Szrj /* Constraint transformations may result in that eliminable
242438fd1498Szrj hard regs become uneliminable and pseudos which use them
242538fd1498Szrj should be spilled. It is better to do it before pseudo
242638fd1498Szrj assignments.
242738fd1498Szrj
242838fd1498Szrj For example, rs6000 can make
242938fd1498Szrj RS6000_PIC_OFFSET_TABLE_REGNUM uneliminable if we started
243038fd1498Szrj to use a constant pool. */
243138fd1498Szrj lra_eliminate (false, false);
243238fd1498Szrj /* We should try to assign hard registers to scratches even
243338fd1498Szrj if there were no RTL transformations in lra_constraints.
243438fd1498Szrj Also we should check IRA assignments on the first
243538fd1498Szrj iteration as they can be wrong because of early clobbers
243638fd1498Szrj operands which are ignored in IRA. */
243738fd1498Szrj if (! reloads_p && lra_constraint_iter > 1)
243838fd1498Szrj {
243938fd1498Szrj /* Stack is not empty here only when there are changes
244038fd1498Szrj during the elimination sub-pass. */
244138fd1498Szrj if (bitmap_empty_p (lra_constraint_insn_stack_bitmap))
244238fd1498Szrj break;
244338fd1498Szrj else
244438fd1498Szrj /* If there are no reloads but changing due
244538fd1498Szrj elimination, restart the constraint sub-pass
244638fd1498Szrj first. */
244738fd1498Szrj continue;
244838fd1498Szrj }
244938fd1498Szrj /* Do inheritance only for regular algorithms. */
245038fd1498Szrj if (! lra_simple_p)
245138fd1498Szrj {
245238fd1498Szrj if (flag_ipa_ra)
245338fd1498Szrj {
245438fd1498Szrj if (live_p)
245538fd1498Szrj lra_clear_live_ranges ();
245638fd1498Szrj /* As a side-effect of lra_create_live_ranges, we calculate
245738fd1498Szrj actual_call_used_reg_set, which is needed during
245838fd1498Szrj lra_inheritance. */
245938fd1498Szrj lra_create_live_ranges (true, true);
246038fd1498Szrj live_p = true;
246138fd1498Szrj }
246238fd1498Szrj lra_inheritance ();
246338fd1498Szrj }
246438fd1498Szrj if (live_p)
246538fd1498Szrj lra_clear_live_ranges ();
246638fd1498Szrj bool fails_p;
246738fd1498Szrj do
246838fd1498Szrj {
246938fd1498Szrj /* We need live ranges for lra_assign -- so build them.
247038fd1498Szrj But don't remove dead insns or change global live
247138fd1498Szrj info as we can undo inheritance transformations after
247238fd1498Szrj inheritance pseudo assigning. */
247338fd1498Szrj lra_create_live_ranges (true, false);
247438fd1498Szrj live_p = true;
247538fd1498Szrj /* If we don't spill non-reload and non-inheritance
247638fd1498Szrj pseudos, there is no sense to run memory-memory move
247738fd1498Szrj coalescing. If inheritance pseudos were spilled, the
247838fd1498Szrj memory-memory moves involving them will be removed by
247938fd1498Szrj pass undoing inheritance. */
248038fd1498Szrj if (lra_simple_p)
248138fd1498Szrj lra_assign (fails_p);
248238fd1498Szrj else
248338fd1498Szrj {
248438fd1498Szrj bool spill_p = !lra_assign (fails_p);
248538fd1498Szrj
248638fd1498Szrj if (lra_undo_inheritance ())
248738fd1498Szrj live_p = false;
248838fd1498Szrj if (spill_p && ! fails_p)
248938fd1498Szrj {
249038fd1498Szrj if (! live_p)
249138fd1498Szrj {
249238fd1498Szrj lra_create_live_ranges (true, true);
249338fd1498Szrj live_p = true;
249438fd1498Szrj }
249538fd1498Szrj if (lra_coalesce ())
249638fd1498Szrj live_p = false;
249738fd1498Szrj }
249838fd1498Szrj if (! live_p)
249938fd1498Szrj lra_clear_live_ranges ();
250038fd1498Szrj }
250138fd1498Szrj if (fails_p)
250238fd1498Szrj {
250338fd1498Szrj /* It is a very rare case. It is the last hope to
250438fd1498Szrj split a hard regno live range for a reload
250538fd1498Szrj pseudo. */
250638fd1498Szrj if (live_p)
250738fd1498Szrj lra_clear_live_ranges ();
250838fd1498Szrj live_p = false;
250938fd1498Szrj if (! lra_split_hard_reg_for ())
251038fd1498Szrj break;
251138fd1498Szrj }
251238fd1498Szrj }
251338fd1498Szrj while (fails_p);
251438fd1498Szrj }
251538fd1498Szrj /* Don't clear optional reloads bitmap until all constraints are
251638fd1498Szrj satisfied as we need to differ them from regular reloads. */
251738fd1498Szrj bitmap_clear (&lra_optional_reload_pseudos);
251838fd1498Szrj bitmap_clear (&lra_subreg_reload_pseudos);
251938fd1498Szrj bitmap_clear (&lra_inheritance_pseudos);
252038fd1498Szrj bitmap_clear (&lra_split_regs);
252138fd1498Szrj if (! live_p)
252238fd1498Szrj {
252338fd1498Szrj /* We need full live info for spilling pseudos into
252438fd1498Szrj registers instead of memory. */
252538fd1498Szrj lra_create_live_ranges (lra_reg_spill_p, true);
252638fd1498Szrj live_p = true;
252738fd1498Szrj }
252838fd1498Szrj /* We should check necessity for spilling here as the above live
252938fd1498Szrj range pass can remove spilled pseudos. */
253038fd1498Szrj if (! lra_need_for_spills_p ())
253138fd1498Szrj break;
253238fd1498Szrj /* Now we know what pseudos should be spilled. Try to
253338fd1498Szrj rematerialize them first. */
253438fd1498Szrj if (lra_remat ())
253538fd1498Szrj {
253638fd1498Szrj /* We need full live info -- see the comment above. */
253738fd1498Szrj lra_create_live_ranges (lra_reg_spill_p, true);
253838fd1498Szrj live_p = true;
253938fd1498Szrj if (! lra_need_for_spills_p ())
254038fd1498Szrj break;
254138fd1498Szrj }
254238fd1498Szrj lra_spill ();
254338fd1498Szrj /* Assignment of stack slots changes elimination offsets for
254438fd1498Szrj some eliminations. So update the offsets here. */
254538fd1498Szrj lra_eliminate (false, false);
254638fd1498Szrj lra_constraint_new_regno_start = max_reg_num ();
254738fd1498Szrj if (lra_bad_spill_regno_start == INT_MAX
254838fd1498Szrj && lra_inheritance_iter > LRA_MAX_INHERITANCE_PASSES
254938fd1498Szrj && lra_rematerialization_iter > LRA_MAX_REMATERIALIZATION_PASSES)
255038fd1498Szrj /* After switching off inheritance and rematerialization
255138fd1498Szrj passes, avoid spilling reload pseudos will be created to
255238fd1498Szrj prevent LRA cycling in some complicated cases. */
255338fd1498Szrj lra_bad_spill_regno_start = lra_constraint_new_regno_start;
255438fd1498Szrj lra_assignment_iter_after_spill = 0;
255538fd1498Szrj }
255638fd1498Szrj restore_scratches ();
255738fd1498Szrj lra_eliminate (true, false);
255838fd1498Szrj lra_final_code_change ();
255938fd1498Szrj lra_in_progress = 0;
256038fd1498Szrj if (live_p)
256138fd1498Szrj lra_clear_live_ranges ();
256238fd1498Szrj lra_live_ranges_finish ();
256338fd1498Szrj lra_constraints_finish ();
256438fd1498Szrj finish_reg_info ();
256538fd1498Szrj sbitmap_free (lra_constraint_insn_stack_bitmap);
256638fd1498Szrj lra_constraint_insn_stack.release ();
256738fd1498Szrj finish_insn_recog_data ();
256838fd1498Szrj regstat_free_n_sets_and_refs ();
256938fd1498Szrj regstat_free_ri ();
257038fd1498Szrj reload_completed = 1;
257138fd1498Szrj update_inc_notes ();
257238fd1498Szrj
257338fd1498Szrj inserted_p = fixup_abnormal_edges ();
257438fd1498Szrj
257538fd1498Szrj /* We've possibly turned single trapping insn into multiple ones. */
257638fd1498Szrj if (cfun->can_throw_non_call_exceptions)
257738fd1498Szrj {
257838fd1498Szrj auto_sbitmap blocks (last_basic_block_for_fn (cfun));
257938fd1498Szrj bitmap_ones (blocks);
258038fd1498Szrj find_many_sub_basic_blocks (blocks);
258138fd1498Szrj }
258238fd1498Szrj
258338fd1498Szrj if (inserted_p)
258438fd1498Szrj commit_edge_insertions ();
258538fd1498Szrj
258638fd1498Szrj /* Replacing pseudos with their memory equivalents might have
258738fd1498Szrj created shared rtx. Subsequent passes would get confused
258838fd1498Szrj by this, so unshare everything here. */
258938fd1498Szrj unshare_all_rtl_again (get_insns ());
259038fd1498Szrj
259138fd1498Szrj if (flag_checking)
259238fd1498Szrj check_rtl (true);
259338fd1498Szrj
259438fd1498Szrj timevar_pop (TV_LRA);
259538fd1498Szrj }
259638fd1498Szrj
259738fd1498Szrj /* Called once per compiler to initialize LRA data once. */
259838fd1498Szrj void
lra_init_once(void)259938fd1498Szrj lra_init_once (void)
260038fd1498Szrj {
260138fd1498Szrj init_insn_code_data_once ();
260238fd1498Szrj }
260338fd1498Szrj
260438fd1498Szrj /* Called once per compiler to finish LRA data which are initialize
260538fd1498Szrj once. */
260638fd1498Szrj void
lra_finish_once(void)260738fd1498Szrj lra_finish_once (void)
260838fd1498Szrj {
260938fd1498Szrj finish_insn_code_data_once ();
261038fd1498Szrj }
2611