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]

[PATCH] S/390 backend update


This patch fixes several bugs in the s390 backend:

- The addsi3_cc and related insns tried to use the condition code
  set by the arithmetic instructions to compare the result of the
  addition/subtraction against zero.  This works most of the time,
  but fails unfortunately if the operation overflows.

  For comparisons of the type > 0 or < 0 this cannot be fixed; so
  we have to generate an explicit compare instruction after the
  add/subtract.  However, for EQ or NE comparisons we can use
  the 'logical' add/subtract instructions instead, which set the
  condition code so that it can reliably be used.

  However, they set the condition code in a different way than 
  most other instructions, therefore some changes to the condition
  code handling have been necessary.

  This change exposed some latent condition code handling bugs
  which are also fixed.

- The load address 'la' instructions performs a 31-bit addition,
  not 32-bit, therefore it must not be used to add non-addresses.
  This patch fixes some cases where the la instruction was used
  incorrectly.

- When using -mno-backchain, in some rare corner cases incorrect
  prolog code was generated.

- The operands 0 and 1 of cmpsi_cct do not commute (thanks to 
  Tod for pointing this out).

In addition, some other changes are included:

- Add the UNORDERED family of comparisons.

- Improve legitimize_address to make better use of the two-register
  (base + index + displacement) addressing mode.
  
Bootstrapped and regtested on s390-ibm-linux and s390x-ibm-linux.
Installed on mainline.

Bye,
Ulrich

ChangeLog:


	* config/s390/s390.h (EXTRA_CC_MODES): Add CCLmode.
	(SELECT_CC_MODE): Use s390_select_ccmode.
	* config/s390/s390-protos.h (s390_select_ccmode): Add.
	* config/s390/s390.c (s390_select_ccmode): New.
	(s390_match_ccmode): Add CCLmode.
	(s390_branch_condition_mask, s390_branch_condition_mnemonic): New.
	(output_branch_condition, output_inverse_branch_condition): Removed.
	(print_operand): Use s390_branch_condition_mnemonic.
	* config/s390/s390.md (addsi3_cc, addsi3_cconly, addsi3_cconly2,
	subsi3_cc, subsi3_cconly): Use logical instructions and CCLmode.
	(bunordered, bordered, buneq, bungt, bunlt, bnuge, bunle, bltgt): New.

	* config/s390/s390.c (check_and_change_labels): Preserve CC mode
	when converting conditional branches to far branches.
	* config/s390/s390.md (cmpstr_const, cmpstr_64, cmpstr_31, cmpint_si,
	cmpint_di): Use CCSmode instead of CCUmode.

	* config/s390/s390.c (legitimate_la_operand_p): New.
	* config/s390/s390-protos.h (legitimate_la_operand_p): Add.
	* config/s390/s390.md (movsi): Convert load address patterns to
	arithmetic operations when necessary.
	(addaddr_picR, addaddr_picL, addaddr_picN): Removed.
	(do_la): Renamed to *do_la and use legitimate_la_operand_p.
	(*do_la_reg_0): Don't use before reload.

	* config/s390/s390.c (legitimize_address): Make more efficient
	use of two-register addressing mode.

	* config/s390/s390.c (s390_function_prologue): Fix incorrect prolog
	with -mno-backchain in some corner cases.

	* config/s390/s390.md (cmpsi_cct): Operands 0 and 1 do not commute.


Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.3
diff -c -p -r1.3 s390-protos.h
*** s390-protos.h	2001/08/18 20:25:53	1.3
--- s390-protos.h	2001/09/29 22:51:51
*************** extern int load_multiple_operation PARAM
*** 42,48 ****
--- 42,50 ----
  extern int store_multiple_operation PARAMS ((rtx, enum machine_mode));
  
  extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
+ extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
  extern int symbolic_reference_mentioned_p PARAMS ((rtx));
+ extern int legitimate_la_operand_p PARAMS ((rtx));
  extern int legitimate_pic_operand_p PARAMS ((rtx));
  extern int legitimate_constant_p PARAMS ((rtx));
  extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.8
diff -c -p -r1.8 s390.c
*** s390.c	2001/09/21 11:41:43	1.8
--- s390.c	2001/09/29 22:51:57
*************** struct s390_address
*** 94,104 ****
  };
  
  static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));
  static int base_n_index_p PARAMS ((rtx));
  static int check_mode PARAMS ((rtx, enum machine_mode *));
  static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
