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]

POWER4/PPC970 mfcr field


	The following patch adds GCC support for the mfcr field form of
the instruction if the assembler support is present.  Moving one field is
much faster than moving all CR fields on this class of processors.

David


2003-07-07  David Edelsohn  <edelsohn@gnu.org
	    Fariborz Jahanian  <fjahanian@apple.com>

	* configure.in: Test for PowerPC mfcr field support in assembler.
	* config.in, configure: Regenderated.

	* config/rs6000/power4.md: Add mfcrf reservation.
	* config/rs6000/rs6000-protos.h (mfcr_operation): Declare.
	* config/rs6000/rs6000.c (mfcr_operation): Define.
	(print_operand): Add 'Q' case for mfcrf.
	* config/rs6000/rs6000.h (TARGET_MFCRF): New.
	* config/rs6000/rs6000.md (attribute "type"): Add mfcrf.
	(movcc_internal1): Emit optional field operand for mfcr and set
	"type" attribute appropriately.
	(mfcr SCC): Likewise.
	(movesi_from_cr_one): New.

Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.696
diff -c -p -r1.696 configure.in
*** configure.in	6 Jul 2003 18:50:44 -0000	1.696
--- configure.in	6 Jul 2003 23:50:20 -0000
*************** changequote([,])dnl
*** 2461,2466 ****
--- 2461,2501 ----
  	  [Define if your assembler supports ltoffx and ldxmov relocations.])
      fi
      ;;
+   powerpc*-*-*)
+     AC_CACHE_CHECK([assembler supports mfcr field],
+ 	gcc_cv_as_mfcrf, [
+ 	gcc_cv_as_mfcrf=unknown
+ 	if test $in_tree_gas = yes ; then
+           gcc_GAS_VERSION_GTE_IFELSE(2,14,0,[
+ 	    gcc_cv_as_mfcrf=yes
+           ])
+ 	elif test x$gcc_cv_as != x; then
+ 	    cat > conftest.s << 'EOF'
+ 	      case "$target" in
+ changequote(,)dnl
+ 		*-*-aix*)
+ 	.csect .text[PR]
+ 		;;
+ 		*)
+ 	.text
+ 		;;
+ 	      esac
+ 	mfcr 3,128
+ EOF
+ changequote([,])dnl
+ 	    if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ 		gcc_cv_as_mfcrf=yes
+ 	    else
+ 		gcc_cv_as_mfcrf=no
+ 	    fi
+ 	    rm -f conftest.s conftest.o
+ 	fi
+     ])
+     if test "x$gcc_cv_as_mfcrf" = xyes; then
+ 	AC_DEFINE(HAVE_AS_MFCRF, 1,
+ 	  [Define if your assembler supports mfcr field.])
+     fi
+     ;;
  esac
  
  AC_MSG_CHECKING(assembler dwarf2 debug_line support)
Index: config/rs6000/power4.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/power4.md,v
retrieving revision 1.14
diff -c -p -r1.14 power4.md
*** config/rs6000/power4.md	26 Jun 2003 05:22:32 -0000	1.14
--- config/rs6000/power4.md	6 Jul 2003 23:50:20 -0000
***************
*** 202,208 ****
    |(du2_power4+du3_power4,iu2_power4,iu2_power4)\
    |(du3_power4+du4_power4,nothing,iu2_power4,iu1_power4)")
  
