xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/lra.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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, &reg_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, &reg_obstack);
2096c0a68be4Smrg   bitmap_initialize (&scratch_operand_bitmap, &reg_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 = &REG_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, &reg_obstack);
24331debfc3dSmrg   bitmap_initialize (&lra_split_regs, &reg_obstack);
24341debfc3dSmrg   bitmap_initialize (&lra_optional_reload_pseudos, &reg_obstack);
24351debfc3dSmrg   bitmap_initialize (&lra_subreg_reload_pseudos, &reg_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