]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/ira.c
[Ada] Small improvement to Expand_N_Unchecked_Type_Conversion
[thirdparty/gcc.git] / gcc / ira.c
index 55b4bd700be81dd9d7b5644db66ddec65a31da6c..a655ae12eb2d501bee6423acdb02e8944a54945e 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1,5 +1,5 @@
 /* Integrated Register Allocator (IRA) entry point.
-   Copyright (C) 2006-2016 Free Software Foundation, Inc.
+   Copyright (C) 2006-2020 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -233,7 +233,7 @@ along with GCC; see the file COPYING3.  If not see
         more profitable than memory usage.
 
        * Popping the allocnos from the stack and assigning them hard
-         registers.  If IRA can not assign a hard register to an
+         registers.  If IRA cannot assign a hard register to an
          allocno and the allocno is coalesced, IRA undoes the
          coalescing and puts the uncoalesced allocnos onto the stack in
          the hope that some such allocnos will get a hard register
@@ -371,6 +371,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl.h"
 #include "tree.h"
 #include "df.h"
+#include "memmodel.h"
 #include "tm_p.h"
 #include "insn-config.h"
 #include "regs.h"
@@ -393,10 +394,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-rtl.h"
 
 struct target_ira default_target_ira;
-struct target_ira_int default_target_ira_int;
+class target_ira_int default_target_ira_int;
 #if SWITCHABLE_TARGET
 struct target_ira *this_target_ira = &default_target_ira;
-struct target_ira_int *this_target_ira_int = &default_target_ira_int;
+class target_ira_int *this_target_ira_int = &default_target_ira_int;
 #endif
 
 /* A modified value of flag `-fira-verbose' used internally.  */
@@ -410,7 +411,7 @@ int ira_spilled_reg_stack_slots_num;
 
 /* The following array contains info about spilled pseudo-registers
    stack slots used in current function so far.  */
-struct ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots;
+class ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots;
 
 /* Correspondingly overall cost of the allocation, overall cost before
    reload, cost of the allocnos assigned to hard-registers, cost of
@@ -448,7 +449,8 @@ setup_reg_mode_hard_regset (void)
     for (hard_regno = 0; hard_regno < FIRST_PSEUDO_REGISTER; hard_regno++)
       {
        CLEAR_HARD_REG_SET (ira_reg_mode_hard_regset[hard_regno][m]);
-       for (i = hard_regno_nregs[hard_regno][m] - 1; i >= 0; i--)
+       for (i = hard_regno_nregs (hard_regno, (machine_mode) m) - 1;
+            i >= 0; i--)
          if (hard_regno + i < FIRST_PSEUDO_REGISTER)
            SET_HARD_REG_BIT (ira_reg_mode_hard_regset[hard_regno][m],
                              hard_regno + i);
@@ -469,8 +471,7 @@ setup_class_hard_regs (void)
   ira_assert (SHRT_MAX >= FIRST_PSEUDO_REGISTER);
   for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
     {
-      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+      temp_hard_regset = reg_class_contents[cl] & ~no_unit_alloc_regs;
       CLEAR_HARD_REG_SET (processed_hard_reg_set);
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        {
@@ -512,9 +513,10 @@ setup_alloc_regs (bool use_hard_frame_p)
 #ifdef ADJUST_REG_ALLOC_ORDER
   ADJUST_REG_ALLOC_ORDER;
 #endif
-  COPY_HARD_REG_SET (no_unit_alloc_regs, fixed_nonglobal_reg_set);
+  no_unit_alloc_regs = fixed_nonglobal_reg_set;
   if (! use_hard_frame_p)
-    SET_HARD_REG_BIT (no_unit_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+    add_to_hard_reg_set (&no_unit_alloc_regs, Pmode,
+                        HARD_FRAME_POINTER_REGNUM);
   setup_class_hard_regs ();
 }
 
@@ -539,8 +541,7 @@ setup_reg_subclasses (void)
       if (i == (int) NO_REGS)
        continue;
 
-      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
-      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+      temp_hard_regset = reg_class_contents[i] & ~no_unit_alloc_regs;
       if (hard_reg_set_empty_p (temp_hard_regset))
        continue;
       for (j = 0; j < N_REG_CLASSES; j++)
@@ -548,8 +549,7 @@ setup_reg_subclasses (void)
          {
            enum reg_class *p;
 
-           COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[j]);
-           AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+           temp_hard_regset2 = reg_class_contents[j] & ~no_unit_alloc_regs;
            if (! hard_reg_set_subset_p (temp_hard_regset,
                                         temp_hard_regset2))
              continue;
@@ -603,10 +603,8 @@ setup_class_subset_and_memory_move_costs (void)
   for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
     for (cl2 = (int) N_REG_CLASSES - 1; cl2 >= 0; cl2--)
       {
-       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-       COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
-       AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+       temp_hard_regset = reg_class_contents[cl] & ~no_unit_alloc_regs;
+       temp_hard_regset2 = reg_class_contents[cl2] & ~no_unit_alloc_regs;
        ira_class_subset_p[cl][cl2]
          = hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2);
        if (! hard_reg_set_empty_p (temp_hard_regset2)
@@ -755,8 +753,7 @@ setup_stack_reg_pressure_class (void)
     for (i = 0; i < ira_pressure_classes_num; i++)
       {
        cl = ira_pressure_classes[i];
-       COPY_HARD_REG_SET (temp_hard_regset2, temp_hard_regset);
-       AND_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+       temp_hard_regset2 = temp_hard_regset & reg_class_contents[cl];
        size = hard_reg_set_size (temp_hard_regset2);
        if (best < size)
          {
@@ -791,78 +788,82 @@ setup_pressure_classes (void)
   HARD_REG_SET temp_hard_regset2;
   bool insert_p;
 
-  n = 0;
-  for (cl = 0; cl < N_REG_CLASSES; cl++)
-    {
-      if (ira_class_hard_regs_num[cl] == 0)
-       continue;
-      if (ira_class_hard_regs_num[cl] != 1
-         /* A register class without subclasses may contain a few
-            hard registers and movement between them is costly
-            (e.g. SPARC FPCC registers).  We still should consider it
-            as a candidate for a pressure class.  */
-         && alloc_reg_class_subclasses[cl][0] < cl)
+  if (targetm.compute_pressure_classes)
+    n = targetm.compute_pressure_classes (pressure_classes);
+  else
+    { 
+      n = 0;
+      for (cl = 0; cl < N_REG_CLASSES; cl++)
        {
-         /* Check that the moves between any hard registers of the
-            current class are not more expensive for a legal mode
-            than load/store of the hard registers of the current
-            class.  Such class is a potential candidate to be a
-            register pressure class.  */
-         for (m = 0; m < NUM_MACHINE_MODES; m++)
+         if (ira_class_hard_regs_num[cl] == 0)
+           continue;
+         if (ira_class_hard_regs_num[cl] != 1
+             /* A register class without subclasses may contain a few
+                hard registers and movement between them is costly
+                (e.g. SPARC FPCC registers).  We still should consider it
+                as a candidate for a pressure class.  */
+             && alloc_reg_class_subclasses[cl][0] < cl)
            {
-             COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-             AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-             AND_COMPL_HARD_REG_SET (temp_hard_regset,
-                                     ira_prohibited_class_mode_regs[cl][m]);
-             if (hard_reg_set_empty_p (temp_hard_regset))
+             /* Check that the moves between any hard registers of the
+                current class are not more expensive for a legal mode
+                than load/store of the hard registers of the current
+                class.  Such class is a potential candidate to be a
+                register pressure class.  */
+             for (m = 0; m < NUM_MACHINE_MODES; m++)
+               {
+                 temp_hard_regset
+                   = (reg_class_contents[cl]
+                      & ~(no_unit_alloc_regs
+                          | ira_prohibited_class_mode_regs[cl][m]));
+                 if (hard_reg_set_empty_p (temp_hard_regset))
+                   continue;
+                 ira_init_register_move_cost_if_necessary ((machine_mode) m);
+                 cost = ira_register_move_cost[m][cl][cl];
+                 if (cost <= ira_max_memory_move_cost[m][cl][1]
+                     || cost <= ira_max_memory_move_cost[m][cl][0])
+                   break;
+               }
+             if (m >= NUM_MACHINE_MODES)
                continue;
-             ira_init_register_move_cost_if_necessary ((machine_mode) m);
-             cost = ira_register_move_cost[m][cl][cl];
-             if (cost <= ira_max_memory_move_cost[m][cl][1]
-                 || cost <= ira_max_memory_move_cost[m][cl][0])
-               break;
            }
-         if (m >= NUM_MACHINE_MODES)
-           continue;
-       }
-      curr = 0;
-      insert_p = true;
-      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-      /* Remove so far added pressure classes which are subset of the
-        current candidate class.  Prefer GENERAL_REGS as a pressure
-        register class to another class containing the same
-        allocatable hard registers.  We do this because machine
-        dependent cost hooks might give wrong costs for the latter
-        class but always give the right cost for the former class
-        (GENERAL_REGS).  */
-      for (i = 0; i < n; i++)
-       {
-         cl2 = pressure_classes[i];
-         COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
-         AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
-         if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
-             && (! hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2)
-                 || cl2 == (int) GENERAL_REGS))
+         curr = 0;
+         insert_p = true;
+         temp_hard_regset = reg_class_contents[cl] & ~no_unit_alloc_regs;
+         /* Remove so far added pressure classes which are subset of the
+            current candidate class.  Prefer GENERAL_REGS as a pressure
+            register class to another class containing the same
+            allocatable hard registers.  We do this because machine
+            dependent cost hooks might give wrong costs for the latter
+            class but always give the right cost for the former class
+            (GENERAL_REGS).  */
+         for (i = 0; i < n; i++)
            {
+             cl2 = pressure_classes[i];
+             temp_hard_regset2 = (reg_class_contents[cl2]
+                                  & ~no_unit_alloc_regs);
+             if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
+                 && (temp_hard_regset != temp_hard_regset2
+                     || cl2 == (int) GENERAL_REGS))
+               {
+                 pressure_classes[curr++] = (enum reg_class) cl2;
+                 insert_p = false;
+                 continue;
+               }
+             if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
+                 && (temp_hard_regset2 != temp_hard_regset
+                     || cl == (int) GENERAL_REGS))
+               continue;
+             if (temp_hard_regset2 == temp_hard_regset)
+               insert_p = false;
              pressure_classes[curr++] = (enum reg_class) cl2;
