public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch] Add microMIPS jraddiusp support
@ 2013-03-04 23:08 Moore, Catherine
  2013-03-05 21:10 ` Richard Sandiford
  0 siblings, 1 reply; 7+ messages in thread
From: Moore, Catherine @ 2013-03-04 23:08 UTC (permalink / raw)
  To: rdsandiford; +Cc: gcc-patches, Moore, Catherine, Rozycki, Maciej

[-- Attachment #1: Type: text/plain, Size: 545 bytes --]

Hi Richard,
This patch adds support for the microMIPS jraddiusp instruction to the base microMIPS base.
Is this okay to commit?
Thanks,
Catherine

2013-03-04  Catherine Moore  <clm@codesourcery.com>

	* config/mips/micromips.md (mips_jraddiusp): New insn.
	* config/mips/mips.c (mips_expand_epilogue): Generate JRADDIUSP.

2013-03-04  Catherine Moore  <clm@codesourcery.com>

	* gcc.target/mips/umips-jraddiusp-1.c: New test.
	* gcc.target/mips/umips-jraddiusp-2.c: Likewise.
	* gcc.target/mips/umips-jraddiusp-3.c: Likewise



[-- Attachment #2: jraddiusp.patch --]
[-- Type: application/octet-stream, Size: 5046 bytes --]

Index: testsuite/gcc.target/mips/umips-jraddiusp-1.c
===================================================================
--- testsuite/gcc.target/mips/umips-jraddiusp-1.c	(revision 0)
+++ testsuite/gcc.target/mips/umips-jraddiusp-1.c	(revision 0)
@@ -0,0 +1,15 @@
+/* Check that we can use the jraddiusp instruction.  */
+/* { dg-options "-mabi=32 (-mmicromips)" } */
+
+int bar (int);
+
+MICROMIPS int
+foo (int n, int a, int b, int c, int d)
+{
+  int i, j;
+  i = bar (n);
+  j = bar (n);
+  return i + j;
+}
+
+/* { dg-final { scan-assembler "\tjraddiusp\t32" } } */
Index: testsuite/gcc.target/mips/umips-jraddiusp-2.c
===================================================================
--- testsuite/gcc.target/mips/umips-jraddiusp-2.c	(revision 0)
+++ testsuite/gcc.target/mips/umips-jraddiusp-2.c	(revision 0)
@@ -0,0 +1,23 @@
+/* Check that we do not use the jraddiusp instruction for large frames.  */
+/* { dg-options "-mabi=32 (-mmicromips)" } */
+
+int bar (int);
+
+MICROMIPS int
+foo (int n, int a, int b, int c, int d)
+{
+  int i, j = 0;
+  int temp[150];
+  for (i = 0; i < 150; i++)
+    temp[i] = bar (n);
+
+  for (i = 0; i < 150; i++)
+    temp[i] += bar (temp[i]);
+
+  for (i = 0; i < 150; i++)
+    j += temp[i];
+
+  return j;
+}
+
+/* { dg-final { scan-assembler-not "\tjraddiusp" } } */
Index: testsuite/gcc.target/mips/umips-jraddiusp-3.c
===================================================================
--- testsuite/gcc.target/mips/umips-jraddiusp-3.c	(revision 0)
+++ testsuite/gcc.target/mips/umips-jraddiusp-3.c	(revision 0)
@@ -0,0 +1,13 @@
+/* Check that we do not use the jraddisup instruction in a __builtin_eh_return
+   function.  */
+/* { dg-options "-mabi=32 (-mmicromips)" } */
+
+void bar (void);
+
+MICROMIPS void
+foo (int x)
+{
+  __builtin_unwind_init ();
+  __builtin_eh_return (x, bar);
+}
+/* { dg-final { scan-assembler-not "\tjraddiusp" } } */
Index: config/mips/micromips.md
===================================================================
--- config/mips/micromips.md	(revision 196341)
+++ config/mips/micromips.md	(working copy)
@@ -95,6 +95,19 @@
    (set_attr "mode" "SI")
    (set_attr "can_delay" "no")])
 
+;; For JRADDIUSP.
+(define_insn "jraddiusp"
+  [(parallel [(return)
+              (use (reg:SI 31))
+	      (set (reg:SI 29)
+		   (plus:SI (reg:SI 29)
+			    (match_operand 0 "const_int_operand")))])]
+  "TARGET_MICROMIPS"
+  "jraddiusp\t%0"
+  [(set_attr "type"	"trap")
+   (set_attr "can_delay" "no")
+   (set_attr "mode"	"SI")])
+
 ;; For MOVEP.
 (define_peephole2
   [(set (match_operand:MOVEP1 0 "register_operand" "")
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c	(revision 196341)
+++ config/mips/mips.c	(working copy)
@@ -11364,6 +11364,7 @@
   const struct mips_frame_info *frame;
   HOST_WIDE_INT step1, step2;
   rtx base, adjust, insn;
+  bool use_jraddiusp_p = false;
 
   if (!sibcall_p && mips_can_use_return_insn ())
     {
@@ -11453,6 +11454,14 @@
       mips_for_each_saved_gpr_and_fpr (frame->total_size - step2,
 				       mips_restore_reg);
 
+      /* Check if we can use JRADDIUSP.  */
+      use_jraddiusp_p = (TARGET_MICROMIPS
+			 && !crtl->calls_eh_return
+			 && !sibcall_p
+			 && step2 > 0
+			 && (step2 & 3) == 0
+			 && step2 <= (31 << 2));
+
       if (cfun->machine->interrupt_handler_p)
 	{
 	  HOST_WIDE_INT offset;
@@ -11480,8 +11489,9 @@
 	  mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM), mem);
 	  offset -= UNITS_PER_WORD;
 
-	  /* If we don't use shadow register set, we need to update SP.  */
-	  if (!cfun->machine->use_shadow_register_set_p)
+	  /* If we don't use shadow register set or the microMIPS
+             JRADDIUSP insn, we need to update SP.  */
+	  if (!cfun->machine->use_shadow_register_set_p && !use_jraddiusp_p)
 	    mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
 	  else
 	    /* The choice of position is somewhat arbitrary in this case.  */
@@ -11492,11 +11502,14 @@
 				    gen_rtx_REG (SImode, K0_REG_NUM)));
 	}
       else
-	/* Deallocate the final bit of the frame.  */
-	mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
+	/* Deallocate the final bit of the frame unless using the microMIPS
+           JRADDIUSP insn.  */
+	if (!use_jraddiusp_p)
+	  mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
     }
 
-  gcc_assert (!mips_epilogue.cfa_restores);
+  if (!use_jraddiusp_p)
+    gcc_assert (!mips_epilogue.cfa_restores);
 
   /* Add in the __builtin_eh_return stack adjustment.  We need to
      use a temporary in MIPS16 code.  */
@@ -11546,6 +11559,8 @@
 	      rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
 	      pat = gen_return_internal (reg);
 	    }
+	  else if (use_jraddiusp_p)
+	    pat = gen_jraddiusp (GEN_INT (step2));
 	  else
 	    {
 	      rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);

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

* Re: [Patch] Add microMIPS jraddiusp support
  2013-03-04 23:08 [Patch] Add microMIPS jraddiusp support Moore, Catherine
@ 2013-03-05 21:10 ` Richard Sandiford
  2013-03-14 21:07   ` Moore, Catherine
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Sandiford @ 2013-03-05 21:10 UTC (permalink / raw)
  To: Moore, Catherine; +Cc: gcc-patches, Rozycki, Maciej

"Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> Index: config/mips/micromips.md
> ===================================================================
> --- config/mips/micromips.md	(revision 196341)
> +++ config/mips/micromips.md	(working copy)
> @@ -95,6 +95,19 @@
>     (set_attr "mode" "SI")
>     (set_attr "can_delay" "no")])
>  
> +;; For JRADDIUSP.
> +(define_insn "jraddiusp"
> +  [(parallel [(return)
> +              (use (reg:SI 31))
> +	      (set (reg:SI 29)
> +		   (plus:SI (reg:SI 29)
> +			    (match_operand 0 "const_int_operand")))])]

Since this is a generic pattern (not depending on UNSPECs, etc.),
I think we should use a specific predicate instead of const_int_operand.
From the suggestion in the thread about addition, this would be a "uw5",
i.e. uw5_operand.

> Index: config/mips/mips.c
> ===================================================================
> --- config/mips/mips.c	(revision 196341)
> +++ config/mips/mips.c	(working copy)
> @@ -11364,6 +11364,7 @@
>    const struct mips_frame_info *frame;
>    HOST_WIDE_INT step1, step2;
>    rtx base, adjust, insn;
> +  bool use_jraddiusp_p = false;
>  
>    if (!sibcall_p && mips_can_use_return_insn ())
>      {
> @@ -11453,6 +11454,14 @@
>        mips_for_each_saved_gpr_and_fpr (frame->total_size - step2,
>  				       mips_restore_reg);
>  
> +      /* Check if we can use JRADDIUSP.  */
> +      use_jraddiusp_p = (TARGET_MICROMIPS
> +			 && !crtl->calls_eh_return
> +			 && !sibcall_p
> +			 && step2 > 0
> +			 && (step2 & 3) == 0
> +			 && step2 <= (31 << 2));
> +
>        if (cfun->machine->interrupt_handler_p)
>  	{
>  	  HOST_WIDE_INT offset;
> @@ -11480,8 +11489,9 @@
>  	  mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM), mem);
>  	  offset -= UNITS_PER_WORD;
>  
> -	  /* If we don't use shadow register set, we need to update SP.  */
> -	  if (!cfun->machine->use_shadow_register_set_p)
> +	  /* If we don't use shadow register set or the microMIPS
> +             JRADDIUSP insn, we need to update SP.  */
> +	  if (!cfun->machine->use_shadow_register_set_p && !use_jraddiusp_p)
>  	    mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
>  	  else
>  	    /* The choice of position is somewhat arbitrary in this case.  */

We shouldn't use JRADDIUSP in an interrupt handler, so I think it would
be better to move the use_jraddiusp_p condition into the else branch and
drop the hunk above.

> @@ -11492,11 +11502,14 @@
>  				    gen_rtx_REG (SImode, K0_REG_NUM)));
>  	}
>        else
> -	/* Deallocate the final bit of the frame.  */
> -	mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
> +	/* Deallocate the final bit of the frame unless using the microMIPS
> +           JRADDIUSP insn.  */
> +	if (!use_jraddiusp_p)
> +	  mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
>      }
>  
> -  gcc_assert (!mips_epilogue.cfa_restores);
> +  if (!use_jraddiusp_p)
> +    gcc_assert (!mips_epilogue.cfa_restores);

We still need to emit the CFA restores somewhere.  Something like:

	else if (TARGET_MICROMIPS
		 && !crtl->calls_eh_return
		 && !sibcall_p
		 && step2 > 0
		 && mips_unsigned_immediate_p (step2, 5, 2))
	  {
	    /* We can deallocate the stack and jump to $31 using JRADDIUSP.
	       Emit the CFA restores immediately before the deallocation.  */
	    use_jraddisup_p = true;
	    mips_epilogue_emit_cfa_restores ();
	  }
	else
	  /* Deallocate the final bit of the frame.  */
	  mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);

where mips_unsigned_immediate_p comes from the other thread.

Thanks,
Richard

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

* RE: [Patch] Add microMIPS jraddiusp support
  2013-03-05 21:10 ` Richard Sandiford
