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]

S/390: Add ALC/SLB patterns


Hello,

this adds the add-with-carry/subtract-with-borrow type instructions
supported on zSeries machines.  It does not yet make full use of those,
however, because doing so exposes a combine bug that needs to be
fixed first, see:
http://gcc.gnu.org/ml/gcc-patches/2003-07/msg01786.html

One very important case is already enabled: 'long long' operations
in 31-bit mode on zSeries machines now use ALC/SLB; in a cc1
binary compiled with --with-arch=z900 those insns are used
at about 900 places.

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux as well
as s390-ibm-linux configured with --with-arch=z900.
Applied to CVS head.

Bye,
Ulrich

ChangeLog:

	* config/s390/s390-protos.h (s390_alc_comparison): Add prototype.
	(s390_slb_comparison): Likewise.
	* config/s390/s390.c (s390_alc_comparison, s390_slb_comparison):
	New functions.
	* config/s390/s390.h (PREDICATE_CODES): Add s390_alc_comparison
	and s390_slb_comparison.
	* config/s390/s390.md ("*adddi3_31", "*subdi3_31"): Do not use on 
	zSeries machines.
	("*adddi3_31z", "*subdi3_31z"): New insns.
	("*adddi3_alc_cc", "*adddi3_alc", "*subdi3_slb_cc", "*subdi3_slb",
	"*addsi3_alc_cc", "*addsi3_alc", "*subsi3_slb_cc", "*subsi3_slb"):
	New insns.
	
Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.36
diff -c -p -r1.36 s390-protos.h
*** gcc/config/s390/s390-protos.h	23 Aug 2003 00:17:35 -0000	1.36
--- gcc/config/s390/s390-protos.h	14 Oct 2003 19:27:37 -0000
*************** extern int tls_symbolic_operand (rtx);
*** 49,54 ****
--- 49,56 ----
  extern int s390_match_ccmode (rtx, enum machine_mode);
  extern enum machine_mode s390_tm_ccmode (rtx, rtx, int);
  extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
+ extern int s390_alc_comparison (rtx op, enum machine_mode mode);
+ extern int s390_slb_comparison (rtx op, enum machine_mode mode);
  extern int symbolic_reference_mentioned_p (rtx);
  extern int tls_symbolic_reference_mentioned_p (rtx);
  extern rtx s390_tls_get_offset (void);
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.114
diff -c -p -r1.114 s390.c
*** gcc/config/s390/s390.c	25 Sep 2003 21:38:43 -0000	1.114
--- gcc/config/s390/s390.c	14 Oct 2003 19:27:39 -0000
*************** s390_select_ccmode (enum rtx_code code, 
*** 447,452 ****
--- 447,536 ----
      }
  }
  
+ /* Return nonzero if OP is a valid comparison operator
+    for an ALC condition in mode MODE.  */
+ 
+ int
+ s390_alc_comparison (rtx op, enum machine_mode mode)
+ {
+   if (mode != VOIDmode && mode != GET_MODE (op))
+     return 0;
+ 
+   if (GET_RTX_CLASS (GET_CODE (op)) != '<')
+     return 0;
+ 
+   if (GET_CODE (XEXP (op, 0)) != REG
+       || REGNO (XEXP (op, 0)) != CC_REGNUM
+       || XEXP (op, 1) != const0_rtx)
+     return 0;
+ 
+   switch (GET_MODE (XEXP (op, 0)))
+     {
+     case CCL1mode:
+       return GET_CODE (op) == LTU;
+ 
+     case CCL2mode:
+       return GET_CODE (op) == LEU;
+ 
+     case CCUmode:
+       return GET_CODE (op) == GTU;
+ 
+     case CCURmode:
+       return GET_CODE (op) == LTU;
+ 
+     case CCSmode:
+       return GET_CODE (op) == UNGT;
+ 
+     case CCSRmode:
+       return GET_CODE (op) == UNLT;
+ 
+     default:
+       return 0;
+     }
+ }
+ 
+ /* Return nonzero if OP is a valid comparison operator
+    for an SLB condition in mode MODE.  */
+ 
+ int
+ s390_slb_comparison (rtx op, enum machine_mode mode)
+ {
+   if (mode != VOIDmode && mode != GET_MODE (op))
+     return 0;
+ 
+   if (GET_RTX_CLASS (GET_CODE (op)) != '<')
+     return 0;
+ 
+   if (GET_CODE (XEXP (op, 0)) != REG
+       || REGNO (XEXP (op, 0)) != CC_REGNUM
+       || XEXP (op, 1) != const0_rtx)
+     return 0;
+ 
+   switch (GET_MODE (XEXP (op, 0)))
+     {
+     case CCL1mode:
+       return GET_CODE (op) == GEU;
+ 
+     case CCL2mode:
+       return GET_CODE (op) == GTU;
+ 
+     case CCUmode:
+       return GET_CODE (op) == LEU;
+ 
+     case CCURmode:
+       return GET_CODE (op) == GEU;
+ 
+     case CCSmode:
+       return GET_CODE (op) == LE;
+ 
+     case CCSRmode:
+       return GET_CODE (op) == GE;
+ 
+     default:
+       return 0;
+     }
+ }
+ 
  /* Return branch condition mask to implement a branch
     specified by CODE.  */
  
