From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 624ED399C03E for ; Fri, 9 Apr 2021 16:55:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 624ED399C03E Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 139GbGqv017802; Fri, 9 Apr 2021 12:55:09 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 37ts0g3bp5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 09 Apr 2021 12:55:09 -0400 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 139GbNQ9018157; Fri, 9 Apr 2021 12:55:08 -0400 Received: from ppma03wdc.us.ibm.com (ba.79.3fa9.ip4.static.sl-reverse.com [169.63.121.186]) by mx0a-001b2d01.pphosted.com with ESMTP id 37ts0g3bns-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 09 Apr 2021 12:55:08 -0400 Received: from pps.filterd (ppma03wdc.us.ibm.com [127.0.0.1]) by ppma03wdc.us.ibm.com (8.16.0.43/8.16.0.43) with SMTP id 139GrfW8006611; Fri, 9 Apr 2021 16:55:07 GMT Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by ppma03wdc.us.ibm.com with ESMTP id 37tj6kk0f8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 09 Apr 2021 16:55:07 +0000 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 139Gt5hS14352796 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 9 Apr 2021 16:55:05 GMT Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CBE31BE05D; Fri, 9 Apr 2021 16:55:05 +0000 (GMT) Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4BC11BE056; Fri, 9 Apr 2021 16:55:05 +0000 (GMT) Received: from lexx (unknown [9.163.22.48]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP; Fri, 9 Apr 2021 16:55:05 +0000 (GMT) Message-ID: Subject: Re: [PATCH 2/2] Add IEEE 128-bit min/max support on PowerPC From: will schmidt To: Michael Meissner , gcc-patches@gcc.gnu.org, Segher Boessenkool , David Edelsohn , Bill Schmidt , Peter Bergner Date: Fri, 09 Apr 2021 11:54:59 -0500 In-Reply-To: <20210409144358.GB14459@ibm-toto.the-meissners.org> References: <20210409143800.GA12782@ibm-toto.the-meissners.org> <20210409144358.GB14459@ibm-toto.the-meissners.org> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.28.5 (3.28.5-10.el7) Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 X-Proofpoint-GUID: eD0eCs4ZQRUo7aaqIq7v1hNHZEjUpBEf X-Proofpoint-ORIG-GUID: q8az0c2pMXBN3Uw2tf6Bk1ViIO-cbvoO X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-04-09_07:2021-04-09, 2021-04-09 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 bulkscore=0 spamscore=0 mlxscore=0 priorityscore=1501 impostorscore=0 malwarescore=0 adultscore=0 clxscore=1015 mlxlogscore=999 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104060000 definitions=main-2104090114 X-Spam-Status: No, score=-12.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Fri, 09 Apr 2021 16:55:13 -0000 On Fri, 2021-04-09 at 10:43 -0400, Michael Meissner wrote: > Add IEEE 128-bit fp conditional move on PowerPC. > > This patch has been posted various times in the past. My memory is the last > time I changed the patch, I addressed the concerns posted at that time. Since > then the patch seems to have gone into a limbo state. This is covered in the patch series title page, Don't distract from the patch itself here. > > This patch adds the support for power10 IEEE 128-bit floating point conditional > move and for automatically generating min/max. Unlike the previous patch, I > decided to keep two separate patterns for fpmask before splitting (one pattern > for normal compares, and the other pattern for inverted compares). I can go > back to a single pattern with a new predicate that allows either comparison. ok. > > Compared to the original code, these patterns do simplify the fpmask insns to > having one alternative instead of two. In the original code, the first > alternative tried to use the result as a temporary register. But that doesn't > work if you are doing a conditional move with SF/DF types, but the comparison > is KF/TF. That is because the SF/DF types can use the traditional FPR > registers, but IEEE 128-bit floating point can only do arithmetic in the > traditional Altivec registers. ok. > > This code also has to insert a XXPERMDI if you are moving KF/TF values, but > the comparison is done with SF/DF values. In this case, the set and compare > mask for SF/DF clears the bottom 64-bits of the register, and the XXPERMDI is > needed to fill it. ok. > > I have tested this patch in various little endian and big endian PowerPC builds > since I've posted. It has no regressions, and it adds the instructions if > -mcpu=power10 is used. > > gcc/ > 2021-04-09 Michael Meissner > > * config/rs6000/rs6000.c (have_compare_and_set_mask): Add IEEE > 128-bit floating point types. ok > * config/rs6000/rs6000.md (FPMASK): New iterator. > (FPMASK2): New iterator. comment on this below. > (Fv mode attribute): Add KFmode and TFmode. ok Missing an entry? I'm not certain I've followed changelog versus code accurately here. May need an additional entry, stl (movcc): Replace SFDF with FPMASK > (movcc_fpmask): Replace > movcc_p9. Add IEEE 128-bit fp support. > (movcc_invert_fpmask): Replace > movcc_invert_p9. Add IEEE 128-bit fp > support. > (fpmask): Add IEEE 128-bit fp support. Enable generator to > build te RTL. > (xxsel): Add IEEE 128-bit fp support. Enable generator to > build te RTL. ok > > gcc/testsuite/ > 2021-04-09 Michael Meissner > > * gcc.target/powerpc/float128-cmove.c: New test. > * gcc.target/powerpc/float128-minmax-3.c: New test. > --- > gcc/config/rs6000/rs6000.c | 8 +- > gcc/config/rs6000/rs6000.md | 186 ++++++++++++------ > .../gcc.target/powerpc/float128-cmove.c | 93 +++++++++ > .../gcc.target/powerpc/float128-minmax-3.c | 15 ++ > 4 files changed, 236 insertions(+), 66 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-cmove.c > create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c > > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c > index e87686c1c4d..ad0d83f6d3f 100644 > --- a/gcc/config/rs6000/rs6000.c > +++ b/gcc/config/rs6000/rs6000.c > @@ -15706,8 +15706,8 @@ rs6000_emit_vector_cond_expr (rtx dest, rtx op_true, rtx op_false, > return 1; > } > > -/* Possibly emit the xsmaxcdp and xsmincdp instructions to emit a maximum or > - minimum with "C" semantics. > +/* Possibly emit the xsmaxc{dp,qp} and xsminc{dp,qp} instructions to emit a > + maximum or minimum with "C" semantics. > > Unless you use -ffast-math, you can't use these instructions to replace > conditions that implicitly reverse the condition because the comparison > @@ -15843,6 +15843,10 @@ have_compare_and_set_mask (machine_mode mode) > case E_DFmode: > return TARGET_P9_MINMAX; > > + case E_KFmode: > + case E_TFmode: > + return FLOAT128_MIN_MAX_FPMASK_P (mode); > + > default: > break; > } > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 17b2fdc1cdd..ca4a4d01f05 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -575,6 +575,19 @@ (define_mode_iterator SFDF [SF DF]) > ; And again, for when we need two FP modes in a pattern. > (define_mode_iterator SFDF2 [SF DF]) > > +; Floating scalars that supports the set compare mask instruction. > +(define_mode_iterator FPMASK [SF > + DF > + (KF "FLOAT128_MIN_MAX_FPMASK_P (KFmode)") > + (TF "FLOAT128_MIN_MAX_FPMASK_P (TFmode)")]) > + > +; And again, for patterns that need two (potentially) different floating point > +; scalars that support the set compare mask instruction. All the words are here, i think. But I'd be explicit that the defines are identical by design. I've read over the rest, nothing else jumps out at me. Thanks -WIll > +(define_mode_iterator FPMASK2 [SF > + DF > + (KF "FLOAT128_MIN_MAX_FPMASK_P (KFmode)") > + (TF "FLOAT128_MIN_MAX_FPMASK_P (TFmode)")]) > + > ; A generic s/d attribute, for sp/dp for example. > (define_mode_attr sd [(SF "s") (DF "d") > (V4SF "s") (V2DF "d")]) > @@ -608,8 +621,13 @@ (define_mode_attr Ff [(SF "f") (DF "d") (DI "d")]) > ; SF/DF constraint for arithmetic on VSX registers using instructions added in > ; ISA 2.06 (power7). This includes instructions that normally target DF mode, > ; but are used on SFmode, since internally SFmode values are kept in the DFmode > -; format. > -(define_mode_attr Fv [(SF "wa") (DF "wa") (DI "wa")]) > +; format. Also include IEEE 128-bit instructions which are restricted to the > +; Altivec registers. > +(define_mode_attr Fv [(SF "wa") > + (DF "wa") > + (DI "wa") > + (KF "v") > + (TF "v")]) > > ; Which isa is needed for those float instructions? > (define_mode_attr Fisa [(SF "p8v") (DF "*") (DI "*")]) > @@ -5316,10 +5334,10 @@ (define_insn "*setnbcr_signed_" > > ;; Floating point conditional move > (define_expand "movcc" > - [(set (match_operand:SFDF 0 "gpc_reg_operand") > - (if_then_else:SFDF (match_operand 1 "comparison_operator") > - (match_operand:SFDF 2 "gpc_reg_operand") > - (match_operand:SFDF 3 "gpc_reg_operand")))] > + [(set (match_operand:FPMASK 0 "gpc_reg_operand") > + (if_then_else:FPMASK (match_operand 1 "comparison_operator") > + (match_operand:FPMASK 2 "gpc_reg_operand") > + (match_operand:FPMASK 3 "gpc_reg_operand")))] > "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT" > { > if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) > @@ -5339,92 +5357,132 @@ (define_insn "*fsel4" > "fsel %0,%1,%2,%3" > [(set_attr "type" "fp")]) > > -(define_insn_and_split "*movcc_p9" > - [(set (match_operand:SFDF 0 "vsx_register_operand" "=&,") > - (if_then_else:SFDF > +(define_insn_and_split "*movcc_fpmask" > + [(set (match_operand:FPMASK 0 "vsx_register_operand" "=") > + (if_then_else:FPMASK > (match_operator:CCFP 1 "fpmask_comparison_operator" > - [(match_operand:SFDF2 2 "vsx_register_operand" ",") > - (match_operand:SFDF2 3 "vsx_register_operand" ",")]) > - (match_operand:SFDF 4 "vsx_register_operand" ",") > - (match_operand:SFDF 5 "vsx_register_operand" ","))) > - (clobber (match_scratch:V2DI 6 "=0,&wa"))] > + [(match_operand:FPMASK2 2 "vsx_register_operand" "") > + (match_operand:FPMASK2 3 "vsx_register_operand" "")]) > + (match_operand:FPMASK 4 "vsx_register_operand" "") > + (match_operand:FPMASK 5 "vsx_register_operand" ""))) > + (clobber (match_scratch:V2DI 6 "=&"))] > "TARGET_P9_MINMAX" > "#" > "&& 1" > - [(set (match_dup 6) > - (if_then_else:V2DI (match_dup 1) > - (match_dup 7) > - (match_dup 8))) > - (set (match_dup 0) > - (if_then_else:SFDF (ne (match_dup 6) > - (match_dup 8)) > - (match_dup 4) > - (match_dup 5)))] > + [(pc)] > { > - if (GET_CODE (operands[6]) == SCRATCH) > - operands[6] = gen_reg_rtx (V2DImode); > + rtx dest = operands[0]; > + rtx cmp = operands[1]; > + rtx cmp_op1 = operands[2]; > + rtx cmp_op2 = operands[3]; > + rtx move_t = operands[4]; > + rtx move_f = operands[5]; > + rtx mask_reg = operands[6]; > + rtx mask_m1 = CONSTM1_RTX (V2DImode); > + rtx mask_0 = CONST0_RTX (V2DImode); > + machine_mode move_mode = mode; > + machine_mode compare_mode = mode; > + > + if (GET_CODE (mask_reg) == SCRATCH) > + mask_reg = gen_reg_rtx (V2DImode); > > - operands[7] = CONSTM1_RTX (V2DImode); > - operands[8] = CONST0_RTX (V2DImode); > + /* Emit the compare and set mask instruction. */ > + emit_insn (gen_fpmask (mask_reg, cmp, cmp_op1, cmp_op2, > + mask_m1, mask_0)); > + > + /* If we have a 64-bit comparison, but an 128-bit move, we need to extend the > + mask. Because we are using the splat builtin to extend the V2DImode, we > + need to use element 1 on little endian systems. */ > + if (!FLOAT128_IEEE_P (compare_mode) && FLOAT128_IEEE_P (move_mode)) > + { > + rtx element = WORDS_BIG_ENDIAN ? const0_rtx : const1_rtx; > + emit_insn (gen_vsx_xxspltd_v2di (mask_reg, mask_reg, element)); > + } > + > + /* Now emit the XXSEL insn. */ > + emit_insn (gen_xxsel (dest, mask_reg, mask_0, move_t, move_f)); > + DONE; > } > - [(set_attr "length" "8") > + ;; length is 12 in case we need to add XXPERMDI > + [(set_attr "length" "12") > (set_attr "type" "vecperm")]) > > ;; Handle inverting the fpmask comparisons. > -(define_insn_and_split "*movcc_invert_p9" > - [(set (match_operand:SFDF 0 "vsx_register_operand" "=&,") > - (if_then_else:SFDF > +(define_insn_and_split "*movcc_invert_fpmask" > + [(set (match_operand:FPMASK 0 "vsx_register_operand" "=") > + (if_then_else:FPMASK > (match_operator:CCFP 1 "invert_fpmask_comparison_operator" > - [(match_operand:SFDF2 2 "vsx_register_operand" ",") > - (match_operand:SFDF2 3 "vsx_register_operand" ",")]) > - (match_operand:SFDF 4 "vsx_register_operand" ",") > - (match_operand:SFDF 5 "vsx_register_operand" ","))) > - (clobber (match_scratch:V2DI 6 "=0,&wa"))] > + [(match_operand:FPMASK2 2 "vsx_register_operand" "") > + (match_operand:FPMASK2 3 "vsx_register_operand" "")]) > + (match_operand:FPMASK 4 "vsx_register_operand" "") > + (match_operand:FPMASK 5 "vsx_register_operand" ""))) > + (clobber (match_scratch:V2DI 6 "=&"))] > "TARGET_P9_MINMAX" > "#" > "&& 1" > - [(set (match_dup 6) > - (if_then_else:V2DI (match_dup 9) > - (match_dup 7) > - (match_dup 8))) > - (set (match_dup 0) > - (if_then_else:SFDF (ne (match_dup 6) > - (match_dup 8)) > - (match_dup 5) > - (match_dup 4)))] > + [(pc)] > { > - rtx op1 = operands[1]; > - enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1)); > + rtx dest = operands[0]; > + rtx old_cmp = operands[1]; > + rtx cmp_op1 = operands[2]; > + rtx cmp_op2 = operands[3]; > + enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (old_cmp)); > + rtx cmp_rev = gen_rtx_fmt_ee (cond, CCFPmode, cmp_op1, cmp_op2); > + rtx move_f = operands[4]; > + rtx move_t = operands[5]; > + rtx mask_reg = operands[6]; > + rtx mask_m1 = CONSTM1_RTX (V2DImode); > + rtx mask_0 = CONST0_RTX (V2DImode); > + machine_mode move_mode = mode; > + machine_mode compare_mode = mode; > > - if (GET_CODE (operands[6]) == SCRATCH) > - operands[6] = gen_reg_rtx (V2DImode); > + if (GET_CODE (mask_reg) == SCRATCH) > + mask_reg = gen_reg_rtx (V2DImode); > > - operands[7] = CONSTM1_RTX (V2DImode); > - operands[8] = CONST0_RTX (V2DImode); > + /* Emit the compare and set mask instruction. */ > + emit_insn (gen_fpmask (mask_reg, cmp_rev, cmp_op1, cmp_op2, > + mask_m1, mask_0)); > > - operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]); > + /* If we have a 64-bit comparison, but an 128-bit move, we need to extend the > + mask. Because we are using the splat builtin to extend the V2DImode, we > + need to use element 1 on little endian systems. */ > + if (!FLOAT128_IEEE_P (compare_mode) && FLOAT128_IEEE_P (move_mode)) > + { > + rtx element = WORDS_BIG_ENDIAN ? const0_rtx : const1_rtx; > + emit_insn (gen_vsx_xxspltd_v2di (mask_reg, mask_reg, element)); > + } > + > + /* Now emit the XXSEL insn. */ > + emit_insn (gen_xxsel (dest, mask_reg, mask_0, move_t, move_f)); > + DONE; > } > - [(set_attr "length" "8") > + ;; length is 12 in case we need to add XXPERMDI > + [(set_attr "length" "12") > (set_attr "type" "vecperm")]) > > -(define_insn "*fpmask" > - [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") > +(define_insn "fpmask" > + [(set (match_operand:V2DI 0 "vsx_register_operand" "=") > (if_then_else:V2DI > (match_operator:CCFP 1 "fpmask_comparison_operator" > - [(match_operand:SFDF 2 "vsx_register_operand" "") > - (match_operand:SFDF 3 "vsx_register_operand" "")]) > + [(match_operand:FPMASK 2 "vsx_register_operand" "") > + (match_operand:FPMASK 3 "vsx_register_operand" "")]) > (match_operand:V2DI 4 "all_ones_constant" "") > (match_operand:V2DI 5 "zero_constant" "")))] > "TARGET_P9_MINMAX" > - "xscmp%V1dp %x0,%x2,%x3" > +{ > + return (FLOAT128_IEEE_P (mode) > + ? "xscmp%V1qp %0,%2,%3" > + : "xscmp%V1dp %x0,%x2,%x3"); > +} > [(set_attr "type" "fpcompare")]) > > -(define_insn "*xxsel" > - [(set (match_operand:SFDF 0 "vsx_register_operand" "=") > - (if_then_else:SFDF (ne (match_operand:V2DI 1 "vsx_register_operand" "wa") > - (match_operand:V2DI 2 "zero_constant" "")) > - (match_operand:SFDF 3 "vsx_register_operand" "") > - (match_operand:SFDF 4 "vsx_register_operand" "")))] > +(define_insn "xxsel" > + [(set (match_operand:FPMASK 0 "vsx_register_operand" "=wa") > + (if_then_else:FPMASK > + (ne (match_operand:V2DI 1 "vsx_register_operand" "wa") > + (match_operand:V2DI 2 "zero_constant" "")) > + (match_operand:FPMASK 3 "vsx_register_operand" "wa") > + (match_operand:FPMASK 4 "vsx_register_operand" "wa")))] > "TARGET_P9_MINMAX" > "xxsel %x0,%x4,%x3,%x1" > [(set_attr "type" "vecmove")]) > diff --git a/gcc/testsuite/gcc.target/powerpc/float128-cmove.c b/gcc/testsuite/gcc.target/powerpc/float128-cmove.c > new file mode 100644 > index 00000000000..639d5a77087 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/float128-cmove.c > @@ -0,0 +1,93 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target ppc_float128_hw } */ > +/* { dg-require-effective-target power10_ok } */ > +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ > +/* { dg-final { scan-assembler {\mxscmpeq[dq]p\M} } } */ > +/* { dg-final { scan-assembler {\mxxpermdi\M} } } */ > +/* { dg-final { scan-assembler {\mxxsel\M} } } */ > +/* { dg-final { scan-assembler-not {\mxscmpu[dq]p\M} } } */ > +/* { dg-final { scan-assembler-not {\mfcmp[uo]\M} } } */ > +/* { dg-final { scan-assembler-not {\mfsel\M} } } */ > + > +/* This series of tests tests whether you can do a conditional move where the > + test is one floating point type, and the result is another floating point > + type. > + > + If the comparison type is SF/DFmode, and the move type is IEEE 128-bit > + floating point, we have to duplicate the mask in the lower 64-bits with > + XXPERMDI because XSCMPEQDP clears the bottom 64-bits of the mask register. > + > + Going the other way (IEEE 128-bit comparsion, 64-bit move) is fine as the > + mask word will be 128-bits. */ > + > +float > +eq_f_d (float a, float b, double x, double y) > +{ > + return (x == y) ? a : b; > +} > + > +double > +eq_d_f (double a, double b, float x, float y) > +{ > + return (x == y) ? a : b; > +} > + > +float > +eq_f_f128 (float a, float b, __float128 x, __float128 y) > +{ > + return (x == y) ? a : b; > +} > + > +double > +eq_d_f128 (double a, double b, __float128 x, __float128 y) > +{ > + return (x == y) ? a : b; > +} > + > +__float128 > +eq_f128_f (__float128 a, __float128 b, float x, float y) > +{ > + return (x == y) ? a : b; > +} > + > +__float128 > +eq_f128_d (__float128 a, __float128 b, double x, double y) > +{ > + return (x != y) ? a : b; > +} > + > +float > +ne_f_d (float a, float b, double x, double y) > +{ > + return (x != y) ? a : b; > +} > + > +double > +ne_d_f (double a, double b, float x, float y) > +{ > + return (x != y) ? a : b; > +} > + > +float > +ne_f_f128 (float a, float b, __float128 x, __float128 y) > +{ > + return (x != y) ? a : b; > +} > + > +double > +ne_d_f128 (double a, double b, __float128 x, __float128 y) > +{ > + return (x != y) ? a : b; > +} > + > +__float128 > +ne_f128_f (__float128 a, __float128 b, float x, float y) > +{ > + return (x != y) ? a : b; > +} > + > +__float128 > +ne_f128_d (__float128 a, __float128 b, double x, double y) > +{ > + return (x != y) ? a : b; > +} > diff --git a/gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c b/gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c > new file mode 100644 > index 00000000000..6f7627c0f2a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/float128-minmax-3.c > @@ -0,0 +1,15 @@ > +/* { dg-require-effective-target ppc_float128_hw } */ > +/* { dg-require-effective-target power10_ok } */ > +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ > + > +#ifndef TYPE > +#define TYPE _Float128 > +#endif > + > +/* Test that the fminf128/fmaxf128 functions generate if/then/else and not a > + call. */ > +TYPE f128_min (TYPE a, TYPE b) { return (a < b) ? a : b; } > +TYPE f128_max (TYPE a, TYPE b) { return (b > a) ? b : a; } > + > +/* { dg-final { scan-assembler {\mxsmaxcqp\M} } } */ > +/* { dg-final { scan-assembler {\mxsmincqp\M} } } */ > -- > 2.22.0 > >