-             insert_p = false;
-             continue;
            }
-         if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
-             && (! hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset)
-                 || cl == (int) GENERAL_REGS))
-           continue;
-         if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
-           insert_p = false;
-         pressure_classes[curr++] = (enum reg_class) cl2;
+         /* If the current candidate is a subset of a so far added
+            pressure class, don't add it to the list of the pressure
+            classes.  */
+         if (insert_p)
+           pressure_classes[curr++] = (enum reg_class) cl;
+         n = curr;
        }
-      /* If the current candidate is a subset of a so far added
-        pressure class, don't add it to the list of the pressure
-        classes.  */
-      if (insert_p)
-       pressure_classes[curr++] = (enum reg_class) cl;
-      n = curr;
     }
 #ifdef ENABLE_IRA_CHECKING
   {
@@ -873,7 +874,7 @@ setup_pressure_classes (void)
        registers available for the allocation.  */
     CLEAR_HARD_REG_SET (temp_hard_regset);
     CLEAR_HARD_REG_SET (temp_hard_regset2);
-    COPY_HARD_REG_SET (ignore_hard_regs, no_unit_alloc_regs);
+    ignore_hard_regs = no_unit_alloc_regs;
     for (cl = 0; cl < LIM_REG_CLASSES; cl++)
       {
        /* For some targets (like MIPS with MD_REGS), there are some
@@ -884,23 +885,23 @@ setup_pressure_classes (void)
            break;
        if (m >= NUM_MACHINE_MODES)
          {
-           IOR_HARD_REG_SET (ignore_hard_regs, reg_class_contents[cl]);
+           ignore_hard_regs |= reg_class_contents[cl];
            continue;
          }
        for (i = 0; i < n; i++)
          if ((int) pressure_classes[i] == cl)
            break;
-       IOR_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+       temp_hard_regset2 |= reg_class_contents[cl];
        if (i < n)
-         IOR_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+         temp_hard_regset |= reg_class_contents[cl];
       }
     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
       /* Some targets (like SPARC with ICC reg) have allocatable regs
         for which no reg class is defined.  */
       if (REGNO_REG_CLASS (i) == NO_REGS)
        SET_HARD_REG_BIT (ignore_hard_regs, i);
-    AND_COMPL_HARD_REG_SET (temp_hard_regset, ignore_hard_regs);
-    AND_COMPL_HARD_REG_SET (temp_hard_regset2, ignore_hard_regs);
+    temp_hard_regset &= ~ignore_hard_regs;
+    temp_hard_regset2 &= ~ignore_hard_regs;
     ira_assert (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset));
   }
 #endif
@@ -928,7 +929,7 @@ setup_uniform_class_p (void)
       ira_uniform_class_p[cl] = false;
       if (ira_class_hard_regs_num[cl] == 0)
        continue;
-      /* We can not use alloc_reg_class_subclasses here because move
+      /* We cannot use alloc_reg_class_subclasses here because move
         cost hooks does not take into account that some registers are
         unavailable for the subtarget.  E.g. for i686, INT_SSE_REGS
         is element of alloc_reg_class_subclasses for GENERAL_REGS
@@ -957,7 +958,7 @@ setup_uniform_class_p (void)
    IRA_IMPORTANT_CLASSES, and IRA_IMPORTANT_CLASSES_NUM.
 
    Target may have many subtargets and not all target hard registers can
-   be used for allocation, e.g. x86 port in 32-bit mode can not use
+   be used for allocation, e.g. x86 port in 32-bit mode cannot use
    hard registers introduced in x86-64 like r8-r15).  Some classes
    might have the same allocatable hard registers, e.g.  INDEX_REGS
    and GENERAL_REGS in x86 port in 32-bit mode.  To decrease different
@@ -992,19 +993,15 @@ setup_allocno_and_important_classes (void)
      same set of hard registers.  */
   for (i = 0; i < LIM_REG_CLASSES; i++)
     {
-      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
-      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+      temp_hard_regset = reg_class_contents[i] & ~no_unit_alloc_regs;
       for (j = 0; j < n; j++)
        {
          cl = classes[j];
-         COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
-         AND_COMPL_HARD_REG_SET (temp_hard_regset2,
-                                 no_unit_alloc_regs);
-         if (hard_reg_set_equal_p (temp_hard_regset,
-                                   temp_hard_regset2))
+         temp_hard_regset2 = reg_class_contents[cl] & ~no_unit_alloc_regs;
+         if (temp_hard_regset == temp_hard_regset2)
            break;
        }
-      if (j >= n)
+      if (j >= n || targetm.additional_allocno_class_p (i))
        classes[n++] = (enum reg_class) i;
       else if (i == GENERAL_REGS)
        /* Prefer general regs.  For i386 example, it means that
@@ -1028,14 +1025,12 @@ setup_allocno_and_important_classes (void)
   for (cl = 0; cl < N_REG_CLASSES; cl++)
     if (ira_class_hard_regs_num[cl] > 0)
       {
-       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+       temp_hard_regset = reg_class_contents[cl] & ~no_unit_alloc_regs;
        set_p = false;
        for (j = 0; j < ira_allocno_classes_num; j++)
          {
-           COPY_HARD_REG_SET (temp_hard_regset2,
-                              reg_class_contents[ira_allocno_classes[j]]);
-           AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+           temp_hard_regset2 = (reg_class_contents[ira_allocno_classes[j]]
+                                & ~no_unit_alloc_regs);
            if ((enum reg_class) cl == ira_allocno_classes[j])
              break;
            else if (hard_reg_set_subset_p (temp_hard_regset,
@@ -1109,10 +1104,9 @@ setup_class_translate_array (enum reg_class *class_translate,
       for (i = 0; i < classes_num; i++)
        {
          aclass = classes[i];
-         COPY_HARD_REG_SET (temp_hard_regset,
-                            reg_class_contents[aclass]);
-         AND_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-         AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+         temp_hard_regset = (reg_class_contents[aclass]
+                             & reg_class_contents[cl]
+                             & ~no_unit_alloc_regs);
          if (! hard_reg_set_empty_p (temp_hard_regset))
            {
              min_cost = INT_MAX;
@@ -1214,10 +1208,8 @@ setup_reg_class_relations (void)
          ira_reg_classes_intersect_p[cl1][cl2] = false;
          ira_reg_class_intersect[cl1][cl2] = NO_REGS;
          ira_reg_class_subset[cl1][cl2] = NO_REGS;
-         COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]);
-         AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-         COPY_HARD_REG_SET (temp_set2, reg_class_contents[cl2]);
-         AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+         temp_hard_regset = reg_class_contents[cl1] & ~no_unit_alloc_regs;
+         temp_set2 = reg_class_contents[cl2] & ~no_unit_alloc_regs;
          if (hard_reg_set_empty_p (temp_hard_regset)
              && hard_reg_set_empty_p (temp_set2))
            {
@@ -1255,16 +1247,14 @@ setup_reg_class_relations (void)
            }
          ira_reg_class_subunion[cl1][cl2] = NO_REGS;
          ira_reg_class_superunion[cl1][cl2] = NO_REGS;
-         COPY_HARD_REG_SET (intersection_set, reg_class_contents[cl1]);
-         AND_HARD_REG_SET (intersection_set, reg_class_contents[cl2]);
-         AND_COMPL_HARD_REG_SET (intersection_set, no_unit_alloc_regs);
-         COPY_HARD_REG_SET (union_set, reg_class_contents[cl1]);
-         IOR_HARD_REG_SET (union_set, reg_class_contents[cl2]);
-         AND_COMPL_HARD_REG_SET (union_set, no_unit_alloc_regs);
+         intersection_set = (reg_class_contents[cl1]
+                             & reg_class_contents[cl2]
+                             & ~no_unit_alloc_regs);
+         union_set = ((reg_class_contents[cl1] | reg_class_contents[cl2])
+                      & ~no_unit_alloc_regs);
          for (cl3 = 0; cl3 < N_REG_CLASSES; cl3++)
            {
-             COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl3]);
-             AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+             temp_hard_regset = reg_class_contents[cl3] & ~no_unit_alloc_regs;
              if (hard_reg_set_subset_p (temp_hard_regset, intersection_set))
                {
                  /* CL3 allocatable hard register set is inside of
@@ -1272,17 +1262,16 @@ setup_reg_class_relations (void)
                     of CL1 and CL2.  */
                  if (important_class_p[cl3])
                    {
-                     COPY_HARD_REG_SET
-                       (temp_set2,
-                        reg_class_contents
-                        [(int) ira_reg_class_intersect[cl1][cl2]]);
-                     AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+                     temp_set2
+                       = (reg_class_contents
+                          [ira_reg_class_intersect[cl1][cl2]]);
+                     temp_set2 &= ~no_unit_alloc_regs;
                      if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2)
                          /* If the allocatable hard register sets are
                             the same, prefer GENERAL_REGS or the
                             smallest class for debugging
                             purposes.  */
-                         || (hard_reg_set_equal_p (temp_hard_regset, temp_set2)
+                         || (temp_hard_regset == temp_set2
                              && (cl3 == GENERAL_REGS
                                  || ((ira_reg_class_intersect[cl1][cl2]
                                       != GENERAL_REGS)
@@ -1293,14 +1282,13 @@ setup_reg_class_relations (void)
                                           ira_reg_class_intersect[cl1][cl2]])))))
                        ira_reg_class_intersect[cl1][cl2] = (enum reg_class) cl3;
                    }
