public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] [ARC] Cleanup, fix and set LRA default.
@ 2018-11-12 11:29 Claudiu Zissulescu
  2018-11-12 11:36 ` Eric Botcazou
  2018-11-13 14:53 ` Andrew Burgess
  0 siblings, 2 replies; 4+ messages in thread
From: Claudiu Zissulescu @ 2018-11-12 11:29 UTC (permalink / raw)
  To: gcc-patches; +Cc: fbedard, andrew.burgess, claziss

From: claziss <claziss@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  <claziss@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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] [ARC] Cleanup, fix and set LRA default.
  2018-11-12 11:29 [PATCH] [ARC] Cleanup, fix and set LRA default Claudiu Zissulescu
@ 2018-11-12 11:36 ` Eric Botcazou
  2018-11-13 14:53 ` Andrew Burgess
  1 sibling, 0 replies; 4+ messages in thread
From: Eric Botcazou @ 2018-11-12 11:36 UTC (permalink / raw)
  To: Claudiu Zissulescu; +Cc: gcc-patches, fbedard, andrew.burgess, claziss

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

You'll need to update htdocs/backends.html of wwwdocs once this is done:
  https://gcc.gnu.org/backends.html

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] [ARC] Cleanup, fix and set LRA default.
  2018-11-12 11:29 [PATCH] [ARC] Cleanup, fix and set LRA default Claudiu Zissulescu
  2018-11-12 11:36 ` Eric Botcazou
@ 2018-11-13 14:53 ` Andrew Burgess
  2018-11-14  9:50   ` claziss
  1 sibling, 1 reply; 4+ messages in thread
From: Andrew Burgess @ 2018-11-13 14:53 UTC (permalink / raw)
  To: Claudiu Zissulescu; +Cc: gcc-patches, fbedard, claziss

* Claudiu Zissulescu <claziss@gmail.com> [2018-11-12 13:29:33 +0200]:

> From: claziss <claziss@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  <claziss@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.

The entries below this are for arc.md, but you're missing the filename
in the ChangeLog format.

> 	(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.

I'm basically happy with this.  There's a few formatting issues as we
saw in previous patches - tabs instead of whitespace in comments and
single whitespace instead of two at the end of a sentence.  But with
that fixed (and the doc fix Eric suggested) I'm happy.

Thanks,
Andrew


> ---
>  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
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] [ARC] Cleanup, fix and set LRA default.
  2018-11-13 14:53 ` Andrew Burgess
@ 2018-11-14  9:50   ` claziss
  0 siblings, 0 replies; 4+ messages in thread
From: claziss @ 2018-11-14  9:50 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gcc-patches, fbedard, claziss, Eric Botcazou

Thank you all for your review. I have pushed the patch with the
suggested mods. I also made a new patch (and pushed) for wwwdocs.

Claudiu

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-11-14  9:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-12 11:29 [PATCH] [ARC] Cleanup, fix and set LRA default Claudiu Zissulescu
2018-11-12 11:36 ` Eric Botcazou
2018-11-13 14:53 ` Andrew Burgess
2018-11-14  9:50   ` claziss

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).