This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
S/390: enable doloop_end pattern
- From: "Ulrich Weigand" <Ulrich dot Weigand at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 12 Sep 2002 14:40:43 +0200
- Subject: S/390: enable doloop_end pattern
- Sensitivity:
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