@ 2013-03-14 21:07   ` Moore, Catherine
  2013-03-14 21:38     ` Richard Sandiford
  0 siblings, 1 reply; 7+ messages in thread
From: Moore, Catherine @ 2013-03-14 21:07 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches, Rozycki, Maciej

[-- Attachment #1: Type: text/plain, Size: 5886 bytes --]

Hi Richard,

I updated this patch using your suggestions.  I'm having a problem though, that I'm having trouble nailing.  Building libstdc++ for microMIPS is failing trying to generate dwarf2 CFI info:

_Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)
Analyzing compilation unit
Performing interprocedural optimizations
 <*free_lang_data> <visibility> <early_local_cleanups> <*free_inline_summary> <whole-program> <profile_estimate> <cp> <inline> <pure-const> <static-var>Assembling functions:
 _Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)
mm.cc: In function '_Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)':
mm.cc:34:1: internal compiler error: in maybe_record_trace_start, at dwarf2cfi.c:2209
0x8570656 maybe_record_trace_start
        /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2209
0x857113f create_trace_edges
        /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2301
0x8572505 scan_trace
        /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2514
0x85726b3 create_cfi_notes
        /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2540
0x8572703 execute_dwarf2_frame
        /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2897
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://support.codesourcery.com/GNUToolchain/> for instructions.

I've attached a testcase hoping that you might have some ideas.   I plan to keep debugging in the meanwhile.  I was able to reproduce with ./cc1plus -mmicromips -Os mm.ii.

Thanks,
Catherine


> -----Original Message-----
> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: Tuesday, March 05, 2013 4:10 PM
> To: Moore, Catherine
> Cc: gcc-patches@gcc.gnu.org; Rozycki, Maciej
> Subject: Re: [Patch] Add microMIPS jraddiusp support
> 
> "Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> > Index: config/mips/micromips.md
> >
> ==========================================================
> =========
> > --- config/mips/micromips.md	(revision 196341)
> > +++ config/mips/micromips.md	(working copy)
> > @@ -95,6 +95,19 @@
> >     (set_attr "mode" "SI")
> >     (set_attr "can_delay" "no")])
> >
> > +;; For JRADDIUSP.
> > +(define_insn "jraddiusp"
> > +  [(parallel [(return)
> > +              (use (reg:SI 31))
> > +	      (set (reg:SI 29)
> > +		   (plus:SI (reg:SI 29)
> > +			    (match_operand 0 "const_int_operand")))])]
> 
> Since this is a generic pattern (not depending on UNSPECs, etc.), I think we
> should use a specific predicate instead of const_int_operand.
> From the suggestion in the thread about addition, this would be a "uw5", i.e.
> uw5_operand.
> 
> > Index: config/mips/mips.c
> >
> ==========================================================
> =========
> > --- config/mips/mips.c	(revision 196341)
> > +++ config/mips/mips.c	(working copy)
> > @@ -11364,6 +11364,7 @@
> >    const struct mips_frame_info *frame;
> >    HOST_WIDE_INT step1, step2;
> >    rtx base, adjust, insn;
> > +  bool use_jraddiusp_p = false;
> >
> >    if (!sibcall_p && mips_can_use_return_insn ())
> >      {
> > @@ -11453,6 +11454,14 @@
> >        mips_for_each_saved_gpr_and_fpr (frame->total_size - step2,
> >  				       mips_restore_reg);
> >
> > +      /* Check if we can use JRADDIUSP.  */
> > +      use_jraddiusp_p = (TARGET_MICROMIPS
> > +			 && !crtl->calls_eh_return
> > +			 && !sibcall_p
> > +			 && step2 > 0
> > +			 && (step2 & 3) == 0
> > +			 && step2 <= (31 << 2));
> > +
> >        if (cfun->machine->interrupt_handler_p)
> >  	{
> >  	  HOST_WIDE_INT offset;
> > @@ -11480,8 +11489,9 @@
> >  	  mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM),
> mem);
> >  	  offset -= UNITS_PER_WORD;
> >
> > -	  /* If we don't use shadow register set, we need to update SP.  */
> > -	  if (!cfun->machine->use_shadow_register_set_p)
> > +	  /* If we don't use shadow register set or the microMIPS
> > +             JRADDIUSP insn, we need to update SP.  */
> > +	  if (!cfun->machine->use_shadow_register_set_p &&
> !use_jraddiusp_p)
> >  	    mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
> >  	  else
> >  	    /* The choice of position is somewhat arbitrary in this case.
> > */
> 
> We shouldn't use JRADDIUSP in an interrupt handler, so I think it would be
> better to move the use_jraddiusp_p condition into the else branch and drop
> the hunk above.
> 
> > @@ -11492,11 +11502,14 @@
> >  				    gen_rtx_REG (SImode, K0_REG_NUM)));
> >  	}
> >        else
> > -	/* Deallocate the final bit of the frame.  */
> > -	mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
> > +	/* Deallocate the final bit of the frame unless using the microMIPS
> > +           JRADDIUSP insn.  */
> > +	if (!use_jraddiusp_p)
> > +	  mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
> >      }
> >
> > -  gcc_assert (!mips_epilogue.cfa_restores);
> > +  if (!use_jraddiusp_p)
> > +    gcc_assert (!mips_epilogue.cfa_restores);
> 
> We still need to emit the CFA restores somewhere.  Something like:
> 
> 	else if (TARGET_MICROMIPS
> 		 && !crtl->calls_eh_return
> 		 && !sibcall_p
> 		 && step2 > 0
> 		 && mips_unsigned_immediate_p (step2, 5, 2))
> 	  {
> 	    /* We can deallocate the stack and jump to $31 using JRADDIUSP.
> 	       Emit the CFA restores immediately before the deallocation.  */
> 	    use_jraddisup_p = true;
> 	    mips_epilogue_emit_cfa_restores ();
> 	  }
> 	else
> 	  /* Deallocate the final bit of the frame.  */
> 	  mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
> 
> where mips_unsigned_immediate_p comes from the other thread.
> 
> Thanks,
> Richard

