summaryrefslogtreecommitdiffstats
path: root/gcc/config/s390
diff options
context:
space:
mode:
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-12 12:37:17 +0000
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-12 12:37:17 +0000
commit3c482144c48758f8c427460a207e13152b934c1f (patch)
treec09f1ced7a79890e1cfd65982f2caf85ad9e44cc /gcc/config/s390
parentace8254e610f2c04403adf3bffe5ab56779b32b8 (diff)
downloadppe42-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.def2
-rw-r--r--gcc/config/s390/s390.c120
-rw-r--r--gcc/config/s390/s390.md245
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.
OpenPOWER on IntegriCloud