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]

[patch, s390] insv/extv


Hi,

after several internal revisions and fixing the blocking bug in
combine this patch enables insv/extv for s390(x).

A slightly different version boostrapped and regtested on s390,z9-109 with no regressions.

Ok for mainline, once testsuite rerun completed successfully?

Bye,
Adrian

2005-10-13  Adrian Straetling  <straetling@de.ibm.com>

      * config/s390/s390.c: (s390_expand_insv): New.
      * config/s390/s390-protos.h: Declare.
      * config/s390/s390.md: ("UNSPEC_SETHIGH"): Rename to "UNSPEC_ICM".
      ("icm_hi"): Remove mode attribute.
      ("*sethigh<mode><mode>"): Rewrite to "sethighpart<mode>". Adjust all uses.
      ("*extracthi,*extractqi"): Remove.
      ("*extv<mode>","*extzv<mode>"): New.
      ("insv","*insv<mode>_mem_reg","*insvdi_mem_reghigh",
      "*insv<mode>_reg_imm","*insv<mode>_reg_extimm"): New.


Index: gcc/config/s390/s390-protos.h
===================================================================
*** gcc/config/s390/s390-protos.h.orig	2005-10-14 11:16:37.000000000 +0200
--- gcc/config/s390/s390-protos.h	2005-10-14 11:16:37.000000000 +0200
*************** extern void s390_expand_movmem (rtx, rtx
*** 73,78 ****
--- 73,79 ----
  extern void s390_expand_setmem (rtx, rtx, rtx);
  extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
  extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+ extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
  extern rtx s390_return_addr_rtx (int, rtx);
  extern rtx s390_back_chain_rtx (void);
  extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig	2005-10-14 11:16:37.000000000 +0200
--- gcc/config/s390/s390.c	2005-10-14 11:16:37.000000000 +0200
*************** s390_expand_addcc (enum rtx_code cmp_cod
*** 3813,3818 ****
--- 3813,3917 ----
    return false;
  }
  
+ /* Expand code for the insv template. Return true if successful, false else.  */
+ 
+ bool 
+ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
+ {
+   int bitsize = INTVAL (op1);
+   int bitpos = INTVAL (op2);
+ 
+   /* We need byte alignement.  */
+   if (bitsize % BITS_PER_UNIT)
+     return false;
+ 
+   if (bitpos == 0
+       && memory_operand (dest, VOIDmode)
+       && (register_operand (src, word_mode)
+ 	  || const_int_operand (src, VOIDmode)))
+     {
+       /* Emit standard pattern if possible.  */
+       enum machine_mode mode = smallest_mode_for_size (bitsize, MODE_INT);
+       if (GET_MODE_BITSIZE (mode) == bitsize)
+ 	emit_move_insn (adjust_address (dest, mode, 0), gen_lowpart (mode, src));
+ 
+       /* (set (ze (mem)) (const_int)).  */
+       else if (const_int_operand (src, VOIDmode))
+ 	{
+ 	  int size = bitsize / BITS_PER_UNIT;
+ 	  rtx src_mem = adjust_address (force_const_mem (word_mode, src), BLKmode,
+ 					GET_MODE_SIZE (word_mode) - size);
+ 
+ 	  gcc_assert (INTVAL (MEM_SIZE (src_mem)) == size);
+ 
+ 	  dest = adjust_address (dest, BLKmode, 0);
+ 	  /*set_mem_size (src_mem, size);*/
+ 	  set_mem_size (dest, GEN_INT (size));
+ 
+ 	  s390_expand_movmem (dest, src_mem, GEN_INT (size));
+ 	}
+ 	  
+       /* (set (ze (mem)) (reg)).  */
+       else if (register_operand (src, word_mode))
+ 	{
+ 	  if (bitsize <= GET_MODE_BITSIZE (SImode))
+ 	    emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, op1,
+ 						  const0_rtx), src);
+ 	  else
+ 	    {
+ 	      /* Emit st,stcmh sequence.  */
+ 	      int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
+ 	      int size = stcmh_width / BITS_PER_UNIT;
+ 
+ 	      emit_move_insn (adjust_address (dest, SImode, size), 
+ 			      gen_lowpart (SImode, src));
+ 	      set_mem_size (dest, GEN_INT (size));
+ 	      emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
+ 						    (stcmh_width), const0_rtx),
+ 			      gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
+ 						(GET_MODE_BITSIZE (SImode))));
+ 	    }
+ 	}
+       else
+ 	return false;
+ 
+       return true;
+     }
+ 
+   /* (set (ze (reg)) (const_int)).  */
+   if (TARGET_ZARCH
+       && register_operand (dest, word_mode) 
+       && (bitpos % 16) == 0
+       && (bitsize % 16) == 0
+       && const_int_operand (src, VOIDmode))
+     {
+       HOST_WIDE_INT val = INTVAL (src);
+       int regpos = bitpos + bitsize;
+ 
+       while (regpos > bitpos)
+ 	{
+ 	  enum machine_mode putmode;
+ 	  int putsize;
+ 
+ 	  if (TARGET_EXTIMM && (regpos % 32 == 0) && (regpos >= bitpos + 32))
+ 	    putmode = SImode;
+ 	  else
+ 	    putmode = HImode;
+ 
+ 	  putsize = GET_MODE_BITSIZE (putmode);
+ 	  regpos -= putsize;
+ 	  emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, 
+ 						GEN_INT (putsize),
+ 						GEN_INT (regpos)), 
+ 			  gen_int_mode (val, putmode));
+ 	  val >>= putsize;
+ 	}
+       gcc_assert (regpos == bitpos);
+       return true;
+     }
+ 
+   return false;
+ }
  
  /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
     We need to emit DTP-relative relocations.  */
