From: claziss <claz...@synopsys.com>

Hi Andrew,

This is a patch which fixes and sets LRA by default.

OK to apply?
Claudiu

 **** Commit message ****

LP_COUNT register cannot be freely allocated by the compiler as it
size, and/or content may change depending on the ARC hardware
configuration. Thus, make this register fixed.

Remove register classes and unused constraint letters.

Cleanup the implementation of conditional_register_usage hook by using
macros instead of magic constants and removing all references to
reg_class_contents which are bringing so much grief when lra is enabled.

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claz...@synopsys.com>

        * config/arc/arc.h (reg_class): Reorder registers classes, remove
        unused register classes.
        (REG_CLASS_NAMES): Likewise.
        (REG_CLASS_CONTENTS): Likewise.
        (FIXED_REGISTERS): Make lp_count fixed.
        (BASE_REG_CLASS): Remove ACC16_BASE_REGS reference.
        (PROGRAM_COUNTER_REGNO): Remove.
        * config/arc/arc.c (arc_conditional_register_usage): Remove unused
        register classes, use constants for register numbers, remove
        reg_class_contents references.
        (arc_process_double_reg_moves): Add asserts.
        (arc_secondary_reload): Remove LPCOUNT_REG reference, use
        lra_in_progress predicate.
        (arc_init_reg_tables): Remove unused register classes.
        (arc_register_move_cost): Likewise.
        (arc_preferred_reload_class): Likewise.
        (hwloop_optimize): Update rtx patterns involving lp_count
        register.
        (arc_return_address_register): Rename ILINK1, INLINK2 regnums
        macros.
        * config/arc/constraints.md ("c"): Choose between GENERAL_REGS and
        CHEAP_CORE_REGS.  Former one will be used for LRA.
        ("Rac"): Choose between GENERAL_REGS and ALL_CORE_REGS.  Former
        one will be used for LRA.
        ("w"): Choose between GENERAL_REGS and WRITABLE_CORE_REGS.  Former
        one will be used for LRA.
        ("W"): Choose between GENERAL_REGS and MPY_WRITABLE_CORE_REGS.
        Former one will be used for LRA.
        ("f"): Delete constraint.
        ("k"): Likewise.
        ("e"): Likewise.
        (movqi_insn): Remove unsed lp_count constraints.
        (movhi_insn): Likewise.
        (movsi_insn): Update pattern.
        (arc_lp): Likewise.
        (dbnz): Likewise.
        ("l"): Change it from register constraint to constraint.
        (stack_tie): Remove 'b' constraint letter.
        (R4_REG): Define.
        (R9_REG, R15_REG, R16_REG, R25_REG): Likewise.
        (R32_REG, R40_REG, R41_REG, R42_REG, R43_REG, R44_REG): Likewise.
        (R57_REG, R59_REG, PCL_REG): Likewise.
        (ILINK1_REGNUM): Renamed to ILINK1_REG.
        (ILINK2_REGNUM): Renamed to ILINK2_REG.
        (Rgp): Remove.
        (SP_REGS): Likewise.
        (Rcw): Remove unused reg classes.
        * config/arc/predicates.md (dest_reg_operand): Just default on
        register_operand predicate.
        (mpy_dest_reg_operand): Likewise.
        (move_dest_operand): Use macros instead of constants.
---
 gcc/config/arc/arc.c          | 331 +++++++++++++---------------------
 gcc/config/arc/arc.h          | 106 ++++-------
 gcc/config/arc/arc.md         |  57 ++++--
 gcc/config/arc/arc.opt        |   7 +-
 gcc/config/arc/constraints.md |  45 ++---
 gcc/config/arc/predicates.md  |  28 +--
 6 files changed, 222 insertions(+), 352 deletions(-)

diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 75c2384eede..6802ca66554 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -734,11 +734,6 @@ arc_secondary_reload (bool in_p,
   if (cl == DOUBLE_REGS)
     return GENERAL_REGS;
 
-  /* The loop counter register can be stored, but not loaded directly.  */
-  if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
-      && in_p && MEM_P (x))
-    return GENERAL_REGS;
-
  /* If we have a subreg (reg), where reg is a pseudo (that will end in
     a memory location), then we may need a scratch register to handle
     the fp/sp+largeoffset address.  */
