11debfc3dSmrg /* LRA (local register allocator) driver and LRA utilities.
2*8feb0f0bSmrg Copyright (C) 2010-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Vladimir Makarov <vmakarov@redhat.com>.
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3. If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>. */
201debfc3dSmrg
211debfc3dSmrg
221debfc3dSmrg /* The Local Register Allocator (LRA) is a replacement of former
231debfc3dSmrg reload pass. It is focused to simplify code solving the reload
241debfc3dSmrg pass tasks, to make the code maintenance easier, and to implement new
251debfc3dSmrg perspective optimizations.
261debfc3dSmrg
271debfc3dSmrg The major LRA design solutions are:
281debfc3dSmrg o division small manageable, separated sub-tasks
291debfc3dSmrg o reflection of all transformations and decisions in RTL as more
301debfc3dSmrg as possible
311debfc3dSmrg o insn constraints as a primary source of the info (minimizing
321debfc3dSmrg number of target-depended macros/hooks)
331debfc3dSmrg
341debfc3dSmrg In brief LRA works by iterative insn process with the final goal is
351debfc3dSmrg to satisfy all insn and address constraints:
361debfc3dSmrg o New reload insns (in brief reloads) and reload pseudos might be
371debfc3dSmrg generated;
381debfc3dSmrg o Some pseudos might be spilled to assign hard registers to
391debfc3dSmrg new reload pseudos;
401debfc3dSmrg o Recalculating spilled pseudo values (rematerialization);
411debfc3dSmrg o Changing spilled pseudos to stack memory or their equivalences;
421debfc3dSmrg o Allocation stack memory changes the address displacement and
431debfc3dSmrg new iteration is needed.
441debfc3dSmrg
451debfc3dSmrg Here is block diagram of LRA passes:
461debfc3dSmrg
471debfc3dSmrg ------------------------
481debfc3dSmrg --------------- | Undo inheritance for | ---------------
491debfc3dSmrg | Memory-memory | | spilled pseudos, | | New (and old) |
501debfc3dSmrg | move coalesce |<---| splits for pseudos got |<-- | pseudos |
511debfc3dSmrg --------------- | the same hard regs, | | assignment |
521debfc3dSmrg Start | | and optional reloads | ---------------
531debfc3dSmrg | | ------------------------ ^
541debfc3dSmrg V | ---------------- |
551debfc3dSmrg ----------- V | Update virtual | |
561debfc3dSmrg | Remove |----> ------------>| register | |
571debfc3dSmrg | scratches | ^ | displacements | |
581debfc3dSmrg ----------- | ---------------- |
591debfc3dSmrg | | |
601debfc3dSmrg | V New |
611debfc3dSmrg | ------------ pseudos -------------------
621debfc3dSmrg | |Constraints:| or insns | Inheritance/split |
631debfc3dSmrg | | RTL |--------->| transformations |
641debfc3dSmrg | | transfor- | | in EBB scope |
651debfc3dSmrg | substi- | mations | -------------------
661debfc3dSmrg | tutions ------------
671debfc3dSmrg | | No change
681debfc3dSmrg ---------------- V
691debfc3dSmrg | Spilled pseudo | -------------------
701debfc3dSmrg | to memory |<----| Rematerialization |
711debfc3dSmrg | substitution | -------------------
721debfc3dSmrg ----------------
731debfc3dSmrg | No susbtitions
741debfc3dSmrg V
751debfc3dSmrg -------------------------
761debfc3dSmrg | Hard regs substitution, |
771debfc3dSmrg | devirtalization, and |------> Finish
781debfc3dSmrg | restoring scratches got |
791debfc3dSmrg | memory |
801debfc3dSmrg -------------------------
811debfc3dSmrg
821debfc3dSmrg To speed up the process:
831debfc3dSmrg o We process only insns affected by changes on previous
841debfc3dSmrg iterations;
851debfc3dSmrg o We don't use DFA-infrastructure because it results in much slower
861debfc3dSmrg compiler speed than a special IR described below does;
871debfc3dSmrg o We use a special insn representation for quick access to insn
881debfc3dSmrg info which is always *synchronized* with the current RTL;
891debfc3dSmrg o Insn IR is minimized by memory. It is divided on three parts:
901debfc3dSmrg o one specific for each insn in RTL (only operand locations);
911debfc3dSmrg o one common for all insns in RTL with the same insn code
921debfc3dSmrg (different operand attributes from machine descriptions);
931debfc3dSmrg o one oriented for maintenance of live info (list of pseudos).
941debfc3dSmrg o Pseudo data:
951debfc3dSmrg o all insns where the pseudo is referenced;
961debfc3dSmrg o live info (conflicting hard regs, live ranges, # of
971debfc3dSmrg references etc);
981debfc3dSmrg o data used for assigning (preferred hard regs, costs etc).
991debfc3dSmrg
1001debfc3dSmrg This file contains LRA driver, LRA utility functions and data, and
1011debfc3dSmrg code for dealing with scratches. */
1021debfc3dSmrg
1031debfc3dSmrg #include "config.h"
1041debfc3dSmrg #include "system.h"
1051debfc3dSmrg #include "coretypes.h"
1061debfc3dSmrg #include "backend.h"
1071debfc3dSmrg #include "target.h"
1081debfc3dSmrg #include "rtl.h"
1091debfc3dSmrg #include "tree.h"
1101debfc3dSmrg #include "predict.h"
1111debfc3dSmrg #include "df.h"
1121debfc3dSmrg #include "memmodel.h"
1131debfc3dSmrg #include "tm_p.h"
1141debfc3dSmrg #include "optabs.h"
1151debfc3dSmrg #include "regs.h"
1161debfc3dSmrg #include "ira.h"
1171debfc3dSmrg #include "recog.h"
1181debfc3dSmrg #include "expr.h"
1191debfc3dSmrg #include "cfgrtl.h"
1201debfc3dSmrg #include "cfgbuild.h"
1211debfc3dSmrg #include "lra.h"
1221debfc3dSmrg #include "lra-int.h"
1231debfc3dSmrg #include "print-rtl.h"
124*8feb0f0bSmrg #include "function-abi.h"
1251debfc3dSmrg
1261debfc3dSmrg /* Dump bitmap SET with TITLE and BB INDEX. */
1271debfc3dSmrg void
lra_dump_bitmap_with_title(const char * title,bitmap set,int index)1281debfc3dSmrg lra_dump_bitmap_with_title (const char *title, bitmap set, int index)
1291debfc3dSmrg {
1301debfc3dSmrg unsigned int i;
1311debfc3dSmrg int count;
1321debfc3dSmrg bitmap_iterator bi;
1331debfc3dSmrg static const int max_nums_on_line = 10;
1341debfc3dSmrg
1351debfc3dSmrg if (bitmap_empty_p (set))
1361debfc3dSmrg return;
1371debfc3dSmrg fprintf (lra_dump_file, " %s %d:", title, index);
1381debfc3dSmrg fprintf (lra_dump_file, "\n");
1391debfc3dSmrg count = max_nums_on_line + 1;
1401debfc3dSmrg EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
1411debfc3dSmrg {
1421debfc3dSmrg if (count > max_nums_on_line)
1431debfc3dSmrg {
1441debfc3dSmrg fprintf (lra_dump_file, "\n ");
1451debfc3dSmrg count = 0;
1461debfc3dSmrg }
1471debfc3dSmrg fprintf (lra_dump_file, " %4u", i);
1481debfc3dSmrg count++;
1491debfc3dSmrg }
1501debfc3dSmrg fprintf (lra_dump_file, "\n");
1511debfc3dSmrg }
1521debfc3dSmrg
1531debfc3dSmrg /* Hard registers currently not available for allocation. It can
1541debfc3dSmrg changed after some hard registers become not eliminable. */
1551debfc3dSmrg HARD_REG_SET lra_no_alloc_regs;
1561debfc3dSmrg
1571debfc3dSmrg static int get_new_reg_value (void);
1581debfc3dSmrg static void expand_reg_info (void);
1591debfc3dSmrg static void invalidate_insn_recog_data (int);
1601debfc3dSmrg static int get_insn_freq (rtx_insn *);
1611debfc3dSmrg static void invalidate_insn_data_regno_info (lra_insn_recog_data_t,
1621debfc3dSmrg rtx_insn *, int);
163c0a68be4Smrg static void remove_scratches_1 (rtx_insn *);
1641debfc3dSmrg
1651debfc3dSmrg /* Expand all regno related info needed for LRA. */
1661debfc3dSmrg static void
expand_reg_data(int old)1671debfc3dSmrg expand_reg_data (int old)
1681debfc3dSmrg {
1691debfc3dSmrg resize_reg_info ();
1701debfc3dSmrg expand_reg_info ();
1711debfc3dSmrg ira_expand_reg_equiv ();
1721debfc3dSmrg for (int i = (int) max_reg_num () - 1; i >= old; i--)
1731debfc3dSmrg lra_change_class (i, ALL_REGS, " Set", true);
1741debfc3dSmrg }
1751debfc3dSmrg
1761debfc3dSmrg /* Create and return a new reg of ORIGINAL mode. If ORIGINAL is NULL
1771debfc3dSmrg or of VOIDmode, use MD_MODE for the new reg. Initialize its
1781debfc3dSmrg register class to RCLASS. Print message about assigning class
1791debfc3dSmrg RCLASS containing new register name TITLE unless it is NULL. Use
1801debfc3dSmrg attributes of ORIGINAL if it is a register. The created register
1811debfc3dSmrg will have unique held value. */
1821debfc3dSmrg rtx
lra_create_new_reg_with_unique_value(machine_mode md_mode,rtx original,enum reg_class rclass,const char * title)1831debfc3dSmrg lra_create_new_reg_with_unique_value (machine_mode md_mode, rtx original,
1841debfc3dSmrg enum reg_class rclass, const char *title)
1851debfc3dSmrg {
1861debfc3dSmrg machine_mode mode;
1871debfc3dSmrg rtx new_reg;
1881debfc3dSmrg
1891debfc3dSmrg if (original == NULL_RTX || (mode = GET_MODE (original)) == VOIDmode)
1901debfc3dSmrg mode = md_mode;
1911debfc3dSmrg lra_assert (mode != VOIDmode);
1921debfc3dSmrg new_reg = gen_reg_rtx (mode);
1931debfc3dSmrg if (original == NULL_RTX || ! REG_P (original))
1941debfc3dSmrg {
1951debfc3dSmrg if (lra_dump_file != NULL)
1961debfc3dSmrg fprintf (lra_dump_file, " Creating newreg=%i", REGNO (new_reg));
1971debfc3dSmrg }
1981debfc3dSmrg else
1991debfc3dSmrg {
2001debfc3dSmrg if (ORIGINAL_REGNO (original) >= FIRST_PSEUDO_REGISTER)
2011debfc3dSmrg ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original);
2021debfc3dSmrg REG_USERVAR_P (new_reg) = REG_USERVAR_P (original);
2031debfc3dSmrg REG_POINTER (new_reg) = REG_POINTER (original);
2041debfc3dSmrg REG_ATTRS (new_reg) = REG_ATTRS (original);
2051debfc3dSmrg if (lra_dump_file != NULL)
2061debfc3dSmrg fprintf (lra_dump_file, " Creating newreg=%i from oldreg=%i",
2071debfc3dSmrg REGNO (new_reg), REGNO (original));
2081debfc3dSmrg }
2091debfc3dSmrg if (lra_dump_file != NULL)
2101debfc3dSmrg {
2111debfc3dSmrg if (title != NULL)
2121debfc3dSmrg fprintf (lra_dump_file, ", assigning class %s to%s%s r%d",
2131debfc3dSmrg reg_class_names[rclass], *title == '\0' ? "" : " ",
2141debfc3dSmrg title, REGNO (new_reg));
2151debfc3dSmrg fprintf (lra_dump_file, "\n");
2161debfc3dSmrg }
2171debfc3dSmrg expand_reg_data (max_reg_num ());
2181debfc3dSmrg setup_reg_classes (REGNO (new_reg), rclass, NO_REGS, rclass);
2191debfc3dSmrg return new_reg;
2201debfc3dSmrg }
2211debfc3dSmrg
2221debfc3dSmrg /* Analogous to the previous function but also inherits value of
2231debfc3dSmrg ORIGINAL. */
2241debfc3dSmrg rtx
lra_create_new_reg(machine_mode md_mode,rtx original,enum reg_class rclass,const char * title)2251debfc3dSmrg lra_create_new_reg (machine_mode md_mode, rtx original,
2261debfc3dSmrg enum reg_class rclass, const char *title)
2271debfc3dSmrg {
2281debfc3dSmrg rtx new_reg;
2291debfc3dSmrg
2301debfc3dSmrg new_reg
2311debfc3dSmrg = lra_create_new_reg_with_unique_value (md_mode, original, rclass, title);
2321debfc3dSmrg if (original != NULL_RTX && REG_P (original))
2331debfc3dSmrg lra_assign_reg_val (REGNO (original), REGNO (new_reg));
2341debfc3dSmrg return new_reg;
2351debfc3dSmrg }
2361debfc3dSmrg
2371debfc3dSmrg /* Set up for REGNO unique hold value. */
2381debfc3dSmrg void
lra_set_regno_unique_value(int regno)2391debfc3dSmrg lra_set_regno_unique_value (int regno)
2401debfc3dSmrg {
2411debfc3dSmrg lra_reg_info[regno].val = get_new_reg_value ();
2421debfc3dSmrg }
2431debfc3dSmrg
2441debfc3dSmrg /* Invalidate INSN related info used by LRA. The info should never be
2451debfc3dSmrg used after that. */
2461debfc3dSmrg void
lra_invalidate_insn_data(rtx_insn * insn)2471debfc3dSmrg lra_invalidate_insn_data (rtx_insn *insn)
2481debfc3dSmrg {
2491debfc3dSmrg lra_invalidate_insn_regno_info (insn);
2501debfc3dSmrg invalidate_insn_recog_data (INSN_UID (insn));
2511debfc3dSmrg }
2521debfc3dSmrg
2531debfc3dSmrg /* Mark INSN deleted and invalidate the insn related info used by
2541debfc3dSmrg LRA. */
2551debfc3dSmrg void
lra_set_insn_deleted(rtx_insn * insn)2561debfc3dSmrg lra_set_insn_deleted (rtx_insn *insn)
2571debfc3dSmrg {
2581debfc3dSmrg lra_invalidate_insn_data (insn);
2591debfc3dSmrg SET_INSN_DELETED (insn);
2601debfc3dSmrg }
2611debfc3dSmrg
2621debfc3dSmrg /* Delete an unneeded INSN and any previous insns who sole purpose is
2631debfc3dSmrg loading data that is dead in INSN. */
2641debfc3dSmrg void
lra_delete_dead_insn(rtx_insn * insn)2651debfc3dSmrg lra_delete_dead_insn (rtx_insn *insn)
2661debfc3dSmrg {
2671debfc3dSmrg rtx_insn *prev = prev_real_insn (insn);
2681debfc3dSmrg rtx prev_dest;
2691debfc3dSmrg
2701debfc3dSmrg /* If the previous insn sets a register that dies in our insn,
2711debfc3dSmrg delete it too. */
2721debfc3dSmrg if (prev && GET_CODE (PATTERN (prev)) == SET
2731debfc3dSmrg && (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest))
2741debfc3dSmrg && reg_mentioned_p (prev_dest, PATTERN (insn))
2751debfc3dSmrg && find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
2761debfc3dSmrg && ! side_effects_p (SET_SRC (PATTERN (prev))))
2771debfc3dSmrg lra_delete_dead_insn (prev);
2781debfc3dSmrg
2791debfc3dSmrg lra_set_insn_deleted (insn);
2801debfc3dSmrg }
2811debfc3dSmrg
2821debfc3dSmrg /* Emit insn x = y + z. Return NULL if we failed to do it.
2831debfc3dSmrg Otherwise, return the insn. We don't use gen_add3_insn as it might
2841debfc3dSmrg clobber CC. */
2851debfc3dSmrg static rtx_insn *
emit_add3_insn(rtx x,rtx y,rtx z)2861debfc3dSmrg emit_add3_insn (rtx x, rtx y, rtx z)
2871debfc3dSmrg {
2881debfc3dSmrg rtx_insn *last;
2891debfc3dSmrg
2901debfc3dSmrg last = get_last_insn ();
2911debfc3dSmrg
2921debfc3dSmrg if (have_addptr3_insn (x, y, z))
2931debfc3dSmrg {
2941debfc3dSmrg rtx_insn *insn = gen_addptr3_insn (x, y, z);
2951debfc3dSmrg
2961debfc3dSmrg /* If the target provides an "addptr" pattern it hopefully does
2971debfc3dSmrg for a reason. So falling back to the normal add would be
2981debfc3dSmrg a bug. */
2991debfc3dSmrg lra_assert (insn != NULL_RTX);
3001debfc3dSmrg emit_insn (insn);
3011debfc3dSmrg return insn;
3021debfc3dSmrg }
3031debfc3dSmrg
3041debfc3dSmrg rtx_insn *insn = emit_insn (gen_rtx_SET (x, gen_rtx_PLUS (GET_MODE (y),
3051debfc3dSmrg y, z)));
3061debfc3dSmrg if (recog_memoized (insn) < 0)
3071debfc3dSmrg {
3081debfc3dSmrg delete_insns_since (last);
3091debfc3dSmrg insn = NULL;
3101debfc3dSmrg }
3111debfc3dSmrg return insn;
3121debfc3dSmrg }
3131debfc3dSmrg
3141debfc3dSmrg /* Emit insn x = x + y. Return the insn. We use gen_add2_insn as the
3151debfc3dSmrg last resort. */
3161debfc3dSmrg static rtx_insn *
emit_add2_insn(rtx x,rtx y)3171debfc3dSmrg emit_add2_insn (rtx x, rtx y)
3181debfc3dSmrg {
3191debfc3dSmrg rtx_insn *insn = emit_add3_insn (x, x, y);
3201debfc3dSmrg if (insn == NULL_RTX)
3211debfc3dSmrg {
3221debfc3dSmrg insn = gen_add2_insn (x, y);
3231debfc3dSmrg if (insn != NULL_RTX)
3241debfc3dSmrg emit_insn (insn);
3251debfc3dSmrg }
3261debfc3dSmrg return insn;
3271debfc3dSmrg }
3281debfc3dSmrg
3291debfc3dSmrg /* Target checks operands through operand predicates to recognize an
3301debfc3dSmrg insn. We should have a special precaution to generate add insns
3311debfc3dSmrg which are frequent results of elimination.
3321debfc3dSmrg
3331debfc3dSmrg Emit insns for x = y + z. X can be used to store intermediate
3341debfc3dSmrg values and should be not in Y and Z when we use X to store an
3351debfc3dSmrg intermediate value. Y + Z should form [base] [+ index[ * scale]] [
3361debfc3dSmrg + disp] where base and index are registers, disp and scale are
3371debfc3dSmrg constants. Y should contain base if it is present, Z should
3381debfc3dSmrg contain disp if any. index[*scale] can be part of Y or Z. */
3391debfc3dSmrg void
lra_emit_add(rtx x,rtx y,rtx z)3401debfc3dSmrg lra_emit_add (rtx x, rtx y, rtx z)
3411debfc3dSmrg {
3421debfc3dSmrg int old;
3431debfc3dSmrg rtx_insn *last;
3441debfc3dSmrg rtx a1, a2, base, index, disp, scale, index_scale;
3451debfc3dSmrg bool ok_p;
3461debfc3dSmrg
3471debfc3dSmrg rtx_insn *add3_insn = emit_add3_insn (x, y, z);
3481debfc3dSmrg old = max_reg_num ();
3491debfc3dSmrg if (add3_insn != NULL)
3501debfc3dSmrg ;
3511debfc3dSmrg else
3521debfc3dSmrg {
3531debfc3dSmrg disp = a2 = NULL_RTX;
3541debfc3dSmrg if (GET_CODE (y) == PLUS)
3551debfc3dSmrg {
3561debfc3dSmrg a1 = XEXP (y, 0);
3571debfc3dSmrg a2 = XEXP (y, 1);
3581debfc3dSmrg disp = z;
3591debfc3dSmrg }
3601debfc3dSmrg else
3611debfc3dSmrg {
3621debfc3dSmrg a1 = y;
3631debfc3dSmrg if (CONSTANT_P (z))
3641debfc3dSmrg disp = z;
3651debfc3dSmrg else
3661debfc3dSmrg a2 = z;
3671debfc3dSmrg }
3681debfc3dSmrg index_scale = scale = NULL_RTX;
3691debfc3dSmrg if (GET_CODE (a1) == MULT)
3701debfc3dSmrg {
3711debfc3dSmrg index_scale = a1;
3721debfc3dSmrg index = XEXP (a1, 0);
3731debfc3dSmrg scale = XEXP (a1, 1);
3741debfc3dSmrg base = a2;
3751debfc3dSmrg }
3761debfc3dSmrg else if (a2 != NULL_RTX && GET_CODE (a2) == MULT)
3771debfc3dSmrg {
3781debfc3dSmrg index_scale = a2;
3791debfc3dSmrg index = XEXP (a2, 0);
3801debfc3dSmrg scale = XEXP (a2, 1);
3811debfc3dSmrg base = a1;
3821debfc3dSmrg }
3831debfc3dSmrg else
3841debfc3dSmrg {
3851debfc3dSmrg base = a1;
3861debfc3dSmrg index = a2;
3871debfc3dSmrg }
3881debfc3dSmrg if ((base != NULL_RTX && ! (REG_P (base) || GET_CODE (base) == SUBREG))
3891debfc3dSmrg || (index != NULL_RTX
3901debfc3dSmrg && ! (REG_P (index) || GET_CODE (index) == SUBREG))
3911debfc3dSmrg || (disp != NULL_RTX && ! CONSTANT_P (disp))
3921debfc3dSmrg || (scale != NULL_RTX && ! CONSTANT_P (scale)))
3931debfc3dSmrg {
3941debfc3dSmrg /* Probably we have no 3 op add. Last chance is to use 2-op
3951debfc3dSmrg add insn. To succeed, don't move Z to X as an address
3961debfc3dSmrg segment always comes in Y. Otherwise, we might fail when
3971debfc3dSmrg adding the address segment to register. */
3981debfc3dSmrg lra_assert (x != y && x != z);
3991debfc3dSmrg emit_move_insn (x, y);
4001debfc3dSmrg rtx_insn *insn = emit_add2_insn (x, z);
4011debfc3dSmrg lra_assert (insn != NULL_RTX);
4021debfc3dSmrg }
4031debfc3dSmrg else
4041debfc3dSmrg {
4051debfc3dSmrg if (index_scale == NULL_RTX)
4061debfc3dSmrg index_scale = index;
4071debfc3dSmrg if (disp == NULL_RTX)
4081debfc3dSmrg {
4091debfc3dSmrg /* Generate x = index_scale; x = x + base. */
4101debfc3dSmrg lra_assert (index_scale != NULL_RTX && base != NULL_RTX);
4111debfc3dSmrg emit_move_insn (x, index_scale);
4121debfc3dSmrg rtx_insn *insn = emit_add2_insn (x, base);
4131debfc3dSmrg lra_assert (insn != NULL_RTX);
4141debfc3dSmrg }
4151debfc3dSmrg else if (scale == NULL_RTX)
4161debfc3dSmrg {
4171debfc3dSmrg /* Try x = base + disp. */
4181debfc3dSmrg lra_assert (base != NULL_RTX);
4191debfc3dSmrg last = get_last_insn ();
4201debfc3dSmrg rtx_insn *move_insn =
4211debfc3dSmrg emit_move_insn (x, gen_rtx_PLUS (GET_MODE (base), base, disp));
4221debfc3dSmrg if (recog_memoized (move_insn) < 0)
4231debfc3dSmrg {
4241debfc3dSmrg delete_insns_since (last);
4251debfc3dSmrg /* Generate x = disp; x = x + base. */
4261debfc3dSmrg emit_move_insn (x, disp);
4271debfc3dSmrg rtx_insn *add2_insn = emit_add2_insn (x, base);
4281debfc3dSmrg lra_assert (add2_insn != NULL_RTX);
4291debfc3dSmrg }
4301debfc3dSmrg /* Generate x = x + index. */
4311debfc3dSmrg if (index != NULL_RTX)
4321debfc3dSmrg {
4331debfc3dSmrg rtx_insn *insn = emit_add2_insn (x, index);
4341debfc3dSmrg lra_assert (insn != NULL_RTX);
4351debfc3dSmrg }
4361debfc3dSmrg }
4371debfc3dSmrg else
4381debfc3dSmrg {
4391debfc3dSmrg /* Try x = index_scale; x = x + disp; x = x + base. */
4401debfc3dSmrg last = get_last_insn ();
4411debfc3dSmrg rtx_insn *move_insn = emit_move_insn (x, index_scale);
4421debfc3dSmrg ok_p = false;
4431debfc3dSmrg if (recog_memoized (move_insn) >= 0)
4441debfc3dSmrg {
4451debfc3dSmrg rtx_insn *insn = emit_add2_insn (x, disp);
4461debfc3dSmrg if (insn != NULL_RTX)
4471debfc3dSmrg {
4481debfc3dSmrg if (base == NULL_RTX)
4491debfc3dSmrg ok_p = true;
4501debfc3dSmrg else
4511debfc3dSmrg {
4521debfc3dSmrg insn = emit_add2_insn (x, base);
4531debfc3dSmrg if (insn != NULL_RTX)
4541debfc3dSmrg ok_p = true;
4551debfc3dSmrg }
4561debfc3dSmrg }
4571debfc3dSmrg }
4581debfc3dSmrg if (! ok_p)
4591debfc3dSmrg {
4601debfc3dSmrg rtx_insn *insn;
4611debfc3dSmrg
4621debfc3dSmrg delete_insns_since (last);
4631debfc3dSmrg /* Generate x = disp; x = x + base; x = x + index_scale. */
4641debfc3dSmrg emit_move_insn (x, disp);
4651debfc3dSmrg if (base != NULL_RTX)
4661debfc3dSmrg {
4671debfc3dSmrg insn = emit_add2_insn (x, base);
4681debfc3dSmrg lra_assert (insn != NULL_RTX);
4691debfc3dSmrg }
4701debfc3dSmrg insn = emit_add2_insn (x, index_scale);
4711debfc3dSmrg lra_assert (insn != NULL_RTX);
4721debfc3dSmrg }
4731debfc3dSmrg }
4741debfc3dSmrg }
4751debfc3dSmrg }
4761debfc3dSmrg /* Functions emit_... can create pseudos -- so expand the pseudo
4771debfc3dSmrg data. */
4781debfc3dSmrg if (old != max_reg_num ())
4791debfc3dSmrg expand_reg_data (old);
4801debfc3dSmrg }
4811debfc3dSmrg
4821debfc3dSmrg /* The number of emitted reload insns so far. */
4831debfc3dSmrg int lra_curr_reload_num;
4841debfc3dSmrg
4851debfc3dSmrg /* Emit x := y, processing special case when y = u + v or y = u + v *
4861debfc3dSmrg scale + w through emit_add (Y can be an address which is base +
4871debfc3dSmrg index reg * scale + displacement in general case). X may be used
4881debfc3dSmrg as intermediate result therefore it should be not in Y. */
4891debfc3dSmrg void
lra_emit_move(rtx x,rtx y)4901debfc3dSmrg lra_emit_move (rtx x, rtx y)
4911debfc3dSmrg {
4921debfc3dSmrg int old;
493*8feb0f0bSmrg rtx_insn *insn;
4941debfc3dSmrg
4951debfc3dSmrg if (GET_CODE (y) != PLUS)
4961debfc3dSmrg {
4971debfc3dSmrg if (rtx_equal_p (x, y))
4981debfc3dSmrg return;
4991debfc3dSmrg old = max_reg_num ();
500*8feb0f0bSmrg
501*8feb0f0bSmrg insn = (GET_CODE (x) != STRICT_LOW_PART
502*8feb0f0bSmrg ? emit_move_insn (x, y) : emit_insn (gen_rtx_SET (x, y)));
503c0a68be4Smrg /* The move pattern may require scratch registers, so convert them
504c0a68be4Smrg into real registers now. */
505c0a68be4Smrg if (insn != NULL_RTX)
506c0a68be4Smrg remove_scratches_1 (insn);
5071debfc3dSmrg if (REG_P (x))
5081debfc3dSmrg lra_reg_info[ORIGINAL_REGNO (x)].last_reload = ++lra_curr_reload_num;
5091debfc3dSmrg /* Function emit_move can create pseudos -- so expand the pseudo
5101debfc3dSmrg data. */
5111debfc3dSmrg if (old != max_reg_num ())
5121debfc3dSmrg expand_reg_data (old);
5131debfc3dSmrg return;
5141debfc3dSmrg }
5151debfc3dSmrg lra_emit_add (x, XEXP (y, 0), XEXP (y, 1));
5161debfc3dSmrg }
5171debfc3dSmrg
5181debfc3dSmrg /* Update insn operands which are duplication of operands whose
5191debfc3dSmrg numbers are in array of NOPS (with end marker -1). The insn is
5201debfc3dSmrg represented by its LRA internal representation ID. */
5211debfc3dSmrg void
lra_update_dups(lra_insn_recog_data_t id,signed char * nops)5221debfc3dSmrg lra_update_dups (lra_insn_recog_data_t id, signed char *nops)
5231debfc3dSmrg {
5241debfc3dSmrg int i, j, nop;
5251debfc3dSmrg struct lra_static_insn_data *static_id = id->insn_static_data;
5261debfc3dSmrg
5271debfc3dSmrg for (i = 0; i < static_id->n_dups; i++)
5281debfc3dSmrg for (j = 0; (nop = nops[j]) >= 0; j++)
5291debfc3dSmrg if (static_id->dup_num[i] == nop)
5301debfc3dSmrg *id->dup_loc[i] = *id->operand_loc[nop];
5311debfc3dSmrg }
5321debfc3dSmrg
5331debfc3dSmrg
5341debfc3dSmrg
5351debfc3dSmrg /* This page contains code dealing with info about registers in the
5361debfc3dSmrg insns. */
5371debfc3dSmrg
5381debfc3dSmrg /* Pools for insn reg info. */
5391debfc3dSmrg object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
5401debfc3dSmrg
5411debfc3dSmrg /* Create LRA insn related info about a reference to REGNO in INSN
5421debfc3dSmrg with TYPE (in/out/inout), biggest reference mode MODE, flag that it
543*8feb0f0bSmrg is reference through subreg (SUBREG_P), and reference to the next
5441debfc3dSmrg insn reg info (NEXT). If REGNO can be early clobbered,
5451debfc3dSmrg alternatives in which it can be early clobbered are given by
546*8feb0f0bSmrg EARLY_CLOBBER_ALTS. */
5471debfc3dSmrg static struct lra_insn_reg *
new_insn_reg(rtx_insn * insn,int regno,enum op_type type,machine_mode mode,bool subreg_p,alternative_mask early_clobber_alts,struct lra_insn_reg * next)5481debfc3dSmrg new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
549*8feb0f0bSmrg machine_mode mode, bool subreg_p,
5501debfc3dSmrg alternative_mask early_clobber_alts,
551*8feb0f0bSmrg struct lra_insn_reg *next)
5521debfc3dSmrg {
5531debfc3dSmrg lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
5541debfc3dSmrg ir->type = type;
5551debfc3dSmrg ir->biggest_mode = mode;
556a2dc1f3fSmrg if (NONDEBUG_INSN_P (insn)
557a2dc1f3fSmrg && partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
5581debfc3dSmrg lra_reg_info[regno].biggest_mode = mode;
5591debfc3dSmrg ir->subreg_p = subreg_p;
5601debfc3dSmrg ir->early_clobber_alts = early_clobber_alts;
5611debfc3dSmrg ir->regno = regno;
5621debfc3dSmrg ir->next = next;
5631debfc3dSmrg return ir;
5641debfc3dSmrg }
5651debfc3dSmrg
5661debfc3dSmrg /* Free insn reg info list IR. */
5671debfc3dSmrg static void
free_insn_regs(struct lra_insn_reg * ir)5681debfc3dSmrg free_insn_regs (struct lra_insn_reg *ir)
5691debfc3dSmrg {
5701debfc3dSmrg struct lra_insn_reg *next_ir;
5711debfc3dSmrg
5721debfc3dSmrg for (; ir != NULL; ir = next_ir)
5731debfc3dSmrg {
5741debfc3dSmrg next_ir = ir->next;
5751debfc3dSmrg lra_insn_reg_pool.remove (ir);
5761debfc3dSmrg }
5771debfc3dSmrg }
5781debfc3dSmrg
5791debfc3dSmrg /* Finish pool for insn reg info. */
5801debfc3dSmrg static void
finish_insn_regs(void)5811debfc3dSmrg finish_insn_regs (void)
5821debfc3dSmrg {
5831debfc3dSmrg lra_insn_reg_pool.release ();
5841debfc3dSmrg }
5851debfc3dSmrg
5861debfc3dSmrg
5871debfc3dSmrg
5881debfc3dSmrg /* This page contains code dealing LRA insn info (or in other words
5891debfc3dSmrg LRA internal insn representation). */
5901debfc3dSmrg
5911debfc3dSmrg /* Map INSN_CODE -> the static insn data. This info is valid during
5921debfc3dSmrg all translation unit. */
5931debfc3dSmrg struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES];
5941debfc3dSmrg
5951debfc3dSmrg /* Debug insns are represented as a special insn with one input
5961debfc3dSmrg operand which is RTL expression in var_location. */
5971debfc3dSmrg
5981debfc3dSmrg /* The following data are used as static insn operand data for all
5991debfc3dSmrg debug insns. If structure lra_operand_data is changed, the
6001debfc3dSmrg initializer should be changed too. */
6011debfc3dSmrg static struct lra_operand_data debug_operand_data =
6021debfc3dSmrg {
6031debfc3dSmrg NULL, /* alternative */
6041debfc3dSmrg 0, /* early_clobber_alts */
605a2dc1f3fSmrg E_VOIDmode, /* We are not interesting in the operand mode. */
6061debfc3dSmrg OP_IN,
607*8feb0f0bSmrg 0, 0, 0
6081debfc3dSmrg };
6091debfc3dSmrg
6101debfc3dSmrg /* The following data are used as static insn data for all debug
611a2dc1f3fSmrg bind insns. If structure lra_static_insn_data is changed, the
6121debfc3dSmrg initializer should be changed too. */
613a2dc1f3fSmrg static struct lra_static_insn_data debug_bind_static_data =
6141debfc3dSmrg {
6151debfc3dSmrg &debug_operand_data,
6161debfc3dSmrg 0, /* Duplication operands #. */
6171debfc3dSmrg -1, /* Commutative operand #. */
6181debfc3dSmrg 1, /* Operands #. There is only one operand which is debug RTL
6191debfc3dSmrg expression. */
6201debfc3dSmrg 0, /* Duplications #. */
6211debfc3dSmrg 0, /* Alternatives #. We are not interesting in alternatives
6221debfc3dSmrg because we does not proceed debug_insns for reloads. */
6231debfc3dSmrg NULL, /* Hard registers referenced in machine description. */
6241debfc3dSmrg NULL /* Descriptions of operands in alternatives. */
6251debfc3dSmrg };
6261debfc3dSmrg
627a2dc1f3fSmrg /* The following data are used as static insn data for all debug
628a2dc1f3fSmrg marker insns. If structure lra_static_insn_data is changed, the
629a2dc1f3fSmrg initializer should be changed too. */
630a2dc1f3fSmrg static struct lra_static_insn_data debug_marker_static_data =
631a2dc1f3fSmrg {
632a2dc1f3fSmrg &debug_operand_data,
633a2dc1f3fSmrg 0, /* Duplication operands #. */
634a2dc1f3fSmrg -1, /* Commutative operand #. */
635a2dc1f3fSmrg 0, /* Operands #. There isn't any operand. */
636a2dc1f3fSmrg 0, /* Duplications #. */
637a2dc1f3fSmrg 0, /* Alternatives #. We are not interesting in alternatives
638a2dc1f3fSmrg because we does not proceed debug_insns for reloads. */
639a2dc1f3fSmrg NULL, /* Hard registers referenced in machine description. */
640a2dc1f3fSmrg NULL /* Descriptions of operands in alternatives. */
641a2dc1f3fSmrg };
642a2dc1f3fSmrg
6431debfc3dSmrg /* Called once per compiler work to initialize some LRA data related
6441debfc3dSmrg to insns. */
6451debfc3dSmrg static void
init_insn_code_data_once(void)6461debfc3dSmrg init_insn_code_data_once (void)
6471debfc3dSmrg {
6481debfc3dSmrg memset (insn_code_data, 0, sizeof (insn_code_data));
6491debfc3dSmrg }
6501debfc3dSmrg
6511debfc3dSmrg /* Called once per compiler work to finalize some LRA data related to
6521debfc3dSmrg insns. */
6531debfc3dSmrg static void
finish_insn_code_data_once(void)6541debfc3dSmrg finish_insn_code_data_once (void)
6551debfc3dSmrg {
6561debfc3dSmrg for (unsigned int i = 0; i < NUM_INSN_CODES; i++)
6571debfc3dSmrg {
6581debfc3dSmrg if (insn_code_data[i] != NULL)
659*8feb0f0bSmrg {
6601debfc3dSmrg free (insn_code_data[i]);
661*8feb0f0bSmrg insn_code_data[i] = NULL;
662*8feb0f0bSmrg }
6631debfc3dSmrg }
6641debfc3dSmrg }
6651debfc3dSmrg
6661debfc3dSmrg /* Return static insn data, allocate and setup if necessary. Although
6671debfc3dSmrg dup_num is static data (it depends only on icode), to set it up we
6681debfc3dSmrg need to extract insn first. So recog_data should be valid for
6691debfc3dSmrg normal insn (ICODE >= 0) before the call. */
6701debfc3dSmrg static struct lra_static_insn_data *
get_static_insn_data(int icode,int nop,int ndup,int nalt)6711debfc3dSmrg get_static_insn_data (int icode, int nop, int ndup, int nalt)
6721debfc3dSmrg {
6731debfc3dSmrg struct lra_static_insn_data *data;
6741debfc3dSmrg size_t n_bytes;
6751debfc3dSmrg
6761debfc3dSmrg lra_assert (icode < (int) NUM_INSN_CODES);
6771debfc3dSmrg if (icode >= 0 && (data = insn_code_data[icode]) != NULL)
6781debfc3dSmrg return data;
6791debfc3dSmrg lra_assert (nop >= 0 && ndup >= 0 && nalt >= 0);
6801debfc3dSmrg n_bytes = sizeof (struct lra_static_insn_data)
6811debfc3dSmrg + sizeof (struct lra_operand_data) * nop
6821debfc3dSmrg + sizeof (int) * ndup;
6831debfc3dSmrg data = XNEWVAR (struct lra_static_insn_data, n_bytes);
6841debfc3dSmrg data->operand_alternative = NULL;
6851debfc3dSmrg data->n_operands = nop;
6861debfc3dSmrg data->n_dups = ndup;
6871debfc3dSmrg data->n_alternatives = nalt;
6881debfc3dSmrg data->operand = ((struct lra_operand_data *)
6891debfc3dSmrg ((char *) data + sizeof (struct lra_static_insn_data)));
6901debfc3dSmrg data->dup_num = ((int *) ((char *) data->operand
6911debfc3dSmrg + sizeof (struct lra_operand_data) * nop));
6921debfc3dSmrg if (icode >= 0)
6931debfc3dSmrg {
6941debfc3dSmrg int i;
6951debfc3dSmrg
6961debfc3dSmrg insn_code_data[icode] = data;
6971debfc3dSmrg for (i = 0; i < nop; i++)
6981debfc3dSmrg {
6991debfc3dSmrg data->operand[i].constraint
7001debfc3dSmrg = insn_data[icode].operand[i].constraint;
7011debfc3dSmrg data->operand[i].mode = insn_data[icode].operand[i].mode;
7021debfc3dSmrg data->operand[i].strict_low = insn_data[icode].operand[i].strict_low;
7031debfc3dSmrg data->operand[i].is_operator
7041debfc3dSmrg = insn_data[icode].operand[i].is_operator;
7051debfc3dSmrg data->operand[i].type
7061debfc3dSmrg = (data->operand[i].constraint[0] == '=' ? OP_OUT
7071debfc3dSmrg : data->operand[i].constraint[0] == '+' ? OP_INOUT
7081debfc3dSmrg : OP_IN);
7091debfc3dSmrg data->operand[i].is_address = false;
7101debfc3dSmrg }
7111debfc3dSmrg for (i = 0; i < ndup; i++)
7121debfc3dSmrg data->dup_num[i] = recog_data.dup_num[i];
7131debfc3dSmrg }
7141debfc3dSmrg return data;
7151debfc3dSmrg }
7161debfc3dSmrg
7171debfc3dSmrg /* The current length of the following array. */
7181debfc3dSmrg int lra_insn_recog_data_len;
7191debfc3dSmrg
7201debfc3dSmrg /* Map INSN_UID -> the insn recog data (NULL if unknown). */
7211debfc3dSmrg lra_insn_recog_data_t *lra_insn_recog_data;
7221debfc3dSmrg
723*8feb0f0bSmrg /* Alloc pool we allocate entries for lra_insn_recog_data from. */
724*8feb0f0bSmrg static object_allocator<class lra_insn_recog_data>
725*8feb0f0bSmrg lra_insn_recog_data_pool ("insn recog data pool");
726*8feb0f0bSmrg
7271debfc3dSmrg /* Initialize LRA data about insns. */
7281debfc3dSmrg static void
init_insn_recog_data(void)7291debfc3dSmrg init_insn_recog_data (void)
7301debfc3dSmrg {
7311debfc3dSmrg lra_insn_recog_data_len = 0;
7321debfc3dSmrg lra_insn_recog_data = NULL;
7331debfc3dSmrg }
7341debfc3dSmrg
7351debfc3dSmrg /* Expand, if necessary, LRA data about insns. */
7361debfc3dSmrg static void
check_and_expand_insn_recog_data(int index)7371debfc3dSmrg check_and_expand_insn_recog_data (int index)
7381debfc3dSmrg {
7391debfc3dSmrg int i, old;
7401debfc3dSmrg
7411debfc3dSmrg if (lra_insn_recog_data_len > index)
7421debfc3dSmrg return;
7431debfc3dSmrg old = lra_insn_recog_data_len;
7441debfc3dSmrg lra_insn_recog_data_len = index * 3 / 2 + 1;
7451debfc3dSmrg lra_insn_recog_data = XRESIZEVEC (lra_insn_recog_data_t,
7461debfc3dSmrg lra_insn_recog_data,
7471debfc3dSmrg lra_insn_recog_data_len);
7481debfc3dSmrg for (i = old; i < lra_insn_recog_data_len; i++)
7491debfc3dSmrg lra_insn_recog_data[i] = NULL;
7501debfc3dSmrg }
7511debfc3dSmrg
7521debfc3dSmrg /* Finish LRA DATA about insn. */
7531debfc3dSmrg static void
free_insn_recog_data(lra_insn_recog_data_t data)7541debfc3dSmrg free_insn_recog_data (lra_insn_recog_data_t data)
7551debfc3dSmrg {
7561debfc3dSmrg if (data->operand_loc != NULL)
7571debfc3dSmrg free (data->operand_loc);
7581debfc3dSmrg if (data->dup_loc != NULL)
7591debfc3dSmrg free (data->dup_loc);
7601debfc3dSmrg if (data->arg_hard_regs != NULL)
7611debfc3dSmrg free (data->arg_hard_regs);
7621debfc3dSmrg if (data->icode < 0 && NONDEBUG_INSN_P (data->insn))
7631debfc3dSmrg {
7641debfc3dSmrg if (data->insn_static_data->operand_alternative != NULL)
7651debfc3dSmrg free (const_cast <operand_alternative *>
7661debfc3dSmrg (data->insn_static_data->operand_alternative));
7671debfc3dSmrg free_insn_regs (data->insn_static_data->hard_regs);
7681debfc3dSmrg free (data->insn_static_data);
7691debfc3dSmrg }
7701debfc3dSmrg free_insn_regs (data->regs);
7711debfc3dSmrg data->regs = NULL;
772*8feb0f0bSmrg lra_insn_recog_data_pool.remove (data);
7731debfc3dSmrg }
7741debfc3dSmrg
7751debfc3dSmrg /* Pools for copies. */
7761debfc3dSmrg static object_allocator<lra_copy> lra_copy_pool ("lra copies");
7771debfc3dSmrg
7781debfc3dSmrg /* Finish LRA data about all insns. */
7791debfc3dSmrg static void
finish_insn_recog_data(void)7801debfc3dSmrg finish_insn_recog_data (void)
7811debfc3dSmrg {
7821debfc3dSmrg int i;
7831debfc3dSmrg lra_insn_recog_data_t data;
7841debfc3dSmrg
7851debfc3dSmrg for (i = 0; i < lra_insn_recog_data_len; i++)
7861debfc3dSmrg if ((data = lra_insn_recog_data[i]) != NULL)
7871debfc3dSmrg free_insn_recog_data (data);
7881debfc3dSmrg finish_insn_regs ();
7891debfc3dSmrg lra_copy_pool.release ();
7901debfc3dSmrg lra_insn_reg_pool.release ();
791*8feb0f0bSmrg lra_insn_recog_data_pool.release ();
7921debfc3dSmrg free (lra_insn_recog_data);
7931debfc3dSmrg }
7941debfc3dSmrg
7951debfc3dSmrg /* Setup info about operands in alternatives of LRA DATA of insn. */
7961debfc3dSmrg static void
setup_operand_alternative(lra_insn_recog_data_t data,const operand_alternative * op_alt)7971debfc3dSmrg setup_operand_alternative (lra_insn_recog_data_t data,
7981debfc3dSmrg const operand_alternative *op_alt)
7991debfc3dSmrg {
8001debfc3dSmrg int i, j, nop, nalt;
8011debfc3dSmrg int icode = data->icode;
8021debfc3dSmrg struct lra_static_insn_data *static_data = data->insn_static_data;
8031debfc3dSmrg
8041debfc3dSmrg static_data->commutative = -1;
8051debfc3dSmrg nop = static_data->n_operands;
8061debfc3dSmrg nalt = static_data->n_alternatives;
8071debfc3dSmrg static_data->operand_alternative = op_alt;
8081debfc3dSmrg for (i = 0; i < nop; i++)
8091debfc3dSmrg {
8101debfc3dSmrg static_data->operand[i].early_clobber_alts = 0;
8111debfc3dSmrg static_data->operand[i].is_address = false;
8121debfc3dSmrg if (static_data->operand[i].constraint[0] == '%')
8131debfc3dSmrg {
8141debfc3dSmrg /* We currently only support one commutative pair of operands. */
8151debfc3dSmrg if (static_data->commutative < 0)
8161debfc3dSmrg static_data->commutative = i;
8171debfc3dSmrg else
8181debfc3dSmrg lra_assert (icode < 0); /* Asm */
8191debfc3dSmrg /* The last operand should not be marked commutative. */
8201debfc3dSmrg lra_assert (i != nop - 1);
8211debfc3dSmrg }
8221debfc3dSmrg }
8231debfc3dSmrg for (j = 0; j < nalt; j++)
8241debfc3dSmrg for (i = 0; i < nop; i++, op_alt++)
8251debfc3dSmrg {
8261debfc3dSmrg if (op_alt->earlyclobber)
8271debfc3dSmrg static_data->operand[i].early_clobber_alts |= (alternative_mask) 1 << j;
8281debfc3dSmrg static_data->operand[i].is_address |= op_alt->is_address;
8291debfc3dSmrg }
8301debfc3dSmrg }
8311debfc3dSmrg
8321debfc3dSmrg /* Recursively process X and collect info about registers, which are
8331debfc3dSmrg not the insn operands, in X with TYPE (in/out/inout) and flag that
8341debfc3dSmrg it is early clobbered in the insn (EARLY_CLOBBER) and add the info
8351debfc3dSmrg to LIST. X is a part of insn given by DATA. Return the result
836*8feb0f0bSmrg list. */
8371debfc3dSmrg 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)838a2dc1f3fSmrg collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
839a2dc1f3fSmrg lra_insn_recog_data_t data,
8401debfc3dSmrg struct lra_insn_reg *list,
841*8feb0f0bSmrg enum op_type type, bool early_clobber)
8421debfc3dSmrg {
8431debfc3dSmrg int i, j, regno, last;
8441debfc3dSmrg bool subreg_p;
8451debfc3dSmrg machine_mode mode;
8461debfc3dSmrg struct lra_insn_reg *curr;
8471debfc3dSmrg rtx op = *x;
8481debfc3dSmrg enum rtx_code code = GET_CODE (op);
8491debfc3dSmrg const char *fmt = GET_RTX_FORMAT (code);
8501debfc3dSmrg
8511debfc3dSmrg for (i = 0; i < data->insn_static_data->n_operands; i++)
852a2dc1f3fSmrg if (! data->insn_static_data->operand[i].is_operator
853a2dc1f3fSmrg && x == data->operand_loc[i])
8541debfc3dSmrg /* It is an operand loc. Stop here. */
8551debfc3dSmrg return list;
8561debfc3dSmrg for (i = 0; i < data->insn_static_data->n_dups; i++)
8571debfc3dSmrg if (x == data->dup_loc[i])
8581debfc3dSmrg /* It is a dup loc. Stop here. */
8591debfc3dSmrg return list;
8601debfc3dSmrg mode = GET_MODE (op);
8611debfc3dSmrg subreg_p = false;
8621debfc3dSmrg if (code == SUBREG)
8631debfc3dSmrg {
864a2dc1f3fSmrg mode = wider_subreg_mode (op);
865a2dc1f3fSmrg if (read_modify_subreg_p (op))
866a2dc1f3fSmrg subreg_p = true;
8671debfc3dSmrg op = SUBREG_REG (op);
8681debfc3dSmrg code = GET_CODE (op);
8691debfc3dSmrg }
8701debfc3dSmrg if (REG_P (op))
8711debfc3dSmrg {
8721debfc3dSmrg if ((regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER)
8731debfc3dSmrg return list;
8741debfc3dSmrg /* Process all regs even unallocatable ones as we need info
8751debfc3dSmrg about all regs for rematerialization pass. */
876a2dc1f3fSmrg for (last = end_hard_regno (mode, regno); regno < last; regno++)
8771debfc3dSmrg {
8781debfc3dSmrg for (curr = list; curr != NULL; curr = curr->next)
8791debfc3dSmrg if (curr->regno == regno && curr->subreg_p == subreg_p
8801debfc3dSmrg && curr->biggest_mode == mode)
8811debfc3dSmrg {
8821debfc3dSmrg if (curr->type != type)
8831debfc3dSmrg curr->type = OP_INOUT;
8841debfc3dSmrg if (early_clobber)
8851debfc3dSmrg curr->early_clobber_alts = ALL_ALTERNATIVES;
8861debfc3dSmrg break;
8871debfc3dSmrg }
8881debfc3dSmrg if (curr == NULL)
8891debfc3dSmrg {
8901debfc3dSmrg /* This is a new hard regno or the info cannot be
8911debfc3dSmrg integrated into the found structure. */
8921debfc3dSmrg #ifdef STACK_REGS
8931debfc3dSmrg early_clobber
8941debfc3dSmrg = (early_clobber
8951debfc3dSmrg /* This clobber is to inform popping floating
8961debfc3dSmrg point stack only. */
8971debfc3dSmrg && ! (FIRST_STACK_REG <= regno
8981debfc3dSmrg && regno <= LAST_STACK_REG));
8991debfc3dSmrg #endif
9001debfc3dSmrg list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
901*8feb0f0bSmrg early_clobber ? ALL_ALTERNATIVES : 0, list);
9021debfc3dSmrg }
9031debfc3dSmrg }
9041debfc3dSmrg return list;
9051debfc3dSmrg }
9061debfc3dSmrg switch (code)
9071debfc3dSmrg {
9081debfc3dSmrg case SET:
909a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data,
910*8feb0f0bSmrg list, OP_OUT, false);
911a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &SET_SRC (op), data,
912*8feb0f0bSmrg list, OP_IN, false);
9131debfc3dSmrg break;
9141debfc3dSmrg case CLOBBER:
915a2dc1f3fSmrg /* We treat clobber of non-operand hard registers as early clobber. */
916a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
917*8feb0f0bSmrg list, OP_OUT, true);
9181debfc3dSmrg break;
9191debfc3dSmrg case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
920a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
921*8feb0f0bSmrg list, OP_INOUT, false);
9221debfc3dSmrg break;
9231debfc3dSmrg case PRE_MODIFY: case POST_MODIFY:
924a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
925*8feb0f0bSmrg list, OP_INOUT, false);
926a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data,
927*8feb0f0bSmrg list, OP_IN, false);
9281debfc3dSmrg break;
9291debfc3dSmrg default:
9301debfc3dSmrg fmt = GET_RTX_FORMAT (code);
9311debfc3dSmrg for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
9321debfc3dSmrg {
9331debfc3dSmrg if (fmt[i] == 'e')
934a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data,
935*8feb0f0bSmrg list, OP_IN, false);
9361debfc3dSmrg else if (fmt[i] == 'E')
9371debfc3dSmrg for (j = XVECLEN (op, i) - 1; j >= 0; j--)
938a2dc1f3fSmrg list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, j),
939*8feb0f0bSmrg data, list, OP_IN, false);
9401debfc3dSmrg }
9411debfc3dSmrg }
9421debfc3dSmrg return list;
9431debfc3dSmrg }
9441debfc3dSmrg
9451debfc3dSmrg /* Set up and return info about INSN. Set up the info if it is not set up
9461debfc3dSmrg yet. */
9471debfc3dSmrg lra_insn_recog_data_t
lra_set_insn_recog_data(rtx_insn * insn)9481debfc3dSmrg lra_set_insn_recog_data (rtx_insn *insn)
9491debfc3dSmrg {
9501debfc3dSmrg lra_insn_recog_data_t data;
9511debfc3dSmrg int i, n, icode;
9521debfc3dSmrg rtx **locs;
9531debfc3dSmrg unsigned int uid = INSN_UID (insn);
9541debfc3dSmrg struct lra_static_insn_data *insn_static_data;
9551debfc3dSmrg
9561debfc3dSmrg check_and_expand_insn_recog_data (uid);
9571debfc3dSmrg if (DEBUG_INSN_P (insn))
9581debfc3dSmrg icode = -1;
9591debfc3dSmrg else
9601debfc3dSmrg {
9611debfc3dSmrg icode = INSN_CODE (insn);
9621debfc3dSmrg if (icode < 0)
9631debfc3dSmrg /* It might be a new simple insn which is not recognized yet. */
9641debfc3dSmrg INSN_CODE (insn) = icode = recog_memoized (insn);
9651debfc3dSmrg }
966*8feb0f0bSmrg data = lra_insn_recog_data_pool.allocate ();
9671debfc3dSmrg lra_insn_recog_data[uid] = data;
9681debfc3dSmrg data->insn = insn;
9691debfc3dSmrg data->used_insn_alternative = LRA_UNKNOWN_ALT;
9701debfc3dSmrg data->icode = icode;
9711debfc3dSmrg data->regs = NULL;
9721debfc3dSmrg if (DEBUG_INSN_P (insn))
9731debfc3dSmrg {
9741debfc3dSmrg data->dup_loc = NULL;
9751debfc3dSmrg data->arg_hard_regs = NULL;
9761debfc3dSmrg data->preferred_alternatives = ALL_ALTERNATIVES;
977a2dc1f3fSmrg if (DEBUG_BIND_INSN_P (insn))
978a2dc1f3fSmrg {
979a2dc1f3fSmrg data->insn_static_data = &debug_bind_static_data;
9801debfc3dSmrg data->operand_loc = XNEWVEC (rtx *, 1);
9811debfc3dSmrg data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
982a2dc1f3fSmrg }
983a2dc1f3fSmrg else if (DEBUG_MARKER_INSN_P (insn))
984a2dc1f3fSmrg {
985a2dc1f3fSmrg data->insn_static_data = &debug_marker_static_data;
986a2dc1f3fSmrg data->operand_loc = NULL;
987a2dc1f3fSmrg }
9881debfc3dSmrg return data;
9891debfc3dSmrg }
9901debfc3dSmrg if (icode < 0)
9911debfc3dSmrg {
9921debfc3dSmrg int nop, nalt;
9931debfc3dSmrg machine_mode operand_mode[MAX_RECOG_OPERANDS];
9941debfc3dSmrg const char *constraints[MAX_RECOG_OPERANDS];
9951debfc3dSmrg
9961debfc3dSmrg nop = asm_noperands (PATTERN (insn));
9971debfc3dSmrg data->operand_loc = data->dup_loc = NULL;
9981debfc3dSmrg nalt = 1;
9991debfc3dSmrg if (nop < 0)
10001debfc3dSmrg {
10011debfc3dSmrg /* It is a special insn like USE or CLOBBER. We should
10021debfc3dSmrg recognize any regular insn otherwise LRA can do nothing
10031debfc3dSmrg with this insn. */
10041debfc3dSmrg gcc_assert (GET_CODE (PATTERN (insn)) == USE
10051debfc3dSmrg || GET_CODE (PATTERN (insn)) == CLOBBER
10061debfc3dSmrg || GET_CODE (PATTERN (insn)) == ASM_INPUT);
10071debfc3dSmrg data->insn_static_data = insn_static_data
10081debfc3dSmrg = get_static_insn_data (-1, 0, 0, nalt);
10091debfc3dSmrg }
10101debfc3dSmrg else
10111debfc3dSmrg {
10121debfc3dSmrg /* expand_asm_operands makes sure there aren't too many
10131debfc3dSmrg operands. */
10141debfc3dSmrg lra_assert (nop <= MAX_RECOG_OPERANDS);
10151debfc3dSmrg if (nop != 0)
10161debfc3dSmrg data->operand_loc = XNEWVEC (rtx *, nop);
10171debfc3dSmrg /* Now get the operand values and constraints out of the
10181debfc3dSmrg insn. */
10191debfc3dSmrg decode_asm_operands (PATTERN (insn), NULL,
10201debfc3dSmrg data->operand_loc,
10211debfc3dSmrg constraints, operand_mode, NULL);
10221debfc3dSmrg if (nop > 0)
1023*8feb0f0bSmrg for (const char *p =constraints[0]; *p; p++)
10241debfc3dSmrg nalt += *p == ',';
10251debfc3dSmrg data->insn_static_data = insn_static_data
10261debfc3dSmrg = get_static_insn_data (-1, nop, 0, nalt);
10271debfc3dSmrg for (i = 0; i < nop; i++)
10281debfc3dSmrg {
10291debfc3dSmrg insn_static_data->operand[i].mode = operand_mode[i];
10301debfc3dSmrg insn_static_data->operand[i].constraint = constraints[i];
10311debfc3dSmrg insn_static_data->operand[i].strict_low = false;
10321debfc3dSmrg insn_static_data->operand[i].is_operator = false;
10331debfc3dSmrg insn_static_data->operand[i].is_address = false;
10341debfc3dSmrg }
10351debfc3dSmrg }
10361debfc3dSmrg for (i = 0; i < insn_static_data->n_operands; i++)
10371debfc3dSmrg insn_static_data->operand[i].type
10381debfc3dSmrg = (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
10391debfc3dSmrg : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
10401debfc3dSmrg : OP_IN);
10411debfc3dSmrg data->preferred_alternatives = ALL_ALTERNATIVES;
10421debfc3dSmrg if (nop > 0)
10431debfc3dSmrg {
10441debfc3dSmrg operand_alternative *op_alt = XCNEWVEC (operand_alternative,
10451debfc3dSmrg nalt * nop);
1046a2dc1f3fSmrg preprocess_constraints (nop, nalt, constraints, op_alt,
1047a2dc1f3fSmrg data->operand_loc);
10481debfc3dSmrg setup_operand_alternative (data, op_alt);
10491debfc3dSmrg }
10501debfc3dSmrg }
10511debfc3dSmrg else
10521debfc3dSmrg {
10531debfc3dSmrg insn_extract (insn);
10541debfc3dSmrg data->insn_static_data = insn_static_data
10551debfc3dSmrg = get_static_insn_data (icode, insn_data[icode].n_operands,
10561debfc3dSmrg insn_data[icode].n_dups,
10571debfc3dSmrg insn_data[icode].n_alternatives);
10581debfc3dSmrg n = insn_static_data->n_operands;
10591debfc3dSmrg if (n == 0)
10601debfc3dSmrg locs = NULL;
10611debfc3dSmrg else
10621debfc3dSmrg {
10631debfc3dSmrg locs = XNEWVEC (rtx *, n);
10641debfc3dSmrg memcpy (locs, recog_data.operand_loc, n * sizeof (rtx *));
10651debfc3dSmrg }
10661debfc3dSmrg data->operand_loc = locs;
10671debfc3dSmrg n = insn_static_data->n_dups;
10681debfc3dSmrg if (n == 0)
10691debfc3dSmrg locs = NULL;
10701debfc3dSmrg else
10711debfc3dSmrg {
10721debfc3dSmrg locs = XNEWVEC (rtx *, n);
10731debfc3dSmrg memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
10741debfc3dSmrg }
10751debfc3dSmrg data->dup_loc = locs;
10761debfc3dSmrg data->preferred_alternatives = get_preferred_alternatives (insn);
10771debfc3dSmrg const operand_alternative *op_alt = preprocess_insn_constraints (icode);
10781debfc3dSmrg if (!insn_static_data->operand_alternative)
10791debfc3dSmrg setup_operand_alternative (data, op_alt);
10801debfc3dSmrg else if (op_alt != insn_static_data->operand_alternative)
10811debfc3dSmrg insn_static_data->operand_alternative = op_alt;
10821debfc3dSmrg }
10831debfc3dSmrg if (GET_CODE (PATTERN (insn)) == CLOBBER || GET_CODE (PATTERN (insn)) == USE)
10841debfc3dSmrg insn_static_data->hard_regs = NULL;
10851debfc3dSmrg else
10861debfc3dSmrg insn_static_data->hard_regs
1087a2dc1f3fSmrg = collect_non_operand_hard_regs (insn, &PATTERN (insn), data,
1088*8feb0f0bSmrg NULL, OP_IN, false);
10891debfc3dSmrg data->arg_hard_regs = NULL;
10901debfc3dSmrg if (CALL_P (insn))
10911debfc3dSmrg {
10921debfc3dSmrg bool use_p;
10931debfc3dSmrg rtx link;
10941debfc3dSmrg int n_hard_regs, regno, arg_hard_regs[FIRST_PSEUDO_REGISTER];
10951debfc3dSmrg
10961debfc3dSmrg n_hard_regs = 0;
10971debfc3dSmrg /* Finding implicit hard register usage. We believe it will be
10981debfc3dSmrg not changed whatever transformations are used. Call insns
10991debfc3dSmrg are such example. */
11001debfc3dSmrg for (link = CALL_INSN_FUNCTION_USAGE (insn);
11011debfc3dSmrg link != NULL_RTX;
11021debfc3dSmrg link = XEXP (link, 1))
11031debfc3dSmrg if (((use_p = GET_CODE (XEXP (link, 0)) == USE)
11041debfc3dSmrg || GET_CODE (XEXP (link, 0)) == CLOBBER)
11051debfc3dSmrg && REG_P (XEXP (XEXP (link, 0), 0)))
11061debfc3dSmrg {
11071debfc3dSmrg regno = REGNO (XEXP (XEXP (link, 0), 0));
11081debfc3dSmrg lra_assert (regno < FIRST_PSEUDO_REGISTER);
11091debfc3dSmrg /* It is an argument register. */
11101debfc3dSmrg for (i = REG_NREGS (XEXP (XEXP (link, 0), 0)) - 1; i >= 0; i--)
11111debfc3dSmrg arg_hard_regs[n_hard_regs++]
11121debfc3dSmrg = regno + i + (use_p ? 0 : FIRST_PSEUDO_REGISTER);
11131debfc3dSmrg }
1114c0a68be4Smrg
11151debfc3dSmrg if (n_hard_regs != 0)
11161debfc3dSmrg {
11171debfc3dSmrg arg_hard_regs[n_hard_regs++] = -1;
11181debfc3dSmrg data->arg_hard_regs = XNEWVEC (int, n_hard_regs);
11191debfc3dSmrg memcpy (data->arg_hard_regs, arg_hard_regs,
11201debfc3dSmrg sizeof (int) * n_hard_regs);
11211debfc3dSmrg }
11221debfc3dSmrg }
11231debfc3dSmrg /* Some output operand can be recognized only from the context not
11241debfc3dSmrg from the constraints which are empty in this case. Call insn may
11251debfc3dSmrg contain a hard register in set destination with empty constraint
11261debfc3dSmrg and extract_insn treats them as an input. */
11271debfc3dSmrg for (i = 0; i < insn_static_data->n_operands; i++)
11281debfc3dSmrg {
11291debfc3dSmrg int j;
11301debfc3dSmrg rtx pat, set;
11311debfc3dSmrg struct lra_operand_data *operand = &insn_static_data->operand[i];
11321debfc3dSmrg
11331debfc3dSmrg /* ??? Should we treat 'X' the same way. It looks to me that
11341debfc3dSmrg 'X' means anything and empty constraint means we do not
11351debfc3dSmrg care. */
11361debfc3dSmrg if (operand->type != OP_IN || *operand->constraint != '\0'
11371debfc3dSmrg || operand->is_operator)
11381debfc3dSmrg continue;
11391debfc3dSmrg pat = PATTERN (insn);
11401debfc3dSmrg if (GET_CODE (pat) == SET)
11411debfc3dSmrg {
11421debfc3dSmrg if (data->operand_loc[i] != &SET_DEST (pat))
11431debfc3dSmrg continue;
11441debfc3dSmrg }
11451debfc3dSmrg else if (GET_CODE (pat) == PARALLEL)
11461debfc3dSmrg {
11471debfc3dSmrg for (j = XVECLEN (pat, 0) - 1; j >= 0; j--)
11481debfc3dSmrg {
11491debfc3dSmrg set = XVECEXP (PATTERN (insn), 0, j);
11501debfc3dSmrg if (GET_CODE (set) == SET
11511debfc3dSmrg && &SET_DEST (set) == data->operand_loc[i])
11521debfc3dSmrg break;
11531debfc3dSmrg }
11541debfc3dSmrg if (j < 0)
11551debfc3dSmrg continue;
11561debfc3dSmrg }
11571debfc3dSmrg else
11581debfc3dSmrg continue;
11591debfc3dSmrg operand->type = OP_OUT;
11601debfc3dSmrg }
11611debfc3dSmrg return data;
11621debfc3dSmrg }
11631debfc3dSmrg
11641debfc3dSmrg /* Return info about insn give by UID. The info should be already set
11651debfc3dSmrg up. */
11661debfc3dSmrg static lra_insn_recog_data_t
get_insn_recog_data_by_uid(int uid)11671debfc3dSmrg get_insn_recog_data_by_uid (int uid)
11681debfc3dSmrg {
11691debfc3dSmrg lra_insn_recog_data_t data;
11701debfc3dSmrg
11711debfc3dSmrg data = lra_insn_recog_data[uid];
11721debfc3dSmrg lra_assert (data != NULL);
11731debfc3dSmrg return data;
11741debfc3dSmrg }
11751debfc3dSmrg
11761debfc3dSmrg /* Invalidate all info about insn given by its UID. */
11771debfc3dSmrg static void
invalidate_insn_recog_data(int uid)11781debfc3dSmrg invalidate_insn_recog_data (int uid)
11791debfc3dSmrg {
11801debfc3dSmrg lra_insn_recog_data_t data;
11811debfc3dSmrg
11821debfc3dSmrg data = lra_insn_recog_data[uid];
11831debfc3dSmrg lra_assert (data != NULL);
11841debfc3dSmrg free_insn_recog_data (data);
11851debfc3dSmrg lra_insn_recog_data[uid] = NULL;
11861debfc3dSmrg }
11871debfc3dSmrg
11881debfc3dSmrg /* Update all the insn info about INSN. It is usually called when
11891debfc3dSmrg something in the insn was changed. Return the updated info. */
11901debfc3dSmrg lra_insn_recog_data_t
lra_update_insn_recog_data(rtx_insn * insn)11911debfc3dSmrg lra_update_insn_recog_data (rtx_insn *insn)
11921debfc3dSmrg {
11931debfc3dSmrg lra_insn_recog_data_t data;
11941debfc3dSmrg int n;
11951debfc3dSmrg unsigned int uid = INSN_UID (insn);
11961debfc3dSmrg struct lra_static_insn_data *insn_static_data;
1197a2dc1f3fSmrg poly_int64 sp_offset = 0;
11981debfc3dSmrg
11991debfc3dSmrg check_and_expand_insn_recog_data (uid);
12001debfc3dSmrg if ((data = lra_insn_recog_data[uid]) != NULL
12011debfc3dSmrg && data->icode != INSN_CODE (insn))
12021debfc3dSmrg {
12031debfc3dSmrg sp_offset = data->sp_offset;
12041debfc3dSmrg invalidate_insn_data_regno_info (data, insn, get_insn_freq (insn));
12051debfc3dSmrg invalidate_insn_recog_data (uid);
12061debfc3dSmrg data = NULL;
12071debfc3dSmrg }
12081debfc3dSmrg if (data == NULL)
12091debfc3dSmrg {
12101debfc3dSmrg data = lra_get_insn_recog_data (insn);
12111debfc3dSmrg /* Initiate or restore SP offset. */
12121debfc3dSmrg data->sp_offset = sp_offset;
12131debfc3dSmrg return data;
12141debfc3dSmrg }
12151debfc3dSmrg insn_static_data = data->insn_static_data;
12161debfc3dSmrg data->used_insn_alternative = LRA_UNKNOWN_ALT;
12171debfc3dSmrg if (DEBUG_INSN_P (insn))
12181debfc3dSmrg return data;
12191debfc3dSmrg if (data->icode < 0)
12201debfc3dSmrg {
12211debfc3dSmrg int nop;
12221debfc3dSmrg machine_mode operand_mode[MAX_RECOG_OPERANDS];
12231debfc3dSmrg const char *constraints[MAX_RECOG_OPERANDS];
12241debfc3dSmrg
12251debfc3dSmrg nop = asm_noperands (PATTERN (insn));
12261debfc3dSmrg if (nop >= 0)
12271debfc3dSmrg {
12281debfc3dSmrg lra_assert (nop == data->insn_static_data->n_operands);
12291debfc3dSmrg /* Now get the operand values and constraints out of the
12301debfc3dSmrg insn. */
12311debfc3dSmrg decode_asm_operands (PATTERN (insn), NULL,
12321debfc3dSmrg data->operand_loc,
12331debfc3dSmrg constraints, operand_mode, NULL);
12341debfc3dSmrg
12351debfc3dSmrg if (flag_checking)
12361debfc3dSmrg for (int i = 0; i < nop; i++)
12371debfc3dSmrg lra_assert
12381debfc3dSmrg (insn_static_data->operand[i].mode == operand_mode[i]
12391debfc3dSmrg && insn_static_data->operand[i].constraint == constraints[i]
12401debfc3dSmrg && ! insn_static_data->operand[i].is_operator);
12411debfc3dSmrg }
12421debfc3dSmrg
12431debfc3dSmrg if (flag_checking)
12441debfc3dSmrg for (int i = 0; i < insn_static_data->n_operands; i++)
12451debfc3dSmrg lra_assert
12461debfc3dSmrg (insn_static_data->operand[i].type
12471debfc3dSmrg == (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
12481debfc3dSmrg : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
12491debfc3dSmrg : OP_IN));
12501debfc3dSmrg }
12511debfc3dSmrg else
12521debfc3dSmrg {
12531debfc3dSmrg insn_extract (insn);
12541debfc3dSmrg n = insn_static_data->n_operands;
12551debfc3dSmrg if (n != 0)
12561debfc3dSmrg memcpy (data->operand_loc, recog_data.operand_loc, n * sizeof (rtx *));
12571debfc3dSmrg n = insn_static_data->n_dups;
12581debfc3dSmrg if (n != 0)
12591debfc3dSmrg memcpy (data->dup_loc, recog_data.dup_loc, n * sizeof (rtx *));
12601debfc3dSmrg lra_assert (check_bool_attrs (insn));
12611debfc3dSmrg }
12621debfc3dSmrg return data;
12631debfc3dSmrg }
12641debfc3dSmrg
12651debfc3dSmrg /* Set up that INSN is using alternative ALT now. */
12661debfc3dSmrg void
lra_set_used_insn_alternative(rtx_insn * insn,int alt)12671debfc3dSmrg lra_set_used_insn_alternative (rtx_insn *insn, int alt)
12681debfc3dSmrg {
12691debfc3dSmrg lra_insn_recog_data_t data;
12701debfc3dSmrg
12711debfc3dSmrg data = lra_get_insn_recog_data (insn);
12721debfc3dSmrg data->used_insn_alternative = alt;
12731debfc3dSmrg }
12741debfc3dSmrg
12751debfc3dSmrg /* Set up that insn with UID is using alternative ALT now. The insn
12761debfc3dSmrg info should be already set up. */
12771debfc3dSmrg void
lra_set_used_insn_alternative_by_uid(int uid,int alt)12781debfc3dSmrg lra_set_used_insn_alternative_by_uid (int uid, int alt)
12791debfc3dSmrg {
12801debfc3dSmrg lra_insn_recog_data_t data;
12811debfc3dSmrg
12821debfc3dSmrg check_and_expand_insn_recog_data (uid);
12831debfc3dSmrg data = lra_insn_recog_data[uid];
12841debfc3dSmrg lra_assert (data != NULL);
12851debfc3dSmrg data->used_insn_alternative = alt;
12861debfc3dSmrg }
12871debfc3dSmrg
12881debfc3dSmrg
12891debfc3dSmrg
12901debfc3dSmrg /* This page contains code dealing with common register info and
12911debfc3dSmrg pseudo copies. */
12921debfc3dSmrg
12931debfc3dSmrg /* The size of the following array. */
12941debfc3dSmrg static int reg_info_size;
12951debfc3dSmrg /* Common info about each register. */
1296*8feb0f0bSmrg class lra_reg *lra_reg_info;
12971debfc3dSmrg
1298a2dc1f3fSmrg HARD_REG_SET hard_regs_spilled_into;
1299a2dc1f3fSmrg
13001debfc3dSmrg /* Last register value. */
13011debfc3dSmrg static int last_reg_value;
13021debfc3dSmrg
13031debfc3dSmrg /* Return new register value. */
13041debfc3dSmrg static int
get_new_reg_value(void)13051debfc3dSmrg get_new_reg_value (void)
13061debfc3dSmrg {
13071debfc3dSmrg return ++last_reg_value;
13081debfc3dSmrg }
13091debfc3dSmrg
13101debfc3dSmrg /* Vec referring to pseudo copies. */
13111debfc3dSmrg static vec<lra_copy_t> copy_vec;
13121debfc3dSmrg
13131debfc3dSmrg /* Initialize I-th element of lra_reg_info. */
13141debfc3dSmrg static inline void
initialize_lra_reg_info_element(int i)13151debfc3dSmrg initialize_lra_reg_info_element (int i)
13161debfc3dSmrg {
13171debfc3dSmrg bitmap_initialize (&lra_reg_info[i].insn_bitmap, ®_obstack);
13181debfc3dSmrg #ifdef STACK_REGS
13191debfc3dSmrg lra_reg_info[i].no_stack_p = false;
13201debfc3dSmrg #endif
13211debfc3dSmrg CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
13221debfc3dSmrg lra_reg_info[i].preferred_hard_regno1 = -1;
13231debfc3dSmrg lra_reg_info[i].preferred_hard_regno2 = -1;
13241debfc3dSmrg lra_reg_info[i].preferred_hard_regno_profit1 = 0;
13251debfc3dSmrg lra_reg_info[i].preferred_hard_regno_profit2 = 0;
13261debfc3dSmrg lra_reg_info[i].biggest_mode = VOIDmode;
13271debfc3dSmrg lra_reg_info[i].live_ranges = NULL;
13281debfc3dSmrg lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
13291debfc3dSmrg lra_reg_info[i].last_reload = 0;
13301debfc3dSmrg lra_reg_info[i].restore_rtx = NULL_RTX;
13311debfc3dSmrg lra_reg_info[i].val = get_new_reg_value ();
13321debfc3dSmrg lra_reg_info[i].offset = 0;
13331debfc3dSmrg lra_reg_info[i].copies = NULL;
13341debfc3dSmrg }
13351debfc3dSmrg
13361debfc3dSmrg /* Initialize common reg info and copies. */
13371debfc3dSmrg static void
init_reg_info(void)13381debfc3dSmrg init_reg_info (void)
13391debfc3dSmrg {
13401debfc3dSmrg int i;
13411debfc3dSmrg
13421debfc3dSmrg last_reg_value = 0;
13431debfc3dSmrg reg_info_size = max_reg_num () * 3 / 2 + 1;
1344*8feb0f0bSmrg lra_reg_info = XNEWVEC (class lra_reg, reg_info_size);
13451debfc3dSmrg for (i = 0; i < reg_info_size; i++)
13461debfc3dSmrg initialize_lra_reg_info_element (i);
13471debfc3dSmrg copy_vec.truncate (0);
1348a2dc1f3fSmrg CLEAR_HARD_REG_SET (hard_regs_spilled_into);
13491debfc3dSmrg }
13501debfc3dSmrg
13511debfc3dSmrg
13521debfc3dSmrg /* Finish common reg info and copies. */
13531debfc3dSmrg static void
finish_reg_info(void)13541debfc3dSmrg finish_reg_info (void)
13551debfc3dSmrg {
13561debfc3dSmrg int i;
13571debfc3dSmrg
13581debfc3dSmrg for (i = 0; i < reg_info_size; i++)
13591debfc3dSmrg bitmap_clear (&lra_reg_info[i].insn_bitmap);
13601debfc3dSmrg free (lra_reg_info);
13611debfc3dSmrg reg_info_size = 0;
13621debfc3dSmrg }
13631debfc3dSmrg
13641debfc3dSmrg /* Expand common reg info if it is necessary. */
13651debfc3dSmrg static void
expand_reg_info(void)13661debfc3dSmrg expand_reg_info (void)
13671debfc3dSmrg {
13681debfc3dSmrg int i, old = reg_info_size;
13691debfc3dSmrg
13701debfc3dSmrg if (reg_info_size > max_reg_num ())
13711debfc3dSmrg return;
13721debfc3dSmrg reg_info_size = max_reg_num () * 3 / 2 + 1;
1373*8feb0f0bSmrg lra_reg_info = XRESIZEVEC (class lra_reg, lra_reg_info, reg_info_size);
13741debfc3dSmrg for (i = old; i < reg_info_size; i++)
13751debfc3dSmrg initialize_lra_reg_info_element (i);
13761debfc3dSmrg }
13771debfc3dSmrg
13781debfc3dSmrg /* Free all copies. */
13791debfc3dSmrg void
lra_free_copies(void)13801debfc3dSmrg lra_free_copies (void)
13811debfc3dSmrg {
13821debfc3dSmrg lra_copy_t cp;
13831debfc3dSmrg
13841debfc3dSmrg while (copy_vec.length () != 0)
13851debfc3dSmrg {
13861debfc3dSmrg cp = copy_vec.pop ();
13871debfc3dSmrg lra_reg_info[cp->regno1].copies = lra_reg_info[cp->regno2].copies = NULL;
13881debfc3dSmrg lra_copy_pool.remove (cp);
13891debfc3dSmrg }
13901debfc3dSmrg }
13911debfc3dSmrg
13921debfc3dSmrg /* Create copy of two pseudos REGNO1 and REGNO2. The copy execution
13931debfc3dSmrg frequency is FREQ. */
13941debfc3dSmrg void
lra_create_copy(int regno1,int regno2,int freq)13951debfc3dSmrg lra_create_copy (int regno1, int regno2, int freq)
13961debfc3dSmrg {
13971debfc3dSmrg bool regno1_dest_p;
13981debfc3dSmrg lra_copy_t cp;
13991debfc3dSmrg
14001debfc3dSmrg lra_assert (regno1 != regno2);
14011debfc3dSmrg regno1_dest_p = true;
14021debfc3dSmrg if (regno1 > regno2)
14031debfc3dSmrg {
14041debfc3dSmrg std::swap (regno1, regno2);
14051debfc3dSmrg regno1_dest_p = false;
14061debfc3dSmrg }
14071debfc3dSmrg cp = lra_copy_pool.allocate ();
14081debfc3dSmrg copy_vec.safe_push (cp);
14091debfc3dSmrg cp->regno1_dest_p = regno1_dest_p;
14101debfc3dSmrg cp->freq = freq;
14111debfc3dSmrg cp->regno1 = regno1;
14121debfc3dSmrg cp->regno2 = regno2;
14131debfc3dSmrg cp->regno1_next = lra_reg_info[regno1].copies;
14141debfc3dSmrg lra_reg_info[regno1].copies = cp;
14151debfc3dSmrg cp->regno2_next = lra_reg_info[regno2].copies;
14161debfc3dSmrg lra_reg_info[regno2].copies = cp;
14171debfc3dSmrg if (lra_dump_file != NULL)
14181debfc3dSmrg fprintf (lra_dump_file, " Creating copy r%d%sr%d@%d\n",
14191debfc3dSmrg regno1, regno1_dest_p ? "<-" : "->", regno2, freq);
14201debfc3dSmrg }
14211debfc3dSmrg
14221debfc3dSmrg /* Return N-th (0, 1, ...) copy. If there is no copy, return
14231debfc3dSmrg NULL. */
14241debfc3dSmrg lra_copy_t
lra_get_copy(int n)14251debfc3dSmrg lra_get_copy (int n)
14261debfc3dSmrg {
14271debfc3dSmrg if (n >= (int) copy_vec.length ())
14281debfc3dSmrg return NULL;
14291debfc3dSmrg return copy_vec[n];
14301debfc3dSmrg }
14311debfc3dSmrg
14321debfc3dSmrg
14331debfc3dSmrg
14341debfc3dSmrg /* This page contains code dealing with info about registers in
14351debfc3dSmrg insns. */
14361debfc3dSmrg
1437*8feb0f0bSmrg /* Process X of INSN recursively and add info (operand type is given
1438*8feb0f0bSmrg by TYPE) about registers in X to the insn DATA. If X can be early
1439*8feb0f0bSmrg clobbered, alternatives in which it can be early clobbered are given
1440*8feb0f0bSmrg by EARLY_CLOBBER_ALTS. */
14411debfc3dSmrg static void
add_regs_to_insn_regno_info(lra_insn_recog_data_t data,rtx x,rtx_insn * insn,enum op_type type,alternative_mask early_clobber_alts)1442a2dc1f3fSmrg add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
1443*8feb0f0bSmrg rtx_insn *insn, enum op_type type,
14441debfc3dSmrg alternative_mask early_clobber_alts)
14451debfc3dSmrg {
14461debfc3dSmrg int i, j, regno;
14471debfc3dSmrg bool subreg_p;
14481debfc3dSmrg machine_mode mode;
14491debfc3dSmrg const char *fmt;
14501debfc3dSmrg enum rtx_code code;
14511debfc3dSmrg struct lra_insn_reg *curr;
14521debfc3dSmrg
14531debfc3dSmrg code = GET_CODE (x);
14541debfc3dSmrg mode = GET_MODE (x);
14551debfc3dSmrg subreg_p = false;
14561debfc3dSmrg if (GET_CODE (x) == SUBREG)
14571debfc3dSmrg {
1458a2dc1f3fSmrg mode = wider_subreg_mode (x);
1459a2dc1f3fSmrg if (read_modify_subreg_p (x))
1460a2dc1f3fSmrg subreg_p = true;
14611debfc3dSmrg x = SUBREG_REG (x);
14621debfc3dSmrg code = GET_CODE (x);
14631debfc3dSmrg }
14641debfc3dSmrg if (REG_P (x))
14651debfc3dSmrg {
14661debfc3dSmrg regno = REGNO (x);
14671debfc3dSmrg /* Process all regs even unallocatable ones as we need info about
14681debfc3dSmrg all regs for rematerialization pass. */
14691debfc3dSmrg expand_reg_info ();
1470a2dc1f3fSmrg if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn)))
14711debfc3dSmrg {
14721debfc3dSmrg data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
1473*8feb0f0bSmrg early_clobber_alts, data->regs);
14741debfc3dSmrg return;
14751debfc3dSmrg }
14761debfc3dSmrg else
14771debfc3dSmrg {
14781debfc3dSmrg for (curr = data->regs; curr != NULL; curr = curr->next)
14791debfc3dSmrg if (curr->regno == regno)
14801debfc3dSmrg {
14811debfc3dSmrg if (curr->subreg_p != subreg_p || curr->biggest_mode != mode)
14821debfc3dSmrg /* The info cannot be integrated into the found
14831debfc3dSmrg structure. */
14841debfc3dSmrg data->regs = new_insn_reg (data->insn, regno, type, mode,
1485*8feb0f0bSmrg subreg_p, early_clobber_alts,
1486*8feb0f0bSmrg data->regs);
14871debfc3dSmrg else
14881debfc3dSmrg {
14891debfc3dSmrg if (curr->type != type)
14901debfc3dSmrg curr->type = OP_INOUT;
14911debfc3dSmrg curr->early_clobber_alts |= early_clobber_alts;
14921debfc3dSmrg }
14931debfc3dSmrg return;
14941debfc3dSmrg }
14951debfc3dSmrg gcc_unreachable ();
14961debfc3dSmrg }
14971debfc3dSmrg }
14981debfc3dSmrg
14991debfc3dSmrg switch (code)
15001debfc3dSmrg {
15011debfc3dSmrg case SET:
1502*8feb0f0bSmrg add_regs_to_insn_regno_info (data, SET_DEST (x), insn, OP_OUT, 0);
1503*8feb0f0bSmrg add_regs_to_insn_regno_info (data, SET_SRC (x), insn, OP_IN, 0);
15041debfc3dSmrg break;
15051debfc3dSmrg case CLOBBER:
15061debfc3dSmrg /* We treat clobber of non-operand hard registers as early
1507a2dc1f3fSmrg clobber. */
1508a2dc1f3fSmrg add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
1509*8feb0f0bSmrg ALL_ALTERNATIVES);
15101debfc3dSmrg break;
15111debfc3dSmrg case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
1512*8feb0f0bSmrg add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, 0);
15131debfc3dSmrg break;
15141debfc3dSmrg case PRE_MODIFY: case POST_MODIFY:
1515*8feb0f0bSmrg add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, 0);
1516*8feb0f0bSmrg add_regs_to_insn_regno_info (data, XEXP (x, 1), insn, OP_IN, 0);
15171debfc3dSmrg break;
15181debfc3dSmrg default:
15191debfc3dSmrg if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT)
15201debfc3dSmrg /* Some targets place small structures in registers for return
15211debfc3dSmrg values of functions, and those registers are wrapped in
15221debfc3dSmrg PARALLEL that we may see as the destination of a SET. Here
15231debfc3dSmrg is an example:
15241debfc3dSmrg
15251debfc3dSmrg (call_insn 13 12 14 2 (set (parallel:BLK [
15261debfc3dSmrg (expr_list:REG_DEP_TRUE (reg:DI 0 ax)
15271debfc3dSmrg (const_int 0 [0]))
15281debfc3dSmrg (expr_list:REG_DEP_TRUE (reg:DI 1 dx)
15291debfc3dSmrg (const_int 8 [0x8]))
15301debfc3dSmrg ])
15311debfc3dSmrg (call (mem:QI (symbol_ref:DI (... */
15321debfc3dSmrg type = OP_IN;
15331debfc3dSmrg fmt = GET_RTX_FORMAT (code);
15341debfc3dSmrg for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
15351debfc3dSmrg {
15361debfc3dSmrg if (fmt[i] == 'e')
1537*8feb0f0bSmrg add_regs_to_insn_regno_info (data, XEXP (x, i), insn, type, 0);
15381debfc3dSmrg else if (fmt[i] == 'E')
15391debfc3dSmrg {
15401debfc3dSmrg for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1541a2dc1f3fSmrg add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), insn,
1542*8feb0f0bSmrg type, 0);
15431debfc3dSmrg }
15441debfc3dSmrg }
15451debfc3dSmrg }
15461debfc3dSmrg }
15471debfc3dSmrg
15481debfc3dSmrg /* Return execution frequency of INSN. */
15491debfc3dSmrg static int
get_insn_freq(rtx_insn * insn)15501debfc3dSmrg get_insn_freq (rtx_insn *insn)
15511debfc3dSmrg {
15521debfc3dSmrg basic_block bb = BLOCK_FOR_INSN (insn);
15531debfc3dSmrg
15541debfc3dSmrg gcc_checking_assert (bb != NULL);
15551debfc3dSmrg return REG_FREQ_FROM_BB (bb);
15561debfc3dSmrg }
15571debfc3dSmrg
15581debfc3dSmrg /* Invalidate all reg info of INSN with DATA and execution frequency
15591debfc3dSmrg FREQ. Update common info about the invalidated registers. */
15601debfc3dSmrg static void
invalidate_insn_data_regno_info(lra_insn_recog_data_t data,rtx_insn * insn,int freq)15611debfc3dSmrg invalidate_insn_data_regno_info (lra_insn_recog_data_t data, rtx_insn *insn,
15621debfc3dSmrg int freq)
15631debfc3dSmrg {
15641debfc3dSmrg int uid;
15651debfc3dSmrg bool debug_p;
15661debfc3dSmrg unsigned int i;
15671debfc3dSmrg struct lra_insn_reg *ir, *next_ir;
15681debfc3dSmrg
15691debfc3dSmrg uid = INSN_UID (insn);
15701debfc3dSmrg debug_p = DEBUG_INSN_P (insn);
15711debfc3dSmrg for (ir = data->regs; ir != NULL; ir = next_ir)
15721debfc3dSmrg {
15731debfc3dSmrg i = ir->regno;
15741debfc3dSmrg next_ir = ir->next;
15751debfc3dSmrg lra_insn_reg_pool.remove (ir);
15761debfc3dSmrg bitmap_clear_bit (&lra_reg_info[i].insn_bitmap, uid);
15771debfc3dSmrg if (i >= FIRST_PSEUDO_REGISTER && ! debug_p)
15781debfc3dSmrg {
15791debfc3dSmrg lra_reg_info[i].nrefs--;
15801debfc3dSmrg lra_reg_info[i].freq -= freq;
15811debfc3dSmrg lra_assert (lra_reg_info[i].nrefs >= 0 && lra_reg_info[i].freq >= 0);
15821debfc3dSmrg }
15831debfc3dSmrg }
15841debfc3dSmrg data->regs = NULL;
15851debfc3dSmrg }
15861debfc3dSmrg
15871debfc3dSmrg /* Invalidate all reg info of INSN. Update common info about the
15881debfc3dSmrg invalidated registers. */
15891debfc3dSmrg void
lra_invalidate_insn_regno_info(rtx_insn * insn)15901debfc3dSmrg lra_invalidate_insn_regno_info (rtx_insn *insn)
15911debfc3dSmrg {
15921debfc3dSmrg invalidate_insn_data_regno_info (lra_get_insn_recog_data (insn), insn,
15931debfc3dSmrg get_insn_freq (insn));
15941debfc3dSmrg }
15951debfc3dSmrg
15961debfc3dSmrg /* Update common reg info from reg info of insn given by its DATA and
15971debfc3dSmrg execution frequency FREQ. */
15981debfc3dSmrg static void
setup_insn_reg_info(lra_insn_recog_data_t data,int freq)15991debfc3dSmrg setup_insn_reg_info (lra_insn_recog_data_t data, int freq)
16001debfc3dSmrg {
16011debfc3dSmrg unsigned int i;
16021debfc3dSmrg struct lra_insn_reg *ir;
16031debfc3dSmrg
16041debfc3dSmrg for (ir = data->regs; ir != NULL; ir = ir->next)
16051debfc3dSmrg if ((i = ir->regno) >= FIRST_PSEUDO_REGISTER)
16061debfc3dSmrg {
16071debfc3dSmrg lra_reg_info[i].nrefs++;
16081debfc3dSmrg lra_reg_info[i].freq += freq;
16091debfc3dSmrg }
16101debfc3dSmrg }
16111debfc3dSmrg
16121debfc3dSmrg /* Set up insn reg info of INSN. Update common reg info from reg info
16131debfc3dSmrg of INSN. */
16141debfc3dSmrg void
lra_update_insn_regno_info(rtx_insn * insn)16151debfc3dSmrg lra_update_insn_regno_info (rtx_insn *insn)
16161debfc3dSmrg {
1617a2dc1f3fSmrg int i, freq;
16181debfc3dSmrg lra_insn_recog_data_t data;
16191debfc3dSmrg struct lra_static_insn_data *static_data;
16201debfc3dSmrg enum rtx_code code;
16211debfc3dSmrg rtx link;
16221debfc3dSmrg
16231debfc3dSmrg if (! INSN_P (insn))
16241debfc3dSmrg return;
16251debfc3dSmrg data = lra_get_insn_recog_data (insn);
16261debfc3dSmrg static_data = data->insn_static_data;
1627a2dc1f3fSmrg freq = NONDEBUG_INSN_P (insn) ? get_insn_freq (insn) : 0;
16281debfc3dSmrg invalidate_insn_data_regno_info (data, insn, freq);
16291debfc3dSmrg for (i = static_data->n_operands - 1; i >= 0; i--)
1630a2dc1f3fSmrg add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn,
16311debfc3dSmrg static_data->operand[i].type,
16321debfc3dSmrg static_data->operand[i].early_clobber_alts);
16331debfc3dSmrg if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE)
1634a2dc1f3fSmrg add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), insn,
1635*8feb0f0bSmrg code == USE ? OP_IN : OP_OUT, 0);
16361debfc3dSmrg if (CALL_P (insn))
16371debfc3dSmrg /* On some targets call insns can refer to pseudos in memory in
16381debfc3dSmrg CALL_INSN_FUNCTION_USAGE list. Process them in order to
16391debfc3dSmrg consider their occurrences in calls for different
16401debfc3dSmrg transformations (e.g. inheritance) with given pseudos. */
16411debfc3dSmrg for (link = CALL_INSN_FUNCTION_USAGE (insn);
16421debfc3dSmrg link != NULL_RTX;
16431debfc3dSmrg link = XEXP (link, 1))
1644c0a68be4Smrg {
1645c0a68be4Smrg code = GET_CODE (XEXP (link, 0));
1646c0a68be4Smrg if ((code == USE || code == CLOBBER)
16471debfc3dSmrg && MEM_P (XEXP (XEXP (link, 0), 0)))
1648a2dc1f3fSmrg add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
1649*8feb0f0bSmrg code == USE ? OP_IN : OP_OUT, 0);
1650c0a68be4Smrg }
16511debfc3dSmrg if (NONDEBUG_INSN_P (insn))
16521debfc3dSmrg setup_insn_reg_info (data, freq);
16531debfc3dSmrg }
16541debfc3dSmrg
16551debfc3dSmrg /* Return reg info of insn given by it UID. */
16561debfc3dSmrg struct lra_insn_reg *
lra_get_insn_regs(int uid)16571debfc3dSmrg lra_get_insn_regs (int uid)
16581debfc3dSmrg {
16591debfc3dSmrg lra_insn_recog_data_t data;
16601debfc3dSmrg
16611debfc3dSmrg data = get_insn_recog_data_by_uid (uid);
16621debfc3dSmrg return data->regs;
16631debfc3dSmrg }
16641debfc3dSmrg
16651debfc3dSmrg
16661debfc3dSmrg
16671debfc3dSmrg /* Recursive hash function for RTL X. */
16681debfc3dSmrg hashval_t
lra_rtx_hash(rtx x)16691debfc3dSmrg lra_rtx_hash (rtx x)
16701debfc3dSmrg {
16711debfc3dSmrg int i, j;
16721debfc3dSmrg enum rtx_code code;
16731debfc3dSmrg const char *fmt;
16741debfc3dSmrg hashval_t val = 0;
16751debfc3dSmrg
16761debfc3dSmrg if (x == 0)
16771debfc3dSmrg return val;
16781debfc3dSmrg
16791debfc3dSmrg code = GET_CODE (x);
16801debfc3dSmrg val += (int) code + 4095;
16811debfc3dSmrg
16821debfc3dSmrg /* Some RTL can be compared nonrecursively. */
16831debfc3dSmrg switch (code)
16841debfc3dSmrg {
16851debfc3dSmrg case REG:
16861debfc3dSmrg return val + REGNO (x);
16871debfc3dSmrg
16881debfc3dSmrg case LABEL_REF:
16891debfc3dSmrg return iterative_hash_object (XEXP (x, 0), val);
16901debfc3dSmrg
16911debfc3dSmrg case SYMBOL_REF:
16921debfc3dSmrg return iterative_hash_object (XSTR (x, 0), val);
16931debfc3dSmrg
16941debfc3dSmrg case SCRATCH:
16951debfc3dSmrg case CONST_DOUBLE:
16961debfc3dSmrg case CONST_VECTOR:
16971debfc3dSmrg return val;
16981debfc3dSmrg
1699a05ac97eSmrg case CONST_INT:
1700a05ac97eSmrg return val + UINTVAL (x);
1701a05ac97eSmrg
17021debfc3dSmrg default:
17031debfc3dSmrg break;
17041debfc3dSmrg }
17051debfc3dSmrg
17061debfc3dSmrg /* Hash the elements. */
17071debfc3dSmrg fmt = GET_RTX_FORMAT (code);
17081debfc3dSmrg for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
17091debfc3dSmrg {
17101debfc3dSmrg switch (fmt[i])
17111debfc3dSmrg {
17121debfc3dSmrg case 'w':
17131debfc3dSmrg val += XWINT (x, i);
17141debfc3dSmrg break;
17151debfc3dSmrg
17161debfc3dSmrg case 'n':
17171debfc3dSmrg case 'i':
17181debfc3dSmrg val += XINT (x, i);
17191debfc3dSmrg break;
17201debfc3dSmrg
17211debfc3dSmrg case 'V':
17221debfc3dSmrg case 'E':
17231debfc3dSmrg val += XVECLEN (x, i);
17241debfc3dSmrg
17251debfc3dSmrg for (j = 0; j < XVECLEN (x, i); j++)
17261debfc3dSmrg val += lra_rtx_hash (XVECEXP (x, i, j));
17271debfc3dSmrg break;
17281debfc3dSmrg
17291debfc3dSmrg case 'e':
17301debfc3dSmrg val += lra_rtx_hash (XEXP (x, i));
17311debfc3dSmrg break;
17321debfc3dSmrg
17331debfc3dSmrg case 'S':
17341debfc3dSmrg case 's':
17351debfc3dSmrg val += htab_hash_string (XSTR (x, i));
17361debfc3dSmrg break;
17371debfc3dSmrg
17381debfc3dSmrg case 'u':
17391debfc3dSmrg case '0':
17401debfc3dSmrg case 't':
17411debfc3dSmrg break;
17421debfc3dSmrg
17431debfc3dSmrg /* It is believed that rtx's at this level will never
17441debfc3dSmrg contain anything but integers and other rtx's, except for
17451debfc3dSmrg within LABEL_REFs and SYMBOL_REFs. */
17461debfc3dSmrg default:
17471debfc3dSmrg abort ();
17481debfc3dSmrg }
17491debfc3dSmrg }
17501debfc3dSmrg return val;
17511debfc3dSmrg }
17521debfc3dSmrg
17531debfc3dSmrg
17541debfc3dSmrg
17551debfc3dSmrg /* This page contains code dealing with stack of the insns which
17561debfc3dSmrg should be processed by the next constraint pass. */
17571debfc3dSmrg
17581debfc3dSmrg /* Bitmap used to put an insn on the stack only in one exemplar. */
17591debfc3dSmrg static sbitmap lra_constraint_insn_stack_bitmap;
17601debfc3dSmrg
17611debfc3dSmrg /* The stack itself. */
17621debfc3dSmrg vec<rtx_insn *> lra_constraint_insn_stack;
17631debfc3dSmrg
17641debfc3dSmrg /* Put INSN on the stack. If ALWAYS_UPDATE is true, always update the reg
17651debfc3dSmrg info for INSN, otherwise only update it if INSN is not already on the
17661debfc3dSmrg stack. */
17671debfc3dSmrg static inline void
lra_push_insn_1(rtx_insn * insn,bool always_update)17681debfc3dSmrg lra_push_insn_1 (rtx_insn *insn, bool always_update)
17691debfc3dSmrg {
17701debfc3dSmrg unsigned int uid = INSN_UID (insn);
17711debfc3dSmrg if (always_update)
17721debfc3dSmrg lra_update_insn_regno_info (insn);
17731debfc3dSmrg if (uid >= SBITMAP_SIZE (lra_constraint_insn_stack_bitmap))
17741debfc3dSmrg lra_constraint_insn_stack_bitmap =
17751debfc3dSmrg sbitmap_resize (lra_constraint_insn_stack_bitmap, 3 * uid / 2, 0);
17761debfc3dSmrg if (bitmap_bit_p (lra_constraint_insn_stack_bitmap, uid))
17771debfc3dSmrg return;
17781debfc3dSmrg bitmap_set_bit (lra_constraint_insn_stack_bitmap, uid);
17791debfc3dSmrg if (! always_update)
17801debfc3dSmrg lra_update_insn_regno_info (insn);
17811debfc3dSmrg lra_constraint_insn_stack.safe_push (insn);
17821debfc3dSmrg }
17831debfc3dSmrg
17841debfc3dSmrg /* Put INSN on the stack. */
17851debfc3dSmrg void
lra_push_insn(rtx_insn * insn)17861debfc3dSmrg lra_push_insn (rtx_insn *insn)
17871debfc3dSmrg {
17881debfc3dSmrg lra_push_insn_1 (insn, false);
17891debfc3dSmrg }
17901debfc3dSmrg
17911debfc3dSmrg /* Put INSN on the stack and update its reg info. */
17921debfc3dSmrg void
lra_push_insn_and_update_insn_regno_info(rtx_insn * insn)17931debfc3dSmrg lra_push_insn_and_update_insn_regno_info (rtx_insn *insn)
17941debfc3dSmrg {
17951debfc3dSmrg lra_push_insn_1 (insn, true);
17961debfc3dSmrg }
17971debfc3dSmrg
17981debfc3dSmrg /* Put insn with UID on the stack. */
17991debfc3dSmrg void
lra_push_insn_by_uid(unsigned int uid)18001debfc3dSmrg lra_push_insn_by_uid (unsigned int uid)
18011debfc3dSmrg {
18021debfc3dSmrg lra_push_insn (lra_insn_recog_data[uid]->insn);
18031debfc3dSmrg }
18041debfc3dSmrg
18051debfc3dSmrg /* Take the last-inserted insns off the stack and return it. */
18061debfc3dSmrg rtx_insn *
lra_pop_insn(void)18071debfc3dSmrg lra_pop_insn (void)
18081debfc3dSmrg {
18091debfc3dSmrg rtx_insn *insn = lra_constraint_insn_stack.pop ();
18101debfc3dSmrg bitmap_clear_bit (lra_constraint_insn_stack_bitmap, INSN_UID (insn));
18111debfc3dSmrg return insn;
18121debfc3dSmrg }
18131debfc3dSmrg
18141debfc3dSmrg /* Return the current size of the insn stack. */
18151debfc3dSmrg unsigned int
lra_insn_stack_length(void)18161debfc3dSmrg lra_insn_stack_length (void)
18171debfc3dSmrg {
18181debfc3dSmrg return lra_constraint_insn_stack.length ();
18191debfc3dSmrg }
18201debfc3dSmrg
18211debfc3dSmrg /* Push insns FROM to TO (excluding it) going in reverse order. */
18221debfc3dSmrg static void
push_insns(rtx_insn * from,rtx_insn * to)18231debfc3dSmrg push_insns (rtx_insn *from, rtx_insn *to)
18241debfc3dSmrg {
18251debfc3dSmrg rtx_insn *insn;
18261debfc3dSmrg
18271debfc3dSmrg if (from == NULL_RTX)
18281debfc3dSmrg return;
18291debfc3dSmrg for (insn = from; insn != to; insn = PREV_INSN (insn))
18301debfc3dSmrg if (INSN_P (insn))
18311debfc3dSmrg lra_push_insn (insn);
18321debfc3dSmrg }
18331debfc3dSmrg
18341debfc3dSmrg /* Set up sp offset for insn in range [FROM, LAST]. The offset is
18351debfc3dSmrg taken from the next BB insn after LAST or zero if there in such
18361debfc3dSmrg insn. */
18371debfc3dSmrg static void
setup_sp_offset(rtx_insn * from,rtx_insn * last)18381debfc3dSmrg setup_sp_offset (rtx_insn *from, rtx_insn *last)
18391debfc3dSmrg {
1840a2dc1f3fSmrg rtx_insn *before = next_nonnote_nondebug_insn_bb (last);
1841a2dc1f3fSmrg poly_int64 offset = (before == NULL_RTX || ! INSN_P (before)
18421debfc3dSmrg ? 0 : lra_get_insn_recog_data (before)->sp_offset);
18431debfc3dSmrg
18441debfc3dSmrg for (rtx_insn *insn = from; insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
18451debfc3dSmrg lra_get_insn_recog_data (insn)->sp_offset = offset;
18461debfc3dSmrg }
18471debfc3dSmrg
18481debfc3dSmrg /* Emit insns BEFORE before INSN and insns AFTER after INSN. Put the
18491debfc3dSmrg insns onto the stack. Print about emitting the insns with
18501debfc3dSmrg TITLE. */
18511debfc3dSmrg void
lra_process_new_insns(rtx_insn * insn,rtx_insn * before,rtx_insn * after,const char * title)18521debfc3dSmrg lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
18531debfc3dSmrg const char *title)
18541debfc3dSmrg {
18551debfc3dSmrg rtx_insn *last;
18561debfc3dSmrg
18571debfc3dSmrg if (before == NULL_RTX && after == NULL_RTX)
18581debfc3dSmrg return;
18591debfc3dSmrg if (lra_dump_file != NULL)
18601debfc3dSmrg {
18611debfc3dSmrg dump_insn_slim (lra_dump_file, insn);
18621debfc3dSmrg if (before != NULL_RTX)
18631debfc3dSmrg {
18641debfc3dSmrg fprintf (lra_dump_file," %s before:\n", title);
18651debfc3dSmrg dump_rtl_slim (lra_dump_file, before, NULL, -1, 0);
18661debfc3dSmrg }
18671debfc3dSmrg if (after != NULL_RTX)
18681debfc3dSmrg {
18691debfc3dSmrg fprintf (lra_dump_file, " %s after:\n", title);
18701debfc3dSmrg dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
18711debfc3dSmrg }
18721debfc3dSmrg fprintf (lra_dump_file, "\n");
18731debfc3dSmrg }
18741debfc3dSmrg if (before != NULL_RTX)
18751debfc3dSmrg {
18761debfc3dSmrg if (cfun->can_throw_non_call_exceptions)
18771debfc3dSmrg copy_reg_eh_region_note_forward (insn, before, NULL);
18781debfc3dSmrg emit_insn_before (before, insn);
18791debfc3dSmrg push_insns (PREV_INSN (insn), PREV_INSN (before));
18801debfc3dSmrg setup_sp_offset (before, PREV_INSN (insn));
18811debfc3dSmrg }
18821debfc3dSmrg if (after != NULL_RTX)
18831debfc3dSmrg {
18841debfc3dSmrg if (cfun->can_throw_non_call_exceptions)
18851debfc3dSmrg copy_reg_eh_region_note_forward (insn, after, NULL);
18861debfc3dSmrg for (last = after; NEXT_INSN (last) != NULL_RTX; last = NEXT_INSN (last))
18871debfc3dSmrg ;
18881debfc3dSmrg emit_insn_after (after, insn);
18891debfc3dSmrg push_insns (last, insn);
18901debfc3dSmrg setup_sp_offset (after, last);
18911debfc3dSmrg }
18921debfc3dSmrg if (cfun->can_throw_non_call_exceptions)
18931debfc3dSmrg {
18941debfc3dSmrg rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
18951debfc3dSmrg if (note && !insn_could_throw_p (insn))
18961debfc3dSmrg remove_note (insn, note);
18971debfc3dSmrg }
18981debfc3dSmrg }
18991debfc3dSmrg
19001debfc3dSmrg
19011debfc3dSmrg /* Replace all references to register OLD_REGNO in *LOC with pseudo
19021debfc3dSmrg register NEW_REG. Try to simplify subreg of constant if SUBREG_P.
1903a2dc1f3fSmrg DEBUG_P is if LOC is within a DEBUG_INSN. Return true if any
1904a2dc1f3fSmrg change was made. */
19051debfc3dSmrg bool
lra_substitute_pseudo(rtx * loc,int old_regno,rtx new_reg,bool subreg_p,bool debug_p)1906a2dc1f3fSmrg lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p,
1907a2dc1f3fSmrg bool debug_p)
19081debfc3dSmrg {
19091debfc3dSmrg rtx x = *loc;
19101debfc3dSmrg bool result = false;
19111debfc3dSmrg enum rtx_code code;
19121debfc3dSmrg const char *fmt;
19131debfc3dSmrg int i, j;
19141debfc3dSmrg
19151debfc3dSmrg if (x == NULL_RTX)
19161debfc3dSmrg return false;
19171debfc3dSmrg
19181debfc3dSmrg code = GET_CODE (x);
19191debfc3dSmrg if (code == SUBREG && subreg_p)
19201debfc3dSmrg {
19211debfc3dSmrg rtx subst, inner = SUBREG_REG (x);
19221debfc3dSmrg /* Transform subreg of constant while we still have inner mode
19231debfc3dSmrg of the subreg. The subreg internal should not be an insn
19241debfc3dSmrg operand. */
19251debfc3dSmrg if (REG_P (inner) && (int) REGNO (inner) == old_regno
19261debfc3dSmrg && CONSTANT_P (new_reg)
19271debfc3dSmrg && (subst = simplify_subreg (GET_MODE (x), new_reg, GET_MODE (inner),
19281debfc3dSmrg SUBREG_BYTE (x))) != NULL_RTX)
19291debfc3dSmrg {
19301debfc3dSmrg *loc = subst;
19311debfc3dSmrg return true;
19321debfc3dSmrg }
19331debfc3dSmrg
19341debfc3dSmrg }
19351debfc3dSmrg else if (code == REG && (int) REGNO (x) == old_regno)
19361debfc3dSmrg {
19371debfc3dSmrg machine_mode mode = GET_MODE (x);
19381debfc3dSmrg machine_mode inner_mode = GET_MODE (new_reg);
19391debfc3dSmrg
19401debfc3dSmrg if (mode != inner_mode
1941c0a68be4Smrg && ! (CONST_SCALAR_INT_P (new_reg) && SCALAR_INT_MODE_P (mode)))
19421debfc3dSmrg {
1943a2dc1f3fSmrg poly_uint64 offset = 0;
1944a2dc1f3fSmrg if (partial_subreg_p (mode, inner_mode)
1945a2dc1f3fSmrg && SCALAR_INT_MODE_P (inner_mode))
1946a2dc1f3fSmrg offset = subreg_lowpart_offset (mode, inner_mode);
1947a2dc1f3fSmrg if (debug_p)
1948a2dc1f3fSmrg new_reg = gen_rtx_raw_SUBREG (mode, new_reg, offset);
19491debfc3dSmrg else
1950a2dc1f3fSmrg new_reg = gen_rtx_SUBREG (mode, new_reg, offset);
19511debfc3dSmrg }
19521debfc3dSmrg *loc = new_reg;
19531debfc3dSmrg return true;
19541debfc3dSmrg }
19551debfc3dSmrg
19561debfc3dSmrg /* Scan all the operand sub-expressions. */
19571debfc3dSmrg fmt = GET_RTX_FORMAT (code);
19581debfc3dSmrg for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
19591debfc3dSmrg {
19601debfc3dSmrg if (fmt[i] == 'e')
19611debfc3dSmrg {
19621debfc3dSmrg if (lra_substitute_pseudo (&XEXP (x, i), old_regno,
1963a2dc1f3fSmrg new_reg, subreg_p, debug_p))
19641debfc3dSmrg result = true;
19651debfc3dSmrg }
19661debfc3dSmrg else if (fmt[i] == 'E')
19671debfc3dSmrg {
19681debfc3dSmrg for (j = XVECLEN (x, i) - 1; j >= 0; j--)
19691debfc3dSmrg if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno,
1970a2dc1f3fSmrg new_reg, subreg_p, debug_p))
19711debfc3dSmrg result = true;
19721debfc3dSmrg }
19731debfc3dSmrg }
19741debfc3dSmrg return result;
19751debfc3dSmrg }
19761debfc3dSmrg
19771debfc3dSmrg /* Call lra_substitute_pseudo within an insn. Try to simplify subreg
19781debfc3dSmrg of constant if SUBREG_P. This won't update the insn ptr, just the
19791debfc3dSmrg contents of the insn. */
19801debfc3dSmrg bool
lra_substitute_pseudo_within_insn(rtx_insn * insn,int old_regno,rtx new_reg,bool subreg_p)19811debfc3dSmrg lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno,
19821debfc3dSmrg rtx new_reg, bool subreg_p)
19831debfc3dSmrg {
19841debfc3dSmrg rtx loc = insn;
1985a2dc1f3fSmrg return lra_substitute_pseudo (&loc, old_regno, new_reg, subreg_p,
1986a2dc1f3fSmrg DEBUG_INSN_P (insn));
19871debfc3dSmrg }
19881debfc3dSmrg
19891debfc3dSmrg
19901debfc3dSmrg
19911debfc3dSmrg /* This page contains code dealing with scratches (changing them onto
19921debfc3dSmrg pseudos and restoring them from the pseudos).
19931debfc3dSmrg
19941debfc3dSmrg We change scratches into pseudos at the beginning of LRA to
19951debfc3dSmrg simplify dealing with them (conflicts, hard register assignments).
19961debfc3dSmrg
19971debfc3dSmrg If the pseudo denoting scratch was spilled it means that we do need
19981debfc3dSmrg a hard register for it. Such pseudos are transformed back to
19991debfc3dSmrg scratches at the end of LRA. */
20001debfc3dSmrg
20011debfc3dSmrg /* Description of location of a former scratch operand. */
20021debfc3dSmrg struct sloc
20031debfc3dSmrg {
20041debfc3dSmrg rtx_insn *insn; /* Insn where the scratch was. */
20051debfc3dSmrg int nop; /* Number of the operand which was a scratch. */
2006c0a68be4Smrg int icode; /* Original icode from which scratch was removed. */
20071debfc3dSmrg };
20081debfc3dSmrg
20091debfc3dSmrg typedef struct sloc *sloc_t;
20101debfc3dSmrg
20111debfc3dSmrg /* Locations of the former scratches. */
20121debfc3dSmrg static vec<sloc_t> scratches;
20131debfc3dSmrg
20141debfc3dSmrg /* Bitmap of scratch regnos. */
20151debfc3dSmrg static bitmap_head scratch_bitmap;
20161debfc3dSmrg
20171debfc3dSmrg /* Bitmap of scratch operands. */
20181debfc3dSmrg static bitmap_head scratch_operand_bitmap;
20191debfc3dSmrg
20201debfc3dSmrg /* Return true if pseudo REGNO is made of SCRATCH. */
20211debfc3dSmrg bool
lra_former_scratch_p(int regno)20221debfc3dSmrg lra_former_scratch_p (int regno)
20231debfc3dSmrg {
20241debfc3dSmrg return bitmap_bit_p (&scratch_bitmap, regno);
20251debfc3dSmrg }
20261debfc3dSmrg
20271debfc3dSmrg /* Return true if the operand NOP of INSN is a former scratch. */
20281debfc3dSmrg bool
lra_former_scratch_operand_p(rtx_insn * insn,int nop)20291debfc3dSmrg lra_former_scratch_operand_p (rtx_insn *insn, int nop)
20301debfc3dSmrg {
20311debfc3dSmrg return bitmap_bit_p (&scratch_operand_bitmap,
20321debfc3dSmrg INSN_UID (insn) * MAX_RECOG_OPERANDS + nop) != 0;
20331debfc3dSmrg }
20341debfc3dSmrg
20351debfc3dSmrg /* Register operand NOP in INSN as a former scratch. It will be
20361debfc3dSmrg changed to scratch back, if it is necessary, at the LRA end. */
20371debfc3dSmrg void
lra_register_new_scratch_op(rtx_insn * insn,int nop,int icode)2038c0a68be4Smrg lra_register_new_scratch_op (rtx_insn *insn, int nop, int icode)
20391debfc3dSmrg {
20401debfc3dSmrg lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
20411debfc3dSmrg rtx op = *id->operand_loc[nop];
20421debfc3dSmrg sloc_t loc = XNEW (struct sloc);
20431debfc3dSmrg lra_assert (REG_P (op));
20441debfc3dSmrg loc->insn = insn;
20451debfc3dSmrg loc->nop = nop;
2046c0a68be4Smrg loc->icode = icode;
20471debfc3dSmrg scratches.safe_push (loc);
20481debfc3dSmrg bitmap_set_bit (&scratch_bitmap, REGNO (op));
20491debfc3dSmrg bitmap_set_bit (&scratch_operand_bitmap,
20501debfc3dSmrg INSN_UID (insn) * MAX_RECOG_OPERANDS + nop);
20511debfc3dSmrg add_reg_note (insn, REG_UNUSED, op);
20521debfc3dSmrg }
20531debfc3dSmrg
2054c0a68be4Smrg /* Change INSN's scratches into pseudos and save their location. */
20551debfc3dSmrg static void
remove_scratches_1(rtx_insn * insn)2056c0a68be4Smrg remove_scratches_1 (rtx_insn *insn)
20571debfc3dSmrg {
20581debfc3dSmrg int i;
20591debfc3dSmrg bool insn_changed_p;
20601debfc3dSmrg rtx reg;
20611debfc3dSmrg lra_insn_recog_data_t id;
20621debfc3dSmrg struct lra_static_insn_data *static_id;
20631debfc3dSmrg
20641debfc3dSmrg id = lra_get_insn_recog_data (insn);
20651debfc3dSmrg static_id = id->insn_static_data;
20661debfc3dSmrg insn_changed_p = false;
20671debfc3dSmrg for (i = 0; i < static_id->n_operands; i++)
20681debfc3dSmrg if (GET_CODE (*id->operand_loc[i]) == SCRATCH
20691debfc3dSmrg && GET_MODE (*id->operand_loc[i]) != VOIDmode)
20701debfc3dSmrg {
20711debfc3dSmrg insn_changed_p = true;
20721debfc3dSmrg *id->operand_loc[i] = reg
20731debfc3dSmrg = lra_create_new_reg (static_id->operand[i].mode,
20741debfc3dSmrg *id->operand_loc[i], ALL_REGS, NULL);
2075c0a68be4Smrg lra_register_new_scratch_op (insn, i, id->icode);
20761debfc3dSmrg if (lra_dump_file != NULL)
20771debfc3dSmrg fprintf (lra_dump_file,
20781debfc3dSmrg "Removing SCRATCH in insn #%u (nop %d)\n",
20791debfc3dSmrg INSN_UID (insn), i);
20801debfc3dSmrg }
20811debfc3dSmrg if (insn_changed_p)
20821debfc3dSmrg /* Because we might use DF right after caller-saves sub-pass
20831debfc3dSmrg we need to keep DF info up to date. */
20841debfc3dSmrg df_insn_rescan (insn);
20851debfc3dSmrg }
2086c0a68be4Smrg
2087c0a68be4Smrg /* Change scratches into pseudos and save their location. */
2088c0a68be4Smrg static void
remove_scratches(void)2089c0a68be4Smrg remove_scratches (void)
2090c0a68be4Smrg {
2091c0a68be4Smrg basic_block bb;
2092c0a68be4Smrg rtx_insn *insn;
2093c0a68be4Smrg
2094c0a68be4Smrg scratches.create (get_max_uid ());
2095c0a68be4Smrg bitmap_initialize (&scratch_bitmap, ®_obstack);
2096c0a68be4Smrg bitmap_initialize (&scratch_operand_bitmap, ®_obstack);
2097c0a68be4Smrg FOR_EACH_BB_FN (bb, cfun)
2098c0a68be4Smrg FOR_BB_INSNS (bb, insn)
2099c0a68be4Smrg if (INSN_P (insn))
2100c0a68be4Smrg remove_scratches_1 (insn);
21011debfc3dSmrg }
21021debfc3dSmrg
21031debfc3dSmrg /* Changes pseudos created by function remove_scratches onto scratches. */
21041debfc3dSmrg static void
restore_scratches(void)21051debfc3dSmrg restore_scratches (void)
21061debfc3dSmrg {
21071debfc3dSmrg int regno;
21081debfc3dSmrg unsigned i;
21091debfc3dSmrg sloc_t loc;
21101debfc3dSmrg rtx_insn *last = NULL;
21111debfc3dSmrg lra_insn_recog_data_t id = NULL;
21121debfc3dSmrg
21131debfc3dSmrg for (i = 0; scratches.iterate (i, &loc); i++)
21141debfc3dSmrg {
21151debfc3dSmrg /* Ignore already deleted insns. */
21161debfc3dSmrg if (NOTE_P (loc->insn)
21171debfc3dSmrg && NOTE_KIND (loc->insn) == NOTE_INSN_DELETED)
21181debfc3dSmrg continue;
21191debfc3dSmrg if (last != loc->insn)
21201debfc3dSmrg {
21211debfc3dSmrg last = loc->insn;
21221debfc3dSmrg id = lra_get_insn_recog_data (last);
21231debfc3dSmrg }
2124c0a68be4Smrg if (loc->icode != id->icode)
2125c0a68be4Smrg {
2126c0a68be4Smrg /* The icode doesn't match, which means the insn has been modified
2127c0a68be4Smrg (e.g. register elimination). The scratch cannot be restored. */
2128c0a68be4Smrg continue;
2129c0a68be4Smrg }
21301debfc3dSmrg if (REG_P (*id->operand_loc[loc->nop])
21311debfc3dSmrg && ((regno = REGNO (*id->operand_loc[loc->nop]))
21321debfc3dSmrg >= FIRST_PSEUDO_REGISTER)
21331debfc3dSmrg && lra_get_regno_hard_regno (regno) < 0)
21341debfc3dSmrg {
21351debfc3dSmrg /* It should be only case when scratch register with chosen
21361debfc3dSmrg constraint 'X' did not get memory or hard register. */
21371debfc3dSmrg lra_assert (lra_former_scratch_p (regno));
21381debfc3dSmrg *id->operand_loc[loc->nop]
21391debfc3dSmrg = gen_rtx_SCRATCH (GET_MODE (*id->operand_loc[loc->nop]));
21401debfc3dSmrg lra_update_dup (id, loc->nop);
21411debfc3dSmrg if (lra_dump_file != NULL)
21421debfc3dSmrg fprintf (lra_dump_file, "Restoring SCRATCH in insn #%u(nop %d)\n",
21431debfc3dSmrg INSN_UID (loc->insn), loc->nop);
21441debfc3dSmrg }
21451debfc3dSmrg }
21461debfc3dSmrg for (i = 0; scratches.iterate (i, &loc); i++)
21471debfc3dSmrg free (loc);
21481debfc3dSmrg scratches.release ();
21491debfc3dSmrg bitmap_clear (&scratch_bitmap);
21501debfc3dSmrg bitmap_clear (&scratch_operand_bitmap);
21511debfc3dSmrg }
21521debfc3dSmrg
21531debfc3dSmrg
21541debfc3dSmrg
21551debfc3dSmrg /* Function checks RTL for correctness. If FINAL_P is true, it is
21561debfc3dSmrg done at the end of LRA and the check is more rigorous. */
21571debfc3dSmrg static void
check_rtl(bool final_p)21581debfc3dSmrg check_rtl (bool final_p)
21591debfc3dSmrg {
21601debfc3dSmrg basic_block bb;
21611debfc3dSmrg rtx_insn *insn;
21621debfc3dSmrg
21631debfc3dSmrg lra_assert (! final_p || reload_completed);
21641debfc3dSmrg FOR_EACH_BB_FN (bb, cfun)
21651debfc3dSmrg FOR_BB_INSNS (bb, insn)
21661debfc3dSmrg if (NONDEBUG_INSN_P (insn)
21671debfc3dSmrg && GET_CODE (PATTERN (insn)) != USE
21681debfc3dSmrg && GET_CODE (PATTERN (insn)) != CLOBBER
21691debfc3dSmrg && GET_CODE (PATTERN (insn)) != ASM_INPUT)
21701debfc3dSmrg {
21711debfc3dSmrg if (final_p)
21721debfc3dSmrg {
21731debfc3dSmrg extract_constrain_insn (insn);
21741debfc3dSmrg continue;
21751debfc3dSmrg }
21761debfc3dSmrg /* LRA code is based on assumption that all addresses can be
21771debfc3dSmrg correctly decomposed. LRA can generate reloads for
21781debfc3dSmrg decomposable addresses. The decomposition code checks the
21791debfc3dSmrg correctness of the addresses. So we don't need to check
21801debfc3dSmrg the addresses here. Don't call insn_invalid_p here, it can
21811debfc3dSmrg change the code at this stage. */
21821debfc3dSmrg if (recog_memoized (insn) < 0 && asm_noperands (PATTERN (insn)) < 0)
21831debfc3dSmrg fatal_insn_not_found (insn);
21841debfc3dSmrg }
21851debfc3dSmrg }
21861debfc3dSmrg
21871debfc3dSmrg /* Determine if the current function has an exception receiver block
21881debfc3dSmrg that reaches the exit block via non-exceptional edges */
21891debfc3dSmrg static bool
has_nonexceptional_receiver(void)21901debfc3dSmrg has_nonexceptional_receiver (void)
21911debfc3dSmrg {
21921debfc3dSmrg edge e;
21931debfc3dSmrg edge_iterator ei;
21941debfc3dSmrg basic_block *tos, *worklist, bb;
21951debfc3dSmrg
21961debfc3dSmrg /* If we're not optimizing, then just err on the safe side. */
21971debfc3dSmrg if (!optimize)
21981debfc3dSmrg return true;
21991debfc3dSmrg
22001debfc3dSmrg /* First determine which blocks can reach exit via normal paths. */
22011debfc3dSmrg tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
22021debfc3dSmrg
22031debfc3dSmrg FOR_EACH_BB_FN (bb, cfun)
22041debfc3dSmrg bb->flags &= ~BB_REACHABLE;
22051debfc3dSmrg
22061debfc3dSmrg /* Place the exit block on our worklist. */
22071debfc3dSmrg EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_REACHABLE;
22081debfc3dSmrg *tos++ = EXIT_BLOCK_PTR_FOR_FN (cfun);
22091debfc3dSmrg
22101debfc3dSmrg /* Iterate: find everything reachable from what we've already seen. */
22111debfc3dSmrg while (tos != worklist)
22121debfc3dSmrg {
22131debfc3dSmrg bb = *--tos;
22141debfc3dSmrg
22151debfc3dSmrg FOR_EACH_EDGE (e, ei, bb->preds)
22161debfc3dSmrg if (e->flags & EDGE_ABNORMAL)
22171debfc3dSmrg {
22181debfc3dSmrg free (worklist);
22191debfc3dSmrg return true;
22201debfc3dSmrg }
22211debfc3dSmrg else
22221debfc3dSmrg {
22231debfc3dSmrg basic_block src = e->src;
22241debfc3dSmrg
22251debfc3dSmrg if (!(src->flags & BB_REACHABLE))
22261debfc3dSmrg {
22271debfc3dSmrg src->flags |= BB_REACHABLE;
22281debfc3dSmrg *tos++ = src;
22291debfc3dSmrg }
22301debfc3dSmrg }
22311debfc3dSmrg }
22321debfc3dSmrg free (worklist);
22331debfc3dSmrg /* No exceptional block reached exit unexceptionally. */
22341debfc3dSmrg return false;
22351debfc3dSmrg }
22361debfc3dSmrg
22371debfc3dSmrg
22381debfc3dSmrg /* Process recursively X of INSN and add REG_INC notes if necessary. */
22391debfc3dSmrg static void
add_auto_inc_notes(rtx_insn * insn,rtx x)22401debfc3dSmrg add_auto_inc_notes (rtx_insn *insn, rtx x)
22411debfc3dSmrg {
22421debfc3dSmrg enum rtx_code code = GET_CODE (x);
22431debfc3dSmrg const char *fmt;
22441debfc3dSmrg int i, j;
22451debfc3dSmrg
22461debfc3dSmrg if (code == MEM && auto_inc_p (XEXP (x, 0)))
22471debfc3dSmrg {
22481debfc3dSmrg add_reg_note (insn, REG_INC, XEXP (XEXP (x, 0), 0));
22491debfc3dSmrg return;
22501debfc3dSmrg }
22511debfc3dSmrg
22521debfc3dSmrg /* Scan all X sub-expressions. */
22531debfc3dSmrg fmt = GET_RTX_FORMAT (code);
22541debfc3dSmrg for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
22551debfc3dSmrg {
22561debfc3dSmrg if (fmt[i] == 'e')
22571debfc3dSmrg add_auto_inc_notes (insn, XEXP (x, i));
22581debfc3dSmrg else if (fmt[i] == 'E')
22591debfc3dSmrg for (j = XVECLEN (x, i) - 1; j >= 0; j--)
22601debfc3dSmrg add_auto_inc_notes (insn, XVECEXP (x, i, j));
22611debfc3dSmrg }
22621debfc3dSmrg }
22631debfc3dSmrg
22641debfc3dSmrg
22651debfc3dSmrg /* Remove all REG_DEAD and REG_UNUSED notes and regenerate REG_INC.
22661debfc3dSmrg We change pseudos by hard registers without notification of DF and
22671debfc3dSmrg that can make the notes obsolete. DF-infrastructure does not deal
22681debfc3dSmrg with REG_INC notes -- so we should regenerate them here. */
22691debfc3dSmrg static void
update_inc_notes(void)22701debfc3dSmrg update_inc_notes (void)
22711debfc3dSmrg {
22721debfc3dSmrg rtx *pnote;
22731debfc3dSmrg basic_block bb;
22741debfc3dSmrg rtx_insn *insn;
22751debfc3dSmrg
22761debfc3dSmrg FOR_EACH_BB_FN (bb, cfun)
22771debfc3dSmrg FOR_BB_INSNS (bb, insn)
22781debfc3dSmrg if (NONDEBUG_INSN_P (insn))
22791debfc3dSmrg {
22801debfc3dSmrg pnote = ®_NOTES (insn);
22811debfc3dSmrg while (*pnote != 0)
22821debfc3dSmrg {
22831debfc3dSmrg if (REG_NOTE_KIND (*pnote) == REG_DEAD
22841debfc3dSmrg || REG_NOTE_KIND (*pnote) == REG_UNUSED
22851debfc3dSmrg || REG_NOTE_KIND (*pnote) == REG_INC)
22861debfc3dSmrg *pnote = XEXP (*pnote, 1);
22871debfc3dSmrg else
22881debfc3dSmrg pnote = &XEXP (*pnote, 1);
22891debfc3dSmrg }
22901debfc3dSmrg
22911debfc3dSmrg if (AUTO_INC_DEC)
22921debfc3dSmrg add_auto_inc_notes (insn, PATTERN (insn));
22931debfc3dSmrg }
22941debfc3dSmrg }
22951debfc3dSmrg
22961debfc3dSmrg /* Set to 1 while in lra. */
22971debfc3dSmrg int lra_in_progress;
22981debfc3dSmrg
22991debfc3dSmrg /* Start of pseudo regnos before the LRA. */
23001debfc3dSmrg int lra_new_regno_start;
23011debfc3dSmrg
23021debfc3dSmrg /* Start of reload pseudo regnos before the new spill pass. */
23031debfc3dSmrg int lra_constraint_new_regno_start;
23041debfc3dSmrg
23051debfc3dSmrg /* Avoid spilling pseudos with regno more than the following value if
23061debfc3dSmrg it is possible. */
23071debfc3dSmrg int lra_bad_spill_regno_start;
23081debfc3dSmrg
2309*8feb0f0bSmrg /* A pseudo of Pmode. */
2310*8feb0f0bSmrg rtx lra_pmode_pseudo;
2311*8feb0f0bSmrg
23121debfc3dSmrg /* Inheritance pseudo regnos before the new spill pass. */
23131debfc3dSmrg bitmap_head lra_inheritance_pseudos;
23141debfc3dSmrg
23151debfc3dSmrg /* Split regnos before the new spill pass. */
23161debfc3dSmrg bitmap_head lra_split_regs;
23171debfc3dSmrg
23181debfc3dSmrg /* Reload pseudo regnos before the new assignment pass which still can
23191debfc3dSmrg be spilled after the assignment pass as memory is also accepted in
23201debfc3dSmrg insns for the reload pseudos. */
23211debfc3dSmrg bitmap_head lra_optional_reload_pseudos;
23221debfc3dSmrg
23231debfc3dSmrg /* Pseudo regnos used for subreg reloads before the new assignment
23241debfc3dSmrg pass. Such pseudos still can be spilled after the assignment
23251debfc3dSmrg pass. */
23261debfc3dSmrg bitmap_head lra_subreg_reload_pseudos;
23271debfc3dSmrg
23281debfc3dSmrg /* File used for output of LRA debug information. */
23291debfc3dSmrg FILE *lra_dump_file;
23301debfc3dSmrg
2331c0a68be4Smrg /* True if we found an asm error. */
2332c0a68be4Smrg bool lra_asm_error_p;
2333c0a68be4Smrg
23341debfc3dSmrg /* True if we should try spill into registers of different classes
23351debfc3dSmrg instead of memory. */
23361debfc3dSmrg bool lra_reg_spill_p;
23371debfc3dSmrg
23381debfc3dSmrg /* Set up value LRA_REG_SPILL_P. */
23391debfc3dSmrg static void
setup_reg_spill_flag(void)23401debfc3dSmrg setup_reg_spill_flag (void)
23411debfc3dSmrg {
23421debfc3dSmrg int cl, mode;
23431debfc3dSmrg
23441debfc3dSmrg if (targetm.spill_class != NULL)
23451debfc3dSmrg for (cl = 0; cl < (int) LIM_REG_CLASSES; cl++)
23461debfc3dSmrg for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
23471debfc3dSmrg if (targetm.spill_class ((enum reg_class) cl,
23481debfc3dSmrg (machine_mode) mode) != NO_REGS)
23491debfc3dSmrg {
23501debfc3dSmrg lra_reg_spill_p = true;
23511debfc3dSmrg return;
23521debfc3dSmrg }
23531debfc3dSmrg lra_reg_spill_p = false;
23541debfc3dSmrg }
23551debfc3dSmrg
23561debfc3dSmrg /* True if the current function is too big to use regular algorithms
23571debfc3dSmrg in LRA. In other words, we should use simpler and faster algorithms
23581debfc3dSmrg in LRA. It also means we should not worry about generation code
23591debfc3dSmrg for caller saves. The value is set up in IRA. */
23601debfc3dSmrg bool lra_simple_p;
23611debfc3dSmrg
23621debfc3dSmrg /* Major LRA entry function. F is a file should be used to dump LRA
23631debfc3dSmrg debug info. */
23641debfc3dSmrg void
lra(FILE * f)23651debfc3dSmrg lra (FILE *f)
23661debfc3dSmrg {
23671debfc3dSmrg int i;
23681debfc3dSmrg bool live_p, inserted_p;
23691debfc3dSmrg
23701debfc3dSmrg lra_dump_file = f;
2371c0a68be4Smrg lra_asm_error_p = false;
2372*8feb0f0bSmrg lra_pmode_pseudo = gen_reg_rtx (Pmode);
23731debfc3dSmrg
23741debfc3dSmrg timevar_push (TV_LRA);
23751debfc3dSmrg
23761debfc3dSmrg /* Make sure that the last insn is a note. Some subsequent passes
23771debfc3dSmrg need it. */
23781debfc3dSmrg emit_note (NOTE_INSN_DELETED);
23791debfc3dSmrg
2380*8feb0f0bSmrg lra_no_alloc_regs = ira_no_alloc_regs;
23811debfc3dSmrg
23821debfc3dSmrg init_reg_info ();
23831debfc3dSmrg expand_reg_info ();
23841debfc3dSmrg
23851debfc3dSmrg init_insn_recog_data ();
23861debfc3dSmrg
23871debfc3dSmrg /* Some quick check on RTL generated by previous passes. */
23881debfc3dSmrg if (flag_checking)
23891debfc3dSmrg check_rtl (false);
23901debfc3dSmrg
23911debfc3dSmrg lra_in_progress = 1;
23921debfc3dSmrg
23931debfc3dSmrg lra_live_range_iter = lra_coalesce_iter = lra_constraint_iter = 0;
23941debfc3dSmrg lra_assignment_iter = lra_assignment_iter_after_spill = 0;
23951debfc3dSmrg lra_inheritance_iter = lra_undo_inheritance_iter = 0;
23961debfc3dSmrg lra_rematerialization_iter = 0;
23971debfc3dSmrg
23981debfc3dSmrg setup_reg_spill_flag ();
23991debfc3dSmrg
24001debfc3dSmrg /* Function remove_scratches can creates new pseudos for clobbers --
24011debfc3dSmrg so set up lra_constraint_new_regno_start before its call to
24021debfc3dSmrg permit changing reg classes for pseudos created by this
24031debfc3dSmrg simplification. */
24041debfc3dSmrg lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num ();
24051debfc3dSmrg lra_bad_spill_regno_start = INT_MAX;
24061debfc3dSmrg remove_scratches ();
24071debfc3dSmrg
24081debfc3dSmrg /* A function that has a non-local label that can reach the exit
24091debfc3dSmrg block via non-exceptional paths must save all call-saved
24101debfc3dSmrg registers. */
24111debfc3dSmrg if (cfun->has_nonlocal_label && has_nonexceptional_receiver ())
24121debfc3dSmrg crtl->saves_all_registers = 1;
24131debfc3dSmrg
24141debfc3dSmrg if (crtl->saves_all_registers)
24151debfc3dSmrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2416*8feb0f0bSmrg if (!crtl->abi->clobbers_full_reg_p (i)
2417*8feb0f0bSmrg && !fixed_regs[i]
2418*8feb0f0bSmrg && !LOCAL_REGNO (i))
24191debfc3dSmrg df_set_regs_ever_live (i, true);
24201debfc3dSmrg
24211debfc3dSmrg /* We don't DF from now and avoid its using because it is to
24221debfc3dSmrg expensive when a lot of RTL changes are made. */
24231debfc3dSmrg df_set_flags (DF_NO_INSN_RESCAN);
24241debfc3dSmrg lra_constraint_insn_stack.create (get_max_uid ());
24251debfc3dSmrg lra_constraint_insn_stack_bitmap = sbitmap_alloc (get_max_uid ());
24261debfc3dSmrg bitmap_clear (lra_constraint_insn_stack_bitmap);
24271debfc3dSmrg lra_live_ranges_init ();
24281debfc3dSmrg lra_constraints_init ();
24291debfc3dSmrg lra_curr_reload_num = 0;
24301debfc3dSmrg push_insns (get_last_insn (), NULL);
24311debfc3dSmrg /* It is needed for the 1st coalescing. */
24321debfc3dSmrg bitmap_initialize (&lra_inheritance_pseudos, ®_obstack);
24331debfc3dSmrg bitmap_initialize (&lra_split_regs, ®_obstack);
24341debfc3dSmrg bitmap_initialize (&lra_optional_reload_pseudos, ®_obstack);
24351debfc3dSmrg bitmap_initialize (&lra_subreg_reload_pseudos, ®_obstack);
24361debfc3dSmrg live_p = false;
2437a2dc1f3fSmrg if (maybe_ne (get_frame_size (), 0) && crtl->stack_alignment_needed)
24381debfc3dSmrg /* If we have a stack frame, we must align it now. The stack size
24391debfc3dSmrg may be a part of the offset computation for register
24401debfc3dSmrg elimination. */
24411debfc3dSmrg assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
24421debfc3dSmrg lra_init_equiv ();
24431debfc3dSmrg for (;;)
24441debfc3dSmrg {
24451debfc3dSmrg for (;;)
24461debfc3dSmrg {
24471debfc3dSmrg bool reloads_p = lra_constraints (lra_constraint_iter == 0);
24481debfc3dSmrg /* Constraint transformations may result in that eliminable
24491debfc3dSmrg hard regs become uneliminable and pseudos which use them
24501debfc3dSmrg should be spilled. It is better to do it before pseudo
24511debfc3dSmrg assignments.
24521debfc3dSmrg
24531debfc3dSmrg For example, rs6000 can make
24541debfc3dSmrg RS6000_PIC_OFFSET_TABLE_REGNUM uneliminable if we started
24551debfc3dSmrg to use a constant pool. */
24561debfc3dSmrg lra_eliminate (false, false);
24571debfc3dSmrg /* We should try to assign hard registers to scratches even
24581debfc3dSmrg if there were no RTL transformations in lra_constraints.
24591debfc3dSmrg Also we should check IRA assignments on the first
24601debfc3dSmrg iteration as they can be wrong because of early clobbers
24611debfc3dSmrg operands which are ignored in IRA. */
24621debfc3dSmrg if (! reloads_p && lra_constraint_iter > 1)
24631debfc3dSmrg {
24641debfc3dSmrg /* Stack is not empty here only when there are changes
24651debfc3dSmrg during the elimination sub-pass. */
24661debfc3dSmrg if (bitmap_empty_p (lra_constraint_insn_stack_bitmap))
24671debfc3dSmrg break;
24681debfc3dSmrg else
24691debfc3dSmrg /* If there are no reloads but changing due
24701debfc3dSmrg elimination, restart the constraint sub-pass
24711debfc3dSmrg first. */
24721debfc3dSmrg continue;
24731debfc3dSmrg }
24741debfc3dSmrg /* Do inheritance only for regular algorithms. */
24751debfc3dSmrg if (! lra_simple_p)
24761debfc3dSmrg lra_inheritance ();
24771debfc3dSmrg if (live_p)
24781debfc3dSmrg lra_clear_live_ranges ();
2479a2dc1f3fSmrg bool fails_p;
2480a2dc1f3fSmrg do
2481a2dc1f3fSmrg {
2482a2dc1f3fSmrg /* We need live ranges for lra_assign -- so build them.
2483a2dc1f3fSmrg But don't remove dead insns or change global live
2484a2dc1f3fSmrg info as we can undo inheritance transformations after
2485a2dc1f3fSmrg inheritance pseudo assigning. */
2486*8feb0f0bSmrg lra_create_live_ranges (true, !lra_simple_p);
24871debfc3dSmrg live_p = true;
2488a2dc1f3fSmrg /* If we don't spill non-reload and non-inheritance
2489a2dc1f3fSmrg pseudos, there is no sense to run memory-memory move
2490a2dc1f3fSmrg coalescing. If inheritance pseudos were spilled, the
2491a2dc1f3fSmrg memory-memory moves involving them will be removed by
2492a2dc1f3fSmrg pass undoing inheritance. */
24931debfc3dSmrg if (lra_simple_p)
2494a2dc1f3fSmrg lra_assign (fails_p);
24951debfc3dSmrg else
24961debfc3dSmrg {
2497a2dc1f3fSmrg bool spill_p = !lra_assign (fails_p);
24981debfc3dSmrg
24991debfc3dSmrg if (lra_undo_inheritance ())
25001debfc3dSmrg live_p = false;
2501a2dc1f3fSmrg if (spill_p && ! fails_p)
25021debfc3dSmrg {
25031debfc3dSmrg if (! live_p)
25041debfc3dSmrg {
25051debfc3dSmrg lra_create_live_ranges (true, true);
25061debfc3dSmrg live_p = true;
25071debfc3dSmrg }
25081debfc3dSmrg if (lra_coalesce ())
25091debfc3dSmrg live_p = false;
25101debfc3dSmrg }
25111debfc3dSmrg if (! live_p)
25121debfc3dSmrg lra_clear_live_ranges ();
25131debfc3dSmrg }
2514a2dc1f3fSmrg if (fails_p)
2515a2dc1f3fSmrg {
2516a2dc1f3fSmrg /* It is a very rare case. It is the last hope to
2517a2dc1f3fSmrg split a hard regno live range for a reload
2518a2dc1f3fSmrg pseudo. */
2519a2dc1f3fSmrg if (live_p)
2520a2dc1f3fSmrg lra_clear_live_ranges ();
2521a2dc1f3fSmrg live_p = false;
2522a2dc1f3fSmrg if (! lra_split_hard_reg_for ())
2523a2dc1f3fSmrg break;
2524a2dc1f3fSmrg }
2525a2dc1f3fSmrg }
2526a2dc1f3fSmrg while (fails_p);
2527*8feb0f0bSmrg if (! live_p) {
2528*8feb0f0bSmrg /* We need the correct reg notes for work of constraint sub-pass. */
2529*8feb0f0bSmrg lra_create_live_ranges (true, true);
2530*8feb0f0bSmrg live_p = true;
2531*8feb0f0bSmrg }
25321debfc3dSmrg }
25331debfc3dSmrg /* Don't clear optional reloads bitmap until all constraints are
25341debfc3dSmrg satisfied as we need to differ them from regular reloads. */
25351debfc3dSmrg bitmap_clear (&lra_optional_reload_pseudos);
25361debfc3dSmrg bitmap_clear (&lra_subreg_reload_pseudos);
25371debfc3dSmrg bitmap_clear (&lra_inheritance_pseudos);
25381debfc3dSmrg bitmap_clear (&lra_split_regs);
25391debfc3dSmrg if (! live_p)
25401debfc3dSmrg {
25411debfc3dSmrg /* We need full live info for spilling pseudos into
25421debfc3dSmrg registers instead of memory. */
25431debfc3dSmrg lra_create_live_ranges (lra_reg_spill_p, true);
25441debfc3dSmrg live_p = true;
25451debfc3dSmrg }
25461debfc3dSmrg /* We should check necessity for spilling here as the above live
25471debfc3dSmrg range pass can remove spilled pseudos. */
25481debfc3dSmrg if (! lra_need_for_spills_p ())
25491debfc3dSmrg break;
25501debfc3dSmrg /* Now we know what pseudos should be spilled. Try to
25511debfc3dSmrg rematerialize them first. */
25521debfc3dSmrg if (lra_remat ())
25531debfc3dSmrg {
25541debfc3dSmrg /* We need full live info -- see the comment above. */
25551debfc3dSmrg lra_create_live_ranges (lra_reg_spill_p, true);
25561debfc3dSmrg live_p = true;
25571debfc3dSmrg if (! lra_need_for_spills_p ())
2558c0a68be4Smrg {
2559c0a68be4Smrg if (lra_need_for_scratch_reg_p ())
2560c0a68be4Smrg continue;
25611debfc3dSmrg break;
25621debfc3dSmrg }
2563c0a68be4Smrg }
25641debfc3dSmrg lra_spill ();
25651debfc3dSmrg /* Assignment of stack slots changes elimination offsets for
25661debfc3dSmrg some eliminations. So update the offsets here. */
25671debfc3dSmrg lra_eliminate (false, false);
25681debfc3dSmrg lra_constraint_new_regno_start = max_reg_num ();
25691debfc3dSmrg if (lra_bad_spill_regno_start == INT_MAX
25701debfc3dSmrg && lra_inheritance_iter > LRA_MAX_INHERITANCE_PASSES
25711debfc3dSmrg && lra_rematerialization_iter > LRA_MAX_REMATERIALIZATION_PASSES)
25721debfc3dSmrg /* After switching off inheritance and rematerialization
25731debfc3dSmrg passes, avoid spilling reload pseudos will be created to
25741debfc3dSmrg prevent LRA cycling in some complicated cases. */
25751debfc3dSmrg lra_bad_spill_regno_start = lra_constraint_new_regno_start;
25761debfc3dSmrg lra_assignment_iter_after_spill = 0;
25771debfc3dSmrg }
25781debfc3dSmrg restore_scratches ();
25791debfc3dSmrg lra_eliminate (true, false);
25801debfc3dSmrg lra_final_code_change ();
25811debfc3dSmrg lra_in_progress = 0;
25821debfc3dSmrg if (live_p)
25831debfc3dSmrg lra_clear_live_ranges ();
25841debfc3dSmrg lra_live_ranges_finish ();
25851debfc3dSmrg lra_constraints_finish ();
25861debfc3dSmrg finish_reg_info ();
25871debfc3dSmrg sbitmap_free (lra_constraint_insn_stack_bitmap);
25881debfc3dSmrg lra_constraint_insn_stack.release ();
25891debfc3dSmrg finish_insn_recog_data ();
25901debfc3dSmrg regstat_free_n_sets_and_refs ();
25911debfc3dSmrg regstat_free_ri ();
25921debfc3dSmrg reload_completed = 1;
25931debfc3dSmrg update_inc_notes ();
25941debfc3dSmrg
25951debfc3dSmrg inserted_p = fixup_abnormal_edges ();
25961debfc3dSmrg
25971debfc3dSmrg /* We've possibly turned single trapping insn into multiple ones. */
25981debfc3dSmrg if (cfun->can_throw_non_call_exceptions)
25991debfc3dSmrg {
26001debfc3dSmrg auto_sbitmap blocks (last_basic_block_for_fn (cfun));
26011debfc3dSmrg bitmap_ones (blocks);
26021debfc3dSmrg find_many_sub_basic_blocks (blocks);
26031debfc3dSmrg }
26041debfc3dSmrg
26051debfc3dSmrg if (inserted_p)
26061debfc3dSmrg commit_edge_insertions ();
26071debfc3dSmrg
26081debfc3dSmrg /* Replacing pseudos with their memory equivalents might have
26091debfc3dSmrg created shared rtx. Subsequent passes would get confused
26101debfc3dSmrg by this, so unshare everything here. */
26111debfc3dSmrg unshare_all_rtl_again (get_insns ());
26121debfc3dSmrg
26131debfc3dSmrg if (flag_checking)
26141debfc3dSmrg check_rtl (true);
26151debfc3dSmrg
26161debfc3dSmrg timevar_pop (TV_LRA);
26171debfc3dSmrg }
26181debfc3dSmrg
26191debfc3dSmrg /* Called once per compiler to initialize LRA data once. */
26201debfc3dSmrg void
lra_init_once(void)26211debfc3dSmrg lra_init_once (void)
26221debfc3dSmrg {
26231debfc3dSmrg init_insn_code_data_once ();
26241debfc3dSmrg }
26251debfc3dSmrg
26261debfc3dSmrg /* Called once per compiler to finish LRA data which are initialize
26271debfc3dSmrg once. */
26281debfc3dSmrg void
lra_finish_once(void)26291debfc3dSmrg lra_finish_once (void)
26301debfc3dSmrg {
26311debfc3dSmrg finish_insn_code_data_once ();
26321debfc3dSmrg }
2633