-                 COPY_HARD_REG_SET
-                   (temp_set2,
-                    reg_class_contents[(int) ira_reg_class_subset[cl1][cl2]]);
-                 AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+                 temp_set2
+                   = (reg_class_contents[ira_reg_class_subset[cl1][cl2]]
+                      & ~no_unit_alloc_regs);
                  if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2)
                      /* Ignore unavailable hard registers and prefer
                         smallest class for debugging purposes.  */
-                     || (hard_reg_set_equal_p (temp_hard_regset, temp_set2)
+                     || (temp_hard_regset == temp_set2
                          && hard_reg_set_subset_p
                             (reg_class_contents[cl3],
                              reg_class_contents
@@ -1313,15 +1301,13 @@ setup_reg_class_relations (void)
                  /* CL3 allocatable hard register set is inside of
                     union of allocatable hard register sets of CL1
                     and CL2.  */
-                 COPY_HARD_REG_SET
-                   (temp_set2,
-                    reg_class_contents[(int) ira_reg_class_subunion[cl1][cl2]]);
-                 AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+                 temp_set2
+                   = (reg_class_contents[ira_reg_class_subunion[cl1][cl2]]
+                      & ~no_unit_alloc_regs);
                  if (ira_reg_class_subunion[cl1][cl2] == NO_REGS
                      || (hard_reg_set_subset_p (temp_set2, temp_hard_regset)
                          
-                         && (! hard_reg_set_equal_p (temp_set2,
-                                                     temp_hard_regset)
+                         && (temp_set2 != temp_hard_regset
                              || cl3 == GENERAL_REGS
                              /* If the allocatable hard register sets are the
                                 same, prefer GENERAL_REGS or the smallest
@@ -1338,15 +1324,13 @@ setup_reg_class_relations (void)
                  /* CL3 allocatable hard register set contains union
                     of allocatable hard register sets of CL1 and
                     CL2.  */
-                 COPY_HARD_REG_SET
-                   (temp_set2,
-                    reg_class_contents[(int) ira_reg_class_superunion[cl1][cl2]]);
-                 AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+                 temp_set2
+                   = (reg_class_contents[ira_reg_class_superunion[cl1][cl2]]
+                      & ~no_unit_alloc_regs);
                  if (ira_reg_class_superunion[cl1][cl2] == NO_REGS
                      || (hard_reg_set_subset_p (temp_hard_regset, temp_set2)
 
-                         && (! hard_reg_set_equal_p (temp_set2,
-                                                     temp_hard_regset)
+                         && (temp_set2 != temp_hard_regset
                              || cl3 == GENERAL_REGS
                              /* If the allocatable hard register sets are the
                                 same, prefer GENERAL_REGS or the smallest
@@ -1490,8 +1474,7 @@ setup_prohibited_class_mode_regs (void)
 
   for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
     {
-      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+      temp_hard_regset = reg_class_contents[cl] & ~no_unit_alloc_regs;
       for (j = 0; j < NUM_MACHINE_MODES; j++)
        {
          count = 0;
@@ -1500,7 +1483,7 @@ setup_prohibited_class_mode_regs (void)
          for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--)
            {
              hard_regno = ira_class_hard_regs[cl][k];
-             if (! HARD_REGNO_MODE_OK (hard_regno, (machine_mode) j))
+             if (!targetm.hard_regno_mode_ok (hard_regno, (machine_mode) j))
                SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
                                  hard_regno);
              else if (in_hard_reg_set_p (temp_hard_regset,
@@ -1532,7 +1515,7 @@ clarify_prohibited_class_mode_regs (void)
            hard_regno = ira_class_hard_regs[cl][k];
            if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j], hard_regno))
              continue;
-           nregs = hard_regno_nregs[hard_regno][j];
+           nregs = hard_regno_nregs (hard_regno, (machine_mode) j);
            if (hard_regno + nregs > FIRST_PSEUDO_REGISTER)
              {
                SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
@@ -1564,18 +1547,27 @@ ira_init_register_move_cost (machine_mode mode)
 {
   static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
   bool all_match = true;
-  unsigned int cl1, cl2;
+  unsigned int i, cl1, cl2;
+  HARD_REG_SET ok_regs;
 
   ira_assert (ira_register_move_cost[mode] == NULL
              && ira_may_move_in_cost[mode] == NULL
              && ira_may_move_out_cost[mode] == NULL);
-  ira_assert (have_regs_of_mode[mode]);
+  CLEAR_HARD_REG_SET (ok_regs);
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (targetm.hard_regno_mode_ok (i, mode))
+      SET_HARD_REG_BIT (ok_regs, i);
+
+  /* Note that we might be asked about the move costs of modes that
+     cannot be stored in any hard register, for example if an inline
+     asm tries to create a register operand with an impossible mode.
+     We therefore can't assert have_regs_of_mode[mode] here.  */
   for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++)
     for (cl2 = 0; cl2 < N_REG_CLASSES; cl2++)
       {
        int cost;
-       if (!contains_reg_of_mode[cl1][mode]
-           || !contains_reg_of_mode[cl2][mode])
+       if (!hard_reg_set_intersect_p (ok_regs, reg_class_contents[cl1])
+           || !hard_reg_set_intersect_p (ok_regs, reg_class_contents[cl2]))
          {
            if ((ira_reg_class_max_nregs[cl1][mode]
                 > ira_class_hard_regs_num[cl1])
@@ -1665,6 +1657,8 @@ ira_init_once (void)
 {
   ira_init_costs_once ();
   lra_init_once ();
+
+  ira_use_lra_p = targetm.lra_p ();
 }
 
 /* Free ira_max_register_move_cost, ira_may_move_in_cost and
@@ -1744,7 +1738,7 @@ setup_prohibited_mode_move_regs (void)
       SET_HARD_REG_SET (ira_prohibited_mode_move_regs[i]);
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
        {
-         if (! HARD_REGNO_MODE_OK (j, (machine_mode) i))
+         if (!targetm.hard_regno_mode_ok (j, (machine_mode) i))
            continue;
          set_mode_and_regno (test_reg1, (machine_mode) i, j);
          set_mode_and_regno (test_reg2, (machine_mode) i, j);
@@ -1764,74 +1758,66 @@ setup_prohibited_mode_move_regs (void)
 
 \f
 
-/* Setup possible alternatives in ALTS for INSN.  */
-void
-ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
+/* Extract INSN and return the set of alternatives that we should consider.
+   This excludes any alternatives whose constraints are obviously impossible
+   to meet (e.g. because the constraint requires a constant and the operand
+   is nonconstant).  It also excludes alternatives that are bound to need
+   a spill or reload, as long as we have other alternatives that match
+   exactly.  */
+alternative_mask
+ira_setup_alts (rtx_insn *insn)
 {
-  /* MAP nalt * nop -> start of constraints for given operand and
-     alternative.  */
-  static vec<const char *> insn_constraints;
   int nop, nalt;
   bool curr_swapped;
   const char *p;
   int commutative = -1;
 
   extract_insn (insn);
+  preprocess_constraints (insn);
   alternative_mask preferred = get_preferred_alternatives (insn);
-  CLEAR_HARD_REG_SET (alts);
-  insn_constraints.release ();
-  insn_constraints.safe_grow_cleared (recog_data.n_operands
-                                     * recog_data.n_alternatives + 1);
+  alternative_mask alts = 0;
+  alternative_mask exact_alts = 0;
   /* Check that the hard reg set is enough for holding all
      alternatives.  It is hard to imagine the situation when the
      assertion is wrong.  */
   ira_assert (recog_data.n_alternatives
              <= (int) MAX (sizeof (HARD_REG_ELT_TYPE) * CHAR_BIT,
                            FIRST_PSEUDO_REGISTER));
+  for (nop = 0; nop < recog_data.n_operands; nop++)
+    if (recog_data.constraints[nop][0] == '%')
+      {
+       commutative = nop;
+       break;
+      }
   for (curr_swapped = false;; curr_swapped = true)
     {
-      /* Calculate some data common for all alternatives to speed up the
-        function.  */
-      for (nop = 0; nop < recog_data.n_operands; nop++)
-       {
-         for (nalt = 0, p = recog_data.constraints[nop];
-              nalt < recog_data.n_alternatives;
-              nalt++)
-           {
-             insn_constraints[nop * recog_data.n_alternatives + nalt] = p;
-             while (*p && *p != ',')
-               {
-                 /* We only support one commutative marker, the first
-                    one.  We already set commutative above.  */
-                 if (*p == '%' && commutative < 0)
-                   commutative = nop;
-                 p++;
-               }
-             if (*p)
-               p++;
-           }
-       }
       for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
        {
-         if (!TEST_BIT (preferred, nalt)
-             || TEST_HARD_REG_BIT (alts, nalt))
+         if (!TEST_BIT (preferred, nalt) || TEST_BIT (exact_alts, nalt))
            continue;
 
+         const operand_alternative *op_alt
+           = &recog_op_alt[nalt * recog_data.n_operands];
+         int this_reject = 0;
          for (nop = 0; nop < recog_data.n_operands; nop++)
            {
              int c, len;
 
+             this_reject += op_alt[nop].reject;
+
              rtx op = recog_data.operand[nop];
-             p = insn_constraints[nop * recog_data.n_alternatives + nalt];
+             p = op_alt[nop].constraint;
              if (*p == 0 || *p == ',')
                continue;
-             
+
+             bool win_p = false;
              do
                switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
                  {
                  case '#':
                  case ',':
                    c = '\0';
+                   /* FALLTHRU */
                  case '\0':
                    len = 0;
                    break;
@@ -1842,7 +1828,14 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
 
                  case '0':  case '1':  case '2':  case '3':  case '4':
                  case '5':  case '6':  case '7':  case '8':  case '9':
-                   goto op_success;
+                   {
+                     rtx other = recog_data.operand[c - '0'];
+                     if (MEM_P (other)
+                         ? rtx_equal_p (other, op)
+                         : REG_P (op) || SUBREG_P (op))
+                       goto op_success;
+                     win_p = true;
+                   }
                    break;
                    
                  case 'g':
@@ -1856,7 +1849,11 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
                        {
                        case CT_REGISTER:
                          if (reg_class_for_constraint (cn) != NO_REGS)
-                           goto op_success;
+                           {
+                             if (REG_P (op) || SUBREG_P (op))
+                               goto op_success;
+                             win_p = true;
+                           }
                          break;
 
                        case CT_CONST_INT:
@@ -1867,9 +1864,14 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
                          break;
 
                        case CT_ADDRESS:
+                         goto op_success;
+
                        case CT_MEMORY:
                        case CT_SPECIAL_MEMORY:
-                         goto op_success;
+                         if (MEM_P (op))
+                           goto op_success;
+                         win_p = true;
+                         break;
 
                        case CT_FIXED_FORM:
                          if (constraint_satisfied_p (op, cn))
@@ -1880,12 +1882,22 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
                    }
                  }
              while (p += len, c);
-             break;
+             if (!win_p)
+               break;
+             /* We can make the alternative match by spilling a register
+                to memory or loading something into a register.  Count a
+                cost of one reload (the equivalent of the '?' constraint).  */
+             this_reject += 6;
            op_success:
              ;
            }
+
          if (nop >= recog_data.n_operands)
-           SET_HARD_REG_BIT (alts, nalt);
+           {
+             alts |= ALTERNATIVE_BIT (nalt);
+             if (this_reject == 0)
+               exact_alts |= ALTERNATIVE_BIT (nalt);
+           }
        }
       if (commutative < 0)
        break;
@@ -1895,14 +1907,15 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
       if (curr_swapped)
        break;
     }
+  return exact_alts ? exact_alts : alts;
 }
 
 /* Return the number of the output non-early clobber operand which
    should be the same in any case as operand with number OP_NUM (or
-   negative value if there is no such operand).  The function takes
-   only really possible alternatives into consideration.  */
+   negative value if there is no such operand).  ALTS is the mask
+   of alternatives that we should consider.  */
 int
-ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
+ira_get_dup_out_num (int op_num, alternative_mask alts)
 {
   int curr_alt, c, original, dup;
   bool ignore_p, use_commut_op_p;
@@ -1919,7 +1932,7 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
     {
       rtx op = recog_data.operand[op_num];
       
-      for (curr_alt = 0, ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt),
+      for (curr_alt = 0, ignore_p = !TEST_BIT (alts, curr_alt),
           original = -1;;)
        {
          c = *str;
@@ -1930,7 +1943,7 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
          else if (c == ',')
            {
              curr_alt++;
-             ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt);
+             ignore_p = !TEST_BIT (alts, curr_alt);
            }
          else if (! ignore_p)
            switch (c)
@@ -1960,26 +1973,8 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
        }
       if (original == -1)
        goto fail;
-      dup = -1;
-      for (ignore_p = false, str = recog_data.constraints[original - '0'];
-          *str != 0;
-          str++)
-       if (ignore_p)
-         {
-           if (*str == ',')
-             ignore_p = false;
-         }
-       else if (*str == '#')
-         ignore_p = true;
-       else if (! ignore_p)
-         {
-           if (*str == '=')
-             dup = original - '0';
-           /* It is better ignore an alternative with early clobber.  */
-           else if (*str == '&')
-             goto fail;
-         }
-      if (dup >= 0)
+      dup = original - '0';
+      if (recog_data.operand_type[dup] == OP_OUT)
        return dup;
     fail:
       if (use_commut_op_p)
@@ -2233,7 +2228,7 @@ compute_regs_asm_clobbered (void)
        {
          df_ref def;
 
-         if (NONDEBUG_INSN_P (insn) && extract_asm_operands (PATTERN (insn)))
+         if (NONDEBUG_INSN_P (insn) && asm_noperands (PATTERN (insn)) >= 0)
            FOR_EACH_INSN_DEF (def, insn)
              {
                unsigned int dregno = DF_REF_REGNO (def);
@@ -2252,10 +2247,14 @@ compute_regs_asm_clobbered (void)
 void
 ira_setup_eliminable_regset (void)
 {
-#ifdef ELIMINABLE_REGS
   int i;
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
-#endif
+  int fp_reg_count = hard_regno_nregs (HARD_FRAME_POINTER_REGNUM, Pmode);
+
+  /* Setup is_leaf as frame_pointer_required may use it.  This function
+     is called by sched_init before ira if scheduling is enabled.  */
+  crtl->is_leaf = leaf_function_p ();
+
   /* FIXME: If EXIT_IGNORE_STACK is set, we will not save and restore
      sp for alloca.  So we can't eliminate the frame pointer in that
      case.  At some point, we should improve this by emitting the
@@ -2271,9 +2270,6 @@ ira_setup_eliminable_regset (void)
           && cfun->can_throw_non_call_exceptions)
        || crtl->accesses_prior_frames
        || (SUPPORTS_STACK_ALIGNMENT && crtl->stack_realign_needed)
-       /* We need a frame pointer for all Cilk Plus functions that use
-         Cilk keywords.  */
-       || (flag_cilkplus && cfun->is_cilk_function)
        || targetm.frame_pointer_required ());
 
     /* The chance that FRAME_POINTER_NEEDED is changed from inspecting
@@ -2282,16 +2278,16 @@ ira_setup_eliminable_regset (void)
        frame pointer in LRA.  */
 
   if (frame_pointer_needed)
-    df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
+    for (i = 0; i < fp_reg_count; i++)
+      df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM + i, true);
     
-  COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs);
+  ira_no_alloc_regs = no_unit_alloc_regs;
   CLEAR_HARD_REG_SET (eliminable_regset);
 
   compute_regs_asm_clobbered ();
 
   /* Build the regset of all eliminable registers and show we can't
      use those that we already know won't be eliminated.  */
-#ifdef ELIMINABLE_REGS
   for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++)
     {
       bool cannot_elim
@@ -2306,38 +2302,29 @@ ira_setup_eliminable_regset (void)
              SET_HARD_REG_BIT (ira_no_alloc_regs, eliminables[i].from);
        }
       else if (cannot_elim)
-       error ("%s cannot be used in asm here",
+       error ("%s cannot be used in %<asm%> here",
               reg_names[eliminables[i].from]);
       else
        df_set_regs_ever_live (eliminables[i].from, true);
     }
   if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
     {
-      if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
-       {
-         SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
-         if (frame_pointer_needed)
-           SET_HARD_REG_BIT (ira_no_alloc_regs, HARD_FRAME_POINTER_REGNUM);
-       }
-      else if (frame_pointer_needed)
-       error ("%s cannot be used in asm here",
-              reg_names[HARD_FRAME_POINTER_REGNUM]);
-      else
-       df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
-    }
-
-#else
-  if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
-    {
-      SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
-      if (frame_pointer_needed)
-       SET_HARD_REG_BIT (ira_no_alloc_regs, FRAME_POINTER_REGNUM);
+      for (i = 0; i < fp_reg_count; i++)
+       if (!TEST_HARD_REG_BIT (crtl->asm_clobbers,
+                               HARD_FRAME_POINTER_REGNUM + i))
+         {
+           SET_HARD_REG_BIT (eliminable_regset,
+                             HARD_FRAME_POINTER_REGNUM + i);
+           if (frame_pointer_needed)
+             SET_HARD_REG_BIT (ira_no_alloc_regs,
+                               HARD_FRAME_POINTER_REGNUM + i);
+         }
+       else if (frame_pointer_needed)
+         error ("%s cannot be used in %<asm%> here",
+                reg_names[HARD_FRAME_POINTER_REGNUM + i]);
+       else
+         df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM + i, true);
     }
-  else if (frame_pointer_needed)
-    error ("%s cannot be used in asm here", reg_names[FRAME_POINTER_REGNUM]);
-  else
-    df_set_regs_ever_live (FRAME_POINTER_REGNUM, true);
-#endif
 }
 
 \f
@@ -2385,12 +2372,10 @@ setup_reg_renumber (void)
          for (i = 0; i < nwords; i++)
            {
              obj = ALLOCNO_OBJECT (a, i);
-             IOR_COMPL_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
-                                     reg_class_contents[pclass]);
+             OBJECT_TOTAL_CONFLICT_HARD_REGS (obj)
+               |= ~reg_class_contents[pclass];
            }
-         if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
-             && ira_hard_reg_set_intersection_p (hard_regno, ALLOCNO_MODE (a),
-                                                 call_used_reg_set))
+         if (ira_need_caller_save_p (a, hard_regno))
            {
              ira_assert (!optimize || flag_caller_saves
                          || (ALLOCNO_CALLS_CROSSED_NUM (a)
@@ -2509,7 +2494,7 @@ check_allocation (void)
       if (ALLOCNO_CAP_MEMBER (a) != NULL
          || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0)
        continue;
-      nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (a)];
+      nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (a));
       if (nregs == 1)
        /* We allocated a single hard register.  */
        n = 1;
@@ -2538,9 +2523,8 @@ check_allocation (void)
              if (conflict_hard_regno < 0)
                continue;
 
-             conflict_nregs
-               = (hard_regno_nregs
-                  [conflict_hard_regno][ALLOCNO_MODE (conflict_a)]);
+             conflict_nregs = hard_regno_nregs (conflict_hard_regno,
+                                                ALLOCNO_MODE (conflict_a));
 
              if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1
                  && conflict_nregs == ALLOCNO_NUM_OBJECTS (conflict_a))
@@ -2651,7 +2635,7 @@ ira_update_equiv_info_by_shuffle_insn (int to_regno, int from_regno, rtx_insn *i
        }
       if (find_reg_note (insn, REG_EQUIV, x) == NULL_RTX)
        {
-         note = set_unique_reg_note (insn, REG_EQUIV, x);
+         note = set_unique_reg_note (insn, REG_EQUIV, copy_rtx (x));
          gcc_assert (note != NULL_RTX);
          if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
            {
@@ -2998,7 +2982,7 @@ validate_equiv_mem (rtx_insn *start, rtx reg, rtx memref)
            return valid_none;
        }
 
-      note_stores (PATTERN (insn), validate_equiv_mem_from_store, &info);
+      note_stores (insn, validate_equiv_mem_from_store, &info);
       if (info.equiv_mem_modified)
        return valid_none;
 
@@ -3133,10 +3117,30 @@ equiv_init_movable_p (rtx x, int regno)
   return 1;
 }
 
-/* TRUE if X references a memory location that would be affected by a store
-   to MEMREF.  */
-static int
-memref_referenced_p (rtx memref, rtx x)
+static bool memref_referenced_p (rtx memref, rtx x, bool read_p);
+
+/* Auxiliary function for memref_referenced_p.  Process setting X for
+   MEMREF store.  */
+static bool
+process_set_for_memref_referenced_p (rtx memref, rtx x)
+{
+  /* If we are setting a MEM, it doesn't count (its address does), but any
+     other SET_DEST that has a MEM in it is referencing the MEM.  */
+  if (MEM_P (x))
+    {
+      if (memref_referenced_p (memref, XEXP (x, 0), true))
+       return true;
+    }
+  else if (memref_referenced_p (memref, x, false))
+    return true;
+  
+  return false;
+}
+
+/* TRUE if X references a memory location (as a read if READ_P) that
+   would be affected by a store to MEMREF.  */
+static bool
+memref_referenced_p (rtx memref, rtx x, bool read_p)
 {
   int i, j;
   const char *fmt;
@@ -3152,30 +3156,50 @@ memref_referenced_p (rtx memref, rtx x)
     case CC0:
     case HIGH:
     case LO_SUM:
-      return 0;
+      return false;
 
     case REG:
       return (reg_equiv[REGNO (x)].replacement
              && memref_referenced_p (memref,
-                                     reg_equiv[REGNO (x)].replacement));
+                                     reg_equiv[REGNO (x)].replacement, read_p));
 
     case MEM:
-      if (true_dependence (memref, VOIDmode, x))
-       return 1;
+      /* Memory X might have another effective type than MEMREF.  */
+      if (read_p || true_dependence (memref, VOIDmode, x))
+       return true;
       break;
 
     case SET:
-      /* If we are setting a MEM, it doesn't count (its address does), but any
-        other SET_DEST that has a MEM in it is referencing the MEM.  */
-      if (MEM_P (SET_DEST (x)))
-       {
-         if (memref_referenced_p (memref, XEXP (SET_DEST (x), 0)))
-           return 1;
-       }
-      else if (memref_referenced_p (memref, SET_DEST (x)))
-       return 1;
+      if (process_set_for_memref_referenced_p (memref, SET_DEST (x)))
+       return true;
+
+      return memref_referenced_p (memref, SET_SRC (x), true);
 
-      return memref_referenced_p (memref, SET_SRC (x));
+    case CLOBBER:
+      if (process_set_for_memref_referenced_p (memref, XEXP (x, 0)))
+       return true;
+
+      return false;
+
+    case PRE_DEC:
+    case POST_DEC:
+    case PRE_INC:
+    case POST_INC:
+      if (process_set_for_memref_referenced_p (memref, XEXP (x, 0)))
+       return true;
+
+      return memref_referenced_p (memref, XEXP (x, 0), true);
+      
+    case POST_MODIFY:
+    case PRE_MODIFY:
+      /* op0 = op0 + op1 */
+      if (process_set_for_memref_referenced_p (memref, XEXP (x, 0)))
+       return true;
+
+      if (memref_referenced_p (memref, XEXP (x, 0), true))
+       return true;
+
+      return memref_referenced_p (memref, XEXP (x, 1), true);
 
     default:
       break;
@@ -3186,17 +3210,17 @@ memref_referenced_p (rtx memref, rtx x)
     switch (fmt[i])
       {
       case 'e':
-       if (memref_referenced_p (memref, XEXP (x, i)))
-         return 1;
+       if (memref_referenced_p (memref, XEXP (x, i), read_p))
+         return true;
        break;
       case 'E':
        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         if (memref_referenced_p (memref, XVECEXP (x, i, j)))
-           return 1;
+         if (memref_referenced_p (memref, XVECEXP (x, i, j), read_p))
+           return true;
        break;
       }
 
-  return 0;
+  return false;
 }
 
 /* TRUE if some insn in the range (START, END] references a memory location
@@ -3217,7 +3241,7 @@ memref_used_between_p (rtx memref, rtx_insn *start, rtx_insn *end)
       if (!NONDEBUG_INSN_P (insn))
        continue;
 
-      if (memref_referenced_p (memref, PATTERN (insn)))
+      if (memref_referenced_p (memref, PATTERN (insn), false))
        return 1;
 
       /* Nonconst functions may access memory.  */
@@ -3300,6 +3324,80 @@ adjust_cleared_regs (rtx loc, const_rtx old_rtx ATTRIBUTE_UNUSED, void *data)
   return NULL_RTX;
 }
 
+/* Given register REGNO is set only once, return true if the defining
+   insn dominates all uses.  */
+
+static bool
+def_dominates_uses (int regno)
+{
+  df_ref def = DF_REG_DEF_CHAIN (regno);
+
+  struct df_insn_info *def_info = DF_REF_INSN_INFO (def);
+  /* If this is an artificial def (eh handler regs, hard frame pointer
+     for non-local goto, regs defined on function entry) then def_info
+     is NULL and the reg is always live before any use.  We might
+     reasonably return true in that case, but since the only call
+     of this function is currently here in ira.c when we are looking
+     at a defining insn we can't have an artificial def as that would
+     bump DF_REG_DEF_COUNT.  */
+  gcc_assert (DF_REG_DEF_COUNT (regno) == 1 && def_info != NULL);
+
+  rtx_insn *def_insn = DF_REF_INSN (def);
+  basic_block def_bb = BLOCK_FOR_INSN (def_insn);
+
+  for (df_ref use = DF_REG_USE_CHAIN (regno);
+       use;
+       use = DF_REF_NEXT_REG (use))
+    {
+      struct df_insn_info *use_info = DF_REF_INSN_INFO (use);
+      /* Only check real uses, not artificial ones.  */
+      if (use_info)
+       {
+         rtx_insn *use_insn = DF_REF_INSN (use);
+         if (!DEBUG_INSN_P (use_insn))
+           {
+             basic_block use_bb = BLOCK_FOR_INSN (use_insn);
+             if (use_bb != def_bb
+                 ? !dominated_by_p (CDI_DOMINATORS, use_bb, def_bb)
+                 : DF_INSN_INFO_LUID (use_info) < DF_INSN_INFO_LUID (def_info))
+               return false;
+           }
+       }
+    }
+  return true;
+}
+
+/* Scan the instructions before update_equiv_regs.  Record which registers
+   are referenced as paradoxical subregs.  Also check for cases in which
+   the current function needs to save a register that one of its call
+   instructions clobbers.
+
+   These things are logically unrelated, but it's more efficient to do
+   them together.  */
+
+static void
+update_equiv_regs_prescan (void)
+{
+  basic_block bb;
+  rtx_insn *insn;
+  function_abi_aggregator callee_abis;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    FOR_BB_INSNS (bb, insn)
+      if (NONDEBUG_INSN_P (insn))
+       {
+         set_paradoxical_subreg (insn);
+         if (CALL_P (insn))
+           callee_abis.note_callee_abi (insn_callee_abi (insn));
+       }
+
+  HARD_REG_SET extra_caller_saves = callee_abis.caller_save_regs (*crtl->abi);
+  if (!hard_reg_set_empty_p (extra_caller_saves))
+    for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+      if (TEST_HARD_REG_BIT (extra_caller_saves, regno))
+       df_set_regs_ever_live (regno, true);
+}
+
 /* Find registers that are equivalent to a single value throughout the
    compilation (either because they can be referenced in memory or are
    set once from a single constant).  Lower their priority for a
@@ -3316,15 +3414,6 @@ update_equiv_regs (void)
   rtx_insn *insn;
   basic_block bb;
 
-  /* Scan insns and set pdx_subregs if the reg is used in a
-     paradoxical subreg.  Don't set such reg equivalent to a mem,
-     because lra will not substitute such equiv memory in order to
-     prevent access beyond allocated memory for paradoxical memory subreg.  */
-  FOR_EACH_BB_FN (bb, cfun)
-    FOR_BB_INSNS (bb, insn)
-      if (NONDEBUG_INSN_P (insn))
-       set_paradoxical_subreg (insn);
-
   /* Scan the insns and find which registers have equivalences.  Do this
      in a separate scan of the insns because (due to -fcse-follow-jumps)
      a register can be set below its use.  */
@@ -3356,7 +3445,7 @@ update_equiv_regs (void)
          if (set == NULL_RTX
              || side_effects_p (SET_SRC (set)))
            {
-             note_stores (PATTERN (insn), no_equiv, NULL);
+             note_pattern_stores (PATTERN (insn), no_equiv, NULL);
              continue;
            }
          else if (GET_CODE (PATTERN (insn)) == PARALLEL)
@@ -3367,7 +3456,7 @@ update_equiv_regs (void)
                {
                  rtx part = XVECEXP (PATTERN (insn), 0, i);
                  if (part != set)
-                   note_stores (part, no_equiv, NULL);
+                   note_pattern_stores (part, no_equiv, NULL);
                }
            }
 
@@ -3425,7 +3514,7 @@ update_equiv_regs (void)
            {
              /* This might be setting a SUBREG of a pseudo, a pseudo that is
                 also set somewhere else to a constant.  */
-             note_stores (set, no_equiv, NULL);
+             note_pattern_stores (set, no_equiv, NULL);
              continue;
            }
 
@@ -3433,7 +3522,7 @@ update_equiv_regs (void)
             equivalent to a mem.  */
          if (MEM_P (src) && reg_equiv[regno].pdx_subregs)
            {
-             note_stores (set, no_equiv, NULL);
+             note_pattern_stores (set, no_equiv, NULL);
              continue;
            }
 
@@ -3456,7 +3545,7 @@ update_equiv_regs (void)
              rtx_insn_list *list;
 
              /* If we have already processed this pseudo and determined it
-                can not have an equivalence, then honor that decision.  */
+                cannot have an equivalence, then honor that decision.  */
              if (reg_equiv[regno].no_equiv)
                continue;
 
@@ -3498,9 +3587,18 @@ update_equiv_regs (void)
            = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv[regno].init_insns);
 
          /* If this register is known to be equal to a constant, record that
-            it is always equivalent to the constant.  */
+            it is always equivalent to the constant.
+            Note that it is possible to have a register use before
+            the def in loops (see gcc.c-torture/execute/pr79286.c)
+            where the reg is undefined on first use.  If the def insn
+            won't trap we can use it as an equivalence, effectively
+            choosing the "undefined" value for the reg to be the
+            same as the value set by the def.  */
          if (DF_REG_DEF_COUNT (regno) == 1
-             && note && ! rtx_varies_p (XEXP (note, 0), 0))
+             && note
+             && !rtx_varies_p (XEXP (note, 0), 0)
+             && (!may_trap_or_fault_p (XEXP (note, 0))
+                 || def_dominates_uses (regno)))
            {
              rtx note_value = XEXP (note, 0);
              remove_note (insn, note);
@@ -3584,16 +3682,15 @@ update_equiv_regs (void)
 static void
 add_store_equivs (void)
 {
-  bitmap_head seen_insns;
+  auto_bitmap seen_insns;
 
-  bitmap_initialize (&seen_insns, NULL);
   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
       rtx set, src, dest;
       unsigned regno;
       rtx_insn *init_insn;
 
-      bitmap_set_bit (&seen_insns, INSN_UID (insn));
+      bitmap_set_bit (seen_insns, INSN_UID (insn));
 
       if (! INSN_P (insn))
        continue;
@@ -3614,7 +3711,7 @@ add_store_equivs (void)
          && ! reg_equiv[regno].pdx_subregs
          && reg_equiv[regno].init_insns != NULL
          && (init_insn = reg_equiv[regno].init_insns->insn ()) != 0
-         && bitmap_bit_p (&seen_insns, INSN_UID (init_insn))
+         && bitmap_bit_p (seen_insns, INSN_UID (init_insn))
          && ! find_reg_note (init_insn, REG_EQUIV, NULL_RTX)
          && validate_equiv_mem (init_insn, src, dest) == valid_reload
          && ! memref_used_between_p (dest, init_insn, insn)
@@ -3634,7 +3731,6 @@ add_store_equivs (void)
                     INSN_UID (insn));
        }
     }
-  bitmap_clear (&seen_insns);
 }
 
 /* Scan all regs killed in an insn to see if any of them are registers
@@ -3647,7 +3743,7 @@ add_store_equivs (void)
 static void
 combine_and_move_insns (void)
 {
-  bitmap cleared_regs = BITMAP_ALLOC (NULL);
+  auto_bitmap cleared_regs;
   int max = max_reg_num ();
 
   for (int regno = FIRST_PSEUDO_REGISTER; regno < max; regno++)
@@ -3673,6 +3769,11 @@ combine_and_move_insns (void)
       if (JUMP_P (use_insn))
        continue;
 
+      /* Also don't substitute into a conditional trap insn -- it can become
+        an unconditional trap, and that is a flow control insn.  */
+      if (GET_CODE (PATTERN (use_insn)) == TRAP_IF)
+       continue;
+
       df_ref def = DF_REG_DEF_CHAIN (regno);
       gcc_assert (DF_REG_DEF_COUNT (regno) == 1 && DF_REF_INSN_INFO (def));
       rtx_insn *def_insn = DF_REF_INSN (def);