@@ -756,8 +751,9 @@ arc_secondary_reload (bool in_p,
          if (regno != -1)
            return NO_REGS;
 
-         /* It is a pseudo that ends in a stack location.  */
-         if (reg_equiv_mem (REGNO (x)))
+         /* It is a pseudo that ends in a stack location.  This
+            procedure only works with the old reload step.  */
+         if (reg_equiv_mem (REGNO (x)) && !lra_in_progress)
            {
              /* Get the equivalent address and check the range of the
                 offset.  */
@@ -1659,8 +1655,6 @@ enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
 enum reg_class
 arc_preferred_reload_class (rtx, enum reg_class cl)
 {
-  if ((cl) == CHEAP_CORE_REGS  || (cl) == WRITABLE_CORE_REGS)
-    return GENERAL_REGS;
   return cl;
 }
 
@@ -1758,25 +1752,21 @@ arc_conditional_register_usage (void)
       strcpy (rname29, "ilink");
       strcpy (rname30, "r30");
 
-      if (!TEST_HARD_REG_BIT (overrideregs, 30))
+      if (!TEST_HARD_REG_BIT (overrideregs, R30_REG))
        {
          /* No user interference.  Set the r30 to be used by the
             compiler.  */
-         call_used_regs[30] = 1;
-         fixed_regs[30] = 0;
+         call_used_regs[R30_REG] = 1;
+         fixed_regs[R30_REG] = 0;
 
-         arc_regno_reg_class[30] = WRITABLE_CORE_REGS;
-         SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], 30);
-         SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], 30);
-         SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], 30);
-         SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], 30);
+         arc_regno_reg_class[R30_REG] = GENERAL_REGS;
        }
    }
 
   if (TARGET_MUL64_SET)
     {
-      fix_start = 57;
-      fix_end = 59;
+      fix_start = R57_REG;
+      fix_end = R59_REG;
 
       /* We don't provide a name for mmed.  In rtl / assembly resource lists,
         you are supposed to refer to it as mlo & mhi, e.g
@@ -1799,8 +1789,8 @@ arc_conditional_register_usage (void)
 
   if (TARGET_MULMAC_32BY16_SET)
     {
-      fix_start = 56;
-      fix_end = fix_end > 57 ? fix_end : 57;
+      fix_start = MUL32x16_REG;
+      fix_end = fix_end > R57_REG ? fix_end : R57_REG;
       strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
       strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
     }
@@ -1862,130 +1852,59 @@ arc_conditional_register_usage (void)
   /* Reduced configuration: don't use r4-r9, r16-r25.  */
   if (TARGET_RF16)
     {
-      for (i = 4; i <= 9; i++)
-       {
-         fixed_regs[i] = call_used_regs[i] = 1;
-       }
-      for (i = 16; i <= 25; i++)
-       {
-         fixed_regs[i] = call_used_regs[i] = 1;
-       }
-    }
-
-  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-    if (!call_used_regs[regno])
-      CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
-  for (regno = 32; regno < 60; regno++)
-    if (!fixed_regs[regno])
-      SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
-  if (!TARGET_ARC600_FAMILY)
-    {
-      for (regno = 32; regno <= 60; regno++)
-       CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
-
-      /* If they have used -ffixed-lp_count, make sure it takes
-        effect.  */
-      if (fixed_regs[LP_COUNT])
-       {
-         CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
-         CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
-         CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
-
-         /* Instead of taking out SF_MODE like below, forbid it outright.  */
-         arc_hard_regno_modes[60] = 0;
-       }
-      else
-       arc_hard_regno_modes[60] = 1 << (int) S_MODE;
+      for (i = R4_REG; i <= R9_REG; i++)
+       fixed_regs[i] = call_used_regs[i] = 1;
+      for (i = R16_REG; i <= R25_REG; i++)
+       fixed_regs[i] = call_used_regs[i] = 1;
     }
 
   /* ARCHS has 64-bit data-path which makes use of the even-odd paired
      registers.  */
   if (TARGET_HS)
-    {
-      for (regno = 1; regno < 32; regno +=2)
-       {
-         arc_hard_regno_modes[regno] = S_MODES;
-       }
-    }
+    for (regno = R1_REG; regno < R32_REG; regno +=2)
+      arc_hard_regno_modes[regno] = S_MODES;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if (i < 29)
-       {
-         if ((TARGET_Q_CLASS || TARGET_RRQ_CLASS)
-             && ((i <= 3) || ((i >= 12) && (i <= 15))))
-           arc_regno_reg_class[i] = ARCOMPACT16_REGS;
-         else
-           arc_regno_reg_class[i] = GENERAL_REGS;
-       }
-      else if (i < 60)
-       arc_regno_reg_class[i]
-         = (fixed_regs[i]
-            ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
-               ? CHEAP_CORE_REGS : ALL_CORE_REGS)
-            : (((!TARGET_ARC600_FAMILY)
-                && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
-               ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
-      else
-       arc_regno_reg_class[i] = NO_REGS;
-    }
-
-  /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS / TARGET_RRQ_CLASS
-     has not been activated.  */
-  if (!TARGET_Q_CLASS && !TARGET_RRQ_CLASS)
-    CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
-  if (!TARGET_Q_CLASS)
-    CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
-
-  gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
+    if (i < ILINK1_REG)
+      {
+       if ((TARGET_Q_CLASS || TARGET_RRQ_CLASS)
+           && ((i <= R3_REG) || ((i >= R12_REG) && (i <= R15_REG))))
+         arc_regno_reg_class[i] = ARCOMPACT16_REGS;
+       else
+         arc_regno_reg_class[i] = GENERAL_REGS;
+      }
+    else if (i < LP_COUNT)
+      arc_regno_reg_class[i] = GENERAL_REGS;
+    else
+      arc_regno_reg_class[i] = NO_REGS;
 
   /* Handle Special Registers.  */
-  arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register.  */
-  if (!TARGET_V2)
-    arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register.  */
-  arc_regno_reg_class[31] = LINK_REGS; /* blink register.  */
-  arc_regno_reg_class[60] = LPCOUNT_REG;
-  arc_regno_reg_class[61] = NO_REGS;      /* CC_REG: must be NO_REGS.  */
+  arc_regno_reg_class[CC_REG] = NO_REGS;      /* CC_REG: must be NO_REGS.  */
   arc_regno_reg_class[62] = GENERAL_REGS;
 
   if (TARGET_DPFP)
-    {
-      for (i = 40; i < 44; ++i)
-       {
-         arc_regno_reg_class[i] = DOUBLE_REGS;
-
-         /* Unless they want us to do 'mov d1, 0x00000000' make sure
-            no attempt is made to use such a register as a destination
-            operand in *movdf_insn.  */
-         if (!TARGET_ARGONAUT_SET)
-           {
-           /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
-              interpreted to mean they can use D1 or D2 in their insn.  */
-           CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS       ], i);
-           CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS         ], i);
-           CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS    ], i);
-           CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
-           }
-       }
-    }
+    for (i = R40_REG; i < R44_REG; ++i)
+      {
+       arc_regno_reg_class[i] = DOUBLE_REGS;
+       if (!TARGET_ARGONAUT_SET)
+         CLEAR_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i);
+      }
   else
     {
-      /* Disable all DOUBLE_REGISTER settings,
-        if not generating DPFP code.  */
-      arc_regno_reg_class[40] = ALL_REGS;
-      arc_regno_reg_class[41] = ALL_REGS;
-      arc_regno_reg_class[42] = ALL_REGS;
-      arc_regno_reg_class[43] = ALL_REGS;
+      /* Disable all DOUBLE_REGISTER settings, if not generating DPFP
+        code.  */
+      arc_regno_reg_class[R40_REG] = ALL_REGS;
+      arc_regno_reg_class[R41_REG] = ALL_REGS;
+      arc_regno_reg_class[R42_REG] = ALL_REGS;
+      arc_regno_reg_class[R43_REG] = ALL_REGS;
 
-      fixed_regs[40] = 1;
-      fixed_regs[41] = 1;
-      fixed_regs[42] = 1;
-      fixed_regs[43] = 1;
+      fixed_regs[R40_REG] = 1;
+      fixed_regs[R41_REG] = 1;
+      fixed_regs[R42_REG] = 1;
+      fixed_regs[R43_REG] = 1;
 
-      arc_hard_regno_modes[40] = 0;
-      arc_hard_regno_modes[42] = 0;
-
-      CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
+      arc_hard_regno_modes[R40_REG] = 0;
+      arc_hard_regno_modes[R42_REG] = 0;
     }
 
   if (TARGET_SIMD_SET)
