diff options
author | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-09-12 12:37:17 +0000 |
---|---|---|
committer | uweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-09-12 12:37:17 +0000 |
commit | 3c482144c48758f8c427460a207e13152b934c1f (patch) | |
tree | c09f1ced7a79890e1cfd65982f2caf85ad9e44cc /gcc/config/s390 | |
parent | ace8254e610f2c04403adf3bffe5ab56779b32b8 (diff) | |
download | ppe42-gcc-3c482144c48758f8c427460a207e13152b934c1f.tar.gz ppe42-gcc-3c482144c48758f8c427460a207e13152b934c1f.zip |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57060 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390')
-rw-r--r-- | gcc/config/s390/s390-modes.def | 2 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 120 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 245 |
3 files changed, 283 insertions, 84 deletions
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def index db577aa90ae..9f9d5265720 100644 --- a/gcc/config/s390/s390-modes.def +++ b/gcc/config/s390/s390-modes.def @@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA. */ CC (CCZ) CC (CCA) +CC (CCAP) +CC (CCAN) CC (CCL) CC (CCL1) CC (CCL2) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index d390d0a5025..26c4dd2fe3d 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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; diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 561b1b0986b..3974e21cfd4 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3080,6 +3080,20 @@ [(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,6 +3224,19 @@ (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,52 +5972,184 @@ ;; -;;- 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. |