s390-modes.def (CCAPmode, CCANmode): New CC modes.
authorUlrich Weigand <uweigand@de.ibm.com>
Thu, 12 Sep 2002 12:37:17 +0000 (12:37 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Thu, 12 Sep 2002 12:37:17 +0000 (12:37 +0000)
* config/s390/s390-modes.def (CCAPmode, CCANmode): New CC modes.
* config/s390/s390.c (s390_match_ccmode_set): Support new CC modes.
(s390_select_ccmode): Likewise.
(s390_branch_condition_mask): Likewise.
(optimization_options): Do not set flag_branch_on_count.
(s390_split_branches): Handle doloop branches.
(s390_chunkify_pool): Likewise.
* config/s390/s390.md ("*adddi3_imm_cc", "*addsi3_imm_cc"): New insns.
("doloop_end"): New expander.
("doolop_si", "*doloop_si_long", "doloop_di", "*doloop_di_long",
associated splitters): New.

From-SVN: r57060

gcc/ChangeLog
gcc/config/s390/s390-modes.def
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 914ae17b2fb4c332a7eb72cdb602cc329685d342..96ccecc8b94bc103704d2a51fd850a62632a41c9 100644 (file)
@@ -1,3 +1,17 @@
+2002-09-12  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390-modes.def (CCAPmode, CCANmode): New CC modes.
+       * config/s390/s390.c (s390_match_ccmode_set): Support new CC modes.
+       (s390_select_ccmode): Likewise.
+       (s390_branch_condition_mask): Likewise.
+       (optimization_options): Do not set flag_branch_on_count.
+       (s390_split_branches): Handle doloop branches.
+       (s390_chunkify_pool): Likewise.
+       * config/s390/s390.md ("*adddi3_imm_cc", "*addsi3_imm_cc"): New insns.
+       ("doloop_end"): New expander.
+       ("doolop_si", "*doloop_si_long", "doloop_di", "*doloop_di_long",
+       associated splitters): New.
+
 2002-09-11  Hartmut Penner  <hpenner@de.ibm.com>
 
        * fold-const.c (make_range): Only narrow to signed range if
index db577aa90ae5602b40f7e2312f45e96419bbf230..9f9d5265720e987d9937e74a31087c038345b65b 100644 (file)
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA.  */
 
 CC (CCZ)
 CC (CCA)
+CC (CCAP)
+CC (CCAN)
 CC (CCL)
 CC (CCL1)
 CC (CCL2)
index d390d0a502569662c0f62d9f514d43a349712394..26c4dd2fe3d5430711741ab64ca3b36ee82abc39 100644 (file)
@@ -182,6 +182,12 @@ s390_match_ccmode_set (set, req_mode)
          && req_mode != CCSRmode && req_mode != CCURmode)
         return 0;
       break;
+
+    case CCAPmode:
+    case CCANmode:
+      if (req_mode != CCAmode)
+        return 0;
+      break;
  
     default:
       abort ();
@@ -274,6 +280,9 @@ s390_select_ccmode (code, op0, op1)
     {
       case EQ:
       case NE:
+       if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
+           && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K')) 
+         return CCAPmode;
        if (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
            || GET_CODE (op1) == NEG)
          return CCLmode;
@@ -306,6 +315,14 @@ s390_select_ccmode (code, op0, op1)
       case LT:
       case GE:
       case GT:
+         if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
+             && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K')) 
+            {
+             if (INTVAL (XEXP((op0), 1)) < 0)
+               return CCANmode;
+              else
+               return CCAPmode;
+           }
       case UNORDERED:
       case ORDERED:
       case UNEQ:
@@ -461,6 +478,34 @@ s390_branch_condition_mask (code)
         }
       break;
 
