* [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 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* 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
* 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 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
* [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 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 11:09 ` Richard Biener 2019-09-06 12:40 ` Richard Sandiford 2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich ` (6 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
* 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 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
* [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 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich @ 2019-09-05 11:11 ` Ilya Leoshkevich 2019-09-06 12:58 ` Richard Sandiford 2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 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
* 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
* [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 ` (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 10:34 ` Segher Boessenkool 2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich ` (4 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
* 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 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 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
* [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 ` (3 preceding siblings ...) 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-30 14:41 ` Andreas Krebbel 2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF 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 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
* 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
* [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 ` (4 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:11 ` Ilya Leoshkevich 2019-09-30 14:51 ` Andreas Krebbel 2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test 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 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
* 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
* [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 ` (5 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: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 8/9] S/390: Use 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 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 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 9/9] S/390: Test 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 8/9] S/390: Use 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 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
* [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 ` (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 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
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 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 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich 2019-09-06 12:58 ` Richard Sandiford 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 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich 2019-09-30 14:41 ` Andreas Krebbel 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:12 ` [PATCH v3 9/9] S/390: Test 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 8/9] S/390: Use 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).