Index: gcc/config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.86
diff -c -p -r1.86 s390.h
*** gcc/config/s390/s390.h	13 Oct 2003 17:01:01 -0000	1.86
--- gcc/config/s390/s390.h	14 Oct 2003 19:27:39 -0000
*************** do {									\
*** 1030,1036 ****
    {"const0_operand",  { CONST_INT, CONST_DOUBLE }},			\
    {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, 		\
  			   CONST_INT, CONST_DOUBLE }},			\
!   {"s390_plus_operand", { PLUS }},
  
  /* Specify the machine mode that this machine uses for the index in the
     tablejump instruction.  */
--- 1030,1038 ----
    {"const0_operand",  { CONST_INT, CONST_DOUBLE }},			\
    {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, 		\
  			   CONST_INT, CONST_DOUBLE }},			\
!   {"s390_plus_operand", { PLUS }},					\
!   {"s390_alc_comparison", { LTU, GTU, LEU, GEU }},			\
!   {"s390_slb_comparison", { LTU, GTU, LEU, GEU }},
  
  /* Specify the machine mode that this machine uses for the index in the
     tablejump instruction.  */
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.79
diff -c -p -r1.79 s390.md
*** gcc/config/s390/s390.md	14 Oct 2003 19:21:45 -0000	1.79
--- gcc/config/s390/s390.md	14 Oct 2003 19:27:41 -0000
***************
*** 3254,3265 ****
     ag\t%0,%2"
    [(set_attr "op_type"  "RRE,RI,RXY")])
  
  (define_insn_and_split "*adddi3_31"
    [(set (match_operand:DI 0 "register_operand" "=&d")
          (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
                   (match_operand:DI 2 "general_operand" "do") ) )
     (clobber (reg:CC 33))]
!   "!TARGET_64BIT"
    "#"
    "&& reload_completed"
    [(parallel
--- 3254,3290 ----
     ag\t%0,%2"
    [(set_attr "op_type"  "RRE,RI,RXY")])
  
+ (define_insn_and_split "*adddi3_31z"
+   [(set (match_operand:DI 0 "register_operand" "=&d")
+         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+                  (match_operand:DI 2 "general_operand" "do") ) )
+    (clobber (reg:CC 33))]
+   "!TARGET_64BIT && TARGET_CPU_ZARCH"
+   "#"
+   "&& reload_completed"
+   [(parallel
+     [(set (reg:CCL1 33)
+           (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
+                         (match_dup 7)))
+      (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
+    (parallel
+     [(set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
+                                  (ltu:SI (reg:CCL1 33) (const_int 0))))
+      (clobber (reg:CC 33))])]
+   "operands[3] = operand_subword (operands[0], 0, 0, DImode);
+    operands[4] = operand_subword (operands[1], 0, 0, DImode);
+    operands[5] = operand_subword (operands[2], 0, 0, DImode);
+    operands[6] = operand_subword (operands[0], 1, 0, DImode);
+    operands[7] = operand_subword (operands[1], 1, 0, DImode);
+    operands[8] = operand_subword (operands[2], 1, 0, DImode);"
+   [(set_attr "op_type"  "NN")])
+ 
  (define_insn_and_split "*adddi3_31"
    [(set (match_operand:DI 0 "register_operand" "=&d")
          (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
                   (match_operand:DI 2 "general_operand" "do") ) )
     (clobber (reg:CC 33))]
!   "!TARGET_CPU_ZARCH"
    "#"
    "&& reload_completed"
    [(parallel
***************
*** 3804,3815 ****
     sg\t%0,%2"
    [(set_attr "op_type"  "RRE,RRE")])
  
  (define_insn_and_split "*subdi3_31"
    [(set (match_operand:DI 0 "register_operand" "=&d")
          (minus:DI (match_operand:DI 1 "register_operand" "0")
                    (match_operand:DI 2 "general_operand" "do") ) )
     (clobber (reg:CC 33))]
!   "!TARGET_64BIT"
    "#"
    "&& reload_completed"
    [(parallel
--- 3829,3865 ----
     sg\t%0,%2"
    [(set_attr "op_type"  "RRE,RRE")])
  
+ (define_insn_and_split "*subdi3_31z"
+   [(set (match_operand:DI 0 "register_operand" "=&d")
+         (minus:DI (match_operand:DI 1 "register_operand" "0")
+                   (match_operand:DI 2 "general_operand" "do") ) )
+    (clobber (reg:CC 33))]
+   "!TARGET_64BIT && TARGET_CPU_ZARCH"
+   "#"
+   "&& reload_completed"
+   [(parallel
+     [(set (reg:CCL2 33)
+           (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
+                         (match_dup 7)))
+      (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
+    (parallel
+     [(set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
+                                   (gtu:SI (reg:CCL2 33) (const_int 0))))
+      (clobber (reg:CC 33))])]
+   "operands[3] = operand_subword (operands[0], 0, 0, DImode);
+    operands[4] = operand_subword (operands[1], 0, 0, DImode);
+    operands[5] = operand_subword (operands[2], 0, 0, DImode);
+    operands[6] = operand_subword (operands[0], 1, 0, DImode);
+    operands[7] = operand_subword (operands[1], 1, 0, DImode);
+    operands[8] = operand_subword (operands[2], 1, 0, DImode);"
+   [(set_attr "op_type"  "NN")])
+ 
  (define_insn_and_split "*subdi3_31"
    [(set (match_operand:DI 0 "register_operand" "=&d")
          (minus:DI (match_operand:DI 1 "register_operand" "0")
                    (match_operand:DI 2 "general_operand" "do") ) )
     (clobber (reg:CC 33))]
!   "!TARGET_CPU_ZARCH"
    "#"
    "&& reload_completed"
    [(parallel
***************
*** 4055,4060 ****
--- 4105,4231 ----
     se\t%0,%2"
    [(set_attr "op_type"  "RR,RX")
     (set_attr "type"     "fsimps,fsimps")])
+ 
+ 
+ ;;
+ ;;- Conditional add/subtract instructions.
+ ;;
+ 
+ ;
+ ; adddicc instruction pattern(s).
+ ;
+ 
+ (define_insn "*adddi3_alc_cc"
+   [(set (reg 33) 
+         (compare
+           (plus:DI (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+                             (match_operand:DI 2 "general_operand" "d,m"))
+                    (match_operand:DI 3 "s390_alc_comparison" ""))
+           (const_int 0)))
+    (set (match_operand:DI 0 "register_operand" "=d,d")
+         (plus:DI (plus:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+   "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT" 
+   "@
+    alcgr\\t%0,%2
+    alcg\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ (define_insn "*adddi3_alc"
+   [(set (match_operand:DI 0 "register_operand" "=d,d")
+         (plus:DI (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+                           (match_operand:DI 2 "general_operand" "d,m"))
+                  (match_operand:DI 3 "s390_alc_comparison" "")))
+    (clobber (reg:CC 33))] 
+   "TARGET_64BIT" 
+   "@
+    alcgr\\t%0,%2
+    alcg\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ (define_insn "*subdi3_slb_cc"
+   [(set (reg 33) 
+         (compare
+           (minus:DI (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                               (match_operand:DI 2 "general_operand" "d,m"))
+                     (match_operand:DI 3 "s390_slb_comparison" ""))
+           (const_int 0)))
+    (set (match_operand:DI 0 "register_operand" "=d,d")
+         (minus:DI (minus:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+   "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT" 
+   "@
+    slbgr\\t%0,%2
+    slbg\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ (define_insn "*subdi3_slb"
+   [(set (match_operand:DI 0 "register_operand" "=d,d")
+         (minus:DI (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                             (match_operand:DI 2 "general_operand" "d,m"))
+                   (match_operand:DI 3 "s390_slb_comparison" "")))
+    (clobber (reg:CC 33))] 
+   "TARGET_64BIT" 
+   "@
+    slbgr\\t%0,%2
+    slbg\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ ;
+ ; addsicc instruction pattern(s).
+ ;
+ 
+ (define_insn "*addsi3_alc_cc"
+   [(set (reg 33) 
+         (compare
+           (plus:SI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+                             (match_operand:SI 2 "general_operand" "d,m"))
+                    (match_operand:SI 3 "s390_alc_comparison" ""))
+           (const_int 0)))
+    (set (match_operand:SI 0 "register_operand" "=d,d")
+         (plus:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+   "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH" 
+   "@
+    alcr\\t%0,%2
+    alc\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ (define_insn "*addsi3_alc"
+   [(set (match_operand:SI 0 "register_operand" "=d,d")
+         (plus:SI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+                           (match_operand:SI 2 "general_operand" "d,m"))
+                  (match_operand:SI 3 "s390_alc_comparison" "")))
+    (clobber (reg:CC 33))]
+   "TARGET_CPU_ZARCH" 
+   "@
+    alcr\\t%0,%2
+    alc\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ (define_insn "*subsi3_slb_cc"
+   [(set (reg 33) 
+         (compare
+           (minus:SI (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+                               (match_operand:SI 2 "general_operand" "d,m"))
+                     (match_operand:SI 3 "s390_slb_comparison" ""))
+           (const_int 0)))
+    (set (match_operand:SI 0 "register_operand" "=d,d")
+         (minus:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+   "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH" 
+   "@
+    slbr\\t%0,%2
+    slb\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
+ 
+ (define_insn "*subsi3_slb"
+   [(set (match_operand:SI 0 "register_operand" "=d,d")
+         (minus:SI (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+                             (match_operand:SI 2 "general_operand" "d,m"))
+                   (match_operand:SI 3 "s390_slb_comparison" "")))
+    (clobber (reg:CC 33))] 
+   "TARGET_CPU_ZARCH" 
+   "@
+    slbr\\t%0,%2
+    slb\\t%0,%2"
+   [(set_attr "op_type"  "RRE,RXY")])
  
  
  ;;
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de


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