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: enable doloop_end pattern


Hello,

this adds the doloop_end patterns and required splitters to the s390
backend; the machine-dependent reorg machinery is also updated to
cope with the new type of branches.

Also, the condition code set by ahi/aghi is now used (the overflow
cases can be handled correctly, depending on the sign of the immediate
constant that is added).

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.

ChangeLog:

      * 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.

Index: gcc/config/s390/s390-modes.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-modes.def,v
retrieving revision 1.2
diff -c -p -r1.2 s390-modes.def
*** gcc/config/s390/s390-modes.def  13 Aug 2002 16:02:51 -0000    1.2
--- gcc/config/s390/s390-modes.def  11 Sep 2002 21:17:52 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 23,28 ****
--- 23,30 ----

  CC (CCZ)
  CC (CCA)
+ CC (CCAP)
+ CC (CCAN)
  CC (CCL)
  CC (CCL1)
  CC (CCL2)
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.50
diff -c -p -r1.50 s390.c
*** gcc/config/s390/s390.c    5 Sep 2002 14:46:39 -0000     1.50
--- gcc/config/s390/s390.c    11 Sep 2002 21:17:54 -0000
*************** s390_match_ccmode_set (set, req_mode)
*** 182,187 ****
--- 182,193 ----
        && req_mode != CCSRmode && req_mode != CCURmode)
          return 0;
        break;
+
+     case CCAPmode:
+     case CCANmode:
+       if (req_mode != CCAmode)
+         return 0;
+       break;

      default:
        abort ();
*************** s390_select_ccmode (code, op0, op1)
*** 274,279 ****
--- 280,288 ----
      {
        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;
*************** s390_select_ccmode (code, op0, op1)
*** 306,311 ****
--- 315,328 ----
        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:
*************** s390_branch_condition_mask (code)
*** 461,466 ****
--- 478,511 ----
          }
        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))
          {
*************** optimization_options (level, size)
*** 758,768 ****
       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
--- 803,808 ----
*************** static void
*** 2605,2616 ****
  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;

    /* We need correct insn addresses.  */

--- 2645,2652 ----
  s390_split_branches ()
  {
    rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
!   rtx insn, pat, tmp, target;
!   rtx *label;

    /* We need correct insn addresses.  */

*************** s390_split_branches ()
*** 2624,2685 ****
      continue;

        pat = PATTERN (insn);
!       if (GET_CODE (pat) != SET)
      continue;

        if (GET_CODE (SET_SRC (pat)) == LABEL_REF)
      {
!       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);
            else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
!             label = XEXP (SET_SRC (pat), 2);
        else
          continue;
          }
        else
      continue;

!       if (get_attr_length (insn) == 4)
      continue;

        regs_ever_live[RETURN_REGNUM] = 1;

!       if (flag_pic)
      {
!       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);
      }
        else
      {
!       target = force_const_mem (Pmode, label);
!       jump = temp_reg;
!     }

!       if (GET_CODE (SET_SRC (pat)) == IF_THEN_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 = 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;
      }
  }

--- 2660,2720 ----
      continue;

        pat = PATTERN (insn);
!       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);
      }
        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);
            else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
!             label = &XEXP (SET_SRC (pat), 2);
        else
          continue;
          }
        else
      continue;

!       if (get_attr_length (insn) <= (TARGET_64BIT ? 6 : 4))
      continue;

        regs_ever_live[RETURN_REGNUM] = 1;

!       if (TARGET_64BIT)
!     {
!       tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, *label), insn);
!       INSN_ADDRESSES_NEW (tmp, -1);
!
!       target = temp_reg;
!     }
!       else if (!flag_pic)
      {
!       tmp = force_const_mem (Pmode, *label);
!       tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
!       INSN_ADDRESSES_NEW (tmp, -1);
!
!       target = temp_reg;
      }
        else
      {
!       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);
      }

!       if (!validate_change (insn, label, target, 0))
!     abort ();
      }
  }

*************** s390_chunkify_pool ()
*** 3177,3182 ****
--- 3212,3220 ----
        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: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.29
diff -c -p -r1.29 s390.md
*** gcc/config/s390/s390.md   9 Sep 2002 18:02:01 -0000     1.29
--- gcc/config/s390/s390.md   11 Sep 2002 21:17:57 -0000
***************
*** 3080,3085 ****
--- 3080,3099 ----
    [(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")
***************
*** 3210,3215 ****
--- 3224,3242 ----
      (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")
***************
*** 5945,5996 ****


  ;;
! ;;- Subtract one and jump if not zero.
  ;;

! ;(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")]
! ;)


  ;;
  ;;- Unconditional jump instructions.
--- 5972,6155 ----


  ;;
! ;;- 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_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.


Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com


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