@@ -2007,23 +1926,15 @@ arc_conditional_register_usage (void)
     }
 
   /* pc : r63 */
-  arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
+  arc_regno_reg_class[PCL_REG] = NO_REGS;
 
   /*ARCV2 Accumulator.  */
   if ((TARGET_V2
        && (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED))
       || TARGET_PLUS_DMPY)
   {
-    arc_regno_reg_class[ACCL_REGNO] = WRITABLE_CORE_REGS;
-    arc_regno_reg_class[ACCH_REGNO] = WRITABLE_CORE_REGS;
-    SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCL_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCH_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCL_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCH_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCL_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCH_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], ACCL_REGNO);
-    SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], ACCH_REGNO);
+    arc_regno_reg_class[ACCL_REGNO] = GENERAL_REGS;
+    arc_regno_reg_class[ACCH_REGNO] = GENERAL_REGS;
 
     /* Allow the compiler to freely use them.  */
     if (!TEST_HARD_REG_BIT (overrideregs, ACCL_REGNO))
@@ -7798,6 +7709,25 @@ hwloop_fail (hwloop_info loop)
   delete_insn (loop->loop_end);
 }
 
+/* Return the next insn after INSN that is not a NOTE, but stop the
+   search before we enter another basic block.  This routine does not
+   look inside SEQUENCEs.  */
+
+static rtx_insn *
+next_nonnote_insn_bb (rtx_insn *insn)
+{
+  while (insn)
+    {
+      insn = NEXT_INSN (insn);
+      if (insn == 0 || !NOTE_P (insn))
+       break;
+      if (NOTE_INSN_BASIC_BLOCK_P (insn))
+       return NULL;
+    }
+
+  return insn;
+}
+
 /* Optimize LOOP.  */
 
 static bool
@@ -7815,41 +7745,41 @@ hwloop_optimize (hwloop_info loop)
   if (loop->depth > 1)
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d is not innermost\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d is not innermost\n",
+                loop->loop_no);
       return false;
     }
 
   if (!loop->incoming_dest)
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d has more than one entry\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d has more than one entry\n",
+                loop->loop_no);
       return false;
     }
 
   if (loop->incoming_dest != loop->head)
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d is not entered from head\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d is not entered from head\n",
+                loop->loop_no);
       return false;
     }
 
   if (loop->has_call || loop->has_asm)
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d has invalid insn\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d has invalid insn\n",
+                loop->loop_no);
       return false;
     }
 
-  /* Scan all the blocks to make sure they don't use iter_reg.  */
+  /* Scan all the blocks to make sure they don't use iter_reg. */
   if (loop->iter_reg_used || loop->iter_reg_used_outside)
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d uses iterator\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d uses iterator\n",
+                loop->loop_no);
       return false;
     }
 
@@ -7863,8 +7793,8 @@ hwloop_optimize (hwloop_info loop)
   if (!insn)
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
+                loop->loop_no);
       return false;
     }
 
@@ -7882,12 +7812,21 @@ hwloop_optimize (hwloop_info loop)
       return false;
     }
 
-  /* Check if we use a register or not.  */
+  /* Check if we use a register or not.         */
   if (!REG_P (loop->iter_reg))
     {
       if (dump_file)
-        fprintf (dump_file, ";; loop %d iterator is MEM\n",
-                 loop->loop_no);
+       fprintf (dump_file, ";; loop %d iterator is MEM\n",
+                loop->loop_no);
+      return false;
+    }
+
+  /* Check if we use a register or not.         */
+  if (!REG_P (loop->iter_reg))
+    {
+      if (dump_file)
+       fprintf (dump_file, ";; loop %d iterator is MEM\n",
+                loop->loop_no);
       return false;
     }
 