[-- Attachment #2: jraddiusp.patch --]
[-- Type: application/octet-stream, Size: 6105 bytes --]

Index: testsuite/gcc.target/mips/umips-jraddiusp-1.c
===================================================================
--- testsuite/gcc.target/mips/umips-jraddiusp-1.c	(revision 0)
+++ testsuite/gcc.target/mips/umips-jraddiusp-1.c	(revision 0)
@@ -0,0 +1,15 @@
+/* Check that we can use the jraddiusp instruction.  */
+/* { dg-options "-mabi=32 (-mmicromips)" } */
+
+int bar (int);
+
+MICROMIPS int
+foo (int n, int a, int b, int c, int d)
+{
+  int i, j;
+  i = bar (n);
+  j = bar (n);
+  return i + j;
+}
+
+/* { dg-final { scan-assembler "\tjraddiusp\t32" } } */
Index: testsuite/gcc.target/mips/umips-jraddiusp-2.c
===================================================================
--- testsuite/gcc.target/mips/umips-jraddiusp-2.c	(revision 0)
+++ testsuite/gcc.target/mips/umips-jraddiusp-2.c	(revision 0)
@@ -0,0 +1,23 @@
+/* Check that we do not use the jraddiusp instruction for large frames.  */
+/* { dg-options "-mabi=32 (-mmicromips)" } */
+
+int bar (int);
+
+MICROMIPS int
+foo (int n, int a, int b, int c, int d)
+{
+  int i, j = 0;
+  int temp[150];
+  for (i = 0; i < 150; i++)
+    temp[i] = bar (n);
+
+  for (i = 0; i < 150; i++)
+    temp[i] += bar (temp[i]);
+
+  for (i = 0; i < 150; i++)
+    j += temp[i];
+
+  return j;
+}
+
+/* { dg-final { scan-assembler-not "\tjraddiusp" } } */
Index: testsuite/gcc.target/mips/umips-jraddiusp-3.c
===================================================================
--- testsuite/gcc.target/mips/umips-jraddiusp-3.c	(revision 0)
+++ testsuite/gcc.target/mips/umips-jraddiusp-3.c	(revision 0)
@@ -0,0 +1,13 @@
+/* Check that we do not use the jraddisup instruction in a __builtin_eh_return
+   function.  */
+/* { dg-options "-mabi=32 (-mmicromips)" } */
+
+void bar (void);
+
+MICROMIPS void
+foo (int x)
+{
+  __builtin_unwind_init ();
+  __builtin_eh_return (x, bar);
+}
+/* { dg-final { scan-assembler-not "\tjraddiusp" } } */
Index: config/mips/micromips.md
===================================================================
--- config/mips/micromips.md	(revision 196341)
+++ config/mips/micromips.md	(working copy)
@@ -95,6 +95,19 @@
    (set_attr "mode" "SI")
    (set_attr "can_delay" "no")])
 
+;; For JRADDIUSP.
+(define_insn "jraddiusp"
+  [(parallel [(return)
+	      (use (reg:SI 31))
+	      (set (reg:SI 29)
+		   (plus:SI (reg:SI 29)
+			    (match_operand 0 "Uuw05_operand")))])]
+  "TARGET_MICROMIPS"
+  "jraddiusp\t%0"
+  [(set_attr "type"	"trap")
+   (set_attr "can_delay" "no")
+   (set_attr "mode"	"SI")])
+
 ;; For MOVEP.
 (define_peephole2
   [(set (match_operand:MOVEP1 0 "register_operand" "")
Index: config/mips/predicates.md
===================================================================
--- config/mips/predicates.md	(revision 196341)
+++ config/mips/predicates.md	(working copy)
@@ -131,6 +131,10 @@
   (ior (match_operand 0 "const_0_operand")
        (match_operand 0 "movep_src_register")))
 
+(define_predicate "Uuw05_operand"
+  (and (match_code "const_int")
+       (match_test "mips_unsigned_immediate_p (INTVAL (op), 5, 2)")))
+
 (define_predicate "lo_operand"
   (and (match_code "reg")
        (match_test "REGNO (op) == LO_REGNUM")))
Index: config/mips/mips-protos.h
===================================================================
--- config/mips/mips-protos.h	(revision 196341)
+++ config/mips/mips-protos.h	(working copy)
@@ -350,6 +350,9 @@ extern void mips_expand_vec_reduc (rtx, rtx, rtx (
 extern void mips_expand_vec_minmax (rtx, rtx, rtx,
 				    rtx (*) (rtx, rtx, rtx), bool);
 
+extern bool mips_signed_immediate_p (unsigned HOST_WIDE_INT, int, int);
+extern bool mips_unsigned_immediate_p (unsigned HOST_WIDE_INT, int, int);
+
 extern const char *umips_output_save_restore (bool, rtx);
 extern bool umips_save_restore_pattern_p (bool, rtx);
 extern bool umips_load_store_pair_p (bool, rtx *);
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c	(revision 196341)
+++ config/mips/mips.c	(working copy)
@@ -2377,6 +2377,25 @@ mips_address_insns (rtx x, enum machine_mode mode,
   return 0;
 }
 
+/* Return true if X fits within an unsigned field of BITS bits that is
+   shifted left SHIFT bits before being used.  */
+
+bool
+mips_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits, int shift = 0)
+{
+  return (x & ((1 << shift) - 1)) == 0 && x < (1 << (shift + bits));
+}
+
+/* Return true if X fits within a signed field of  BITS bits that is
+   shifted left SHIFT bits before being used.  */
+
+bool
+mips_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits, int shift = 0)
+{
+ x += 1 << (bits + shift - 1);
+ return mips_unsigned_immediate_p (x, bits, shift);
+}
+
 /* Return true if X is a legitimate address with a 12-bit offset.
    MODE is the mode of the value being accessed.  */
 
@@ -11364,6 +11383,7 @@ mips_expand_epilogue (bool sibcall_p)
   const struct mips_frame_info *frame;
   HOST_WIDE_INT step1, step2;
   rtx base, adjust, insn;
+  bool use_jraddiusp_p = false;
 
   if (!sibcall_p && mips_can_use_return_insn ())
     {
@@ -11491,6 +11511,15 @@ mips_expand_epilogue (bool sibcall_p)
 	  emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM),
 				    gen_rtx_REG (SImode, K0_REG_NUM)));
 	}
