summaryrefslogtreecommitdiff
path: root/gcc/config/s390/s390.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/s390/s390.md')
-rw-r--r--gcc/config/s390/s390.md158
1 files changed, 120 insertions, 38 deletions
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 7d9d1ad7ecd..3b74e450c2f 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler -- S/390 / zSeries version.
-;; Copyright (C) 1999-2014 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2015 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com) and
;; Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
@@ -2389,7 +2389,7 @@
(use (match_operand 2 "" ""))])]
"reload_completed"
{
- enum machine_mode mode;
+ machine_mode mode;
int regno;
int count;
rtx from;
@@ -2479,7 +2479,7 @@
(use (match_operand 2 "" ""))])]
"reload_completed"
{
- enum machine_mode mode;
+ machine_mode mode;
int regno;
int count;
rtx to;
@@ -2825,8 +2825,8 @@
(clobber (reg:CC CC_REGNUM))])]
""
{
- enum machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
- enum machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
+ machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
+ machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
rtx reg0 = gen_reg_rtx (dreg_mode);
rtx reg1 = gen_reg_rtx (dreg_mode);
rtx addr0 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg0));
@@ -3042,8 +3042,8 @@
(clobber (reg:CC CC_REGNUM))])]
""
{
- enum machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
- enum machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
+ machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
+ machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
rtx reg0 = gen_reg_rtx (dreg_mode);
rtx reg1 = gen_reg_rtx (dreg_mode);
rtx addr0 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg0));
@@ -3215,8 +3215,8 @@
(use (match_dup 3))])]
""
{
- enum machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
- enum machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
+ machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
+ machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
rtx reg0 = gen_reg_rtx (dreg_mode);
rtx reg1 = gen_reg_rtx (dreg_mode);
rtx addr0 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg0));
@@ -4124,8 +4124,8 @@
{
if (!TARGET_Z196)
{
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
+ rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (TDmode);
REAL_VALUE_TYPE cmp, sub;
@@ -4163,8 +4163,8 @@
{
if (!TARGET_Z196)
{
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
+ rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (TDmode);
REAL_VALUE_TYPE cmp, sub;
@@ -4202,8 +4202,8 @@
{
if (!TARGET_Z196)
{
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
+ rtx_code_label *label2 = gen_label_rtx ();
rtx temp = gen_reg_rtx (<BFP:MODE>mode);
REAL_VALUE_TYPE cmp, sub;
@@ -4406,6 +4406,18 @@
[(set_attr "op_type" "RRF")
(set_attr "type" "ftruncsd")])
+(define_expand "trunctdsd2"
+ [(parallel
+ [(set (match_dup 3)
+ (float_truncate:DD (match_operand:TD 1 "register_operand" "")))
+ (clobber (match_scratch:TD 2 ""))])
+ (set (match_operand:SD 0 "register_operand" "")
+ (float_truncate:SD (match_dup 3)))]
+ "TARGET_HARD_DFP"
+{
+ operands[3] = gen_reg_rtx (DDmode);
+})
+
;
; extend(sf|df)(df|tf)2 instruction pattern(s).
;
@@ -4442,6 +4454,16 @@
[(set_attr "op_type" "RRF")
(set_attr "type" "fsimptf")])
+(define_expand "extendsdtd2"
+ [(set (match_dup 2)
+ (float_extend:DD (match_operand:SD 1 "register_operand" "")))
+ (set (match_operand:TD 0 "register_operand" "")
+ (float_extend:TD (match_dup 2)))]
+ "TARGET_HARD_DFP"
+{
+ operands[2] = gen_reg_rtx (DDmode);
+})
+
; Binary Floating Point - load fp integer
; Expanders for: floor, btrunc, round, ceil, and nearbyint
@@ -5045,10 +5067,10 @@
(match_operand:DI 2 "nonmemory_operand" "")))]
"TARGET_64BIT"
{
- HOST_WIDE_INT c = INTVAL (operands[2]);
-
if (GET_CODE (operands[2]) == CONST_INT)
{
+ HOST_WIDE_INT c = INTVAL (operands[2]);
+
if (!CONST_OK_FOR_CONSTRAINT_P (c, 'K', "K")
&& !CONST_OK_FOR_CONSTRAINT_P (c, 'O', "Os"))
{
@@ -5071,10 +5093,10 @@
(use (const_int 0))])]
"!TARGET_64BIT"
{
- HOST_WIDE_INT c = INTVAL (operands[2]);
-
if (GET_CODE (operands[2]) == CONST_INT)
{
+ HOST_WIDE_INT c = INTVAL (operands[2]);
+
if (!CONST_OK_FOR_CONSTRAINT_P (c, 'K', "K")
&& !CONST_OK_FOR_CONSTRAINT_P (c, 'O', "Os"))
{
@@ -6115,7 +6137,7 @@
{
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
{
- rtx label1 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
operands[1] = make_safe_from (operands[1], operands[0]);
emit_move_insn (operands[0], const0_rtx);
@@ -6141,9 +6163,9 @@
}
else
{
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx label3 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
+ rtx_code_label *label2 = gen_label_rtx ();
+ rtx_code_label *label3 = gen_label_rtx ();
operands[1] = force_reg (SImode, operands[1]);
operands[1] = make_safe_from (operands[1], operands[0]);
@@ -6201,7 +6223,7 @@
{
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 0)
{
- rtx label1 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
operands[1] = make_safe_from (operands[1], operands[0]);
emit_move_insn (operands[0], operands[1]);
@@ -6228,9 +6250,9 @@
}
else
{
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx label3 = gen_label_rtx ();
+ rtx_code_label *label1 = gen_label_rtx ();
+ rtx_code_label *label2 = gen_label_rtx ();
+ rtx_code_label *label3 = gen_label_rtx ();
operands[1] = force_reg (SImode, operands[1]);
operands[1] = make_safe_from (operands[1], operands[0]);
@@ -7001,6 +7023,21 @@
""
"s390_expand_logical_operator (XOR, <MODE>mode, operands); DONE;")
+; Combine replaces (xor (x) (const_int -1)) with (not (x)) when doing
+; simplifications. So its better to have something matching.
+(define_split
+ [(set (match_operand:INT 0 "nonimmediate_operand" "")
+ (not:INT (match_operand:INT 1 "nonimmediate_operand" "")))]
+ ""
+ [(parallel
+ [(set (match_dup 0) (xor:INT (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ operands[2] = constm1_rtx;
+ if (!s390_logical_operator_ok_p (operands))
+ FAIL;
+})
+
;
; xordi3 instruction pattern(s).
;
@@ -7351,13 +7388,27 @@
[(set_attr "op_type" "RR<E>")
(set_attr "z10prop" "z10_super_c_E1")])
-(define_insn_and_split "*negdi2_31"
+(define_insn "*negdi2_31"
[(set (match_operand:DI 0 "register_operand" "=d")
(neg:DI (match_operand:DI 1 "register_operand" "d")))
(clobber (reg:CC CC_REGNUM))]
"!TARGET_ZARCH"
- "#"
- "&& reload_completed"
+ "#")
+
+; Split a DImode NEG on 31bit into 2 SImode NEGs
+
+; Doing the twos complement separately on the SImode parts does an
+; unwanted +1 on the high part which needs to be subtracted afterwards
+; ... unless the +1 on the low part created an overflow.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (match_operand:DI 1 "register_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH
+ && (REGNO (operands[0]) == REGNO (operands[1])
+ || s390_split_ok_p (operands[0], operands[1], DImode, 0))
+ && reload_completed"
[(parallel
[(set (match_dup 2) (neg:SI (match_dup 3)))
(clobber (reg:CC CC_REGNUM))])
@@ -7379,6 +7430,40 @@
operands[5] = operand_subword (operands[1], 1, 0, DImode);
operands[6] = gen_label_rtx ();")
+; Like above but first make a copy of the low part of the src operand
+; since it might overlap with the high part of the destination.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (match_operand:DI 1 "register_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH
+ && s390_split_ok_p (operands[0], operands[1], DImode, 1)
+ && reload_completed"
+ [; Make a backup of op5 first
+ (set (match_dup 4) (match_dup 5))
+ ; Setting op2 here might clobber op5
+ (parallel
+ [(set (match_dup 2) (neg:SI (match_dup 3)))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (reg:CCAP CC_REGNUM)
+ (compare:CCAP (neg:SI (match_dup 4)) (const_int 0)))
+ (set (match_dup 4) (neg:SI (match_dup 4)))])
+ (set (pc)
+ (if_then_else (ne (reg:CCAP CC_REGNUM) (const_int 0))
+ (pc)
+ (label_ref (match_dup 6))))
+ (parallel
+ [(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
+ (clobber (reg:CC CC_REGNUM))])
+ (match_dup 6)]
+ "operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[1], 0, 0, DImode);
+ operands[4] = operand_subword (operands[0], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);
+ operands[6] = gen_label_rtx ();")
+
;
; neg(df|sf)2 instruction pattern(s).
;
@@ -8057,16 +8142,13 @@
(define_expand "cbranchcc4"
[(set (pc)
- (if_then_else (match_operator 0 "s390_eqne_operator"
+ (if_then_else (match_operator 0 "s390_comparison"
[(match_operand 1 "cc_reg_operand" "")
- (match_operand 2 "const0_operand" "")])
+ (match_operand 2 "const_int_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
- "TARGET_HARD_FLOAT"
- "s390_emit_jump (operands[3],
- s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
- DONE;")
-
+ ""
+ "")
;;
@@ -9629,7 +9711,7 @@
UNSPECV_POOL_ENTRY)]
""
{
- enum machine_mode mode = GET_MODE (PATTERN (insn));
+ machine_mode mode = GET_MODE (PATTERN (insn));
unsigned int align = GET_MODE_BITSIZE (mode);
s390_output_pool_entry (operands[0], mode, align);
return "";