@@ -7905,7 +7844,11 @@ hwloop_optimize (hwloop_info loop)
          || (loop->incoming_src
              && REGNO_REG_SET_P (df_get_live_out (loop->incoming_src),
                                  LP_COUNT)))
-       return false;
+       {
+         if (dump_file)
+           fprintf (dump_file, ";; loop %d, lp_count is alive", loop->loop_no);
+         return false;
+       }
       else
        need_fix = true;
     }
@@ -8020,7 +7963,7 @@ hwloop_optimize (hwloop_info loop)
     {
       /* The loop uses a R-register, but the lp_count is free, thus
         use lp_count.  */
-      emit_insn (gen_movsi (lp_reg, iter_reg));
+      emit_insn (gen_rtx_SET (lp_reg, iter_reg));
       SET_HARD_REG_BIT (loop->regs_set_in_loop, LP_COUNT);
       iter_reg = lp_reg;
       if (dump_file)
@@ -8030,8 +7973,7 @@ hwloop_optimize (hwloop_info loop)
        }
     }
 
-  insn = emit_insn (gen_arc_lp (iter_reg,
-                               loop->start_label,
+  insn = emit_insn (gen_arc_lp (loop->start_label,
                                loop->end_label));
 
   seq = get_insns ();
@@ -8049,12 +7991,12 @@ hwloop_optimize (hwloop_info loop)
       seq = emit_label_before (gen_label_rtx (), seq);
       new_bb = create_basic_block (seq, insn, entry_bb);
       FOR_EACH_EDGE (e, ei, loop->incoming)
-        {
-          if (!(e->flags & EDGE_FALLTHRU))
-            redirect_edge_and_branch_force (e, new_bb);
-          else
-            redirect_edge_succ (e, new_bb);
-        }
+       {
+         if (!(e->flags & EDGE_FALLTHRU))
+           redirect_edge_and_branch_force (e, new_bb);
+         else
+           redirect_edge_succ (e, new_bb);
+       }
 
       make_edge (new_bb, loop->head, 0);
     }
@@ -8062,17 +8004,19 @@ hwloop_optimize (hwloop_info loop)
     {
 #if 0
       while (DEBUG_INSN_P (entry_after)
-             || (NOTE_P (entry_after)
-                && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK))
+            || (NOTE_P (entry_after)
+                && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK
+                /* Make sure we don't split a call and its corresponding
+                   CALL_ARG_LOCATION note.  */
+                && NOTE_KIND (entry_after) != NOTE_INSN_CALL_ARG_LOCATION))
         entry_after = NEXT_INSN (entry_after);
 #endif
-      entry_after = next_nonnote_nondebug_insn_bb (entry_after);
+      entry_after = next_nonnote_insn_bb (entry_after);
 
       gcc_assert (entry_after);
       emit_insn_before (seq, entry_after);
     }
 
-  delete_insn (loop->loop_end);
   /* Insert the loop end label before the last instruction of the
      loop.  */
   emit_label_after (end_label, loop->last_insn);