+      else if (TARGET_MICROMIPS
+	       && !crtl->calls_eh_return
+	       && !sibcall_p
+	       && step2 > 0
+	       && mips_unsigned_immediate_p (step2, 5, 2))
+	{
+	  use_jraddiusp_p = true;
+	  mips_epilogue_emit_cfa_restores ();
+	}
       else
 	/* Deallocate the final bit of the frame.  */
 	mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
@@ -11546,6 +11575,8 @@ mips_expand_epilogue (bool sibcall_p)
 	      rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
 	      pat = gen_return_internal (reg);
 	    }
+	  else if (use_jraddiusp_p)
+	    pat = gen_jraddiusp (GEN_INT (step2));
 	  else
 	    {
 	      rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);

[-- Attachment #3: jraddiusp.cl --]
[-- Type: application/octet-stream, Size: 577 bytes --]

2013-03-13  Catherine Moore  <clm@codesourcery.com>

	* config/mips/micromips.md (mips_jraddiusp): New insn.
	* config/mips/mips.c (mips_signed_immediate_p): New.
	(mips_unsigned_immediate_p): New.
	(mips_expand_epilogue): Generate JRADDIUSP.
	* config/mips/predicates.md (Uuw05_operand): New predicate.
	* config/mips/mips-protos.h (mips_signed_immediate_p): New.
	(mips_unsigned_immediate_p): New.

	testsuite/
	* gcc.target/mips/umips-jraddiusp-1.c: New test.
	* gcc.target/mips/umips-jraddiusp-2.c: New test.
	* gcc.target/mips/umips-jraddiusp-3.c: New test.

[-- Attachment #4: mm.ii --]
[-- Type: application/octet-stream, Size: 1087 bytes --]

# 1 "mm.cc"
# 1 "/scratch/cmoore/umips-elf/obj/gcc-2012.09-999999-mips-sde-elf-i686-pc-linux-gnu/mips-sde-elf/micromips/libstdc++-v3/libsupc++//"
# 1 "<command-line>"
# 1 "mm.cc"
void abort (void) __attribute__ ((noreturn));
namespace std __attribute__ ((__visibility__ ("default")))
{
  using ::abort;

}
struct _Unwind_Context;
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *);
extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *);
extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *);

_Unwind_Ptr
base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
{
  if (encoding == 0xff)
    return 0;

  switch (encoding & 0x70)
    {
    case 0x00:
    case 0x10:
    case 0x50:
      return 0;

    case 0x20:
      return _Unwind_GetTextRelBase (context);
    case 0x30:
      return _Unwind_GetDataRelBase (context);
    case 0x40:
      return _Unwind_GetRegionStart (context);
    }
  std::abort ();
}

[-- Attachment #5: mm.ii.240r.nothrow --]
[-- Type: application/octet-stream, Size: 17265 bytes --]


;; Function _Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*) (_Z21base_of_encoded_valuehP15_Unwind_Context, funcdef_no=0, decl_uid=1865, cgraph_uid=0)



_Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)

Dataflow summary:
;;  invalidated by call 	 0 [$0] 1 [$1] 2 [$2] 3 [$3] 4 [$4] 5 [$5] 6 [$6] 7 [$7] 8 [$8] 9 [$9] 10 [$10] 11 [$11] 12 [$12] 13 [$13] 14 [$14] 15 [$15] 24 [$24] 25 [$25] 26 [$26] 27 [$27] 32 [$f0] 33 [$f1] 34 [$f2] 35 [$f3] 36 [$f4] 37 [$f5] 38 [$f6] 39 [$f7] 40 [$f8] 41 [$f9] 42 [$f10] 43 [$f11] 44 [$f12] 45 [$f13] 46 [$f14] 47 [$f15] 48 [$f16] 49 [$f17] 50 [$f18] 51 [$f19] 64 [hi] 65 [lo] 66 [] 67 [$fcc0] 68 [$fcc1] 69 [$fcc2] 70 [$fcc3] 71 [$fcc4] 72 [$fcc5] 73 [$fcc6] 74 [$fcc7] 75 [] 76 [$cprestore] 176 [$ac1hi] 177 [$ac1lo] 178 [$ac2hi] 179 [$ac2lo] 180 [$ac3hi] 181 [$ac3lo]
;;  hardware regs used 	 29 [$sp]
;;  regular block artificial uses 	 29 [$sp]
;;  eh block artificial uses 	 29 [$sp] 77 [$arg]
;;  entry block defs 	 4 [$4] 5 [$5] 6 [$6] 7 [$7] 29 [$sp] 31 [$31] 44 [$f12] 45 [$f13] 46 [$f14] 47 [$f15]
;;  exit block uses 	 2 [$2] 28 [$28] 29 [$sp] 31 [$31]
;;  regs ever live 	 2[$2] 3[$3] 4[$4] 5[$5] 29[$sp] 31[$31]
;;  ref usage 	r0={4d} r1={4d} r2={6d,8u,5e} r3={6d,7u} r4={9d,6u,1e} r5={5d,3u} r6={5d} r7={5d} r8={4d} r9={4d} r10={4d} r11={4d} r12={4d} r13={4d} r14={4d} r15={4d} r24={4d} r25={4d} r26={4d} r27={4d} r28={1u} r29={3d,30u} r31={5d,2u} r32={4d} r33={4d} r34={4d} r35={4d} r36={4d} r37={4d} r38={4d} r39={4d} r40={4d} r41={4d} r42={4d} r43={4d} r44={5d} r45={5d} r46={5d} r47={5d} r48={4d} r49={4d} r50={4d} r51={4d} r64={4d} r65={4d} r66={4d} r67={4d} r68={4d} r69={4d} r70={4d} r71={4d} r72={4d} r73={4d} r74={4d} r75={4d} r76={4d} r176={4d} r177={4d} r178={4d} r179={4d} r180={4d} r181={4d} 
;;    total ref usage 323{260d,57u,6e} in 31{30 regular + 1 call} insns.
(note 1 0 13 NOTE_INSN_DELETED)
(note 13 1 7 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 7 13 10 NOTE_INSN_DELETED)
(note 10 7 100 NOTE_INSN_FUNCTION_BEG)
(insn/f 100 10 8 (set (reg/f:SI 29 $sp)
        (plus:SI (reg/f:SI 29 $sp)
            (const_int -24 [0xffffffffffffffe8]))) mm.cc:15 11 {*addsi3}
     (nil))
(insn 8 100 15 (set (reg/v:SI 4 $4 [orig:197 encoding+-3 ] [197])
        (zero_extend:SI (reg:QI 4 $4 [ encoding ]))) mm.cc:15 186 {*zero_extendqisi2}
     (nil))
(insn 15 8 101 (set (reg:SI 3 $3 [200])
        (const_int 255 [0xff])) mm.cc:16 283 {*movsi_internal}
     (expr_list:REG_EQUIV (const_int 255 [0xff])
        (nil)))
(insn 101 15 103 (clobber (mem/c:BLK (reg/f:SI 29 $sp) [3 A8])) mm.cc:15 -1
     (nil))
(note 103 101 141 NOTE_INSN_PROLOGUE_END)
(insn 141 103 17 (sequence [
            (jump_insn 16 103 102 (set (pc)
                    (if_then_else (eq (reg/v:SI 4 $4 [orig:197 encoding+-3 ] [197])
                            (reg:SI 3 $3 [200]))
                        (label_ref:SI 60)
                        (pc))) mm.cc:16 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [200])
                    (expr_list:REG_EQUAL (if_then_else (eq (reg/v:SI 4 $4 [orig:197 encoding+-3 ] [197])
                                (const_int 255 [0xff]))
                            (label_ref:SI 60)
                            (pc))
                        (expr_list:REG_BR_PROB (const_int 1991 [0x7c7])
                            (nil))))
             -> 60)
            (insn/f 102 16 17 (set (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                            (const_int 20 [0x14])) [3 S4 A32])
                    (reg:SI 31 $31)) 283 {*movsi_internal}
                 (expr_list:REG_FRAME_RELATED_EXPR (set/f (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                                (const_int 20 [0x14])) [3 S4 A32])
                        (reg:SI 31 $31))
                    (nil)))
        ]) mm.cc:16 -1
     (nil))
