Patchwork FW: [PATCH] [MIPS] microMIPS gcc support

login
register
mail settings
Submitter Richard Sandiford
Date Feb. 21, 2013, 9:20 p.m.
Message ID <87r4k9uzxn.fsf@talisman.default>
Download mbox | patch
Permalink /patch/222414/
State New
Headers show

Comments

Richard Sandiford - Feb. 21, 2013, 9:20 p.m.
"Moore, Catherine" <Catherine_Moore@mentor.com> writes:
>> Looks good otherwise, but please post an updated patch.  It's probably
>> stating the obvious, but the patch is too invasive for this late stage
>> of 4.8, so
>> it'll need to wait until 4.9.
>> 
>
> The updated patch is attached.  How's it looking this time?

Almost there. :-)

As I mentioned in an earlier reply, please always check for warnings.
If you're not bootstrapping on a MIPS host then instead configure the
cross compiler with --enable-werror-always, using a recent GCC as the
host compiler.  If the patch goes in with warnings, it'll break the
build for other people.

The warnings I could see are:

> +  for (n = 0; n < XVECLEN (pattern, 0); n++)
> +    {
> +      rtx set, reg, mem, this_base;
> +      HOST_WIDE_INT this_offset;
> +      unsigned int this_regno;

this_regno is an unused variable (thanks for making it unused though).

>  static bool
>  mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
>  {
> +
> +  unsigned int compression_mode = mips_get_compress_mode (decl);

compression_mode is unused.

> +static bool
> +umips_build_save_restore (mips_save_restore_fn fn,
> +			  unsigned *mask, HOST_WIDE_INT *offset)
> +{
> +  int i, nregs;
> +  unsigned int j;
> +  rtx pattern, set, reg, mem;
> +  HOST_WIDE_INT this_offset;
> +  rtx this_base;
> +
> +  /* Try matching $16 to $31 (s0 to ra).  */
> +  for (i = 0; i < ARRAY_SIZE (umips_swm_mask); i++)
> +    if ((*mask & 0xffff0000) == umips_swm_mask[i])
> +      break;
> +
> +  if (i == ARRAY_SIZE (umips_swm_mask))
> +    return false;

"i" needs to be unsigned to avoid a "comparison between signed and unsigned"
warning.

> +/* Return the assembly instruction for microMIPS lwm or swm.
> +   SAVE_P and PATTERN are as for umips_save_restore_pattern_p.  */
> +
> +const char *
> +umips_output_save_restore (bool save_p, rtx pattern)
> +{
> +  static char buffer[300];
> +  char *s;
> +  int n;
> +  HOST_WIDE_INT offset;
> +  rtx base, mem, set, reg, last_set, last_reg;
> +
> +  /* Parse the pattern.  */
> +  gcc_assert (umips_save_restore_pattern_p (save_p, pattern));
> +
> +  s = strcpy (buffer, save_p ? "swm\t" : "lwm\t");
> +  s += strlen (s);
> +  n = XVECLEN (pattern, 0);
> +
> +  set = XVECEXP (pattern, 0, 0);
> +  reg = save_p ? SET_SRC (set) : SET_DEST (set);

"reg" is unused and should be deleted.

In case it sounds otherwise, I didn't build the patch to try to catch you out.
I built it so that I could try to answer:

> > Is this a test of the swap_p case?  Thanks if so, but could you add a comment
> > saying where the SWP gets generated, and why the test needs to be skipped
> > at -O1 and -Os?
> > 
> Yes, this was the swap_p case.  But it turns out that umips-lpw-swp-1.c
> was also testing the swap_p case.  I've now dropped this test in favor
> of a different test that exercises the swap_p = false case.
> You had mentioned testing for explicit registers.  This is turning out
> to be problematic.  The Linux and ELF tool chains don't always use the
> same register set.  In addition, -O3 seems to expose more opportunities
> for generating these instructions so the code generated isn't consistent
> among optimization options.  I've changed it back to just testing for
> swp, but I'm open to other suggestions.

I've attached some tests below, both for LWP (which didn't seem to be
covered) and SWP.  They use things like multiplication to force a
particular load or store order in scheduled code, so that both swap_p
and !swap_p are covered (verified using both printfs and -fno-peephole2).
umips-lwp-7.c tests for:

  /* Avoid invalid load pair instructions.  */
  if (load_p && REGNO (first_reg) == REGNO (base1))
    return false;

  /* We must avoid this case for anti-dependence.
     Ex:  lw $3, 4($3)
          lw $2, 0($3)
     first_reg is $2, but the base is $3.  */
  if (load_p
      && swap_p
      && REGNO (first_reg) + 1 == REGNO (base1))
    return false;

while umips-lwp-8.c is an example of something that would be pessimised
by not having the swap_p test above.

I also noticed a couple of other things while testing:

- ISA_HAS_LOAD_DELAY should be false for microMIPS, otherwise we'll try
  to insert nops after LWP on targets that default to -mips1, and ICE
  when we see that we have a double SET.

- In the testsuite, a -mmicromips test option should override an ambient
  -mips16, and vice versa.

- umips-movep-2.c fails on n64 because there the moves are DImode rather
  than SImode.  Since the initial patch is just for 32-bit, I forced
  -mgp32 for now.  Also, the function needs a MICROMIPS attribute.

There were various other minor formatting and comment nits that were probably
easier for me to fix than describe.  There was also some trailing whitespace.

The patch is OK for 4.9 with this one applied on top of it, provided that
it works with your setup of course.  Thanks for your patience!

Richard
Moore, Catherine - Feb. 24, 2013, 11:52 p.m.
HI Richard, 
The base patch is now committed.  The final patch, including your final edits is attached.  I will be posting the optimization pieces later this week.
Thanks for working with me on this.
Catherine


> -----Original Message-----
> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: Thursday, February 21, 2013 4:20 PM
> To: Moore, Catherine
> Cc: gcc-patches@gcc.gnu.org; Rozycki, Maciej
> Subject: Re: FW: [PATCH] [MIPS] microMIPS gcc support
> 
> "Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> >> Looks good otherwise, but please post an updated patch.  It's
> >> probably stating the obvious, but the patch is too invasive for this
> >> late stage of 4.8, so it'll need to wait until 4.9.
> >>
> >
> > The updated patch is attached.  How's it looking this time?
> 
> Almost there. :-)
> 
> As I mentioned in an earlier reply, please always check for warnings.
> If you're not bootstrapping on a MIPS host then instead configure the cross
> compiler with --enable-werror-always, using a recent GCC as the host
> compiler.  If the patch goes in with warnings, it'll break the build for other
> people.
> 
> The warnings I could see are:
> 
> > +  for (n = 0; n < XVECLEN (pattern, 0); n++)
> > +    {
> > +      rtx set, reg, mem, this_base;
> > +      HOST_WIDE_INT this_offset;
> > +      unsigned int this_regno;
> 
> this_regno is an unused variable (thanks for making it unused though).
> 
> >  static bool
> >  mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
> > {
> > +
> > +  unsigned int compression_mode = mips_get_compress_mode (decl);
> 
> compression_mode is unused.
> 
> > +static bool
> > +umips_build_save_restore (mips_save_restore_fn fn,
> > +			  unsigned *mask, HOST_WIDE_INT *offset) {
> > +  int i, nregs;
> > +  unsigned int j;
> > +  rtx pattern, set, reg, mem;
> > +  HOST_WIDE_INT this_offset;
> > +  rtx this_base;
> > +
> > +  /* Try matching $16 to $31 (s0 to ra).  */  for (i = 0; i <
> > + ARRAY_SIZE (umips_swm_mask); i++)
> > +    if ((*mask & 0xffff0000) == umips_swm_mask[i])
> > +      break;
> > +
> > +  if (i == ARRAY_SIZE (umips_swm_mask))
> > +    return false;
> 
> "i" needs to be unsigned to avoid a "comparison between signed and
> unsigned"
> warning.
> 
> > +/* Return the assembly instruction for microMIPS lwm or swm.
> > +   SAVE_P and PATTERN are as for umips_save_restore_pattern_p.  */
> > +
> > +const char *
> > +umips_output_save_restore (bool save_p, rtx pattern) {
> > +  static char buffer[300];
> > +  char *s;
> > +  int n;
> > +  HOST_WIDE_INT offset;
> > +  rtx base, mem, set, reg, last_set, last_reg;
> > +
> > +  /* Parse the pattern.  */
> > +  gcc_assert (umips_save_restore_pattern_p (save_p, pattern));
> > +
> > +  s = strcpy (buffer, save_p ? "swm\t" : "lwm\t");  s += strlen (s);
> > + n = XVECLEN (pattern, 0);
> > +
> > +  set = XVECEXP (pattern, 0, 0);
> > +  reg = save_p ? SET_SRC (set) : SET_DEST (set);
> 
> "reg" is unused and should be deleted.
> 
> In case it sounds otherwise, I didn't build the patch to try to catch you out.
> I built it so that I could try to answer:
> 
> > > Is this a test of the swap_p case?  Thanks if so, but could you add
> > > a comment saying where the SWP gets generated, and why the test
> > > needs to be skipped at -O1 and -Os?
> > >
> > Yes, this was the swap_p case.  But it turns out that
> > umips-lpw-swp-1.c was also testing the swap_p case.  I've now dropped
> > this test in favor of a different test that exercises the swap_p = false case.
> > You had mentioned testing for explicit registers.  This is turning out
> > to be problematic.  The Linux and ELF tool chains don't always use the
> > same register set.  In addition, -O3 seems to expose more
> > opportunities for generating these instructions so the code generated
> > isn't consistent among optimization options.  I've changed it back to
> > just testing for swp, but I'm open to other suggestions.
> 
> I've attached some tests below, both for LWP (which didn't seem to be
> covered) and SWP.  They use things like multiplication to force a particular
> load or store order in scheduled code, so that both swap_p and !swap_p are
> covered (verified using both printfs and -fno-peephole2).
> umips-lwp-7.c tests for:
> 
>   /* Avoid invalid load pair instructions.  */
>   if (load_p && REGNO (first_reg) == REGNO (base1))
>     return false;
> 
>   /* We must avoid this case for anti-dependence.
>      Ex:  lw $3, 4($3)
>           lw $2, 0($3)
>      first_reg is $2, but the base is $3.  */
>   if (load_p
>       && swap_p
>       && REGNO (first_reg) + 1 == REGNO (base1))
>     return false;
> 
> while umips-lwp-8.c is an example of something that would be pessimised by
> not having the swap_p test above.
> 
> I also noticed a couple of other things while testing:
> 
> - ISA_HAS_LOAD_DELAY should be false for microMIPS, otherwise we'll try
>   to insert nops after LWP on targets that default to -mips1, and ICE
>   when we see that we have a double SET.
> 
> - In the testsuite, a -mmicromips test option should override an ambient
>   -mips16, and vice versa.
> 
> - umips-movep-2.c fails on n64 because there the moves are DImode rather
>   than SImode.  Since the initial patch is just for 32-bit, I forced
>   -mgp32 for now.  Also, the function needs a MICROMIPS attribute.
> 
> There were various other minor formatting and comment nits that were
> probably easier for me to fix than describe.  There was also some trailing
> whitespace.
> 
> The patch is OK for 4.9 with this one applied on top of it, provided that it
> works with your setup of course.  Thanks for your patience!
> 
> Richard
> 
> 
> Index: gcc/config/mips/constraints.md
> ==========================================================
> =========
> --- gcc/config/mips/constraints.md	2013-02-21 19:57:26.000000000 +0000
> +++ gcc/config/mips/constraints.md	2013-02-21 20:24:30.909497318 +0000
> @@ -239,9 +239,10 @@ (define_memory_constraint "ZC"
>     @code{sc}.  When not compiling for microMIPS code, @code{ZC} is
>     equivalent to @code{R}."
>    (and (match_code "mem")
> -       (if_then_else (match_test "TARGET_MICROMIPS")
> -		     (match_test "umips_12bit_offset_address_p (XEXP (op,
> 0), mode)")
> -		     (match_test "mips_address_insns (XEXP (op, 0), mode,
> false)"))))
> +       (if_then_else
> +	 (match_test "TARGET_MICROMIPS")
> +	 (match_test "umips_12bit_offset_address_p (XEXP (op, 0), mode)")
> +	 (match_test "mips_address_insns (XEXP (op, 0), mode, false)"))))
> 
>  (define_address_constraint "ZD"
>    "When compiling microMIPS code, this constraint matches an address
> operand
> Index: gcc/config/mips/micromips.md
> ==========================================================
> =========
> --- gcc/config/mips/micromips.md	2013-02-21 19:57:26.000000000 +0000
> +++ gcc/config/mips/micromips.md	2013-02-21 20:29:35.840530555 +0000
> @@ -48,8 +48,7 @@ (define_peephole2
>    "TARGET_MICROMIPS
>     && umips_load_store_pair_p (true, operands)"
>    [(parallel [(set (match_dup 0) (match_dup 1))
> -              (set (match_dup 2) (match_dup 3))])]
> -)
> +              (set (match_dup 2) (match_dup 3))])])
> 
>  ;; The behavior of the LWP insn is undefined if placed in a delay slot.
>  (define_insn "*lwp"
> @@ -77,8 +76,7 @@ (define_peephole2
>    "TARGET_MICROMIPS
>     && umips_load_store_pair_p (false, operands)"
>    [(parallel [(set (match_dup 0) (match_dup 1))
> -              (set (match_dup 2) (match_dup 3))])]
> -)
> +              (set (match_dup 2) (match_dup 3))])])
> 
>  ;; The behavior of the SWP insn is undefined if placed in a delay slot.
>  (define_insn "*swp"
> @@ -106,8 +104,7 @@ (define_peephole2
>    "TARGET_MICROMIPS
>     && umips_movep_target_p (operands[0], operands[2])"
>    [(parallel [(set (match_dup 0) (match_dup 1))
> -              (set (match_dup 2) (match_dup 3))])]
> -)
> +              (set (match_dup 2) (match_dup 3))])])
> 
>  ;; The behavior of the MOVEP insn is undefined if placed in a delay slot.
>  (define_insn "*movep<MOVEP1:mode><MOVEP2:mode>"
> Index: gcc/config/mips/mips.c
> ==========================================================
> =========
> --- gcc/config/mips/mips.c	2013-02-21 20:03:53.631341344 +0000
> +++ gcc/config/mips/mips.c	2013-02-21 21:08:27.247096879 +0000
> @@ -1252,7 +1252,7 @@ mips_use_debug_exception_return_p (tree  }
> 
>  /* Return the set of compression modes that are explicitly required
> -   by DECL.  */
> +   by the attributes in ATTRIBUTES.  */
> 
>  static unsigned int
>  mips_get_compress_on_flags (tree attributes) @@ -1269,7 +1269,7 @@
> mips_get_compress_on_flags (tree attribu  }
> 
>  /* Return the set of compression modes that are explicitly forbidden
> -   by DECL.  */
> +   by the attributes in ATTRIBUTES.  */
> 
>  static unsigned int
>  mips_get_compress_off_flags (tree attributes) @@ -1290,6 +1290,7 @@
> mips_get_compress_off_flags (tree attrib
> 
>  /* Return the compression mode that should be used for function DECL.
>     Return the ambient setting if DECL is null.  */
> +
>  static unsigned int
>  mips_get_compress_mode (tree decl)
>  {
> @@ -1411,20 +1412,16 @@ mips_merge_decl_attributes (tree olddecl
> 
>    diff = (mips_get_compress_on_flags (DECL_ATTRIBUTES (olddecl))
>  	  ^ mips_get_compress_on_flags (DECL_ATTRIBUTES (newdecl)));
> -
>    if (diff)
>      error ("%qE redeclared with conflicting %qs attributes",
>  	   DECL_NAME (newdecl), mips_get_compress_on_name (diff));
> 
> -
>    diff = (mips_get_compress_off_flags (DECL_ATTRIBUTES (olddecl))
>  	  ^ mips_get_compress_off_flags (DECL_ATTRIBUTES (newdecl)));
> -
>    if (diff)
>      error ("%qE redeclared with conflicting %qs attributes",
>  	   DECL_NAME (newdecl), mips_get_compress_off_name (diff));
> 
> -
>    return merge_attributes (DECL_ATTRIBUTES (olddecl),
>  			   DECL_ATTRIBUTES (newdecl));
>  }
> @@ -6194,7 +6191,7 @@ mips_start_function_definition (const ch
>    if (TARGET_MICROMIPS)
>      fprintf (asm_out_file, "\t.set\tmicromips\n");  #ifdef
> HAVE_GAS_MICROMIPS
> -  else
> +  else
>      fprintf (asm_out_file, "\t.set\tnomicromips\n");  #endif
> 
> @@ -7040,8 +7037,6 @@ mips_call_may_need_jalx_p (tree decl)  static bool
> mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)  {
> -
> -  unsigned int compression_mode = mips_get_compress_mode (decl);
>    if (!TARGET_SIBCALLS)
>      return false;
> 
> @@ -7050,8 +7045,8 @@ mips_function_ok_for_sibcall (tree decl,
>    if (mips_interrupt_type_p (TREE_TYPE (current_function_decl)))
>      return false;
> 
> -  /* Direct Js are only possible to functions that use the same ISA
> -  encoding.  There is no JX counterpoart of JALX.  */
> +  /* Direct Js are only possible to functions that use the same ISA encoding.
> +     There is no JX counterpoart of JALX.  */
>    if (decl
>        && const_call_insn_operand (XEXP (DECL_RTL (decl), 0), VOIDmode)
>        && mips_call_may_need_jalx_p (decl)) @@ -10400,10 +10395,10 @@
> mips_save_reg (rtx reg, rtx mem)
>     instruction.  The entries are ordered by number of registers set in
>     the mask.  We also ignore the single register encodings because a
>     normal SW/LW is preferred.  */
> -
> +
>  static const unsigned int umips_swm_mask[17] = {
>    0xc0ff0000, 0x80ff0000, 0x40ff0000, 0x807f0000,
> -  0x00ff0000, 0x803f0000, 0x007f0000, 0x801f0000,
> +  0x00ff0000, 0x803f0000, 0x007f0000, 0x801f0000,
>    0x003f0000, 0x800f0000, 0x001f0000, 0x80070000,
>    0x000f0000, 0x80030000, 0x00070000, 0x80010000,
>    0x00030000
> @@ -10424,8 +10419,8 @@ static const unsigned int umips_swm_enco
> umips_build_save_restore (mips_save_restore_fn fn,
>  			  unsigned *mask, HOST_WIDE_INT *offset)  {
> -  int i, nregs;
> -  unsigned int j;
> +  int nregs;
> +  unsigned int i, j;
>    rtx pattern, set, reg, mem;
>    HOST_WIDE_INT this_offset;
>    rtx this_base;
> @@ -10438,7 +10433,7 @@ umips_build_save_restore (mips_save_rest
>    if (i == ARRAY_SIZE (umips_swm_mask))
>      return false;
> 
> -  /* Adjust offset for output.  */
> +  /* Get the offset of the lowest save slot.  */
>    nregs = (umips_swm_encoding[i] & 0xf) + (umips_swm_encoding[i] >> 4);
>    this_offset = *offset - UNITS_PER_WORD * (nregs - 1);
> 
> @@ -10453,10 +10448,9 @@ umips_build_save_restore (mips_save_rest
>    /* For registers $16-$23 and $30.  */
>    for (j = 0; j < (umips_swm_encoding[i] & 0xf); j++)
>      {
> -      unsigned int regno;
>        HOST_WIDE_INT offset = this_offset + j * UNITS_PER_WORD;
>        mem = gen_frame_mem (SImode, plus_constant (Pmode, this_base,
> offset));
> -      regno = (j != 8) ? 16 + j : 30;
> +      unsigned int regno = (j != 8) ? 16 + j : 30;
>        *mask &= ~(1 << regno);
>        reg = gen_rtx_REG (SImode, regno);
>        if (fn == mips_save_reg)
> @@ -10488,7 +10482,7 @@ umips_build_save_restore (mips_save_rest
> 
>    pattern = emit_insn (pattern);
>    if (fn == mips_save_reg)
> -    RTX_FRAME_RELATED_P (pattern) = 1;
> +    RTX_FRAME_RELATED_P (pattern) = 1;
> 
>    /* Adjust the last offset.  */
>    *offset -= UNITS_PER_WORD * nregs;
> @@ -10514,7 +10508,7 @@ mips_for_each_saved_gpr_and_fpr (HOST_WI
>       the return register be stored at func+4, and also it allows us not to
>       need a nop in the epilogue if at least one register is reloaded in
>       addition to return address.  */
> -  offset = cfun->machine->frame.gp_sp_offset - sp_offset;
> +  offset = frame->gp_sp_offset - sp_offset;
>    mask = frame->mask;
> 
>    if (TARGET_MICROMIPS)
> @@ -17087,8 +17081,8 @@ mips_option_override (void)
> 
>    /* Now select the ISA mode.
> 
> -     Do all CPP-sensitive stuff in uncompressed mode;
> -     We'll switch modes later if required.  */
> +     Do all CPP-sensitive stuff in uncompressed mode; we'll switch modes
> +     later if required.  */
>    mips_set_compression_mode (0);
>  }
> 
> @@ -17366,7 +17360,6 @@ umips_save_restore_pattern_p (bool save_
>      {
>        rtx set, reg, mem, this_base;
>        HOST_WIDE_INT this_offset;
> -      unsigned int this_regno;
> 
>        /* Check that we have a SET.  */
>        set = XVECEXP (pattern, 0, n);
> @@ -17414,7 +17407,8 @@ umips_save_restore_pattern_p (bool save_
> 
>    return false;
>  }
> -/* Return the assembly instruction for microMIPS lwm or swm.
> +
> +/* Return the assembly instruction for microMIPS LWM or SWM.
>     SAVE_P and PATTERN are as for umips_save_restore_pattern_p.  */
> 
>  const char *
> @@ -17424,7 +17418,7 @@ umips_output_save_restore (bool save_p,
>    char *s;
>    int n;
>    HOST_WIDE_INT offset;
> -  rtx base, mem, set, reg, last_set, last_reg;
> +  rtx base, mem, set, last_set, last_reg;
> 
>    /* Parse the pattern.  */
>    gcc_assert (umips_save_restore_pattern_p (save_p, pattern)); @@ -
> 17434,7 +17428,6 @@ umips_output_save_restore (bool save_p,
>    n = XVECLEN (pattern, 0);
> 
>    set = XVECEXP (pattern, 0, 0);
> -  reg = save_p ? SET_SRC (set) : SET_DEST (set);
>    mem = save_p ? SET_DEST (set) : SET_SRC (set);
>    mips_split_plus (XEXP (mem, 0), &base, &offset);
> 
> @@ -17506,7 +17499,9 @@ umips_load_store_pair_p_1 (bool load_p,
>    return true;
>  }
> 
> -/* Return true if operands can be used in an LWP or SWP instruction.  */
> +/* OPERANDS describes the operands to a pair of SETs, in the order
> +   dest1, src1, dest2, src2.  Return true if the operands can be used
> +   in an LWP or SWP instruction; LOAD_P says which.  */
> 
>  bool
>  umips_load_store_pair_p (bool load_p, rtx *operands) @@ -17537,8
> +17532,9 @@ umips_load_store_pair_p (bool load_p, rt
>    return false;
>  }
> 
> -/* Return the assembly instruction for microMIPS lwp or swp.
> -   LOAD_P is true for load.  */
> +/* Return the assembly instruction for a microMIPS LWP or SWP in which
> +   the first register is REG and the first memory slot is MEM.
> +   LOAD_P is true for LWP.  */
> 
>  static void
>  umips_output_load_store_pair_1 (bool load_p, rtx reg, rtx mem) @@ -
> 17551,6 +17547,9 @@ umips_output_load_store_pair_1 (bool loa
>      output_asm_insn ("swp\t%0,%1", ops);  }
> 
> +/* Output the assembly instruction for a microMIPS LWP or SWP instruction.
> +   LOAD_P and OPERANDS are as for umips_load_store_pair_p.  */
> +
>  void
>  umips_output_load_store_pair (bool load_p, rtx *operands)  { @@ -17569,7
> +17568,7 @@ umips_output_load_store_pair (bool load_
>        mem1 = operands[0];
>        mem2 = operands[2];
>      }
> -
> +
>    if (REGNO (reg2) == REGNO (reg1) + 1)
>      {
>        umips_output_load_store_pair_1 (load_p, reg1, mem1); @@ -17588,12
> +17587,12 @@ umips_movep_target_p (rtx reg1, rtx reg2
>    int regno1, regno2, pair;
>    unsigned int i;
>    static const int match[8] = {
> -    0x00000060,	/* 5, 6 */
> -    0x000000a0,	/* 5, 7 */
> -    0x000000c0,	/* 6, 7 */
> -    0x00200010,	/* 4, 21 */
> -    0x00400010,	/* 4, 22 */
> -    0x00000030,	/* 4, 5 */
> +    0x00000060, /* 5, 6 */
> +    0x000000a0, /* 5, 7 */
> +    0x000000c0, /* 6, 7 */
> +    0x00200010, /* 4, 21 */
> +    0x00400010, /* 4, 22 */
> +    0x00000030, /* 4, 5 */
>      0x00000050, /* 4, 6 */
>      0x00000090  /* 4, 7 */
>    };
> @@ -17604,7 +17603,7 @@ umips_movep_target_p (rtx reg1, rtx reg2
>    regno1 = REGNO (reg1);
>    regno2 = REGNO (reg2);
> 
> -  if (!GP_REG_P (regno1)  || !GP_REG_P (regno2))
> +  if (!GP_REG_P (regno1) || !GP_REG_P (regno2))
>      return false;
> 
>    pair = (1 << regno1) | (1 << regno2);
> Index: gcc/config/mips/mips.h
> ==========================================================
> =========
> --- gcc/config/mips/mips.h	2013-02-21 20:03:53.632341352 +0000
> +++ gcc/config/mips/mips.h	2013-02-21 20:04:23.070542151 +0000
> @@ -1019,7 +1019,8 @@ #define ISA_HAS_DSPR2
> 	(TARGET_DSPR2 &&
>     and "addiu $4,$4,1".  */
>  #define ISA_HAS_LOAD_DELAY	(ISA_MIPS1
> 	\
>  				 && !TARGET_MIPS3900
> 	\
> -				 && !TARGET_MIPS16)
> +				 && !TARGET_MIPS16			\
> +				 && !TARGET_MICROMIPS)
> 
>  /* Likewise mtc1 and mfc1.  */
>  #define ISA_HAS_XFER_DELAY	(mips_isa <= 3			\
> Index: gcc/config/mips/mips.md
> ==========================================================
> =========
> --- gcc/config/mips/mips.md	2013-02-21 19:57:26.000000000 +0000
> +++ gcc/config/mips/mips.md	2013-02-21 20:06:12.347267724 +0000
> @@ -5471,7 +5471,7 @@ (define_insn "*branch_equality<mode>"
>      return mips_output_conditional_branch (insn, operands,
>  					   "%*b%C1z%:\t%2,%0",
>  					   "%*b%N1z%:\t%2,%0");
> -
> +
>    return mips_output_conditional_branch (insn, operands,
>  					 MIPS_BRANCH ("b%C1",
> "%2,%z3,%0"),
>  					 MIPS_BRANCH ("b%N1",
> "%2,%z3,%0"));
> Index: gcc/testsuite/gcc.target/mips/mips.exp
> ==========================================================
> =========
> --- gcc/testsuite/gcc.target/mips/mips.exp	2013-02-21
> 20:03:53.632341352 +0000
> +++ gcc/testsuite/gcc.target/mips/mips.exp	2013-02-21
> 20:04:23.071542158 +0000
> @@ -817,6 +817,8 @@ proc mips-dg-finish {} {
>  #            |                           |
>  #         -mips16/-mflip-mips16       -mno-mips16
>  #            |                           |
> +#         -micromips                  -mno-micromips
> +#            |                           |
>  #         -mips3d                     -mno-mips3d
>  #            |                           |
>  #         -mpaired-single             -mno-paired-single
> @@ -905,6 +907,8 @@ proc mips-dg-options { args } {
> 
>      # Handle dependencies between options on the left of the
>      # dependency diagram.
> +    mips_option_dependency options "-mips16" "-mno-micromips"
> +    mips_option_dependency options "-mmicromips" "-mno-mips16"
>      mips_option_dependency options "-mips3d" "-mpaired-single"
>      mips_option_dependency options "-mpaired-single" "-mfp64"
>      mips_option_dependency options "-mfp64" "-mhard-float"
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-1.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-1.c	2013-02-21
> 20:33:17.980173008 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4)
> +{
> +  int r5 = r4[0];
> +  int r6 = r4[1];
> +  r4[2] = r5 * r5;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tlwp\t\\\$5,0\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-2.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-2.c	2013-02-21
> 20:36:21.709519202 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4)
> +{
> +  int r5 = r4[0];
> +  int r6 = r4[1];
> +  r4[2] = r6 * r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tlwp\t\\\$5,0\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-3.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-3.c	2013-02-21
> 20:36:29.710578763 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4)
> +{
> +  int r5 = r4[511];
> +  int r6 = r4[512];
> +  r4[2] = r5 * r5;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tlwp\t\\\$5,2044\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-4.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-4.c	2013-02-21
> 20:36:37.533637002 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4)
> +{
> +  int r5 = r4[511];
> +  int r6 = r4[512];
> +  r4[2] = r6 * r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tlwp\t\\\$5,2044\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-5.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-5.c	2013-02-21
> 20:36:46.255701936 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4)
> +{
> +  int r5 = r4[512];
> +  int r6 = r4[513];
> +  r4[2] = r5 * r5;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler-not "\tlwp" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-6.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-6.c	2013-02-21
> 20:36:53.911758937 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4)
> +{
> +  int r5 = r4[512];
> +  int r6 = r4[513];
> +  r4[2] = r6 * r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler-not "\tlwp" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-7.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-7.c	2013-02-21
> 20:04:23.074542181 +0000
> @@ -0,0 +1,41 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +f1 (int *r4, int dummy, int *other)
> +{
> +  int r5 = r4[1];
> +  int newr4 = r4[0];
> +  other[0] = r5 * r5;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r4asm asm ("$4") = newr4;
> +    asm ("#foo" : "=m" (other[1]) : "d" (r4asm), "d" (r5asm));
> +  }
> +}
> +
> +void MICROMIPS
> +f2 (int *r4, int dummy, int *other)
> +{
> +  int newr4 = r4[0];
> +  int r5 = *(int *)(newr4 + 4);
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r4asm asm ("$4") = newr4;
> +    asm ("#foo" : "=m" (other[0]) : "d" (r4asm), "d" (r5asm));
> +  }
> +}
> +
> +void MICROMIPS
> +f3 (int dummy, int *r5, int *other)
> +{
> +  int newr5 = r5[1];
> +  int r4 = *(int *)newr5;
> +  {
> +    register int r5asm asm ("$4") = r4;
> +    register int r4asm asm ("$5") = newr5;
> +    asm ("#foo" : "=m" (other[0]) : "d" (r4asm), "d" (r5asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler-not "\tlwp" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-8.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-8.c	2013-02-21
> 20:04:23.074542181 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +f1 (int dummy, int *r5, int *other)
> +{
> +  int r4 = r5[0];
> +  int newr5 = r5[1];
> +  other[0] = r4 * r4;
> +  {
> +    register int r5asm asm ("$4") = r4;
> +    register int r4asm asm ("$5") = newr5;
> +    asm ("#foo" : "=m" (other[1]) : "d" (r4asm), "d" (r5asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tlwp\t\\\$4,0\\(\\\$5\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-swp-1.c
> ==========================================================
> =========
> --- gcc/testsuite/gcc.target/mips/umips-lwp-swp-1.c	2013-02-21
> 20:03:53.633341359 +0000
> +++ /dev/null	2013-02-18 18:12:58.656083693 +0000
> @@ -1,17 +0,0 @@
> -/* Test that an SWP can be generated when the instruction order is
> reversed:
> -
> -   ie.  ST $3, mem+4
> -	ST $2, mem
> -*/
> -
> -/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
> -/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> -/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
> -/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> -
> -void MICROMIPS
> -foo (long long l1, long long *l2)
> -{
> -  *l2 = l1;
> -}
> -/* { dg-final { scan-assembler "\tswp\t\\\$4,0\\(\\\$6\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-swp-2.c
> ==========================================================
> =========
> --- gcc/testsuite/gcc.target/mips/umips-lwp-swp-2.c	2013-02-21
> 20:03:53.633341359 +0000
> +++ /dev/null	2013-02-18 18:12:58.656083693 +0000
> @@ -1,176 +0,0 @@
> -/* Test that an SWP can be generated when the instruction order is not
> reversed:
> -
> -   ie.  ST $2, mem
> -	ST $2, mem+4
> -*/
> -
> -/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
> -/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> -
> -#include <stdarg.h>
> -
> -void MICROMIPS s(int, ...);
> -void MICROMIPS z(int, ...);
> -void MICROMIPS c(int, ...);
> -
> -typedef int l[500];
> -
> -void
> -MICROMIPS f (int n)
> -{
> -  int i;
> -  l a0, a1, a2, a3, a4, a5, a6, a7, a8, a9;
> -  l a10, a11, a12, a13, a14, a15, a16, a17, a18, a19;
> -  l a20, a21, a22, a23, a24, a25, a26, a27, a28, a29;
> -  l a30, a31, a32, a33, a34, a35, a36, a37, a38, a39;
> -  int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
> -  int i10, i11, i12, i13, i14, i15, i16, i17, i18, i19;
> -  int i20, i21, i22, i23, i24, i25, i26, i27, i28, i29;
> -  int i30, i31, i32, i33, i34, i35, i36, i37, i38, i39;
> -
> -  for (i = 0; i < n; i++)
> -    {
> -      s (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
> -	 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
> -         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
> -         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
> -      i0 = a0[0];
> -      i1 = a1[0];
> -      i2 = a2[0];
> -      i3 = a3[0];
> -      i4 = a4[0];
> -      i5 = a5[0];
> -      i6 = a6[0];
> -      i7 = a7[0];
> -      i8 = a8[0];
> -      i9 = a9[0];
> -      i10 = a10[0];
> -      i11 = a11[0];
> -      i12 = a12[0];
> -      i13 = a13[0];
> -      i14 = a14[0];
> -      i15 = a15[0];
> -      i16 = a16[0];
> -      i17 = a17[0];
> -      i18 = a18[0];
> -      i19 = a19[0];
> -      i20 = a20[0];
> -      i21 = a21[0];
> -      i22 = a22[0];
> -      i23 = a23[0];
> -      i24 = a24[0];
> -      i25 = a25[0];
> -      i26 = a26[0];
> -      i27 = a27[0];
> -      i28 = a28[0];
> -      i29 = a29[0];
> -      i30 = a30[0];
> -      i31 = a31[0];
> -      i32 = a32[0];
> -      i33 = a33[0];
> -      i34 = a34[0];
> -      i35 = a35[0];
> -      i36 = a36[0];
> -      i37 = a37[0];
> -      i38 = a38[0];
> -      i39 = a39[0];
> -      z (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
> -	 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
> -         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
> -         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
> -      a0[i0] = i0;
> -      a1[i1] = i1;
> -      a2[i2] = i2;
> -      a3[i3] = i3;
> -      a4[i4] = i4;
> -      a5[i5] = i5;
> -      a6[i6] = i6;
> -      a7[i7] = i7;
> -      a8[i8] = i8;
> -      a9[i9] = i9;
> -      a10[i10] = i10;
> -      a11[i11] = i11;
> -      a12[i12] = i12;
> -      a13[i13] = i13;
> -      a14[i14] = i14;
> -      a15[i15] = i15;
> -      a16[i16] = i16;
> -      a17[i17] = i17;
> -      a18[i18] = i18;
> -      a19[i19] = i19;
> -      a20[i20] = i20;
> -      a21[i21] = i21;
> -      a22[i22] = i22;
> -      a23[i23] = i23;
> -      a24[i24] = i24;
> -      a25[i25] = i25;
> -      a26[i26] = i26;
> -      a27[i27] = i27;
> -      a28[i28] = i28;
> -      a29[i29] = i29;
> -      a30[i30] = i30;
> -      a31[i31] = i31;
> -      a32[i32] = i32;
> -      a33[i33] = i33;
> -      a34[i34] = i34;
> -      a35[i35] = i35;
> -      a36[i36] = i36;
> -      a37[i37] = i37;
> -      a38[i38] = i38;
> -      a39[i39] = i39;
> -      c (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
> -	 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
> -         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
> -         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
> -    }
> -}
> -
> -int
> -MICROMIPS main ()
> -{
> -  f (1);
> -}
> -
> -void
> -MICROMIPS s (int n, ...)
> -{
> -  va_list list;
> -
> -  va_start (list, n);
> -  while (n--)
> -    {
> -      int *a = va_arg (list, int *);
> -      a[0] = n;
> -    }
> -  va_end (list);
> -}
> -
> -void
> -MICROMIPS z (int n, ...)
> -{
> -  va_list list;
> -
> -  va_start (list, n);
> -  while (n--)
> -    {
> -      int *a = va_arg (list, int *);
> -      __builtin_memset (a, 0, sizeof (l));
> -    }
> -  va_end (list);
> -}
> -
> -void
> -MICROMIPS c (int n, ...)
> -{
> -  va_list list;
> -
> -  va_start (list, n);
> -  while (n--)
> -    {
> -      int *a = va_arg (list, int *);
> -      if (a[n] != n)
> -	;
> -    }
> -  va_end (list);
> -}
> -/* { dg-final { scan-assembler "\tswp" } } */
> Index: gcc/testsuite/gcc.target/mips/umips-lwp-swp-volatile.c
> ==========================================================
> =========
> --- gcc/testsuite/gcc.target/mips/umips-lwp-swp-volatile.c	2013-02-21
> 19:57:47.000000000 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-lwp-swp-volatile.c	2013-02-21
> 20:04:49.560724491 +0000
> @@ -2,8 +2,8 @@
>  /* { dg-options "-mmicromips" } */
> 
>  /* This test ensures that we do not generate microMIPS SWP or LWP
> -   instructions when any component of the accessed memory is volatile;
> -   they are unsafe for such since they might cause replay of partial
> +   instructions when any component of the accessed memory is volatile;
> +   they are unsafe for such since they might cause replay of partial
>     accesses if interrupted by an exception.  */
> 
>  static void set_csr (volatile void *p, int v)
> Index: gcc/testsuite/gcc.target/mips/umips-movep-2.c
> ==========================================================
> =========
> --- gcc/testsuite/gcc.target/mips/umips-movep-2.c	2013-02-21
> 20:03:53.632341352 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-movep-2.c	2013-02-21
> 20:42:40.247604192 +0000
> @@ -1,12 +1,13 @@
>  /* Check that we can generate the MOVEP instruction.  */
> -/* { dg-options "-fpeephole2 (-mmicromips)" } */
> +/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
>  /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> 
>  int bar (int, int);
> 
> -int
> +int MICROMIPS
>  foo (int n, int a)
>  {
>    return bar (0, 0);
>  }
> -/* { dg-final { scan-assembler "\tmovep\t" } } */
> +
> +/* { dg-final { scan-assembler "\tmovep\t\\\$4,\\\$5,\\\$0,\\\$0" } }
> +*/
> Index: gcc/testsuite/gcc.target/mips/umips-save-restore-1.c
> ==========================================================
> =========
> --- gcc/testsuite/gcc.target/mips/umips-save-restore-1.c	2013-02-21
> 19:57:47.000000000 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-save-restore-1.c	2013-02-21
> 20:06:37.807422840 +0000
> @@ -5,7 +5,7 @@
>  int bar (int, int, int, int, int);
> 
>  MICROMIPS int
> -foo (int n, int a, int b, int c, int d)
> +foo (int n, int a, int b, int c, int d)
>  {
>    int i, j;
> 
> Index: gcc/testsuite/gcc.target/mips/umips-swp-1.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-1.c	2013-02-21
> 20:04:23.075542188 +0000
> @@ -0,0 +1,10 @@
> +/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (long long l1, long long *l2)
> +{
> +  *l2 = l1;
> +}
> +
> +/* { dg-final { scan-assembler "\tswp\t\\\$4,0\\(\\\$6\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-swp-2.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-2.c	2013-02-21
> 20:40:04.431076334 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4, int r5, int r6)
> +{
> +  r6 *= r6;
> +  r4[0] = r5;
> +  r4[1] = r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tswp\t\\\$5,0\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-swp-3.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-3.c	2013-02-21
> 20:40:16.614164109 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4, int r5, int r6)
> +{
> +  r5 *= r5;
> +  r4[0] = r5;
> +  r4[1] = r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tswp\t\\\$5,0\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-swp-4.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-4.c	2013-02-21
> 20:40:21.540184989 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4, int r5, int r6)
> +{
> +  r6 *= r6;
> +  r4[511] = r5;
> +  r4[512] = r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tswp\t\\\$5,2044\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-swp-5.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-5.c	2013-02-21
> 20:40:28.131170677 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4, int r5, int r6)
> +{
> +  r5 *= r5;
> +  r4[511] = r5;
> +  r4[512] = r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler "\tswp\t\\\$5,2044\\(\\\$4\\)" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-swp-6.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-6.c	2013-02-21
> 20:40:33.757163423 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4, int r5, int r6)
> +{
> +  r6 *= r6;
> +  r4[512] = r5;
> +  r4[513] = r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler-not "\tswp" } }*/
> Index: gcc/testsuite/gcc.target/mips/umips-swp-7.c
> ==========================================================
> =========
> --- /dev/null	2013-02-18 18:12:58.656083693 +0000
> +++ gcc/testsuite/gcc.target/mips/umips-swp-7.c	2013-02-21
> 20:40:38.486160549 +0000
> @@ -0,0 +1,17 @@
> +/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
> +
> +void MICROMIPS
> +foo (int *r4, int r5, int r6)
> +{
> +  r5 *= r5;
> +  r4[512] = r5;
> +  r4[513] = r6;
> +  {
> +    register int r5asm asm ("$5") = r5;
> +    register int r6asm asm ("$6") = r6;
> +    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
> +  }
> +}
> +
> +/* { dg-final { scan-assembler-not "\tswp" } }*/
Richard Sandiford - Feb. 25, 2013, 9:41 a.m.
"Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> HI Richard, 
> The base patch is now committed.  The final patch, including your final
> edits is attached.  I will be posting the optimization pieces later this
> week.

Sorry, when I said that it was ok for 4.9, I meant that it should wait
until 4.8 had branched.  As I say, I think the patch is too invasive
for 4.8 at this (regression fixes only) stage.

Please revert the patch for now and reapply it once 4.9 starts.

Richard
Moore, Catherine - Feb. 25, 2013, 1:55 p.m.
> -----Original Message-----
> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: Monday, February 25, 2013 4:42 AM
> To: Moore, Catherine
> Cc: gcc-patches@gcc.gnu.org; Rozycki, Maciej
> Subject: Re: FW: [PATCH] [MIPS] microMIPS gcc support
> 
> "Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> > HI Richard,
> > The base patch is now committed.  The final patch, including your
> > final edits is attached.  I will be posting the optimization pieces
> > later this week.
> 
> Sorry, when I said that it was ok for 4.9, I meant that it should wait until 4.8
> had branched.  As I say, I think the patch is too invasive for 4.8 at this
> (regression fixes only) stage.
> 
> Please revert the patch for now and reapply it once 4.9 starts.
> 

Now reverted.  I thought that we had branched.
Catherine

Patch

Index: gcc/config/mips/constraints.md
===================================================================
--- gcc/config/mips/constraints.md	2013-02-21 19:57:26.000000000 +0000
+++ gcc/config/mips/constraints.md	2013-02-21 20:24:30.909497318 +0000
@@ -239,9 +239,10 @@  (define_memory_constraint "ZC"
    @code{sc}.  When not compiling for microMIPS code, @code{ZC} is
    equivalent to @code{R}."
   (and (match_code "mem")
-       (if_then_else (match_test "TARGET_MICROMIPS")
-		     (match_test "umips_12bit_offset_address_p (XEXP (op, 0), mode)")
-		     (match_test "mips_address_insns (XEXP (op, 0), mode, false)"))))
+       (if_then_else
+	 (match_test "TARGET_MICROMIPS")
+	 (match_test "umips_12bit_offset_address_p (XEXP (op, 0), mode)")
+	 (match_test "mips_address_insns (XEXP (op, 0), mode, false)"))))
 
 (define_address_constraint "ZD"
   "When compiling microMIPS code, this constraint matches an address operand
Index: gcc/config/mips/micromips.md
===================================================================
--- gcc/config/mips/micromips.md	2013-02-21 19:57:26.000000000 +0000
+++ gcc/config/mips/micromips.md	2013-02-21 20:29:35.840530555 +0000
@@ -48,8 +48,7 @@  (define_peephole2
   "TARGET_MICROMIPS
    && umips_load_store_pair_p (true, operands)"
   [(parallel [(set (match_dup 0) (match_dup 1))
-              (set (match_dup 2) (match_dup 3))])]
-)
+              (set (match_dup 2) (match_dup 3))])])
 
 ;; The behavior of the LWP insn is undefined if placed in a delay slot.
 (define_insn "*lwp"
@@ -77,8 +76,7 @@  (define_peephole2
   "TARGET_MICROMIPS
    && umips_load_store_pair_p (false, operands)"
   [(parallel [(set (match_dup 0) (match_dup 1))
-              (set (match_dup 2) (match_dup 3))])]
-)
+              (set (match_dup 2) (match_dup 3))])])
 
 ;; The behavior of the SWP insn is undefined if placed in a delay slot.
 (define_insn "*swp"
@@ -106,8 +104,7 @@  (define_peephole2
   "TARGET_MICROMIPS
    && umips_movep_target_p (operands[0], operands[2])"
   [(parallel [(set (match_dup 0) (match_dup 1))
-              (set (match_dup 2) (match_dup 3))])]
-)
+              (set (match_dup 2) (match_dup 3))])])
 
 ;; The behavior of the MOVEP insn is undefined if placed in a delay slot.
 (define_insn "*movep<MOVEP1:mode><MOVEP2:mode>"
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2013-02-21 20:03:53.631341344 +0000
+++ gcc/config/mips/mips.c	2013-02-21 21:08:27.247096879 +0000
@@ -1252,7 +1252,7 @@  mips_use_debug_exception_return_p (tree
 }
 
 /* Return the set of compression modes that are explicitly required
-   by DECL.  */
+   by the attributes in ATTRIBUTES.  */
 
 static unsigned int
 mips_get_compress_on_flags (tree attributes)
@@ -1269,7 +1269,7 @@  mips_get_compress_on_flags (tree attribu
 }
 
 /* Return the set of compression modes that are explicitly forbidden
-   by DECL.  */
+   by the attributes in ATTRIBUTES.  */
 
 static unsigned int
 mips_get_compress_off_flags (tree attributes)
@@ -1290,6 +1290,7 @@  mips_get_compress_off_flags (tree attrib
 
 /* Return the compression mode that should be used for function DECL.
    Return the ambient setting if DECL is null.  */
+
 static unsigned int
 mips_get_compress_mode (tree decl)
 {
@@ -1411,20 +1412,16 @@  mips_merge_decl_attributes (tree olddecl
 
   diff = (mips_get_compress_on_flags (DECL_ATTRIBUTES (olddecl))
 	  ^ mips_get_compress_on_flags (DECL_ATTRIBUTES (newdecl)));
-
   if (diff)
     error ("%qE redeclared with conflicting %qs attributes",
 	   DECL_NAME (newdecl), mips_get_compress_on_name (diff));
 
-
   diff = (mips_get_compress_off_flags (DECL_ATTRIBUTES (olddecl))
 	  ^ mips_get_compress_off_flags (DECL_ATTRIBUTES (newdecl)));
-
   if (diff)
     error ("%qE redeclared with conflicting %qs attributes",
 	   DECL_NAME (newdecl), mips_get_compress_off_name (diff));
 
-
   return merge_attributes (DECL_ATTRIBUTES (olddecl),
 			   DECL_ATTRIBUTES (newdecl));
 }
@@ -6194,7 +6191,7 @@  mips_start_function_definition (const ch
   if (TARGET_MICROMIPS)
     fprintf (asm_out_file, "\t.set\tmicromips\n");
 #ifdef HAVE_GAS_MICROMIPS
-  else 
+  else
     fprintf (asm_out_file, "\t.set\tnomicromips\n");
 #endif
 
@@ -7040,8 +7037,6 @@  mips_call_may_need_jalx_p (tree decl)
 static bool
 mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 {
-
-  unsigned int compression_mode = mips_get_compress_mode (decl);
   if (!TARGET_SIBCALLS)
     return false;
 
@@ -7050,8 +7045,8 @@  mips_function_ok_for_sibcall (tree decl,
   if (mips_interrupt_type_p (TREE_TYPE (current_function_decl)))
     return false;
 
-  /* Direct Js are only possible to functions that use the same ISA
-  encoding.  There is no JX counterpoart of JALX.  */
+  /* Direct Js are only possible to functions that use the same ISA encoding.
+     There is no JX counterpoart of JALX.  */
   if (decl
       && const_call_insn_operand (XEXP (DECL_RTL (decl), 0), VOIDmode)
       && mips_call_may_need_jalx_p (decl))
@@ -10400,10 +10395,10 @@  mips_save_reg (rtx reg, rtx mem)
    instruction.  The entries are ordered by number of registers set in
    the mask.  We also ignore the single register encodings because a
    normal SW/LW is preferred.  */
-   
+
 static const unsigned int umips_swm_mask[17] = {
   0xc0ff0000, 0x80ff0000, 0x40ff0000, 0x807f0000,
-  0x00ff0000, 0x803f0000, 0x007f0000, 0x801f0000,	
+  0x00ff0000, 0x803f0000, 0x007f0000, 0x801f0000,
   0x003f0000, 0x800f0000, 0x001f0000, 0x80070000,
   0x000f0000, 0x80030000, 0x00070000, 0x80010000,
   0x00030000
@@ -10424,8 +10419,8 @@  static const unsigned int umips_swm_enco
 umips_build_save_restore (mips_save_restore_fn fn,
 			  unsigned *mask, HOST_WIDE_INT *offset)
 {
-  int i, nregs;
-  unsigned int j;
+  int nregs;
+  unsigned int i, j;
   rtx pattern, set, reg, mem;
   HOST_WIDE_INT this_offset;
   rtx this_base;
@@ -10438,7 +10433,7 @@  umips_build_save_restore (mips_save_rest
   if (i == ARRAY_SIZE (umips_swm_mask))
     return false;
 
-  /* Adjust offset for output.  */
+  /* Get the offset of the lowest save slot.  */
   nregs = (umips_swm_encoding[i] & 0xf) + (umips_swm_encoding[i] >> 4);
   this_offset = *offset - UNITS_PER_WORD * (nregs - 1);
 
@@ -10453,10 +10448,9 @@  umips_build_save_restore (mips_save_rest
   /* For registers $16-$23 and $30.  */
   for (j = 0; j < (umips_swm_encoding[i] & 0xf); j++)
     {
-      unsigned int regno;
       HOST_WIDE_INT offset = this_offset + j * UNITS_PER_WORD;
       mem = gen_frame_mem (SImode, plus_constant (Pmode, this_base, offset));
-      regno = (j != 8) ? 16 + j : 30;
+      unsigned int regno = (j != 8) ? 16 + j : 30;
       *mask &= ~(1 << regno);
       reg = gen_rtx_REG (SImode, regno);
       if (fn == mips_save_reg)
@@ -10488,7 +10482,7 @@  umips_build_save_restore (mips_save_rest
 
   pattern = emit_insn (pattern);
   if (fn == mips_save_reg)
-    RTX_FRAME_RELATED_P (pattern) = 1;  
+    RTX_FRAME_RELATED_P (pattern) = 1;
 
   /* Adjust the last offset.  */
   *offset -= UNITS_PER_WORD * nregs;
@@ -10514,7 +10508,7 @@  mips_for_each_saved_gpr_and_fpr (HOST_WI
      the return register be stored at func+4, and also it allows us not to
      need a nop in the epilogue if at least one register is reloaded in
      addition to return address.  */
-  offset = cfun->machine->frame.gp_sp_offset - sp_offset;
+  offset = frame->gp_sp_offset - sp_offset;
   mask = frame->mask;
 
   if (TARGET_MICROMIPS)
@@ -17087,8 +17081,8 @@  mips_option_override (void)
 
   /* Now select the ISA mode.
 
-     Do all CPP-sensitive stuff in uncompressed mode;
-     We'll switch modes later if required.  */
+     Do all CPP-sensitive stuff in uncompressed mode; we'll switch modes
+     later if required.  */
   mips_set_compression_mode (0);
 }
 
@@ -17366,7 +17360,6 @@  umips_save_restore_pattern_p (bool save_
     {
       rtx set, reg, mem, this_base;
       HOST_WIDE_INT this_offset;
-      unsigned int this_regno;
 
       /* Check that we have a SET.  */
       set = XVECEXP (pattern, 0, n);
@@ -17414,7 +17407,8 @@  umips_save_restore_pattern_p (bool save_
 
   return false;
 }
-/* Return the assembly instruction for microMIPS lwm or swm.
+
+/* Return the assembly instruction for microMIPS LWM or SWM.
    SAVE_P and PATTERN are as for umips_save_restore_pattern_p.  */
 
 const char *
@@ -17424,7 +17418,7 @@  umips_output_save_restore (bool save_p,
   char *s;
   int n;
   HOST_WIDE_INT offset;
-  rtx base, mem, set, reg, last_set, last_reg;
+  rtx base, mem, set, last_set, last_reg;
 
   /* Parse the pattern.  */
   gcc_assert (umips_save_restore_pattern_p (save_p, pattern));
@@ -17434,7 +17428,6 @@  umips_output_save_restore (bool save_p,
   n = XVECLEN (pattern, 0);
 
   set = XVECEXP (pattern, 0, 0);
-  reg = save_p ? SET_SRC (set) : SET_DEST (set);
   mem = save_p ? SET_DEST (set) : SET_SRC (set);
   mips_split_plus (XEXP (mem, 0), &base, &offset);
 
@@ -17506,7 +17499,9 @@  umips_load_store_pair_p_1 (bool load_p,
   return true;
 }
 
-/* Return true if operands can be used in an LWP or SWP instruction.  */
+/* OPERANDS describes the operands to a pair of SETs, in the order
+   dest1, src1, dest2, src2.  Return true if the operands can be used
+   in an LWP or SWP instruction; LOAD_P says which.  */
 
 bool
 umips_load_store_pair_p (bool load_p, rtx *operands)
@@ -17537,8 +17532,9 @@  umips_load_store_pair_p (bool load_p, rt
   return false;
 }
 
-/* Return the assembly instruction for microMIPS lwp or swp.
-   LOAD_P is true for load.  */
+/* Return the assembly instruction for a microMIPS LWP or SWP in which
+   the first register is REG and the first memory slot is MEM.
+   LOAD_P is true for LWP.  */
 
 static void
 umips_output_load_store_pair_1 (bool load_p, rtx reg, rtx mem)
@@ -17551,6 +17547,9 @@  umips_output_load_store_pair_1 (bool loa
     output_asm_insn ("swp\t%0,%1", ops);
 }
 
+/* Output the assembly instruction for a microMIPS LWP or SWP instruction.
+   LOAD_P and OPERANDS are as for umips_load_store_pair_p.  */
+
 void
 umips_output_load_store_pair (bool load_p, rtx *operands)
 {
@@ -17569,7 +17568,7 @@  umips_output_load_store_pair (bool load_
       mem1 = operands[0];
       mem2 = operands[2];
     }
-   
+
   if (REGNO (reg2) == REGNO (reg1) + 1)
     {
       umips_output_load_store_pair_1 (load_p, reg1, mem1);
@@ -17588,12 +17587,12 @@  umips_movep_target_p (rtx reg1, rtx reg2
   int regno1, regno2, pair;
   unsigned int i;
   static const int match[8] = {
-    0x00000060,	/* 5, 6 */
-    0x000000a0,	/* 5, 7 */
-    0x000000c0,	/* 6, 7 */
-    0x00200010,	/* 4, 21 */
-    0x00400010,	/* 4, 22 */
-    0x00000030,	/* 4, 5 */
+    0x00000060, /* 5, 6 */
+    0x000000a0, /* 5, 7 */
+    0x000000c0, /* 6, 7 */
+    0x00200010, /* 4, 21 */
+    0x00400010, /* 4, 22 */
+    0x00000030, /* 4, 5 */
     0x00000050, /* 4, 6 */
     0x00000090  /* 4, 7 */
   };
@@ -17604,7 +17603,7 @@  umips_movep_target_p (rtx reg1, rtx reg2
   regno1 = REGNO (reg1);
   regno2 = REGNO (reg2);
 
-  if (!GP_REG_P (regno1)  || !GP_REG_P (regno2))
+  if (!GP_REG_P (regno1) || !GP_REG_P (regno2))
     return false;
 
   pair = (1 << regno1) | (1 << regno2);
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2013-02-21 20:03:53.632341352 +0000
+++ gcc/config/mips/mips.h	2013-02-21 20:04:23.070542151 +0000
@@ -1019,7 +1019,8 @@  #define ISA_HAS_DSPR2		(TARGET_DSPR2 &&
    and "addiu $4,$4,1".  */
 #define ISA_HAS_LOAD_DELAY	(ISA_MIPS1				\
 				 && !TARGET_MIPS3900			\
-				 && !TARGET_MIPS16)
+				 && !TARGET_MIPS16			\
+				 && !TARGET_MICROMIPS)
 
 /* Likewise mtc1 and mfc1.  */
 #define ISA_HAS_XFER_DELAY	(mips_isa <= 3			\
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md	2013-02-21 19:57:26.000000000 +0000
+++ gcc/config/mips/mips.md	2013-02-21 20:06:12.347267724 +0000
@@ -5471,7 +5471,7 @@  (define_insn "*branch_equality<mode>"
     return mips_output_conditional_branch (insn, operands,
 					   "%*b%C1z%:\t%2,%0",
 					   "%*b%N1z%:\t%2,%0");
-    
+
   return mips_output_conditional_branch (insn, operands,
 					 MIPS_BRANCH ("b%C1", "%2,%z3,%0"),
 					 MIPS_BRANCH ("b%N1", "%2,%z3,%0"));
Index: gcc/testsuite/gcc.target/mips/mips.exp
===================================================================
--- gcc/testsuite/gcc.target/mips/mips.exp	2013-02-21 20:03:53.632341352 +0000
+++ gcc/testsuite/gcc.target/mips/mips.exp	2013-02-21 20:04:23.071542158 +0000
@@ -817,6 +817,8 @@  proc mips-dg-finish {} {
 #            |                           |
 #         -mips16/-mflip-mips16       -mno-mips16
 #            |                           |
+#         -micromips                  -mno-micromips
+#            |                           |
 #         -mips3d                     -mno-mips3d
 #            |                           |
 #         -mpaired-single             -mno-paired-single
@@ -905,6 +907,8 @@  proc mips-dg-options { args } {
 
     # Handle dependencies between options on the left of the
     # dependency diagram.
+    mips_option_dependency options "-mips16" "-mno-micromips"
+    mips_option_dependency options "-mmicromips" "-mno-mips16"
     mips_option_dependency options "-mips3d" "-mpaired-single"
     mips_option_dependency options "-mpaired-single" "-mfp64"
     mips_option_dependency options "-mfp64" "-mhard-float"
Index: gcc/testsuite/gcc.target/mips/umips-lwp-1.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-1.c	2013-02-21 20:33:17.980173008 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4)
+{
+  int r5 = r4[0];
+  int r6 = r4[1];
+  r4[2] = r5 * r5;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tlwp\t\\\$5,0\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-2.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-2.c	2013-02-21 20:36:21.709519202 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4)
+{
+  int r5 = r4[0];
+  int r6 = r4[1];
+  r4[2] = r6 * r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tlwp\t\\\$5,0\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-3.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-3.c	2013-02-21 20:36:29.710578763 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4)
+{
+  int r5 = r4[511];
+  int r6 = r4[512];
+  r4[2] = r5 * r5;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tlwp\t\\\$5,2044\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-4.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-4.c	2013-02-21 20:36:37.533637002 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4)
+{
+  int r5 = r4[511];
+  int r6 = r4[512];
+  r4[2] = r6 * r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tlwp\t\\\$5,2044\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-5.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-5.c	2013-02-21 20:36:46.255701936 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4)
+{
+  int r5 = r4[512];
+  int r6 = r4[513];
+  r4[2] = r5 * r5;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler-not "\tlwp" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-6.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-6.c	2013-02-21 20:36:53.911758937 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4)
+{
+  int r5 = r4[512];
+  int r6 = r4[513];
+  r4[2] = r6 * r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[3]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler-not "\tlwp" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-7.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-7.c	2013-02-21 20:04:23.074542181 +0000
@@ -0,0 +1,41 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+f1 (int *r4, int dummy, int *other)
+{
+  int r5 = r4[1];
+  int newr4 = r4[0];
+  other[0] = r5 * r5;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r4asm asm ("$4") = newr4;
+    asm ("#foo" : "=m" (other[1]) : "d" (r4asm), "d" (r5asm));
+  }
+}
+
+void MICROMIPS
+f2 (int *r4, int dummy, int *other)
+{
+  int newr4 = r4[0];
+  int r5 = *(int *)(newr4 + 4);
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r4asm asm ("$4") = newr4;
+    asm ("#foo" : "=m" (other[0]) : "d" (r4asm), "d" (r5asm));
+  }
+}
+
+void MICROMIPS
+f3 (int dummy, int *r5, int *other)
+{
+  int newr5 = r5[1];
+  int r4 = *(int *)newr5;
+  {
+    register int r5asm asm ("$4") = r4;
+    register int r4asm asm ("$5") = newr5;
+    asm ("#foo" : "=m" (other[0]) : "d" (r4asm), "d" (r5asm));
+  }
+}
+
+/* { dg-final { scan-assembler-not "\tlwp" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-8.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-8.c	2013-02-21 20:04:23.074542181 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-mgp32 -fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+f1 (int dummy, int *r5, int *other)
+{
+  int r4 = r5[0];
+  int newr5 = r5[1];
+  other[0] = r4 * r4;
+  {
+    register int r5asm asm ("$4") = r4;
+    register int r4asm asm ("$5") = newr5;
+    asm ("#foo" : "=m" (other[1]) : "d" (r4asm), "d" (r5asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tlwp\t\\\$4,0\\(\\\$5\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-swp-1.c
===================================================================
--- gcc/testsuite/gcc.target/mips/umips-lwp-swp-1.c	2013-02-21 20:03:53.633341359 +0000
+++ /dev/null	2013-02-18 18:12:58.656083693 +0000
@@ -1,17 +0,0 @@ 
-/* Test that an SWP can be generated when the instruction order is reversed:
-   
-   ie.  ST $3, mem+4
-	ST $2, mem
-*/
-   
-/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
-/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
-/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
-/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
-
-void MICROMIPS
-foo (long long l1, long long *l2)
-{
-  *l2 = l1;
-}
-/* { dg-final { scan-assembler "\tswp\t\\\$4,0\\(\\\$6\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-lwp-swp-2.c
===================================================================
--- gcc/testsuite/gcc.target/mips/umips-lwp-swp-2.c	2013-02-21 20:03:53.633341359 +0000
+++ /dev/null	2013-02-18 18:12:58.656083693 +0000
@@ -1,176 +0,0 @@ 
-/* Test that an SWP can be generated when the instruction order is not reversed:
-   
-   ie.  ST $2, mem
-	ST $2, mem+4
-*/
-   
-/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
-/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
-
-#include <stdarg.h>
-
-void MICROMIPS s(int, ...);
-void MICROMIPS z(int, ...);
-void MICROMIPS c(int, ...);
-
-typedef int l[500];
-
-void
-MICROMIPS f (int n)
-{
-  int i;
-  l a0, a1, a2, a3, a4, a5, a6, a7, a8, a9;
-  l a10, a11, a12, a13, a14, a15, a16, a17, a18, a19;
-  l a20, a21, a22, a23, a24, a25, a26, a27, a28, a29;
-  l a30, a31, a32, a33, a34, a35, a36, a37, a38, a39;
-  int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
-  int i10, i11, i12, i13, i14, i15, i16, i17, i18, i19;
-  int i20, i21, i22, i23, i24, i25, i26, i27, i28, i29;
-  int i30, i31, i32, i33, i34, i35, i36, i37, i38, i39;
-
-  for (i = 0; i < n; i++)
-    {
-      s (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-	 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
-         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
-         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
-      i0 = a0[0];
-      i1 = a1[0];
-      i2 = a2[0];
-      i3 = a3[0];
-      i4 = a4[0];
-      i5 = a5[0];
-      i6 = a6[0];
-      i7 = a7[0];
-      i8 = a8[0];
-      i9 = a9[0];
-      i10 = a10[0];
-      i11 = a11[0];
-      i12 = a12[0];
-      i13 = a13[0];
-      i14 = a14[0];
-      i15 = a15[0];
-      i16 = a16[0];
-      i17 = a17[0];
-      i18 = a18[0];
-      i19 = a19[0];
-      i20 = a20[0];
-      i21 = a21[0];
-      i22 = a22[0];
-      i23 = a23[0];
-      i24 = a24[0];
-      i25 = a25[0];
-      i26 = a26[0];
-      i27 = a27[0];
-      i28 = a28[0];
-      i29 = a29[0];
-      i30 = a30[0];
-      i31 = a31[0];
-      i32 = a32[0];
-      i33 = a33[0];
-      i34 = a34[0];
-      i35 = a35[0];
-      i36 = a36[0];
-      i37 = a37[0];
-      i38 = a38[0];
-      i39 = a39[0];
-      z (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-	 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
-         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
-         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
-      a0[i0] = i0;
-      a1[i1] = i1;
-      a2[i2] = i2;
-      a3[i3] = i3;
-      a4[i4] = i4;
-      a5[i5] = i5;
-      a6[i6] = i6;
-      a7[i7] = i7;
-      a8[i8] = i8;
-      a9[i9] = i9;
-      a10[i10] = i10;
-      a11[i11] = i11;
-      a12[i12] = i12;
-      a13[i13] = i13;
-      a14[i14] = i14;
-      a15[i15] = i15;
-      a16[i16] = i16;
-      a17[i17] = i17;
-      a18[i18] = i18;
-      a19[i19] = i19;
-      a20[i20] = i20;
-      a21[i21] = i21;
-      a22[i22] = i22;
-      a23[i23] = i23;
-      a24[i24] = i24;
-      a25[i25] = i25;
-      a26[i26] = i26;
-      a27[i27] = i27;
-      a28[i28] = i28;
-      a29[i29] = i29;
-      a30[i30] = i30;
-      a31[i31] = i31;
-      a32[i32] = i32;
-      a33[i33] = i33;
-      a34[i34] = i34;
-      a35[i35] = i35;
-      a36[i36] = i36;
-      a37[i37] = i37;
-      a38[i38] = i38;
-      a39[i39] = i39;
-      c (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-	 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
-         a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
-         a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
-    }
-}
-
-int
-MICROMIPS main ()
-{
-  f (1);
-}
-
-void
-MICROMIPS s (int n, ...)
-{
-  va_list list;
-
-  va_start (list, n);
-  while (n--)
-    {
-      int *a = va_arg (list, int *);
-      a[0] = n;
-    }
-  va_end (list);
-}
-
-void
-MICROMIPS z (int n, ...)
-{
-  va_list list;
-
-  va_start (list, n);
-  while (n--)
-    {
-      int *a = va_arg (list, int *);
-      __builtin_memset (a, 0, sizeof (l));
-    }
-  va_end (list);
-}
-
-void
-MICROMIPS c (int n, ...)
-{
-  va_list list;
-
-  va_start (list, n);
-  while (n--)
-    {
-      int *a = va_arg (list, int *);
-      if (a[n] != n)
-	;
-    }
-  va_end (list);
-}
-/* { dg-final { scan-assembler "\tswp" } } */
Index: gcc/testsuite/gcc.target/mips/umips-lwp-swp-volatile.c
===================================================================
--- gcc/testsuite/gcc.target/mips/umips-lwp-swp-volatile.c	2013-02-21 19:57:47.000000000 +0000
+++ gcc/testsuite/gcc.target/mips/umips-lwp-swp-volatile.c	2013-02-21 20:04:49.560724491 +0000
@@ -2,8 +2,8 @@ 
 /* { dg-options "-mmicromips" } */
 
 /* This test ensures that we do not generate microMIPS SWP or LWP
-   instructions when any component of the accessed memory is volatile; 
-   they are unsafe for such since they might cause replay of partial 
+   instructions when any component of the accessed memory is volatile;
+   they are unsafe for such since they might cause replay of partial
    accesses if interrupted by an exception.  */
 
 static void set_csr (volatile void *p, int v)
Index: gcc/testsuite/gcc.target/mips/umips-movep-2.c
===================================================================
--- gcc/testsuite/gcc.target/mips/umips-movep-2.c	2013-02-21 20:03:53.632341352 +0000
+++ gcc/testsuite/gcc.target/mips/umips-movep-2.c	2013-02-21 20:42:40.247604192 +0000
@@ -1,12 +1,13 @@ 
 /* Check that we can generate the MOVEP instruction.  */
-/* { dg-options "-fpeephole2 (-mmicromips)" } */
+/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 
 int bar (int, int);
 
-int
+int MICROMIPS
 foo (int n, int a)
 {
   return bar (0, 0);
 }
-/* { dg-final { scan-assembler "\tmovep\t" } } */
+
+/* { dg-final { scan-assembler "\tmovep\t\\\$4,\\\$5,\\\$0,\\\$0" } } */
Index: gcc/testsuite/gcc.target/mips/umips-save-restore-1.c
===================================================================
--- gcc/testsuite/gcc.target/mips/umips-save-restore-1.c	2013-02-21 19:57:47.000000000 +0000
+++ gcc/testsuite/gcc.target/mips/umips-save-restore-1.c	2013-02-21 20:06:37.807422840 +0000
@@ -5,7 +5,7 @@ 
 int bar (int, int, int, int, int);
 
 MICROMIPS int
-foo (int n, int a, int b, int c, int d) 
+foo (int n, int a, int b, int c, int d)
 {
   int i, j;
 
Index: gcc/testsuite/gcc.target/mips/umips-swp-1.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-1.c	2013-02-21 20:04:23.075542188 +0000
@@ -0,0 +1,10 @@ 
+/* { dg-options "-fpeephole2 -mgp32 (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (long long l1, long long *l2)
+{
+  *l2 = l1;
+}
+
+/* { dg-final { scan-assembler "\tswp\t\\\$4,0\\(\\\$6\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-swp-2.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-2.c	2013-02-21 20:40:04.431076334 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4, int r5, int r6)
+{
+  r6 *= r6;
+  r4[0] = r5;
+  r4[1] = r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tswp\t\\\$5,0\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-swp-3.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-3.c	2013-02-21 20:40:16.614164109 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4, int r5, int r6)
+{
+  r5 *= r5;
+  r4[0] = r5;
+  r4[1] = r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tswp\t\\\$5,0\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-swp-4.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-4.c	2013-02-21 20:40:21.540184989 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4, int r5, int r6)
+{
+  r6 *= r6;
+  r4[511] = r5;
+  r4[512] = r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tswp\t\\\$5,2044\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-swp-5.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-5.c	2013-02-21 20:40:28.131170677 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4, int r5, int r6)
+{
+  r5 *= r5;
+  r4[511] = r5;
+  r4[512] = r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler "\tswp\t\\\$5,2044\\(\\\$4\\)" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-swp-6.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-6.c	2013-02-21 20:40:33.757163423 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4, int r5, int r6)
+{
+  r6 *= r6;
+  r4[512] = r5;
+  r4[513] = r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler-not "\tswp" } }*/
Index: gcc/testsuite/gcc.target/mips/umips-swp-7.c
===================================================================
--- /dev/null	2013-02-18 18:12:58.656083693 +0000
+++ gcc/testsuite/gcc.target/mips/umips-swp-7.c	2013-02-21 20:40:38.486160549 +0000
@@ -0,0 +1,17 @@ 
+/* { dg-options "-fpeephole2 -mtune=m14k (-mmicromips)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+void MICROMIPS
+foo (int *r4, int r5, int r6)
+{
+  r5 *= r5;
+  r4[512] = r5;
+  r4[513] = r6;
+  {
+    register int r5asm asm ("$5") = r5;
+    register int r6asm asm ("$6") = r6;
+    asm ("#foo" : "=m" (r4[2]) : "d" (r5asm), "d" (r6asm));
+  }
+}
+
+/* { dg-final { scan-assembler-not "\tswp" } }*/