@@ -8724,26 +8668,6 @@ int
 arc_register_move_cost (machine_mode,
                        enum reg_class from_class, enum reg_class to_class)
 {
-  /* The ARC600 has no bypass for extension registers, hence a nop might be
-     needed to be inserted after a write so that reads are safe.  */
-  if (TARGET_ARC600)
-    {
-      if (to_class == MPY_WRITABLE_CORE_REGS)
-       return 3;
-     /* Instructions modifying LP_COUNT need 4 additional cycles before
-       the register will actually contain the value.  */
-      else if (to_class == LPCOUNT_REG)
-       return 6;
-      else if (to_class == WRITABLE_CORE_REGS)
-       return 6;
-    }
-
-  /* Using lp_count as scratch reg is a VERY bad idea.  */
-  if (from_class == LPCOUNT_REG)
-    return 1000;
-  if (to_class == LPCOUNT_REG)
-    return 6;
-
   /* Force an attempt to 'mov Dy,Dx' to spill.  */
   if ((TARGET_ARC700 || TARGET_EM) && TARGET_DPFP
       && from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
@@ -9962,17 +9886,20 @@ split_subsi (rtx *operands)
 static bool
 arc_process_double_reg_moves (rtx *operands)
 {
-  rtx dest = operands[0];
-  rtx src  = operands[1];
-
   enum usesDxState { none, srcDx, destDx, maxDx };
   enum usesDxState state = none;
+  rtx dest = operands[0];
+  rtx src  = operands[1];
 
   if (refers_to_regno_p (40, 44, src, 0))
-    state = srcDx;
+    {
+      state = srcDx;
+      gcc_assert (REG_P (dest));
+    }
   if (refers_to_regno_p (40, 44, dest, 0))
     {
       /* Via arc_register_move_cost, we should never see D,D moves.  */
+      gcc_assert (REG_P (src));
       gcc_assert (state == none);
       state = destDx;
     }
@@ -10324,11 +10251,11 @@ arc_return_address_register (unsigned int fn_type)
   if (ARC_INTERRUPT_P (fn_type))
     {
       if ((fn_type & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_FIRQ)) != 0)
-        regno = ILINK1_REGNUM;
+       regno = ILINK1_REG;
       else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
-        regno = ILINK2_REGNUM;
+       regno = ILINK2_REG;
       else
-        gcc_unreachable ();
+       gcc_unreachable ();
     }
   else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
     regno = RETURN_ADDR_REGNUM;
@@ -10379,14 +10306,12 @@ arc_eh_uses (int regno)
   return false;
 }
 
-#ifndef TARGET_NO_LRA
-#define TARGET_NO_LRA !TARGET_LRA
-#endif
+/* Return true if we use LRA instead of reload pass.  */
 
-static bool
+bool
 arc_lra_p (void)
 {
-  return !TARGET_NO_LRA;
+  return arc_lra_flag;
 }
 
 /* ??? Should we define TARGET_REGISTER_PRIORITY?  We might perfer to use
@@ -11325,7 +11250,7 @@ operands_ok_ldd_std (rtx rt, rtx rt2, HOST_WIDE_INT 
offset)
   t = REGNO (rt);
   t2 = REGNO (rt2);
 
-  if ((t2 == PROGRAM_COUNTER_REGNO)
+  if ((t2 == PCL_REG)
       || (t % 2 != 0)  /* First destination register is not even.  */
       || (t2 != t + 1))
       return false;
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index d8ea7769db8..afd6d7681cf 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -312,8 +312,6 @@ if (GET_MODE_CLASS (MODE) == MODE_INT               \
 #undef WCHAR_TYPE_SIZE
 #define WCHAR_TYPE_SIZE 32
 
-#define PROGRAM_COUNTER_REGNO 63
-
 /* Standard register usage.  */
 
 /* Number of actual hardware registers.
@@ -373,7 +371,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT               \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   0, 0, 0, 0, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1, 0, 1, 1, 1,       \
+  1, 1, 1, 1, 1, 1, 1, 1,       \
                                \
   0, 0, 0, 0, 0, 0, 0, 0,       \
   0, 0, 0, 0, 0, 0, 0, 0,       \
@@ -470,25 +468,15 @@ enum reg_class
 {
    NO_REGS,
    R0_REGS,                    /* 'x' */
-   GP_REG,                     /* 'Rgp' */
-   FP_REG,                     /* 'f' */
-   SP_REGS,                    /* 'b' */
-   LPCOUNT_REG,                /* 'l' */
-   LINK_REGS,                  /* 'k' */
-   DOUBLE_REGS,                        /* D0, D1 */
-   SIMD_VR_REGS,               /* VR00-VR63 */
-   SIMD_DMA_CONFIG_REGS,       /* DI0-DI7,DO0-DO7 */
+   R0R1_CD_REGS,               /* 'Rsd' */
+   R0R3_CD_REGS,               /* 'Rcd' */
    ARCOMPACT16_REGS,           /* 'q' */
-   AC16_BASE_REGS,             /* 'e' */
    SIBCALL_REGS,               /* "Rsc" */
-   GENERAL_REGS,               /* 'r' */
-   MPY_WRITABLE_CORE_REGS,     /* 'W' */
-   WRITABLE_CORE_REGS,         /* 'w' */
-   CHEAP_CORE_REGS,            /* 'c' */
-   ALL_CORE_REGS,              /* 'Rac' */
-   R0R3_CD_REGS,               /* 'Rcd' */
-   R0R1_CD_REGS,               /* 'Rsd' */
    AC16_H_REGS,                        /* 'h' */
+   DOUBLE_REGS,                        /* 'D' */
+   GENERAL_REGS,               /* 'r' */
+   SIMD_VR_REGS,               /* 'v' */
+   SIMD_DMA_CONFIG_REGS,       /* 'd' */
    ALL_REGS,
    LIM_REG_CLASSES
 };
@@ -497,29 +485,19 @@ enum reg_class
 
 /* Give names of register classes as strings for dump file.   */
 #define REG_CLASS_NAMES          \