(note 17 141 18 [bb 3] NOTE_INSN_BASIC_BLOCK)
(note 18 17 19 NOTE_INSN_DELETED)
(insn 19 18 20 (set (reg:SI 2 $2 [202])
        (and:SI (reg/v:SI 4 $4 [orig:197 encoding+-3 ] [197])
            (const_int 112 [0x70]))) mm.cc:19 154 {*andsi3}
     (expr_list:REG_DEAD (reg/v:SI 4 $4 [orig:197 encoding+-3 ] [197])
        (nil)))
(insn 20 19 147 (set (reg:SI 3 $3 [203])
        (const_int 32 [0x20])) mm.cc:19 283 {*movsi_internal}
     (expr_list:REG_EQUIV (const_int 32 [0x20])
        (nil)))
(insn 147 20 77 (sequence [
            (jump_insn 21 20 22 (set (pc)
                    (if_then_else (eq (reg:SI 2 $2 [202])
                            (reg:SI 3 $3 [203]))
                        (label_ref 38)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [203])
                    (expr_list:REG_EQUAL (if_then_else (eq (reg:SI 2 $2 [202])
                                (const_int 32 [0x20]))
                            (label_ref:SI 38)
                            (pc))
                        (expr_list:REG_BR_PROB (const_int 2000 [0x7d0])
                            (nil))))
             -> 38)
            (insn 22 21 77 (set (reg:SI 3 $3 [204])
                    (leu:SI (reg:SI 2 $2 [202])
                        (const_int 32 [0x20]))) 513 {*sleu_sisi}
                 (nil))
        ]) mm.cc:19 -1
     (nil))
(note 77 147 149 [bb 4] NOTE_INSN_BASIC_BLOCK)
(insn 149 77 78 (sequence [
            (jump_insn 23 77 30 (set (pc)
                    (if_then_else (eq (reg:SI 3 $3 [204])
                            (const_int 0 [0]))
                        (label_ref 29)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [204])
                    (expr_list:REG_BR_PROB (const_int 7084 [0x1bac])
                        (nil)))
             -> 29)
            (insn/s 30 23 78 (set (reg:SI 3 $3 [206])
                    (const_int 64 [0x40])) 283 {*movsi_internal}
                 (expr_list:REG_EQUIV (const_int 64 [0x40])
                    (nil)))
        ]) mm.cc:19 -1
     (nil))
(note 78 149 151 [bb 5] NOTE_INSN_BASIC_BLOCK)
(insn 151 78 79 (sequence [
            (jump_insn 24 78 25 (set (pc)
                    (if_then_else (eq (reg:SI 2 $2 [202])
                            (const_int 0 [0]))
                        (label_ref:SI 60)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_BR_PROB (const_int 2856 [0xb28])
                    (nil))
             -> 60)
            (insn 25 24 79 (set (reg:SI 3 $3 [205])
                    (const_int 16 [0x10])) 283 {*movsi_internal}
                 (expr_list:REG_EQUIV (const_int 16 [0x10])
                    (nil)))
        ]) mm.cc:19 -1
     (nil))
(note 79 151 153 [bb 6] NOTE_INSN_BASIC_BLOCK)
(insn 153 79 124 (sequence [
            (jump_insn 26 79 142 (set (pc)
                    (if_then_else (ne (reg:SI 2 $2 [202])
                            (reg:SI 3 $3 [205]))
                        (label_ref:SI 56)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [205])
                    (expr_list:REG_DEAD (reg:SI 2 $2 [202])
                        (expr_list:REG_EQUAL (if_then_else (ne (reg:SI 2 $2 [202])
                                    (const_int 16 [0x10]))
                                (label_ref:SI 56)
                                (pc))
                            (expr_list:REG_BR_PROB (const_int 6002 [0x1772])
                                (nil)))))
             -> 56)
            (insn/f 142 26 124 (set (reg:SI 31 $31)
                    (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                            (const_int 20 [0x14])) [3 S4 A32])) 283 {*movsi_internal}
                 (expr_list:REG_CFA_RESTORE (reg:SI 31 $31)
                    (nil)))
        ]) mm.cc:19 -1
     (nil))
(note 124 153 162 [bb 7] NOTE_INSN_BASIC_BLOCK)
(insn 162 124 163 (sequence [
            (jump_insn 125 124 160 (set (pc)
                    (label_ref:SI 161)) 550 {*jump_absolute}
                 (nil)
             -> 161)
            (insn/s 160 125 163 (set (reg/i:SI 2 $2)
                    (const_int 0 [0])) 283 {*movsi_internal}
                 (nil))
        ]) mm.cc:34 -1
     (nil))
(barrier 163 162 29)
(code_label 29 163 81 5 "" [1 uses])
(note 81 29 155 [bb 8] NOTE_INSN_BASIC_BLOCK)
(insn 155 81 82 (sequence [
            (jump_insn 31 81 32 (set (pc)
                    (if_then_else (eq (reg:SI 2 $2 [202])
                            (reg:SI 3 $3 [206]))
                        (label_ref 50)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [206])
                    (expr_list:REG_EQUAL (if_then_else (eq (reg:SI 2 $2 [202])
                                (const_int 64 [0x40]))
                            (label_ref:SI 50)
                            (pc))
                        (expr_list:REG_BR_PROB (const_int 3530 [0xdca])
                            (nil))))
             -> 50)
            (insn 32 31 82 (set (reg:SI 3 $3 [207])
                    (const_int 80 [0x50])) 283 {*movsi_internal}
                 (expr_list:REG_EQUIV (const_int 80 [0x50])
                    (nil)))
        ]) mm.cc:19 -1
     (nil))
(note 82 155 157 [bb 9] NOTE_INSN_BASIC_BLOCK)
(insn 157 82 83 (sequence [
            (jump_insn 33 82 34 (set (pc)
                    (if_then_else (eq (reg:SI 2 $2 [202])
                            (reg:SI 3 $3 [207]))
                        (label_ref:SI 60)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [207])
                    (expr_list:REG_EQUAL (if_then_else (eq (reg:SI 2 $2 [202])
                                (const_int 80 [0x50]))
                            (label_ref:SI 60)
                            (pc))
                        (expr_list:REG_BR_PROB (const_int 1817 [0x719])
                            (nil))))
             -> 60)
            (insn 34 33 83 (set (reg:SI 3 $3 [208])
                    (const_int 48 [0x30])) 283 {*movsi_internal}
                 (expr_list:REG_EQUIV (const_int 48 [0x30])
                    (nil)))
        ]) mm.cc:19 -1
     (nil))
(note 83 157 159 [bb 10] NOTE_INSN_BASIC_BLOCK)
(insn 159 83 45 (sequence [
            (jump_insn 35 83 118 (set (pc)
                    (if_then_else (ne (reg:SI 2 $2 [202])
                            (reg:SI 3 $3 [208]))
                        (label_ref:SI 56)
                        (pc))) mm.cc:19 436 {*branch_equalitysi}
                 (expr_list:REG_DEAD (reg:SI 3 $3 [208])
                    (expr_list:REG_DEAD (reg:SI 2 $2 [202])
                        (expr_list:REG_EQUAL (if_then_else (ne (reg:SI 2 $2 [202])
                                    (const_int 48 [0x30]))
                                (label_ref:SI 56)
                                (pc))
                            (expr_list:REG_BR_PROB (const_int 4544 [0x11c0])
                                (nil)))))
             -> 56)
            (insn 118 35 45 (set (reg:SI 31 $31)
                    (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                            (const_int 20 [0x14])) [3 S4 A32])) 283 {*movsi_internal}
                 (nil))
        ]) mm.cc:19 -1
     (nil))
