From patchwork Thu Jan 13 17:08:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raoni Fassina Firmino X-Patchwork-Id: 49995 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9A42A385AC1E for ; Thu, 13 Jan 2022 17:09:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9A42A385AC1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1642093783; bh=vcqRNZEQAfH7LGO5QWrDVH4ukUFmOwCLzigU3sJw5G4=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=bPIvhae4UJKaqNDkm7YF1evGPdREcqczQzuXiwonUYc/gaXzKIIOH/rTXiGDC5Wxk NIS60+byWIJOrBahGUSPJnWiNZxKboLpO1OZXeTAqLfMSRXaQBu1kmYI6t68u2ENui Y14KzD812c5RRfFRqvEKWp7+U30fZeN8BrXrfbNU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 21126385840D for ; Thu, 13 Jan 2022 17:09:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 21126385840D Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 20DGqZNd027362; Thu, 13 Jan 2022 17:09:04 GMT Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3djr040dkp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Jan 2022 17:09:04 +0000 Received: from m0098409.ppops.net (m0098409.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 20DGqtm5032096; Thu, 13 Jan 2022 17:09:04 GMT 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 3djr040dk6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Jan 2022 17:09:03 +0000 Received: from pps.filterd (ppma03wdc.us.ibm.com [127.0.0.1]) by ppma03wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 20DH7Vxp007954; Thu, 13 Jan 2022 17:09:02 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma03wdc.us.ibm.com with ESMTP id 3djknseh79-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Jan 2022 17:09:02 +0000 Received: from b01ledav006.gho.pok.ibm.com (b01ledav006.gho.pok.ibm.com [9.57.199.111]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 20DH905525297172 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 13 Jan 2022 17:09:00 GMT Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B522BAC059; Thu, 13 Jan 2022 17:09:00 +0000 (GMT) Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 03553AC07C; Thu, 13 Jan 2022 17:08:56 +0000 (GMT) Received: from workbox (unknown [9.65.220.25]) by b01ledav006.gho.pok.ibm.com (Postfix) with ESMTPS; Thu, 13 Jan 2022 17:08:56 +0000 (GMT) Date: Thu, 13 Jan 2022 14:08:53 -0300 To: gcc-patches@gcc.gnu.org Subject: [PATCH v9] rtl: builtins: (not just) rs6000: Add builtins for fegetround, feclearexcept and feraiseexcept [PR94193] Message-ID: <20220113170853.mw2bcii7x2rgwc2l@workbox> Mail-Followup-To: gcc-patches@gcc.gnu.org, segher@kernel.crashing.org, joseph@codesourcery.com, jakub@redhat.com, rguenther@suse.de, hp@bitrange.com, law@redhat.com, will_schmidt@vnet.ibm.com, jeffreyalaw@gmail.com Content-Disposition: inline X-TM-AS-GCONF: 00 X-Proofpoint-GUID: J6yGSR9eG5zsQwiGQexaIs7bkZ5qIhic X-Proofpoint-ORIG-GUID: -aJRmelS8RyXv4rNe_7niE359sw1S2pC X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-01-13_08,2022-01-13_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 spamscore=0 clxscore=1015 priorityscore=1501 adultscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2201130106 X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, 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-Patchwork-Original-From: Raoni Fassina Firmino via Gcc-patches From: Raoni Fassina Firmino Reply-To: Raoni Fassina Firmino Cc: jakub@redhat.com, rguenther@suse.de, segher@kernel.crashing.org, law@redhat.com, joseph@codesourcery.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Changes since v8[8]: - Refactored and expanded builtin-feclearexcept-feraiseexcept-2.c testcase: + Use a macro to avoid extended repetition of the core test code. + Expanded the test code to check builtins return code. + Added more tests to test all valid (standard) exceptions input combinations. + Updated the header comment to explain why the input must be passed as constants. Changes since v7[7]: - Fixed an array indexing bug on fegeround testcase. - Fixed typos and spelling mistakes spread trouout the added comments. - Reworded header comment/description for fegetround expander. - Fixed changelog in the commit message. This is an update to v8, based on the same review from Seguer to expand the test coverage for feclearexcept and feraiseexcept (That is also why I am keeping the v8 changelog here, since v8 had no reviews). Two things to point out is: 1) The use of a macro there instead of a function, unfortunately the builtins (for rs6000) only expand when the input is a constant, so a macro is the way to go, and for the same reason 2) I wanted to simplify the way to test all combinations of input, but I could not think in a way without making some macro magics that would be way less readable than listing all combinations by hand. Tested on top of master (02a8a01bf396e009bfc31e1104c315fd403b4cca) on the following plataforms with no regression: - powerpc64le-linux-gnu (Power 9) - powerpc64le-linux-gnu (Power 8) - powerpc64-linux-gnu (Power 9, with 32 and 64 bits tests) Documentation changes tested on x86_64-redhat-linux. == I'm repeating the "changelog" from past versions here for convenience: Changes since v6[6] and v5[5]: - Based this version on the v5 one. - Reworked all builtins back to the way they are in v5 and added the following changes: + Added a test to target libc, only expanding with glibc as the target libc. + Updated all three expanders header comment to reflect the added behavior (fegetround got a full header as it had none). + Added extra documentation for the builtins on doc/extend.texi, similar to v6 version, but only the introductory paragraph, without a dedicated entry for each, since now they behavior and signature match the C99 ones. - Changed the description for the return operand in the RTL template of the fegetround expander. Using "(set )", the same way as rs6000_mffsl expander (this change was taken from v6). - Updated the commit message mentioning the target libc restriction and updated changelog. Changes since v5[5]: - Reworked all builtins to accept the FE_* macros as parameters and so be agnostic to libc implementations. Largely based of fpclassify. To that end, there is some new files changed: + Change the argument list for the builtins declarations in builtins.def + Added new types in builtin-types.def to use in the buitins declarations. + Added extra documentation for the builtins on doc/extend.texi, similar to fpclassify. - Updated doc/md.texi documentation with the new optab behaviors. - Updated comments to the expanders and expand handlers to try to explain whats is going on. - Changed the description for the return operand in the RTL template of the fegetround expander. Using "(set )", the same way as rs6000_mffsl expander. - Updated testcases with helper macros with the new argument list. Changes since v4[4]: - Fixed more spelling and code style. - Add more clarification on comments for feraiseexcept and feclearexcept expands; Changes since v3[3]: - Fixed fegetround bug on powerpc64 (big endian) that Segher spotted; Changes since v2[2]: - Added documentation for the new optabs; - Remove use of non portable __builtin_clz; - Changed feclearexcept and feraiseexcept to accept all 4 valid flags at the same time and added more test for that case; - Extended feclearexcept and feraiseexcept testcases to match accepting multiple flags; - Fixed builtin-feclearexcept-feraiseexcept-2.c testcase comparison after feclearexcept tests; - Updated commit message to reflect change in feclearexcept and feraiseexcept from the glibc counterpart; - Fixed English spelling and typos; - Fixed code-style; - Changed subject line tag to make clear it is not just rs6000 code. Changes since v1[1]: - Fixed English spelling; - Fixed code-style; - Changed match operand predicate in feclearexcept and feraiseexcept; - Changed testcase options; - Minor changes in test code to be C90 compatible; - Other minor changes suggested by Segher; - Changed subject line tag (not sure if I tagged correctly or should include optabs: also) [1] https://gcc.gnu.org/pipermail/gcc-patches/2020-August/552024.html [2] https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553297.html [3] https://gcc.gnu.org/pipermail/gcc-patches/2020-October/557109.html [4] https://gcc.gnu.org/pipermail/gcc-patches/2020-October/557349.html [5] https://gcc.gnu.org/pipermail/gcc-patches/2020-November/557984.html [6] https://gcc.gnu.org/pipermail/gcc-patches/2021-October/581837.html [7] https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585375.html [8] https://gcc.gnu.org/pipermail/gcc-patches/2021-December/587360.html ---- 8< ---- This optimizations were originally in glibc, but was removed and suggested that they were a good fit as gcc builtins[1]. feclearexcept and feraiseexcept were extended (in comparison to the glibc version) to accept any combination of the accepted flags, not limited to just one flag bit at a time anymore. The builtin expanders needs knowledge of the target libc's FE_* values, so they are limited to expand only to suitable libcs. The associated bugreport: PR target/94193 [1] https://sourceware.org/legacy-ml/libc-alpha/2020-03/msg00047.html https://sourceware.org/legacy-ml/libc-alpha/2020-03/msg00080.html 2020-08-13 Raoni Fassina Firmino gcc/ChangeLog: * builtins.c (expand_builtin_fegetround): New function. (expand_builtin_feclear_feraise_except): New function. (expand_builtin): Add cases for BUILT_IN_FEGETROUND, BUILT_IN_FECLEAREXCEPT and BUILT_IN_FERAISEEXCEPT. * config/rs6000/rs6000.md (fegetroundsi): New pattern. (feclearexceptsi): New Pattern. (feraiseexceptsi): New Pattern. * doc/extend.texi: Add a new introductory paragraph about the new builtins. * doc/md.texi: (fegetround@var{m}): Document new optab. (feclearexcept@var{m}): Document new optab. (feraiseexcept@var{m}): Document new optab. * optabs.def (fegetround_optab): New optab. (feclearexcept_optab): New optab. (feraiseexcept_optab): New optab. gcc/testsuite/ChangeLog: * gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c: New test. * gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c: New test. * gcc.target/powerpc/builtin-fegetround.c: New test. Signed-off-by: Raoni Fassina Firmino --- gcc/builtins.c | 76 ++++++++++++ gcc/config/rs6000/rs6000.md | 111 ++++++++++++++++++ gcc/doc/extend.texi | 8 ++ gcc/doc/md.texi | 17 +++ gcc/optabs.def | 4 + .../builtin-feclearexcept-feraiseexcept-1.c | 76 ++++++++++++ .../builtin-feclearexcept-feraiseexcept-2.c | 91 ++++++++++++++ .../gcc.target/powerpc/builtin-fegetround.c | 36 ++++++ 8 files changed, 419 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c create mode 100644 gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c diff --git a/gcc/builtins.c b/gcc/builtins.c index c780340ed327..f52bff85f923 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -119,6 +119,9 @@ static rtx expand_builtin_mathfn_3 (tree, rtx, rtx); static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx); static rtx expand_builtin_interclass_mathfn (tree, rtx); static rtx expand_builtin_sincos (tree); +static rtx expand_builtin_fegetround (tree, rtx, machine_mode); +static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode, + optab); static rtx expand_builtin_cexpi (tree, rtx); static rtx expand_builtin_int_roundingfn (tree, rtx); static rtx expand_builtin_int_roundingfn_2 (tree, rtx); @@ -2555,6 +2558,59 @@ expand_builtin_sincos (tree exp) return const0_rtx; } +/* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the + result and setting it in TARGET. Otherwise return NULL_RTX on failure. */ +static rtx +expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode) +{ + if (!validate_arglist (exp, VOID_TYPE)) + return NULL_RTX; + + insn_code icode = direct_optab_handler (fegetround_optab, SImode); + if (icode == CODE_FOR_nothing) + return NULL_RTX; + + if (target == 0 + || GET_MODE (target) != target_mode + || !(*insn_data[icode].operand[0].predicate) (target, target_mode)) + target = gen_reg_rtx (target_mode); + + rtx pat = GEN_FCN (icode) (target); + if (!pat) + return NULL_RTX; + emit_insn (pat); + + return target; +} + +/* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99 + fenv.h), returning the result and setting it in TARGET. Otherwise return + NULL_RTX on failure. */ +static rtx +expand_builtin_feclear_feraise_except (tree exp, rtx target, + machine_mode target_mode, optab op_optab) +{ + if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; + rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + + insn_code icode = direct_optab_handler (op_optab, SImode); + if (icode == CODE_FOR_nothing) + return NULL_RTX; + + if (target == 0 + || GET_MODE (target) != target_mode + || !(*insn_data[icode].operand[0].predicate) (target, target_mode)) + target = gen_reg_rtx (target_mode); + + rtx pat = GEN_FCN (icode) (target, op0); + if (!pat) + return NULL_RTX; + emit_insn (pat); + + return target; +} + /* Expand a call to the internal cexpi builtin to the sincos math function. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. */ @@ -7056,6 +7112,26 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, return target; break; + case BUILT_IN_FEGETROUND: + target = expand_builtin_fegetround (exp, target, target_mode); + if (target) + return target; + break; + + case BUILT_IN_FECLEAREXCEPT: + target = expand_builtin_feclear_feraise_except (exp, target, target_mode, + feclearexcept_optab); + if (target) + return target; + break; + + case BUILT_IN_FERAISEEXCEPT: + target = expand_builtin_feclear_feraise_except (exp, target, target_mode, + feraiseexcept_optab); + if (target) + return target; + break; + case BUILT_IN_APPLY_ARGS: return expand_builtin_apply_args (); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6f74075f58d8..5f1a7f047cec 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6917,6 +6917,117 @@ [(set_attr "type" "fpload") (set_attr "length" "8") (set_attr "isa" "*,p8v,p8v")]) + +;; int fegetround(void) +;; +;; This expansion for the C99 function only expands for compatible +;; target libcs, because it needs to return one of FE_DOWNWARD, +;; FE_TONEAREST, FE_TOWARDZERO or FE_UPWARD with the values as defined +;; by the target libc, and since the libc is free to choose the values +;; (and they may differ from the hardware) and the expander needs to +;; know then beforehand, this expanded only expands for target libcs +;; that it can handle the values is knows. +;; Because of these restriction, this only expands on the desired +;; case and fallback to a call to libc otherwise. +(define_expand "fegetroundsi" + [(set (match_operand:SI 0 "gpc_reg_operand") + (unspec_volatile:SI [(const_int 0)] UNSPECV_MFFSL))] + "TARGET_HARD_FLOAT" +{ + if (!OPTION_GLIBC) + FAIL; + + rtx tmp_df = gen_reg_rtx (DFmode); + emit_insn (gen_rs6000_mffsl (tmp_df)); + + rtx tmp_di = simplify_gen_subreg (DImode, tmp_df, DFmode, 0); + rtx tmp_di_2 = gen_reg_rtx (DImode); + emit_insn (gen_anddi3 (tmp_di_2, tmp_di, GEN_INT (3))); + rtx tmp_si = gen_reg_rtx (SImode); + tmp_si = gen_lowpart (SImode, tmp_di_2); + emit_move_insn (operands[0], tmp_si); + DONE; +}) + +;; int feclearexcept(int excepts) +;; +;; This expansion for the C99 function only works when EXCEPTS is a +;; constant known at compile time and specifies any one of +;; FE_INEXACT, FE_DIVBYZERO, FE_UNDERFLOW and FE_OVERFLOW flags. +;; It doesn't handle values out of range, and always returns 0. +;; Note that FE_INVALID is unsupported because it maps to more than +;; one bit of the FPSCR register. +;; The FE_* are defined in the target libc, and since they are free to +;; choose the values and the expand needs to know them beforehand, +;; this expander only expands for target libcs that it can handle the +;; values it knows. +;; Because of these restrictions, this only expands on the desired +;; cases and fallback to a call to libc on any other case. +(define_expand "feclearexceptsi" + [(use (match_operand:SI 1 "const_int_operand" "n")) + (set (match_operand:SI 0 "gpc_reg_operand") + (const_int 0))] + "TARGET_HARD_FLOAT" +{ + if (!OPTION_GLIBC) + FAIL; + + unsigned int fe = INTVAL (operands[1]); + if (fe != (fe & 0x1e000000)) + FAIL; + + if (fe & 0x02000000) /* FE_INEXACT */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 6))); + if (fe & 0x04000000) /* FE_DIVBYZERO */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 5))); + if (fe & 0x08000000) /* FE_UNDERFLOW */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 4))); + if (fe & 0x10000000) /* FE_OVERFLOW */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 3))); + + emit_move_insn (operands[0], const0_rtx); + DONE; +}) + +;; int feraiseexcept(int excepts) +;; +;; This expansion for the C99 function only works when excepts is a +;; constant known at compile time and specifies any one of +;; FE_INEXACT, FE_DIVBYZERO, FE_UNDERFLOW and FE_OVERFLOW flags. +;; It doesn't handle values out of range, and always returns 0. +;; Note that FE_INVALID is unsupported because it maps to more than +;; one bit of the FPSCR register. +;; The FE_* are defined in the target libc, and since they are free to +;; choose the values and the expand needs to know them beforehand, +;; this expander only expands for target libcs that it can handle the +;; values it knows. +;; Because of these restrictions, this only expands on the desired +;; cases and fallback to a call to libc on any other case. +(define_expand "feraiseexceptsi" + [(use (match_operand:SI 1 "const_int_operand" "n")) + (set (match_operand:SI 0 "gpc_reg_operand") + (const_int 0))] + "TARGET_HARD_FLOAT" +{ + if (!OPTION_GLIBC) + FAIL; + + unsigned int fe = INTVAL (operands[1]); + if (fe != (fe & 0x1e000000)) + FAIL; + + if (fe & 0x02000000) /* FE_INEXACT */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 6))); + if (fe & 0x04000000) /* FE_DIVBYZERO */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 5))); + if (fe & 0x08000000) /* FE_UNDERFLOW */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 4))); + if (fe & 0x10000000) /* FE_OVERFLOW */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 3))); + + emit_move_insn (operands[0], const0_rtx); + DONE; +}) ;; Define the TImode operations that can be done in a small number ;; of instructions. The & constraints are to prevent the register diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 637124a71722..0b2dc5f9d121 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -13485,6 +13485,14 @@ In the same fashion, GCC provides @code{fpclassify}, @code{isfinite}, @code{__builtin_} prefixed. The @code{isinf} and @code{isnan} built-in functions appear both with and without the @code{__builtin_} prefix. +GCC provides built-in versions of the ISO C99 floating-point rounding and +exceptions handling functions @code{fegetround}, @code{feclearexcept} and +@code{feraiseexcept}. They may not be available for all targets, and because +they need close interaction with libc internal values, they may not be available +for all target libcs, but in all cases they will gracefully fallback to libc +calls. This built-in functions appear both with and without the +@code{__builtin_} prefix. + @deftypefn {Built-in Function} void *__builtin_alloca (size_t size) The @code{__builtin_alloca} function must be called at block scope. The function allocates an object @var{size} bytes large on the stack diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 19e89ae502bc..5568f9453233 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -6069,6 +6069,23 @@ mode @var{m}, which is a scalar or vector floating-point mode. This pattern is not allowed to @code{FAIL}. +@cindex @code{fegetround@var{m}} instruction pattern +@item @samp{fegetround@var{m}} +Store the current machine floating-point rounding mode into operand 0. +Operand 0 has mode @var{m}, which is scalar. This pattern is used to +implement the @code{fegetround} function from the ISO C99 standard. + +@cindex @code{feclearexcept@var{m}} instruction pattern +@cindex @code{feraiseexcept@var{m}} instruction pattern +@item @samp{feclearexcept@var{m}} +@item @samp{feraiseexcept@var{m}} +Clears or raises the supported machine floating-point exceptions +represented by the bits in operand 1. Error status is stored as +nonzero value in operand 0. Both operands have mode @var{m}, which is +a scalar. These patterns are used to implement the +@code{feclearexcept} and @code{feraiseexcept} functions from the ISO +C99 standard. + @cindex @code{exp@var{m}2} instruction pattern @item @samp{exp@var{m}2} Raise e (the base of natural logarithms) to the power of operand 1 diff --git a/gcc/optabs.def b/gcc/optabs.def index 5fcf5386a0b3..f4afe5c75b5b 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -330,6 +330,10 @@ OPTAB_D (sinh_optab, "sinh$a2") OPTAB_D (tan_optab, "tan$a2") OPTAB_D (tanh_optab, "tanh$a2") +OPTAB_D (fegetround_optab, "fegetround$a") +OPTAB_D (feclearexcept_optab, "feclearexcept$a") +OPTAB_D (feraiseexcept_optab, "feraiseexcept$a") + /* C99 implementations of fmax/fmin. */ OPTAB_D (fmax_optab, "fmax$a3") OPTAB_D (fmin_optab, "fmin$a3") diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c new file mode 100644 index 000000000000..4482e89b0db9 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c @@ -0,0 +1,76 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-lm -fno-builtin" } */ + +/* This testcase ensures that the builtins expand with the matching arguments + or otherwise fallback gracefully to a function call, and don't ICE during + compilation. + "-fno-builtin" option is used to enable calls to libc implementation of the + gcc builtins tested when not using __builtin_ prefix. */ + +#include + +int +main () +{ + int rsi = 0; + long rsl = 0; + short rss = 0; + char rsc = 0; + + unsigned int rui = 0; + unsigned long rul = 0; + unsigned short rus = 0; + unsigned char ruc = 0; + + int e = FE_DIVBYZERO; + + __builtin_feclearexcept(e); // CALL + __builtin_feclearexcept(FE_ALL_EXCEPT); // CALL + __builtin_feclearexcept(FE_INVALID); // CALL + __builtin_feclearexcept(FE_INVALID | FE_INEXACT); // CALL + + __builtin_feclearexcept(FE_INEXACT | FE_DIVBYZERO | + FE_UNDERFLOW | FE_OVERFLOW); // EXPAND + __builtin_feclearexcept(FE_INEXACT | FE_OVERFLOW); // EXPAND + __builtin_feclearexcept(FE_INEXACT); // EXPAND + __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + __builtin_feclearexcept(FE_UNDERFLOW); // EXPAND + __builtin_feclearexcept(FE_OVERFLOW); // EXPAND + __builtin_feclearexcept(0); // EXPAND + + rsi = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rsl = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rss = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rsc = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rui = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rul = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rus = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + ruc = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + + + __builtin_feraiseexcept(e); // CALL + __builtin_feraiseexcept(FE_ALL_EXCEPT); // CALL + __builtin_feraiseexcept(FE_INVALID); // CALL + __builtin_feraiseexcept(FE_INVALID | FE_INEXACT); // CALL + + __builtin_feraiseexcept(FE_INEXACT | FE_DIVBYZERO | + FE_UNDERFLOW | FE_OVERFLOW); // EXPAND + __builtin_feraiseexcept(FE_INEXACT | FE_OVERFLOW); // EXPAND + __builtin_feraiseexcept(FE_INEXACT); // EXPAND + __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + __builtin_feraiseexcept(FE_UNDERFLOW); // EXPAND + __builtin_feraiseexcept(FE_OVERFLOW); // EXPAND + __builtin_feraiseexcept(0); // EXPAND + + rsi = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rsl = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rss = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rsc = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rui = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rul = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rus = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + ruc = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c new file mode 100644 index 000000000000..28c2a00ec520 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c @@ -0,0 +1,91 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-lm -fno-builtin" } */ + +/* This testcase ensures that the builtins are correctly expanded and match the + expected result. + "-fno-builtin" option is used to enable calls to libc implementation of the + gcc builtins tested when not using __builtin_ prefix. + The excepts parameter needs to be passed as constant to + __builtin_feclearexcept and __builtin_feraiseexcept because some bultins only + expand on constant input. */ + +#include + +#ifdef DEBUG +#include +#define INFO(...) printf(__VA_ARGS__) +#define FAIL(ret, raised, expected, excepts, excepts_str, func) \ + printf("ERROR [l %d] testing %s (%x): %s returned %d." \ + " Raised except bits %x, expecected %x\n", \ + __LINE__, excepts_str, excepts, func, ret, raised, expected) +#else +void abort (void); +#define INFO(...) +#define FAIL(ret, raised, expected, excepts, excepts_str, func) abort() +#endif + +#define TEST(excepts) \ + do { \ + int ret = 0; \ + int raised = 0; \ + \ + INFO("test: %s (%x)\n", #excepts, excepts); \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + ret = __builtin_feraiseexcept(excepts); \ + raised = fetestexcept(FE_ALL_EXCEPT); \ + if (ret != 0 || raised != (excepts)) \ + FAIL(ret, raised, excepts, excepts, #excepts, \ + "__builtin_feraiseexcept"); \ + \ + feraiseexcept(FE_ALL_EXCEPT); \ + ret = __builtin_feclearexcept(excepts); \ + raised = fetestexcept(FE_ALL_EXCEPT); \ + if (ret != 0 || raised != (FE_ALL_EXCEPT & ~(excepts))) \ + FAIL(ret, raised, FE_ALL_EXCEPT & ~(excepts), excepts, #excepts, \ + "__builtin_feclearexcept"); \ + } while (0) + +int +main () +{ + TEST(0); + TEST(FE_ALL_EXCEPT); + + TEST(FE_INVALID); + TEST(FE_DIVBYZERO); + TEST(FE_INEXACT); + TEST(FE_OVERFLOW); + TEST(FE_UNDERFLOW); + + TEST(FE_INVALID | FE_DIVBYZERO); + TEST(FE_INVALID | FE_INEXACT); + TEST(FE_INVALID | FE_OVERFLOW); + TEST(FE_INVALID | FE_UNDERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT); + TEST(FE_DIVBYZERO | FE_OVERFLOW); + TEST(FE_DIVBYZERO | FE_UNDERFLOW); + TEST(FE_INEXACT | FE_OVERFLOW); + TEST(FE_INEXACT | FE_UNDERFLOW); + TEST(FE_OVERFLOW | FE_UNDERFLOW); + + TEST(FE_INVALID | FE_DIVBYZERO | FE_INEXACT); + TEST(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); + TEST(FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW); + TEST(FE_INVALID | FE_INEXACT | FE_OVERFLOW); + TEST(FE_INVALID | FE_INEXACT | FE_UNDERFLOW); + TEST(FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT | FE_UNDERFLOW); + TEST(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); + TEST(FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW); + + TEST(FE_INVALID | FE_DIVBYZERO | FE_INEXACT | FE_UNDERFLOW); + TEST(FE_INVALID | FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW); + TEST(FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW); + TEST(FE_INVALID | FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c b/gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c new file mode 100644 index 000000000000..56ffc50e3ee3 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-lm -fno-builtin" } */ + +/* This testcase ensures that the builtins is correctly expanded and match the + expected result from the standard function. + "-fno-builtin" option is used to enable calls to libc implementation of the + gcc builtins tested when not using __builtin_ prefix. */ + +#include + +#ifdef DEBUG +#include +#define FAIL(v, e) printf("ERROR, __builtin_fegetround() returned %d," \ + " not the expecected value %d\n", v, e); +#else +void abort (void); +#define FAIL(v, e) abort() +#endif + +int +main () +{ + int i, rounding, expected; + const int rm[] = {FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD}; + for (i = 0; i < sizeof rm / sizeof rm[0]; i++) + { + fesetround(rm[i]); + rounding = __builtin_fegetround(); + expected = fegetround(); + if (rounding != expected) + FAIL(rounding, expected); + } + + return 0; +}