-{                         \
-  "NO_REGS",                     \
-  "R0_REGS",                     \
-  "GP_REG",                      \
-  "FP_REG",                      \
-  "SP_REGS",             \
-  "LPCOUNT_REG",         \
-  "LINK_REGS",                   \
-  "DOUBLE_REGS",          \
-  "SIMD_VR_REGS",         \
-  "SIMD_DMA_CONFIG_REGS", \
-  "ARCOMPACT16_REGS",            \
-  "AC16_BASE_REGS",       \
+{                        \
+  "NO_REGS",             \
+  "R0_REGS",             \
+  "R0R1_CD_REGS",        \
+  "R0R3_CD_REGS",        \
+  "ARCOMPACT16_REGS",    \
   "SIBCALL_REGS",        \
-  "GENERAL_REGS",                \
-  "MPY_WRITABLE_CORE_REGS",   \
-  "WRITABLE_CORE_REGS",   \
-  "CHEAP_CORE_REGS",     \
-  "ALL_CORE_REGS",       \
-  "R0R3_CD_REGS", \
-  "R0R1_CD_REGS", \
-  "AC16_H_REGS",           \
-  "ALL_REGS"             \
+  "AC16_H_REGS",         \
+  "DOUBLE_REGS",         \
+  "GENERAL_REGS",        \
+  "SIMD_VR_REGS",        \
+  "SIMD_DMA_CONFIG_REGS", \
+  "ALL_REGS"             \
 }
 
 /* Define which registers fit in which classes.
@@ -527,33 +505,19 @@ enum reg_class
    of length N_REG_CLASSES.  */
 
 #define REG_CLASS_CONTENTS \
-{                                                                              
                        \
-  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},             /* 
No Registers */                 \
-  {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'x', 
r0 register , r0 */       \
-  {0x04000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rgp', 
Global Pointer, r26 */  \
-  {0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'f', 
Frame Pointer, r27 */     \
-  {0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'b', 
Stack Pointer, r28 */     \
-  {0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000000},      /* 'l', 
LPCOUNT Register, r60 */  \
-  {0xe0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'k', 
LINK Registers, r29-r31 */        \
-  {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000},      /* 'D', 
D1, D2 Registers */       \
-  {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000},      /* 'V', 
VR00-VR63 Registers */    \
-  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff},      /* 'V', 
DI0-7,DO0-7 Registers */  \
-  {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},             /* 
'q', r0-r3, r12-r15 */          \
-  {0x1000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},             /* 
'e', r0-r3, r12-r15, sp */      \
-  {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},    /* "Rsc", 
r0-r12 */ \
-  {0x9fffffff, 0x80000000, 0x00000000, 0x00000000, 0x00000000},      /* 'r', 
r0-r28, blink, ap and pcl */      \
-  {0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'W',  
r0-r31 */ \
-  /* Include ap / pcl in WRITABLE_CORE_REGS for sake of symmetry.  As these \
-     registers are fixed, it does not affect the literal meaning of the \
-     constraints, but it makes it a superset of GENERAL_REGS, thus \
-     enabling some operations that would otherwise not be possible.  */ \
-  {0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'w', 
r0-r31, r60 */ \
-  {0xffffffff, 0x9fffffff, 0x00000000, 0x00000000, 0x00000000},      /* 'c', 
r0-r60, ap, pcl */ \
-  {0xffffffff, 0x9fffffff, 0x00000000, 0x00000000, 0x00000000},      /* 'Rac', 
r0-r60, ap, pcl */ \
-  {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rcd', 
r0-r3 */ \
-  {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rsd', 
r0-r1 */ \
-  {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'h',  
r0-28, r30 */ \
-  {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff}       /* All 
Registers */               \
+{                                                                      \
+  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},        /* 
NO_REGS  */ \
+  {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'x' */ \
+  {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd' */ \
+  {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd' */ \
+  {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q' */ \
+  {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc' */ \
+  {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h' */ \
+  {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D' */ \
+  {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'r' */ \
+  {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'v' */ \
+  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'd' */ \
+  {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff}  /* ALL_REGS */\
 }
 
 /* Local macros to mark the first and last regs of different classes.  */
@@ -590,7 +554,7 @@ extern enum reg_class arc_regno_reg_class[];
 /* The class value for valid base registers. A base register is one used in
    an address which is the register value plus a displacement.  */
 
-#define BASE_REG_CLASS (TARGET_MIXED_CODE ? AC16_BASE_REGS : GENERAL_REGS)
+#define BASE_REG_CLASS GENERAL_REGS
 
 /* These assume that REGNO is a hard or pseudo reg number.
    They give nonzero only if REGNO is a hard reg of the suitable class
@@ -1658,4 +1622,8 @@ enum
 /* The default option for BI/BIH instructions.  */
 #define DEFAULT_BRANCH_INDEX 0
 
+#ifndef TARGET_LRA
+#define TARGET_LRA arc_lra_p()
+#endif
+
 #endif /* GCC_ARC_H */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 3c0931947d9..a28c67ac184 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -170,18 +170,37 @@
    (R1_REG 1)
    (R2_REG 2)
    (R3_REG 3)
+   (R4_REG 4)
+
+   (R9_REG 9)
    (R10_REG 10)
+
    (R12_REG 12)
+
+   (R15_REG 15)
+   (R16_REG 16)
+
+   (R25_REG 25)
    (SP_REG 28)
-   (ILINK1_REGNUM 29)
-   (ILINK2_REGNUM 30)
+   (ILINK1_REG 29)
+   (ILINK2_REG 30)
+   (R30_REG 30)
    (RETURN_ADDR_REGNUM 31)
+   (R32_REG 32)
+   (R40_REG 40)
+   (R41_REG 41)
+   (R42_REG 42)
+   (R43_REG 43)
+   (R44_REG 44)
+   (R57_REG 57)
    (MUL64_OUT_REG 58)
    (MUL32x16_REG 56)
    (ARCV2_ACC 58)
+   (R59_REG 59)
 
    (LP_COUNT 60)
    (CC_REG 61)
+   (PCL_REG 63)
    (LP_START 144)
    (LP_END 145)
   ]
@@ -651,8 +670,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
 ; The iscompact attribute allows the epilogue expander to know for which
 ; insns it should lengthen the return insn.
 (define_insn "*movqi_insn"
-  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   
h,w*l,w*l,???w,h,w*l,Rcq,  S,!*x,  r,r, Ucm,m,???m,  m,Usc")
-       (match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    P,hCm1, 
cL,  I,?Rac,i, ?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
+  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h, 
w, w,???w,h, w,Rcq,  S,!*x,  r,r, Ucm,m,???m,  m,Usc")
+       (match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    
P,hCm1,cL, I,?Rac,i,?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
   "register_operand (operands[0], QImode)
    || register_operand (operands[1], QImode)"
   "@
@@ -688,8 +707,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
   "if (prepare_move_operands (operands, HImode)) DONE;")
 
 (define_insn "*movhi_insn"
-  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   
h,w*l,w*l,???w,Rcq#q,h,w*l,Rcq,  S,  r,r, Ucm,m,???m,  m,VUsc")
-       (match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,    P,hCm1, 
cL,  I,?Rac,    i,i, ?i,  T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
+  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h, 
w, w,???w,Rcq#q,h, w,Rcq,  S,  r,r, Ucm,m,???m,  m,VUsc")
+       (match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,    
P,hCm1,cL, I,?Rac,    i,i,?i,  T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
   "register_operand (operands[0], HImode)
    || register_operand (operands[1], HImode)
    || (CONSTANT_P (operands[1])
@@ -739,9 +758,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
 ; the iscompact attribute allows the epilogue expander to know for which
 ; insns it should lengthen the return insn.
 ; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
-(define_insn "*movsi_insn"                      ;   0     1     2     3    4  
5    6   7   8   9   10    11  12  13    14  15   16  17  18     19     20  21  
22    23    24 25 26    27 28  29  30   31
-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   
h,w*l,w*l,  w,  w,  w,  w,  ???w, ?w,  w,Rcq#q,  h, w*l,Rcq,  S,   
Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,  m,VUsc")
-       (match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    P,hCm1, 
cL,  I,Crr,Clo,Chi,Cbi,?Rac*l,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck,   
Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac,Cm3, C32"))]
+(define_insn "*movsi_insn"                      ;   0     1     2     3    4  
5  6   7   8   9   10  11  12  13    14  15   16  17  18     19     20  21  22  
  23    24 25 26    27 28  29  30   31
+  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   
h,wl, w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,  h,  wl,Rcq,  S,   Us<,RcqRck,!*x,  
r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,  m,VUsc")
+       (match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    
P,hCm1,cL, I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck,   
Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac,Cm3, C32"))]
   "register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode)
    || (CONSTANT_P (operands[1])
@@ -5001,12 +5020,12 @@ core_3, archs4x, archs4xd, archs4xd_slow"
 })
 
 (define_insn "arc_lp"
-  [(unspec:SI [(match_operand:SI 0 "register_operand" "l")]
+  [(unspec:SI [(reg:SI LP_COUNT)]
              UNSPEC_ARC_LP)
-   (use (label_ref (match_operand 1 "" "")))
-   (use (label_ref (match_operand 2 "" "")))]
+   (use (label_ref (match_operand 0 "" "")))
+   (use (label_ref (match_operand 1 "" "")))]
   ""
-  "lp\\t@%l2\\t; %0:@%l1->@%l2"
+  "lp\\t@%l1\\t; lp_count:@%l0->@%l1"
   [(set_attr "type" "loop_setup")
    (set_attr "length" "4")])
 
@@ -5014,16 +5033,16 @@ core_3, archs4x, archs4xd, archs4xd_slow"
 ;; register, instead of going to memory.
 (define_insn "loop_end"
   [(set (pc)
-       (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,0")
+       (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,m")
                          (const_int 1))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))
-   (set (match_operand:SI 0 "nonimmediate_operand" "=l!r,m")
+   (set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
        (plus (match_dup 2) (const_int -1)))
    (unspec [(const_int 0)] UNSPEC_ARC_LP)
    (clobber (match_scratch:SI 3 "=X,&r"))]
   ""
-  "\\t;%0 %1 %2"
+  "; ZOL_END, begins @%l1"
   [(set_attr "length" "0")
    (set_attr "predicable" "no")
    (set_attr "type" "loop_end")])
@@ -5068,7 +5087,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"
 (define_insn_and_split "dbnz"
   [(set (pc)
        (if_then_else
-        (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+r!l,m")
+        (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+rl,m")
                      (const_int -1))
             (const_int 0))
         (label_ref (match_operand 1 "" ""))
@@ -6282,8 +6301,8 @@ core_3, archs4x, archs4xd, archs4xd_slow"
 
 (define_insn "stack_tie"
   [(set (mem:BLK (scratch))
-       (unspec:BLK [(match_operand:SI 0 "register_operand" "rb")
-                    (match_operand:SI 1 "register_operand" "rb")]
+       (unspec:BLK [(match_operand:SI 0 "register_operand" "r")
+                    (match_operand:SI 1 "register_operand" "r")]
                    UNSPEC_ARC_STKTIE))]
   ""
   ""
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index e8f97e4d1af..af9e2d16ca0 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -401,12 +401,9 @@ Target
 Pass -marclinux_prof option through to linker.
 
 ;; lra is still unproven for ARC, so allow to fall back to reload with 
-mno-lra.
-;Target InverseMask(NO_LRA)
-; lra still won't allow to configure libgcc; see PR rtl-optimization/55464.
-; so don't enable by default.
 mlra
-Target Mask(LRA)
-Enable lra.
+Target Report Var(arc_lra_flag) Init(1) Save
+Use LRA instead of reload.
 
 mlra-priority-none
 Target RejectNegative Var(arc_lra_priority_tag, ARC_LRA_PRIORITY_NONE)
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index cbb31249240..064718972d1 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -24,48 +24,33 @@
 ; result registers of ARC600.
 ; First, define a class for core registers that can be read cheaply.  This
 ; is most or all core registers for ARC600, but only r0-r31 for ARC700
-(define_register_constraint "c" "CHEAP_CORE_REGS"
-  "core register @code{r0}-@code{r31}, @code{ap},@code{pcl}")
+(define_register_constraint "c" "GENERAL_REGS"
+  "Legacy, core register @code{r0}-@code{r31}, @code{ap},@code{pcl}")
 
 ; All core regs - e.g. for when we must have a way to reload a register.
-(define_register_constraint "Rac" "ALL_CORE_REGS"
-  "core register @code{r0}-@code{r60}, @code{ap},@code{pcl}")
+(define_register_constraint "Rac" "GENERAL_REGS"
+  "Legacy, core register @code{r0}-@code{r60}, @code{ap},@code{pcl}")
 
 ; Some core registers (.e.g lp_count) aren't general registers because they
 ; can't be used as the destination of a multi-cycle operation like
 ; load and/or multiply, yet they are still writable in the sense that
 ; register-register moves and single-cycle arithmetic (e.g "add", "and",
 ; but not "mpy") can write to them.
-(define_register_constraint "w" "WRITABLE_CORE_REGS"
-  "writable core register: @code{r0}-@code{r31}, @code{r60}, nonfixed core 
register")
+(define_register_constraint "w" "GENERAL_REGS"
+  "Legacy, writable core register: @code{r0}-@code{r31}, @code{r60}, nonfixed 
core register")
 
-(define_register_constraint "W" "MPY_WRITABLE_CORE_REGS"
-  "writable core register except @code{LP_COUNT} (@code{r60}): 
@code{r0}-@code{r31}, nonfixed core register")
+(define_register_constraint "W" "GENERAL_REGS"
+  "Legacy, writable core register except @code{LP_COUNT} (@code{r60}): 
@code{r0}-@code{r31}, nonfixed core register")
 
-(define_register_constraint "l" "LPCOUNT_REG"
+(define_constraint "l"
   "@internal
-   Loop count register @code{r60}")
+   Loop count register @code{r60}"
+  (and (match_code "reg")
+       (match_test "REGNO (op) == LP_COUNT")))
 
 (define_register_constraint "x" "R0_REGS"
   "@code{R0} register.")
 
-(define_register_constraint "Rgp" "GP_REG"
-  "@internal
-   Global Pointer register @code{r26}")
-
-(define_register_constraint "f" "FP_REG"
-  "@internal
-   Frame Pointer register @code{r27}")
-
-(define_register_constraint "b" "SP_REGS"
-  "@internal
-   Stack Pointer register @code{r28}")
-
-(define_register_constraint "k" "LINK_REGS"
-  "@internal
-   Link Registers @code{ilink1}:@code{r29}, @code{ilink2}:@code{r30},
-   @code{blink}:@code{r31},")
-
 (define_register_constraint "q" "TARGET_Q_CLASS ? ARCOMPACT16_REGS : NO_REGS"
   "Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
    @code{r12}-@code{r15}")
@@ -78,10 +63,6 @@
   "Registers usable in NPS400 bitfield instructions: @code{r0}-@code{r3},
    @code{r12}-@code{r15}")
 
-(define_register_constraint "e" "AC16_BASE_REGS"
-  "Registers usable as base-regs of memory addresses in ARCompact 16-bit memory
-   instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}, @code{sp}")
-
 (define_register_constraint "D" "DOUBLE_REGS"
   "ARC FPX (dpfp) 64-bit registers. @code{D0}, @code{D1}")
 
@@ -472,7 +453,7 @@
        (match_test
        "TARGET_Rcw
         && REGNO (op) < FIRST_PSEUDO_REGISTER
-        && TEST_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS],
+        && TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
                               REGNO (op))")))
 
 (define_constraint "Rcr"
diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
index efa3650e1fa..c4be56f766e 100644
--- a/gcc/config/arc/predicates.md
+++ b/gcc/config/arc/predicates.md
@@ -20,33 +20,12 @@
 (define_predicate "dest_reg_operand"
   (match_code "reg,subreg")
 {
-  rtx op0 = op;
-
-  if (GET_CODE (op0) == SUBREG)
-    op0 = SUBREG_REG (op0);
-  if (REG_P (op0) && REGNO (op0) < FIRST_PSEUDO_REGISTER
-      && TEST_HARD_REG_BIT (reg_class_contents[ALL_CORE_REGS],
-                           REGNO (op0))
-      && !TEST_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS],
-                           REGNO (op0)))
-    return 0;
   return register_operand (op, mode);
 })
 
 (define_predicate "mpy_dest_reg_operand"
   (match_code "reg,subreg")
 {
-  rtx op0 = op;
-
-  if (GET_CODE (op0) == SUBREG)
-    op0 = SUBREG_REG (op0);
-  if (REG_P (op0) && REGNO (op0) < FIRST_PSEUDO_REGISTER
-      && TEST_HARD_REG_BIT (reg_class_contents[ALL_CORE_REGS],
-                           REGNO (op0))
-      /* Make sure the destination register is not LP_COUNT.  */
-      && !TEST_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS],
-                           REGNO (op0)))
-    return 0;
   return register_operand (op, mode);
 })
 
@@ -358,13 +337,14 @@
     case REG :
      /* Program Counter register cannot be the target of a move.  It is
         a readonly register.  */
-      if (REGNO (op) == PROGRAM_COUNTER_REGNO)
+      if (REGNO (op) == PCL_REG)
        return 0;
       else if (TARGET_MULMAC_32BY16_SET
-              && (REGNO (op) == 56 || REGNO(op) == 57))
+              && (REGNO (op) == MUL32x16_REG || REGNO (op) == R57_REG))
        return 0;
       else if (TARGET_MUL64_SET
-              && (REGNO (op) == 57 || REGNO(op) == 58 || REGNO(op) == 59 ))
+              && (REGNO (op) == R57_REG || REGNO (op) == MUL64_OUT_REG
+                  || REGNO (op) == R59_REG))
        return 0;
       else if (REGNO (op) == LP_COUNT)
         return 1;
-- 
2.19.1

Reply via email to