aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel1@de.ibm.com>2009-08-20 09:19:53 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2009-08-20 09:19:53 +0000
commitf1149235142d434a76ceec242944c85c9749d3d4 (patch)
tree31e0965f7952a66e2759635c762fd4bd809f2972 /gcc/config/s390
parenta552b644fb1f7fe9eb3fd637839007669edd221c (diff)
downloadgcc-f1149235142d434a76ceec242944c85c9749d3d4.zip
gcc-f1149235142d434a76ceec242944c85c9749d3d4.tar.gz
gcc-f1149235142d434a76ceec242944c85c9749d3d4.tar.bz2
s390.md ("*brx_stage1_<GPR:mode>", [...]): New patterns.
2009-08-20 Andreas Krebbel <krebbel1@de.ibm.com> * config/s390/s390.md ("*brx_stage1_<GPR:mode>", "*brxg_64bit", "*brx_64bit", "*brx_31bit"): New patterns. * config/s390/s390.c ('E'): New output modifier. From-SVN: r150954
Diffstat (limited to 'gcc/config/s390')
-rw-r--r--gcc/config/s390/predicates.md3
-rw-r--r--gcc/config/s390/s390.c10
-rw-r--r--gcc/config/s390/s390.md174
3 files changed, 187 insertions, 0 deletions
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index d09c9b3..9d619fb 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -197,6 +197,9 @@
(define_predicate "s390_scond_operator"
(match_code "ltu, gtu, leu, geu"))
+(define_predicate "s390_brx_operator"
+ (match_code "le, gt"))
+
;; Return nonzero if OP is a valid comparison operator
;; for an ALC condition.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 25203ab..1431bfd 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -4957,6 +4957,7 @@ print_operand_address (FILE *file, rtx addr)
'C': print opcode suffix for branch condition.
'D': print opcode suffix for inverse branch condition.
+ 'E': print opcode suffix for branch on index instruction.
'J': print tls_load/tls_gdcall/tls_ldcall suffix
'G': print the size of the operand in bytes.
'O': print only the displacement of a memory reference.
@@ -4989,6 +4990,15 @@ print_operand (FILE *file, rtx x, int code)
fprintf (file, s390_branch_condition_mnemonic (x, TRUE));
return;
+ case 'E':
+ if (GET_CODE (x) == LE)
+ fprintf (file, "l");
+ else if (GET_CODE (x) == GT)
+ fprintf (file, "h");
+ else
+ gcc_unreachable ();
+ return;
+
case 'J':
if (GET_CODE (x) == SYMBOL_REF)
{
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index b6a5446..7898dc5 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -7561,6 +7561,180 @@
;; This is all complicated by the fact that since this is a jump insn
;; we must handle our own output reloads.
+;; branch on index
+
+; This splitter will be matched by combine and has to add the 2 moves
+; necessary to load the compare and the increment values into a
+; register pair as needed by brxle.
+
+(define_insn_and_split "*brx_stage1_<GPR:mode>"
+ [(set (pc)
+ (if_then_else
+ (match_operator 6 "s390_brx_operator"
+ [(plus:GPR (match_operand:GPR 1 "register_operand" "")
+ (match_operand:GPR 2 "general_operand" ""))
+ (match_operand:GPR 3 "register_operand" "")])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:GPR 4 "nonimmediate_operand" "")
+ (plus:GPR (match_dup 1) (match_dup 2)))
+ (clobber (match_scratch:GPR 5 ""))]
+ "TARGET_CPU_ZARCH"
+ "#"
+ "!reload_completed && !reload_in_progress"
+ [(set (match_dup 7) (match_dup 2)) ; the increment
+ (set (match_dup 8) (match_dup 3)) ; the comparison value
+ (parallel [(set (pc)
+ (if_then_else
+ (match_op_dup 6
+ [(plus:GPR (match_dup 1) (match_dup 7))
+ (match_dup 8)])
+ (label_ref (match_dup 0))
+ (pc)))
+ (set (match_dup 4)
+ (plus:GPR (match_dup 1) (match_dup 7)))
+ (clobber (match_dup 5))
+ (clobber (reg:CC CC_REGNUM))])]
+ {
+ rtx dreg = gen_reg_rtx (word_mode == DImode ? TImode : DImode);
+ operands[7] = gen_lowpart (<GPR:MODE>mode,
+ gen_highpart (word_mode, dreg));
+ operands[8] = gen_lowpart (<GPR:MODE>mode,
+ gen_lowpart (word_mode, dreg));
+ })
+
+; brxlg, brxhg
+
+(define_insn_and_split "*brxg_64bit"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "s390_brx_operator"
+ [(plus:DI (match_operand:DI 1 "register_operand" "d,d,d")
+ (subreg:DI (match_operand:TI 2 "register_operand" "d,d,d") 0))
+ (subreg:DI (match_dup 2) 8)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:DI 3 "nonimmediate_operand" "=1,?X,?X")
+ (plus:DI (match_dup 1)
+ (subreg:DI (match_dup 2) 0)))
+ (clobber (match_scratch:DI 4 "=X,&1,&?d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT"
+{
+ if (which_alternative != 0)
+ return "#";
+ else if (get_attr_length (insn) == 6)
+ return "brx%E5g\t%1,%2,%l0";
+ else
+ return "agr\t%1,%2\;cgr\t%1,%M2\;jg%C5\t%l0";
+}
+ "&& reload_completed
+ && (!REG_P (operands[3])
+ || !rtx_equal_p (operands[1], operands[3]))"
+ [(set (match_dup 4) (match_dup 1))
+ (parallel [(set (match_dup 4) (plus:DI (match_dup 4) (subreg:DI (match_dup 2) 0)))
+ (clobber (reg:CC CC_REGNUM))])
+ (set (reg:CCS CC_REGNUM) (compare:CCS (match_dup 4) (subreg:DI (match_dup 2) 8)))
+ (set (match_dup 3) (match_dup 4))
+ (set (pc) (if_then_else (match_op_dup 5 [(reg:CCS CC_REGNUM) (const_int 0)])
+ (label_ref (match_dup 0))
+ (pc)))]
+ ""
+ [(set_attr "op_type" "RIE")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 6) (const_int 16)))])
+
+; brxle, brxh
+
+(define_insn_and_split "*brx_64bit"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "s390_brx_operator"
+ [(plus:SI (match_operand:SI 1 "register_operand" "d,d,d")
+ (subreg:SI (match_operand:TI 2 "register_operand" "d,d,d") 4))
+ (subreg:SI (match_dup 2) 12)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:SI 3 "nonimmediate_operand" "=1,?X,?X")
+ (plus:SI (match_dup 1)
+ (subreg:SI (match_dup 2) 4)))
+ (clobber (match_scratch:SI 4 "=X,&1,&?d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT"
+{
+ if (which_alternative != 0)
+ return "#";
+ else if (get_attr_length (insn) == 6)
+ return "brx%C5\t%1,%2,%l0";
+ else
+ return "ar\t%1,%2\;cr\t%1,%M2\;jg%C5\t%l0";
+}
+ "&& reload_completed
+ && (!REG_P (operands[3])
+ || !rtx_equal_p (operands[1], operands[3]))"
+ [(set (match_dup 4) (match_dup 1))
+ (parallel [(set (match_dup 4) (plus:SI (match_dup 4) (subreg:SI (match_dup 2) 4)))
+ (clobber (reg:CC CC_REGNUM))])
+ (set (reg:CCS CC_REGNUM) (compare:CCS (match_dup 4) (subreg:SI (match_dup 2) 12)))
+ (set (match_dup 3) (match_dup 4))
+ (set (pc) (if_then_else (match_op_dup 5 [(reg:CCS CC_REGNUM) (const_int 0)])
+ (label_ref (match_dup 0))
+ (pc)))]
+ ""
+ [(set_attr "op_type" "RSI")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 6) (const_int 14)))])
+
+; brxle, brxh
+
+(define_insn_and_split "*brx_31bit"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "s390_brx_operator"
+ [(plus:SI (match_operand:SI 1 "register_operand" "d,d,d")
+ (subreg:SI (match_operand:DI 2 "register_operand" "d,d,d") 0))
+ (subreg:SI (match_dup 2) 4)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:SI 3 "nonimmediate_operand" "=1,?X,?X")
+ (plus:SI (match_dup 1)
+ (subreg:SI (match_dup 2) 0)))
+ (clobber (match_scratch:SI 4 "=X,&1,&?d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_64BIT && TARGET_CPU_ZARCH"
+{
+ if (which_alternative != 0)
+ return "#";
+ else if (get_attr_length (insn) == 6)
+ return "brx%C5\t%1,%2,%l0";
+ else
+ return "ar\t%1,%2\;cr\t%1,%M2\;jg%C5\t%l0";
+}
+ "&& reload_completed
+ && (!REG_P (operands[3])
+ || !rtx_equal_p (operands[1], operands[3]))"
+ [(set (match_dup 4) (match_dup 1))
+ (parallel [(set (match_dup 4) (plus:SI (match_dup 4) (subreg:SI (match_dup 2) 0)))
+ (clobber (reg:CC CC_REGNUM))])
+ (set (reg:CCS CC_REGNUM) (compare:CCS (match_dup 4) (subreg:SI (match_dup 2) 4)))
+ (set (match_dup 3) (match_dup 4))
+ (set (pc) (if_then_else (match_op_dup 5 [(reg:CCS CC_REGNUM) (const_int 0)])
+ (label_ref (match_dup 0))
+ (pc)))]
+ ""
+ [(set_attr "op_type" "RSI")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 6) (const_int 14)))])
+
+
+;; branch on count
+
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
(use (match_operand 1 "" "")) ; iterations; zero if unknown