From 5d880bd24bc667dc41a1f31d5713c8dbd90d86c2 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 17 Jun 2004 10:32:14 +0000 Subject: [PATCH] s390-modes.def (CCL3mode): New machine mode. * config/s390/s390-modes.def (CCL3mode): New machine mode. * config/s390/s390.c (s390_match_ccmode_set): Support CCL3mode. (s390_alc_comparison, s390_slb_comparison): Likewise. (s390_branch_condition_mask): Likewise. * config/s390/s390.md ("*subdi3_cc2", "*subdi3_cconly2"): New. ("*subsi3_cc2", "*subsi3_cconly2"): New. * config/s390/s390.h (PREDICATE_CODE): Accept SIGN_EXTEND and ZERO_EXTEND for s390_alc_comparison and s390_slb_comparison. * config/s390/s390.c (s390_alc_comparison, s390_slb_comparison): Handle SIGN_EXTEND and ZERO_EXTEND. * config/s390/s390-protos.h (s390_expand_addcc): New prototype. * config/s390/s390.c (s390_expand_addcc): New function. * config/s390/s390.md ("adddicc", "addsicc"): New expanders. ("*sconddi", "*scondsi", "*sconddi_neg", "*scondsi_neg"): New insns. ("sltu", "sgtu", "sleu", "sgeu"): New expanders. From-SVN: r83287 --- gcc/ChangeLog | 20 ++++ gcc/config/s390/s390-modes.def | 1 + gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 194 +++++++++++++++++++++++++++++++++ gcc/config/s390/s390.h | 6 +- gcc/config/s390/s390.md | 164 ++++++++++++++++++++++++++++ 6 files changed, 384 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5c07681ecc6..17ffc884dcb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2004-06-17 Ulrich Weigand + + * config/s390/s390-modes.def (CCL3mode): New machine mode. + * config/s390/s390.c (s390_match_ccmode_set): Support CCL3mode. + (s390_alc_comparison, s390_slb_comparison): Likewise. + (s390_branch_condition_mask): Likewise. + * config/s390/s390.md ("*subdi3_cc2", "*subdi3_cconly2"): New. + ("*subsi3_cc2", "*subsi3_cconly2"): New. + + * config/s390/s390.h (PREDICATE_CODE): Accept SIGN_EXTEND and + ZERO_EXTEND for s390_alc_comparison and s390_slb_comparison. + * config/s390/s390.c (s390_alc_comparison, s390_slb_comparison): + Handle SIGN_EXTEND and ZERO_EXTEND. + + * config/s390/s390-protos.h (s390_expand_addcc): New prototype. + * config/s390/s390.c (s390_expand_addcc): New function. + * config/s390/s390.md ("adddicc", "addsicc"): New expanders. + ("*sconddi", "*scondsi", "*sconddi_neg", "*scondsi_neg"): New insns. + ("sltu", "sgtu", "sleu", "sgeu"): New expanders. + 2004-06-17 Ben Elliston * tree-alias-common.c: Add whitespace. diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def index 08759558871..d1e7304e425 100644 --- a/gcc/config/s390/s390-modes.def +++ b/gcc/config/s390/s390-modes.def @@ -32,6 +32,7 @@ CC_MODE (CCAN); CC_MODE (CCL); CC_MODE (CCL1); CC_MODE (CCL2); +CC_MODE (CCL3); CC_MODE (CCU); CC_MODE (CCUR); CC_MODE (CCS); diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 90e4de61ac3..2362cb66d0a 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -76,6 +76,7 @@ extern void s390_load_address (rtx, rtx); extern void s390_expand_movstr (rtx, rtx, rtx); extern void s390_expand_clrstr (rtx, rtx); extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx); +extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx); extern rtx s390_return_addr_rtx (int, rtx); extern rtx s390_emit_call (rtx, rtx, rtx, rtx); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index ed1eb50f830..d922e94a499 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -282,6 +282,7 @@ s390_match_ccmode_set (rtx set, enum machine_mode req_mode) case CCLmode: case CCL1mode: case CCL2mode: + case CCL3mode: case CCT1mode: case CCT2mode: case CCT3mode: @@ -477,6 +478,9 @@ s390_alc_comparison (rtx op, enum machine_mode mode) if (mode != VOIDmode && mode != GET_MODE (op)) return 0; + while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) + op = XEXP (op, 0); + if (!COMPARISON_P (op)) return 0; @@ -493,6 +497,9 @@ s390_alc_comparison (rtx op, enum machine_mode mode) case CCL2mode: return GET_CODE (op) == LEU; + case CCL3mode: + return GET_CODE (op) == GEU; + case CCUmode: return GET_CODE (op) == GTU; @@ -519,6 +526,9 @@ s390_slb_comparison (rtx op, enum machine_mode mode) if (mode != VOIDmode && mode != GET_MODE (op)) return 0; + while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) + op = XEXP (op, 0); + if (!COMPARISON_P (op)) return 0; @@ -535,6 +545,9 @@ s390_slb_comparison (rtx op, enum machine_mode mode) case CCL2mode: return GET_CODE (op) == GTU; + case CCL3mode: + return GET_CODE (op) == LTU; + case CCUmode: return GET_CODE (op) == LEU; @@ -640,6 +653,19 @@ s390_branch_condition_mask (rtx code) } break; + case CCL3mode: + switch (GET_CODE (code)) + { + case EQ: return CC0 | CC2; + case NE: return CC1 | CC3; + case LTU: return CC1; + case GTU: return CC3; + case LEU: return CC1 | CC2; + case GEU: return CC2 | CC3; + default: + abort (); + } + case CCUmode: switch (GET_CODE (code)) { @@ -3194,6 +3220,174 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len) #endif } + +/* Expand conditional increment or decrement using alc/slb instructions. + Should generate code setting DST to either SRC or SRC + INCREMENT, + depending on the result of the comparison CMP_OP0 CMP_CODE CMP_OP1. + Returns true if successful, false otherwise. */ + +bool +s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1, + rtx dst, rtx src, rtx increment) +{ + enum machine_mode cmp_mode; + enum machine_mode cc_mode; + rtx op_res; + rtx insn; + rtvec p; + + if ((GET_MODE (cmp_op0) == SImode || GET_MODE (cmp_op0) == VOIDmode) + && (GET_MODE (cmp_op1) == SImode || GET_MODE (cmp_op1) == VOIDmode)) + cmp_mode = SImode; + else if ((GET_MODE (cmp_op0) == DImode || GET_MODE (cmp_op0) == VOIDmode) + && (GET_MODE (cmp_op1) == DImode || GET_MODE (cmp_op1) == VOIDmode)) + cmp_mode = DImode; + else + return false; + + /* Try ADD LOGICAL WITH CARRY. */ + if (increment == const1_rtx) + { + /* Determine CC mode to use. */ + if (cmp_code == EQ || cmp_code == NE) + { + if (cmp_op1 != const0_rtx) + { + cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1, + NULL_RTX, 0, OPTAB_WIDEN); + cmp_op1 = const0_rtx; + } + + cmp_code = cmp_code == EQ ? LEU : GTU; + } + + if (cmp_code == LTU || cmp_code == LEU) + { + rtx tem = cmp_op0; + cmp_op0 = cmp_op1; + cmp_op1 = tem; + cmp_code = swap_condition (cmp_code); + } + + switch (cmp_code) + { + case GTU: + cc_mode = CCUmode; + break; + + case GEU: + cc_mode = CCL3mode; + break; + + default: + return false; + } + + /* Emit comparison instruction pattern. */ + if (!register_operand (cmp_op0, cmp_mode)) + cmp_op0 = force_reg (cmp_mode, cmp_op0); + + insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM), + gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1)); + /* We use insn_invalid_p here to add clobbers if required. */ + if (insn_invalid_p (emit_insn (insn))) + abort (); + + /* Emit ALC instruction pattern. */ + op_res = gen_rtx_fmt_ee (cmp_code, GET_MODE (dst), + gen_rtx_REG (cc_mode, CC_REGNUM), + const0_rtx); + + if (src != const0_rtx) + { + if (!register_operand (src, GET_MODE (dst))) + src = force_reg (GET_MODE (dst), src); + + src = gen_rtx_PLUS (GET_MODE (dst), src, const0_rtx); + op_res = gen_rtx_PLUS (GET_MODE (dst), src, op_res); + } + + p = rtvec_alloc (2); + RTVEC_ELT (p, 0) = + gen_rtx_SET (VOIDmode, dst, op_res); + RTVEC_ELT (p, 1) = + gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, p)); + + return true; + } + + /* Try SUBTRACT LOGICAL WITH BORROW. */ + if (increment == constm1_rtx) + { + /* Determine CC mode to use. */ + if (cmp_code == EQ || cmp_code == NE) + { + if (cmp_op1 != const0_rtx) + { + cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1, + NULL_RTX, 0, OPTAB_WIDEN); + cmp_op1 = const0_rtx; + } + + cmp_code = cmp_code == EQ ? LEU : GTU; + } + + if (cmp_code == GTU || cmp_code == GEU) + { + rtx tem = cmp_op0; + cmp_op0 = cmp_op1; + cmp_op1 = tem; + cmp_code = swap_condition (cmp_code); + } + + switch (cmp_code) + { + case LEU: + cc_mode = CCUmode; + break; + + case LTU: + cc_mode = CCL3mode; + break; + + default: + return false; + } + + /* Emit comparison instruction pattern. */ + if (!register_operand (cmp_op0, cmp_mode)) + cmp_op0 = force_reg (cmp_mode, cmp_op0); + + insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM), + gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1)); + /* We use insn_invalid_p here to add clobbers if required. */ + if (insn_invalid_p (emit_insn (insn))) + abort (); + + /* Emit SLB instruction pattern. */ + if (!register_operand (src, GET_MODE (dst))) + src = force_reg (GET_MODE (dst), src); + + op_res = gen_rtx_MINUS (GET_MODE (dst), + gen_rtx_MINUS (GET_MODE (dst), src, const0_rtx), + gen_rtx_fmt_ee (cmp_code, GET_MODE (dst), + gen_rtx_REG (cc_mode, CC_REGNUM), + const0_rtx)); + p = rtvec_alloc (2); + RTVEC_ELT (p, 0) = + gen_rtx_SET (VOIDmode, dst, op_res); + RTVEC_ELT (p, 1) = + gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, p)); + + return true; + } + + return false; +} + + /* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL. We need to emit DTP-relative relocations. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index a73a6804861..af7551d9318 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -990,8 +990,10 @@ do { \ {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, \ CONST_INT, CONST_DOUBLE }}, \ {"s390_plus_operand", { PLUS }}, \ - {"s390_alc_comparison", { LTU, GTU, LEU, GEU }}, \ - {"s390_slb_comparison", { LTU, GTU, LEU, GEU }}, + {"s390_alc_comparison", { ZERO_EXTEND, SIGN_EXTEND, \ + LTU, GTU, LEU, GEU }}, \ + {"s390_slb_comparison", { ZERO_EXTEND, SIGN_EXTEND, \ + LTU, GTU, LEU, GEU }}, /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 91caa4a1422..8c3708769a6 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3976,6 +3976,18 @@ slg\t%0,%2" [(set_attr "op_type" "RRE,RXY")]) +(define_insn "*subdi3_cc2" + [(set (reg 33) + (compare (match_operand:DI 1 "register_operand" "0,0") + (match_operand:DI 2 "general_operand" "d,m"))) + (set (match_operand:DI 0 "register_operand" "=d,d") + (minus:DI (match_dup 1) (match_dup 2)))] + "s390_match_ccmode (insn, CCL3mode) && TARGET_64BIT" + "@ + slgr\t%0,%2 + slg\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + (define_insn "*subdi3_cconly" [(set (reg 33) (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0") @@ -3988,6 +4000,17 @@ slg\t%0,%2" [(set_attr "op_type" "RRE,RXY")]) +(define_insn "*subdi3_cconly2" + [(set (reg 33) + (compare (match_operand:DI 1 "register_operand" "0,0") + (match_operand:DI 2 "general_operand" "d,m"))) + (clobber (match_scratch:DI 0 "=d,d"))] + "s390_match_ccmode (insn, CCL3mode) && TARGET_64BIT" + "@ + slgr\t%0,%2 + slg\t%0,%2" + [(set_attr "op_type" "RRE,RXY")]) + (define_insn "*subdi3_64" [(set (match_operand:DI 0 "register_operand" "=d,d") (minus:DI (match_operand:DI 1 "register_operand" "0,0") @@ -4111,6 +4134,19 @@ sly\t%0,%2" [(set_attr "op_type" "RR,RX,RXY")]) +(define_insn "*subsi3_cc2" + [(set (reg 33) + (compare (match_operand:SI 1 "register_operand" "0,0,0") + (match_operand:SI 2 "general_operand" "d,R,T"))) + (set (match_operand:SI 0 "register_operand" "=d,d,d") + (minus:SI (match_dup 1) (match_dup 2)))] + "s390_match_ccmode (insn, CCL3mode)" + "@ + slr\t%0,%2 + sl\t%0,%2 + sly\t%0,%2" + [(set_attr "op_type" "RR,RX,RXY")]) + (define_insn "*subsi3_cconly" [(set (reg 33) (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0,0") @@ -4124,6 +4160,18 @@ sly\t%0,%2" [(set_attr "op_type" "RR,RX,RXY")]) +(define_insn "*subsi3_cconly2" + [(set (reg 33) + (compare (match_operand:SI 1 "register_operand" "0,0,0") + (match_operand:SI 2 "general_operand" "d,R,T"))) + (clobber (match_scratch:SI 0 "=d,d,d"))] + "s390_match_ccmode (insn, CCL3mode)" + "@ + slr\t%0,%2 + sl\t%0,%2 + sly\t%0,%2" + [(set_attr "op_type" "RR,RX,RXY")]) + (define_insn "*subsi3_sign" [(set (match_operand:SI 0 "register_operand" "=d,d") (minus:SI (match_operand:SI 1 "register_operand" "0,0") @@ -4339,6 +4387,17 @@ slbg\\t%0,%2" [(set_attr "op_type" "RRE,RXY")]) +(define_expand "adddicc" + [(match_operand:DI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:DI 2 "register_operand" "") + (match_operand:DI 3 "const_int_operand" "")] + "TARGET_64BIT" + "if (!s390_expand_addcc (GET_CODE (operands[1]), + s390_compare_op0, s390_compare_op1, + operands[0], operands[2], + operands[3])) FAIL; DONE;") + ; ; addsicc instruction pattern(s). ; @@ -4397,6 +4456,111 @@ slb\\t%0,%2" [(set_attr "op_type" "RRE,RXY")]) +(define_expand "addsicc" + [(match_operand:SI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "const_int_operand" "")] + "TARGET_CPU_ZARCH" + "if (!s390_expand_addcc (GET_CODE (operands[1]), + s390_compare_op0, s390_compare_op1, + operands[0], operands[2], + operands[3])) FAIL; DONE;") + +; +; scond instruction pattern(s). +; + +(define_insn_and_split "*sconddi" + [(set (match_operand:DI 0 "register_operand" "=&d") + (match_operand:DI 1 "s390_alc_comparison" "")) + (clobber (reg:CC 33))] + "TARGET_64BIT" + "#" + "&& reload_completed" + [(set (match_dup 0) (const_int 0)) + (parallel + [(set (match_dup 0) (plus:DI (plus:DI (match_dup 0) (match_dup 0)) + (match_dup 1))) + (clobber (reg:CC 33))])] + "" + [(set_attr "op_type" "NN")]) + +(define_insn_and_split "*scondsi" + [(set (match_operand:SI 0 "register_operand" "=&d") + (match_operand:SI 1 "s390_alc_comparison" "")) + (clobber (reg:CC 33))] + "TARGET_CPU_ZARCH" + "#" + "&& reload_completed" + [(set (match_dup 0) (const_int 0)) + (parallel + [(set (match_dup 0) (plus:SI (plus:SI (match_dup 0) (match_dup 0)) + (match_dup 1))) + (clobber (reg:CC 33))])] + "" + [(set_attr "op_type" "NN")]) + +(define_insn_and_split "*sconddi_neg" + [(set (match_operand:DI 0 "register_operand" "=&d") + (match_operand:DI 1 "s390_slb_comparison" "")) + (clobber (reg:CC 33))] + "TARGET_64BIT" + "#" + "&& reload_completed" + [(set (match_dup 0) (const_int 0)) + (parallel + [(set (match_dup 0) (minus:DI (minus:DI (match_dup 0) (match_dup 0)) + (match_dup 1))) + (clobber (reg:CC 33))]) + (parallel + [(set (match_dup 0) (neg:DI (match_dup 0))) + (clobber (reg:CC 33))])] + "" + [(set_attr "op_type" "NN")]) + +(define_insn_and_split "*scondsi_neg" + [(set (match_operand:SI 0 "register_operand" "=&d") + (match_operand:SI 1 "s390_slb_comparison" "")) + (clobber (reg:CC 33))] + "TARGET_CPU_ZARCH" + "#" + "&& reload_completed" + [(set (match_dup 0) (const_int 0)) + (parallel + [(set (match_dup 0) (minus:SI (minus:SI (match_dup 0) (match_dup 0)) + (match_dup 1))) + (clobber (reg:CC 33))]) + (parallel + [(set (match_dup 0) (neg:SI (match_dup 0))) + (clobber (reg:CC 33))])] + "" + [(set_attr "op_type" "NN")]) + +(define_expand "sltu" + [(match_operand:SI 0 "register_operand" "")] + "TARGET_CPU_ZARCH" + "if (!s390_expand_addcc (LTU, s390_compare_op0, s390_compare_op1, + operands[0], const0_rtx, const1_rtx)) FAIL; DONE;") + +(define_expand "sgtu" + [(match_operand:SI 0 "register_operand" "")] + "TARGET_CPU_ZARCH" + "if (!s390_expand_addcc (GTU, s390_compare_op0, s390_compare_op1, + operands[0], const0_rtx, const1_rtx)) FAIL; DONE;") + +(define_expand "sleu" + [(match_operand:SI 0 "register_operand" "")] + "TARGET_CPU_ZARCH" + "if (!s390_expand_addcc (LEU, s390_compare_op0, s390_compare_op1, + operands[0], const0_rtx, const1_rtx)) FAIL; DONE;") + +(define_expand "sgeu" + [(match_operand:SI 0 "register_operand" "")] + "TARGET_CPU_ZARCH" + "if (!s390_expand_addcc (GEU, s390_compare_op0, s390_compare_op1, + operands[0], const0_rtx, const1_rtx)) FAIL; DONE;") + ;; ;;- Multiply instructions. -- 2.30.2