Merge new optabs with the existing implementations for signbit and
isinf.
gcc/ChangeLog:
* config/s390/s390.h (S390_TDC_POSITIVE_ZERO): Remove.
(S390_TDC_NEGATIVE_ZERO): Remove.
(S390_TDC_POSITIVE_NORMALIZED_BFP_NUMBER): Remove.
(S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER): Remove.
(S390_TDC_POSITIVE_DENORMALIZED_BFP_NUMBER): Remove.
(S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER): Remove.
(S390_TDC_POSITIVE_INFINITY): Remove.
(S390_TDC_NEGATIVE_INFINITY): Remove.
(S390_TDC_POSITIVE_QUIET_NAN): Remove.
(S390_TDC_NEGATIVE_QUIET_NAN): Remove.
(S390_TDC_POSITIVE_SIGNALING_NAN): Remove.
(S390_TDC_NEGATIVE_SIGNALING_NAN): Remove.
(S390_TDC_POSITIVE_DENORMALIZED_DFP_NUMBER): Remove.
(S390_TDC_NEGATIVE_DENORMALIZED_DFP_NUMBER): Remove.
(S390_TDC_POSITIVE_NORMALIZED_DFP_NUMBER): Remove.
(S390_TDC_NEGATIVE_NORMALIZED_DFP_NUMBER): Remove.
(S390_TDC_SIGNBIT_SET): Remove.
(S390_TDC_INFINITY): Remove.
* config/s390/s390.md (signbit<mode>2<tf_fpr>): Merge this one
(isinf<mode>2<tf_fpr>): and this one into
(<TDC_CLASS:tdc_insn><mode>2<tf_fpr>): new expander.
(isnormal<mode>2<tf_fpr>): New BFP expander.
(isnormal<mode>2): New DFP expander.
* config/s390/vector.md (signbittf2_vr): Merge this one
(isinftf2_vr): and this one into
(<tdc_insn>tf2_vr): new expander.
(signbittf2): Merge this one
(isinftf2): and this one into
(<tdc_insn>tf2): new expander.
gcc/testsuite/ChangeLog:
* gcc.target/s390/isfinite-isinf-isnormal-signbit-1.c: New test.
* gcc.target/s390/isfinite-isinf-isnormal-signbit-2.c: New test.
* gcc.target/s390/isfinite-isinf-isnormal-signbit-3.c: New test.
* gcc.target/s390/isfinite-isinf-isnormal-signbit.h: New test.
---
Bootstrap and regtest are running. About to push if they succeed and
there are no comments.
gcc/config/s390/s390.h | 31 -----
gcc/config/s390/s390.md | 114 +++++++++++++++---
gcc/config/s390/vector.md | 42 ++-----
.../s390/isfinite-isinf-isnormal-signbit-1.c | 62 ++++++++++
.../s390/isfinite-isinf-isnormal-signbit-2.c | 13 ++
.../s390/isfinite-isinf-isnormal-signbit-3.c | 13 ++
.../s390/isfinite-isinf-isnormal-signbit.h | 23 ++++
7 files changed, 215 insertions(+), 83 deletions(-)
create mode 100644
gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-1.c
create mode 100644
gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-2.c
create mode 100644
gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-3.c
create mode 100644
gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit.h
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 4a4dde1a9ba..9a4ddfe7f63 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -288,37 +288,6 @@ extern const char *s390_host_detect_local_cpu (int argc,
const char **argv);
"%{!mesa:%{!mzarch:%{m31:-mesa}%{m64:-mzarch}}}", \
"%{!march=*:-march=z900}"
-/* Constants needed to control the TEST DATA CLASS (TDC) instruction. */
-#define S390_TDC_POSITIVE_ZERO (1 << 11)
-#define S390_TDC_NEGATIVE_ZERO (1 << 10)
-#define S390_TDC_POSITIVE_NORMALIZED_BFP_NUMBER (1 << 9)
-#define S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER (1 << 8)
-#define S390_TDC_POSITIVE_DENORMALIZED_BFP_NUMBER (1 << 7)
-#define S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER (1 << 6)
-#define S390_TDC_POSITIVE_INFINITY (1 << 5)
-#define S390_TDC_NEGATIVE_INFINITY (1 << 4)
-#define S390_TDC_POSITIVE_QUIET_NAN (1 << 3)
-#define S390_TDC_NEGATIVE_QUIET_NAN (1 << 2)
-#define S390_TDC_POSITIVE_SIGNALING_NAN (1 << 1)
-#define S390_TDC_NEGATIVE_SIGNALING_NAN (1 << 0)
-
-/* The following values are different for DFP. */
-#define S390_TDC_POSITIVE_DENORMALIZED_DFP_NUMBER (1 << 9)
-#define S390_TDC_NEGATIVE_DENORMALIZED_DFP_NUMBER (1 << 8)
-#define S390_TDC_POSITIVE_NORMALIZED_DFP_NUMBER (1 << 7)
-#define S390_TDC_NEGATIVE_NORMALIZED_DFP_NUMBER (1 << 6)
-
-/* For signbit, the BFP-DFP-difference makes no difference. */
-#define S390_TDC_SIGNBIT_SET (S390_TDC_NEGATIVE_ZERO \
- | S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER \
- | S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER\
- | S390_TDC_NEGATIVE_INFINITY \
- | S390_TDC_NEGATIVE_QUIET_NAN \
- | S390_TDC_NEGATIVE_SIGNALING_NAN )
-
-#define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
- | S390_TDC_NEGATIVE_INFINITY )
-
/* Target machine storage layout. */
/* Everything is big-endian. */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 3d5759d6252..d2c8c2a1b7d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -432,6 +432,81 @@
(define_constants [(TBEGIN_MASK 65292)]) ; 0xff0c
(define_constants [(TBEGINC_MASK 65288)]) ; 0xff08
+;; TEST DATA CLASS
+
+; Data class bitmap:
+;
+; positive zero 11
+; negative zero 10
+; positive normalized bfp number 9
+; negative normalized bfp number 8
+; positive denormalized bfp number 7
+; negative denormalized bfp number 6
+; positive infinity 5
+; negative infinity 4
+; positive quiet nan 3
+; negative quiet nan 2
+; positive signaling nan 1
+; negative signaling nan 0
+;
+; The following values are different for DFP:
+;
+; positive denormalized dfp number 9
+; negative denormalized dfp number 8
+; positive normalized dfp number 7
+; negative normalized dfp number 6
+
+; For signbit, the BFP-DFP-difference makes no difference.
+; S390_TDC_SIGNBIT_SET = negative_zero
+; | negative_normalized_bfp_number
+; | negative_denormalized_bfp_number
+; | negative_infinity
+; | negative_quiet_nan
+; | negative_signaling_nan
+; = 1365
+;
+; For finite, the BFP-DFP-difference makes no difference.
+; S390_TDC_FINITE = positive_zero
+; | negative_zero
+; | positive_normalized_bfp_number
+; | negative_normalized_bfp_number
+; | positive_denormalized_bfp_number
+; | negative_denormalized_bfp_number
+; = 4032
+;
+; S390_TDC_INFINITY = positive_infinity
+; | negative_infinity
+; = 48
+;
+; S390_TDC_NORMAL_BFP = positive_normalized_bfp_number
+; | negative_normalized_bfp_number
+; = 768
+;
+; S390_TDC_NORMAL_DFP = positive_normalized_dfp_number
+; | negative_normalized_dfp_number
+; = 192
+
+(define_constants [(S390_TDC_SIGNBIT_SET 1365)
+ (S390_TDC_FINITE 4032)
+ (S390_TDC_INFINITY 48)
+ (S390_TDC_NORMAL_BFP 768)
+ (S390_TDC_NORMAL_DFP 192)])
+
+(define_int_iterator TDC_CLASS [S390_TDC_SIGNBIT_SET
+ S390_TDC_FINITE
+ S390_TDC_INFINITY])
+
+(define_int_iterator TDC_CLASS_BFP [S390_TDC_SIGNBIT_SET
+ S390_TDC_FINITE
+ S390_TDC_INFINITY
+ S390_TDC_NORMAL_BFP])
+
+(define_int_attr tdc_insn [(S390_TDC_SIGNBIT_SET "signbit")
+ (S390_TDC_FINITE "isfinite")
+ (S390_TDC_INFINITY "isinf")
+ (S390_TDC_NORMAL_BFP "isnormal")
+ (S390_TDC_NORMAL_DFP "isnormal")])
+
;; Instruction operand type as used in the Principles of Operation.
;; Used to determine defaults for length and other attribute values.
@@ -3549,29 +3624,32 @@
; Test data class.
;
-(define_expand "signbit<mode>2<tf_fpr>"
+(define_expand "<TDC_CLASS:tdc_insn><mode>2<tf_fpr>"
[(set (reg:CCZ CC_REGNUM)
- (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
- (match_dup 2)]
- UNSPEC_TDC_INSN))
+ (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
+ (const_int TDC_CLASS)]
+ UNSPEC_TDC_INSN))
(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
- "TARGET_HARD_FLOAT"
-{
- operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
-})
+ (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
+ "TARGET_HARD_FLOAT")
-(define_expand "isinf<mode>2<tf_fpr>"
+(define_expand "isnormal<mode>2<tf_fpr>"
[(set (reg:CCZ CC_REGNUM)
- (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
- (match_dup 2)]
- UNSPEC_TDC_INSN))
+ (unspec:CCZ [(match_operand:BFP 1 "register_operand" "f")
+ (const_int S390_TDC_NORMAL_BFP)]
+ UNSPEC_TDC_INSN))
(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
- "TARGET_HARD_FLOAT"
-{
- operands[2] = GEN_INT (S390_TDC_INFINITY);
-})
+ (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
+ "TARGET_HARD_FLOAT")
+
+(define_expand "isnormal<mode>2"
+ [(set (reg:CCZ CC_REGNUM)
+ (unspec:CCZ [(match_operand:DFP_ALL 1 "register_operand" "f")
+ (const_int S390_TDC_NORMAL_DFP)]
+ UNSPEC_TDC_INSN))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
+ "TARGET_HARD_DFP")
; This extracts CC into a GPR properly shifted. The actual IPM
; instruction will be issued by reload. The constraint of operand 1
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index a75b7cb5825..b3e14601dbd 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -3064,11 +3064,11 @@
; test data class
-(define_expand "signbittf2_vr"
+(define_expand "<tdc_insn>tf2_vr"
[(parallel
[(set (reg:CCRAW CC_REGNUM)
(unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
- (match_dup 2)]
+ (const_int TDC_CLASS_BFP)]
UNSPEC_VEC_VFTCICC))
(clobber (scratch:V1TI))])
(set (match_operand:SI 0 "register_operand" "")
@@ -3077,40 +3077,14 @@
(if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
(const_int 1)
(match_dup 0)))]
- "TARGET_VXE"
-{
- operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
-})
-
-(define_expand "signbittf2"
- [(match_operand:SI 0 "register_operand" "")
- (match_operand:TF 1 "register_operand" "")]
- "HAVE_TF (signbittf2)"
- { EXPAND_TF (signbittf2, 2); })
-
-(define_expand "isinftf2_vr"
- [(parallel
- [(set (reg:CCRAW CC_REGNUM)
- (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
- (match_dup 2)]
- UNSPEC_VEC_VFTCICC))
- (clobber (scratch:V1TI))])
- (set (match_operand:SI 0 "register_operand" "")
- (const_int 0))
- (set (match_dup 0)
- (if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
- (const_int 1)
- (match_dup 0)))]
- "TARGET_VXE"
-{
- operands[2] = GEN_INT (S390_TDC_INFINITY);
-})
+ "TARGET_VXE")
-(define_expand "isinftf2"
+(define_expand "<tdc_insn>tf2"
[(match_operand:SI 0 "register_operand" "")
- (match_operand:TF 1 "register_operand" "")]
- "HAVE_TF (isinftf2)"
- { EXPAND_TF (isinftf2, 2); })
+ (match_operand:TF 1 "register_operand" "")
+ (const_int TDC_CLASS_BFP)]
+ "HAVE_TF (<tdc_insn>tf2)"
+ { EXPAND_TF (<tdc_insn>tf2, 2); })
;
; Vector byte swap patterns
diff --git a/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-1.c
b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-1.c
new file mode 100644
index 00000000000..a832036c88d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-1.c
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z9-ec -mzarch" } */
+
+#define SIGNBIT(T) \
+ int signbit_##T (T x) { return __builtin_signbit (x); }
+
+SIGNBIT (float)
+/* { dg-final { scan-assembler-times {tceb\t%f[0-9]+,1365} 1 } } */
+
+SIGNBIT (double)
+/* { dg-final { scan-assembler-times {tcdb\t%f[0-9]+,1365} 1 } } */
+
+SIGNBIT (_Decimal32)
+/* { dg-final { scan-assembler-times {tdcet\t%f[0-9]+,1365} 1 } } */
+
+SIGNBIT (_Decimal64)
+/* { dg-final { scan-assembler-times {tdcdt\t%f[0-9]+,1365} 1 } } */
+
+#define ISFINITE(T) \
+ int isfinite_##T (T x) { return __builtin_isfinite (x); }
+
+ISFINITE (float)
+/* { dg-final { scan-assembler-times {tceb\t%f[0-9]+,4032} 1 } } */
+
+ISFINITE (double)
+/* { dg-final { scan-assembler-times {tcdb\t%f[0-9]+,4032} 1 } } */
+
+ISFINITE (_Decimal32)
+/* { dg-final { scan-assembler-times {tdcet\t%f[0-9]+,4032} 1 } } */
+
+ISFINITE (_Decimal64)
+/* { dg-final { scan-assembler-times {tdcdt\t%f[0-9]+,4032} 1 } } */
+
+#define ISINF(T) \
+ int isinf_##T (T x) { return __builtin_isinf (x); }
+
+ISINF (float)
+/* { dg-final { scan-assembler-times {tceb\t%f[0-9]+,48} 1 } } */
+
+ISINF (double)
+/* { dg-final { scan-assembler-times {tcdb\t%f[0-9]+,48} 1 } } */
+
+ISINF (_Decimal32)
+/* { dg-final { scan-assembler-times {tdcet\t%f[0-9]+,48} 1 } } */
+
+ISINF (_Decimal64)
+/* { dg-final { scan-assembler-times {tdcdt\t%f[0-9]+,48} 1 } } */
+
+#define ISNORMAL(T) \
+ int isnormal_##T (T x) { return __builtin_isnormal (x); }
+
+ISNORMAL (float)
+/* { dg-final { scan-assembler-times {tceb\t%f[0-9]+,768} 1 } } */
+
+ISNORMAL (double)
+/* { dg-final { scan-assembler-times {tcdb\t%f[0-9]+,768} 1 } } */
+
+ISNORMAL (_Decimal32)
+/* { dg-final { scan-assembler-times {tdcet\t%f[0-9]+,192} 1 } } */
+
+ISNORMAL (_Decimal64)
+/* { dg-final { scan-assembler-times {tdcdt\t%f[0-9]+,192} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-2.c
b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-2.c
new file mode 100644
index 00000000000..2ff5a37c0f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z13 -mzarch" } */
+
+#include "isfinite-isinf-isnormal-signbit.h"
+
+/* { dg-final { scan-assembler-times {tcxb\t%f[0-9]+,1365} 1 } } SIGNBIT long
double */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,1365} 1 } } SIGNBIT
_Decimal128 */
+/* { dg-final { scan-assembler-times {tcxb\t%f[0-9]+,4032} 1 } } ISFINITE long
double */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,4032} 1 } } ISFINITE
_Decimal128 */
+/* { dg-final { scan-assembler-times {tcxb\t%f[0-9]+,48} 1 } } ISINF long
double */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,48} 1 } } ISINF
_Decimal128 */
+/* { dg-final { scan-assembler-times {tcxb\t%f[0-9]+,768} 1 } } ISNORMAL long
double */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,192} 1 } } ISNORMAL
_Decimal128 */
diff --git a/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-3.c
b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-3.c
new file mode 100644
index 00000000000..8f67553c7da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z14 -mzarch" } */
+
+#include "isfinite-isinf-isnormal-signbit.h"
+
+/* { dg-final { scan-assembler-times {wftcixb\t%v[0-9]+,%v[0-9]+,1365} 1 } } */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,1365} 1 } } */
+/* { dg-final { scan-assembler-times {wftcixb\t%v[0-9]+,%v[0-9]+,4032} 1 } } */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,4032} 1 } } */
+/* { dg-final { scan-assembler-times {wftcixb\t%v[0-9]+,%v[0-9]+,48} 1 } } */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,48} 1 } } */
+/* { dg-final { scan-assembler-times {wftcixb\t%v[0-9]+,%v[0-9]+,768} 1 } } */
+/* { dg-final { scan-assembler-times {tdcxt\t%f[0-9]+,192} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit.h
b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit.h
new file mode 100644
index 00000000000..9195f7c5f67
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/isfinite-isinf-isnormal-signbit.h
@@ -0,0 +1,23 @@
+#define SIGNBIT(T, U) \
+ int signbit_##U (T x) { return __builtin_signbit (x); }
+
+SIGNBIT (long double, long_double)
+SIGNBIT (_Decimal128, _Decimal128)
+
+#define ISFINITE(T, U) \
+ int isfinite_##U (T x) { return __builtin_isfinite (x); }
+
+ISFINITE (long double, long_double)
+ISFINITE (_Decimal128, _Decimal128)
+
+#define ISINF(T, U) \
+ int isinf_##U (T x) { return __builtin_isinf (x); }
+
+ISINF (long double, long_double)
+ISINF (_Decimal128, _Decimal128)
+
+#define ISNORMAL(T, U) \
+ int isnormal_##U (T x) { return __builtin_isnormal (x); }
+
+ISNORMAL (long double, long_double)
+ISNORMAL (_Decimal128, _Decimal128)
--
2.47.0