From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qv1-xf29.google.com (mail-qv1-xf29.google.com [IPv6:2607:f8b0:4864:20::f29]) by sourceware.org (Postfix) with ESMTPS id 42B94385AC1E for ; Sat, 15 Jan 2022 16:40:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 42B94385AC1E Received: by mail-qv1-xf29.google.com with SMTP id bt14so7499808qvb.13 for ; Sat, 15 Jan 2022 08:40:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=+AzKvIljhg0jO1GE+l5zH7/E+HMCwFs439piOJTM968=; b=JI8kS0N94qMGPXPW14GmBHG+4qn8pf/CHOgF0XeHk3kBbKxmnbHuAuitfw/6xk1Ho6 pDxkyNU/zfKw28lSuOm4DqaXgzLjOds5OfY6F/dYDtR5BQgDTaVbGftxHwLJAJU3gRtT i2CuUPrnTjjcrhuBEbAP8RM5tq9wRxdJW3i4imJjbDJE8VDCH2iC3ffP9I4FYj6en1+B aKCQ9hPFP6wEoqmbZkeZNcR1pwAZ9z4E6H8/UnL5KKRWd236N4XVkdO8YhrMtYvlxfTK youtpMCPTvAokLZbe4jAZftMGkBfWNVwrUo8OD5m6dq8spVW6K6ii8dTiZL3SLdi/IAb brGg== X-Gm-Message-State: AOAM530bifj58LcGbKXcOu7v3xIep54WkKSz5uXW2DbA8Xc3DkK0XrHS XTHssZB/Uw6X1inQGf2PVOEJOb2vzIBjFwYOYbs= X-Google-Smtp-Source: ABdhPJwNrkxSFtY85J6T0nI/yuhEqSecRKUGNOA3/BipdOul8MJXClz6xwZJpU8BfzaCrJQFxF6Ox9FZ6f6k26x15a0= X-Received: by 2002:a05:6214:501a:: with SMTP id jo26mr12323920qvb.48.1642264825324; Sat, 15 Jan 2022 08:40:25 -0800 (PST) MIME-Version: 1.0 References: <20220114225607.GP2646553@tucnak> <20220115095608.GR2646553@tucnak> <20220115112250.GT2646553@tucnak> In-Reply-To: <20220115112250.GT2646553@tucnak> From: Uros Bizjak Date: Sat, 15 Jan 2022 17:40:13 +0100 Message-ID: Subject: Re: [PATCH] widening_mul, i386, v2: Improve spaceship expansion on x86 [PR103973] To: Jakub Jelinek Cc: Richard Biener , "gcc-patches@gcc.gnu.org" Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 15 Jan 2022 16:40:32 -0000 On Sat, Jan 15, 2022 at 12:23 PM Jakub Jelinek wrote: > > On Sat, Jan 15, 2022 at 11:42:55AM +0100, Uros Bizjak wrote: > > Yes, that would be nice. XFmode is used for long double, and not obsolete. > > Ok, that seems to work. Compared to the incremental patch I've posted, I > also had to add handling of the case where we have just > x == y ? 0 : x < y ? -1 : 1 (both for -ffast-math and non-ffast-math). > Apparently even that is worth optimizing. > Tested so far on the new testcases, will run full bootstrap/regtest tonight. > > > > Why? That seems to be a waste of time to me, unless something uses them > > > already during expansion. Because pass_expand::execute > > > runs: > > > /* We need JUMP_LABEL be set in order to redirect jumps, and hence > > > split edges which edge insertions might do. */ > > > rebuild_jump_labels (get_insns ()); > > > which resets all LABEL_NUSES to 0 (well, to: > > > if (LABEL_P (insn)) > > > LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); > > > and then recomputes them and adds JUMP_LABEL if needed: > > > JUMP_LABEL (insn) = label; > > > > I was not aware of that detail. Thanks for sharing (and I wonder if > > all other cases should be removed from the source). > > I guess it depends, for code that can only be called during the expand pass > dropping it should be just fine, for code that can be called also (or only) > later I think adding JUMP_LABEL and correct LABEL_NUSES is needed because > nothing will fix it up afterwards. > > 2022-01-15 Jakub Jelinek > > PR target/103973 > * tree-cfg.h (cond_only_block_p): Declare. > * tree-ssa-phiopt.c (cond_only_block_p): Move function to ... > * tree-cfg.c (cond_only_block_p): ... here. No longer static. > * optabs.def (spaceship_optab): New optab. > * internal-fn.def (SPACESHIP): New internal function. > * internal-fn.h (expand_SPACESHIP): Declare. > * internal-fn.c (expand_PHI): Formatting fix. > (expand_SPACESHIP): New function. > * tree-ssa-math-opts.c (optimize_spaceship): New function. > (math_opts_dom_walker::after_dom_children): Use it. > * config/i386/i386.md (spaceship3): New define_expand. > * config/i386/i386-protos.h (ix86_expand_fp_spaceship): Declare. > * config/i386/i386-expand.c (ix86_expand_fp_spaceship): New function. > * doc/md.texi (spaceship@var{m}3): Document. > > * gcc.target/i386/pr103973-1.c: New test. > * gcc.target/i386/pr103973-2.c: New test. > * gcc.target/i386/pr103973-3.c: New test. > * gcc.target/i386/pr103973-4.c: New test. > * gcc.target/i386/pr103973-5.c: New test. > * gcc.target/i386/pr103973-6.c: New test. > * gcc.target/i386/pr103973-7.c: New test. > * gcc.target/i386/pr103973-8.c: New test. > * gcc.target/i386/pr103973-9.c: New test. > * gcc.target/i386/pr103973-10.c: New test. > * gcc.target/i386/pr103973-11.c: New test. > * gcc.target/i386/pr103973-12.c: New test. > * gcc.target/i386/pr103973-13.c: New test. > * gcc.target/i386/pr103973-14.c: New test. > * gcc.target/i386/pr103973-15.c: New test. > * gcc.target/i386/pr103973-16.c: New test. > * gcc.target/i386/pr103973-17.c: New test. > * gcc.target/i386/pr103973-18.c: New test. > * gcc.target/i386/pr103973-19.c: New test. > * gcc.target/i386/pr103973-20.c: New test. > * g++.target/i386/pr103973-1.C: New test. > * g++.target/i386/pr103973-2.C: New test. > * g++.target/i386/pr103973-3.C: New test. > * g++.target/i386/pr103973-4.C: New test. > * g++.target/i386/pr103973-5.C: New test. > * g++.target/i386/pr103973-6.C: New test. > * g++.target/i386/pr103973-7.C: New test. > * g++.target/i386/pr103973-8.C: New test. > * g++.target/i386/pr103973-9.C: New test. > * g++.target/i386/pr103973-10.C: New test. > * g++.target/i386/pr103973-11.C: New test. > * g++.target/i386/pr103973-12.C: New test. > * g++.target/i386/pr103973-13.C: New test. > * g++.target/i386/pr103973-14.C: New test. > * g++.target/i386/pr103973-15.C: New test. > * g++.target/i386/pr103973-16.C: New test. > * g++.target/i386/pr103973-17.C: New test. > * g++.target/i386/pr103973-18.C: New test. > * g++.target/i386/pr103973-19.C: New test. > * g++.target/i386/pr103973-20.C: New test. OK (with a comment fix below) for the x86 part. Thanks, Uros. > --- gcc/tree-cfg.h.jj 2022-01-14 23:57:44.491718086 +0100 > +++ gcc/tree-cfg.h 2022-01-15 09:51:25.359468982 +0100 > @@ -111,6 +111,7 @@ extern basic_block gimple_switch_label_b > extern basic_block gimple_switch_default_bb (function *, gswitch *); > extern edge gimple_switch_edge (function *, gswitch *, unsigned); > extern edge gimple_switch_default_edge (function *, gswitch *); > +extern bool cond_only_block_p (basic_block); > > /* Return true if the LHS of a call should be removed. */ > > --- gcc/tree-ssa-phiopt.c.jj 2022-01-14 23:57:44.536717549 +0100 > +++ gcc/tree-ssa-phiopt.c 2022-01-15 09:51:25.361468954 +0100 > @@ -1958,31 +1958,6 @@ minmax_replacement (basic_block cond_bb, > return true; > } > > -/* Return true if the only executable statement in BB is a GIMPLE_COND. */ > - > -static bool > -cond_only_block_p (basic_block bb) > -{ > - /* BB must have no executable statements. */ > - gimple_stmt_iterator gsi = gsi_after_labels (bb); > - if (phi_nodes (bb)) > - return false; > - while (!gsi_end_p (gsi)) > - { > - gimple *stmt = gsi_stmt (gsi); > - if (is_gimple_debug (stmt)) > - ; > - else if (gimple_code (stmt) == GIMPLE_NOP > - || gimple_code (stmt) == GIMPLE_PREDICT > - || gimple_code (stmt) == GIMPLE_COND) > - ; > - else > - return false; > - gsi_next (&gsi); > - } > - return true; > -} > - > /* Attempt to optimize (x <=> y) cmp 0 and similar comparisons. > For strong ordering <=> try to match something like: > : // cond3_bb (== cond2_bb) > --- gcc/tree-cfg.c.jj 2022-01-14 23:57:44.477718253 +0100 > +++ gcc/tree-cfg.c 2022-01-15 09:51:25.363468925 +0100 > @@ -9410,6 +9410,31 @@ gimple_switch_default_edge (function *if > return gimple_switch_edge (ifun, gs, 0); > } > > +/* Return true if the only executable statement in BB is a GIMPLE_COND. */ > + > +bool > +cond_only_block_p (basic_block bb) > +{ > + /* BB must have no executable statements. */ > + gimple_stmt_iterator gsi = gsi_after_labels (bb); > + if (phi_nodes (bb)) > + return false; > + while (!gsi_end_p (gsi)) > + { > + gimple *stmt = gsi_stmt (gsi); > + if (is_gimple_debug (stmt)) > + ; > + else if (gimple_code (stmt) == GIMPLE_NOP > + || gimple_code (stmt) == GIMPLE_PREDICT > + || gimple_code (stmt) == GIMPLE_COND) > + ; > + else > + return false; > + gsi_next (&gsi); > + } > + return true; > +} > + > > /* Emit return warnings. */ > > --- gcc/optabs.def.jj 2022-01-14 23:57:44.445718634 +0100 > +++ gcc/optabs.def 2022-01-15 09:51:25.383468640 +0100 > @@ -259,6 +259,7 @@ OPTAB_D (usubv4_optab, "usubv$I$a4") > OPTAB_D (umulv4_optab, "umulv$I$a4") > OPTAB_D (negv3_optab, "negv$I$a3") > OPTAB_D (addptr3_optab, "addptr$a3") > +OPTAB_D (spaceship_optab, "spaceship$a3") > > OPTAB_D (smul_highpart_optab, "smul$a3_highpart") > OPTAB_D (umul_highpart_optab, "umul$a3_highpart") > --- gcc/internal-fn.def.jj 2022-01-14 23:57:44.433718778 +0100 > +++ gcc/internal-fn.def 2022-01-15 09:51:25.399468413 +0100 > @@ -430,6 +430,9 @@ DEF_INTERNAL_FN (NOP, ECF_CONST | ECF_LE > /* Temporary vehicle for __builtin_shufflevector. */ > DEF_INTERNAL_FN (SHUFFLEVECTOR, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) > > +/* <=> optimization. */ > +DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) > + > #undef DEF_INTERNAL_INT_FN > #undef DEF_INTERNAL_FLT_FN > #undef DEF_INTERNAL_FLT_FLOATN_FN > --- gcc/internal-fn.h.jj 2022-01-14 23:57:44.445718634 +0100 > +++ gcc/internal-fn.h 2022-01-15 09:51:25.399468413 +0100 > @@ -241,6 +241,7 @@ extern void expand_internal_call (gcall > extern void expand_internal_call (internal_fn, gcall *); > extern void expand_PHI (internal_fn, gcall *); > extern void expand_SHUFFLEVECTOR (internal_fn, gcall *); > +extern void expand_SPACESHIP (internal_fn, gcall *); > > extern bool vectorized_internal_fn_supported_p (internal_fn, tree); > > --- gcc/internal-fn.c.jj 2022-01-14 23:57:44.433718778 +0100 > +++ gcc/internal-fn.c 2022-01-15 09:51:25.400468399 +0100 > @@ -4425,5 +4425,27 @@ expand_SHUFFLEVECTOR (internal_fn, gcall > void > expand_PHI (internal_fn, gcall *) > { > - gcc_unreachable (); > + gcc_unreachable (); > +} > + > +void > +expand_SPACESHIP (internal_fn, gcall *stmt) > +{ > + tree lhs = gimple_call_lhs (stmt); > + tree rhs1 = gimple_call_arg (stmt, 0); > + tree rhs2 = gimple_call_arg (stmt, 1); > + tree type = TREE_TYPE (rhs1); > + > + rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); > + rtx op1 = expand_normal (rhs1); > + rtx op2 = expand_normal (rhs2); > + > + class expand_operand ops[3]; > + create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs))); > + create_input_operand (&ops[1], op1, TYPE_MODE (type)); > + create_input_operand (&ops[2], op2, TYPE_MODE (type)); > + insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type)); > + expand_insn (icode, 3, ops); > + if (!rtx_equal_p (target, ops[0].value)) > + emit_move_insn (target, ops[0].value); > } > --- gcc/tree-ssa-math-opts.c.jj 2022-01-14 23:57:44.492718074 +0100 > +++ gcc/tree-ssa-math-opts.c 2022-01-15 11:37:13.131069782 +0100 > @@ -4637,6 +4637,227 @@ convert_mult_to_highpart (gassign *stmt, > return true; > } > > +/* If target has spaceship3 expander, pattern recognize > + [local count: 1073741824]: > + if (a_2(D) == b_3(D)) > + goto ; [34.00%] > + else > + goto ; [66.00%] > + > + [local count: 708669601]: > + if (a_2(D) < b_3(D)) > + goto ; [1.04%] > + else > + goto ; [98.96%] > + > + [local count: 701299439]: > + if (a_2(D) > b_3(D)) > + goto ; [48.89%] > + else > + goto ; [51.11%] > + > + [local count: 342865295]: > + > + [local count: 1073741824]: > + and turn it into: > + [local count: 1073741824]: > + _1 = .SPACESHIP (a_2(D), b_3(D)); > + if (_1 == 0) > + goto ; [34.00%] > + else > + goto ; [66.00%] > + > + [local count: 708669601]: > + if (_1 == -1) > + goto ; [1.04%] > + else > + goto ; [98.96%] > + > + [local count: 701299439]: > + if (_1 == 1) > + goto ; [48.89%] > + else > + goto ; [51.11%] > + > + [local count: 342865295]: > + > + [local count: 1073741824]: > + so that the backend can emit optimal comparison and > + conditional jump sequence. */ > + > +static void > +optimize_spaceship (gimple *stmt) > +{ > + enum tree_code code = gimple_cond_code (stmt); > + if (code != EQ_EXPR && code != NE_EXPR) > + return; > + tree arg1 = gimple_cond_lhs (stmt); > + tree arg2 = gimple_cond_rhs (stmt); > + if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg1)) > + || optab_handler (spaceship_optab, > + TYPE_MODE (TREE_TYPE (arg1))) == CODE_FOR_nothing > + || operand_equal_p (arg1, arg2, 0)) > + return; > + > + basic_block bb0 = gimple_bb (stmt), bb1, bb2 = NULL; > + edge em1 = NULL, e1 = NULL, e2 = NULL; > + bb1 = EDGE_SUCC (bb0, 1)->dest; > + if (((EDGE_SUCC (bb0, 0)->flags & EDGE_TRUE_VALUE) != 0) ^ (code == EQ_EXPR)) > + bb1 = EDGE_SUCC (bb0, 0)->dest; > + > + gimple *g = last_stmt (bb1); > + if (g == NULL > + || gimple_code (g) != GIMPLE_COND > + || !single_pred_p (bb1) > + || (operand_equal_p (gimple_cond_lhs (g), arg1, 0) > + ? !operand_equal_p (gimple_cond_rhs (g), arg2, 0) > + : (!operand_equal_p (gimple_cond_lhs (g), arg2, 0) > + || !operand_equal_p (gimple_cond_rhs (g), arg1, 0))) > + || !cond_only_block_p (bb1)) > + return; > + > + enum tree_code ccode = (operand_equal_p (gimple_cond_lhs (g), arg1, 0) > + ? LT_EXPR : GT_EXPR); > + switch (gimple_cond_code (g)) > + { > + case LT_EXPR: > + case LE_EXPR: > + break; > + case GT_EXPR: > + case GE_EXPR: > + ccode = ccode == LT_EXPR ? GT_EXPR : LT_EXPR; > + break; > + default: > + return; > + } > + > + for (int i = 0; i < 2; ++i) > + { > + /* With NaNs, />= are false, so we need to look for the > + third comparison on the false edge from whatever non-equality > + comparison the second comparison is. */ > + if (HONOR_NANS (TREE_TYPE (arg1)) > + && (EDGE_SUCC (bb1, i)->flags & EDGE_TRUE_VALUE) != 0) > + continue; > + > + bb2 = EDGE_SUCC (bb1, i)->dest; > + g = last_stmt (bb2); > + if (g == NULL > + || gimple_code (g) != GIMPLE_COND > + || !single_pred_p (bb2) > + || (operand_equal_p (gimple_cond_lhs (g), arg1, 0) > + ? !operand_equal_p (gimple_cond_rhs (g), arg2, 0) > + : (!operand_equal_p (gimple_cond_lhs (g), arg2, 0) > + || !operand_equal_p (gimple_cond_rhs (g), arg1, 0))) > + || !cond_only_block_p (bb2) > + || EDGE_SUCC (bb2, 0)->dest == EDGE_SUCC (bb2, 1)->dest) > + continue; > + > + enum tree_code ccode2 > + = (operand_equal_p (gimple_cond_lhs (g), arg1, 0) ? LT_EXPR : GT_EXPR); > + switch (gimple_cond_code (g)) > + { > + case LT_EXPR: > + case LE_EXPR: > + break; > + case GT_EXPR: > + case GE_EXPR: > + ccode2 = ccode2 == LT_EXPR ? GT_EXPR : LT_EXPR; > + break; > + default: > + continue; > + } > + if (HONOR_NANS (TREE_TYPE (arg1)) && ccode == ccode2) > + continue; > + > + if ((ccode == LT_EXPR) > + ^ ((EDGE_SUCC (bb1, i)->flags & EDGE_TRUE_VALUE) != 0)) > + { > + em1 = EDGE_SUCC (bb1, 1 - i); > + e1 = EDGE_SUCC (bb2, 0); > + e2 = EDGE_SUCC (bb2, 1); > + if ((ccode2 == LT_EXPR) ^ ((e1->flags & EDGE_TRUE_VALUE) == 0)) > + std::swap (e1, e2); > + } > + else > + { > + e1 = EDGE_SUCC (bb1, 1 - i); > + em1 = EDGE_SUCC (bb2, 0); > + e2 = EDGE_SUCC (bb2, 1); > + if ((ccode2 != LT_EXPR) ^ ((em1->flags & EDGE_TRUE_VALUE) == 0)) > + std::swap (em1, e2); > + } > + break; > + } > + > + if (em1 == NULL) > + { > + if ((ccode == LT_EXPR) > + ^ ((EDGE_SUCC (bb1, 0)->flags & EDGE_TRUE_VALUE) != 0)) > + { > + em1 = EDGE_SUCC (bb1, 1); > + e1 = EDGE_SUCC (bb1, 0); > + e2 = (e1->flags & EDGE_TRUE_VALUE) ? em1 : e1; > + } > + else > + { > + em1 = EDGE_SUCC (bb1, 0); > + e1 = EDGE_SUCC (bb1, 1); > + e2 = (e1->flags & EDGE_TRUE_VALUE) ? em1 : e1; > + } > + } > + > + g = gimple_build_call_internal (IFN_SPACESHIP, 2, arg1, arg2); > + tree lhs = make_ssa_name (integer_type_node); > + gimple_call_set_lhs (g, lhs); > + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); > + gsi_insert_before (&gsi, g, GSI_SAME_STMT); > + > + gcond *cond = as_a (stmt); > + gimple_cond_set_lhs (cond, lhs); > + gimple_cond_set_rhs (cond, integer_zero_node); > + update_stmt (stmt); > + > + g = last_stmt (bb1); > + cond = as_a (g); > + gimple_cond_set_lhs (cond, lhs); > + if (em1->src == bb1 && e2 != em1) > + { > + gimple_cond_set_rhs (cond, integer_minus_one_node); > + gimple_cond_set_code (cond, (em1->flags & EDGE_TRUE_VALUE) > + ? EQ_EXPR : NE_EXPR); > + } > + else > + { > + gcc_assert (e1->src == bb1 && e2 != e1); > + gimple_cond_set_rhs (cond, integer_one_node); > + gimple_cond_set_code (cond, (e1->flags & EDGE_TRUE_VALUE) > + ? EQ_EXPR : NE_EXPR); > + } > + update_stmt (g); > + > + if (e2 != e1 && e2 != em1) > + { > + g = last_stmt (bb2); > + cond = as_a (g); > + gimple_cond_set_lhs (cond, lhs); > + if (em1->src == bb2) > + gimple_cond_set_rhs (cond, integer_minus_one_node); > + else > + { > + gcc_assert (e1->src == bb2); > + gimple_cond_set_rhs (cond, integer_one_node); > + } > + gimple_cond_set_code (cond, > + (e2->flags & EDGE_TRUE_VALUE) ? NE_EXPR : EQ_EXPR); > + update_stmt (g); > + } > + > + wide_int wm1 = wi::minus_one (TYPE_PRECISION (integer_type_node)); > + wide_int w2 = wi::two (TYPE_PRECISION (integer_type_node)); > + set_range_info (lhs, VR_RANGE, wm1, w2); > +} > + > > /* Find integer multiplications where the operands are extended from > smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR > @@ -4798,6 +5019,8 @@ math_opts_dom_walker::after_dom_children > break; > } > } > + else if (gimple_code (stmt) == GIMPLE_COND) > + optimize_spaceship (stmt); > gsi_next (&gsi); > } > if (fma_state.m_deferring_p > --- gcc/config/i386/i386.md.jj 2022-01-14 23:57:59.047544505 +0100 > +++ gcc/config/i386/i386.md 2022-01-15 12:13:28.116073760 +0100 > @@ -23886,6 +23886,28 @@ (define_insn "hreset" > [(set_attr "type" "other") > (set_attr "length" "4")]) > > +;; Spaceship optimization > +(define_expand "spaceship3" > + [(match_operand:SI 0 "register_operand") > + (match_operand:MODEF 1 "cmp_fp_expander_operand") > + (match_operand:MODEF 2 "cmp_fp_expander_operand")] > + "(TARGET_80387 || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)) > + && (TARGET_CMOVE || (TARGET_SAHF && TARGET_USE_SAHF))" > +{ > + ix86_expand_fp_spaceship (operands[0], operands[1], operands[2]); > + DONE; > +}) > + > +(define_expand "spaceshipxf3" > + [(match_operand:SI 0 "register_operand") > + (match_operand:XF 1 "nonmemory_operand") > + (match_operand:XF 2 "nonmemory_operand")] > + "TARGET_80387 && (TARGET_CMOVE || (TARGET_SAHF && TARGET_USE_SAHF))" > +{ > + ix86_expand_fp_spaceship (operands[0], operands[1], operands[2]); > + DONE; > +}) > + > (include "mmx.md") > (include "sse.md") > (include "sync.md") > --- gcc/config/i386/i386-protos.h.jj 2022-01-14 23:57:44.398719195 +0100 > +++ gcc/config/i386/i386-protos.h 2022-01-15 09:51:25.410468256 +0100 > @@ -150,6 +150,7 @@ extern bool ix86_expand_int_vec_cmp (rtx > extern bool ix86_expand_fp_vec_cmp (rtx[]); > extern void ix86_expand_sse_movcc (rtx, rtx, rtx, rtx); > extern void ix86_expand_sse_unpack (rtx, rtx, bool, bool); > +extern void ix86_expand_fp_spaceship (rtx, rtx, rtx); > extern bool ix86_expand_int_addcc (rtx[]); > extern rtx_insn *ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool); > extern bool ix86_call_use_plt_p (rtx); > --- gcc/config/i386/i386-expand.c.jj 2022-01-14 23:57:44.379719421 +0100 > +++ gcc/config/i386/i386-expand.c 2022-01-15 10:38:26.924333651 +0100 > @@ -2879,6 +2879,54 @@ ix86_expand_setcc (rtx dest, enum rtx_co > emit_insn (gen_rtx_SET (dest, ret)); > } > > +/* Expand floating point op0 <=> op1 if NaNs are honored. */ Probably independent of NaN, the expansion also works for -ffast-math. > + > +void > +ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1) > +{ > + gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH); > + rtx gt = ix86_expand_fp_compare (GT, op0, op1); > + rtx l0 = gen_label_rtx (); > + rtx l1 = gen_label_rtx (); > + rtx l2 = TARGET_IEEE_FP ? gen_label_rtx () : NULL_RTX; > + rtx lend = gen_label_rtx (); > + rtx tmp; > + rtx_insn *jmp; > + if (l2) > + { > + rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode, > + gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx); > + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un, > + gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx); > + jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); > + add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ()); > + } > + rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode, > + gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx); > + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq, > + gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx); > + jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); > + add_reg_br_prob_note (jmp, profile_probability::unlikely ()); > + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt, > + gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx); > + jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); > + add_reg_br_prob_note (jmp, profile_probability::even ()); > + emit_move_insn (dest, constm1_rtx); > + emit_jump (lend); > + emit_label (l0); > + emit_move_insn (dest, const0_rtx); > + emit_jump (lend); > + emit_label (l1); > + emit_move_insn (dest, const1_rtx); > + emit_jump (lend); > + if (l2) > + { > + emit_label (l2); > + emit_move_insn (dest, const2_rtx); > + } > + emit_label (lend); > +} > + > /* Expand comparison setting or clearing carry flag. Return true when > successful and set pop for the operation. */ > static bool > --- gcc/doc/md.texi.jj 2022-01-14 23:57:44.419718944 +0100 > +++ gcc/doc/md.texi 2022-01-15 09:51:25.429467985 +0100 > @@ -8055,6 +8055,15 @@ inclusive and operand 1 exclusive. > If this pattern is not defined, a call to the library function > @code{__clear_cache} is used. > > +@cindex @code{spaceship@var{m}3} instruction pattern > +@item @samp{spaceship@var{m}3} > +Initialize output operand 0 with mode of integer type to -1, 0, 1 or 2 > +if operand 1 with mode @var{m} compares less than operand 2, equal to > +operand 2, greater than operand 2 or is unordered with operand 2. > +@var{m} should be a scalar floating point mode. > + > +This pattern is not allowed to @code{FAIL}. > + > @end table > > @end ifset > --- gcc/testsuite/gcc.target/i386/pr103973-1.c.jj 2022-01-15 09:51:25.430467971 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-1.c 2022-01-15 09:51:25.430467971 +0100 > @@ -0,0 +1,98 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomisd" 4 { target { ! ia32 } } } } */ > + > +__attribute__((noipa)) int m1 (void) { return -1; } > +__attribute__((noipa)) int p0 (void) { return 0; } > +__attribute__((noipa)) int p1 (void) { return 1; } > +__attribute__((noipa)) int p2 (void) { return 2; } > + > +__attribute__((noipa)) int > +foo (double a, double b) > +{ > + if (a == b) > + return 0; > + if (a < b) > + return -1; > + if (a > b) > + return 1; > + return 2; > +} > + > +__attribute__((noipa)) int > +bar (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (a < b) > + return m1 (); > + if (a > b) > + return p1 (); > + return p2 (); > +} > + > +__attribute__((noipa)) int > +baz (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (b < a) > + return p1 (); > + if (a < b) > + return m1 (); > + return p2 (); > +} > + > +__attribute__((noipa)) int > +qux (double a) > +{ > + if (a != 0.0f) > + { > + if (a <= 0.0f) > + return -1; > + if (a >= 0.0f) > + return 1; > + return 2; > + } > + return 0; > +} > + > +int > +main () > +{ > + double m5 = -5.0f; > + double p5 = 5.0f; > + volatile double p0 = 0.0f; > + double nan = p0 / p0; > + if (foo (p5, p5) != 0 || foo (m5, m5) != 0) > + __builtin_abort (); > + if (foo (m5, p5) != -1 || foo (p5, m5) != 1) > + __builtin_abort (); > + if (foo (m5, nan) != 2 || foo (nan, p5) != 2) > + __builtin_abort (); > + if (foo (nan, nan) != 2) > + __builtin_abort (); > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (bar (m5, nan) != 2 || bar (nan, p5) != 2) > + __builtin_abort (); > + if (bar (nan, nan) != 2) > + __builtin_abort (); > + if (baz (p5, p5) != 0 || baz (m5, m5) != 0) > + __builtin_abort (); > + if (baz (m5, p5) != -1 || baz (p5, m5) != 1) > + __builtin_abort (); > + if (baz (m5, nan) != 2 || baz (nan, p5) != 2) > + __builtin_abort (); > + if (baz (nan, nan) != 2) > + __builtin_abort (); > + if (qux (p0) != 0 || qux (nan) != 2) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/gcc.target/i386/pr103973-2.c.jj 2022-01-15 09:51:25.430467971 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-2.c 2022-01-15 12:00:15.864355970 +0100 > @@ -0,0 +1,7 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#include "pr103973-1.c" > --- gcc/testsuite/gcc.target/i386/pr103973-3.c.jj 2022-01-15 09:51:25.430467971 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-3.c 2022-01-15 09:51:25.430467971 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomiss" 4 { target { ! ia32 } } } } */ > + > +#define double float > +#include "pr103973-1.c" > --- gcc/testsuite/gcc.target/i386/pr103973-4.c.jj 2022-01-15 09:51:25.430467971 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-4.c 2022-01-15 12:00:15.864355970 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double float > +#include "pr103973-1.c" > --- gcc/testsuite/gcc.target/i386/pr103973-5.c.jj 2022-01-15 11:04:02.427452420 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-5.c 2022-01-15 11:06:39.594216502 +0100 > @@ -0,0 +1,85 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -ffast-math -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomisd" 4 { target { ! ia32 } } } } */ > + > +__attribute__((noipa)) int m1 (void) { return -1; } > +__attribute__((noipa)) int p0 (void) { return 0; } > +__attribute__((noipa)) int p1 (void) { return 1; } > +__attribute__((noipa)) int p2 (void) { return 2; } > + > +__attribute__((noipa)) int > +foo (double a, double b) > +{ > + if (a == b) > + return 0; > + if (a < b) > + return -1; > + if (a > b) > + return 1; > + return 2; > +} > + > +__attribute__((noipa)) int > +bar (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (a < b) > + return m1 (); > + if (a > b) > + return p1 (); > + return p2 (); > +} > + > +__attribute__((noipa)) int > +baz (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (b < a) > + return p1 (); > + if (a < b) > + return m1 (); > + return p2 (); > +} > + > +__attribute__((noipa)) int > +qux (double a) > +{ > + if (a != 0.0f) > + { > + if (a <= 0.0f) > + return -1; > + if (a >= 0.0f) > + return 1; > + return 2; > + } > + return 0; > +} > + > +int > +main () > +{ > + double m5 = -5.0f; > + double p5 = 5.0f; > + double p0 = 0.0f; > + if (foo (p5, p5) != 0 || foo (m5, m5) != 0) > + __builtin_abort (); > + if (foo (m5, p5) != -1 || foo (p5, m5) != 1) > + __builtin_abort (); > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (baz (p5, p5) != 0 || baz (m5, m5) != 0) > + __builtin_abort (); > + if (baz (m5, p5) != -1 || baz (p5, m5) != 1) > + __builtin_abort (); > + if (qux (p0) != 0) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/gcc.target/i386/pr103973-6.c.jj 2022-01-15 11:05:24.377286081 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-6.c 2022-01-15 12:00:15.864355970 +0100 > @@ -0,0 +1,7 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#include "pr103973-5.c" > --- gcc/testsuite/gcc.target/i386/pr103973-7.c.jj 2022-01-15 11:05:28.620225748 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-7.c 2022-01-15 11:06:03.899724076 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -ffast-math -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomiss" 4 { target { ! ia32 } } } } */ > + > +#define double float > +#include "pr103973-5.c" > --- gcc/testsuite/gcc.target/i386/pr103973-8.c.jj 2022-01-15 11:05:32.273173801 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-8.c 2022-01-15 12:00:15.865355956 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double float > +#include "pr103973-5.c" > --- gcc/testsuite/gcc.target/i386/pr103973-9.c.jj 2022-01-15 11:41:11.895661977 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-9.c 2022-01-15 11:43:31.718668421 +0100 > @@ -0,0 +1,89 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomisd" 4 { target { ! ia32 } } } } */ > + > +__attribute__((noipa)) int m1 (void) { return -1; } > +__attribute__((noipa)) int p0 (void) { return 0; } > +__attribute__((noipa)) int p1 (void) { return 1; } > + > +__attribute__((noipa)) int > +foo (double a, double b) > +{ > + if (a == b) > + return 0; > + if (a < b) > + return -1; > + return 1; > +} > + > +__attribute__((noipa)) int > +bar (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (a < b) > + return m1 (); > + return p1 (); > +} > + > +__attribute__((noipa)) int > +baz (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (b < a) > + return p1 (); > + return m1 (); > +} > + > +__attribute__((noipa)) int > +qux (double a) > +{ > + if (a != 0.0f) > + { > + if (a <= 0.0f) > + return -1; > + return 1; > + } > + return 0; > +} > + > +int > +main () > +{ > + double m5 = -5.0f; > + double p5 = 5.0f; > + volatile double p0 = 0.0f; > + double nan = p0 / p0; > + if (foo (p5, p5) != 0 || foo (m5, m5) != 0) > + __builtin_abort (); > + if (foo (m5, p5) != -1 || foo (p5, m5) != 1) > + __builtin_abort (); > + if (foo (m5, nan) != 1 || foo (nan, p5) != 1) > + __builtin_abort (); > + if (foo (nan, nan) != 1) > + __builtin_abort (); > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (bar (m5, nan) != 1 || bar (nan, p5) != 1) > + __builtin_abort (); > + if (bar (nan, nan) != 1) > + __builtin_abort (); > + if (baz (p5, p5) != 0 || baz (m5, m5) != 0) > + __builtin_abort (); > + if (baz (m5, p5) != -1 || baz (p5, m5) != 1) > + __builtin_abort (); > + if (baz (m5, nan) != -1 || baz (nan, p5) != -1) > + __builtin_abort (); > + if (baz (nan, nan) != -1) > + __builtin_abort (); > + if (qux (p0) != 0 || qux (nan) != 1) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/gcc.target/i386/pr103973-10.c.jj 2022-01-15 11:44:56.503459584 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-10.c 2022-01-15 12:00:15.865355956 +0100 > @@ -0,0 +1,7 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#include "pr103973-9.c" > --- gcc/testsuite/gcc.target/i386/pr103973-11.c.jj 2022-01-15 11:44:56.504459570 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-11.c 2022-01-15 11:45:08.783284502 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomiss" 4 { target { ! ia32 } } } } */ > + > +#define double float > +#include "pr103973-9.c" > --- gcc/testsuite/gcc.target/i386/pr103973-12.c.jj 2022-01-15 11:44:56.506459542 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-12.c 2022-01-15 12:00:15.865355956 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double float > +#include "pr103973-9.c" > --- gcc/testsuite/gcc.target/i386/pr103973-13.c.jj 2022-01-15 11:44:56.507459527 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-13.c 2022-01-15 11:44:19.254990661 +0100 > @@ -0,0 +1,76 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -ffast-math -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomisd" 4 { target { ! ia32 } } } } */ > + > +__attribute__((noipa)) int m1 (void) { return -1; } > +__attribute__((noipa)) int p0 (void) { return 0; } > +__attribute__((noipa)) int p1 (void) { return 1; } > + > +__attribute__((noipa)) int > +foo (double a, double b) > +{ > + if (a == b) > + return 0; > + if (a < b) > + return -1; > + return 1; > +} > + > +__attribute__((noipa)) int > +bar (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (a < b) > + return m1 (); > + return p1 (); > +} > + > +__attribute__((noipa)) int > +baz (double a, double b) > +{ > + if (a == b) > + return p0 (); > + if (b < a) > + return p1 (); > + return m1 (); > +} > + > +__attribute__((noipa)) int > +qux (double a) > +{ > + if (a != 0.0f) > + { > + if (a <= 0.0f) > + return -1; > + return 1; > + } > + return 0; > +} > + > +int > +main () > +{ > + double m5 = -5.0f; > + double p5 = 5.0f; > + double p0 = 0.0f; > + if (foo (p5, p5) != 0 || foo (m5, m5) != 0) > + __builtin_abort (); > + if (foo (m5, p5) != -1 || foo (p5, m5) != 1) > + __builtin_abort (); > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (baz (p5, p5) != 0 || baz (m5, m5) != 0) > + __builtin_abort (); > + if (baz (m5, p5) != -1 || baz (p5, m5) != 1) > + __builtin_abort (); > + if (qux (p0) != 0) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/gcc.target/i386/pr103973-14.c.jj 2022-01-15 11:44:56.508459513 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-14.c 2022-01-15 12:00:15.865355956 +0100 > @@ -0,0 +1,7 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#include "pr103973-13.c" > --- gcc/testsuite/gcc.target/i386/pr103973-15.c.jj 2022-01-15 11:44:56.509459499 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-15.c 2022-01-15 11:45:27.532017186 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run } */ > +/* { dg-options "-O2 -ffast-math -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } */ > +/* { dg-final { scan-assembler-times "\tcomiss" 4 { target { ! ia32 } } } } */ > + > +#define double float > +#include "pr103973-13.c" > --- gcc/testsuite/gcc.target/i386/pr103973-16.c.jj 2022-01-15 11:44:56.510459485 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-16.c 2022-01-15 12:00:15.865355956 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double float > +#include "pr103973-13.c" > --- gcc/testsuite/gcc.target/i386/pr103973-17.c.jj 2022-01-15 12:01:30.713290043 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-17.c 2022-01-15 12:08:07.244642996 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run { target large_long_double } } */ > +/* { dg-options "-O2 -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double long double > +#include "pr103973-1.c" > --- gcc/testsuite/gcc.target/i386/pr103973-18.c.jj 2022-01-15 12:04:28.332760546 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-18.c 2022-01-15 12:08:13.633552013 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run { target large_long_double } } */ > +/* { dg-options "-O2 -ffast-math -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double long double > +#include "pr103973-5.c" > --- gcc/testsuite/gcc.target/i386/pr103973-19.c.jj 2022-01-15 12:04:31.235719206 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-19.c 2022-01-15 12:08:18.792478544 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run { target large_long_double } } */ > +/* { dg-options "-O2 -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double long double > +#include "pr103973-9.c" > --- gcc/testsuite/gcc.target/i386/pr103973-20.c.jj 2022-01-15 12:04:34.648670603 +0100 > +++ gcc/testsuite/gcc.target/i386/pr103973-20.c 2022-01-15 12:08:26.220372764 +0100 > @@ -0,0 +1,8 @@ > +/* PR target/103973 */ > +/* { dg-do run { target large_long_double } } */ > +/* { dg-options "-O2 -ffast-math -save-temps" } */ > +/* { dg-final { scan-assembler-not "'\tfucom" } } */ > +/* { dg-final { scan-assembler-times "\tfcom" 4 } } */ > + > +#define double long double > +#include "pr103973-13.c" > --- gcc/testsuite/g++.target/i386/pr103973-1.C.jj 2022-01-15 09:51:25.443467786 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-1.C 2022-01-15 09:51:25.443467786 +0100 > @@ -0,0 +1,71 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomisd" 2 { target { ! ia32 } } } } > + > +#include > + > +#ifndef double_type > +#define double_type double > +#endif > + > +__attribute__((noipa)) auto > +foo (double_type a, double_type b) > +{ > + return a <=> b; > +} > + > +__attribute__((noipa)) int > +bar (double_type a, double_type b) > +{ > + auto c = foo (a, b); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + if (c == std::partial_ordering::greater) > + return 1; > + return 2; > +} > + > +__attribute__((noipa)) auto > +baz (double_type a) > +{ > + return a <=> 0.0f; > +} > + > +__attribute__((noipa)) int > +qux (double_type a) > +{ > + auto c = baz (a); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + if (c == std::partial_ordering::greater) > + return 1; > + return 2; > +} > + > +int > +main () > +{ > + double_type m5 = -5.0; > + double_type p5 = 5.0; > + volatile double_type p0 = 0.0; > + double_type nan = p0 / p0; > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (bar (m5, nan) != 2 || bar (nan, p5) != 2) > + __builtin_abort (); > + if (bar (nan, nan) != 2) > + __builtin_abort (); > + if (qux (p0) != 0 || qux (nan) != 2) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/g++.target/i386/pr103973-2.C.jj 2022-01-15 09:51:25.443467786 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-2.C 2022-01-15 12:00:42.392978175 +0100 > @@ -0,0 +1,7 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#include "pr103973-1.C" > --- gcc/testsuite/g++.target/i386/pr103973-3.C.jj 2022-01-15 09:51:25.443467786 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-3.C 2022-01-15 09:51:25.443467786 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -save-temps -std=c++20" } > +// { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomiss" 2 { target { ! ia32 } } } } > + > +#define double_type float > +#include "pr103973-1.C" > --- gcc/testsuite/g++.target/i386/pr103973-4.C.jj 2022-01-15 09:51:25.443467786 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-4.C 2022-01-15 12:00:42.392978175 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type float > +#include "pr103973-1.C" > --- gcc/testsuite/g++.target/i386/pr103973-5.C.jj 2022-01-15 11:07:17.398678932 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-5.C 2022-01-15 11:07:48.314239313 +0100 > @@ -0,0 +1,66 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -ffast-math -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomisd" 2 { target { ! ia32 } } } } > + > +#include > + > +#ifndef double_type > +#define double_type double > +#endif > + > +__attribute__((noipa)) auto > +foo (double_type a, double_type b) > +{ > + return a <=> b; > +} > + > +__attribute__((noipa)) int > +bar (double_type a, double_type b) > +{ > + auto c = foo (a, b); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + if (c == std::partial_ordering::greater) > + return 1; > + return 2; > +} > + > +__attribute__((noipa)) auto > +baz (double_type a) > +{ > + return a <=> 0.0f; > +} > + > +__attribute__((noipa)) int > +qux (double_type a) > +{ > + auto c = baz (a); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + if (c == std::partial_ordering::greater) > + return 1; > + return 2; > +} > + > +int > +main () > +{ > + double_type m5 = -5.0; > + double_type p5 = 5.0; > + double_type p0 = 0.0; > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (qux (p0) != 0) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/g++.target/i386/pr103973-6.C.jj 2022-01-15 11:08:07.181971016 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-6.C 2022-01-15 12:00:42.392978175 +0100 > @@ -0,0 +1,7 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#include "pr103973-5.C" > --- gcc/testsuite/g++.target/i386/pr103973-7.C.jj 2022-01-15 11:08:10.054930163 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-7.C 2022-01-15 11:08:39.354513526 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -ffast-math -save-temps -std=c++20" } > +// { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomiss" 2 { target { ! ia32 } } } } > + > +#define double_type float > +#include "pr103973-5.C" > --- gcc/testsuite/g++.target/i386/pr103973-8.C.jj 2022-01-15 11:08:13.064887361 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-8.C 2022-01-15 12:00:42.392978175 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type float > +#include "pr103973-5.C" > --- gcc/testsuite/g++.target/i386/pr103973-9.C.jj 2022-01-15 11:46:15.455333909 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-9.C 2022-01-15 11:47:00.152696626 +0100 > @@ -0,0 +1,67 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomisd" 2 { target { ! ia32 } } } } > + > +#include > + > +#ifndef double_type > +#define double_type double > +#endif > + > +__attribute__((noipa)) auto > +foo (double_type a, double_type b) > +{ > + return a <=> b; > +} > + > +__attribute__((noipa)) int > +bar (double_type a, double_type b) > +{ > + auto c = foo (a, b); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + return 1; > +} > + > +__attribute__((noipa)) auto > +baz (double_type a) > +{ > + return a <=> 0.0f; > +} > + > +__attribute__((noipa)) int > +qux (double_type a) > +{ > + auto c = baz (a); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + return 1; > +} > + > +int > +main () > +{ > + double_type m5 = -5.0; > + double_type p5 = 5.0; > + volatile double_type p0 = 0.0; > + double_type nan = p0 / p0; > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (bar (m5, nan) != 1 || bar (nan, p5) != 1) > + __builtin_abort (); > + if (bar (nan, nan) != 1) > + __builtin_abort (); > + if (qux (p0) != 0 || qux (nan) != 1) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/g++.target/i386/pr103973-10.C.jj 2022-01-15 11:48:31.928388111 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-10.C 2022-01-15 12:00:42.393978161 +0100 > @@ -0,0 +1,7 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#include "pr103973-9.C" > --- gcc/testsuite/g++.target/i386/pr103973-11.C.jj 2022-01-15 11:48:31.929388096 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-11.C 2022-01-15 11:48:46.756176703 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -save-temps -std=c++20" } > +// { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomiss" 2 { target { ! ia32 } } } } > + > +#define double_type float > +#include "pr103973-9.C" > --- gcc/testsuite/g++.target/i386/pr103973-12.C.jj 2022-01-15 11:48:31.931388068 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-12.C 2022-01-15 12:00:42.393978161 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type float > +#include "pr103973-9.C" > --- gcc/testsuite/g++.target/i386/pr103973-13.C.jj 2022-01-15 11:48:31.932388054 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-13.C 2022-01-15 11:48:13.484651079 +0100 > @@ -0,0 +1,62 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -ffast-math -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tucomisd" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomisd" 2 { target { ! ia32 } } } } > + > +#include > + > +#ifndef double_type > +#define double_type double > +#endif > + > +__attribute__((noipa)) auto > +foo (double_type a, double_type b) > +{ > + return a <=> b; > +} > + > +__attribute__((noipa)) int > +bar (double_type a, double_type b) > +{ > + auto c = foo (a, b); > + if (c == std::partial_ordering::less) > + return -1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + return 1; > +} > + > +__attribute__((noipa)) auto > +baz (double_type a) > +{ > + return a <=> 0.0f; > +} > + > +__attribute__((noipa)) int > +qux (double_type a) > +{ > + auto c = baz (a); > + if (c == std::partial_ordering::greater) > + return 1; > + if (c == std::partial_ordering::equivalent) > + return 0; > + return -1; > +} > + > +int > +main () > +{ > + double_type m5 = -5.0; > + double_type p5 = 5.0; > + double_type p0 = 0.0; > + if (bar (p5, p5) != 0 || bar (m5, m5) != 0) > + __builtin_abort (); > + if (bar (m5, p5) != -1 || bar (p5, m5) != 1) > + __builtin_abort (); > + if (qux (p0) != 0) > + __builtin_abort (); > + if (qux (m5) != -1 || qux (p5) != 1) > + __builtin_abort (); > + return 0; > +} > --- gcc/testsuite/g++.target/i386/pr103973-14.C.jj 2022-01-15 11:48:31.933388039 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-14.C 2022-01-15 12:00:42.393978161 +0100 > @@ -0,0 +1,7 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#include "pr103973-13.C" > --- gcc/testsuite/g++.target/i386/pr103973-15.C.jj 2022-01-15 11:48:31.934388025 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-15.C 2022-01-15 11:49:07.262884325 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run } > +// { dg-options "-O2 -ffast-math -save-temps -std=c++20" } > +// { dg-final { scan-assembler-not "'\tucomiss" { target { ! ia32 } } } } > +// { dg-final { scan-assembler-times "\tcomiss" 2 { target { ! ia32 } } } } > + > +#define double_type float > +#include "pr103973-13.C" > --- gcc/testsuite/g++.target/i386/pr103973-16.C.jj 2022-01-15 11:48:31.935388011 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-16.C 2022-01-15 12:00:42.393978161 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do compile { target ia32 } } > +// { dg-options "-O2 -ffast-math -march=i686 -mfpmath=387 -std=c++20" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type float > +#include "pr103973-13.C" > --- gcc/testsuite/g++.target/i386/pr103973-17.C.jj 2022-01-15 12:09:38.499343432 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-17.C 2022-01-15 12:08:54.276973207 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run { target large_long_double } } > +// { dg-options "-O2 -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type long double > +#include "pr103973-1.C" > --- gcc/testsuite/g++.target/i386/pr103973-18.C.jj 2022-01-15 12:09:41.472301093 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-18.C 2022-01-15 12:09:15.681668382 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run { target large_long_double } } > +// { dg-options "-O2 -ffast-math -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type long double > +#include "pr103973-5.C" > --- gcc/testsuite/g++.target/i386/pr103973-19.C.jj 2022-01-15 12:09:43.544271589 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-19.C 2022-01-15 12:09:22.726568054 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run { target large_long_double } } > +// { dg-options "-O2 -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type long double > +#include "pr103973-9.C" > --- gcc/testsuite/g++.target/i386/pr103973-20.C.jj 2022-01-15 12:09:46.301232323 +0100 > +++ gcc/testsuite/g++.target/i386/pr103973-20.C 2022-01-15 12:09:33.491414751 +0100 > @@ -0,0 +1,8 @@ > +// PR target/103973 > +// { dg-do run { target large_long_double } } > +// { dg-options "-O2 -ffast-math -std=c++20 -save-temps" } > +// { dg-final { scan-assembler-not "'\tfucom" } } > +// { dg-final { scan-assembler-times "\tfcom" 2 } } > + > +#define double_type long double > +#include "pr103973-13.C" > > > Jakub >