+    case CCAPmode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC0;
+        case NE:       return CC1 | CC2 | CC3;
+        case LT:       return CC1 | CC3;
+        case GT:       return CC2;
+        case LE:       return CC0 | CC1 | CC3;
+        case GE:       return CC0 | CC2;
+       default:
+         abort ();
+        }
+      break;
+
+    case CCANmode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC0;
+        case NE:       return CC1 | CC2 | CC3;
+        case LT:       return CC1;
+        case GT:       return CC2 | CC3;
+        case LE:       return CC0 | CC1;
+        case GE:       return CC0 | CC2 | CC3;
+       default:
+         abort ();
+        }
+      break;
+
     case CCSmode:
       switch (GET_CODE (code))
         {
@@ -758,11 +803,6 @@ optimization_options (level, size)
      int level ATTRIBUTE_UNUSED;
      int size ATTRIBUTE_UNUSED;
 {
-#ifdef HAVE_decrement_and_branch_on_count
-  /* When optimizing, enable use of BRCT instruction.  */
-  if (level >= 1)
-      flag_branch_on_count_reg = 1;
-#endif
 }
 
 void
@@ -2605,12 +2645,8 @@ static void
 s390_split_branches ()
 {
   rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
-  rtx insn, pat, label, target, jump, tmp;
-
-  /* In 64-bit mode we can jump +- 4GB.  */
-
-  if (TARGET_64BIT)
-    return;
+  rtx insn, pat, tmp, target;
+  rtx *label;
 
   /* We need correct insn addresses.  */
 
@@ -2624,62 +2660,61 @@ s390_split_branches ()
        continue;
 
       pat = PATTERN (insn);
-      if (GET_CODE (pat) != SET)
+      if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
+       pat = XVECEXP (pat, 0, 0);
+      if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
        continue;
 
       if (GET_CODE (SET_SRC (pat)) == LABEL_REF) 
        {
-         label = SET_SRC (pat);
+         label = &SET_SRC (pat);
        } 
       else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE) 
        {
          if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF) 
-           label = XEXP (SET_SRC (pat), 1);
+           label = &XEXP (SET_SRC (pat), 1);
           else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF) 
-            label = XEXP (SET_SRC (pat), 2);
+            label = &XEXP (SET_SRC (pat), 2);
          else
            continue;
         }
       else
        continue;
 
-      if (get_attr_length (insn) == 4)
+      if (get_attr_length (insn) <= (TARGET_64BIT ? 6 : 4))
        continue;
 
       regs_ever_live[RETURN_REGNUM] = 1;
 
-      if (flag_pic)
+      if (TARGET_64BIT)
        {
-         target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, label), 100);
-         target = gen_rtx_CONST (SImode, target);
-         target = force_const_mem (SImode, target);
-         jump = gen_rtx_REG (Pmode, BASE_REGISTER);
-         jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
+         tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, *label), insn);
+         INSN_ADDRESSES_NEW (tmp, -1);
+
+         target = temp_reg;
        }
-      else
+      else if (!flag_pic)
        {
-         target = force_const_mem (Pmode, label);
-         jump = temp_reg;
-       }
+         tmp = force_const_mem (Pmode, *label);
+         tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
+         INSN_ADDRESSES_NEW (tmp, -1);
 
-      if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
+         target = temp_reg;
+       }
+      else
        {
-         if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
-           jump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (SET_SRC (pat), 0),
-                                        jump, pc_rtx);
-         else
-           jump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (SET_SRC (pat), 0),
-                                        pc_rtx, jump);
+         tmp = gen_rtx_UNSPEC (SImode, gen_rtvec (1, *label), 100);
+         tmp = gen_rtx_CONST (SImode, tmp);
+         tmp = force_const_mem (SImode, tmp);
+         tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
+         INSN_ADDRESSES_NEW (tmp, -1);
+
+         target = gen_rtx_REG (Pmode, BASE_REGISTER);
+         target = gen_rtx_PLUS (Pmode, target, temp_reg);
        }
 
-      tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
-      INSN_ADDRESSES_NEW (tmp, -1);
-
-      tmp = emit_jump_insn_before (gen_rtx_SET (VOIDmode, pc_rtx, jump), insn);
-      INSN_ADDRESSES_NEW (tmp, -1);
-
-      remove_insn (insn);
-      insn = tmp;
+      if (!validate_change (insn, label, target, 0))
+       abort ();
     }
 }
 