(note 45 159 127 [bb 11] NOTE_INSN_BASIC_BLOCK)
(note 127 45 46 NOTE_INSN_EPILOGUE_BEG)
(insn 46 127 119 (set (reg:SI 4 $4)
        (reg/v/f:SI 5 $5 [orig:199 context ] [199])) mm.cc:29 283 {*movsi_internal}
     (expr_list:REG_DEAD (reg/v/f:SI 5 $5 [orig:199 context ] [199])
        (nil)))
(insn 119 46 132 (clobber (mem/c:BLK (reg/f:SI 29 $sp) [3 A8])) mm.cc:34 -1
     (nil))
(insn 132 119 133 (sequence [
            (call_insn/j 47 119 120 (set (reg:SI 2 $2)
                    (call (mem:SI (symbol_ref:SI ("_Z22_Unwind_GetDataRelBaseP15_Unwind_Context") [flags 0x41]  <function_decl 0xf74dea80 _Unwind_GetDataRelBase>) [0 _Unwind_GetDataRelBase S4 A32])
                        (const_int 16 [0x10]))) mm.cc:29 585 {sibcall_value_internal}
                 (expr_list:REG_DEAD (reg:SI 4 $4)
                    (nil))
                (expr_list:REG_LABEL_TARGET (use (reg:SI 4 $4))
                    (nil)))
            (insn/f 120 47 133 (set (reg/f:SI 29 $sp)
                    (plus:SI (reg/f:SI 29 $sp)
                        (const_int 24 [0x18]))) 11 {*addsi3}
                 (expr_list:REG_CFA_DEF_CFA (reg/f:SI 29 $sp)
                    (expr_list:REG_CFA_RESTORE (reg:SI 31 $31)
                        (nil))))
        ]) mm.cc:29 -1
     (nil))
(barrier 133 132 38)
(code_label 38 133 39 4 "" [1 uses])
(note 39 38 128 [bb 12] NOTE_INSN_BASIC_BLOCK)
(note 128 39 114 NOTE_INSN_EPILOGUE_BEG)
(insn 114 128 40 (set (reg:SI 31 $31)
        (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                (const_int 20 [0x14])) [3 S4 A32])) mm.cc:34 283 {*movsi_internal}
     (nil))
(insn 40 114 115 (set (reg:SI 4 $4)
        (reg/v/f:SI 5 $5 [orig:199 context ] [199])) mm.cc:27 283 {*movsi_internal}
     (expr_list:REG_DEAD (reg/v/f:SI 5 $5 [orig:199 context ] [199])
        (nil)))
(insn 115 40 135 (clobber (mem/c:BLK (reg/f:SI 29 $sp) [3 A8])) mm.cc:34 -1
     (nil))
(insn 135 115 136 (sequence [
            (call_insn/j 41 115 116 (set (reg:SI 2 $2)
                    (call (mem:SI (symbol_ref:SI ("_Z22_Unwind_GetTextRelBaseP15_Unwind_Context") [flags 0x41]  <function_decl 0xf74deb00 _Unwind_GetTextRelBase>) [0 _Unwind_GetTextRelBase S4 A32])
                        (const_int 16 [0x10]))) mm.cc:27 585 {sibcall_value_internal}
                 (expr_list:REG_DEAD (reg:SI 4 $4)
                    (nil))
                (expr_list:REG_LABEL_TARGET (use (reg:SI 4 $4))
                    (nil)))
            (insn/f 116 41 136 (set (reg/f:SI 29 $sp)
                    (plus:SI (reg/f:SI 29 $sp)
                        (const_int 24 [0x18]))) 11 {*addsi3}
                 (expr_list:REG_CFA_DEF_CFA (reg/f:SI 29 $sp)
                    (expr_list:REG_CFA_RESTORE (reg:SI 31 $31)
                        (nil))))
        ]) mm.cc:27 -1
     (nil))
(barrier 136 135 50)
(code_label 50 136 51 6 "" [1 uses])
(note 51 50 129 [bb 13] NOTE_INSN_BASIC_BLOCK)
(note 129 51 110 NOTE_INSN_EPILOGUE_BEG)
(insn 110 129 52 (set (reg:SI 31 $31)
        (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                (const_int 20 [0x14])) [3 S4 A32])) mm.cc:34 283 {*movsi_internal}
     (nil))
(insn 52 110 111 (set (reg:SI 4 $4)
        (reg/v/f:SI 5 $5 [orig:199 context ] [199])) mm.cc:31 283 {*movsi_internal}
     (expr_list:REG_DEAD (reg/v/f:SI 5 $5 [orig:199 context ] [199])
        (nil)))
(insn 111 52 138 (clobber (mem/c:BLK (reg/f:SI 29 $sp) [3 A8])) mm.cc:34 -1
     (nil))
(insn 138 111 139 (sequence [
            (call_insn/j 53 111 112 (set (reg:SI 2 $2)
                    (call (mem:SI (symbol_ref:SI ("_Z22_Unwind_GetRegionStartP15_Unwind_Context") [flags 0x41]  <function_decl 0xf74dea00 _Unwind_GetRegionStart>) [0 _Unwind_GetRegionStart S4 A32])
                        (const_int 16 [0x10]))) mm.cc:31 585 {sibcall_value_internal}
                 (expr_list:REG_DEAD (reg:SI 4 $4)
                    (nil))
                (expr_list:REG_LABEL_TARGET (use (reg:SI 4 $4))
                    (nil)))
            (insn/f 112 53 139 (set (reg/f:SI 29 $sp)
                    (plus:SI (reg/f:SI 29 $sp)
                        (const_int 24 [0x18]))) 11 {*addsi3}
                 (expr_list:REG_CFA_DEF_CFA (reg/f:SI 29 $sp)
                    (expr_list:REG_CFA_RESTORE (reg:SI 31 $31)
                        (nil))))
        ]) mm.cc:31 -1
     (nil))
(barrier 139 138 56)
(code_label 56 139 57 3 "" [2 uses])
(note 57 56 58 [bb 14] NOTE_INSN_BASIC_BLOCK)
(call_insn 58 57 59 (parallel [
            (call (mem:SI (symbol_ref:SI ("_Z5abortv") [flags 0x41]  <function_decl 0xf74aa200 abort>) [0 abort S4 A32])
                (const_int 16 [0x10]))
            (clobber (reg:SI 31 $31))
        ]) mm.cc:33 587 {call_internal}
     (expr_list:REG_NORETURN (const_int 0 [0])
        (nil))
    (nil))
(barrier 59 58 60)
(code_label 60 59 61 2 "" [3 uses])
(note 61 60 130 [bb 15] NOTE_INSN_BASIC_BLOCK)
(note 130 61 107 NOTE_INSN_EPILOGUE_BEG)
(insn/f 107 130 66 (set (reg:SI 31 $31)
        (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
                (const_int 20 [0x14])) [3 S4 A32])) mm.cc:34 283 {*movsi_internal}
     (expr_list:REG_CFA_RESTORE (reg:SI 31 $31)
        (nil)))
(insn 66 107 69 (set (reg/i:SI 2 $2)
        (const_int 0 [0])) mm.cc:34 283 {*movsi_internal}
     (nil))
(insn 69 66 161 (use (reg/i:SI 2 $2)) mm.cc:34 -1
     (nil))
(code_label 161 69 108 16 "" [1 uses])
(jump_insn 108 161 109 (parallel [
            (return)
            (use (reg:SI 31 $31))
            (set (reg/f:SI 29 $sp)
                (plus:SI (reg/f:SI 29 $sp)
                    (const_int 24 [0x18])))
        ]) mm.cc:34 957 {jraddiusp}
     (nil)
 -> return)
(barrier 109 108 99)
(note 99 109 0 NOTE_INSN_DELETED)

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

* Re: [Patch] Add microMIPS jraddiusp support
  2013-03-14 21:07   ` Moore, Catherine
@ 2013-03-14 21:38     ` Richard Sandiford
  2013-04-02 17:35       ` Moore, Catherine
  2013-04-03 13:53       ` Moore, Catherine
  0 siblings, 2 replies; 7+ messages in thread