Index: gcc/config/s390/s390.md
===================================================================
*** gcc/config/s390/s390.md.orig	2005-10-14 11:16:37.000000000 +0200
--- gcc/config/s390/s390.md	2005-10-14 11:16:37.000000000 +0200
***************
*** 98,104 ****
    [; Miscellaneous
     (UNSPEC_ROUND		1)
     (UNSPEC_CMPINT		2)
!    (UNSPEC_SETHIGH		10)
  
     ; GOT/PLT and lt-relative accesses
     (UNSPEC_LTREL_OFFSET		100)
--- 98,104 ----
    [; Miscellaneous
     (UNSPEC_ROUND		1)
     (UNSPEC_CMPINT		2)
!    (UNSPEC_ICM			10)
  
     ; GOT/PLT and lt-relative accesses
     (UNSPEC_LTREL_OFFSET		100)
***************
*** 348,357 ****
  ;; and "cfdbr" in SImode.
  (define_mode_attr gf [(DI "g") (SI "f")])
  
- ;; ICM mask required to load MODE value into the highest subreg
- ;; of a SImode register.
- (define_mode_attr icm_hi [(HI "12") (QI "8")])
- 
  ;; ICM mask required to load MODE value into the lowest subreg
  ;; of a SImode register.
  (define_mode_attr icm_lo [(HI "3") (QI "1")])
--- 348,353 ----
***************
*** 2460,2533 ****
  ;;- Conversion instructions.
  ;;
  
! 
! (define_insn "*sethigh<mode>si"
    [(set (match_operand:SI 0 "register_operand" "=d,d")
!         (unspec:SI [(match_operand:HQI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
     (clobber (reg:CC CC_REGNUM))]
    ""
    "@
!    icm\t%0,<icm_hi>,%S1
!    icmy\t%0,<icm_hi>,%S1"
    [(set_attr "op_type" "RS,RSY")])
  
! (define_insn "*sethighqidi_64"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (unspec:DI [(match_operand:QI 1 "s_operand" "QS")] UNSPEC_SETHIGH))
     (clobber (reg:CC CC_REGNUM))]
    "TARGET_64BIT"
!   "icmh\t%0,8,%S1"
    [(set_attr "op_type" "RSY")])
  
! (define_insn "*sethighqidi_31"
    [(set (match_operand:DI 0 "register_operand" "=d,d")
!         (unspec:DI [(match_operand:QI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
     (clobber (reg:CC CC_REGNUM))]
    "!TARGET_64BIT"
    "@
!    icm\t%0,8,%S1
!    icmy\t%0,8,%S1"
    [(set_attr "op_type" "RS,RSY")])
  
! (define_insn_and_split "*extractqi"
!   [(set (match_operand:SI 0 "register_operand" "=d")
!         (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
!                          (match_operand 2 "const_int_operand" "n")
!                          (const_int 0)))
     (clobber (reg:CC CC_REGNUM))]
!   "!TARGET_64BIT
!    && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
       (clobber (reg:CC CC_REGNUM))])
!     (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
  {
!   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
!   operands[1] = change_address (operands[1], QImode, 0);
  })
  
! (define_insn_and_split "*extracthi"
!   [(set (match_operand:SI 0 "register_operand" "=d")
!         (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
!                          (match_operand 2 "const_int_operand" "n")
!                          (const_int 0)))
     (clobber (reg:CC CC_REGNUM))]
!   "!TARGET_64BIT
!    && INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
       (clobber (reg:CC CC_REGNUM))])
!     (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
  {
!   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
!   operands[1] = change_address (operands[1], HImode, 0);
  })
  
  ;
  ; extendsidi2 instruction pattern(s).
  ;
  
--- 2456,2628 ----
  ;;- Conversion instructions.
  ;;
  
! (define_insn "*sethighpartsi"
    [(set (match_operand:SI 0 "register_operand" "=d,d")
! 	(unspec:SI [(match_operand:BLK 1 "s_operand" "Q,S")
! 		    (match_operand:QI 2 "const_int_operand" "n,n")] UNSPEC_ICM))
     (clobber (reg:CC CC_REGNUM))]
    ""
    "@
!    icm\t%0,%2,%S1
!    icmy\t%0,%2,%S1"
    [(set_attr "op_type" "RS,RSY")])
  
! (define_insn "*sethighpartdi_64"
    [(set (match_operand:DI 0 "register_operand" "=d")
! 	(unspec:DI [(match_operand:BLK 1 "s_operand" "QS")
! 		    (match_operand:QI 2 "const_int_operand" "n")] UNSPEC_ICM))
     (clobber (reg:CC CC_REGNUM))]
    "TARGET_64BIT"
!   "icmh\t%0,%2,%S1"
    [(set_attr "op_type" "RSY")])
  
! (define_insn "*sethighpartdi_31"
    [(set (match_operand:DI 0 "register_operand" "=d,d")
! 	(unspec:DI [(match_operand:BLK 1 "s_operand" "Q,S")
! 		    (match_operand:QI 2 "const_int_operand" "n,n")] UNSPEC_ICM))
     (clobber (reg:CC CC_REGNUM))]
    "!TARGET_64BIT"
    "@
!    icm\t%0,%2,%S1
!    icmy\t%0,%2,%S1"
    [(set_attr "op_type" "RS,RSY")])
  
! (define_insn_and_split "*extzv<mode>"
!   [(set (match_operand:GPR 0 "register_operand" "=d")
! 	(zero_extract:GPR (match_operand:QI 1 "s_operand" "QS")
! 		          (match_operand 2 "const_int_operand" "n")
! 		          (const_int 0)))
     (clobber (reg:CC CC_REGNUM))]
!   "INTVAL (operands[2]) > 0
!    && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
       (clobber (reg:CC CC_REGNUM))])
!    (set (match_dup 0) (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
  {
!   int bitsize = INTVAL (operands[2]);
!   int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
!   int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
! 
!   operands[1] = adjust_address (operands[1], BLKmode, 0);
!   set_mem_size (operands[1], GEN_INT (size));
!   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
!   operands[3] = GEN_INT (mask);
  })
  
! (define_insn_and_split "*extv<mode>"
!   [(set (match_operand:GPR 0 "register_operand" "=d")
! 	(sign_extract:GPR (match_operand:QI 1 "s_operand" "QS")
! 		          (match_operand 2 "const_int_operand" "n")
! 		          (const_int 0)))
     (clobber (reg:CC CC_REGNUM))]
!   "INTVAL (operands[2]) > 0
!    && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
       (clobber (reg:CC CC_REGNUM))])
!    (parallel
!     [(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
!      (clobber (reg:CC CC_REGNUM))])]
  {
!   int bitsize = INTVAL (operands[2]);
!   int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
!   int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
! 
!   operands[1] = adjust_address (operands[1], BLKmode, 0);
!   set_mem_size (operands[1], GEN_INT (size));
!   operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
!   operands[3] = GEN_INT (mask);
  })
  
  ;
+ ; insv instruction patterns
+ ;
+ 
+ (define_expand "insv"
+   [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
+ 		      (match_operand 1 "const_int_operand" "")
+ 		      (match_operand 2 "const_int_operand" ""))
+ 	(match_operand 3 "general_operand" ""))]
+   ""
+ {
+   if (s390_expand_insv (operands[0], operands[1], operands[2], operands[3]))
+     DONE;
+   FAIL;
+ })
+ 
+ (define_insn "*insv<mode>_mem_reg"
+   [(set (zero_extract:P (match_operand:QI 0 "memory_operand" "+Q,S")
+ 			(match_operand 1 "const_int_operand" "n,n")
+ 			(const_int 0))
+ 	(match_operand:P 2 "register_operand" "d,d"))]
+   "INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
+    && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
+ {
+     int size = INTVAL (operands[1]) / BITS_PER_UNIT;
+ 
+     operands[1] = GEN_INT ((1ul << size) - 1);
+     return (which_alternative == 0) ? "stcm\t%2,%1,%S0" 
+ 				    : "stcmy\t%2,%1,%S0";
+ }
+ [(set_attr "op_type" "RS,RSY")])
+ 
+ (define_insn "*insvdi_mem_reghigh"
+   [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "+QS")
+ 			 (match_operand 1 "const_int_operand" "n")
+ 			 (const_int 0))
+ 	(lshiftrt:DI (match_operand:DI 2 "register_operand" "d")
+ 		     (const_int 32)))]
+   "TARGET_64BIT
+    && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
+    && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
+ {
+     int size = INTVAL (operands[1]) / BITS_PER_UNIT;
+ 
+     operands[1] = GEN_INT ((1ul << size) - 1);
+     return "stcmh\t%2,%1,%S0";
+ }
+ [(set_attr "op_type" "RSY")])
+ 
+ (define_insn "*insv<mode>_reg_imm"
+   [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
+ 			(const_int 16)
+ 			(match_operand 1 "const_int_operand" "n"))
+ 	(match_operand:P 2 "const_int_operand" "K"))]
+   "TARGET_ZARCH
+    && INTVAL (operands[1]) <= GET_MODE_BITSIZE (Pmode)
+    && INTVAL (operands[1]) % 16 == 0"
+ {
+   switch (INTVAL (operands[1]))
+     {
+       case  0: return "iihh\t%0,%x2"; break;
+       case 16: return "iihl\t%0,%x2"; break;
+       case 32: return "iilh\t%0,%x2"; break;
+       case 48: return "iill\t%0,%x2"; break;
+       default: gcc_unreachable();
+     }
+ }
+ [(set_attr "op_type" "RI")])
+ 
+ (define_insn "*insv<mode>_reg_extimm"
+   [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
+ 			(const_int 32)
+ 			(match_operand 1 "const_int_operand" "n"))
+ 	(match_operand:P 2 "const_int_operand" "Os"))]
+   "TARGET_EXTIMM
+    && INTVAL (operands[1]) <= GET_MODE_BITSIZE (Pmode)
+    && INTVAL (operands[1]) % 32 == 0"
+ {
+   return (INTVAL (operands[1]) == 0) ? "iihf\t%0,%o2"
+ 				     : "iilf\t%0,%o2";
+ }
+ [(set_attr "op_type" "RIL")])
+ 
+ ;
  ; extendsidi2 instruction pattern(s).
  ;
  
