[ARC] Cleanup, fix and set LRA default.

Message ID 20181112112933.10640-1-claziss@gmail.com
State New
Headers show
Series
  • [ARC] Cleanup, fix and set LRA default.
Related show

Commit Message

Claudiu Zissulescu Nov. 12, 2018, 11:29 a.m.
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(-)

-- 
2.19.1

Comments

Eric Botcazou Nov. 12, 2018, 11:36 a.m. | #1
> 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
Andrew Burgess Nov. 13, 2018, 2:52 p.m. | #2
* 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

>
Claudiu Zissulescu Nov. 14, 2018, 9:50 a.m. | #3
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

Patch

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;