@@ -3683,6 +3784,11 @@ combine_and_move_insns (void)
       if (can_throw_internal (def_insn))
        continue;
 
+      /* Instructions with multiple sets can only be moved if DF analysis is
+        performed for all of the registers set.  See PR91052.  */
+      if (multiple_sets (def_insn))
+       continue;
+
       basic_block use_bb = BLOCK_FOR_INSN (use_insn);
       basic_block def_bb = BLOCK_FOR_INSN (def_insn);
       if (bb_loop_depth (use_bb) > bb_loop_depth (def_bb))
@@ -3709,6 +3815,14 @@ combine_and_move_insns (void)
          remove_death (regno, use_insn);
          SET_REG_N_REFS (regno, 0);
          REG_FREQ (regno) = 0;
+         df_ref use;
+         FOR_EACH_INSN_USE (use, def_insn)
+           {
+             unsigned int use_regno = DF_REF_REGNO (use);
+             if (!HARD_REGISTER_NUM_P (use_regno))
+               reg_equiv[use_regno].replace = 0;
+           }
+
          delete_insn (def_insn);
 
          reg_equiv[regno].init_insns = NULL;
@@ -3751,7 +3865,7 @@ combine_and_move_insns (void)
             use_insn, when regno was seen as non-local.  Now that
             regno is local to this block, and dies, such an
             equivalence is invalid.  */
