This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] MIPS: add mips32r2 patterns to generate ext and insinsns.


On Thu, 2005-05-26 at 15:12 +0100, Richard Sandiford wrote:
> David Ung <davidu@mips.com> writes:
> > + /* Return true if we can use the MIPS32/64 R2 ext/ins instructions.
> > +    Return false if OP is not in a register, zero/invalid length bitfields
> > +    or lengths equal to word size. */
> > +    
> > + bool
> > + mips_use_ins_ext_p (rtx op, rtx l, rtx p)
> > + {
> 
> Since you've decided to make mips_use_ins_ext_p take the three
> zero_extend arguments separately (rather than pass a pointer as
> I suggsted originally ;) you at least need to document all the
> arguments.  The comment doesn't mention L and P and doesn't give
> much clue what how they relate OP.  Saying that the three arguments
> are the three operands to a zero_extend would help.

I've done this because the parameters for ext and inv use different
operands.  Simply access the next two operands from &operand[0] (or
&operand[1] for insert) for size and pos didn't appeal to me as good
coding practice.  So, I've decided to op for the 3 explicit
parameters. :)
I've moved the comments from the body to the head of the function and
made references to the parameters.

> 
> > !   else if (!mips_use_ins_ext_p (operands[1], operands[2], operands[3]))
> >       FAIL;
> > +   else
> > +     {
> > +       if (GET_MODE (operands[0]) == DImode)
> > +         emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
> > + 				operands[3]));
> > +       else
> > +         emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
> > + 				operands[3]));
> > +       DONE;
> > +     }
> >   })
> 
> Since we can't fall through (as I'd hoped at fist) I'd prefer that you
> use a positive test here and put the FAIL last.  I.e. swap the bodies
> of the two "else"s.

done.

> 
> > + /* { dg-final { scan-assembler "ext" } } */
> > + /* { dg-final { scan-assembler "ins" } } */
> > +
> > + struct A 
> > + {
> > +   unsigned int i : 2;
> > +   unsigned int j : 3;
> > +   unsigned int k : 4;
> > +   unsigned int l : 5;
> > + };
> > +
> > + void func (struct A);
> > +
> > + unsigned int ext (struct A a)
> > + {
> > +   return a.j;
> > + }
> > +
> > + void ins (int i)
> > + {
> > +   struct A c;
> > +   c.j = i;
> > +   func (c);
> > + }
> 
> This isn't a very good test.  The output will trivially match "ext"
> and "ins" because that's what the functions are called ;)

doh!!!


2005-05-26  David Ung  <davidu@mips.com>

	* config/mips/mips.c (mips_use_ins_ext_p): New helper function
	that determines whether the MIPS32/64 R2 ext/ins should be used.
	* config/mips/mips.h (ISA_HAS_EXT_INS): New macro.
	* config/mips/mips.md (extzv): Changed predicate for operand to
	nonimmediate_operand. Add code to generate insn patterns for
	extzvsi and extzvdi.
	(extzv<mode>): New pattern to match mips32r2 ext insn.
	(insv): Similarly for insertion.
	(insvs<mode>): Similarly.

2005-05-26  David Ung  <davidu@mips.com>

	* gcc.target/mips/ext_ins.c: New test for testing the generation
	of MIPS32/64 rev 2 ext/ins instructions.

Index: gcc/config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.504
diff -c -p -b -r1.504 mips.c
*** gcc/config/mips/mips.c	26 May 2005 05:27:55 -0000	1.504
--- gcc/config/mips/mips.c	26 May 2005 14:53:46 -0000
*************** mips_expand_unaligned_store (rtx dest, r
*** 4159,4164 ****
--- 4159,4195 ----
    return true;
  }
  
+ /* Return true if we can use the MIPS32/64 R2 ext/ins instructions.
+    Return false if OP is not in a register.
+    MIPS ins/ext insns don't support zero length bitfields or fields
+    extending beyond the left or right-most bits.
+    To be valid, the values of POSITION and SIZE must satisfy all of
+    the following:
+      0 <= POSITION < BITS_PER_WORD
+      0 < SIZE <= BITS_PER_WORD
+      0 < POSITION + SIZE <= BITS_PER_WORD
+    Additionally, we reject lengths equal to a word as they are better
+    handled by the move patterns.  */
+ 
+ bool
+ mips_use_ins_ext_p (rtx op, rtx size, rtx position)
+ {
+   HOST_WIDE_INT len, pos;
+ 
+   if (!ISA_HAS_EXT_INS
+       || !register_operand (op, VOIDmode))
+     return false;
+ 
+   len = INTVAL (size);
+   pos = INTVAL (position);
+   
+   if (len <= 0 || len >= BITS_PER_WORD || pos < 0
+       || pos + len > BITS_PER_WORD)
+     return false;
+ 
+   return true;
+ }
+ 
  /* Set up globals to generate code for the ISA or processor
     described by INFO.  */
  
Index: gcc/config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.394
diff -c -p -b -r1.394 mips.h
*** gcc/config/mips/mips.h	26 May 2005 05:27:54 -0000	1.394
--- gcc/config/mips/mips.h	26 May 2005 14:54:40 -0000
*************** extern const struct mips_cpu_info *mips_
*** 670,675 ****
--- 670,680 ----
                                   && (ISA_MIPS32R2                      \
                                       ))
  