! (define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
  
  (define_insn_reservation "power4-lmul-cmp" 7
    (and (eq_attr "type" "lmul_compare")
--- 202,208 ----
    |(du2_power4+du3_power4,iu2_power4,iu2_power4)\
    |(du3_power4+du4_power4,nothing,iu2_power4,iu1_power4)")
  
! (define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
  
  (define_insn_reservation "power4-lmul-cmp" 7
    (and (eq_attr "type" "lmul_compare")
***************
*** 212,218 ****
    |(du3_power4+du4_power4,iu2_power4*6,iu1_power4)")
  ;  |(du3_power4+du4_power4,nothing,iu2_power4*6,iu1_power4)")
  
! (define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
  
  (define_insn_reservation "power4-imul-cmp" 5
    (and (eq_attr "type" "imul_compare")
--- 212,218 ----
    |(du3_power4+du4_power4,iu2_power4*6,iu1_power4)")
  ;  |(du3_power4+du4_power4,nothing,iu2_power4*6,iu1_power4)")
  
! (define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
  
  (define_insn_reservation "power4-imul-cmp" 5
    (and (eq_attr "type" "imul_compare")
***************
*** 222,228 ****
    |(du3_power4+du4_power4,iu2_power4*4,iu1_power4)")
  ;  |(du3_power4+du4_power4,nothing,iu2_power4*4,iu1_power4)")
  
! (define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
  
  (define_insn_reservation "power4-lmul" 7
    (and (eq_attr "type" "lmul")
--- 222,228 ----
    |(du3_power4+du4_power4,iu2_power4*4,iu1_power4)")
  ;  |(du3_power4+du4_power4,nothing,iu2_power4*4,iu1_power4)")
  
! (define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
  
  (define_insn_reservation "power4-lmul" 7
    (and (eq_attr "type" "lmul")
***************
*** 305,310 ****
--- 305,316 ----
     du1_power4+du2_power4+du3_power4+du4_power4+cru_power4,\
     cru_power4,cru_power4,cru_power4")
  
+ ; mfcrf (1 field)
+ (define_insn_reservation "power4-mfcrf" 3
+   (and (eq_attr "type" "mfcrf")
+        (eq_attr "cpu" "power4"))
+   "du1_power4,cru_power4")
+ 
  ; mtcrf (1 field)
  (define_insn_reservation "power4-mtcr" 4
    (and (eq_attr "type" "mtcr")
***************
*** 379,385 ****
  (define_bypass 9 "power4-vecfloat" "power4-vecperm")
  
  (define_bypass 5 "power4-vecsimple,power4-veccomplex"
! 		 "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
  
  (define_bypass 4 "power4-vecsimple,power4-vecperm" "power4-vecstore")
  (define_bypass 7 "power4-veccomplex" "power4-vecstore")
--- 385,391 ----
  (define_bypass 9 "power4-vecfloat" "power4-vecperm")
  
  (define_bypass 5 "power4-vecsimple,power4-veccomplex"
! 		 "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
  
  (define_bypass 4 "power4-vecsimple,power4-vecperm" "power4-vecstore")
  (define_bypass 7 "power4-veccomplex" "power4-vecstore")
Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.59
diff -c -p -r1.59 rs6000-protos.h
*** config/rs6000/rs6000-protos.h	30 Jun 2003 13:30:45 -0000	1.59
--- config/rs6000/rs6000-protos.h	6 Jul 2003 23:50:20 -0000
*************** extern void rs6000_initialize_trampoline
*** 122,127 ****
--- 122,128 ----
  extern struct rtx_def *rs6000_longcall_ref PARAMS ((rtx));
  extern void rs6000_fatal_bad_address PARAMS ((rtx));
  extern int stmw_operation PARAMS ((rtx, enum machine_mode));
+ extern int mfcr_operation PARAMS ((rtx, enum machine_mode));
  extern int mtcrf_operation PARAMS ((rtx, enum machine_mode));
  extern int lmw_operation PARAMS ((rtx, enum machine_mode));
  extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.502
diff -c -p -r1.502 rs6000.c
*** config/rs6000/rs6000.c	5 Jul 2003 15:39:59 -0000	1.502
--- config/rs6000/rs6000.c	6 Jul 2003 23:50:20 -0000
*************** vrsave_operation (op, mode)
*** 7294,7299 ****
--- 7294,7349 ----
    return 1;
  }
  
+ /* Return 1 for an PARALLEL suitable for mfcr.  */
+ 
+ int
+ mfcr_operation (op, mode)
+      rtx op;
+      enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+   int count = XVECLEN (op, 0);
+   int i;
+ 
+   /* Perform a quick check so we don't blow up below.  */
+   if (count < 1
+       || GET_CODE (XVECEXP (op, 0, 0)) != SET
+       || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
+       || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
+     return 0;
+ 
+   for (i = 0; i < count; i++)
+     {
+       rtx exp = XVECEXP (op, 0, i);
+       rtx unspec;
+       int maskval;
+       rtx src_reg;
+ 
+       src_reg = XVECEXP (SET_SRC (exp), 0, 0);
+ 
+       if (GET_CODE (src_reg) != REG
+ 	  || GET_MODE (src_reg) != CCmode
+ 	  || ! CR_REGNO_P (REGNO (src_reg)))
+ 	return 0;
+ 
+       if (GET_CODE (exp) != SET
+ 	  || GET_CODE (SET_DEST (exp)) != REG
+ 	  || GET_MODE (SET_DEST (exp)) != SImode
+ 	  || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
+ 	return 0;
+       unspec = SET_SRC (exp);
+       maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
+ 
+       if (GET_CODE (unspec) != UNSPEC
+ 	  || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
+ 	  || XVECLEN (unspec, 0) != 2
+ 	  || XVECEXP (unspec, 0, 0) != src_reg
+ 	  || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
+ 	  || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
+ 	return 0;
+     }
+   return 1;
+ }
+ 
  /* Return 1 for an PARALLEL suitable for mtcrf.  */
  
  int
*************** print_operand (file, x, code)
*** 8499,8504 ****
--- 8549,8561 ----
        }
        return;
  
+     case 'Q':
+       if (TARGET_MFCRF)
+ 	fputc (',',file);
+         /* FALLTHRU */
+       else
+ 	return;
+ 
      case 'R':
        /* X is a CR register.  Print the mask for `mtcrf'.  */
        if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
*************** rs6000_variable_issue (stream, verbose, 
*** 13190,13196 ****
      {
        enum attr_type type = get_attr_type (insn);
        if (type == TYPE_LOAD_EXT_U || type == TYPE_LOAD_EXT_UX
! 	  || type == TYPE_LOAD_UX || type == TYPE_STORE_UX)
  	return 0;
        else if (type == TYPE_LOAD_U || type == TYPE_STORE_U
  	       || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
--- 13247,13254 ----
      {
        enum attr_type type = get_attr_type (insn);
        if (type == TYPE_LOAD_EXT_U || type == TYPE_LOAD_EXT_UX
! 	  || type == TYPE_LOAD_UX || type == TYPE_STORE_UX
! 	  || type == TYPE_MFCR)
  	return 0;
        else if (type == TYPE_LOAD_U || type == TYPE_STORE_U
  	       || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.283
diff -c -p -r1.283 rs6000.h
*** config/rs6000/rs6000.h	20 Jun 2003 20:16:24 -0000	1.283
--- config/rs6000/rs6000.h	6 Jul 2003 23:50:21 -0000
*************** extern int rs6000_alignment_flags;
*** 475,480 ****
--- 475,490 ----
  #define TARGET_ALIGN_NATURAL 0
  #endif
  
+ /* Define TARGET_MFCRF if the target assembler supports the optional
+    field operand for mfcr and the target processor supports the
+    instruction.  */
+ 
+ #ifdef HAVE_AS_MFCRF
+ #define TARGET_MFCRF (rs6000_cpu == PROCESSOR_POWER4)
+ #else
+ #define TARGET_MFCRF 0
+ #endif
+ 
  #define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
  #define TARGET_ALTIVEC_ABI rs6000_altivec_abi
  #define TARGET_ALTIVEC_VRSAVE rs6000_altivec_vrsave
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.262
diff -c -p -r1.262 rs6000.md
*** config/rs6000/rs6000.md	5 Jul 2003 00:08:11 -0000	1.262
--- config/rs6000/rs6000.md	6 Jul 2003 23:50:21 -0000
***************
*** 62,68 ****
  
  ;; Define an insn type attribute.  This is used in function unit delay
  ;; computations.
! (define_attr "type" "integer,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
    (const_string "integer"))
  
  ;; Length (in bytes).
--- 62,68 ----
  
  ;; Define an insn type attribute.  This is used in function unit delay
  ;; computations.
! (define_attr "type" "integer,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
    (const_string "integer"))
  
  ;; Length (in bytes).
***************
*** 7800,7814 ****
     mcrf %0,%1
     mtcrf 128,%1
     {rlinm|rlwinm} %1,%1,%F0,0xffffffff\;mtcrf %R0,%1\;{rlinm|rlwinm} %1,%1,%f0,0xffffffff
!    mfcr %0
!    mfcr %0\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
     mr %0,%1
     mf%1 %0
     mt%0 %1
     mt%0 %1
     {l%U1%X1|lwz%U1%X1} %0,%1
     {st%U0%U1|stw%U0%U1} %1,%0"
!   [(set_attr "type" "cr_logical,mtcr,mtcr,mfcr,mfcr,*,mfjmpr,*,mtjmpr,load,store")
     (set_attr "length" "4,4,12,4,8,4,4,4,4,4,4")])
  
  ;; For floating-point, we normally deal with the floating-point registers
--- 7800,7832 ----
     mcrf %0,%1
     mtcrf 128,%1
     {rlinm|rlwinm} %1,%1,%F0,0xffffffff\;mtcrf %R0,%1\;{rlinm|rlwinm} %1,%1,%f0,0xffffffff
!    mfcr %0%Q1
!    mfcr %0%Q1\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
     mr %0,%1
     mf%1 %0
     mt%0 %1
     mt%0 %1
     {l%U1%X1|lwz%U1%X1} %0,%1
     {st%U0%U1|stw%U0%U1} %1,%0"
!   [(set (attr "type")
!      (cond [(eq_attr "alternative" "0")
! 		(const_string "cr_logical")
! 	    (eq_attr "alternative" "1,2")
! 		(const_string "mtcr")
! 	    (eq_attr "alternative" "5,7")
! 		(const_string "integer")
! 	    (eq_attr "alternative" "6")
! 		(const_string "mfjmpr")
! 	    (eq_attr "alternative" "8")
! 		(const_string "mtjmpr")
! 	    (eq_attr "alternative" "9")
! 		(const_string "load")
! 	    (eq_attr "alternative" "10")
! 		(const_string "store")
! 	    (ne (symbol_ref "TARGET_MFCRF") (const_int 0))
! 		(const_string "mfcrf")
! 	   ]
! 	(const_string "mfcr")))
     (set_attr "length" "4,4,12,4,8,4,4,4,4,4,4")])
  
  ;; For floating-point, we normally deal with the floating-point registers
***************
*** 11368,11375 ****
  			   [(match_operand 2 "cc_reg_operand" "y")
  			    (const_int 0)]))]
    ""
!   "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
!   [(set_attr "type" "mfcr")
     (set_attr "length" "12")])
  
  ;; Same as above, but get the OV/ORDERED bit.
--- 11386,11397 ----
  			   [(match_operand 2 "cc_reg_operand" "y")
  			    (const_int 0)]))]
    ""
!   "mfcr %0%Q2\;{rlinm|rlwinm} %0,%0,%J1,1"
!   [(set (attr "type")
!      (cond [(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
! 		(const_string "mfcrf")
! 	   ]
! 	(const_string "mfcr")))
     (set_attr "length" "12")])
  
  ;; Same as above, but get the OV/ORDERED bit.
***************
*** 11387,11394 ****
  			   [(match_operand 2 "cc_reg_operand" "y")
  			    (const_int 0)]))]
    "TARGET_POWERPC64"
!   "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
!   [(set_attr "type" "mfcr")
     (set_attr "length" "12")])
  
  (define_insn ""
--- 11409,11420 ----
  			   [(match_operand 2 "cc_reg_operand" "y")
  			    (const_int 0)]))]
    "TARGET_POWERPC64"
!   "mfcr %0%Q2\;{rlinm|rlwinm} %0,%0,%J1,1"
!   [(set (attr "type")
!      (cond [(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
! 		(const_string "mfcrf")
! 	   ]
! 	(const_string "mfcr")))
     (set_attr "length" "12")])
  
  (define_insn ""
***************
*** 11401,11407 ****
  	(match_op_dup 1 [(match_dup 2) (const_int 0)]))]
    "! TARGET_POWERPC64"
    "@
!    mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
     #"
    [(set_attr "type" "delayed_compare")
     (set_attr "length" "12,16")])
--- 11427,11433 ----
  	(match_op_dup 1 [(match_dup 2) (const_int 0)]))]
    "! TARGET_POWERPC64"
    "@
!    mfcr %3%Q2\;{rlinm.|rlwinm.} %3,%3,%J1,1
     #"
    [(set_attr "type" "delayed_compare")
     (set_attr "length" "12,16")])
***************
*** 11443,11451 ****
    operands[4] = GEN_INT (count);
    operands[5] = GEN_INT (put_bit);
  
!   return \"mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
  }"
!   [(set_attr "type" "mfcr")
     (set_attr "length" "12")])
  
  (define_insn ""
--- 11469,11481 ----
    operands[4] = GEN_INT (count);
    operands[5] = GEN_INT (put_bit);
  
!   return \"mfcr %0%Q2\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
  }"
!   [(set (attr "type")
!      (cond [(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
! 		(const_string "mfcrf")
! 	   ]
! 	(const_string "mfcr")))
     (set_attr "length" "12")])
  
  (define_insn ""
***************
*** 11478,11484 ****
    operands[5] = GEN_INT (count);
    operands[6] = GEN_INT (put_bit);
  
!   return \"mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
  }"
    [(set_attr "type" "delayed_compare")
     (set_attr "length" "12,16")])
--- 11508,11514 ----
    operands[5] = GEN_INT (count);
    operands[6] = GEN_INT (put_bit);
  
!   return \"mfcr %4%Q2\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
  }"
    [(set_attr "type" "delayed_compare")
     (set_attr "length" "12,16")])
***************
*** 14433,14438 ****
--- 14463,14489 ----
        rs6000_emit_prologue ();
        DONE;
  }")
+ 
+ (define_insn "*movesi_from_cr_one"
+   [(match_parallel 0 "mfcr_operation"
+ 		   [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
+ 			 (unspec:SI [(match_operand:CC 2 "cc_reg_operand" "y")
+ 				     (match_operand 3 "immediate_operand" "n")]
+ 			  UNSPEC_MOVESI_FROM_CR))])]
+   "TARGET_MFCRF"
+   "*
+ {
+   int mask = 0;
+   int i;
+   for (i = 0; i < XVECLEN (operands[0], 0); i++)
+   {
+     mask = INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1));
+     operands[4] = GEN_INT (mask);
+     output_asm_insn (\"mfcr %1,%4\", operands);
+   }
+   return \"\";
+ }"
+   [(set_attr "type" "mfcrf")])
  
  (define_insn "movesi_from_cr"
    [(set (match_operand:SI 0 "gpc_reg_operand" "=r")


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