-         if (find_reg_note (use_insn, REG_EQUIV, NULL_RTX))
+         if (find_reg_note (use_insn, REG_EQUIV, regno_reg_rtx[regno]))
            {
              rtx set = single_set (use_insn);
              if (set && REG_P (SET_DEST (set)))
@@ -3779,9 +3893,9 @@ combine_and_move_insns (void)
        }
 
       /* Last pass - adjust debug insns referencing cleared regs.  */
-      if (MAY_HAVE_DEBUG_INSNS)
+      if (MAY_HAVE_DEBUG_BIND_INSNS)
        for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
-         if (DEBUG_INSN_P (insn))
+         if (DEBUG_BIND_INSN_P (insn))
            {
              rtx old_loc = INSN_VAR_LOCATION_LOC (insn);
              INSN_VAR_LOCATION_LOC (insn)
@@ -3792,8 +3906,6 @@ combine_and_move_insns (void)
                df_insn_rescan (insn);
            }
     }
-
-  BITMAP_FREE (cleared_regs);
 }
 
 /* A pass over indirect jumps, converting simple cases to direct jumps.
@@ -3952,7 +4064,7 @@ setup_reg_equiv (void)
 
 /* Print chain C to FILE.  */
 static void
-print_insn_chain (FILE *file, struct insn_chain *c)
+print_insn_chain (FILE *file, class insn_chain *c)
 {
   fprintf (file, "insn=%d, ", INSN_UID (c->insn));
   bitmap_print (file, &c->live_throughout, "live_throughout: ", ", ");
@@ -3964,7 +4076,7 @@ print_insn_chain (FILE *file, struct insn_chain *c)
 static void
 print_insn_chains (FILE *file)
 {
-  struct insn_chain *c;
+  class insn_chain *c;
   for (c = reload_insn_chain; c ; c = c->next)
     print_insn_chain (file, c);
 }
@@ -3979,16 +4091,26 @@ pseudo_for_reload_consideration_p (int regno)
   return (reg_renumber[regno] >= 0 || ira_conflicts_p);
 }
 
