* [PATCH v3 0/9] S/390: Use signaling FP comparison instructions
@ 2019-09-05 11:10 Ilya Leoshkevich
2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
` (8 more replies)
0 siblings, 9 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:10 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
Bootstrapped and regtested on s390x-redhat-linux, x86_64-redhat-linux,
ppc64le-redhat-linux.
This patch series adds signaling FP comparison support (both scalar and
vector) to s390 backend.
Patches 1-4 make it possible to query supported vcond rtxes and make
use of that for z13.
Patches 5-7 are preparation cleanups.
Patch 8 is an actual implementation.
Path 9 contains new tests, that make sure autovectorized comparisons use
proper instructions.
Ilya Leoshkevich (9):
Allow COND_EXPR and VEC_COND_EXPR condtions to trap
Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
Introduce can_vector_compare_p function
S/390: Do not use signaling vector comparisons on z13
S/390: Implement vcond expander for V1TI,V1TF
S/390: Remove code duplication in vec_unordered<mode>
S/390: Remove code duplication in vec_* comparison expanders
S/390: Use signaling FP comparison instructions
S/390: Test signaling FP comparison instructions
v1->v2:
Improve wording in documentation commit message.
Replace hook with optabs query.
Add signaling eq test.
v2->v3:
Allow COND_EXPR and VEC_COND_EXPR conditions to throw, while making
sure that GIMPLE_COND's condition still cannot throw.
Remove documentation patch (superseded by
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=275303).
Add PR target/77918 reference.
gcc/config/s390/2827.md | 14 +-
gcc/config/s390/2964.md | 13 +-
gcc/config/s390/3906.md | 17 +-
gcc/config/s390/8561.md | 19 +-
gcc/config/s390/s390-builtins.def | 16 +-
gcc/config/s390/s390-modes.def | 8 +
gcc/config/s390/s390.c | 38 ++-
gcc/config/s390/s390.md | 14 +
gcc/config/s390/vector.md | 283 ++++++++++++------
gcc/emit-rtl.c | 15 +-
gcc/gengenrtl.c | 64 +++-
gcc/gimple-expr.c | 25 +-
gcc/gimple-expr.h | 11 +
gcc/gimple.c | 2 +
gcc/gimplify.c | 5 +-
gcc/optabs-tree.c | 41 ++-
gcc/optabs.c | 43 ++-
gcc/optabs.h | 16 +
gcc/rtl.c | 7 +-
gcc/rtl.h | 12 +
gcc/testsuite/gcc.target/s390/s390.exp | 8 +
.../gcc.target/s390/vector/vec-scalar-cmp-1.c | 8 +-
.../s390/zvector/autovec-double-quiet-eq.c | 8 +
.../s390/zvector/autovec-double-quiet-ge.c | 8 +
.../s390/zvector/autovec-double-quiet-gt.c | 8 +
.../s390/zvector/autovec-double-quiet-le.c | 8 +
.../s390/zvector/autovec-double-quiet-lt.c | 8 +
.../zvector/autovec-double-quiet-ordered.c | 10 +
.../s390/zvector/autovec-double-quiet-uneq.c | 10 +
.../zvector/autovec-double-quiet-unordered.c | 11 +
.../autovec-double-signaling-eq-z13-finite.c | 10 +
.../zvector/autovec-double-signaling-eq-z13.c | 9 +
.../zvector/autovec-double-signaling-eq.c | 11 +
.../autovec-double-signaling-ge-z13-finite.c | 10 +
.../zvector/autovec-double-signaling-ge-z13.c | 9 +
.../zvector/autovec-double-signaling-ge.c | 8 +
.../autovec-double-signaling-gt-z13-finite.c | 10 +
.../zvector/autovec-double-signaling-gt-z13.c | 9 +
.../zvector/autovec-double-signaling-gt.c | 8 +
.../autovec-double-signaling-le-z13-finite.c | 10 +
.../zvector/autovec-double-signaling-le-z13.c | 9 +
.../zvector/autovec-double-signaling-le.c | 8 +
.../autovec-double-signaling-lt-z13-finite.c | 10 +
.../zvector/autovec-double-signaling-lt-z13.c | 9 +
.../zvector/autovec-double-signaling-lt.c | 8 +
...autovec-double-signaling-ltgt-z13-finite.c | 9 +
.../autovec-double-signaling-ltgt-z13.c | 9 +
.../zvector/autovec-double-signaling-ltgt.c | 9 +
.../s390/zvector/autovec-double-smax-z13.F90 | 11 +
.../s390/zvector/autovec-double-smax.F90 | 8 +
.../s390/zvector/autovec-double-smin-z13.F90 | 11 +
.../s390/zvector/autovec-double-smin.F90 | 8 +
.../s390/zvector/autovec-float-quiet-eq.c | 8 +
.../s390/zvector/autovec-float-quiet-ge.c | 8 +
.../s390/zvector/autovec-float-quiet-gt.c | 8 +
.../s390/zvector/autovec-float-quiet-le.c | 8 +
.../s390/zvector/autovec-float-quiet-lt.c | 8 +
.../zvector/autovec-float-quiet-ordered.c | 10 +
.../s390/zvector/autovec-float-quiet-uneq.c | 10 +
.../zvector/autovec-float-quiet-unordered.c | 11 +
.../s390/zvector/autovec-float-signaling-eq.c | 11 +
.../s390/zvector/autovec-float-signaling-ge.c | 8 +
.../s390/zvector/autovec-float-signaling-gt.c | 8 +
.../s390/zvector/autovec-float-signaling-le.c | 8 +
.../s390/zvector/autovec-float-signaling-lt.c | 8 +
.../zvector/autovec-float-signaling-ltgt.c | 9 +
.../gcc.target/s390/zvector/autovec-fortran.h | 7 +
.../autovec-long-double-signaling-ge.c | 8 +
.../autovec-long-double-signaling-gt.c | 8 +
.../autovec-long-double-signaling-le.c | 8 +
.../autovec-long-double-signaling-lt.c | 8 +
.../gcc.target/s390/zvector/autovec.h | 41 +++
gcc/tree-cfg.c | 5 +-
gcc/tree-eh.c | 8 +
gcc/tree-ssa-forwprop.c | 7 +-
gcc/tree-ssa-propagate.c | 9 +-
76 files changed, 994 insertions(+), 191 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec.h
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
@ 2019-09-05 11:10 ` Ilya Leoshkevich
2019-09-06 11:07 ` Richard Biener
2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
` (7 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:10 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
and introduces a temporary if this could happen, for example, generating
_5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
_6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
from GENERIC
VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
{ -1, -1, -1, -1 } ,
{ 0, 0, 0, 0 } >
This is not necessary and makes the resulting GIMPLE harder to analyze.
In particular, one of the next patches in series needs to get to
VEC_COND_EXPR's comparison code, which is not possible when a temporary
is introduced.
This patch takes special care to avoid introducing trapping comparisons
in GIMPLE_COND. They are not allowed, because they would require 3
outgoing edges (then, else and EH), which is awkward to say the least.
Therefore, computations of such conditions should live in their own basic
blocks.
gcc/ChangeLog:
2019-09-03 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
caller passes a non-trapping condition.
(is_gimple_condexpr): Allow trapping conditions.
(is_gimple_condexpr_1): New helper function.
(is_gimple_condexpr_for_cond): New function, acts like old
is_gimple_condexpr.
* gimple-expr.h (is_gimple_condexpr_for_cond): New function.
(gimple_ternary_operands_ok_p): New function to remove code
duplication i verify_gimple_assign_ternary and
valid_gimple_rhs_p.
* gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
VEC_COND_EXPR.
* gimplify.c (gimplify_cond_expr): Use
is_gimple_condexpr_for_cond.
(gimplify_expr): Allow is_gimple_condexpr_for_cond.
* tree-cfg.c (verify_gimple_assign_ternary): Use
gimple_ternary_operands_ok_p.
* tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
VEC_COND_EXPR.
(tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
* tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
is_gimple_condexpr_for_cond, remove pointless tmp check
(forward_propagate_into_cond): Remove pointless tmp check.
* tree-ssa-propagate.c (valid_gimple_rhs_p): Use
gimple_ternary_operands_ok_p.
---
gcc/gimple-expr.c | 25 +++++++++++++++++++++----
gcc/gimple-expr.h | 11 +++++++++++
gcc/gimple.c | 2 ++
gcc/gimplify.c | 5 +++--
gcc/tree-cfg.c | 5 +----
gcc/tree-eh.c | 8 ++++++++
gcc/tree-ssa-forwprop.c | 7 ++++---
gcc/tree-ssa-propagate.c | 9 ++++-----
8 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index b0c9f9b671a..46e5f000580 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -571,6 +571,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
|| TREE_CODE (cond) == TRUTH_NOT_EXPR
|| is_gimple_min_invariant (cond)
|| SSA_VAR_P (cond));
+ gcc_assert (!tree_could_throw_p (cond));
extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
@@ -602,17 +603,33 @@ is_gimple_lvalue (tree t)
|| TREE_CODE (t) == BIT_FIELD_REF);
}
-/* Return true if T is a GIMPLE condition. */
+/* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond. */
-bool
-is_gimple_condexpr (tree t)
+static bool
+is_gimple_condexpr_1 (tree t, bool allow_traps)
{
return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
- && !tree_could_throw_p (t)
+ && (allow_traps || !tree_could_throw_p (t))
&& is_gimple_val (TREE_OPERAND (t, 0))
&& is_gimple_val (TREE_OPERAND (t, 1))));
}
+/* Return true if T is a GIMPLE condition. */
+
+bool
+is_gimple_condexpr (tree t)
+{
+ return is_gimple_condexpr_1 (t, true);
+}
+
+/* Like is_gimple_condexpr, but does not allow T to trap. */
+
+bool
+is_gimple_condexpr_for_cond (tree t)
+{
+ return is_gimple_condexpr_1 (t, false);
+}
+
/* Return true if T is a gimple address. */
bool
diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
index 1ad1432bd17..27190b1e5fe 100644
--- a/gcc/gimple-expr.h
+++ b/gcc/gimple-expr.h
@@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
tree *);
extern bool is_gimple_lvalue (tree);
extern bool is_gimple_condexpr (tree);
+extern bool is_gimple_condexpr_for_cond (tree);
extern bool is_gimple_address (const_tree);
extern bool is_gimple_invariant_address (const_tree);
extern bool is_gimple_ip_invariant_address (const_tree);
@@ -175,4 +176,14 @@ gimple_call_addr_fndecl (const_tree fn)
return NULL_TREE;
}
+static inline bool
+gimple_ternary_operands_ok_p (enum tree_code code, tree op1, tree op2, tree op3)
+{
+ return ((code == VEC_COND_EXPR || code == COND_EXPR)
+ ? is_gimple_condexpr (op1)
+ : is_gimple_val (op1))
+ && is_gimple_val (op2)
+ && is_gimple_val (op3);
+}
+
#endif /* GCC_GIMPLE_EXPR_H */
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 633ef512a19..fd14fbec15e 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
op = gimple_assign_rhs_code (s);
if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
div = gimple_assign_rhs2 (s);
+ else if (op == COND_EXPR || op == VEC_COND_EXPR)
+ op = TREE_CODE (gimple_assign_rhs1 (s));
return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
(INTEGRAL_TYPE_P (t)
&& TYPE_OVERFLOW_TRAPS (t)),
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index daa0b71c191..920e423381c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4141,8 +4141,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
/* Now do the normal gimplification. */
/* Gimplify condition. */
- ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
- fb_rvalue);
+ ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
+ is_gimple_condexpr_for_cond, fb_rvalue);
if (ret == GS_ERROR)
return GS_ERROR;
gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
@@ -12973,6 +12973,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
else if (gimple_test_f == is_gimple_val
|| gimple_test_f == is_gimple_call_addr
|| gimple_test_f == is_gimple_condexpr
+ || gimple_test_f == is_gimple_condexpr_for_cond
|| gimple_test_f == is_gimple_mem_rhs
|| gimple_test_f == is_gimple_mem_rhs_or_call
|| gimple_test_f == is_gimple_reg_rhs
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index b75fdb2e63f..4d2239e9d2f 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4121,10 +4121,7 @@ verify_gimple_assign_ternary (gassign *stmt)
return true;
}
- if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
- ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
- || !is_gimple_val (rhs2)
- || !is_gimple_val (rhs3))
+ if (!gimple_ternary_operands_ok_p (rhs_code, rhs1, rhs2, rhs3))
{
error ("invalid operands in ternary operation");
return true;
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 5bb07e49d28..98dc95a07cd 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
bool honor_snans = fp_operation && flag_signaling_nans != 0;
bool handled;
+ /* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could
+ trap, because that depends on the respective condition op. */
+ gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR);
+
if (TREE_CODE_CLASS (op) != tcc_comparison
&& TREE_CODE_CLASS (op) != tcc_unary
&& TREE_CODE_CLASS (op) != tcc_binary)
@@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
if (!expr)
return false;
+ /* For COND_EXPR and VEC_COND_EXPR, only the condition may trap. */
+ if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
code = TREE_CODE (expr);
t = TREE_TYPE (expr);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index c464c899586..edc5417f455 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -524,9 +524,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
tmp = forward_propagate_into_comparison_1 (stmt, code,
boolean_type_node,
rhs1, rhs2);
- if (tmp)
+ if (tmp
+ && is_gimple_condexpr_for_cond (tmp))
{
- if (dump_file && tmp)
+ if (dump_file)
{
fprintf (dump_file, " Replaced '");
print_gimple_expr (dump_file, stmt, 0);
@@ -604,7 +605,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
if (tmp
&& is_gimple_condexpr (tmp))
{
- if (dump_file && tmp)
+ if (dump_file)
{
fprintf (dump_file, " Replaced '");
print_generic_expr (dump_file, cond);
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 7172ef8b4e6..be34e25fc40 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -523,11 +523,10 @@ valid_gimple_rhs_p (tree expr)
default:
if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
{
- if (((code == VEC_COND_EXPR || code == COND_EXPR)
- ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
- : !is_gimple_val (TREE_OPERAND (expr, 0)))
- || !is_gimple_val (TREE_OPERAND (expr, 1))
- || !is_gimple_val (TREE_OPERAND (expr, 2)))
+ if (!gimple_ternary_operands_ok_p (code,
+ TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1),
+ TREE_OPERAND (expr, 2)))
return false;
break;
}
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 3/9] Introduce can_vector_compare_p function
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
2019-09-06 12:58 ` Richard Sandiford
2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
` (5 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
z13 supports only non-signaling vector comparisons. This means we
cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
However, we cannot express this restriction today: the code only checks
whether vcond$a$b optab exists, which does not contain information about
the operation.
Introduce a function that checks whether back-end supports vector
comparisons with individual rtx codes by matching vcond expander's third
argument with a fake comparison with the corresponding rtx code.
gcc/ChangeLog:
2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* optabs-tree.c (vcond_icode_p): New function.
(vcond_eq_icode_p): New function.
(expand_vec_cond_expr_p): Use vcond_icode_p and
vcond_eq_icode_p.
* optabs.c (can_vector_compare_p): New function.
(get_rtx_code): Use get_rtx_code_safe.
(get_rtx_code_safe): New function.
* optabs.h (enum can_vector_compare_purpose): New enum.
(can_vector_compare_p): New function.
(get_rtx_code_safe): Likewise.
---
gcc/optabs-tree.c | 41 +++++++++++++++++++++++++++++++++--------
gcc/optabs.c | 43 +++++++++++++++++++++++++++++++++++++++----
gcc/optabs.h | 16 ++++++++++++++++
3 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..ff7237187dd 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -23,7 +23,10 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "target.h"
#include "insn-codes.h"
+#include "rtl.h"
#include "tree.h"
+#include "memmodel.h"
+#include "optabs.h"
#include "optabs-tree.h"
#include "stor-layout.h"
@@ -329,6 +332,34 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
return false;
}
+/* Return TRUE iff vcond_optab/vcondu_optab support the given tree
+ comparison. */
+
+static bool
+vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+ enum rtx_code rcode = get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type));
+ if (rcode == LAST_AND_UNUSED_RTX_CODE)
+ /* This may happen, for example, if code == SSA_NAME, in which case we
+ cannot be certain whether a vector insn is available. */
+ return false;
+
+ return can_vector_compare_p (rcode, TYPE_MODE (value_type),
+ TYPE_MODE (cmp_op_type), cvcp_vcond);
+}
+
+/* Return TRUE iff vcondeq_optab supports the given tree comparison. */
+
+static bool
+vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+ if (code != EQ_EXPR && code != NE_EXPR)
+ return false;
+
+ return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
+ != CODE_FOR_nothing;
+}
+
/* Return TRUE iff, appropriate vector insns are available
for vector cond expr with vector type VALUE_TYPE and a comparison
with operand vector types in CMP_OP_TYPE. */
@@ -347,14 +378,8 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
|| maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
return false;
- if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
- TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
- && ((code != EQ_EXPR && code != NE_EXPR)
- || get_vcond_eq_icode (TYPE_MODE (value_type),
- TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
- return false;
-
- return true;
+ return vcond_icode_p (value_type, cmp_op_type, code)
+ || vcond_eq_icode_p (value_type, cmp_op_type, code);
}
/* Use the current target and options to initialize
diff --git a/gcc/optabs.c b/gcc/optabs.c
index cdd07f3e53f..479789570a9 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3819,6 +3819,30 @@ can_compare_p (enum rtx_code code, machine_mode mode,
return 0;
}
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+ CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+ in order to achieve a PURPOSE. */
+
+bool
+can_vector_compare_p (enum rtx_code code, machine_mode value_mode,
+ machine_mode cmp_op_mode,
+ enum can_vector_compare_purpose purpose)
+{
+ enum insn_code icode;
+ bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
+ rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
+ rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
+ rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
+
+ if (purpose == cvcp_vcond
+ && (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
+ != CODE_FOR_nothing
+ && insn_operand_matches (icode, 3, test))
+ return true;
+
+ return false;
+}
+
/* This function is called when we are going to emit a compare instruction that
compares the values found in X and Y, using the rtl operator COMPARISON.
@@ -5348,11 +5372,11 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
return insn;
}
-/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
- or unsigned operation code. */
+/* Return rtx code for TCODE or LAST_AND_UNUSED_RTX_CODE if it has no RTL
+ counterpart. Use UNSIGNEDP to select signed or unsigned operation code. */
enum rtx_code
-get_rtx_code (enum tree_code tcode, bool unsignedp)
+get_rtx_code_safe (enum tree_code tcode, bool unsignedp)
{
enum rtx_code code;
switch (tcode)
@@ -5410,11 +5434,22 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
break;
default:
- gcc_unreachable ();
+ code = LAST_AND_UNUSED_RTX_CODE;
+ break;
}
return code;
}
+/* Like get_rtx_code_safe, but asserts when given unsupported tree codes. */
+
+enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+ enum rtx_code code = get_rtx_code_safe (tcode, unsignedp);
+ gcc_assert (code != LAST_AND_UNUSED_RTX_CODE);
+ return code;
+}
+
/* Return a comparison rtx of mode CMP_MODE for COND. Use UNSIGNEDP to
select signed or unsigned operators. OPNO holds the index of the
first comparison operand for insn ICODE. Do not generate the
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 897bb5d4443..712470a0245 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -242,6 +242,21 @@ enum can_compare_purpose
(without splitting it into pieces). */
extern int can_compare_p (enum rtx_code, machine_mode,
enum can_compare_purpose);
+
+/* The various uses that a vector comparison can have; used by
+ can_vector_compare_p. So far only vcond is defined, vec_cmp is a possible
+ future extension. */
+enum can_vector_compare_purpose
+{
+ cvcp_vcond
+};
+
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+ CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+ in order to achieve a PURPOSE. */
+extern bool can_vector_compare_p (enum rtx_code, machine_mode, machine_mode,
+ enum can_vector_compare_purpose);
+
extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
machine_mode, int);
/* Emit a pair of rtl insns to compare two rtx's and to jump
@@ -356,6 +371,7 @@ extern void expand_insn (enum insn_code icode, unsigned int nops,
extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
class expand_operand *ops);
+extern enum rtx_code get_rtx_code_safe (enum tree_code tcode, bool unsignedp);
extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
#endif /* GCC_OPTABS_H */
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode>
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (4 preceding siblings ...)
2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
2019-09-30 14:41 ` Andreas Krebbel
2019-09-05 11:12 ` [PATCH v3 8/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (2 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
vec_unordered<mode> is vec_ordered<mode> plus a negation at the end.
Reuse vec_unordered<mode> logic.
gcc/ChangeLog:
2019-08-13 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* config/s390/vector.md (vec_unordered<mode>): Call
gen_vec_ordered<mode>.
---
gcc/config/s390/vector.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index ca5ec0dd3b0..1b66b8be61f 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1581,15 +1581,15 @@
; UNORDERED (a, b): !ORDERED (a, b)
(define_expand "vec_unordered<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
- (match_operand:VFT 2 "register_operand" "v")))
- (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
- (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
- (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
+ [(match_operand:<tointvec> 0 "register_operand" "=v")
+ (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v")]
"TARGET_VX"
{
- operands[3] = gen_reg_rtx (<tointvec>mode);
+ emit_insn (gen_vec_ordered<mode> (operands[0], operands[1], operands[2]));
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_NOT (<tointvec>mode, operands[0])));
+ DONE;
})
(define_expand "vec_unordered"
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
2019-09-06 10:34 ` Segher Boessenkool
2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
` (6 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
z13 supports only non-signaling vector comparisons. This means we
cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13. Notify
middle-end about this using more restrictive operator predicate in
vcond<V_HW:mode><V_HW2:mode>.
gcc/ChangeLog:
2019-08-21 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* config/s390/vector.md (vcond_comparison_operator): New
predicate.
(vcond<V_HW:mode><V_HW2:mode>): Use vcond_comparison_operator.
---
gcc/config/s390/vector.md | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 0702e1de835..d7a266c5605 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -614,10 +614,30 @@
operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
})
+(define_predicate "vcond_comparison_operator"
+ (match_operand 0 "comparison_operator")
+{
+ if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
+ && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
+ return true;
+ switch (GET_CODE (op))
+ {
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ case LTGT:
+ /* Signaling vector comparisons are supported only on z14+. */
+ return TARGET_Z14;
+ default:
+ return true;
+ }
+})
+
(define_expand "vcond<V_HW:mode><V_HW2:mode>"
[(set (match_operand:V_HW 0 "register_operand" "")
(if_then_else:V_HW
- (match_operator 3 "comparison_operator"
+ (match_operator 3 "vcond_comparison_operator"
[(match_operand:V_HW2 4 "register_operand" "")
(match_operand:V_HW2 5 "nonmemory_operand" "")])
(match_operand:V_HW 1 "nonmemory_operand" "")
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (2 preceding siblings ...)
2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
2019-09-06 11:09 ` Richard Biener
2019-09-06 12:40 ` Richard Sandiford
2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
` (4 subsequent siblings)
8 siblings, 2 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
One of the next patches in series needs to frequently pass short-lived
fake rtxes to the back-end in order to test its capabilities. In order
to reduce the load on GC, it is beneficial to allocate these rtxes on
stack.
Provide the macro counterparts of gen_* functions required by the next
patch in series.
gcc/ChangeLog:
2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* emit-rtl.c (gen_raw_REG): Use init_raw_REG.
(init_raw_REG): New function.
* gengenrtl.c (gendef): Emit init_* functions and alloca_*
macros.
* rtl.c (rtx_alloc_stat_v): Use rtx_init.
* rtl.h (rtx_init): New function.
(rtx_alloca): New function.
(init_raw_REG): New function.
(alloca_raw_REG): New macro.
---
gcc/emit-rtl.c | 15 +++++++++---
gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
gcc/rtl.c | 7 +-----
gcc/rtl.h | 12 ++++++++++
4 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index a667cdab94e..ecfa3735bba 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
set_regno_raw (x, regno, nregs);
}
-/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
+/* Initialize a REG rtx. Make sure ORIGINAL_REGNO is set properly, and
don't attempt to share with the various global pieces of rtl (such as
frame_pointer_rtx). */
rtx
-gen_raw_REG (machine_mode mode, unsigned int regno)
+init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
{
- rtx x = rtx_alloc (REG MEM_STAT_INFO);
set_mode_and_regno (x, mode, regno);
REG_ATTRS (x) = NULL;
ORIGINAL_REGNO (x) = regno;
return x;
}
+/* Generate a new REG rtx. */
+
+rtx
+gen_raw_REG (machine_mode mode, unsigned int regno)
+{
+ rtx x = rtx_alloc (REG MEM_STAT_INFO);
+ init_raw_REG (x, mode, regno);
+ return x;
+}
+
/* There are some RTL codes that require special attention; the generation
functions do the raw handling. If you add to this list, modify
special_rtx in gengenrtl.c as well. */
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index 5c78fabfb50..cd314a68a83 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -231,8 +231,7 @@ genmacro (int idx)
puts (")");
}
-/* Generate the code for the function to generate RTL whose
- format is FORMAT. */
+/* Generate the code for functions to generate RTL whose format is FORMAT. */
static void
gendef (const char *format)
@@ -240,22 +239,18 @@ gendef (const char *format)
const char *p;
int i, j;
- /* Start by writing the definition of the function name and the types
+ /* Write the definition of the init function name and the types
of the arguments. */
- printf ("static inline rtx\ngen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
+ puts ("static inline rtx");
+ printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format);
for (p = format, i = 0; *p != 0; p++)
if (*p != '0')
printf (",\n\t%sarg%d", type_from_format (*p), i++);
+ puts (")");
- puts (" MEM_STAT_DECL)");
-
- /* Now write out the body of the function itself, which allocates
- the memory and initializes it. */
+ /* Now write out the body of the init function itself. */
puts ("{");
- puts (" rtx rt;");
- puts (" rt = rtx_alloc (code PASS_MEM_STAT);\n");
-
puts (" PUT_MODE_RAW (rt, mode);");
for (p = format, i = j = 0; *p ; ++p, ++i)
@@ -266,16 +261,55 @@ gendef (const char *format)
else
printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
- puts ("\n return rt;\n}\n");
+ puts (" return rt;\n}\n");
+
+ /* Write the definition of the gen function name and the types
+ of the arguments. */
+
+ puts ("static inline rtx");
+ printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (",\n\t%sarg%d", type_from_format (*p), i++);
+ puts (" MEM_STAT_DECL)");
+
+ /* Now write out the body of the function itself, which allocates
+ the memory and initializes it. */
+ puts ("{");
+ puts (" rtx rt;\n");
+
+ puts (" rt = rtx_alloc (code PASS_MEM_STAT);");
+ printf (" init_rtx_fmt_%s (rt, mode", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", arg%d", i++);
+ puts (");\n");
+
+ puts (" return rt;\n}\n");
+
+ /* Write the definition of gen macro. */
+
printf ("#define gen_rtx_fmt_%s(c, m", format);
for (p = format, i = 0; *p != 0; p++)
if (*p != '0')
- printf (", p%i",i++);
- printf (")\\\n gen_rtx_fmt_%s_stat (c, m", format);
+ printf (", arg%d", i++);
+ printf (") \\\n gen_rtx_fmt_%s_stat ((c), (m)", format);
for (p = format, i = 0; *p != 0; p++)
if (*p != '0')
- printf (", p%i",i++);
+ printf (", (arg%d)", i++);
printf (" MEM_STAT_INFO)\n\n");
+
+ /* Write the definition of alloca macro. */
+
+ printf ("#define alloca_rtx_fmt_%s(c, m", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", arg%d", i++);
+ printf (") \\\n init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", (arg%d)", i++);
+ printf (")\n\n");
}
/* Generate the documentation header for files we write. */
diff --git a/gcc/rtl.c b/gcc/rtl.c
index d7b8e9877c3..0be52d38d93 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -219,12 +219,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
PASS_MEM_STAT);
- /* We want to clear everything up to the FLD array. Normally, this
- is one int, but we don't want to assume that and it isn't very
- portable anyway; this is. */
-
- memset (rt, 0, RTX_HDR_SIZE);
- PUT_CODE (rt, code);
+ rtx_init (rt, code);
if (GATHER_STATISTICS)
{
diff --git a/gcc/rtl.h b/gcc/rtl.h
index efb9b3ce40d..cf1547196f2 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2933,6 +2933,15 @@ extern HOST_WIDE_INT get_stack_check_protect (void);
/* In rtl.c */
extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
+inline rtx
+rtx_init (rtx rt, RTX_CODE code)
+{
+ memset (rt, 0, RTX_HDR_SIZE);
+ PUT_CODE (rt, code);
+ return rt;
+}
+#define rtx_alloca(code) \
+ rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
#define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
#define const_wide_int_alloc(NWORDS) \
@@ -3797,7 +3806,10 @@ gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
+extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
extern rtx gen_raw_REG (machine_mode, unsigned int);
+#define alloca_raw_REG(mode, regno) \
+ init_raw_REG (rtx_alloca (REG), (mode), (regno))
extern rtx gen_rtx_REG (machine_mode, unsigned int);
extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
extern rtx gen_rtx_MEM (machine_mode, rtx);
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (3 preceding siblings ...)
2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
2019-09-30 14:51 ` Andreas Krebbel
2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
` (3 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
Currently gcc does not emit wf{c,k}* instructions when comparing long
double values. Middle-end actually adds them in the first place, but
then veclower pass replaces them with floating point register pair
operations, because the corresponding expander is missing.
gcc/ChangeLog:
2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* config/s390/vector.md (vcondv1tiv1tf): New variant of
vcond$a$b expander.
---
gcc/config/s390/vector.md | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index d7a266c5605..ca5ec0dd3b0 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -649,6 +649,21 @@
DONE;
})
+(define_expand "vcondv1tiv1tf"
+ [(set (match_operand:V1TI 0 "register_operand" "")
+ (if_then_else:V1TI
+ (match_operator 3 "vcond_comparison_operator"
+ [(match_operand:V1TF 4 "register_operand" "")
+ (match_operand:V1TF 5 "nonmemory_operand" "")])
+ (match_operand:V1TI 1 "nonmemory_operand" "")
+ (match_operand:V1TI 2 "nonmemory_operand" "")))]
+ "TARGET_VXE"
+{
+ s390_expand_vcond (operands[0], operands[1], operands[2],
+ GET_CODE (operands[3]), operands[4], operands[5]);
+ DONE;
+})
+
(define_expand "vcondu<V_HW:mode><V_HW2:mode>"
[(set (match_operand:V_HW 0 "register_operand" "")
(if_then_else:V_HW
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 9/9] S/390: Test signaling FP comparison instructions
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (7 preceding siblings ...)
2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
@ 2019-09-05 11:12 ` Ilya Leoshkevich
8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:12 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
gcc/testsuite/ChangeLog:
2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* gcc.target/s390/s390.exp: Enable Fortran tests.
* gcc.target/s390/zvector/autovec-double-quiet-eq.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-ge.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-gt.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-le.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-lt.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-ordered.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-uneq.c: New test.
* gcc.target/s390/zvector/autovec-double-quiet-unordered.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-eq.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-ge.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-gt.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-le-z13.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-le.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-lt.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c: New test.
* gcc.target/s390/zvector/autovec-double-signaling-ltgt.c: New test.
* gcc.target/s390/zvector/autovec-double-smax-z13.F90: New test.
* gcc.target/s390/zvector/autovec-double-smax.F90: New test.
* gcc.target/s390/zvector/autovec-double-smin-z13.F90: New test.
* gcc.target/s390/zvector/autovec-double-smin.F90: New test.
* gcc.target/s390/zvector/autovec-float-quiet-eq.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-ge.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-gt.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-le.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-lt.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-ordered.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-uneq.c: New test.
* gcc.target/s390/zvector/autovec-float-quiet-unordered.c: New test.
* gcc.target/s390/zvector/autovec-float-signaling-eq.c: New test.
* gcc.target/s390/zvector/autovec-float-signaling-ge.c: New test.
* gcc.target/s390/zvector/autovec-float-signaling-gt.c: New test.
* gcc.target/s390/zvector/autovec-float-signaling-le.c: New test.
* gcc.target/s390/zvector/autovec-float-signaling-lt.c: New test.
* gcc.target/s390/zvector/autovec-float-signaling-ltgt.c: New test.
* gcc.target/s390/zvector/autovec-fortran.h: New test.
* gcc.target/s390/zvector/autovec-long-double-signaling-ge.c: New test.
* gcc.target/s390/zvector/autovec-long-double-signaling-gt.c: New test.
* gcc.target/s390/zvector/autovec-long-double-signaling-le.c: New test.
* gcc.target/s390/zvector/autovec-long-double-signaling-lt.c: New test.
* gcc.target/s390/zvector/autovec.h: New test.
---
gcc/testsuite/gcc.target/s390/s390.exp | 8 ++++
.../s390/zvector/autovec-double-quiet-eq.c | 8 ++++
.../s390/zvector/autovec-double-quiet-ge.c | 8 ++++
.../s390/zvector/autovec-double-quiet-gt.c | 8 ++++
.../s390/zvector/autovec-double-quiet-le.c | 8 ++++
.../s390/zvector/autovec-double-quiet-lt.c | 8 ++++
.../zvector/autovec-double-quiet-ordered.c | 10 +++++
.../s390/zvector/autovec-double-quiet-uneq.c | 10 +++++
.../zvector/autovec-double-quiet-unordered.c | 11 +++++
.../autovec-double-signaling-eq-z13-finite.c | 10 +++++
.../zvector/autovec-double-signaling-eq-z13.c | 9 ++++
.../zvector/autovec-double-signaling-eq.c | 11 +++++
.../autovec-double-signaling-ge-z13-finite.c | 10 +++++
.../zvector/autovec-double-signaling-ge-z13.c | 9 ++++
.../zvector/autovec-double-signaling-ge.c | 8 ++++
.../autovec-double-signaling-gt-z13-finite.c | 10 +++++
.../zvector/autovec-double-signaling-gt-z13.c | 9 ++++
.../zvector/autovec-double-signaling-gt.c | 8 ++++
.../autovec-double-signaling-le-z13-finite.c | 10 +++++
.../zvector/autovec-double-signaling-le-z13.c | 9 ++++
.../zvector/autovec-double-signaling-le.c | 8 ++++
.../autovec-double-signaling-lt-z13-finite.c | 10 +++++
.../zvector/autovec-double-signaling-lt-z13.c | 9 ++++
.../zvector/autovec-double-signaling-lt.c | 8 ++++
...autovec-double-signaling-ltgt-z13-finite.c | 9 ++++
.../autovec-double-signaling-ltgt-z13.c | 9 ++++
.../zvector/autovec-double-signaling-ltgt.c | 9 ++++
.../s390/zvector/autovec-double-smax-z13.F90 | 11 +++++
.../s390/zvector/autovec-double-smax.F90 | 8 ++++
.../s390/zvector/autovec-double-smin-z13.F90 | 11 +++++
.../s390/zvector/autovec-double-smin.F90 | 8 ++++
.../s390/zvector/autovec-float-quiet-eq.c | 8 ++++
.../s390/zvector/autovec-float-quiet-ge.c | 8 ++++
.../s390/zvector/autovec-float-quiet-gt.c | 8 ++++
.../s390/zvector/autovec-float-quiet-le.c | 8 ++++
.../s390/zvector/autovec-float-quiet-lt.c | 8 ++++
.../zvector/autovec-float-quiet-ordered.c | 10 +++++
.../s390/zvector/autovec-float-quiet-uneq.c | 10 +++++
.../zvector/autovec-float-quiet-unordered.c | 11 +++++
.../s390/zvector/autovec-float-signaling-eq.c | 11 +++++
.../s390/zvector/autovec-float-signaling-ge.c | 8 ++++
.../s390/zvector/autovec-float-signaling-gt.c | 8 ++++
.../s390/zvector/autovec-float-signaling-le.c | 8 ++++
.../s390/zvector/autovec-float-signaling-lt.c | 8 ++++
.../zvector/autovec-float-signaling-ltgt.c | 9 ++++
.../gcc.target/s390/zvector/autovec-fortran.h | 7 ++++
.../autovec-long-double-signaling-ge.c | 8 ++++
.../autovec-long-double-signaling-gt.c | 8 ++++
.../autovec-long-double-signaling-le.c | 8 ++++
.../autovec-long-double-signaling-lt.c | 8 ++++
.../gcc.target/s390/zvector/autovec.h | 41 +++++++++++++++++++
51 files changed, 485 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec.h
diff --git a/gcc/testsuite/gcc.target/s390/s390.exp b/gcc/testsuite/gcc.target/s390/s390.exp
index 86f7e4398eb..925eb568832 100644
--- a/gcc/testsuite/gcc.target/s390/s390.exp
+++ b/gcc/testsuite/gcc.target/s390/s390.exp
@@ -27,6 +27,7 @@ if ![istarget s390*-*-*] then {
# Load support procs.
load_lib gcc-dg.exp
load_lib target-supports.exp
+load_lib gfortran-dg.exp
# Return 1 if the the assembler understands .machine and .machinemode. The
# target attribute needs that feature to work.
@@ -193,6 +194,10 @@ global DEFAULT_CFLAGS
if ![info exists DEFAULT_CFLAGS] then {
set DEFAULT_CFLAGS " -ansi -pedantic-errors"
}
+global DEFAULT_FFLAGS
+if ![info exists DEFAULT_FFLAGS] then {
+ set DEFAULT_FFLAGS " -pedantic-errors"
+}
# Initialize `dg'.
dg-init
@@ -209,6 +214,9 @@ dg-runtest [lsort [prune [glob -nocomplain $srcdir/$subdir/*.{c,S}] \
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*vector*/*.{c,S}]] \
"" $DEFAULT_CFLAGS
+gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*vector*/*.F90]] \
+ "" $DEFAULT_FFLAGS
+
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/target-attribute/*.{c,S}]] \
"" $DEFAULT_CFLAGS
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
new file mode 100644
index 00000000000..dad138770c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_EQ);
+
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
new file mode 100644
index 00000000000..9fddb62573f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_GE);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
new file mode 100644
index 00000000000..eb512f84c47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_GT);
+
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
new file mode 100644
index 00000000000..c049f8b7dee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_LE);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
new file mode 100644
index 00000000000..b6f7702ecd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_LT);
+
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
new file mode 100644
index 00000000000..bf8ebd4ab6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_ORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
new file mode 100644
index 00000000000..421fb5e7ba5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_UNEQ);
+
+/* { dg-final { scan-assembler-times {\n\tvfchdb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
+/* { dg-final { scan-assembler {\n\tvx\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
new file mode 100644
index 00000000000..c42f7930ad8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_UNORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
+/* combine prefers to reorder vsel args instead of using vno. */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c
new file mode 100644
index 00000000000..e3d42eaf3ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_EQ);
+
+/* We can use non-signaling vector comparison instructions with
+ -ffinite-math-only. */
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
new file mode 100644
index 00000000000..f6110328891
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_EQ);
+
+/* z13 does not have signaling vector comparison instructions. */
+/* { dg-final { scan-assembler {\n\tkdbr\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
new file mode 100644
index 00000000000..32088cb55b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_EQ);
+
+/* The vectorizer produces <= and ==, which rtl passes cannot turn into vfkedb
+ yet. */
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfkhedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
new file mode 100644
index 00000000000..b301d1b739b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GE);
+
+/* We can use non-signaling vector comparison instructions with
+ -ffinite-math-only. */
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
new file mode 100644
index 00000000000..ee83f3405c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GE);
+
+/* z13 does not have signaling vector comparison instructions. */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
new file mode 100644
index 00000000000..bcb4c868a15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GE);
+
+/* { dg-final { scan-assembler {\n\tvfkhedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
new file mode 100644
index 00000000000..c49764447f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GT);
+
+/* We can use non-signaling vector comparison instructions with
+ -ffinite-math-only. */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
new file mode 100644
index 00000000000..6b9c11997a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GT);
+
+/* z13 does not have signaling vector comparison instructions. */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
new file mode 100644
index 00000000000..e423ed0f78c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GT);
+
+/* { dg-final { scan-assembler {\n\tvfkhdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
new file mode 100644
index 00000000000..7fa559b5701
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LE);
+
+/* We can use non-signaling vector comparison instructions with
+ -ffinite-math-only. */
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
new file mode 100644
index 00000000000..a80ac20b905
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LE);
+
+/* z13 does not have signaling vector comparison instructions. */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
new file mode 100644
index 00000000000..b97bebaaf8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LE);
+
+/* { dg-final { scan-assembler {\n\tvfkhedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
new file mode 100644
index 00000000000..3305a98379c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LT);
+
+/* We can use non-signaling vector comparison instructions with
+ -ffinite-math-only. */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
new file mode 100644
index 00000000000..8b398a28c37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LT);
+
+/* z13 does not have signaling vector comparison instructions. */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
new file mode 100644
index 00000000000..b01272d00a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LT);
+
+/* { dg-final { scan-assembler {\n\tvfkhdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
new file mode 100644
index 00000000000..76730d70968
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LTGT);
+
+/* ltgt is the same as eq with -ffinite-math-only. */
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
new file mode 100644
index 00000000000..d466697499a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LTGT);
+
+/* z13 does not have signaling vector comparison instructions. */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
new file mode 100644
index 00000000000..645f299a9fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LTGT);
+
+/* { dg-final { scan-assembler-times {\n\tvfkhdb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
new file mode 100644
index 00000000000..b114082df59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z13 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (max)
+
+! Fortran's max does not specify whether or not an exception should be raised in
+! face of qNaNs, and neither does gcc's smax. Vectorize max using quiet
+! comparison, because that's the only one we have on z13.
+! { dg-final { scan-assembler {\n\tvfchdb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
new file mode 100644
index 00000000000..1698ec4f4db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z14 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (max)
+
+! { dg-final { scan-assembler {\n\tvfmaxdb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
new file mode 100644
index 00000000000..fc56e9d6879
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z13 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (min)
+
+! Fortran's min does not specify whether or not an exception should be raised in
+! face of qNaNs, and neither does gcc's smin. Vectorize min using quiet
+! comparison, because that's the only one we have on z13.
+! { dg-final { scan-assembler {\n\tvfchdb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
new file mode 100644
index 00000000000..0dd1a33bb84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z14 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (min)
+
+! { dg-final { scan-assembler {\n\tvfmindb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
new file mode 100644
index 00000000000..c74927dd028
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_EQ);
+
+/* { dg-final { scan-assembler {\n\tvfcesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
new file mode 100644
index 00000000000..4c7cb09eed5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_GE);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
new file mode 100644
index 00000000000..dd787929b9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_GT);
+
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
new file mode 100644
index 00000000000..5bd1e3e98e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_LE);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
new file mode 100644
index 00000000000..4938dcfb430
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_LT);
+
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
new file mode 100644
index 00000000000..222e9efb5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_UNORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
new file mode 100644
index 00000000000..ab5dcac9c34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_UNEQ);
+
+/* { dg-final { scan-assembler-times {\n\tvfchsb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
+/* { dg-final { scan-assembler {\n\tvx\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
new file mode 100644
index 00000000000..c800dce2d7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_UNORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
+/* combine prefers to reorder vsel args instead of using vno. */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
new file mode 100644
index 00000000000..ce3271c918c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_EQ);
+
+/* The vectorizer produces <= and ==, which rtl passes cannot turn into vfkesb
+ yet. */
+/* { dg-final { scan-assembler {\n\tvfcesb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfkhesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
new file mode 100644
index 00000000000..0f98c5467e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_GE);
+
+/* { dg-final { scan-assembler {\n\tvfkhesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
new file mode 100644
index 00000000000..762c4c2030c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_GT);
+
+/* { dg-final { scan-assembler {\n\tvfkhsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
new file mode 100644
index 00000000000..ccf0c5c24d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_LE);
+
+/* { dg-final { scan-assembler {\n\tvfkhesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
new file mode 100644
index 00000000000..b428e5fc52e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_LT);
+
+/* { dg-final { scan-assembler {\n\tvfkhsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
new file mode 100644
index 00000000000..bf15242a4d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_LTGT);
+
+/* { dg-final { scan-assembler-times {\n\tvfkhsb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h b/gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
new file mode 100644
index 00000000000..8e44cb2dd31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
@@ -0,0 +1,7 @@
+#define AUTOVEC_FORTRAN(OP) subroutine f (r, x, y); \
+ real(kind=kind (1.0d0)) :: r(1000000), x(1000000), y(1000000); \
+ integer :: i; \
+ do i = 1, 1000000; \
+ r(i) = OP (x(i), y(i)); \
+ end do; \
+end
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
new file mode 100644
index 00000000000..684a6a9b2e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_GE);
+
+/* { dg-final { scan-assembler {\n\twfkhexb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
new file mode 100644
index 00000000000..76ade12c7f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_GT);
+
+/* { dg-final { scan-assembler {\n\twfkhxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
new file mode 100644
index 00000000000..a15960ec86a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_LE);
+
+/* { dg-final { scan-assembler {\n\twfkhexb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
new file mode 100644
index 00000000000..046d5487af8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_LT);
+
+/* { dg-final { scan-assembler {\n\twfkhxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec.h b/gcc/testsuite/gcc.target/s390/zvector/autovec.h
new file mode 100644
index 00000000000..d04e5d7e00e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec.h
@@ -0,0 +1,41 @@
+#ifndef AUTOVEC_H
+#define AUTOVEC_H 1
+
+#define QUIET_EQ(x, y) ((x) == (y))
+#define QUIET_GE __builtin_isgreaterequal
+#define QUIET_GT __builtin_isgreater
+#define QUIET_LE __builtin_islessequal
+#define QUIET_LT __builtin_isless
+#define QUIET_ORDERED(x, y) (!__builtin_isunordered ((x), (y)))
+#define QUIET_UNEQ(x, y) (__builtin_isless ((x), (y)) \
+ || __builtin_isgreater ((x), (y)))
+#define QUIET_UNORDERED __builtin_isunordered
+#define SIGNALING_EQ(x, y) (((x) <= (y)) && ((x) >= (y)))
+#define SIGNALING_GE(x, y) ((x) >= (y))
+#define SIGNALING_GT(x, y) ((x) > (y))
+#define SIGNALING_LE(x, y) ((x) <= (y))
+#define SIGNALING_LT(x, y) ((x) < (y))
+#define SIGNALING_LTGT(x, y) (((x) < (y)) || ((x) > (y)))
+
+#define AUTOVEC(RESULT_TYPE, OP_TYPE, OP) void \
+f (RESULT_TYPE *r, const OP_TYPE *x, const OP_TYPE *y) \
+{ \
+ int i; \
+\
+ for (i = 0; i < 1000000; i++) \
+ { \
+ OP_TYPE xi = x[i], yi = y[i]; \
+\
+ r[i] = OP (xi, yi); \
+ } \
+}
+
+#define AUTOVEC_DOUBLE(OP) AUTOVEC (long, double, OP)
+
+#define AUTOVEC_FLOAT(OP) AUTOVEC (int, float, OP)
+
+typedef __int128 v1ti __attribute__ ((vector_size (16)));
+typedef long double v1tf __attribute__ ((vector_size (16)));
+#define AUTOVEC_LONG_DOUBLE(OP) AUTOVEC (v1ti, v1tf, OP)
+
+#endif
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 8/9] S/390: Use signaling FP comparison instructions
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (5 preceding siblings ...)
2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
@ 2019-09-05 11:12 ` Ilya Leoshkevich
2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test signaling FP comparison instructions Ilya Leoshkevich
8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:12 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
dg-torture.exp=inf-compare-1.c is failing, because (qNaN > +Inf)
comparison is compiled to CDB instruction, which does not signal an
invalid operation exception. KDB should have been used instead.
This patch introduces a new CCmode and a new pattern in order to
generate signaling instructions in this and similar cases.
gcc/ChangeLog:
2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* config/s390/2827.md: Add new opcodes.
* config/s390/2964.md: Likewise.
* config/s390/3906.md: Likewise.
* config/s390/8561.md: Likewise.
* config/s390/s390-builtins.def (s390_vfchesb): Use
the new vec_cmpgev4sf_quiet_nocc.
(s390_vfchedb): Use the new vec_cmpgev2df_quiet_nocc.
(s390_vfchsb): Use the new vec_cmpgtv4sf_quiet_nocc.
(s390_vfchdb): Use the new vec_cmpgtv2df_quiet_nocc.
(vec_cmplev4sf): Use the new vec_cmplev4sf_quiet_nocc.
(vec_cmplev2df): Use the new vec_cmplev2df_quiet_nocc.
(vec_cmpltv4sf): Use the new vec_cmpltv4sf_quiet_nocc.
(vec_cmpltv2df): Use the new vec_cmpltv2df_quiet_nocc.
* config/s390/s390-modes.def (CCSFPS): New mode.
* config/s390/s390.c (s390_match_ccmode_set): Support CCSFPS.
(s390_select_ccmode): Return CCSFPS for LT, LE, GT, GE and LTGT.
(s390_branch_condition_mask): Reuse CCS for CCSFPS.
(s390_expand_vec_compare): Use non-signaling patterns where
necessary.
(s390_reverse_condition): Support CCSFPS.
* config/s390/s390.md (*cmp<mode>_ccsfps): New pattern.
* config/s390/vector.md: (VFCMP_HW_OP): Remove.
(asm_fcmp_op): Likewise.
(*smaxv2df3_vx): Use pattern for quiet comparison.
(*sminv2df3_vx): Likewise.
(*vec_cmp<VFCMP_HW_OP:code><mode>_nocc): Remove.
(*vec_cmpeq<mode>_quiet_nocc): New pattern.
(vec_cmpgt<mode>_quiet_nocc): Likewise.
(vec_cmplt<mode>_quiet_nocc): New expander.
(vec_cmpge<mode>_quiet_nocc): New pattern.
(vec_cmple<mode>_quiet_nocc): New expander.
(*vec_cmpeq<mode>_signaling_nocc): New pattern.
(*vec_cmpgt<mode>_signaling_nocc): Likewise.
(*vec_cmpgt<mode>_signaling_finite_nocc): Likewise.
(*vec_cmpge<mode>_signaling_nocc): Likewise.
(*vec_cmpge<mode>_signaling_finite_nocc): Likewise.
(vec_cmpungt<mode>): New expander.
(vec_cmpunge<mode>): Likewise.
(vec_cmpuneq<mode>): Use quiet patterns.
(vec_cmpltgt<mode>): Allow only on z14+.
(vec_cmpordered<mode>): Use quiet patterns.
(vec_cmpunordered<mode>): Likewise.
(VEC_CODE_WITH_COMPLEX_EXPAND): Add ungt and unge.
gcc/testsuite/ChangeLog:
2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
* gcc.target/s390/vector/vec-scalar-cmp-1.c: Adjust
expectations.
---
gcc/config/s390/2827.md | 14 +-
gcc/config/s390/2964.md | 13 +-
gcc/config/s390/3906.md | 17 +-
gcc/config/s390/8561.md | 19 +-
gcc/config/s390/s390-builtins.def | 16 +-
gcc/config/s390/s390-modes.def | 8 +
gcc/config/s390/s390.c | 34 ++--
gcc/config/s390/s390.md | 14 ++
gcc/config/s390/vector.md | 171 +++++++++++++++---
.../gcc.target/s390/vector/vec-scalar-cmp-1.c | 8 +-
10 files changed, 240 insertions(+), 74 deletions(-)
diff --git a/gcc/config/s390/2827.md b/gcc/config/s390/2827.md
index 3f63f82284d..aafe8e27339 100644
--- a/gcc/config/s390/2827.md
+++ b/gcc/config/s390/2827.md
@@ -44,7 +44,7 @@
(define_insn_reservation "zEC12_normal_fp" 8
(and (eq_attr "cpu" "zEC12")
- (eq_attr "mnemonic" "lnebr,sdbr,sebr,clfxtr,adbr,aebr,celfbr,clfebr,lpebr,msebr,lndbr,clfdbr,cebr,maebr,ltebr,clfdtr,cdlgbr,cxlftr,lpdbr,cdfbr,lcebr,clfxbr,msdbr,cdbr,madbr,meebr,clgxbr,clgdtr,ledbr,cegbr,cdlftr,cdlgtr,mdbr,clgebr,ltdbr,cdlfbr,cdgbr,clgxtr,lcdbr,celgbr,clgdbr,ldebr,cefbr,fidtr,fixtr,madb,msdb,mseb,fiebra,fidbra,aeb,mdb,seb,cdb,tcdb,sdb,adb,tceb,maeb,ceb,meeb,ldeb")) "nothing")
+ (eq_attr "mnemonic" "lnebr,sdbr,sebr,clfxtr,adbr,aebr,celfbr,clfebr,lpebr,msebr,lndbr,clfdbr,cebr,maebr,ltebr,clfdtr,cdlgbr,cxlftr,lpdbr,cdfbr,lcebr,clfxbr,msdbr,cdbr,madbr,meebr,clgxbr,clgdtr,ledbr,cegbr,cdlftr,cdlgtr,mdbr,clgebr,ltdbr,cdlfbr,cdgbr,clgxtr,lcdbr,celgbr,clgdbr,ldebr,cefbr,fidtr,fixtr,madb,msdb,mseb,fiebra,fidbra,aeb,mdb,seb,cdb,tcdb,sdb,adb,tceb,maeb,ceb,meeb,ldeb,keb,kebr,kdb,kdbr")) "nothing")
(define_insn_reservation "zEC12_cgdbr" 2
(and (eq_attr "cpu" "zEC12")
@@ -426,6 +426,10 @@
(and (eq_attr "cpu" "zEC12")
(eq_attr "mnemonic" "cxbr")) "nothing")
+(define_insn_reservation "zEC12_kxbr" 18
+ (and (eq_attr "cpu" "zEC12")
+ (eq_attr "mnemonic" "kxbr")) "nothing")
+
(define_insn_reservation "zEC12_ddbr" 36
(and (eq_attr "cpu" "zEC12")
(eq_attr "mnemonic" "ddbr")) "nothing")
@@ -578,10 +582,18 @@
(and (eq_attr "cpu" "zEC12")
(eq_attr "mnemonic" "cdtr")) "nothing")
+(define_insn_reservation "zEC12_kdtr" 11
+ (and (eq_attr "cpu" "zEC12")
+ (eq_attr "mnemonic" "kdtr")) "nothing")
+
(define_insn_reservation "zEC12_cxtr" 14
(and (eq_attr "cpu" "zEC12")
(eq_attr "mnemonic" "cxtr")) "nothing")
+(define_insn_reservation "zEC12_kxtr" 14
+ (and (eq_attr "cpu" "zEC12")
+ (eq_attr "mnemonic" "kxtr")) "nothing")
+
(define_insn_reservation "zEC12_slbg" 3
(and (eq_attr "cpu" "zEC12")
(eq_attr "mnemonic" "slbg")) "nothing")
diff --git a/gcc/config/s390/2964.md b/gcc/config/s390/2964.md
index a7897bcf58a..4396e3ba1c0 100644
--- a/gcc/config/s390/2964.md
+++ b/gcc/config/s390/2964.md
@@ -69,7 +69,7 @@ ng,ni,niy,ntstg,ny,o,og,oi,oiy,oy,s,sar,sdb,seb,sfpc,sg,sgf,sh,shy,sl,\
slb,slbg,slg,slgf,sly,sqdb,sqeb,st,stc,stcy,std,stdy,ste,stey,stg,stgrl,\
sth,sthrl,sthy,stoc,stocg,strl,strv,strvg,strvh,sty,sy,tabort,tm,tmy,vl,\
vlbb,vleb,vlef,vleg,vleh,vll,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,\
-vlrepf,vlrepg,vlreph,vst,vstl,x,xg,xi,xiy,xy")
+vlrepf,vlrepg,vlreph,vst,vstl,x,xg,xi,xiy,xy,kdb")
(const_int 1)] (const_int 0)))
(define_attr "z13_unit_vfu" ""
@@ -109,7 +109,8 @@ vuplhh,vuplhw,vupllb,vupllf,vupllh,vx,vzero,wcdgb,wcdlgb,wcgdb,wclgdb,wfadb,\
wfasb,wfaxb,wfcdb,wfcedb,wfcesb,wfcexbs,wfchdb,wfchedb,wfchesb,wfchexb,\
wfchexbs,wfchsb,wfchxb,wfchxbs,wfcsb,wfisb,wfixb,wflcdb,wflcsb,wflcxb,wflld,\
wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmadb,wfmasb,wfmaxb,wfmdb,wfmsb,\
-wfmsdb,wfmssb,wfmsxb,wfmxb,wfsdb,wfssb,wfsxb,wldeb,wledb")
+wfmsdb,wfmssb,wfmsxb,wfmxb,wfsdb,wfssb,wfsxb,wldeb,wledb,kebr,kdb,kdbr,kxbr,\
+kdtr,kxtr,wfkdb,wfksb")
(const_int 1)] (const_int 0)))
(define_attr "z13_cracked" ""
@@ -131,7 +132,7 @@ stmg,stmy,tbegin,tbeginc")
cxtr,dlgr,dlr,dr,dsgfr,dsgr,dxbr,dxtr,fixbr,fixbra,fixtr,flogr,lcxbr,lnxbr,\
lpxbr,ltxbr,ltxtr,lxdb,lxdbr,lxdtr,lxeb,lxebr,m,madb,maeb,maebr,mfy,ml,mlg,\
mlgr,mlr,mr,msdb,mseb,msebr,mvc,mxbr,mxtr,oc,sfpc,slb,slbg,slbgr,slbr,\
-sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc")
+sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc,kxbr,kxtr")
(const_int 1)] (const_int 0)))
(define_attr "z13_endgroup" ""
@@ -198,7 +199,7 @@ vchlhs,vfcedbs,vfcesbs,vfchdbs,vfchedbs,vfchesbs,vfchsbs,vfeeb,vfeef,vfeeh,\
vfeneb,vfenef,vfeneh,vfenezb,vfenezf,vfenezh,vftcidb,vftcisb,vistrb,vistrf,\
vistrh,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,vlrepf,vlrepg,vlreph,vlvgp,\
vpklsfs,vpklsgs,vpklshs,vpksfs,vpksgs,vpkshs,vslb,vsrab,vsrlb,wfcdb,wfcexbs,\
-wfchexbs,wfchxbs,wfcsb")) "nothing")
+wfchexbs,wfchxbs,wfcsb,kebr,kdb,kdbr,wfkdb,wfksb")) "nothing")
(define_insn_reservation "z13_3" 3
(and (eq_attr "cpu" "z13")
@@ -232,7 +233,7 @@ wfmdb,wfmsb,wfmsdb,wfmssb,wfmsxb,wfmxb,wfsdb,wfssb,wfsxb,wldeb,wledb")) "nothing
(and (eq_attr "cpu" "z13")
(eq_attr "mnemonic" "adtr,cdtr,fidtr,ldetr,msg,msgr,sdtr,tdcdt,tdcet,\
vcdgb,vcdlgb,vcgdb,vclgdb,vfadb,vfasb,vfidb,vfisb,vfmadb,vfmasb,vfmdb,vfmsb,\
-vfmsdb,vfmssb,vfsdb,vfssb,vldeb,vledb")) "nothing")
+vfmsdb,vfmssb,vfsdb,vfssb,vldeb,vledb,kdtr")) "nothing")
(define_insn_reservation "z13_8" 8
(and (eq_attr "cpu" "z13")
@@ -254,7 +255,7 @@ celgbr,flogr,m,madb,maeb,maebr,mfy,ml,mlr,mr,msdb,mseb,msebr")) "nothing")
(define_insn_reservation "z13_12" 12
(and (eq_attr "cpu" "z13")
(eq_attr "mnemonic" "cfdbr,cfebr,cgdbr,cgebr,clfdbr,clfebr,clgdbr,\
-clgebr,cxbr,cxtr,mlg,mlgr,tcxb,tdcxt")) "nothing")
+clgebr,cxbr,cxtr,mlg,mlgr,tcxb,tdcxt,kxbr,kxtr")) "nothing")
(define_insn_reservation "z13_13" 13
(and (eq_attr "cpu" "z13")
diff --git a/gcc/config/s390/3906.md b/gcc/config/s390/3906.md
index 8cb4565ee22..1212d8b61f1 100644
--- a/gcc/config/s390/3906.md
+++ b/gcc/config/s390/3906.md
@@ -71,7 +71,7 @@ sgh,sh,shy,sl,slb,slbg,slg,slgf,sly,sqdb,sqeb,st,stc,stcy,std,stdy,ste,\
stey,stg,stgrl,sth,sthrl,sthy,stoc,stocg,strl,strv,strvg,strvh,sty,sy,\
tabort,tm,tmy,vl,vlbb,vleb,vlef,vleg,vleh,vll,vllezb,vllezf,vllezg,vllezh,\
vllezlf,vlrepb,vlrepf,vlrepg,vlreph,vlrl,vlrlr,vst,vstl,vstrl,vstrlr,x,xg,xi,\
-xiy,xy")
+xiy,xy,kdb")
(const_int 1)] (const_int 0)))
(define_attr "z14_unit_vfu" ""
@@ -113,7 +113,8 @@ wfadb,wfasb,wfaxb,wfcdb,wfcedb,wfcesb,wfcexbs,wfchdb,wfchedb,wfchesb,\
wfchexb,wfchexbs,wfchsb,wfchxb,wfchxbs,wfcsb,wfisb,wfixb,wflcdb,wflcsb,wflcxb,\
wflld,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmadb,wfmasb,wfmaxb,\
wfmaxxb,wfmdb,wfminxb,wfmsb,wfmsdb,wfmssb,wfmsxb,wfmxb,wfnmaxb,wfnmsxb,wfsdb,\
-wfssb,wfsxb,wldeb,wledb")
+wfssb,wfsxb,wldeb,wledb,kebr,kdb,kdbr,kxbr,kdtr,kxtr,wfkdb,wfksb,vfkesb,\
+vfkedb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,vfkhedb,wfkhexb")
(const_int 1)] (const_int 0)))
(define_attr "z14_cracked" ""
@@ -135,7 +136,7 @@ stmg,stmy,tbegin,tbeginc")
cxtr,dlgr,dlr,dr,dsgfr,dsgr,dxbr,dxtr,fixbr,fixbra,fixtr,flogr,lcxbr,lnxbr,\
lpxbr,ltxbr,ltxtr,lxdb,lxdbr,lxdtr,lxeb,lxebr,m,madb,maeb,maebr,mfy,mg,mgrk,\
ml,mlg,mlgr,mlr,mr,msdb,mseb,msebr,mvc,mxbr,mxtr,oc,ppa,sfpc,slb,slbg,\
-slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc")
+slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc,kxbr,kxtr")
(const_int 1)] (const_int 0)))
(define_attr "z14_endgroup" ""
@@ -192,7 +193,8 @@ vrepig,vrepih,vsb,vsbiq,vscbib,vscbif,vscbig,vscbih,vscbiq,vsegb,vsegf,vsegh,\
vsel,vsf,vsg,vsh,vsl,vslb,vsldb,vsq,vsra,vsrab,vsrl,vsrlb,vuphb,vuphf,\
vuphh,vuplb,vuplf,vuplhb,vuplhf,vuplhh,vuplhw,vupllb,vupllf,vupllh,vx,vzero,\
wfcedb,wfcesb,wfchdb,wfchedb,wfchesb,wfchexb,wfchsb,wfchxb,wflcdb,wflcsb,\
-wflcxb,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmaxxb,wfminxb,xi,xiy")) "nothing")
+wflcxb,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmaxxb,wfminxb,xi,xiy,\
+vfkesb,vfkedb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,vfkhedb,wfkhexb")) "nothing")
(define_insn_reservation "z14_2" 2
(and (eq_attr "cpu" "z14")
@@ -204,7 +206,7 @@ vchlhs,vfcedbs,vfcesbs,vfchdbs,vfchedbs,vfchesbs,vfchsbs,vfeeb,vfeef,vfeeh,\
vfeneb,vfenef,vfeneh,vfenezb,vfenezf,vfenezh,vftcidb,vftcisb,vistrb,vistrf,\
vistrh,vlgvf,vlgvg,vlgvh,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,vlrepf,\
vlrepg,vlreph,vlrl,vlvgp,vpklsfs,vpklsgs,vpklshs,vpksfs,vpksgs,vpkshs,wfcdb,\
-wfcexbs,wfchexbs,wfchxbs,wfcsb")) "nothing")
+wfcexbs,wfchexbs,wfchxbs,wfcsb,kebr,kdb,kdbr,wfkdb,wfksb")) "nothing")
(define_insn_reservation "z14_3" 3
(and (eq_attr "cpu" "z14")
@@ -238,7 +240,8 @@ wfmasb,wfmdb,wfmsb,wfmsdb,wfmssb,wfsdb,wfssb,wldeb,wledb")) "nothing")
(define_insn_reservation "z14_7" 7
(and (eq_attr "cpu" "z14")
(eq_attr "mnemonic" "adtr,cdtr,fidtr,ldetr,msgrkc,sdtr,tdcdt,tdcet,\
-vfasb,vfisb,vfmasb,vfmsb,vfmssb,vfnmssb,vfssb,vgef,vgeg,wflld")) "nothing")
+vfasb,vfisb,vfmasb,vfmsb,vfmssb,vfnmssb,vfssb,vgef,vgeg,wflld,kdtr"))
+"nothing")
(define_insn_reservation "z14_8" 8
(and (eq_attr "cpu" "z14")
@@ -261,7 +264,7 @@ celgbr,madb,maeb,maebr,msdb,mseb,msebr,vscef,vsceg")) "nothing")
(define_insn_reservation "z14_12" 12
(and (eq_attr "cpu" "z14")
(eq_attr "mnemonic" "cfdbr,cfebr,cgdbr,cgebr,clfdbr,clfebr,clgdbr,\
-clgebr,cxbr,cxtr,tcxb,tdcxt")) "nothing")
+clgebr,cxbr,cxtr,tcxb,tdcxt,kxbr,kxtr")) "nothing")
(define_insn_reservation "z14_13" 13
(and (eq_attr "cpu" "z14")
diff --git a/gcc/config/s390/8561.md b/gcc/config/s390/8561.md
index e5a345f4dba..91a92b6bc5c 100644
--- a/gcc/config/s390/8561.md
+++ b/gcc/config/s390/8561.md
@@ -70,7 +70,7 @@ sar,sdb,seb,sfpc,sg,sgf,sgh,sh,shy,sl,slb,slbg,slg,slgf,sly,sqdb,sqeb,st,\
stc,stcy,std,stdy,ste,stey,stg,stgrl,sth,sthrl,sthy,stoc,stocg,strl,strv,\
strvg,strvh,sty,sy,tabort,tm,tmy,vl,vlbb,vleb,vlef,vleg,vleh,vll,vllezb,\
vllezf,vllezg,vllezh,vllezlf,vlrepb,vlrepf,vlrepg,vlreph,vlrl,vlrlr,vst,\
-vstef,vsteg,vstl,vstrl,vstrlr,x,xg,xi,xiy,xy")
+vstef,vsteg,vstl,vstrl,vstrlr,x,xg,xi,xiy,xy,keb,kdb")
(const_int 1)] (const_int 0)))
(define_attr "arch13_unit_vfu" ""
@@ -112,7 +112,9 @@ vupllf,vupllh,vx,vzero,wfadb,wfasb,wfaxb,wfcdb,wfcedb,wfcesb,wfcexb,wfcexbs,\
wfchdb,wfchedb,wfchesb,wfchexb,wfchexbs,wfchsb,wfchxb,wfchxbs,wfcsb,wfidb,\
wfisb,wfixb,wflcdb,wflcsb,wflcxb,wflld,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,\
wflpxb,wfmadb,wfmasb,wfmaxb,wfmaxxb,wfmdb,wfminxb,wfmsb,wfmsdb,wfmssb,wfmsxb,\
-wfmxb,wfnmaxb,wfnmsxb,wfsdb,wfssb,wfsxb,wldeb,wledb")
+wfmxb,wfnmaxb,wfnmsxb,wfsdb,wfssb,wfsxb,wldeb,wledb,keb,kebr,kdb,kdbr,kxbr,\
+kdtr,kxtr,wfkdb,wfksb,vfkesb,vfkedb,wfkexb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,\
+vfkhedb,wfkhexb")
(const_int 1)] (const_int 0)))
(define_attr "arch13_cracked" ""
@@ -134,7 +136,7 @@ stam,stm,stmg,stmy,tbegin,tbeginc")
cxtr,dlgr,dlr,dr,dsgfr,dsgr,dxbr,dxtr,fixbr,fixbra,fixtr,flogr,lcxbr,lnxbr,\
lpxbr,ltxbr,ltxtr,lxdb,lxdbr,lxdtr,lxeb,lxebr,m,madb,maeb,maebr,mfy,mg,mgrk,\
ml,mlg,mlgr,mlr,mr,msdb,mseb,msebr,mvc,mxbr,mxtr,nc,oc,ppa,sfpc,slb,slbg,\
-slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc")
+slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc,kxbr,kxtr")
(const_int 1)] (const_int 0)))
(define_attr "arch13_endgroup" ""
@@ -194,7 +196,8 @@ vsel,vsf,vsg,vsh,vsl,vslb,vsldb,vsq,vsra,vsrab,vsrl,vsrlb,vuphb,vuphf,\
vuphh,vuplb,vuplf,vuplhb,vuplhf,vuplhh,vuplhw,vupllb,vupllf,vupllh,vx,vzero,\
wfcedb,wfcesb,wfcexb,wfchdb,wfchedb,wfchesb,wfchexb,wfchsb,wfchxb,wflcdb,\
wflcsb,wflcxb,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmaxxb,wfminxb,xi,\
-xiy")) "nothing")
+xiy,vfkesb,vfkedb,wfkexb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,vfkhedb,wfkhexb"))
+"nothing")
(define_insn_reservation "arch13_2" 2
(and (eq_attr "cpu" "arch13")
@@ -206,7 +209,8 @@ vchlhs,vfcedbs,vfcesbs,vfchdbs,vfchedbs,vfchesbs,vfchsbs,vfeeb,vfeef,vfeeh,\
vfeneb,vfenef,vfeneh,vfenezb,vfenezf,vfenezh,vftcidb,vftcisb,vistrb,vistrf,\
vistrh,vlgvb,vlgvf,vlgvg,vlgvh,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,\
vlrepf,vlrepg,vlreph,vlrl,vlvgp,vpklsfs,vpklsgs,vpklshs,vpksfs,vpksgs,vpkshs,\
-wfcdb,wfcexbs,wfchexbs,wfchxbs,wfcsb")) "nothing")
+wfcdb,wfcexbs,wfchexbs,wfchxbs,wfcsb,keb,kebr,kdb,kdbr,wfkdb,wfksb"))
+"nothing")
(define_insn_reservation "arch13_3" 3
(and (eq_attr "cpu" "arch13")
@@ -240,7 +244,7 @@ wfmasb,wfmdb,wfmsb,wfmsdb,wfmssb,wfsdb,wfssb,wldeb,wledb")) "nothing")
(define_insn_reservation "arch13_7" 7
(and (eq_attr "cpu" "arch13")
(eq_attr "mnemonic" "adtr,cdtr,fidtr,ldetr,ltdtr,msgrkc,sdtr,tdcdt,\
-tdcet,vgef,vgeg")) "nothing")
+tdcet,vgef,vgeg,kdtr")) "nothing")
(define_insn_reservation "arch13_8" 8
(and (eq_attr "cpu" "arch13")
@@ -263,7 +267,8 @@ clgebr,mg,mgrk,mlg,mlgr")) "nothing")
(define_insn_reservation "arch13_12" 12
(and (eq_attr "cpu" "arch13")
-(eq_attr "mnemonic" "cxbr,cxftr,cxlftr,cxtr,tcxb,tdcxt")) "nothing")
+(eq_attr "mnemonic" "cxbr,cxftr,cxlftr,cxtr,tcxb,tdcxt,kxbr,kxtr"))
+"nothing")
(define_insn_reservation "arch13_13" 13
(and (eq_attr "cpu" "arch13")
diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def
index cfc69651b0d..013cac0206a 100644
--- a/gcc/config/s390/s390-builtins.def
+++ b/gcc/config/s390/s390-builtins.def
@@ -1495,8 +1495,8 @@ B_DEF (vec_cmpgev4si, vec_cmpgev4si, 0,
B_DEF (vec_cmpgeuv4si, vec_cmpgeuv4si, 0, B_INT | B_VX, 0, BT_FN_V4SI_UV4SI_UV4SI)
B_DEF (vec_cmpgev2di, vec_cmpgev2di, 0, B_INT | B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
B_DEF (vec_cmpgeuv2di, vec_cmpgeuv2di, 0, B_INT | B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF (s390_vfchesb, vec_cmpgev4sf, 0, B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
-B_DEF (s390_vfchedb, vec_cmpgev2df, 0, B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
+B_DEF (s390_vfchesb, vec_cmpgev4sf_quiet_nocc,0, B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
+B_DEF (s390_vfchedb, vec_cmpgev2df_quiet_nocc,0, B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
OB_DEF (s390_vec_cmpgt, s390_vec_cmpgt_s8, s390_vec_cmpgt_dbl, B_VX, BT_FN_OV4SI_OV4SI_OV4SI)
OB_DEF_VAR (s390_vec_cmpgt_s8, s390_vchb, 0, 0, BT_OV_BV16QI_V16QI_V16QI)
@@ -1518,8 +1518,8 @@ B_DEF (s390_vchf, vec_cmpgtv4si, 0,
B_DEF (s390_vchlf, vec_cmpgtuv4si, 0, B_VX, 0, BT_FN_V4SI_UV4SI_UV4SI)
B_DEF (s390_vchg, vec_cmpgtv2di, 0, B_VX, 0, BT_FN_V2DI_V2DI_V2DI)
B_DEF (s390_vchlg, vec_cmpgtuv2di, 0, B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF (s390_vfchsb, vec_cmpgtv4sf, 0, B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
-B_DEF (s390_vfchdb, vec_cmpgtv2df, 0, B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
+B_DEF (s390_vfchsb, vec_cmpgtv4sf_quiet_nocc,0, B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
+B_DEF (s390_vfchdb, vec_cmpgtv2df_quiet_nocc,0, B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
OB_DEF (s390_vec_cmple, s390_vec_cmple_s8, s390_vec_cmple_dbl, B_VX, BT_FN_OV4SI_OV4SI_OV4SI)
OB_DEF_VAR (s390_vec_cmple_s8, vec_cmplev16qi, 0, 0, BT_OV_BV16QI_V16QI_V16QI)
@@ -1541,8 +1541,8 @@ B_DEF (vec_cmplev4si, vec_cmplev4si, 0,
B_DEF (vec_cmpleuv4si, vec_cmpleuv4si, 0, B_INT | B_VX, 0, BT_FN_V4SI_UV4SI_UV4SI)
B_DEF (vec_cmplev2di, vec_cmplev2di, 0, B_INT | B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
B_DEF (vec_cmpleuv2di, vec_cmpleuv2di, 0, B_INT | B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF (vec_cmplev4sf, vec_cmplev4sf, 0, B_INT | B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
-B_DEF (vec_cmplev2df, vec_cmplev2df, 0, B_INT | B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
+B_DEF (vec_cmplev4sf, vec_cmplev4sf_quiet_nocc,0, B_INT | B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
+B_DEF (vec_cmplev2df, vec_cmplev2df_quiet_nocc,0, B_INT | B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
OB_DEF (s390_vec_cmplt, s390_vec_cmplt_s8, s390_vec_cmplt_dbl, B_VX, BT_FN_OV4SI_OV4SI_OV4SI)
OB_DEF_VAR (s390_vec_cmplt_s8, vec_cmpltv16qi, 0, 0, BT_OV_BV16QI_V16QI_V16QI)
@@ -1564,8 +1564,8 @@ B_DEF (vec_cmpltv4si, vec_cmpltv4si, 0,
B_DEF (vec_cmpltuv4si, vec_cmpltuv4si, 0, B_INT | B_VX, 0, BT_FN_V4SI_UV4SI_UV4SI)
B_DEF (vec_cmpltv2di, vec_cmpltv2di, 0, B_INT | B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
B_DEF (vec_cmpltuv2di, vec_cmpltuv2di, 0, B_INT | B_VX, 0, BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF (vec_cmpltv4sf, vec_cmpltv4sf, 0, B_INT | B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
-B_DEF (vec_cmpltv2df, vec_cmpltv2df, 0, B_INT | B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
+B_DEF (vec_cmpltv4sf, vec_cmpltv4sf_quiet_nocc,0, B_INT | B_VXE, 0, BT_FN_V4SI_V4SF_V4SF)
+B_DEF (vec_cmpltv2df, vec_cmpltv2df_quiet_nocc,0, B_INT | B_VX, 0, BT_FN_V2DI_V2DF_V2DF)
OB_DEF (s390_vec_cntlz, s390_vec_cntlz_s8, s390_vec_cntlz_u64, B_VX, BT_FN_OV4SI_OV4SI)
OB_DEF_VAR (s390_vec_cntlz_s8, s390_vclzb, 0, 0, BT_OV_UV16QI_V16QI)
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index 7b7c1141449..2d9cd9b5945 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -52,6 +52,8 @@ CCS: EQ LT GT UNORDERED (LTGFR, LTGR, LTR, ICM/Y,
ADB/R, AEB/R, SDB/R, SEB/R,
SRAG, SRA, SRDA)
CCSR: EQ GT LT UNORDERED (CGF/R, CH/Y)
+CCSFPS: EQ GT LT UNORDERED (KEB/R, KDB/R, KXBR, KDTR,
+ KXTR, WFK)
Condition codes resulting from add with overflow
@@ -140,6 +142,11 @@ around. The following both modes can be considered as CCS and CCU modes with
exchanged operands.
+CCSFPS
+
+This mode is used for signaling rtxes: LT, LE, GT, GE and LTGT.
+
+
CCL1, CCL2
These modes represent the result of overflow checks.
@@ -226,6 +233,7 @@ CC_MODE (CCU);
CC_MODE (CCUR);
CC_MODE (CCS);
CC_MODE (CCSR);
+CC_MODE (CCSFPS);
CC_MODE (CCT);
CC_MODE (CCT1);
CC_MODE (CCT2);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index f36e12affd2..ae1545c39f7 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1376,6 +1376,7 @@ s390_match_ccmode_set (rtx set, machine_mode req_mode)
case E_CCZ1mode:
case E_CCSmode:
case E_CCSRmode:
+ case E_CCSFPSmode:
case E_CCUmode:
case E_CCURmode:
case E_CCOmode:
@@ -1559,6 +1560,12 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
else
return CCAPmode;
}
+
+ /* Fall through. */
+ case LTGT:
+ if (HONOR_NANS (op0) || HONOR_NANS (op1))
+ return CCSFPSmode;
+
/* Fall through. */
case UNORDERED:
case ORDERED:
@@ -1567,7 +1574,6 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
case UNLT:
case UNGE:
case UNGT:
- case LTGT:
if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
&& GET_CODE (op1) != CONST_INT)
return CCSRmode;
@@ -2082,6 +2088,7 @@ s390_branch_condition_mask (rtx code)
break;
case E_CCSmode:
+ case E_CCSFPSmode:
switch (GET_CODE (code))
{
case EQ: return CC0;
@@ -6504,18 +6511,23 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
{
/* NE a != b -> !(a == b) */
case NE: cond = EQ; neg_p = true; break;
- /* UNGT a u> b -> !(b >= a) */
- case UNGT: cond = GE; neg_p = true; swap_p = true; break;
- /* UNGE a u>= b -> !(b > a) */
- case UNGE: cond = GT; neg_p = true; swap_p = true; break;
- /* LE: a <= b -> b >= a */
+ case UNGT:
+ emit_insn (gen_vec_cmpungt (target, cmp_op1, cmp_op2));
+ return;
+ case UNGE:
+ emit_insn (gen_vec_cmpunge (target, cmp_op1, cmp_op2));
+ return;
case LE: cond = GE; swap_p = true; break;
- /* UNLE: a u<= b -> !(a > b) */
- case UNLE: cond = GT; neg_p = true; break;
+ /* UNLE: (a u<= b) -> (b u>= a). */
+ case UNLE:
+ emit_insn (gen_vec_cmpunge (target, cmp_op2, cmp_op1));
+ return;
/* LT: a < b -> b > a */
case LT: cond = GT; swap_p = true; break;
- /* UNLT: a u< b -> !(a >= b) */
- case UNLT: cond = GE; neg_p = true; break;
+ /* UNLT: (a u< b) -> (b u> a). */
+ case UNLT:
+ emit_insn (gen_vec_cmpungt (target, cmp_op2, cmp_op1));
+ return;
case UNEQ:
emit_insn (gen_vec_cmpuneq (target, cmp_op1, cmp_op2));
return;
@@ -6678,7 +6690,7 @@ s390_reverse_condition (machine_mode mode, enum rtx_code code)
{
/* Reversal of FP compares takes care -- an ordered compare
becomes an unordered compare and vice versa. */
- if (mode == CCVFALLmode || mode == CCVFANYmode)
+ if (mode == CCVFALLmode || mode == CCVFANYmode || mode == CCSFPSmode)
return reverse_condition_maybe_unordered (code);
else if (mode == CCVIALLmode || mode == CCVIANYmode)
return reverse_condition (code);
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index e4516f6c378..bf3e051dbae 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1424,6 +1424,20 @@
(set_attr "cpu_facility" "*,*,vx,vxe")
(set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
+(define_insn "*cmp<mode>_ccsfps"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:FP 0 "register_operand" "f,f,v,v")
+ (match_operand:FP 1 "general_operand" "f,R,v,v")))]
+ "s390_match_ccmode (insn, CCSFPSmode) && TARGET_HARD_FLOAT"
+ "@
+ k<xde><bt>r\t%0,%1
+ k<xde>b\t%0,%1
+ wfkdb\t%0,%1
+ wfksb\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE,VRR,VRR")
+ (set_attr "cpu_facility" "*,*,vx,vxe")
+ (set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
+
; Compare and Branch instructions
; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index a093ae5c565..7f33d34e726 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -168,10 +168,6 @@
(define_mode_attr vec_halfnumelts
[(V4SF "V2SF") (V4SI "V2SI")])
-; The comparisons not setting CC iterate over the rtx code.
-(define_code_iterator VFCMP_HW_OP [eq gt ge])
-(define_code_attr asm_fcmp_op [(eq "e") (gt "h") (ge "he")])
-
; Comparison operators on int and fp compares which are directly
@@ -1392,7 +1388,8 @@
"#"
"&& 1"
[(set (match_dup 3)
- (gt:V2DI (match_dup 1) (match_dup 2)))
+ (not:V2DI
+ (unge:V2DI (match_dup 2) (match_dup 1))))
(set (match_dup 0)
(if_then_else:V2DF
(eq (match_dup 3) (match_dup 4))
@@ -1427,7 +1424,8 @@
"#"
"&& 1"
[(set (match_dup 3)
- (gt:V2DI (match_dup 1) (match_dup 2)))
+ (not:V2DI
+ (unge:V2DI (match_dup 2) (match_dup 1))))
(set (match_dup 0)
(if_then_else:V2DF
(eq (match_dup 3) (match_dup 4))
@@ -1481,27 +1479,134 @@
;; Floating point compares
;;
-; EQ, GT, GE
-; vfcesb, vfcedb, wfcexb, vfchsb, vfchdb, wfchxb, vfchesb, vfchedb, wfchexb
-(define_insn "*vec_cmp<VFCMP_HW_OP:code><mode>_nocc"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (VFCMP_HW_OP:<tointvec> (match_operand:VFT 1 "register_operand" "v")
- (match_operand:VFT 2 "register_operand" "v")))]
- "TARGET_VX"
- "<vw>fc<VFCMP_HW_OP:asm_fcmp_op><sdx>b\t%v0,%v1,%v2"
+; vfcesb, vfcedb, wfcexb: non-signaling "==" comparison (a == b)
+(define_insn "*vec_cmpeq<mode>_quiet_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (eq:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v")))]
+ "TARGET_VX"
+ "<vw>fce<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+; vfchsb, vfchdb, wfchxb: non-signaling > comparison (!(b u>= a))
+(define_insn "vec_cmpgt<mode>_quiet_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unge:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+ (match_operand:VFT 1 "register_operand" "v"))))]
+ "TARGET_VX"
+ "<vw>fch<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+(define_expand "vec_cmplt<mode>_quiet_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v"))))]
+ "TARGET_VX")
+
+; vfchesb, vfchedb, wfchexb: non-signaling >= comparison (!(a u< b))
+(define_insn "vec_cmpge<mode>_quiet_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v"))))]
+ "TARGET_VX"
+ "<vw>fche<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+(define_expand "vec_cmple<mode>_quiet_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+ (match_operand:VFT 1 "register_operand" "v"))))]
+ "TARGET_VX")
+
+; vfkesb, vfkedb, wfkexb: signaling == comparison ((a >= b) & (b >= a))
+(define_insn "*vec_cmpeq<mode>_signaling_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (and:<tointvec>
+ (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v"))
+ (ge:<tointvec> (match_dup 2)
+ (match_dup 1))))]
+ "TARGET_VXE"
+ "<vw>fke<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+; vfkhsb, vfkhdb, wfkhxb: signaling > comparison (a > b)
+(define_insn "*vec_cmpgt<mode>_signaling_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v")))]
+ "TARGET_VXE"
+ "<vw>fkh<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+(define_insn "*vec_cmpgt<mode>_signaling_finite_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v")))]
+ "TARGET_VX && !TARGET_VXE && flag_finite_math_only"
+ "<vw>fch<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+; vfkhesb, vfkhedb, wfkhexb: signaling >= comparison (a >= b)
+(define_insn "*vec_cmpge<mode>_signaling_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v")))]
+ "TARGET_VXE"
+ "<vw>fkhe<sdx>b\t%v0,%v1,%v2"
+ [(set_attr "op_type" "VRR")])
+
+(define_insn "*vec_cmpge<mode>_signaling_finite_nocc"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v")))]
+ "TARGET_VX && !TARGET_VXE && flag_finite_math_only"
+ "<vw>fche<sdx>b\t%v0,%v1,%v2"
[(set_attr "op_type" "VRR")])
; Expanders for not directly supported comparisons
+; Signaling comparisons must be expressed via signaling rtxes only,
+; and quiet comparisons must be expressed via quiet rtxes only.
+
+; UNGT a u> b -> !!(b u< a)
+(define_expand "vec_cmpungt<mode>"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+ (match_operand:VFT 1 "register_operand" "v"))))
+ (set (match_dup 0)
+ (not:<tointvec> (match_dup 0)))]
+ "TARGET_VX")
-; UNEQ a u== b -> !(a > b | b > a)
+; UNGE a u>= b -> !!(a u>= b)
+(define_expand "vec_cmpunge<mode>"
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v"))))
+ (set (match_dup 0)
+ (not:<tointvec> (match_dup 0)))]
+ "TARGET_VX")
+
+; UNEQ a u== b -> !(!(a u>= b) | !(b u>= a))
(define_expand "vec_cmpuneq<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
- (match_operand:VFT 2 "register_operand" "v")))
- (set (match_dup 3)
- (gt:<tointvec> (match_dup 2) (match_dup 1)))
- (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
- (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v"))))
+ (set (match_dup 3)
+ (not:<tointvec>
+ (unge:<tointvec> (match_dup 2)
+ (match_dup 1))))
+ (set (match_dup 0)
+ (ior:<tointvec> (match_dup 0)
+ (match_dup 3)))
+ (set (match_dup 0)
+ (not:<tointvec> (match_dup 0)))]
"TARGET_VX"
{
operands[3] = gen_reg_rtx (<tointvec>mode);
@@ -1514,18 +1619,24 @@
(match_operand:VFT 2 "register_operand" "v")))
(set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
(set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
- "TARGET_VX"
+ "TARGET_VXE"
{
operands[3] = gen_reg_rtx (<tointvec>mode);
})
-; ORDERED (a, b): a >= b | b > a
+; ORDERED (a, b): !(a u< b) | !(a u>= b)
(define_expand "vec_cmpordered<mode>"
- [(set (match_operand:<tointvec> 0 "register_operand" "=v")
- (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
- (match_operand:VFT 2 "register_operand" "v")))
- (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
- (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
+ [(set (match_operand:<tointvec> 0 "register_operand" "=v")
+ (not:<tointvec>
+ (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+ (match_operand:VFT 2 "register_operand" "v"))))
+ (set (match_dup 3)
+ (not:<tointvec>
+ (unge:<tointvec> (match_dup 1)
+ (match_dup 2))))
+ (set (match_dup 0)
+ (ior:<tointvec> (match_dup 0)
+ (match_dup 3)))]
"TARGET_VX"
{
operands[3] = gen_reg_rtx (<tointvec>mode);
@@ -1545,7 +1656,7 @@
})
(define_code_iterator VEC_CODE_WITH_COMPLEX_EXPAND
- [uneq ltgt ordered unordered])
+ [ungt unge uneq ltgt ordered unordered])
(define_expand "vec_cmp<code>"
[(match_operand 0 "register_operand" "")
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
index ea51d0c86af..073d574aa5e 100644
--- a/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
+++ b/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
@@ -34,7 +34,7 @@ gt (double a, double b)
return a > b;
}
-/* { dg-final { scan-assembler "gt:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinh\t%r2,0" } } */
+/* { dg-final { scan-assembler "gt:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinh\t%r2,0" } } */
int
ge (double a, double b)
@@ -45,7 +45,7 @@ ge (double a, double b)
return a >= b;
}
-/* { dg-final { scan-assembler "ge:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinhe\t%r2,0" } } */
+/* { dg-final { scan-assembler "ge:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinhe\t%r2,0" } } */
int
lt (double a, double b)
@@ -56,7 +56,7 @@ lt (double a, double b)
return a < b;
}
-/* { dg-final { scan-assembler "lt:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinl\t%r2,0" } } */
+/* { dg-final { scan-assembler "lt:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinl\t%r2,0" } } */
int
le (double a, double b)
@@ -67,4 +67,4 @@ le (double a, double b)
return a <= b;
}
-/* { dg-final { scan-assembler "le:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinle\t%r2,0" } } */
+/* { dg-final { scan-assembler "le:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinle\t%r2,0" } } */
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
` (6 preceding siblings ...)
2019-09-05 11:12 ` [PATCH v3 8/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
@ 2019-09-05 11:12 ` Ilya Leoshkevich
2019-09-30 14:50 ` Andreas Krebbel
2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test signaling FP comparison instructions Ilya Leoshkevich
8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:12 UTC (permalink / raw)
To: gcc-patches
Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
rdapp, Ilya Leoshkevich
s390.md uses a lot of near-identical expanders that perform dispatching
to other expanders based on operand types. Since the following patch
would require even more of these, avoid copy-pasting the code by
generating these expanders using an iterator.
gcc/ChangeLog:
2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* config/s390/s390.c (s390_expand_vec_compare): Use
gen_vec_cmpordered and gen_vec_cmpunordered.
* config/s390/vector.md (vec_cmpuneq, vec_cmpltgt, vec_ordered,
vec_unordered): Delete.
(vec_ordered<mode>): Rename to vec_cmpordered<mode>.
(vec_unordered<mode>): Rename to vec_cmpunordered<mode>.
(vec_cmp<code>): Generic dispatcher.
---
gcc/config/s390/s390.c | 4 +--
gcc/config/s390/vector.md | 67 +++++++--------------------------------
2 files changed, 13 insertions(+), 58 deletions(-)
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 24784266848..f36e12affd2 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6523,10 +6523,10 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
emit_insn (gen_vec_cmpltgt (target, cmp_op1, cmp_op2));
return;
case ORDERED:
- emit_insn (gen_vec_ordered (target, cmp_op1, cmp_op2));
+ emit_insn (gen_vec_cmpordered (target, cmp_op1, cmp_op2));
return;
case UNORDERED:
- emit_insn (gen_vec_unordered (target, cmp_op1, cmp_op2));
+ emit_insn (gen_vec_cmpunordered (target, cmp_op1, cmp_op2));
return;
default: break;
}
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 1b66b8be61f..a093ae5c565 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1507,22 +1507,6 @@
operands[3] = gen_reg_rtx (<tointvec>mode);
})
-(define_expand "vec_cmpuneq"
- [(match_operand 0 "register_operand" "")
- (match_operand 1 "register_operand" "")
- (match_operand 2 "register_operand" "")]
- "TARGET_VX"
-{
- if (GET_MODE (operands[1]) == V4SFmode)
- emit_insn (gen_vec_cmpuneqv4sf (operands[0], operands[1], operands[2]));
- else if (GET_MODE (operands[1]) == V2DFmode)
- emit_insn (gen_vec_cmpuneqv2df (operands[0], operands[1], operands[2]));
- else
- gcc_unreachable ();
-
- DONE;
-})
-
; LTGT a <> b -> a > b | b > a
(define_expand "vec_cmpltgt<mode>"
[(set (match_operand:<tointvec> 0 "register_operand" "=v")
@@ -1535,24 +1519,8 @@
operands[3] = gen_reg_rtx (<tointvec>mode);
})
-(define_expand "vec_cmpltgt"
- [(match_operand 0 "register_operand" "")
- (match_operand 1 "register_operand" "")
- (match_operand 2 "register_operand" "")]
- "TARGET_VX"
-{
- if (GET_MODE (operands[1]) == V4SFmode)
- emit_insn (gen_vec_cmpltgtv4sf (operands[0], operands[1], operands[2]));
- else if (GET_MODE (operands[1]) == V2DFmode)
- emit_insn (gen_vec_cmpltgtv2df (operands[0], operands[1], operands[2]));
- else
- gcc_unreachable ();
-
- DONE;
-})
-
; ORDERED (a, b): a >= b | b > a
-(define_expand "vec_ordered<mode>"
+(define_expand "vec_cmpordered<mode>"
[(set (match_operand:<tointvec> 0 "register_operand" "=v")
(ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")))
@@ -1563,45 +1531,32 @@
operands[3] = gen_reg_rtx (<tointvec>mode);
})
-(define_expand "vec_ordered"
- [(match_operand 0 "register_operand" "")
- (match_operand 1 "register_operand" "")
- (match_operand 2 "register_operand" "")]
- "TARGET_VX"
-{
- if (GET_MODE (operands[1]) == V4SFmode)
- emit_insn (gen_vec_orderedv4sf (operands[0], operands[1], operands[2]));
- else if (GET_MODE (operands[1]) == V2DFmode)
- emit_insn (gen_vec_orderedv2df (operands[0], operands[1], operands[2]));
- else
- gcc_unreachable ();
-
- DONE;
-})
-
; UNORDERED (a, b): !ORDERED (a, b)
-(define_expand "vec_unordered<mode>"
+(define_expand "vec_cmpunordered<mode>"
[(match_operand:<tointvec> 0 "register_operand" "=v")
(match_operand:VFT 1 "register_operand" "v")
(match_operand:VFT 2 "register_operand" "v")]
"TARGET_VX"
{
- emit_insn (gen_vec_ordered<mode> (operands[0], operands[1], operands[2]));
+ emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_NOT (<tointvec>mode, operands[0])));
DONE;
})
-(define_expand "vec_unordered"
+(define_code_iterator VEC_CODE_WITH_COMPLEX_EXPAND
+ [uneq ltgt ordered unordered])
+
+(define_expand "vec_cmp<code>"
[(match_operand 0 "register_operand" "")
- (match_operand 1 "register_operand" "")
- (match_operand 2 "register_operand" "")]
+ (VEC_CODE_WITH_COMPLEX_EXPAND (match_operand 1 "register_operand" "")
+ (match_operand 2 "register_operand" ""))]
"TARGET_VX"
{
if (GET_MODE (operands[1]) == V4SFmode)
- emit_insn (gen_vec_unorderedv4sf (operands[0], operands[1], operands[2]));
+ emit_insn (gen_vec_cmp<code>v4sf (operands[0], operands[1], operands[2]));
else if (GET_MODE (operands[1]) == V2DFmode)
- emit_insn (gen_vec_unorderedv2df (operands[0], operands[1], operands[2]));
+ emit_insn (gen_vec_cmp<code>v2df (operands[0], operands[1], operands[2]));
else
gcc_unreachable ();
--
2.21.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
@ 2019-09-06 10:34 ` Segher Boessenkool
2019-09-30 13:36 ` Ilya Leoshkevich
0 siblings, 1 reply; 23+ messages in thread
From: Segher Boessenkool @ 2019-09-06 10:34 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: gcc-patches, richard.guenther, richard.sandiford, joseph, krebbel, rdapp
Hi Ilya,
On Thu, Sep 05, 2019 at 01:10:14PM +0200, Ilya Leoshkevich wrote:
> z13 supports only non-signaling vector comparisons. This means we
> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13. Notify
> middle-end about this using more restrictive operator predicate in
> vcond<V_HW:mode><V_HW2:mode>.
> +(define_predicate "vcond_comparison_operator"
> + (match_operand 0 "comparison_operator")
> +{
> + if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
> + && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
> + return true;
> + switch (GET_CODE (op))
> + {
> + case LE:
> + case LT:
> + case GE:
> + case GT:
> + case LTGT:
> + /* Signaling vector comparisons are supported only on z14+. */
> + return TARGET_Z14;
> + default:
> + return true;
> + }
> +})
Should you handle -fsignaling-nans here as well?
Segher
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
@ 2019-09-06 11:07 ` Richard Biener
2019-09-06 15:45 ` Ilya Leoshkevich
0 siblings, 1 reply; 23+ messages in thread
From: Richard Biener @ 2019-09-06 11:07 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
Joseph S. Myers, Andreas Krebbel, Robin Dapp
On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
> and introduces a temporary if this could happen, for example, generating
>
> _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
> _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
>
> from GENERIC
>
> VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
> { -1, -1, -1, -1 } ,
> { 0, 0, 0, 0 } >
>
> This is not necessary and makes the resulting GIMPLE harder to analyze.
> In particular, one of the next patches in series needs to get to
> VEC_COND_EXPR's comparison code, which is not possible when a temporary
> is introduced.
>
> This patch takes special care to avoid introducing trapping comparisons
> in GIMPLE_COND. They are not allowed, because they would require 3
> outgoing edges (then, else and EH), which is awkward to say the least.
> Therefore, computations of such conditions should live in their own basic
> blocks.
Comments inline (thanks for the work btw)
> gcc/ChangeLog:
>
> 2019-09-03 Ilya Leoshkevich <iii@linux.ibm.com>
>
> PR target/77918
> * gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
> caller passes a non-trapping condition.
> (is_gimple_condexpr): Allow trapping conditions.
> (is_gimple_condexpr_1): New helper function.
> (is_gimple_condexpr_for_cond): New function, acts like old
> is_gimple_condexpr.
> * gimple-expr.h (is_gimple_condexpr_for_cond): New function.
> (gimple_ternary_operands_ok_p): New function to remove code
> duplication i verify_gimple_assign_ternary and
> valid_gimple_rhs_p.
> * gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
> VEC_COND_EXPR.
> * gimplify.c (gimplify_cond_expr): Use
> is_gimple_condexpr_for_cond.
> (gimplify_expr): Allow is_gimple_condexpr_for_cond.
> * tree-cfg.c (verify_gimple_assign_ternary): Use
> gimple_ternary_operands_ok_p.
> * tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
> VEC_COND_EXPR.
> (tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
> * tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
> is_gimple_condexpr_for_cond, remove pointless tmp check
> (forward_propagate_into_cond): Remove pointless tmp check.
> * tree-ssa-propagate.c (valid_gimple_rhs_p): Use
> gimple_ternary_operands_ok_p.
> ---
> gcc/gimple-expr.c | 25 +++++++++++++++++++++----
> gcc/gimple-expr.h | 11 +++++++++++
> gcc/gimple.c | 2 ++
> gcc/gimplify.c | 5 +++--
> gcc/tree-cfg.c | 5 +----
> gcc/tree-eh.c | 8 ++++++++
> gcc/tree-ssa-forwprop.c | 7 ++++---
> gcc/tree-ssa-propagate.c | 9 ++++-----
> 8 files changed, 54 insertions(+), 18 deletions(-)
>
> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> index b0c9f9b671a..46e5f000580 100644
> --- a/gcc/gimple-expr.c
> +++ b/gcc/gimple-expr.c
> @@ -571,6 +571,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
> || TREE_CODE (cond) == TRUTH_NOT_EXPR
> || is_gimple_min_invariant (cond)
> || SSA_VAR_P (cond));
> + gcc_assert (!tree_could_throw_p (cond));
make this gcc_checking_assert ()
> extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
>
> @@ -602,17 +603,33 @@ is_gimple_lvalue (tree t)
> || TREE_CODE (t) == BIT_FIELD_REF);
> }
>
> -/* Return true if T is a GIMPLE condition. */
> +/* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond. */
>
> -bool
> -is_gimple_condexpr (tree t)
> +static bool
> +is_gimple_condexpr_1 (tree t, bool allow_traps)
> {
> return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
> - && !tree_could_throw_p (t)
> + && (allow_traps || !tree_could_throw_p (t))
> && is_gimple_val (TREE_OPERAND (t, 0))
> && is_gimple_val (TREE_OPERAND (t, 1))));
> }
>
> +/* Return true if T is a GIMPLE condition. */
> +
> +bool
> +is_gimple_condexpr (tree t)
> +{
> + return is_gimple_condexpr_1 (t, true);
> +}
> +
> +/* Like is_gimple_condexpr, but does not allow T to trap. */
> +
> +bool
> +is_gimple_condexpr_for_cond (tree t)
> +{
> + return is_gimple_condexpr_1 (t, false);
> +}
> +
> /* Return true if T is a gimple address. */
>
> bool
> diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
> index 1ad1432bd17..27190b1e5fe 100644
> --- a/gcc/gimple-expr.h
> +++ b/gcc/gimple-expr.h
> @@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
> tree *);
> extern bool is_gimple_lvalue (tree);
> extern bool is_gimple_condexpr (tree);
> +extern bool is_gimple_condexpr_for_cond (tree);
> extern bool is_gimple_address (const_tree);
> extern bool is_gimple_invariant_address (const_tree);
> extern bool is_gimple_ip_invariant_address (const_tree);
> @@ -175,4 +176,14 @@ gimple_call_addr_fndecl (const_tree fn)
> return NULL_TREE;
> }
>
> +static inline bool
> +gimple_ternary_operands_ok_p (enum tree_code code, tree op1, tree op2, tree op3)
> +{
> + return ((code == VEC_COND_EXPR || code == COND_EXPR)
> + ? is_gimple_condexpr (op1)
> + : is_gimple_val (op1))
> + && is_gimple_val (op2)
> + && is_gimple_val (op3);
> +}
Hmm, I don't like this too much, please simply adjust the
two places you use it (there's actually nothign to adjust?)
> #endif /* GCC_GIMPLE_EXPR_H */
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index 633ef512a19..fd14fbec15e 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
> op = gimple_assign_rhs_code (s);
> if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
> div = gimple_assign_rhs2 (s);
> + else if (op == COND_EXPR || op == VEC_COND_EXPR)
> + op = TREE_CODE (gimple_assign_rhs1 (s));
I think this is not correct since we can have
int i = fp > 1. ? intval1 : intval2
and thus FLOAT_TYPE_P (t) is wrong. You need to do
t = TREE_TYPE (op);
as well I think.
OK with those changes - you can apply this independently of the rest of the
series btw.
Thanks,
Richard.
> return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
> (INTEGRAL_TYPE_P (t)
> && TYPE_OVERFLOW_TRAPS (t)),
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index daa0b71c191..920e423381c 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -4141,8 +4141,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
> /* Now do the normal gimplification. */
>
> /* Gimplify condition. */
> - ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
> - fb_rvalue);
> + ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
> + is_gimple_condexpr_for_cond, fb_rvalue);
> if (ret == GS_ERROR)
> return GS_ERROR;
> gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
> @@ -12973,6 +12973,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
> else if (gimple_test_f == is_gimple_val
> || gimple_test_f == is_gimple_call_addr
> || gimple_test_f == is_gimple_condexpr
> + || gimple_test_f == is_gimple_condexpr_for_cond
> || gimple_test_f == is_gimple_mem_rhs
> || gimple_test_f == is_gimple_mem_rhs_or_call
> || gimple_test_f == is_gimple_reg_rhs
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index b75fdb2e63f..4d2239e9d2f 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -4121,10 +4121,7 @@ verify_gimple_assign_ternary (gassign *stmt)
> return true;
> }
>
> - if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
> - ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
> - || !is_gimple_val (rhs2)
> - || !is_gimple_val (rhs3))
> + if (!gimple_ternary_operands_ok_p (rhs_code, rhs1, rhs2, rhs3))
> {
> error ("invalid operands in ternary operation");
> return true;
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index 5bb07e49d28..98dc95a07cd 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
> bool honor_snans = fp_operation && flag_signaling_nans != 0;
> bool handled;
>
> + /* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could
> + trap, because that depends on the respective condition op. */
> + gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR);
> +
> if (TREE_CODE_CLASS (op) != tcc_comparison
> && TREE_CODE_CLASS (op) != tcc_unary
> && TREE_CODE_CLASS (op) != tcc_binary)
> @@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
> if (!expr)
> return false;
>
> + /* For COND_EXPR and VEC_COND_EXPR, only the condition may trap. */
> + if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
> + expr = TREE_OPERAND (expr, 0);
> +
> code = TREE_CODE (expr);
> t = TREE_TYPE (expr);
>
> diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
> index c464c899586..edc5417f455 100644
> --- a/gcc/tree-ssa-forwprop.c
> +++ b/gcc/tree-ssa-forwprop.c
> @@ -524,9 +524,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
> tmp = forward_propagate_into_comparison_1 (stmt, code,
> boolean_type_node,
> rhs1, rhs2);
> - if (tmp)
> + if (tmp
> + && is_gimple_condexpr_for_cond (tmp))
> {
> - if (dump_file && tmp)
> + if (dump_file)
> {
> fprintf (dump_file, " Replaced '");
> print_gimple_expr (dump_file, stmt, 0);
> @@ -604,7 +605,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
> if (tmp
> && is_gimple_condexpr (tmp))
> {
> - if (dump_file && tmp)
> + if (dump_file)
> {
> fprintf (dump_file, " Replaced '");
> print_generic_expr (dump_file, cond);
> diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
> index 7172ef8b4e6..be34e25fc40 100644
> --- a/gcc/tree-ssa-propagate.c
> +++ b/gcc/tree-ssa-propagate.c
> @@ -523,11 +523,10 @@ valid_gimple_rhs_p (tree expr)
> default:
> if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
> {
> - if (((code == VEC_COND_EXPR || code == COND_EXPR)
> - ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
> - : !is_gimple_val (TREE_OPERAND (expr, 0)))
> - || !is_gimple_val (TREE_OPERAND (expr, 1))
> - || !is_gimple_val (TREE_OPERAND (expr, 2)))
> + if (!gimple_ternary_operands_ok_p (code,
> + TREE_OPERAND (expr, 0),
> + TREE_OPERAND (expr, 1),
> + TREE_OPERAND (expr, 2)))
> return false;
> break;
> }
> --
> 2.21.0
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
@ 2019-09-06 11:09 ` Richard Biener
2019-09-06 12:40 ` Richard Sandiford
1 sibling, 0 replies; 23+ messages in thread
From: Richard Biener @ 2019-09-06 11:09 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
Joseph S. Myers, Andreas Krebbel, Robin Dapp
On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> One of the next patches in series needs to frequently pass short-lived
> fake rtxes to the back-end in order to test its capabilities. In order
> to reduce the load on GC, it is beneficial to allocate these rtxes on
> stack.
>
> Provide the macro counterparts of gen_* functions required by the next
> patch in series.
I like it. Richard S. should have the final say as gen* maintainer.
Thanks,
Richard.
> gcc/ChangeLog:
>
> 2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com>
>
> PR target/77918
> * emit-rtl.c (gen_raw_REG): Use init_raw_REG.
> (init_raw_REG): New function.
> * gengenrtl.c (gendef): Emit init_* functions and alloca_*
> macros.
> * rtl.c (rtx_alloc_stat_v): Use rtx_init.
> * rtl.h (rtx_init): New function.
> (rtx_alloca): New function.
> (init_raw_REG): New function.
> (alloca_raw_REG): New macro.
> ---
> gcc/emit-rtl.c | 15 +++++++++---
> gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
> gcc/rtl.c | 7 +-----
> gcc/rtl.h | 12 ++++++++++
> 4 files changed, 74 insertions(+), 24 deletions(-)
>
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index a667cdab94e..ecfa3735bba 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
> set_regno_raw (x, regno, nregs);
> }
>
> -/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
> +/* Initialize a REG rtx. Make sure ORIGINAL_REGNO is set properly, and
> don't attempt to share with the various global pieces of rtl (such as
> frame_pointer_rtx). */
>
> rtx
> -gen_raw_REG (machine_mode mode, unsigned int regno)
> +init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
> {
> - rtx x = rtx_alloc (REG MEM_STAT_INFO);
> set_mode_and_regno (x, mode, regno);
> REG_ATTRS (x) = NULL;
> ORIGINAL_REGNO (x) = regno;
> return x;
> }
>
> +/* Generate a new REG rtx. */
> +
> +rtx
> +gen_raw_REG (machine_mode mode, unsigned int regno)
> +{
> + rtx x = rtx_alloc (REG MEM_STAT_INFO);
> + init_raw_REG (x, mode, regno);
> + return x;
> +}
> +
> /* There are some RTL codes that require special attention; the generation
> functions do the raw handling. If you add to this list, modify
> special_rtx in gengenrtl.c as well. */
> diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
> index 5c78fabfb50..cd314a68a83 100644
> --- a/gcc/gengenrtl.c
> +++ b/gcc/gengenrtl.c
> @@ -231,8 +231,7 @@ genmacro (int idx)
> puts (")");
> }
>
> -/* Generate the code for the function to generate RTL whose
> - format is FORMAT. */
> +/* Generate the code for functions to generate RTL whose format is FORMAT. */
>
> static void
> gendef (const char *format)
> @@ -240,22 +239,18 @@ gendef (const char *format)
> const char *p;
> int i, j;
>
> - /* Start by writing the definition of the function name and the types
> + /* Write the definition of the init function name and the types
> of the arguments. */
>
> - printf ("static inline rtx\ngen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
> + puts ("static inline rtx");
> + printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format);
> for (p = format, i = 0; *p != 0; p++)
> if (*p != '0')
> printf (",\n\t%sarg%d", type_from_format (*p), i++);
> + puts (")");
>
> - puts (" MEM_STAT_DECL)");
> -
> - /* Now write out the body of the function itself, which allocates
> - the memory and initializes it. */
> + /* Now write out the body of the init function itself. */
> puts ("{");
> - puts (" rtx rt;");
> - puts (" rt = rtx_alloc (code PASS_MEM_STAT);\n");
> -
> puts (" PUT_MODE_RAW (rt, mode);");
>
> for (p = format, i = j = 0; *p ; ++p, ++i)
> @@ -266,16 +261,55 @@ gendef (const char *format)
> else
> printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
>
> - puts ("\n return rt;\n}\n");
> + puts (" return rt;\n}\n");
> +
> + /* Write the definition of the gen function name and the types
> + of the arguments. */
> +
> + puts ("static inline rtx");
> + printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
> + for (p = format, i = 0; *p != 0; p++)
> + if (*p != '0')
> + printf (",\n\t%sarg%d", type_from_format (*p), i++);
> + puts (" MEM_STAT_DECL)");
> +
> + /* Now write out the body of the function itself, which allocates
> + the memory and initializes it. */
> + puts ("{");
> + puts (" rtx rt;\n");
> +
> + puts (" rt = rtx_alloc (code PASS_MEM_STAT);");
> + printf (" init_rtx_fmt_%s (rt, mode", format);
> + for (p = format, i = 0; *p != 0; p++)
> + if (*p != '0')
> + printf (", arg%d", i++);
> + puts (");\n");
> +
> + puts (" return rt;\n}\n");
> +
> + /* Write the definition of gen macro. */
> +
> printf ("#define gen_rtx_fmt_%s(c, m", format);
> for (p = format, i = 0; *p != 0; p++)
> if (*p != '0')
> - printf (", p%i",i++);
> - printf (")\\\n gen_rtx_fmt_%s_stat (c, m", format);
> + printf (", arg%d", i++);
> + printf (") \\\n gen_rtx_fmt_%s_stat ((c), (m)", format);
> for (p = format, i = 0; *p != 0; p++)
> if (*p != '0')
> - printf (", p%i",i++);
> + printf (", (arg%d)", i++);
> printf (" MEM_STAT_INFO)\n\n");
> +
> + /* Write the definition of alloca macro. */
> +
> + printf ("#define alloca_rtx_fmt_%s(c, m", format);
> + for (p = format, i = 0; *p != 0; p++)
> + if (*p != '0')
> + printf (", arg%d", i++);
> + printf (") \\\n init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format);
> + for (p = format, i = 0; *p != 0; p++)
> + if (*p != '0')
> + printf (", (arg%d)", i++);
> + printf (")\n\n");
> }
>
> /* Generate the documentation header for files we write. */
> diff --git a/gcc/rtl.c b/gcc/rtl.c
> index d7b8e9877c3..0be52d38d93 100644
> --- a/gcc/rtl.c
> +++ b/gcc/rtl.c
> @@ -219,12 +219,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
> rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
> PASS_MEM_STAT);
>
> - /* We want to clear everything up to the FLD array. Normally, this
> - is one int, but we don't want to assume that and it isn't very
> - portable anyway; this is. */
> -
> - memset (rt, 0, RTX_HDR_SIZE);
> - PUT_CODE (rt, code);
> + rtx_init (rt, code);
>
> if (GATHER_STATISTICS)
> {
> diff --git a/gcc/rtl.h b/gcc/rtl.h
> index efb9b3ce40d..cf1547196f2 100644
> --- a/gcc/rtl.h
> +++ b/gcc/rtl.h
> @@ -2933,6 +2933,15 @@ extern HOST_WIDE_INT get_stack_check_protect (void);
>
> /* In rtl.c */
> extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
> +inline rtx
> +rtx_init (rtx rt, RTX_CODE code)
> +{
> + memset (rt, 0, RTX_HDR_SIZE);
> + PUT_CODE (rt, code);
> + return rt;
> +}
> +#define rtx_alloca(code) \
> + rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
> extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
> #define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
> #define const_wide_int_alloc(NWORDS) \
> @@ -3797,7 +3806,10 @@ gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
> extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
> extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
> extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
> +extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
> extern rtx gen_raw_REG (machine_mode, unsigned int);
> +#define alloca_raw_REG(mode, regno) \
> + init_raw_REG (rtx_alloca (REG), (mode), (regno))
> extern rtx gen_rtx_REG (machine_mode, unsigned int);
> extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
> extern rtx gen_rtx_MEM (machine_mode, rtx);
> --
> 2.21.0
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
2019-09-06 11:09 ` Richard Biener
@ 2019-09-06 12:40 ` Richard Sandiford
2019-09-30 15:00 ` Ilya Leoshkevich
1 sibling, 1 reply; 23+ messages in thread
From: Richard Sandiford @ 2019-09-06 12:40 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: gcc-patches, richard.guenther, segher, joseph, krebbel, rdapp
Ilya Leoshkevich <iii@linux.ibm.com> writes:
> One of the next patches in series needs to frequently pass short-lived
> fake rtxes to the back-end in order to test its capabilities. In order
> to reduce the load on GC, it is beneficial to allocate these rtxes on
> stack.
>
> Provide the macro counterparts of gen_* functions required by the next
> patch in series.
>
> gcc/ChangeLog:
>
> 2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com>
>
> PR target/77918
> * emit-rtl.c (gen_raw_REG): Use init_raw_REG.
> (init_raw_REG): New function.
> * gengenrtl.c (gendef): Emit init_* functions and alloca_*
> macros.
> * rtl.c (rtx_alloc_stat_v): Use rtx_init.
> * rtl.h (rtx_init): New function.
> (rtx_alloca): New function.
> (init_raw_REG): New function.
> (alloca_raw_REG): New macro.
> ---
> gcc/emit-rtl.c | 15 +++++++++---
> gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
> gcc/rtl.c | 7 +-----
> gcc/rtl.h | 12 ++++++++++
> 4 files changed, 74 insertions(+), 24 deletions(-)
>
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index a667cdab94e..ecfa3735bba 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
> set_regno_raw (x, regno, nregs);
> }
>
> -/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
> +/* Initialize a REG rtx. Make sure ORIGINAL_REGNO is set properly, and
> don't attempt to share with the various global pieces of rtl (such as
> frame_pointer_rtx). */
>
> rtx
> -gen_raw_REG (machine_mode mode, unsigned int regno)
> +init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
> {
> - rtx x = rtx_alloc (REG MEM_STAT_INFO);
> set_mode_and_regno (x, mode, regno);
> REG_ATTRS (x) = NULL;
> ORIGINAL_REGNO (x) = regno;
> return x;
> }
>
> +/* Generate a new REG rtx. */
> +
> +rtx
> +gen_raw_REG (machine_mode mode, unsigned int regno)
> +{
> + rtx x = rtx_alloc (REG MEM_STAT_INFO);
> + init_raw_REG (x, mode, regno);
> + return x;
> +}
> +
I think we should keep the gen_raw_REG comment the same (including
the "Make sure..." bit). The point is to contrast gen_raw_REG with
gen_rtx_REG, which does various bits of sharing.
Maybe the comment above init_raw_REG can instead be just:
/* Initialize a fresh REG rtx with mode MODE and register REGNO. */
> [...]
> @@ -266,16 +261,55 @@ gendef (const char *format)
> else
> printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
>
> - puts ("\n return rt;\n}\n");
> + puts (" return rt;\n}\n");
> +
> + /* Write the definition of the gen function name and the types
> + of the arguments. */
> +
> + puts ("static inline rtx");
> + printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
> + for (p = format, i = 0; *p != 0; p++)
> + if (*p != '0')
> + printf (",\n\t%sarg%d", type_from_format (*p), i++);
> + puts (" MEM_STAT_DECL)");
> +
> + /* Now write out the body of the function itself, which allocates
> + the memory and initializes it. */
> + puts ("{");
> + puts (" rtx rt;\n");
> +
> + puts (" rt = rtx_alloc (code PASS_MEM_STAT);");
> + printf (" init_rtx_fmt_%s (rt, mode", format);
> + for (p = format, i = 0; *p != 0; p++)
> + if (*p != '0')
> + printf (", arg%d", i++);
> + puts (");\n");
> +
> + puts (" return rt;\n}\n");
Might as well make it:
printf (" return init_rtx_fmt_%s (rt, mode", format);
and drop the separate return, for consistency with the new
alloca code.
OK with those changes, thanks.
Richard
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 3/9] Introduce can_vector_compare_p function
2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
@ 2019-09-06 12:58 ` Richard Sandiford
0 siblings, 0 replies; 23+ messages in thread
From: Richard Sandiford @ 2019-09-06 12:58 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: gcc-patches, richard.guenther, segher, joseph, krebbel, rdapp
Ilya Leoshkevich <iii@linux.ibm.com> writes:
> @@ -329,6 +332,34 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
> return false;
> }
>
> +/* Return TRUE iff vcond_optab/vcondu_optab support the given tree
> + comparison. */
Nit: better to use "true" rather than "TRUE" in modern comments;
TRUE is a hold-over from C90 days.
> +
> +static bool
> +vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
> +{
> + enum rtx_code rcode = get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type));
> + if (rcode == LAST_AND_UNUSED_RTX_CODE)
> + /* This may happen, for example, if code == SSA_NAME, in which case we
> + cannot be certain whether a vector insn is available. */
> + return false;
IMO expand_vec_cond_expr_p should exit early for SSA names before
calling this function (but after checking get_vcond_mask_icode).
Asserting for a comparison seems reasonable here.
> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index cdd07f3e53f..479789570a9 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -3819,6 +3819,30 @@ can_compare_p (enum rtx_code code, machine_mode mode,
> return 0;
> }
>
> +/* Return whether back-end can emit a vector comparison insn(s) using a give> + CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
> + in order to achieve a PURPOSE. */
Maybe:
/* Return whether the backend can emit a vector comparison for code CODE,
comparing operands of mode CMP_OP_MODE and producing a result
with VALUE_MODE. */
> +
> +bool
> +can_vector_compare_p (enum rtx_code code, machine_mode value_mode,
> + machine_mode cmp_op_mode,
> + enum can_vector_compare_purpose purpose)
I think we should leave out the purpose argument until it's needed.
(Sorry if someone else said the opposite, can't remember now.)
Maybe can_vcond_compare_p would be more consistent with the other
function names in the patch.
Thanks,
Richard
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
2019-09-06 11:07 ` Richard Biener
@ 2019-09-06 15:45 ` Ilya Leoshkevich
2019-09-09 8:43 ` Richard Biener
0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-06 15:45 UTC (permalink / raw)
To: Richard Biener
Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
Joseph S. Myers, Andreas Krebbel, Robin Dapp
> Am 06.09.2019 um 13:07 schrieb Richard Biener <richard.guenther@gmail.com>:
>
> On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>>
>> Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
>> and introduces a temporary if this could happen, for example, generating
>>
>> _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
>> _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
>>
>> from GENERIC
>>
>> VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
>> { -1, -1, -1, -1 } ,
>> { 0, 0, 0, 0 } >
>>
>> This is not necessary and makes the resulting GIMPLE harder to analyze.
>> In particular, one of the next patches in series needs to get to
>> VEC_COND_EXPR's comparison code, which is not possible when a temporary
>> is introduced.
>>
>> This patch takes special care to avoid introducing trapping comparisons
>> in GIMPLE_COND. They are not allowed, because they would require 3
>> outgoing edges (then, else and EH), which is awkward to say the least.
>> Therefore, computations of such conditions should live in their own basic
>> blocks.
>
> Comments inline (thanks for the work btw)
>
>> #endif /* GCC_GIMPLE_EXPR_H */
>> diff --git a/gcc/gimple.c b/gcc/gimple.c
>> index 633ef512a19..fd14fbec15e 100644
>> --- a/gcc/gimple.c
>> +++ b/gcc/gimple.c
>> @@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
>> op = gimple_assign_rhs_code (s);
>> if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
>> div = gimple_assign_rhs2 (s);
>> + else if (op == COND_EXPR || op == VEC_COND_EXPR)
>> + op = TREE_CODE (gimple_assign_rhs1 (s));
>
> I think this is not correct since we can have
>
> int i = fp > 1. ? intval1 : intval2
>
> and thus FLOAT_TYPE_P (t) is wrong. You need to do
>
> t = TREE_TYPE (op);
>
> as well I think.
Doesn't this mean there is a problem with the existing logic too? If `s`
is
int i = fp > 1.;
then
t = gimple_expr_type (s);
would give us BOOLEAN_TYPE instead of REAL_TYPE.
Also, the new logic will probably be a bit more complicated, since I
will first have to do:
tree cond = gimple_assign_rhs1 (s);
then see if `cond` is not e.g. an SSA_NAME, but rather a tcc_comparison,
and only then
t = TREE_TYPE (TREE_OPERAND (cond, 0))
So I'd rather send a new version before merging this :-)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
2019-09-06 15:45 ` Ilya Leoshkevich
@ 2019-09-09 8:43 ` Richard Biener
0 siblings, 0 replies; 23+ messages in thread
From: Richard Biener @ 2019-09-09 8:43 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
Joseph S. Myers, Andreas Krebbel, Robin Dapp
On Fri, Sep 6, 2019 at 5:45 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> > Am 06.09.2019 um 13:07 schrieb Richard Biener <richard.guenther@gmail.com>:
> >
> > On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
> >>
> >> Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
> >> and introduces a temporary if this could happen, for example, generating
> >>
> >> _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
> >> _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
> >>
> >> from GENERIC
> >>
> >> VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
> >> { -1, -1, -1, -1 } ,
> >> { 0, 0, 0, 0 } >
> >>
> >> This is not necessary and makes the resulting GIMPLE harder to analyze.
> >> In particular, one of the next patches in series needs to get to
> >> VEC_COND_EXPR's comparison code, which is not possible when a temporary
> >> is introduced.
> >>
> >> This patch takes special care to avoid introducing trapping comparisons
> >> in GIMPLE_COND. They are not allowed, because they would require 3
> >> outgoing edges (then, else and EH), which is awkward to say the least.
> >> Therefore, computations of such conditions should live in their own basic
> >> blocks.
> >
> > Comments inline (thanks for the work btw)
> >
> >> #endif /* GCC_GIMPLE_EXPR_H */
> >> diff --git a/gcc/gimple.c b/gcc/gimple.c
> >> index 633ef512a19..fd14fbec15e 100644
> >> --- a/gcc/gimple.c
> >> +++ b/gcc/gimple.c
> >> @@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
> >> op = gimple_assign_rhs_code (s);
> >> if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
> >> div = gimple_assign_rhs2 (s);
> >> + else if (op == COND_EXPR || op == VEC_COND_EXPR)
> >> + op = TREE_CODE (gimple_assign_rhs1 (s));
> >
> > I think this is not correct since we can have
> >
> > int i = fp > 1. ? intval1 : intval2
> >
> > and thus FLOAT_TYPE_P (t) is wrong. You need to do
> >
> > t = TREE_TYPE (op);
> >
> > as well I think.
>
> Doesn't this mean there is a problem with the existing logic too? If `s`
> is
>
> int i = fp > 1.;
>
> then
>
> t = gimple_expr_type (s);
>
> would give us BOOLEAN_TYPE instead of REAL_TYPE.
Yeah, that looks broken as well.
>
> Also, the new logic will probably be a bit more complicated, since I
> will first have to do:
>
> tree cond = gimple_assign_rhs1 (s);
>
> then see if `cond` is not e.g. an SSA_NAME, but rather a tcc_comparison,
> and only then
>
> t = TREE_TYPE (TREE_OPERAND (cond, 0))
>
> So I'd rather send a new version before merging this :-)
Fine with me ;)
Richard.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
2019-09-06 10:34 ` Segher Boessenkool
@ 2019-09-30 13:36 ` Ilya Leoshkevich
2019-10-01 0:24 ` Segher Boessenkool
0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-30 13:36 UTC (permalink / raw)
To: Segher Boessenkool
Cc: GCC Patches, richard.guenther, richard.sandiford, joseph, krebbel, rdapp
> Am 06.09.2019 um 12:34 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
>
> Hi Ilya,
>
> On Thu, Sep 05, 2019 at 01:10:14PM +0200, Ilya Leoshkevich wrote:
>> z13 supports only non-signaling vector comparisons. This means we
>> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13. Notify
>> middle-end about this using more restrictive operator predicate in
>> vcond<V_HW:mode><V_HW2:mode>.
>
>> +(define_predicate "vcond_comparison_operator"
>> + (match_operand 0 "comparison_operator")
>> +{
>> + if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
>> + && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
>> + return true;
>> + switch (GET_CODE (op))
>> + {
>> + case LE:
>> + case LT:
>> + case GE:
>> + case GT:
>> + case LTGT:
>> + /* Signaling vector comparisons are supported only on z14+. */
>> + return TARGET_Z14;
>> + default:
>> + return true;
>> + }
>> +})
>
> Should you handle -fsignaling-nans here as well?
Do you mean disabling vectorisation of LE/LT/GE/GT/LTGT when
-fsignaling-nans is in effect? This makes sense to me. I could do that
here, but wouldn't common code (e.g. expand_vec_cond_expr_p) be a better
place?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode>
2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
@ 2019-09-30 14:41 ` Andreas Krebbel
0 siblings, 0 replies; 23+ messages in thread
From: Andreas Krebbel @ 2019-09-30 14:41 UTC (permalink / raw)
To: Ilya Leoshkevich; +Cc: gcc-patches
On 05.09.19 13:10, Ilya Leoshkevich wrote:
> vec_unordered<mode> is vec_ordered<mode> plus a negation at the end.
> Reuse vec_unordered<mode> logic.
>
> gcc/ChangeLog:
>
> 2019-08-13 Ilya Leoshkevich <iii@linux.ibm.com>
>
> PR target/77918
> * config/s390/vector.md (vec_unordered<mode>): Call
> gen_vec_ordered<mode>.
Ok. Thanks!
Andreas
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders
2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
@ 2019-09-30 14:50 ` Andreas Krebbel
0 siblings, 0 replies; 23+ messages in thread
From: Andreas Krebbel @ 2019-09-30 14:50 UTC (permalink / raw)
To: Ilya Leoshkevich; +Cc: gcc-patches
On 05.09.19 13:10, Ilya Leoshkevich wrote:
> s390.md uses a lot of near-identical expanders that perform dispatching
> to other expanders based on operand types. Since the following patch
> would require even more of these, avoid copy-pasting the code by
> generating these expanders using an iterator.
>
> gcc/ChangeLog:
>
> 2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
>
> PR target/77918
> * config/s390/s390.c (s390_expand_vec_compare): Use
> gen_vec_cmpordered and gen_vec_cmpunordered.
> * config/s390/vector.md (vec_cmpuneq, vec_cmpltgt, vec_ordered,
> vec_unordered): Delete.
> (vec_ordered<mode>): Rename to vec_cmpordered<mode>.
> (vec_unordered<mode>): Rename to vec_cmpunordered<mode>.
> (vec_cmp<code>): Generic dispatcher.
VEC_CODE_WITH_COMPLEX_EXPAND is pretty long and doesn't mention that it is about compare operators.
Perhaps VEC_CMP_EXPAND or something like this? Btw. could you please mention the new iterator in the
changelog.
Ok.
Andreas
> ---
> gcc/config/s390/s390.c | 4 +--
> gcc/config/s390/vector.md | 67 +++++++--------------------------------
> 2 files changed, 13 insertions(+), 58 deletions(-)
>
> diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
> index 24784266848..f36e12affd2 100644
> --- a/gcc/config/s390/s390.c
> +++ b/gcc/config/s390/s390.c
> @@ -6523,10 +6523,10 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
> emit_insn (gen_vec_cmpltgt (target, cmp_op1, cmp_op2));
> return;
> case ORDERED:
> - emit_insn (gen_vec_ordered (target, cmp_op1, cmp_op2));
> + emit_insn (gen_vec_cmpordered (target, cmp_op1, cmp_op2));
> return;
> case UNORDERED:
> - emit_insn (gen_vec_unordered (target, cmp_op1, cmp_op2));
> + emit_insn (gen_vec_cmpunordered (target, cmp_op1, cmp_op2));
> return;
> default: break;
> }
> diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
> index 1b66b8be61f..a093ae5c565 100644
> --- a/gcc/config/s390/vector.md
> +++ b/gcc/config/s390/vector.md
> @@ -1507,22 +1507,6 @@
> operands[3] = gen_reg_rtx (<tointvec>mode);
> })
>
> -(define_expand "vec_cmpuneq"
> - [(match_operand 0 "register_operand" "")
> - (match_operand 1 "register_operand" "")
> - (match_operand 2 "register_operand" "")]
> - "TARGET_VX"
> -{
> - if (GET_MODE (operands[1]) == V4SFmode)
> - emit_insn (gen_vec_cmpuneqv4sf (operands[0], operands[1], operands[2]));
> - else if (GET_MODE (operands[1]) == V2DFmode)
> - emit_insn (gen_vec_cmpuneqv2df (operands[0], operands[1], operands[2]));
> - else
> - gcc_unreachable ();
> -
> - DONE;
> -})
> -
> ; LTGT a <> b -> a > b | b > a
> (define_expand "vec_cmpltgt<mode>"
> [(set (match_operand:<tointvec> 0 "register_operand" "=v")
> @@ -1535,24 +1519,8 @@
> operands[3] = gen_reg_rtx (<tointvec>mode);
> })
>
> -(define_expand "vec_cmpltgt"
> - [(match_operand 0 "register_operand" "")
> - (match_operand 1 "register_operand" "")
> - (match_operand 2 "register_operand" "")]
> - "TARGET_VX"
> -{
> - if (GET_MODE (operands[1]) == V4SFmode)
> - emit_insn (gen_vec_cmpltgtv4sf (operands[0], operands[1], operands[2]));
> - else if (GET_MODE (operands[1]) == V2DFmode)
> - emit_insn (gen_vec_cmpltgtv2df (operands[0], operands[1], operands[2]));
> - else
> - gcc_unreachable ();
> -
> - DONE;
> -})
> -
> ; ORDERED (a, b): a >= b | b > a
> -(define_expand "vec_ordered<mode>"
> +(define_expand "vec_cmpordered<mode>"
> [(set (match_operand:<tointvec> 0 "register_operand" "=v")
> (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
> (match_operand:VFT 2 "register_operand" "v")))
> @@ -1563,45 +1531,32 @@
> operands[3] = gen_reg_rtx (<tointvec>mode);
> })
>
> -(define_expand "vec_ordered"
> - [(match_operand 0 "register_operand" "")
> - (match_operand 1 "register_operand" "")
> - (match_operand 2 "register_operand" "")]
> - "TARGET_VX"
> -{
> - if (GET_MODE (operands[1]) == V4SFmode)
> - emit_insn (gen_vec_orderedv4sf (operands[0], operands[1], operands[2]));
> - else if (GET_MODE (operands[1]) == V2DFmode)
> - emit_insn (gen_vec_orderedv2df (operands[0], operands[1], operands[2]));
> - else
> - gcc_unreachable ();
> -
> - DONE;
> -})
> -
> ; UNORDERED (a, b): !ORDERED (a, b)
> -(define_expand "vec_unordered<mode>"
> +(define_expand "vec_cmpunordered<mode>"
> [(match_operand:<tointvec> 0 "register_operand" "=v")
> (match_operand:VFT 1 "register_operand" "v")
> (match_operand:VFT 2 "register_operand" "v")]
> "TARGET_VX"
> {
> - emit_insn (gen_vec_ordered<mode> (operands[0], operands[1], operands[2]));
> + emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
> emit_insn (gen_rtx_SET (operands[0],
> gen_rtx_NOT (<tointvec>mode, operands[0])));
> DONE;
> })
>
> -(define_expand "vec_unordered"
> +(define_code_iterator VEC_CODE_WITH_COMPLEX_EXPAND
> + [uneq ltgt ordered unordered])
> +
> +(define_expand "vec_cmp<code>"
> [(match_operand 0 "register_operand" "")
> - (match_operand 1 "register_operand" "")
> - (match_operand 2 "register_operand" "")]
> + (VEC_CODE_WITH_COMPLEX_EXPAND (match_operand 1 "register_operand" "")
> + (match_operand 2 "register_operand" ""))]
> "TARGET_VX"
> {
> if (GET_MODE (operands[1]) == V4SFmode)
> - emit_insn (gen_vec_unorderedv4sf (operands[0], operands[1], operands[2]));
> + emit_insn (gen_vec_cmp<code>v4sf (operands[0], operands[1], operands[2]));
> else if (GET_MODE (operands[1]) == V2DFmode)
> - emit_insn (gen_vec_unorderedv2df (operands[0], operands[1], operands[2]));
> + emit_insn (gen_vec_cmp<code>v2df (operands[0], operands[1], operands[2]));
> else
> gcc_unreachable ();
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF
2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
@ 2019-09-30 14:51 ` Andreas Krebbel
0 siblings, 0 replies; 23+ messages in thread
From: Andreas Krebbel @ 2019-09-30 14:51 UTC (permalink / raw)
To: Ilya Leoshkevich; +Cc: gcc-patches
On 05.09.19 13:10, Ilya Leoshkevich wrote:
> Currently gcc does not emit wf{c,k}* instructions when comparing long
> double values. Middle-end actually adds them in the first place, but
> then veclower pass replaces them with floating point register pair
> operations, because the corresponding expander is missing.
>
> gcc/ChangeLog:
>
> 2019-08-09 Ilya Leoshkevich <iii@linux.ibm.com>
>
> PR target/77918
> * config/s390/vector.md (vcondv1tiv1tf): New variant of
> vcond$a$b expander.
Couldn't you just add V1TI to V_HW and V_HW2 instead?
Andreas
> ---
> gcc/config/s390/vector.md | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
> index d7a266c5605..ca5ec0dd3b0 100644
> --- a/gcc/config/s390/vector.md
> +++ b/gcc/config/s390/vector.md
> @@ -649,6 +649,21 @@
> DONE;
> })
>
> +(define_expand "vcondv1tiv1tf"
> + [(set (match_operand:V1TI 0 "register_operand" "")
> + (if_then_else:V1TI
> + (match_operator 3 "vcond_comparison_operator"
> + [(match_operand:V1TF 4 "register_operand" "")
> + (match_operand:V1TF 5 "nonmemory_operand" "")])
> + (match_operand:V1TI 1 "nonmemory_operand" "")
> + (match_operand:V1TI 2 "nonmemory_operand" "")))]
> + "TARGET_VXE"
> +{
> + s390_expand_vcond (operands[0], operands[1], operands[2],
> + GET_CODE (operands[3]), operands[4], operands[5]);
> + DONE;
> +})
> +
> (define_expand "vcondu<V_HW:mode><V_HW2:mode>"
> [(set (match_operand:V_HW 0 "register_operand" "")
> (if_then_else:V_HW
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
2019-09-06 12:40 ` Richard Sandiford
@ 2019-09-30 15:00 ` Ilya Leoshkevich
0 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-30 15:00 UTC (permalink / raw)
To: Richard Sandiford
Cc: GCC Patches, Richard Biener, segher, joseph, krebbel, rdapp
> Am 06.09.2019 um 14:40 schrieb Richard Sandiford <richard.sandiford@arm.com>:
>
> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>> One of the next patches in series needs to frequently pass short-lived
>> fake rtxes to the back-end in order to test its capabilities. In order
>> to reduce the load on GC, it is beneficial to allocate these rtxes on
>> stack.
>>
>> Provide the macro counterparts of gen_* functions required by the next
>> patch in series.
>>
>> gcc/ChangeLog:
>>
>> 2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com>
>>
>> PR target/77918
>> * emit-rtl.c (gen_raw_REG): Use init_raw_REG.
>> (init_raw_REG): New function.
>> * gengenrtl.c (gendef): Emit init_* functions and alloca_*
>> macros.
>> * rtl.c (rtx_alloc_stat_v): Use rtx_init.
>> * rtl.h (rtx_init): New function.
>> (rtx_alloca): New function.
>> (init_raw_REG): New function.
>> (alloca_raw_REG): New macro.
>> ---
>> gcc/emit-rtl.c | 15 +++++++++---
>> gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
>> gcc/rtl.c | 7 +-----
>> gcc/rtl.h | 12 ++++++++++
>> 4 files changed, 74 insertions(+), 24 deletions(-)
>>
>> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
>> index a667cdab94e..ecfa3735bba 100644
>> --- a/gcc/emit-rtl.c
>> +++ b/gcc/emit-rtl.c
>> @@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
>> set_regno_raw (x, regno, nregs);
>> }
>>
>> -/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
>> +/* Initialize a REG rtx. Make sure ORIGINAL_REGNO is set properly, and
>> don't attempt to share with the various global pieces of rtl (such as
>> frame_pointer_rtx). */
>>
>> rtx
>> -gen_raw_REG (machine_mode mode, unsigned int regno)
>> +init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
>> {
>> - rtx x = rtx_alloc (REG MEM_STAT_INFO);
>> set_mode_and_regno (x, mode, regno);
>> REG_ATTRS (x) = NULL;
>> ORIGINAL_REGNO (x) = regno;
>> return x;
>> }
>>
>> +/* Generate a new REG rtx. */
>> +
>> +rtx
>> +gen_raw_REG (machine_mode mode, unsigned int regno)
>> +{
>> + rtx x = rtx_alloc (REG MEM_STAT_INFO);
>> + init_raw_REG (x, mode, regno);
>> + return x;
>> +}
>> +
>
> I think we should keep the gen_raw_REG comment the same (including
> the "Make sure..." bit). The point is to contrast gen_raw_REG with
> gen_rtx_REG, which does various bits of sharing.
>
> Maybe the comment above init_raw_REG can instead be just:
>
> /* Initialize a fresh REG rtx with mode MODE and register REGNO. */
>
>> [...]
>> @@ -266,16 +261,55 @@ gendef (const char *format)
>> else
>> printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
>>
>> - puts ("\n return rt;\n}\n");
>> + puts (" return rt;\n}\n");
>> +
>> + /* Write the definition of the gen function name and the types
>> + of the arguments. */
>> +
>> + puts ("static inline rtx");
>> + printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
>> + for (p = format, i = 0; *p != 0; p++)
>> + if (*p != '0')
>> + printf (",\n\t%sarg%d", type_from_format (*p), i++);
>> + puts (" MEM_STAT_DECL)");
>> +
>> + /* Now write out the body of the function itself, which allocates
>> + the memory and initializes it. */
>> + puts ("{");
>> + puts (" rtx rt;\n");
>> +
>> + puts (" rt = rtx_alloc (code PASS_MEM_STAT);");
>> + printf (" init_rtx_fmt_%s (rt, mode", format);
>> + for (p = format, i = 0; *p != 0; p++)
>> + if (*p != '0')
>> + printf (", arg%d", i++);
>> + puts (");\n");
>> +
>> + puts (" return rt;\n}\n");
>
> Might as well make it:
>
> printf (" return init_rtx_fmt_%s (rt, mode", format);
>
> and drop the separate return, for consistency with the new
> alloca code.
>
> OK with those changes, thanks.
I've made the changes and committed the patch:
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=276303
Thanks for the review!
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
2019-09-30 13:36 ` Ilya Leoshkevich
@ 2019-10-01 0:24 ` Segher Boessenkool
0 siblings, 0 replies; 23+ messages in thread
From: Segher Boessenkool @ 2019-10-01 0:24 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: GCC Patches, richard.guenther, richard.sandiford, joseph, krebbel, rdapp
On Mon, Sep 30, 2019 at 03:36:41PM +0200, Ilya Leoshkevich wrote:
> > Am 06.09.2019 um 12:34 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> > Should you handle -fsignaling-nans here as well?
>
> Do you mean disabling vectorisation of LE/LT/GE/GT/LTGT when
> -fsignaling-nans is in effect? This makes sense to me.
I meant it sounds like you need to do *something* more than the generic
code does, here.
> I could do that
> here, but wouldn't common code (e.g. expand_vec_cond_expr_p) be a better
> place?
If it can be done there, all the better, sure.
Anyway, this is a separate issue, don't let me distract you :-)
Segher
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2019-10-01 0:24 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
2019-09-06 11:07 ` Richard Biener
2019-09-06 15:45 ` Ilya Leoshkevich
2019-09-09 8:43 ` Richard Biener
2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
2019-09-06 10:34 ` Segher Boessenkool
2019-09-30 13:36 ` Ilya Leoshkevich
2019-10-01 0:24 ` Segher Boessenkool
2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
2019-09-06 12:58 ` Richard Sandiford
2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
2019-09-06 11:09 ` Richard Biener
2019-09-06 12:40 ` Richard Sandiford
2019-09-30 15:00 ` Ilya Leoshkevich
2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
2019-09-30 14:51 ` Andreas Krebbel
2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
2019-09-30 14:41 ` Andreas Krebbel
2019-09-05 11:12 ` [PATCH v3 8/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
2019-09-30 14:50 ` Andreas Krebbel
2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test signaling FP comparison instructions Ilya Leoshkevich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).