From: Richard Sandiford @ 2013-03-14 21:38 UTC (permalink / raw)
  To: Moore, Catherine; +Cc: gcc-patches, Rozycki, Maciej

"Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> Hi Richard,
>
> I updated this patch using your suggestions.  I'm having a problem
> though, that I'm having trouble nailing.  Building libstdc++ for
> microMIPS is failing trying to generate dwarf2 CFI info:
>
> _Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)
> Analyzing compilation unit
> Performing interprocedural optimizations
>  <*free_lang_data> <visibility> <early_local_cleanups> <*free_inline_summary> <whole-program> <profile_estimate> <cp> <inline> <pure-const> <static-var>Assembling functions:
>  _Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)
> mm.cc: In function '_Unwind_Ptr base_of_encoded_value(unsigned char, _Unwind_Context*)':
> mm.cc:34:1: internal compiler error: in maybe_record_trace_start, at dwarf2cfi.c:2209
> 0x8570656 maybe_record_trace_start
>         /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2209
> 0x857113f create_trace_edges
>         /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2301
> 0x8572505 scan_trace
>         /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2514
> 0x85726b3 create_cfi_notes
>         /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2540
> 0x8572703 execute_dwarf2_frame
>         /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2897
> Please submit a full bug report,
> with preprocessed source if appropriate.
> Please include the complete backtrace with any bug report.
> See <https://support.codesourcery.com/GNUToolchain/> for instructions.
>
> I've attached a testcase hoping that you might have some ideas.  I
> plan to keep debugging in the meanwhile.  I was able to reproduce with
> ./cc1plus -mmicromips -Os mm.ii.

Ah, sorry, I expect it should be:

      mips_epilogue_set_cfa (stack_pointer_rtx, 0);

instead of:

      mips_epilogue_emit_cfa_restores ();

It would probably be better to call mips_epilogue_set_cfa immediately
after emitting the jraddiusp, if that works (in which case making the
assert conditional is OK).

Richard

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

* RE: [Patch] Add microMIPS jraddiusp support
  2013-03-14 21:38     ` Richard Sandiford
@ 2013-04-02 17:35       ` Moore, Catherine
  2013-04-24 11:02         ` Richard Sandiford
  2013-04-03 13:53       ` Moore, Catherine
  1 sibling, 1 reply; 7+ messages in thread
From: Moore, Catherine @ 2013-04-02 17:35 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches, Rozycki, Maciej, Moore, Catherine

[-- Attachment #1: Type: text/plain, Size: 2799 bytes --]

Hi Richard,
I've now updated this patch.  How does this version look?
Catherine

2013-04-02  Catherine Moore  <clm@codesourcery.com>

        * config/mips/micromips.md (jraddiusp): New pattern.
        * config/mips/mips.c (mips_expand_epilogue): Use the JRADDIUSP
        instruction if possible.

> -----Original Message-----
> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: Thursday, March 14, 2013 5:38 PM
> To: Moore, Catherine
> Cc: gcc-patches@gcc.gnu.org; Rozycki, Maciej
> Subject: Re: [Patch] Add microMIPS jraddiusp support
> 
> "Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> > Hi Richard,
> >
> > I updated this patch using your suggestions.  I'm having a problem
> > though, that I'm having trouble nailing.  Building libstdc++ for
> > microMIPS is failing trying to generate dwarf2 CFI info:
> >
> > _Unwind_Ptr base_of_encoded_value(unsigned char,
> _Unwind_Context*)
> > Analyzing compilation unit Performing interprocedural optimizations
> > <*free_lang_data> <visibility> <early_local_cleanups>
> <*free_inline_summary> <whole-program> <profile_estimate> <cp>
> <inline> <pure-const> <static-var>Assembling functions:
> >  _Unwind_Ptr base_of_encoded_value(unsigned char,
> _Unwind_Context*)
> > mm.cc: In function '_Unwind_Ptr base_of_encoded_value(unsigned char,
> _Unwind_Context*)':
> > mm.cc:34:1: internal compiler error: in maybe_record_trace_start, at
> > dwarf2cfi.c:2209
> > 0x8570656 maybe_record_trace_start
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2209
> > 0x857113f create_trace_edges
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2301
> > 0x8572505 scan_trace
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2514
> > 0x85726b3 create_cfi_notes
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2540
> > 0x8572703 execute_dwarf2_frame
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2897
> > Please submit a full bug report,
> > with preprocessed source if appropriate.
> > Please include the complete backtrace with any bug report.
> > See <https://support.codesourcery.com/GNUToolchain/> for instructions.
> >
> > I've attached a testcase hoping that you might have some ideas.  I
> > plan to keep debugging in the meanwhile.  I was able to reproduce with
> > ./cc1plus -mmicromips -Os mm.ii.
> 
> Ah, sorry, I expect it should be:
> 
>       mips_epilogue_set_cfa (stack_pointer_rtx, 0);
> 
> instead of:
> 
>       mips_epilogue_emit_cfa_restores ();
> 
> It would probably be better to call mips_epilogue_set_cfa immediately after
> emitting the jraddiusp, if that works (in which case making the assert
> conditional is OK).
> 
> Richard

[-- Attachment #2: jraddiusp.patch --]
[-- Type: application/octet-stream, Size: 2372 bytes --]

Index: micromips.md
===================================================================
--- micromips.md	(revision 197119)
+++ micromips.md	(working copy)
@@ -95,6 +95,19 @@
    (set_attr "mode" "SI")
    (set_attr "can_delay" "no")])
 
+;; For JRADDIUSP.
+(define_insn "jraddiusp"
+  [(parallel [(return)
+	      (use (reg:SI 31))
+	      (set (reg:SI 29)
+		   (plus:SI (reg:SI 29)
+			    (match_operand 0 "uw5_operand")))])]
+  "TARGET_MICROMIPS"
+  "jraddiusp\t%0"
+  [(set_attr "type"	"trap")
+   (set_attr "can_delay" "no")
+   (set_attr "mode"	"SI")])
+
 ;; For MOVEP.
 (define_peephole2
   [(set (match_operand:MOVEP1 0 "register_operand" "")
Index: mips.c
===================================================================
--- mips.c	(revision 197119)
+++ mips.c	(working copy)
@@ -11414,6 +11414,7 @@ mips_expand_epilogue (bool sibcall_p)
   const struct mips_frame_info *frame;
   HOST_WIDE_INT step1, step2;
   rtx base, adjust, insn;
+  bool use_jraddiusp_p = false;
 
   if (!sibcall_p && mips_can_use_return_insn ())
     {
@@ -11541,12 +11542,19 @@ mips_expand_epilogue (bool sibcall_p)
 	  emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM),
 				    gen_rtx_REG (SImode, K0_REG_NUM)));
 	}
+      else if (TARGET_MICROMIPS
+	       && !crtl->calls_eh_return
+	       && !sibcall_p
+	       && step2 > 0
+	       && mips_unsigned_immediate_p (step2, 5, 2))
+	use_jraddiusp_p = true;
       else
 	/* Deallocate the final bit of the frame.  */
 	mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
     }
 
-  gcc_assert (!mips_epilogue.cfa_restores);
+  if (!use_jraddiusp_p)
+    gcc_assert (!mips_epilogue.cfa_restores);
 
   /* Add in the __builtin_eh_return stack adjustment.  We need to
      use a temporary in MIPS16 code.  */
@@ -11596,12 +11604,18 @@ mips_expand_epilogue (bool sibcall_p)
 	      rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
 	      pat = gen_return_internal (reg);
 	    }
+	  else if (use_jraddiusp_p)
+	    {
+	      pat = gen_jraddiusp (GEN_INT (step2));
+	    }
 	  else
 	    {
 	      rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
 	      pat = gen_simple_return_internal (reg);
 	    }
 	  emit_jump_insn (pat);
+	  if (use_jraddiusp_p)
+	    mips_epilogue_set_cfa (stack_pointer_rtx, step2);
 	}
     }
 

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