- static void output_branch_condition PARAMS ((FILE *, rtx));
- static void output_inverse_branch_condition PARAMS ((FILE *, rtx));
  static int reg_used_in_mem_p PARAMS ((int, rtx));
  static int addr_generation_dependency_p PARAMS ((rtx, rtx));
  static int other_chunk PARAMS ((int *, int, int));
--- 94,104 ----
  };
  
  static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));
+ static int s390_branch_condition_mask PARAMS ((rtx));
+ static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int));
  static int base_n_index_p PARAMS ((rtx));
  static int check_mode PARAMS ((rtx, enum machine_mode *));
  static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
  static int reg_used_in_mem_p PARAMS ((int, rtx));
  static int addr_generation_dependency_p PARAMS ((rtx, rtx));
  static int other_chunk PARAMS ((int *, int, int));
*************** s390_match_ccmode_set (set, req_mode)
*** 135,143 ****
    set_mode = GET_MODE (SET_DEST (set));
    switch (set_mode)
      {
-     case CCmode:
-       return 0;
- 
      case CCSmode:
        if (req_mode != CCSmode)
          return 0;
--- 135,140 ----
*************** s390_match_ccmode_set (set, req_mode)
*** 146,151 ****
--- 143,152 ----
        if (req_mode != CCUmode)
          return 0;
        break;
+     case CCLmode:
+       if (req_mode != CCLmode)
+         return 0;
+       break;
      case CCZmode:
        if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode)
          return 0;
*************** s390_match_ccmode (insn, req_mode)
*** 184,189 ****
--- 185,345 ----
    return 1;
  }
  