-/* Init LIVE_SUBREGS[ALLOCNUM] and LIVE_SUBREGS_USED[ALLOCNUM] using
-   REG to the number of nregs, and INIT_VALUE to get the
-   initialization.  ALLOCNUM need not be the regno of REG.  */
+/* Return true if we can track the individual bytes of subreg X.
+   When returning true, set *OUTER_SIZE to the number of bytes in
+   X itself, *INNER_SIZE to the number of bytes in the inner register
+   and *START to the offset of the first byte.  */
+static bool
+get_subreg_tracking_sizes (rtx x, HOST_WIDE_INT *outer_size,
+                          HOST_WIDE_INT *inner_size, HOST_WIDE_INT *start)
+{
+  rtx reg = regno_reg_rtx[REGNO (SUBREG_REG (x))];
+  return (GET_MODE_SIZE (GET_MODE (x)).is_constant (outer_size)
+         && GET_MODE_SIZE (GET_MODE (reg)).is_constant (inner_size)
+         && SUBREG_BYTE (x).is_constant (start));
+}
+
+/* Init LIVE_SUBREGS[ALLOCNUM] and LIVE_SUBREGS_USED[ALLOCNUM] for
+   a register with SIZE bytes, making the register live if INIT_VALUE.  */
 static void
 init_live_subregs (bool init_value, sbitmap *live_subregs,
-                  bitmap live_subregs_used, int allocnum, rtx reg)
+                  bitmap live_subregs_used, int allocnum, int size)
 {
-  unsigned int regno = REGNO (SUBREG_REG (reg));
-  int size = GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno]));
-
   gcc_assert (size > 0);
 
   /* Been there, done that.  */