* [Patch] Add microMIPS jraddiusp support
  2013-03-14 21:38     ` Richard Sandiford
  2013-04-02 17:35       ` Moore, Catherine
@ 2013-04-03 13:53       ` Moore, Catherine
  1 sibling, 0 replies; 7+ messages in thread
From: Moore, Catherine @ 2013-04-03 13:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: rdsandiford

[-- Attachment #1: Type: text/plain, Size: 3101 bytes --]

This doesn't seem to have made it to the list.

-----Original Message-----
From: Moore, Catherine 
Sent: Tuesday, April 02, 2013 12:26 PM
To: 'Richard Sandiford'
Cc: gcc-patches@gcc.gnu.org; Rozycki, Maciej; 'clm@codesourcery.com'
Subject: RE: [Patch] Add microMIPS jraddiusp support

Hi Richard,
I've now updated this patch.  How does this version look?
Catherine

2013-04-02  Catherine Moore  <clm@codesourcery.com>

        * config/mips/micromips.md (jraddiusp): New pattern.
        * config/mips/mips.c (mips_expand_epilogue): Use the JRADDIUSP
        instruction if possible.

> -----Original Message-----
> From: Richard Sandiford [mailto:rdsandiford@googlemail.com]
> Sent: Thursday, March 14, 2013 5:38 PM
> To: Moore, Catherine
> Cc: gcc-patches@gcc.gnu.org; Rozycki, Maciej
> Subject: Re: [Patch] Add microMIPS jraddiusp support
> 
> "Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> > Hi Richard,
> >
> > I updated this patch using your suggestions.  I'm having a problem 
> > though, that I'm having trouble nailing.  Building libstdc++ for 
> > microMIPS is failing trying to generate dwarf2 CFI info:
> >
> > _Unwind_Ptr base_of_encoded_value(unsigned char,
> _Unwind_Context*)
> > Analyzing compilation unit Performing interprocedural optimizations 
> > <*free_lang_data> <visibility> <early_local_cleanups>
> <*free_inline_summary> <whole-program> <profile_estimate> <cp> 
> <inline> <pure-const> <static-var>Assembling functions:
> >  _Unwind_Ptr base_of_encoded_value(unsigned char,
> _Unwind_Context*)
> > mm.cc: In function '_Unwind_Ptr base_of_encoded_value(unsigned char,
> _Unwind_Context*)':
> > mm.cc:34:1: internal compiler error: in maybe_record_trace_start, at
> > dwarf2cfi.c:2209
> > 0x8570656 maybe_record_trace_start
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2209
> > 0x857113f create_trace_edges
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2301
> > 0x8572505 scan_trace
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2514
> > 0x85726b3 create_cfi_notes
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2540
> > 0x8572703 execute_dwarf2_frame
> >
> > /scratch/cmoore/umips-elf/src/gcc-4.7-2012.09/gcc/dwarf2cfi.c:2897
> > Please submit a full bug report,
> > with preprocessed source if appropriate.
> > Please include the complete backtrace with any bug report.
> > See <https://support.codesourcery.com/GNUToolchain/> for instructions.
> >
> > I've attached a testcase hoping that you might have some ideas.  I 
> > plan to keep debugging in the meanwhile.  I was able to reproduce 
> > with ./cc1plus -mmicromips -Os mm.ii.
> 
> Ah, sorry, I expect it should be:
> 
>       mips_epilogue_set_cfa (stack_pointer_rtx, 0);
> 
> instead of:
> 
>       mips_epilogue_emit_cfa_restores ();
> 
> It would probably be better to call mips_epilogue_set_cfa immediately 
> after emitting the jraddiusp, if that works (in which case making the 
> assert conditional is OK).
> 
> Richard

[-- Attachment #2: jraddiusp.patch --]
[-- Type: application/octet-stream, Size: 2372 bytes --]

Index: micromips.md
===================================================================
--- micromips.md	(revision 197119)
+++ micromips.md	(working copy)
@@ -95,6 +95,19 @@
    (set_attr "mode" "SI")
    (set_attr "can_delay" "no")])
 
+;; For JRADDIUSP.
+(define_insn "jraddiusp"
+  [(parallel [(return)
+	      (use (reg:SI 31))
+	      (set (reg:SI 29)
+		   (plus:SI (reg:SI 29)
+			    (match_operand 0 "uw5_operand")))])]
+  "TARGET_MICROMIPS"
+  "jraddiusp\t%0"
+  [(set_attr "type"	"trap")
+   (set_attr "can_delay" "no")
+   (set_attr "mode"	"SI")])
+
 ;; For MOVEP.
 (define_peephole2
   [(set (match_operand:MOVEP1 0 "register_operand" "")
Index: mips.c
===================================================================
--- mips.c	(revision 197119)
+++ mips.c	(working copy)
@@ -11414,6 +11414,7 @@ mips_expand_epilogue (bool sibcall_p)
   const struct mips_frame_info *frame;
   HOST_WIDE_INT step1, step2;
   rtx base, adjust, insn;
+  bool use_jraddiusp_p = false;
 
   if (!sibcall_p && mips_can_use_return_insn ())
     {
@@ -11541,12 +11542,19 @@ mips_expand_epilogue (bool sibcall_p)
 	  emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM),
 				    gen_rtx_REG (SImode, K0_REG_NUM)));
 	}
+      else if (TARGET_MICROMIPS
+	       && !crtl->calls_eh_return
+	       && !sibcall_p
+	       && step2 > 0
+	       && mips_unsigned_immediate_p (step2, 5, 2))
+	use_jraddiusp_p = true;
       else
 	/* Deallocate the final bit of the frame.  */
 	mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
     }
 
-  gcc_assert (!mips_epilogue.cfa_restores);
+  if (!use_jraddiusp_p)
+    gcc_assert (!mips_epilogue.cfa_restores);
 
   /* Add in the __builtin_eh_return stack adjustment.  We need to
      use a temporary in MIPS16 code.  */
@@ -11596,12 +11604,18 @@ mips_expand_epilogue (bool sibcall_p)
 	      rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
 	      pat = gen_return_internal (reg);
 	    }
+	  else if (use_jraddiusp_p)
+	    {
+	      pat = gen_jraddiusp (GEN_INT (step2));
+	    }
 	  else
 	    {
 	      rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
 	      pat = gen_simple_return_internal (reg);
 	    }
 	  emit_jump_insn (pat);
+	  if (use_jraddiusp_p)
+	    mips_epilogue_set_cfa (stack_pointer_rtx, step2);
 	}
     }
 

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

* Re: [Patch] Add microMIPS jraddiusp support
  2013-04-02 17:35       ` Moore, Catherine
@ 2013-04-24 11:02         ` Richard Sandiford
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Sandiford @ 2013-04-24 11:02 UTC (permalink / raw)
  To: Moore, Catherine; +Cc: gcc-patches, Rozycki, Maciej

"Moore, Catherine" <Catherine_Moore@mentor.com> writes:
> @@ -11596,12 +11604,18 @@ mips_expand_epilogue (bool sibcall_p)
>  	      rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
>  	      pat = gen_return_internal (reg);
>  	    }
> +	  else if (use_jraddiusp_p)
> +	    {
> +	      pat = gen_jraddiusp (GEN_INT (step2));
> +	    }

Redundant braces, should be:

	  else if (use_jraddiusp_p)
	    pat = gen_jraddiusp (GEN_INT (step2));

OK with that change, thanks.

Richard

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

end of thread, other threads:[~2013-04-24  6:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-04 23:08 [Patch] Add microMIPS jraddiusp support Moore, Catherine
2013-03-05 21:10 ` Richard Sandiford
2013-03-14 21:07   ` Moore, Catherine
2013-03-14 21:38     ` Richard Sandiford
2013-04-02 17:35       ` Moore, Catherine
2013-04-24 11:02         ` Richard Sandiford
2013-04-03 13:53       ` Moore, Catherine

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