+ /* Given a comparison code OP (EQ, NE, etc.) and the operands 
+    OP0 and OP1 of a COMPARE, return the mode to be used for the 
+    comparison.  */
+ 
+ enum machine_mode
+ s390_select_ccmode (code, op0, op1) 
+      enum rtx_code code;
+      rtx op0;
+      rtx op1;
+ {
+   switch (code)
+     {
+       case EQ:
+       case NE:
+ 	if (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
+ 	    || GET_CODE (op1) == NEG)
+ 	  return CCLmode;
+ 
+ 	return CCZmode;
+ 
+       case LE:
+       case LT:
+       case GE:
+       case GT:
+       case UNORDERED:
+       case ORDERED:
+       case UNEQ:
+       case UNLE:
+       case UNLT:
+       case UNGE:
+       case UNGT:
+       case LTGT:
+ 	return CCSmode;
+ 
+       case LEU:
+       case LTU:
+       case GEU:
+       case GTU:
+ 	return CCUmode;
+ 
+       default:
+ 	abort ();
+     }
+ }
+ 
+ /* Return branch condition mask to implement a branch 
+    specified by CODE.  */
+ 
+ static int
+ s390_branch_condition_mask (code)
+     rtx code;
+ { 
+   const int CC0 = 1 << 3;
+   const int CC1 = 1 << 2;
+   const int CC2 = 1 << 1;
+   const int CC3 = 1 << 0;
+ 
+   if (GET_CODE (XEXP (code, 0)) != REG
+       || REGNO (XEXP (code, 0)) != CC_REGNUM
+       || XEXP (code, 1) != const0_rtx)
+     abort ();
+ 
+   switch (GET_MODE (XEXP (code, 0)))
+     {
+     case CCZmode:
+       switch (GET_CODE (code))
+         {
+         case EQ:	return CC0;
+ 	case NE:	return CC1 | CC2 | CC3;
+ 	default:
+ 	  abort ();
+         }
+       break;
+ 
+     case CCLmode:
+       switch (GET_CODE (code))
+         {
+         case EQ:	return CC0 | CC2;
+ 	case NE:	return CC1 | CC3;
+ 	case UNORDERED:	return CC2 | CC3;  /* carry */
+ 	case ORDERED:	return CC0 | CC1;  /* no carry */
+ 	default:
+ 	  abort ();
+         }
+       break;
+ 
+     case CCUmode:
+       switch (GET_CODE (code))
+         {
+         case EQ:	return CC0;
+         case NE:	return CC1 | CC2 | CC3;
+         case LTU:	return CC1;
+         case GTU:	return CC2;
+         case LEU:	return CC0 | CC1;
+         case GEU:	return CC0 | CC2;
+ 	default:
+ 	  abort ();
+         }
+       break;
+ 
+     case CCSmode:
+       switch (GET_CODE (code))
+         {
+         case EQ:	return CC0;
+         case NE:	return CC1 | CC2 | CC3;
+         case LT:	return CC1;
+         case GT:	return CC2;
+         case LE:	return CC0 | CC1;
+         case GE:	return CC0 | CC2;
+ 	case UNORDERED:	return CC3;
+ 	case ORDERED:	return CC0 | CC1 | CC2;
+ 	case UNEQ:	return CC0 | CC3;
+         case UNLT:	return CC1 | CC3;
+         case UNGT:	return CC2 | CC3;
+         case UNLE:	return CC0 | CC1 | CC3;
+         case UNGE:	return CC0 | CC2 | CC3;
+ 	case LTGT:	return CC1 | CC2;
+ 	default:
+ 	  abort ();
+         }
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ /* If INV is false, return assembler mnemonic string to implement 
+    a branch specified by CODE.  If INV is true, return mnemonic 
+    for the corresponding inverted branch.  */
+ 
+ static const char *
+ s390_branch_condition_mnemonic (code, inv)
+      rtx code;
+      int inv;
+ {
+   static const char *mnemonic[16] =
+     {
+       NULL, "o", "h", "nle",
+       "l", "nhe", "lh", "ne",
+       "e", "nlh", "he", "nl",
+       "le", "nh", "no", NULL
+     };
+ 
+   int mask = s390_branch_condition_mask (code);
+ 
+   if (inv)
+     mask ^= 15;
+ 
+   if (mask < 1 || mask > 14)
+     abort ();
+ 
+   return mnemonic[mask];
+ }
+ 
+ 
  /* Change optimizations to be performed, depending on the 
     optimization level.
  
*************** legitimate_address_p (mode, addr, strict
*** 887,892 ****
--- 1043,1082 ----
    return s390_decompose_address (addr, NULL, strict);
  }
  
+ /* Return 1 if OP is a valid operand for the LA instruction.
+    In 31-bit, we need to prove that the result is used as an
+    address, as LA performs only a 31-bit addition.  */
+ 
+ int
+ legitimate_la_operand_p (op)
+      register rtx op;
+ {
+   struct s390_address addr;
+   if (!s390_decompose_address (op, &addr, FALSE))
+     return FALSE;
+ 
+   if (TARGET_64BIT)
+     return TRUE;
+ 
+   /* Use of the base or stack pointer implies address.  */
+ 
+   if (addr.base && GET_CODE (addr.base) == REG)
+     {
+       if (REGNO (addr.base) == BASE_REGISTER
+           || REGNO (addr.base) == STACK_POINTER_REGNUM)
+         return TRUE;
+     }
+ 
+   if (addr.indx && GET_CODE (addr.indx) == REG)
+     {
+       if (REGNO (addr.indx) == BASE_REGISTER
+           || REGNO (addr.indx) == STACK_POINTER_REGNUM)
+         return TRUE;
+     }
+ 
+   return FALSE;
+ }
+ 
  /* Return a legitimate reference for ORIG (an address) using the
     register REG.  If REG is 0, a new pseudo is generated.
  
*************** legitimize_address (x, oldx, mode)
*** 1199,1285 ****
       register rtx oldx ATTRIBUTE_UNUSED;
       enum machine_mode mode ATTRIBUTE_UNUSED;
  {
!   if (flag_pic && SYMBOLIC_CONST (x))
!     return legitimize_pic_address (x, 0);
  
!   return x;
! }
  
  
! /* Output branch condition code of CODE in assembler
!    syntax to stdio stream FILE.  */
  
! static void
! output_branch_condition (file, code)
!      FILE *file;
!      rtx code;
! {
!   switch (GET_CODE (code)) 
      {
!     case EQ:
!       fprintf (file, "e");
!       break;
!     case NE:
!       fprintf (file, "ne");
!       break;
!     case GT:
!     case GTU:
!       fprintf (file, "h");
!       break;
!     case LT:
!     case LTU:
!       fprintf (file, "l");
!       break;
!     case GE:
!     case GEU:
!       fprintf (file, "he");
!       break;
!     case LE:
!     case LEU:
!       fprintf (file, "le");
!       break;
!     default:
!       fatal_insn ("Unknown CC code", code);
!     }
! }
  
! /* Output the inverse of the branch condition code of CODE 
!    in assembler syntax to stdio stream FILE.  */
  
! static void
! output_inverse_branch_condition (file, code)
!      FILE *file;
!      rtx code;
! {
!   switch (GET_CODE (code)) 
!     {
!     case EQ:
!       fprintf (file, "ne");
!       break;
!     case NE:
!       fprintf (file, "e");
!       break;
!     case GT:
!     case GTU:
!       fprintf (file, "nh");
!       break;
!     case LT:
!     case LTU:
!       fprintf (file, "nl");
!       break;
!     case GE:
!     case GEU:
!       fprintf (file, "nhe");
!       break;
!     case LE:
!     case LEU:
!       fprintf (file, "nle");
!       break;
!     default:
!       fatal_insn ("Unknown CC code", code);
      }
  }
  
  /* Output symbolic constant X in assembler syntax to 
     stdio stream FILE.  */
  
--- 1389,1440 ----
       register rtx oldx ATTRIBUTE_UNUSED;
       enum machine_mode mode ATTRIBUTE_UNUSED;
  {
!   rtx constant_term = const0_rtx;
  
!   if (flag_pic)
!     {
!       if (SYMBOLIC_CONST (x)
!           || (GET_CODE (x) == PLUS 
!               && (SYMBOLIC_CONST (XEXP (x, 0)) 
!                   || SYMBOLIC_CONST (XEXP (x, 1)))))
! 	  x = legitimize_pic_address (x, 0);
  
+       if (legitimate_address_p (mode, x, FALSE))
+ 	return x;
+     }
  
!   x = eliminate_constant_term (x, &constant_term);
  
!   if (GET_CODE (x) == PLUS)
      {
!       if (GET_CODE (XEXP (x, 0)) == REG)
! 	{
! 	  register rtx temp = gen_reg_rtx (Pmode);
! 	  register rtx val  = force_operand (XEXP (x, 1), temp);
! 	  if (val != temp)
! 	    emit_move_insn (temp, val);
  
! 	  x = gen_rtx_PLUS (Pmode, XEXP (x, 0), temp);
! 	}
  
!       else if (GET_CODE (XEXP (x, 1)) == REG)
! 	{
! 	  register rtx temp = gen_reg_rtx (Pmode);
! 	  register rtx val  = force_operand (XEXP (x, 0), temp);
! 	  if (val != temp)
! 	    emit_move_insn (temp, val);
! 
! 	  x = gen_rtx_PLUS (Pmode, temp, XEXP (x, 1));
! 	}
      }
+ 
+   if (constant_term != const0_rtx)
+     x = gen_rtx_PLUS (Pmode, x, constant_term);
+ 
+   return x;
  }
  
+ 
  /* Output symbolic constant X in assembler syntax to 
     stdio stream FILE.  */
  
*************** print_operand (file, x, code)
*** 1417,1427 ****
    switch (code)
      {
      case 'C':
!       output_branch_condition (file, x);
        return;
  
      case 'D':
!       output_inverse_branch_condition (file, x);
        return;
  
      case 'Y':
--- 1572,1582 ----
    switch (code)
      {
      case 'C':
!       fprintf (file, s390_branch_condition_mnemonic (x, FALSE));
        return;
  
      case 'D':
!       fprintf (file, s390_branch_condition_mnemonic (x, TRUE));
        return;
  
      case 'Y':
*************** check_and_change_labels (insn, ltorg_uid
*** 1806,1812 ****
       int *ltorg_uids;
  {
    rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
!   rtx target, jump;
    rtx pattern, tmp, body, label1;
    int addr0, addr1;
  
--- 1961,1967 ----
       int *ltorg_uids;
  {
    rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
!   rtx target, jump, cjump;
    rtx pattern, tmp, body, label1;
    int addr0, addr1;
  
*************** check_and_change_labels (insn, ltorg_uid
*** 1878,1884 ****
  		    }
  		  
  		  label1 = gen_label_rtx ();
! 		  emit_jump_insn_before (gen_icjump (label1, XEXP (body, 0)), insn);
  		  emit_insn_before (gen_movsi (temp_reg, target), insn);
  		  tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
  		  INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
--- 2033,2042 ----
  		    }
  		  
  		  label1 = gen_label_rtx ();
! 		  cjump = gen_rtx_LABEL_REF (VOIDmode, label1);
! 		  cjump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (body, 0), pc_rtx, cjump);
! 		  cjump = gen_rtx_SET (VOIDmode, pc_rtx, cjump);
! 		  emit_jump_insn_before (cjump, insn);
  		  emit_insn_before (gen_movsi (temp_reg, target), insn);
  		  tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
  		  INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
*************** check_and_change_labels (insn, ltorg_uid
*** 1912,1918 ****
  		    }
  		  
  		  label1 = gen_label_rtx ();
! 		  emit_jump_insn_before (gen_cjump (label1, XEXP (body, 0)), insn);
  		  emit_insn_before (gen_movsi (temp_reg, target), insn);
  		  tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
  		  INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
--- 2070,2079 ----
  		    }
  		  
  		  label1 = gen_label_rtx ();
! 		  cjump = gen_rtx_LABEL_REF (VOIDmode, label1);
! 		  cjump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (body, 0), cjump, pc_rtx);
! 		  cjump = gen_rtx_SET (VOIDmode, pc_rtx, cjump);
! 		  emit_jump_insn_before (cjump, insn);
  		  emit_insn_before (gen_movsi (temp_reg, target), insn);
  		  tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
  		  INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
*************** s390_function_prologue (file, lsize)
*** 2541,2548 ****
  
        /* Decrement stack.  */
  
!       if (TARGET_BACKCHAIN || (STARTING_FRAME_OFFSET +
! 			       lsize + STACK_POINTER_OFFSET > 4095
  			       || frame_pointer_needed
  			       || current_function_calls_alloca))
  	{
--- 2702,2708 ----
  
        /* Decrement stack.  */
  
!       if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
  			       || frame_pointer_needed
  			       || current_function_calls_alloca))
  	{
*************** s390_function_prologue (file, lsize)
*** 2582,2589 ****
  
        /* Generate backchain.  */
  
!       if (TARGET_BACKCHAIN || (STARTING_FRAME_OFFSET + 
! 			       lsize + STACK_POINTER_OFFSET > 4095
  			       || frame_pointer_needed
  			       || current_function_calls_alloca))
  	{
--- 2742,2748 ----
  
        /* Generate backchain.  */
  
!       if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
  			       || frame_pointer_needed
  			       || current_function_calls_alloca))
  	{
Index: gcc/config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.6
diff -c -p -r1.6 s390.h
*** s390.h	2001/09/18 21:51:53	1.6
--- s390.h	2001/09/29 22:52:01
*************** do {                                    
*** 1687,1692 ****
--- 1687,1693 ----
  #define EXTRA_CC_MODES \
  	CC (CCZmode, "CCZ") \
  	CC (CCAmode, "CCA") \
+ 	CC (CCLmode, "CCL") \
  	CC (CCUmode, "CCU") \
  	CC (CCSmode, "CCS") \
  	CC (CCTmode, "CCT")
*************** do {                                    
*** 1694,1706 ****
  /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
     return the mode to be used for the comparison. */
   
! #define SELECT_CC_MODE(OP, X, Y)            \
!  (   (OP) == EQ  || (OP) == NE  ? CCZmode   \
!    : (OP) == LE  || (OP) == LT  ||          \
!      (OP) == GE  || (OP) == GT  ? CCSmode   \
!    : (OP) == LEU || (OP) == LTU ||          \
!      (OP) == GEU || (OP) == GTU ? CCUmode   \
!    : CCmode )
   
   
  /* Define the information needed to generate branch and scc insns.  This is
--- 1695,1701 ----
  /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
     return the mode to be used for the comparison. */
   
! #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
   
   
  /* Define the information needed to generate branch and scc insns.  This is
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.4
diff -c -p -r1.4 s390.md
*** s390.md	2001/09/21 11:41:43	1.4
--- s390.md	2001/09/29 22:52:11
***************
*** 369,375 ****
  
  (define_insn "*cmpsi_cct"
    [(set (reg 33)
!         (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "%d")
  	                  (match_operand:SI 1 "const1_operand" "")
                            (match_operand:SI 2 "immediate_operand"  "I"))
                   (const_int 0)))]
--- 369,375 ----
  
  (define_insn "*cmpsi_cct"
    [(set (reg 33)
!         (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
  	                  (match_operand:SI 1 "const1_operand" "")
                            (match_operand:SI 2 "immediate_operand"  "I"))
                   (const_int 0)))]
***************
*** 856,861 ****
--- 856,874 ----
  
    if (flag_pic && SYMBOLIC_CONST (operands[1]))
      emit_pic_move (operands, SImode);
+ 
+   /* expr.c tries to load an effective address using 
+      force_reg.  This fails because we don't have a 
+      generic load_address pattern.  Convert the move
+      to a proper arithmetic operation instead, unless
+      it is guaranteed to be OK.  */
+   if (GET_CODE (operands[1]) == PLUS
+       && !legitimate_la_operand_p (operands[1]))
+     {
+       operands[1] = force_operand (operands[1], operands[0]);
+       if (operands[1] == operands[0])
+         DONE;
+     }
  }")
  
  (define_insn "*movsi"
***************
*** 1835,1842 ****
  ; Compare a block that is less than 256 bytes in length.
  
  (define_insn "cmpstr_const"
!   [(set (reg:CCU 33)
!         (compare:CCU (match_operand:BLK 0 "s_operand" "oQ")
                       (match_operand:BLK 1 "s_operand" "oQ")))
     (use (match_operand 2 "immediate_operand" "I"))]
    "(unsigned) INTVAL (operands[2]) < 256"
--- 1848,1855 ----
  ; Compare a block that is less than 256 bytes in length.
  
  (define_insn "cmpstr_const"
!   [(set (reg:CCS 33)
!         (compare:CCS (match_operand:BLK 0 "s_operand" "oQ")
                       (match_operand:BLK 1 "s_operand" "oQ")))
     (use (match_operand 2 "immediate_operand" "I"))]
    "(unsigned) INTVAL (operands[2]) < 256"
***************
*** 1848,1855 ****
  ; Compare a block that is larger than 255 bytes in length.
  
  (define_insn "cmpstr_64"
!   [(set (reg:CCU 33)
!         (compare:CCU (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
                       (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0))))
     (clobber (subreg:DI (match_dup 0) 0))
     (clobber (subreg:DI (match_dup 0) 8))
--- 1861,1868 ----
  ; Compare a block that is larger than 255 bytes in length.
  
  (define_insn "cmpstr_64"
!   [(set (reg:CCS 33)
!         (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
                       (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0))))
     (clobber (subreg:DI (match_dup 0) 0))
     (clobber (subreg:DI (match_dup 0) 8))
***************
*** 1862,1869 ****
     (set_attr "type"    "other")])
  
  (define_insn "cmpstr_31"
!   [(set (reg:CCU 33)
!         (compare:CCU (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
                       (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0))))
     (clobber (subreg:SI (match_dup 0) 0))
     (clobber (subreg:SI (match_dup 0) 4))
--- 1875,1882 ----
     (set_attr "type"    "other")])
  
  (define_insn "cmpstr_31"
!   [(set (reg:CCS 33)
!         (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
                       (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0))))
     (clobber (subreg:SI (match_dup 0) 0))
     (clobber (subreg:SI (match_dup 0) 4))
***************
*** 1879,1885 ****
  
  (define_insn "cmpint_si"
    [(set (match_operand:SI 0 "register_operand" "=d")
!         (compare:SI (reg:CCU 33) (const_int 0)))]
    ""
    "*
  {
--- 1892,1898 ----
  
  (define_insn "cmpint_si"
    [(set (match_operand:SI 0 "register_operand" "=d")
!         (compare:SI (reg:CCS 33) (const_int 0)))]
    ""
    "*
  {
***************
*** 1896,1902 ****
  
  (define_insn "cmpint_di"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (compare:DI (reg:CCU 33) (const_int 0)))]
    "TARGET_64BIT"
    "*
  {
--- 1909,1915 ----
  
  (define_insn "cmpint_di"
    [(set (match_operand:DI 0 "register_operand" "=d")
!         (compare:DI (reg:CCS 33) (const_int 0)))]
    "TARGET_64BIT"
    "*
  {
***************
*** 2907,2982 ****
     (set_attr "atype"    "mem")
     (set_attr "type"     "la")])
  
- (define_insn "*addaddr_picR"
-   [(set (match_operand:SI 0 "register_operand" "=d")
-         (plus:SI (match_operand:SI 1 "register_operand" "a")
-                  (unspec:SI [(match_operand:SI 2 "register_operand" "a")] 101)))]
-   ""
-   "la\\t%0,0(%1,%2)"
-   [(set_attr "op_type"  "RX")
-    (set_attr "atype"    "mem")
-    (set_attr "type"     "la")])
- 
- (define_insn "*addaddr_picL"
-   [(set (match_operand:SI 0 "register_operand" "=d")
-         (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "a")] 101)
-                  (match_operand:SI 1 "register_operand" "a")))]
-   ""
-   "la\\t%0,0(%1,%2)"
-   [(set_attr "op_type"  "RX")
-    (set_attr "atype"    "mem")
-    (set_attr "type"     "la")])
- 
- (define_insn "*addaddr_picN"
-   [(set (match_operand:SI 0 "register_operand" "=d")
-         (unspec:SI [(match_operand:SI 1 "register_operand" "a")] 101))]
-   ""
-   "la\\t%0,0(%1)"
-   [(set_attr "op_type"  "RX")
-    (set_attr "atype"    "mem")
-    (set_attr "type"     "la")])
- 
  (define_insn "*addsi3_cc"
    [(set (reg 33) 
!         (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
!                           (match_operand:SI 2 "general_operand" "d,K,m"))
                   (const_int 0)))
!    (set (match_operand:SI 0 "register_operand" "=d,d,d")
          (plus:SI (match_dup 1) (match_dup 2)))]
!   "s390_match_ccmode(insn, CCSmode)"
    "@
!    ar\\t%0,%2
!    ahi\\t%0,%h2
!    a\\t%0,%2"
!   [(set_attr "op_type"  "RR,RI,RX")
!    (set_attr "atype"    "reg,reg,mem")])  
  
  (define_insn "*addsi3_cconly"
    [(set (reg 33) 
!         (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
!                           (match_operand:SI 2 "general_operand" "d,K,m"))
                   (const_int 0)))
!    (clobber (match_scratch:SI 0 "=d,d,d"))]
!   "s390_match_ccmode(insn, CCSmode)"
    "@
!    ar\\t%0,%2
!    ahi\\t%0,%h2
!    a\\t%0,%2"
!   [(set_attr "op_type"  "RR,RI,RX")
!    (set_attr "atype"    "reg,reg,mem")])  
  
  (define_insn "*addsi3_cconly2"
    [(set (reg 33) 
!         (compare (match_operand:SI 1 "register_operand" "%0,0,0")
!                  (neg:SI (match_operand:SI 2 "general_operand" "d,K,m"))))
!    (clobber (match_scratch:SI 0 "=d,d,d"))]
!   "s390_match_ccmode(insn, CCSmode)"
    "@
!    ar\\t%0,%2
!    ahi\\t%0,%h2
!    a\\t%0,%2"
!   [(set_attr "op_type"  "RR,RI,RX")
!    (set_attr "atype"    "reg,reg,mem")])  
  
  (define_insn "addsi3"
    [(set (match_operand:SI 0 "register_operand" "=d,d,d")
--- 2920,2963 ----
     (set_attr "atype"    "mem")
     (set_attr "type"     "la")])
  
  (define_insn "*addsi3_cc"
    [(set (reg 33) 
!         (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
!                           (match_operand:SI 2 "nonimmediate_operand" "d,m"))
                   (const_int 0)))
!    (set (match_operand:SI 0 "register_operand" "=d,d")
          (plus:SI (match_dup 1) (match_dup 2)))]
!   "s390_match_ccmode(insn, CCLmode)"
    "@
!    alr\\t%0,%2
!    al\\t%0,%2"
!   [(set_attr "op_type"  "RR,RX")
!    (set_attr "atype"    "reg,mem")])  
  
  (define_insn "*addsi3_cconly"
    [(set (reg 33) 
!         (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
!                           (match_operand:SI 2 "general_operand" "d,m"))
                   (const_int 0)))
!    (clobber (match_scratch:SI 0 "=d,d"))]
!   "s390_match_ccmode(insn, CCLmode)"
    "@
!    alr\\t%0,%2
!    al\\t%0,%2"
!   [(set_attr "op_type"  "RR,RX")
!    (set_attr "atype"    "reg,mem")])  
  
  (define_insn "*addsi3_cconly2"
    [(set (reg 33) 
!         (compare (match_operand:SI 1 "register_operand" "%0,0")
!                  (neg:SI (match_operand:SI 2 "general_operand" "d,m"))))
!    (clobber (match_scratch:SI 0 "=d,d"))]
!   "s390_match_ccmode(insn, CCLmode)"
    "@
!    alr\\t%0,%2
!    al\\t%0,%2"
!   [(set_attr "op_type"  "RR,RX")
!    (set_attr "atype"    "reg,mem")])  
  
  (define_insn "addsi3"
    [(set (match_operand:SI 0 "register_operand" "=d,d,d")
***************
*** 2991,3000 ****
    [(set_attr "op_type"  "RR,RI,RX")
     (set_attr "atype"    "reg,reg,mem")])
  
! (define_insn "do_la"
    [(set (match_operand:SI 0 "register_operand" "=a")
          (match_operand:QI 1 "address_operand" "p"))]
!   "volatile_ok"
    "la\\t%0,%a1"
    [(set_attr "op_type"  "RX")
     (set_attr "atype"    "mem")
--- 2972,2982 ----
    [(set_attr "op_type"  "RR,RI,RX")
     (set_attr "atype"    "reg,reg,mem")])
  
! (define_insn "*do_la"
    [(set (match_operand:SI 0 "register_operand" "=a")
          (match_operand:QI 1 "address_operand" "p"))]
!   "reload_in_progress || reload_completed
!    || legitimate_la_operand_p (operands[1])"
    "la\\t%0,%a1"
    [(set_attr "op_type"  "RX")
     (set_attr "atype"    "mem")
***************
*** 3004,3010 ****
    [(set (match_operand:SI 0 "register_operand" "=d")
          (plus:SI (match_operand:SI 1 "register_operand" "%0")
                   (match_operand:SI 2 "register_operand" "d")))]
!   ""
    "brxle\\t%0,%2,.+4"
    [(set_attr "op_type" "RSI")
     (set_attr "atype"   "reg")])
--- 2986,2992 ----
    [(set (match_operand:SI 0 "register_operand" "=d")
          (plus:SI (match_operand:SI 1 "register_operand" "%0")
                   (match_operand:SI 2 "register_operand" "d")))]
!   "reload_in_progress || reload_completed"
    "brxle\\t%0,%2,.+4"
    [(set_attr "op_type" "RSI")
     (set_attr "atype"   "reg")])
***************
*** 3220,3229 ****
                   (const_int 0)))
     (set (match_operand:SI 0 "register_operand" "=d,d")
          (minus:SI (match_dup 1) (match_dup 2)))]
!   "s390_match_ccmode(insn, CCSmode)"
    "@
!    sr\\t%0,%2
!    s\\t%0,%2"
    [(set_attr "op_type"  "RR,RX")
     (set_attr "atype"    "reg,mem")])
  
--- 3202,3211 ----
                   (const_int 0)))
     (set (match_operand:SI 0 "register_operand" "=d,d")
          (minus:SI (match_dup 1) (match_dup 2)))]
!   "s390_match_ccmode(insn, CCLmode)"
    "@
!    slr\\t%0,%2
!    sl\\t%0,%2"
    [(set_attr "op_type"  "RR,RX")
     (set_attr "atype"    "reg,mem")])
  
***************
*** 3233,3242 ****
                             (match_operand:SI 2 "general_operand" "d,m"))
                   (const_int 0)))
     (clobber (match_scratch:SI 0 "=d,d"))]