+ /* ISA includes the MIPS32/64 rev 2 ext and ins instructions.  */
+ #define ISA_HAS_EXT_INS         (!TARGET_MIPS16                        \
+                                  && (ISA_MIPS32R2                      \
+                                      ))
+ 
  /* True if the result of a load is not available to the next instruction.
     A nop will then be needed between instructions like "lw $4,..."
     and "addiu $4,$4,1".  */

Index: gcc/config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.319
diff -c -p -b -r1.319 mips.md
*** gcc/config/mips/mips.md	13 May 2005 15:24:35 -0000	1.319
--- gcc/config/mips/mips.md	26 May 2005 14:54:58 -0000
*************** beq\t%2,%.,1b\;\
*** 2818,2824 ****
  
  (define_expand "extzv"
    [(set (match_operand 0 "register_operand")
! 	(zero_extract (match_operand:QI 1 "memory_operand")
  		      (match_operand 2 "immediate_operand")
  		      (match_operand 3 "immediate_operand")))]
    "!TARGET_MIPS16"
--- 2818,2824 ----
  
  (define_expand "extzv"
    [(set (match_operand 0 "register_operand")
! 	(zero_extract (match_operand 1 "nonimmediate_operand")
  		      (match_operand 2 "immediate_operand")
  		      (match_operand 3 "immediate_operand")))]
    "!TARGET_MIPS16"
*************** beq\t%2,%.,1b\;\
*** 2827,2838 ****
  				  INTVAL (operands[2]),
  				  INTVAL (operands[3])))
      DONE;
    else
      FAIL;
  })
  
  (define_expand "insv"
!   [(set (zero_extract (match_operand:QI 0 "memory_operand")
  		      (match_operand 1 "immediate_operand")
  		      (match_operand 2 "immediate_operand"))
  	(match_operand 3 "reg_or_0_operand"))]
--- 2827,2859 ----
  				  INTVAL (operands[2]),
  				  INTVAL (operands[3])))
      DONE;
+   else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3]))
+     {
+       if (GET_MODE (operands[0]) == DImode)
+         emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
+ 				operands[3]));
+       else
+         emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
+ 				operands[3]));
+       DONE;
+     }
    else
      FAIL;
  })
  
+ (define_insn "extzv<mode>"
+   [(set (match_operand:GPR 0 "register_operand" "=d")
+ 	(zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+ 			  (match_operand:SI 2 "immediate_operand" "I")
+ 			  (match_operand:SI 3 "immediate_operand" "I")))]
+   "mips_use_ins_ext_p (operands[1], operands[2], operands[3])"
+   "<d>ext\t%0,%1,%3,%2"
+   [(set_attr "type"	"arith")
+    (set_attr "mode"	"<MODE>")])
+ 
+ 
  (define_expand "insv"
!   [(set (zero_extract (match_operand 0 "nonimmediate_operand")
  		      (match_operand 1 "immediate_operand")
  		      (match_operand 2 "immediate_operand"))
  	(match_operand 3 "reg_or_0_operand"))]
*************** beq\t%2,%.,1b\;\
*** 2842,2851 ****
--- 2863,2892 ----
  				   INTVAL (operands[1]),
  				   INTVAL (operands[2])))
      DONE;
+   else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2]))
+     {
+       if (GET_MODE (operands[0]) == DImode)
+         emit_insn (gen_insvdi (operands[0], operands[1], operands[2],
+ 			       operands[3]));
+       else
+         emit_insn (gen_insvsi (operands[0], operands[1], operands[2],
+ 			       operands[3]));
+       DONE;
+    }
     else
       FAIL;
  })
  
+ (define_insn "insv<mode>"
+   [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d")
+ 			  (match_operand:SI 1 "immediate_operand" "I")
+ 			  (match_operand:SI 2 "immediate_operand" "I"))
+ 	(match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
+   "mips_use_ins_ext_p (operands[0], operands[1], operands[2])"
+   "<d>ins\t%0,%z3,%2,%1"
+   [(set_attr "type"	"arith")
+    (set_attr "mode"	"<MODE>")])
+ 
  ;; Unaligned word moves generated by the bit field patterns.
  ;;
  ;; As far as the rtl is concerned, both the left-part and right-part

Index: gcc.target/mips/ext_ins.c
===================================================================
RCS file: gcc.target/mips/ext_ins.c
diff -N gcc.target/mips/ext_ins.c
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- gcc.target/mips/ext_ins.c   26 May 2005 14:52:53 -0000
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile } */
+ /* { dg-mips-options "-march=mips32r2" } */
+ /* { dg-final { scan-assembler "ext" } } */
+ /* { dg-final { scan-assembler "ins" } } */
+
+ struct A
+ {
+   unsigned int i : 2;
+   unsigned int j : 3;
+   unsigned int k : 4;
+   unsigned int l : 5;
+ };
+
+ void func (struct A);
+
+ unsigned int f1 (struct A a)
+ {
+   return a.j;
+ }
+
+ void f2 (int i)
+ {
+   struct A c;
+   c.j = i;
+   func (c);
+ }




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]