@@ -3177,6 +3212,9 @@ s390_chunkify_pool ()
       else if (GET_CODE (insn) == JUMP_INSN) 
        {
           rtx pat = PATTERN (insn);
+         if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
+           pat = XVECEXP (pat, 0, 0);
+
           if (GET_CODE (pat) == SET) 
             {
              rtx label = 0;
index 561b1b0986bbdcabcb814e03e559a84c143f4c7b..3974e21cfd446823e1b26ef2d78578f6f502a0f9 100644 (file)
   [(set_attr "op_type"  "RRE,RXE")
    (set_attr "atype"    "reg,mem")])
 
+(define_insn "*adddi3_imm_cc"
+  [(set (reg 33) 
+        (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                          (match_operand:DI 2 "const_int_operand" "K"))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d")
+        (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT         
+   && s390_match_ccmode (insn, CCAmode) 
+   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+  "aghi\\t%0,%h2"
+  [(set_attr "op_type"  "RI")
+   (set_attr "atype"    "reg")])  
+
 (define_insn "*adddi3_cc"
   [(set (reg 33) 
         (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
     (set_attr "atype"    "mem")
     (set_attr "type"     "la")])
 
+(define_insn "*addsi3_imm_cc"
+  [(set (reg 33) 
+        (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+                          (match_operand:SI 2 "const_int_operand" "K"))
+                 (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode (insn, CCAmode)
+   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+  "ahi\\t%0,%h2"
+  [(set_attr "op_type"  "RI")
+   (set_attr "atype"    "reg")])  
+
 (define_insn "*addsi3_carry1_cc"
   [(set (reg 33) 
         (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
 
 
 ;;
-;;- Subtract one and jump if not zero.
+;;- Loop instructions.
 ;;
+;;  This is all complicated by the fact that since this is a jump insn
+;;  we must handle our own output reloads.
+(define_expand "doloop_end"
+  [(use (match_operand 0 "" ""))        ; loop pseudo
+   (use (match_operand 1 "" ""))        ; iterations; zero if unknown
+   (use (match_operand 2 "" ""))        ; max iterations
+   (use (match_operand 3 "" ""))        ; loop level
+   (use (match_operand 4 "" ""))]       ; label
+  ""
+  "
+{
+  if (GET_MODE (operands[0]) == SImode)
+    emit_jump_insn (gen_doloop_si (operands[4], operands[0], operands[0]));
+  else if (GET_MODE (operands[0]) == DImode && TARGET_64BIT)
+    emit_jump_insn (gen_doloop_di (operands[4], operands[0], operands[0]));
+  else
+    FAIL;
+
+  DONE;
+}")
+
+(define_insn "doloop_si"
+  [(set (pc)
+        (if_then_else
+          (ne (match_operand:SI 1 "register_operand" "d,d")
+              (const_int 1))
+          (label_ref (match_operand 0 "" ""))
+          (pc)))
+   (set (match_operand:SI 2 "register_operand" "=1,?*m*d")
+        (plus:SI (match_dup 1) (const_int -1)))
+   (clobber (match_scratch:SI 3 "=X,&d"))
+   (clobber (reg:CC 33))]
+  ""
+  "*
+{
+  if (which_alternative != 0)
+    return \"#\";
+  else if (get_attr_length (insn) == 4)
+    return \"brct\\t%1,%l0\";
+  else
+    abort ();
+}"
+  [(set_attr "op_type"  "RI")
+   (set (attr "length")
+        (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+                (const_int 4)
+               (ne (symbol_ref "TARGET_64BIT") (const_int 0))
+                 (const_int 10)
+              (ne (symbol_ref "s390_pool_overflow") (const_int 0))
+                 (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
+                               (const_int 12) (const_int 14))
+               (eq (symbol_ref "flag_pic") (const_int 0))
+                 (const_int 6)] (const_int 8)))])
+
+(define_insn "*doloop_si_long"
+  [(set (pc)
+        (if_then_else
+          (ne (match_operand:SI 1 "register_operand" "d,d")
+              (const_int 1))
+          (match_operand 0 "address_operand" "p,p")
+          (pc)))
+   (set (match_operand:SI 2 "register_operand" "=1,?*m*d")
+        (plus:SI (match_dup 1) (const_int -1)))
+   (clobber (match_scratch:SI 3 "=X,&d"))
+   (clobber (reg:CC 33))]
+  ""
+  "*
+{
+  if (get_attr_op_type (insn) == OP_TYPE_RR)
+    return \"bctr\\t%0\";
+  else
+    return \"bct\\t%a0\";
+}"
+  [(set (attr "op_type") 
+        (if_then_else (match_operand 0 "register_operand" "")
+                      (const_string "RR") (const_string "RX")))
+   (set_attr "atype" "mem")])
 
-;(define_expand "decrement_and_branch_on_count"
-;  [(use (match_operand 0 "register_operand" ""))
-;   (use (label_ref (match_operand 1 "" "")))]
-;  ""
-;  "
-;{
-;/*  if (TARGET_64BIT)
-;    emit_jump_insn (gen_brctdi (operands[0], operands[1]));
-;  else */
-;    emit_jump_insn (gen_brctsi (operands[0], operands[1]));
-;  DONE;
-;}")
-;
-;(define_insn "brctsi"
-;  [(set (pc)
-;        (if_then_else
-;           (ne (match_operand:SI 0 "register_operand" "+a")
-;               (const_int 1))
-;           (label_ref (match_operand 1 "" ""))
-;           (pc)))
-;   (set (match_dup 0)
-;        (plus:SI (match_dup 0) (const_int -1)))]
-;  ""
-;  "brct\\t%0,%l1"
-;   [(set_attr "op_type" "RI")
-;    (set_attr "type"    "branch")]
-;)
-;
-;(define_insn "ibrctsi"
-;  [(set (pc)
-;        (if_then_else
-;          (eq (match_operand:SI 0 "register_operand" "+a")
-;              (const_int 1))
-;          (pc)
-;          (label_ref (match_operand 1 "" ""))))
-;   (set (match_dup 0)
-;        (plus:SI (match_dup 0) (const_int -1)))]
-;  ""
-;  "brct\\t%0,%l1"
-;   [(set_attr "op_type" "RI")
-;    (set_attr "type"    "branch")]
-;)
+(define_split
+  [(set (pc)
+        (if_then_else (ne (match_operand:SI 1 "register_operand" "")
+                          (const_int 1))
+                      (match_operand 0 "" "")
+                      (pc)))
+   (set (match_operand:SI 2 "nonimmediate_operand" "")
+        (plus:SI (match_dup 1) (const_int -1)))
+   (clobber (match_scratch:SI 3 ""))
+   (clobber (reg:CC 33))]
+  "reload_completed
+   && (! REG_P (operands[2])
+       || ! rtx_equal_p (operands[1], operands[2]))"
+  [(set (match_dup 3) (match_dup 1))
+   (parallel [(set (reg:CCAN 33)
+                   (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
+                                 (const_int 0)))
+              (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
+   (set (match_dup 2) (match_dup 3))
+   (set (pc) (if_then_else (ne (reg:CCAN 33) (const_int 0))
+                           (match_dup 0)
+                           (pc)))]
+  "")
+
+(define_insn "doloop_di"
+  [(set (pc)
+        (if_then_else
+          (ne (match_operand:DI 1 "register_operand" "d,d")
+              (const_int 1))
+          (label_ref (match_operand 0 "" ""))
+          (pc)))
+   (set (match_operand:DI 2 "register_operand" "=1,?*m*r")
+        (plus:DI (match_dup 1) (const_int -1)))
+   (clobber (match_scratch:DI 3 "=X,&d"))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "*
+{
+  if (which_alternative != 0)
+    return \"#\";
+  else if (get_attr_length (insn) == 4)
+    return \"brctg\\t%1,%l0\";
+  else
+    abort ();
+}"
+  [(set_attr "op_type"  "RI")
+   (set (attr "length")
+        (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+                      (const_int 4) (const_int 12)))])
+
+(define_insn "*doloop_di_long"
+  [(set (pc)
+        (if_then_else
+          (ne (match_operand:DI 1 "register_operand" "d,d")
+              (const_int 1))
+          (match_operand 0 "address_operand" "p,p")
+          (pc)))
+   (set (match_operand:DI 2 "register_operand" "=1,?*m*d")
+        (plus:DI (match_dup 1) (const_int -1)))
+   (clobber (match_scratch:DI 3 "=X,&d"))
+   (clobber (reg:CC 33))]
+  ""
+  "*
+{
+  if (get_attr_op_type (insn) == OP_TYPE_RRE)
+    return \"bctgr\\t%0\";
+  else
+    return \"bctg\\t%a0\";
+}"
+  [(set (attr "op_type") 
+        (if_then_else (match_operand 0 "register_operand" "")
+                      (const_string "RRE") (const_string "RXE")))
+   (set_attr "atype" "mem")])
 
+(define_split
+  [(set (pc)
+        (if_then_else (ne (match_operand:DI 1 "register_operand" "")
+                          (const_int 1))
+                      (match_operand 0 "" "")
+                      (pc)))
+   (set (match_operand:DI 2 "nonimmediate_operand" "")
+        (plus:DI (match_dup 1) (const_int -1)))
+   (clobber (match_scratch:DI 3 ""))
+   (clobber (reg:CC 33))]
+  "reload_completed
+   && (! REG_P (operands[2])
+       || ! rtx_equal_p (operands[1], operands[2]))"
+  [(set (match_dup 3) (match_dup 1))
+   (parallel [(set (reg:CCAN 33)
+                   (compare:CCAN (plus:DI (match_dup 3) (const_int -1))
+                                 (const_int 0)))
+              (set (match_dup 3) (plus:DI (match_dup 3) (const_int -1)))])
+   (set (match_dup 2) (match_dup 3))
+   (set (pc) (if_then_else (ne (reg:CCAN 33) (const_int 0))
+                           (match_dup 0)
+                           (pc)))]
+  "")
 
 ;;
 ;;- Unconditional jump instructions.