!   "s390_match_ccmode(insn, CCSmode)"
    "@
!    sr\\t%0,%2
!    s\\t%0,%2"
    [(set_attr "op_type"  "RR,RX")
     (set_attr "atype"    "reg,mem")])
  
--- 3215,3224 ----
                             (match_operand:SI 2 "general_operand" "d,m"))
                   (const_int 0)))
     (clobber (match_scratch:SI 0 "=d,d"))]
!   "s390_match_ccmode(insn, CCLmode)"
    "@
!    slr\\t%0,%2
!    sl\\t%0,%2"
    [(set_attr "op_type"  "RR,RX")
     (set_attr "atype"    "reg,mem")])
  
***************
*** 4940,4945 ****
--- 4922,4999 ----
    [(set (reg:CCU 33) (compare:CCU (match_dup 1) (match_dup 2)))
     (set (pc)
          (if_then_else (leu (reg:CCU 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bunordered"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (unordered (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bordered"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (ordered (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "buneq"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (uneq (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bungt"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (ungt (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bunlt"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (unlt (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bunge"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (unge (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bunle"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (unle (reg:CCS 33) (const_int 0))
+                       (label_ref (match_operand 0 "" ""))
+                       (pc)))]
+   ""
+   "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+ 
+ (define_expand "bltgt"
+   [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+    (set (pc)
+         (if_then_else (ltgt (reg:CCS 33) (const_int 0))
                        (label_ref (match_operand 0 "" ""))
                        (pc)))]
    ""
-- 
  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]