@@ -4015,12 +4137,12 @@ static void
 build_insn_chain (void)
 {
   unsigned int i;
-  struct insn_chain **p = &reload_insn_chain;
+  class insn_chain **p = &reload_insn_chain;
   basic_block bb;
-  struct insn_chain *c = NULL;
-  struct insn_chain *next = NULL;
-  bitmap live_relevant_regs = BITMAP_ALLOC (NULL);
-  bitmap elim_regset = BITMAP_ALLOC (NULL);
+  class insn_chain *c = NULL;
+  class insn_chain *next = NULL;
+  auto_bitmap live_relevant_regs;
+  auto_bitmap elim_regset;
   /* live_subregs is a vector used to keep accurate information about
      which hardregs are live in multiword pseudos.  live_subregs and
      live_subregs_used are indexed by pseudo number.  The live_subreg
@@ -4029,7 +4151,7 @@ build_insn_chain (void)
      live_subreg[allocno] is number of bytes that the pseudo can
      occupy.  */
   sbitmap *live_subregs = XCNEWVEC (sbitmap, max_regno);
-  bitmap live_subregs_used = BITMAP_ALLOC (NULL);
+  auto_bitmap live_subregs_used;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (TEST_HARD_REG_BIT (eliminable_regset, i))
@@ -4097,19 +4219,26 @@ build_insn_chain (void)
                        && (!DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)))
                      {
                        rtx reg = DF_REF_REG (def);
-
-                       /* We can model subregs, but not if they are
-                          wrapped in ZERO_EXTRACTS.  */
+                       HOST_WIDE_INT outer_size, inner_size, start;
+
+                       /* We can usually track the liveness of individual
+                          bytes within a subreg.  The only exceptions are
+                          subregs wrapped in ZERO_EXTRACTs and subregs whose
+                          size is not known; in those cases we need to be
+                          conservative and treat the definition as a partial
+                          definition of the full register rather than a full
+                          definition of a specific part of the register.  */
                        if (GET_CODE (reg) == SUBREG
-                           && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
+                           && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT)
+                           && get_subreg_tracking_sizes (reg, &outer_size,
+                                                         &inner_size, &start))
                          {
-                           unsigned int start = SUBREG_BYTE (reg);
-                           unsigned int last = start
-                             + GET_MODE_SIZE (GET_MODE (reg));
+                           HOST_WIDE_INT last = start + outer_size;
 
                            init_live_subregs
                              (bitmap_bit_p (live_relevant_regs, regno),
-                              live_subregs, live_subregs_used, regno, reg);
+                              live_subregs, live_subregs_used, regno,
+                              inner_size);
 
                            if (!DF_REF_FLAGS_IS_SET
                                (def, DF_REF_STRICT_LOW_PART))
@@ -4194,18 +4323,20 @@ build_insn_chain (void)
                    if (regno < FIRST_PSEUDO_REGISTER
                        || pseudo_for_reload_consideration_p (regno))
                      {
+                       HOST_WIDE_INT outer_size, inner_size, start;
                        if (GET_CODE (reg) == SUBREG
                            && !DF_REF_FLAGS_IS_SET (use,
                                                     DF_REF_SIGN_EXTRACT
-                                                    | DF_REF_ZERO_EXTRACT))
+                                                    | DF_REF_ZERO_EXTRACT)
+                           && get_subreg_tracking_sizes (reg, &outer_size,
+                                                         &inner_size, &start))
                          {
-                           unsigned int start = SUBREG_BYTE (reg);
-                           unsigned int last = start
-                             + GET_MODE_SIZE (GET_MODE (reg));
+                           HOST_WIDE_INT last = start + outer_size;
 
                            init_live_subregs
                              (bitmap_bit_p (live_relevant_regs, regno),
-                              live_subregs, live_subregs_used, regno, reg);
+                              live_subregs, live_subregs_used, regno,
+                              inner_size);
 
                            /* Ignore the paradoxical bits.  */
                            if (last > SBITMAP_SIZE (live_subregs[regno]))
@@ -4272,9 +4403,6 @@ build_insn_chain (void)
     if (live_subregs[i] != NULL)
       sbitmap_free (live_subregs[i]);
   free (live_subregs);
-  BITMAP_FREE (live_subregs_used);
-  BITMAP_FREE (live_relevant_regs);
-  BITMAP_FREE (elim_regset);
 
   if (dump_file)
     print_insn_chains (dump_file);
@@ -4289,10 +4417,9 @@ rtx_moveable_p (rtx *loc, enum op_type type)
 {
   const char *fmt;
   rtx x = *loc;
-  enum rtx_code code = GET_CODE (x);
   int i, j;
 
-  code = GET_CODE (x);
+  enum rtx_code code = GET_CODE (x);
   switch (code)
     {
     case CONST:
@@ -4342,6 +4469,12 @@ rtx_moveable_p (rtx *loc, enum op_type type)
         for a reason.  */
       return false;
 
+    case ASM_OPERANDS:
+      /* The same is true for volatile asm: it has unknown side effects, it
+         cannot be moved at will.  */
+      if (MEM_VOLATILE_P (x))
+       return false;
+
     default:
       break;
     }
@@ -4426,9 +4559,8 @@ find_moveable_pseudos (void)
      moved freely downwards, but are otherwise transparent to a block.  */
   bitmap_head *bb_moveable_reg_sets = XNEWVEC (bitmap_head,
                                               last_basic_block_for_fn (cfun));
-  bitmap_head live, used, set, interesting, unusable_as_input;
+  auto_bitmap live, used, set, interesting, unusable_as_input;
   bitmap_iterator bi;
-  bitmap_initialize (&interesting, 0);
 
   first_moveable_pseudo = max_regs;
   pseudo_replaced_reg.release ();
@@ -4438,10 +4570,6 @@ find_moveable_pseudos (void)
   calculate_dominance_info (CDI_DOMINATORS);
 
   i = 0;
-  bitmap_initialize (&live, 0);
-  bitmap_initialize (&used, 0);
-  bitmap_initialize (&set, 0);
-  bitmap_initialize (&unusable_as_input, 0);
   FOR_EACH_BB_FN (bb, cfun)
     {
       rtx_insn *insn;
@@ -4452,13 +4580,13 @@ find_moveable_pseudos (void)
       bitmap_initialize (local, 0);
       bitmap_initialize (transp, 0);
       bitmap_initialize (moveable, 0);
-      bitmap_copy (&live, df_get_live_out (bb));
-      bitmap_and_into (&live, df_get_live_in (bb));
-      bitmap_copy (transp, &live);
+      bitmap_copy (live, df_get_live_out (bb));
+      bitmap_and_into (live, df_get_live_in (bb));
+      bitmap_copy (transp, live);
       bitmap_clear (moveable);
-      bitmap_clear (&live);
-      bitmap_clear (&used);
-      bitmap_clear (&set);
+      bitmap_clear (live);
+      bitmap_clear (used);
+      bitmap_clear (set);
       FOR_BB_INSNS (bb, insn)
        if (NONDEBUG_INSN_P (insn))
          {
@@ -4472,20 +4600,20 @@ find_moveable_pseudos (void)
            if (use
                && def
                && DF_REF_REGNO (use) == DF_REF_REGNO (def)
-               && !bitmap_bit_p (&set, DF_REF_REGNO (use))
+               && !bitmap_bit_p (set, DF_REF_REGNO (use))
                && rtx_moveable_p (&PATTERN (insn), OP_IN))
              {
                unsigned regno = DF_REF_REGNO (use);
                bitmap_set_bit (moveable, regno);
-               bitmap_set_bit (&set, regno);
-               bitmap_set_bit (&used, regno);
+               bitmap_set_bit (set, regno);
+               bitmap_set_bit (used, regno);
                bitmap_clear_bit (transp, regno);
                continue;
              }
            FOR_EACH_INSN_INFO_USE (use, insn_info)
              {
                unsigned regno = DF_REF_REGNO (use);
-               bitmap_set_bit (&used, regno);
+               bitmap_set_bit (used, regno);
                if (bitmap_clear_bit (moveable, regno))
                  bitmap_clear_bit (transp, regno);
              }
@@ -4493,17 +4621,13 @@ find_moveable_pseudos (void)
            FOR_EACH_INSN_INFO_DEF (def, insn_info)
              {
                unsigned regno = DF_REF_REGNO (def);
-               bitmap_set_bit (&set, regno);
+               bitmap_set_bit (set, regno);
                bitmap_clear_bit (transp, regno);
                bitmap_clear_bit (moveable, regno);
              }
          }
     }
 
-  bitmap_clear (&live);
-  bitmap_clear (&used);
-  bitmap_clear (&set);
-
   FOR_EACH_BB_FN (bb, cfun)
     {
       bitmap local = bb_local + bb->index;
@@ -4546,7 +4670,7 @@ find_moveable_pseudos (void)
                if (dump_file)
                  fprintf (dump_file, "Ignoring reg %d, has equiv memory\n",
                           regno);
-               bitmap_set_bit (&unusable_as_input, regno);
+               bitmap_set_bit (unusable_as_input, regno);
                continue;
              }
 
@@ -4606,7 +4730,7 @@ find_moveable_pseudos (void)
                continue;
              }
 
-           bitmap_set_bit (&interesting, regno);
+           bitmap_set_bit (interesting, regno);
            /* If we get here, we know closest_use is a non-NULL insn
               (as opposed to const_0_rtx).  */
            closest_uses[regno] = as_a <rtx_insn *> (closest_use);
@@ -4625,7 +4749,7 @@ find_moveable_pseudos (void)
          }
     }
 