***************
*** 2622,2633 ****
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_SETHIGH))
       (clobber (reg:CC CC_REGNUM))])
     (parallel
      [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
       (clobber (reg:CC CC_REGNUM))])]
!   "")
  
  ;
  ; extend(hi|qi)si2 instruction pattern(s).
--- 2717,2731 ----
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:DI [(match_dup 1) (const_int 8)] UNSPEC_ICM))
       (clobber (reg:CC CC_REGNUM))])
     (parallel
      [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
       (clobber (reg:CC CC_REGNUM))])]
! {
!   operands[1] = adjust_address (operands[1], BLKmode, 0);
!   set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
! })
  
  ;
  ; extend(hi|qi)si2 instruction pattern(s).
***************
*** 2692,2703 ****
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
       (clobber (reg:CC CC_REGNUM))])
     (parallel
      [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
       (clobber (reg:CC CC_REGNUM))])]
!   "")
  
  ;
  ; extendqihi2 instruction pattern(s).
--- 2790,2804 ----
    "#"
    "&& reload_completed"
    [(parallel
!     [(set (match_dup 0) (unspec:SI [(match_dup 1) (const_int 8)] UNSPEC_ICM))
       (clobber (reg:CC CC_REGNUM))])
     (parallel
      [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
       (clobber (reg:CC CC_REGNUM))])]
! {
!   operands[1] = adjust_address (operands[1], BLKmode, 0);
!   set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
! })
  
  ;
  ; extendqihi2 instruction pattern(s).


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