-  EXECUTE_IF_SET_IN_BITMAP (&interesting, 0, i, bi)
+  EXECUTE_IF_SET_IN_BITMAP (interesting, 0, i, bi)
     {
       df_ref def = DF_REG_DEF_CHAIN (i);
       rtx_insn *def_insn = DF_REF_INSN (def);
@@ -4669,7 +4793,7 @@ find_moveable_pseudos (void)
       FOR_EACH_INSN_USE (use, def_insn)
        {
          unsigned regno = DF_REF_REGNO (use);
-         if (bitmap_bit_p (&unusable_as_input, regno))
+         if (bitmap_bit_p (unusable_as_input, regno))
            {
              all_ok = false;
              if (dump_file)
@@ -4735,8 +4859,6 @@ find_moveable_pseudos (void)
       bitmap_clear (bb_transp_live + bb->index);
       bitmap_clear (bb_moveable_reg_sets + bb->index);
     }
-  bitmap_clear (&interesting);
-  bitmap_clear (&unusable_as_input);
   free (uid_luid);
   free (closest_uses);
   free (bb_local);
@@ -4816,14 +4938,12 @@ split_live_ranges_for_shrink_wrap (void)
   basic_block bb, call_dom = NULL;
   basic_block first = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
   rtx_insn *insn, *last_interesting_insn = NULL;
-  bitmap_head need_new, reachable;
+  auto_bitmap need_new, reachable;
   vec<basic_block> queue;
 
   if (!SHRINK_WRAPPING_ENABLED)
     return false;
 
-  bitmap_initialize (&need_new, 0);
-  bitmap_initialize (&reachable, 0);
   queue.create (n_basic_blocks_for_fn (cfun));
 
   FOR_EACH_BB_FN (bb, cfun)
@@ -4832,22 +4952,18 @@ split_live_ranges_for_shrink_wrap (void)
        {
          if (bb == first)
            {
-             bitmap_clear (&need_new);
-             bitmap_clear (&reachable);
              queue.release ();
              return false;
            }
 
-         bitmap_set_bit (&need_new, bb->index);
-         bitmap_set_bit (&reachable, bb->index);
+         bitmap_set_bit (need_new, bb->index);
+         bitmap_set_bit (reachable, bb->index);
          queue.quick_push (bb);
          break;
        }
 
   if (queue.is_empty ())
     {
-      bitmap_clear (&need_new);
-      bitmap_clear (&reachable);
       queue.release ();
       return false;
     }
@@ -4860,7 +4976,7 @@ split_live_ranges_for_shrink_wrap (void)
       bb = queue.pop ();
       FOR_EACH_EDGE (e, ei, bb->succs)
        if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
-           && bitmap_set_bit (&reachable, e->dest->index))
+           && bitmap_set_bit (reachable, e->dest->index))
          queue.quick_push (e->dest);
     }
   queue.release ();
@@ -4872,32 +4988,23 @@ split_live_ranges_for_shrink_wrap (void)
        continue;
 
       if (DF_REG_DEF_COUNT (REGNO (dest)) > 1)
-       {
-         bitmap_clear (&need_new);
-         bitmap_clear (&reachable);
-         return false;
-       }
+       return false;
 
       for (df_ref use = DF_REG_USE_CHAIN (REGNO(dest));
           use;
           use = DF_REF_NEXT_REG (use))
        {
          int ubbi = DF_REF_BB (use)->index;
-         if (bitmap_bit_p (&reachable, ubbi))
-           bitmap_set_bit (&need_new, ubbi);
+         if (bitmap_bit_p (reachable, ubbi))
+           bitmap_set_bit (need_new, ubbi);
        }
       last_interesting_insn = insn;
     }
 
-  bitmap_clear (&reachable);
   if (!last_interesting_insn)
-    {
-      bitmap_clear (&need_new);
-      return false;
-    }
+    return false;
 
-  call_dom = nearest_common_dominator_for_set (CDI_DOMINATORS, &need_new);
-  bitmap_clear (&need_new);
+  call_dom = nearest_common_dominator_for_set (CDI_DOMINATORS, need_new);
   if (call_dom == first)
     return false;
 
@@ -4928,25 +5035,40 @@ split_live_ranges_for_shrink_wrap (void)
       if (!dest || dest == pic_offset_table_rtx)
        continue;
 
-      rtx newreg = NULL_RTX;
+      bool need_newreg = false;
       df_ref use, next;
       for (use = DF_REG_USE_CHAIN (REGNO (dest)); use; use = next)
        {
          rtx_insn *uin = DF_REF_INSN (use);
          next = DF_REF_NEXT_REG (use);
 
+         if (DEBUG_INSN_P (uin))
+           continue;
+
          basic_block ubb = BLOCK_FOR_INSN (uin);
          if (ubb == call_dom
              || dominated_by_p (CDI_DOMINATORS, ubb, call_dom))
            {
-             if (!newreg)
-               newreg = ira_create_new_reg (dest);
-             validate_change (uin, DF_REF_REAL_LOC (use), newreg, true);
+             need_newreg = true;
+             break;
            }
        }
 
-      if (newreg)
+      if (need_newreg)
        {
+         rtx newreg = ira_create_new_reg (dest);
+
+         for (use = DF_REG_USE_CHAIN (REGNO (dest)); use; use = next)
+           {
+             rtx_insn *uin = DF_REF_INSN (use);
+             next = DF_REF_NEXT_REG (use);
+
+             basic_block ubb = BLOCK_FOR_INSN (uin);
+             if (ubb == call_dom
+                 || dominated_by_p (CDI_DOMINATORS, ubb, call_dom))
+               validate_change (uin, DF_REF_REAL_LOC (use), newreg, true);
+           }
+
          rtx_insn *new_move = gen_move_insn (newreg, dest);
          emit_insn_after (new_move, bb_note (call_dom));
          if (dump_file)
@@ -5076,24 +5198,39 @@ ira (FILE *f)
   bool saved_flag_caller_saves = flag_caller_saves;
   enum ira_region saved_flag_ira_region = flag_ira_region;
 
+  clear_bb_flags ();
+
+  /* Determine if the current function is a leaf before running IRA
+     since this can impact optimizations done by the prologue and
+     epilogue thus changing register elimination offsets.
+     Other target callbacks may use crtl->is_leaf too, including
+     SHRINK_WRAPPING_ENABLED, so initialize as early as possible.  */
+  crtl->is_leaf = leaf_function_p ();
+
   /* Perform target specific PIC register initialization.  */
   targetm.init_pic_reg ();
 
   ira_conflicts_p = optimize > 0;
 
-  ira_use_lra_p = targetm.lra_p ();
+  /* Determine the number of pseudos actually requiring coloring.  */
+  unsigned int num_used_regs = 0;
+  for (unsigned int i = FIRST_PSEUDO_REGISTER; i < DF_REG_SIZE (df); i++)
+    if (DF_REG_DEF_COUNT (i) || DF_REG_USE_COUNT (i))
+      num_used_regs++;
+
   /* If there are too many pseudos and/or basic blocks (e.g. 10K
      pseudos and 10K blocks or 100K pseudos and 1K blocks), we will
      use simplified and faster algorithms in LRA.  */
   lra_simple_p
-    = (ira_use_lra_p
-       && max_reg_num () >= (1 << 26) / last_basic_block_for_fn (cfun));
+    = ira_use_lra_p
+      && num_used_regs >= (1U << 26) / last_basic_block_for_fn (cfun);
+
   if (lra_simple_p)
     {
       /* It permits to skip live range splitting in LRA.  */
       flag_caller_saves = false;
       /* There is no sense to do regional allocation when we use
-        simplified LRA.  */
+       simplified LRA.  */
       flag_ira_region = IRA_REGION_ONE;
       ira_conflicts_p = false;
     }
@@ -5162,16 +5299,13 @@ ira (FILE *f)
   if (warn_clobbered)
     generate_setjmp_warnings ();
 
-  /* Determine if the current function is a leaf before running IRA
-     since this can impact optimizations done by the prologue and
-     epilogue thus changing register elimination offsets.  */
-  crtl->is_leaf = leaf_function_p ();
-
   if (resize_reg_info () && flag_ira_loop_pressure)
     ira_set_pseudo_classes (true, ira_dump_file);
 
   init_alias_analysis ();
+  loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
   reg_equiv = XCNEWVEC (struct equivalence, max_reg_num ());
+  update_equiv_regs_prescan ();
   update_equiv_regs ();
 
   /* Don't move insns if live range shrinkage or register
@@ -5186,6 +5320,8 @@ ira (FILE *f)
   if (optimize)
     add_store_equivs ();
 
+  loop_optimizer_finalize ();
+  free_dominance_info (CDI_DOMINATORS);
   end_alias_analysis ();
   free (reg_equiv);
 
@@ -5264,7 +5400,6 @@ ira (FILE *f)
                                        reg_alternate_class (old_regno),
                                        reg_allocno_class (old_regno));
                 }
-
            }
          else
            {
@@ -5300,7 +5435,14 @@ ira (FILE *f)
   calculate_allocation_cost ();
 
 #ifdef ENABLE_IRA_CHECKING
-  if (ira_conflicts_p)
+  if (ira_conflicts_p && ! ira_use_lra_p)
+    /* Opposite to reload pass, LRA does not use any conflict info
+       from IRA.  We don't rebuild conflict info for LRA (through
+       ira_flattening call) and cannot use the check here.  We could
+       rebuild this info for LRA in the check mode but there is a risk
+       that code generated with the check and without it will be a bit
+       different.  Calling ira_flattening in any mode would be a
+       wasting CPU time.  So do not check the allocation for LRA.  */
     check_allocation ();
 #endif
 
@@ -5326,11 +5468,11 @@ ira (FILE *f)
        {
          ira_spilled_reg_stack_slots_num = 0;
          ira_spilled_reg_stack_slots
-           = ((struct ira_spilled_reg_stack_slot *)
+           = ((class ira_spilled_reg_stack_slot *)
               ira_allocate (max_regno
-                            * sizeof (struct ira_spilled_reg_stack_slot)));
-         memset (ira_spilled_reg_stack_slots, 0,
-                 max_regno * sizeof (struct ira_spilled_reg_stack_slot));
+                            * sizeof (class ira_spilled_reg_stack_slot)));
+         memset ((void *)ira_spilled_reg_stack_slots, 0,
+                 max_regno * sizeof (class ira_spilled_reg_stack_slot));
        }
     }
   allocate_initial_values ();
@@ -5472,13 +5614,15 @@ do_reload (void)
      function's frame size is larger than we expect.  */
   if (flag_stack_check == GENERIC_STACK_CHECK)
     {
-      HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
+      poly_int64 size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
 
       for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (df_regs_ever_live_p (i) && !fixed_regs[i] && call_used_regs[i])
+       if (df_regs_ever_live_p (i)
+           && !fixed_regs[i]
+           && !crtl->abi->clobbers_full_reg_p (i))
          size += UNITS_PER_WORD;
 
-      if (size > STACK_CHECK_MAX_FRAME_SIZE)
+      if (constant_lower_bound (size) > STACK_CHECK_MAX_FRAME_SIZE)
        warning (0, "frame size too large for reliable stack checking");
     }