From patchwork Sun Sep 26 20:37:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Sayle X-Patchwork-Id: 45452 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 597303857C75 for ; Sun, 26 Sep 2021 20:38:17 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from server.nextmovesoftware.com (server.nextmovesoftware.com [162.254.253.69]) by sourceware.org (Postfix) with ESMTPS id E92513858C60 for ; Sun, 26 Sep 2021 20:37:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E92513858C60 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=nextmovesoftware.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nextmovesoftware.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nextmovesoftware.com; s=default; h=Content-Type:MIME-Version:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=CQ1vBLbp4+oFd2vZOT3zNO8kigLmIa/VvWE1YRQ/3Jk=; b=Q9QtbTCaZcpZ2pdaHrvmgZ56Pj 96Uix1cI4uhgW3sCLsHcFwNXG3KgExjR+Xo+3RMzQe+IDC8nFcFnDo2wZPriS3viQyAa6XAHYJLGK hft7UVdpjK0iJmh+2nGN5WhjtztmQ3CGdyZEprU/iWTvWFX7Hokeiyr8zUsm/tJWydCTCUhaMgwb9 JWRq7vuUd0pSJyheJOGfpu2eBVadFcnh1bV7aTc+s4muo3SYmZ4cPjZWX/cdj7MhzttMkxAEgVl8z eLqMqOhWUdnTqGTS16TFTzcYyNeYkRXxR54jYoangoAFElxsufF5+e4nxbX7zcU1ZiL8MPOo+SzEG QKocjoKQ==; Received: from host86-186-213-65.range86-186.btcentralplus.com ([86.186.213.65]:65383 helo=Dell) by server.nextmovesoftware.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1mUauM-00071N-VZ for gcc-patches@gcc.gnu.org; Sun, 26 Sep 2021 16:37:59 -0400 From: "Roger Sayle" To: "'GCC Patches'" Subject: [RFC] Experimental __attribute__((saturating)) on integer types. Date: Sun, 26 Sep 2021 21:37:52 +0100 Message-ID: <008b01d7b316$63e54060$2bafc120$@nextmovesoftware.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 thread-index: AdezFadvTRVXz43cSLeqUWVdfZXMEw== Content-Language: en-gb X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server.nextmovesoftware.com X-AntiAbuse: Original Domain - gcc.gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - nextmovesoftware.com X-Get-Message-Sender-Via: server.nextmovesoftware.com: authenticated_id: roger@nextmovesoftware.com X-Authenticated-Sender: server.nextmovesoftware.com: roger@nextmovesoftware.com X-Source: X-Source-Args: X-Source-Dir: X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch is prototype proof-of-concept (and request for feedback) that touches the front-end, middle-end and backend. My recent patch to perform RTL constant folding of saturating arithmetic revealed how difficult it is to generate a (portable) test case for that functionality. This patch experiments with adding an "saturating" attribute to the C-family front-ends to set the TYPE_SATURATING flag on integer types, initially as a debugging/testing tool for the middle-end. GCC already contains logic during RTL expansion to emit [us]s_plus and [us]s_minus instructions via the standard named [us]ss{add,sub}3 optabs. Disappointingly, although the documentation for ssplus3 patterns implies this should work for arbitrary (i.e. integer) modes, the optab querying infrastructure (based on optabs.def) is currently limited to fixed-point modes. Hence the patch below contains a tweak to optabs.def. With both of the above pieces in place, GCC can now generate an ssaddsi3 instruction (such as the example provided for the nvptx backend), or ICE if the required saturating operation doesn't exist, as libgcc doesn't (yet) provide fall-back implementations for saturating signed and unsigned arithmetic. Sticking with the positive, the following code: typedef int sat_int32 __attribute__ ((saturating)); int ssadd32(int x, int y) { sat_int32 t = (sat_int32)x + (sat_int32)y; return (int)t; } with this patch, now generates the following on nvptx-none: mov.u32 %r23, %ar0; mov.u32 %r24, %ar1; add.sat.s32 %value, %r23, %r24; Are any of the independent chunks below suitable for the compiler? Tested on nvptx-none and x86_64-pc-linux-gnu, but nothing changes unless __attribute__ ((saturating)) is explicitly added to the source code [and I'd recommend against that except for testing purposes]. Eventually saturating arithmetic such as this might be useful for kernel security (a hot topic of last week's Linux Plumbers' Conference) but it would require a lot of polishing to clean-up the rough edges (and ideally better hardware support). Thoughts? Even if a new C-family attribute is unsuitable, is my logic/implementation in handle_saturating_attribute correct? 2021-09-26 Roger Sayle gcc/c-family/ChangeLog * c-attribs (handle_saturating_attribute): New callback function for a "saturating" attribute to set the TYPE_SATURATING flag on an integer type. (c_common_attribute_table): New entry for "saturating". gcc/ChangeLog * config/nvptx/nvptx.md (ssaddsi3, sssubsi3): New define_insn patterns for SImode saturating addition/subtraction respectively. * optabs.def (ssadd_optab, usadd_optab, ssub_optab, usub_optab): Allow querying of integer modes in addition to fixed-point modes. * print-tree.c (print_node): Output "saturating" when the TYPE_SATURATING flag is set on integer types. Roger diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 007b928..cd58605 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -169,6 +169,7 @@ static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *); static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int, bool *); static tree handle_retain_attribute (tree *, tree, tree, int, bool *); +static tree handle_saturating_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -536,6 +537,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_special_var_sec_attribute, attr_section_exclusions }, { "access", 1, 3, false, true, true, false, handle_access_attribute, NULL }, + { "saturating", 0, 0, false, true, false, false, + handle_saturating_attribute, NULL }, /* Attributes used by Objective-C. */ { "NSObject", 0, 0, true, false, false, false, handle_nsobject_attribute, NULL }, @@ -5761,6 +5764,27 @@ handle_objc_nullability_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle a "saturating" attribute. */ + +static tree +handle_saturating_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int flags, bool *no_add_attrs) +{ + tree type = *node; + + *no_add_attrs = true; + + if (TREE_CODE (type) == INTEGER_TYPE) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = type = build_duplicate_type (type); + TYPE_SATURATING (type) = 1; + } + else + warning (OPT_Wattributes,"saturating attribute on non-integer type"); + return NULL_TREE; +} + /* Attempt to partially validate a single attribute ATTR as if it were to be applied to an entity OPER. */ diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 108de1c..79fa300 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -1217,6 +1217,22 @@ return asms[INTVAL (operands[2])]; }) +;; Saturating integer arithmetic + +(define_insn "ssaddsi3" + [(set (match_operand:SI 0 "nvptx_register_operand" "=R") + (ss_plus:SI (match_operand:SI 1 "nvptx_register_operand" "R") + (match_operand:SI 2 "nvptx_nonmemory_operand" "Ri")))] + "" + "%.\\tadd.sat.s32\\t%0, %1, %2;") + +(define_insn "sssubsi3" + [(set (match_operand:SI 0 "nvptx_register_operand" "=R") + (ss_minus:SI (match_operand:SI 1 "nvptx_register_operand" "R") + (match_operand:SI 2 "nvptx_register_operand" "R")))] + "" + "%.\\tsub.sat.s32\\t%0, %1, %2;") + ;; Miscellaneous (define_insn "nop" diff --git a/gcc/optabs.def b/gcc/optabs.def index 201b8aa..7d157ad 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -106,14 +106,18 @@ OPTAB_NX(add_optab, "add$Q$a3") OPTAB_VL(addv_optab, "addv$I$a3", PLUS, "add", '3', gen_intv_fp_libfunc) OPTAB_VX(addv_optab, "add$F$a3") OPTAB_NL(ssadd_optab, "ssadd$Q$a3", SS_PLUS, "ssadd", '3', gen_signed_fixed_libfunc) +OPTAB_NX(ssadd_optab, "ssadd$I$a3") OPTAB_NL(usadd_optab, "usadd$Q$a3", US_PLUS, "usadd", '3', gen_unsigned_fixed_libfunc) +OPTAB_NX(usadd_optab, "usadd$I$a3") OPTAB_NL(sub_optab, "sub$P$a3", MINUS, "sub", '3', gen_int_fp_fixed_libfunc) OPTAB_NX(sub_optab, "sub$F$a3") OPTAB_NX(sub_optab, "sub$Q$a3") OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc) OPTAB_VX(subv_optab, "sub$F$a3") OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc) +OPTAB_NX(sssub_optab, "sssub$I$a3") OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc) +OPTAB_NX(sssub_optab, "ussub$I$a3") OPTAB_NL(smul_optab, "mul$Q$a3", MULT, "mul", '3', gen_int_fp_fixed_libfunc) OPTAB_NX(smul_optab, "mul$P$a3") OPTAB_NX(smul_optab, "mul$F$a3") diff --git a/gcc/print-tree.c b/gcc/print-tree.c index d1fbd04..d0e135e 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -620,6 +620,10 @@ print_node (FILE *file, const char *prefix, tree node, int indent, && TYPE_REVERSE_STORAGE_ORDER (node)) fputs (" reverse-storage-order", file); + if (code == INTEGER_TYPE + && TYPE_SATURATING (node)) + fputs(" saturating", file); + if ((code == RECORD_TYPE || code == UNION_TYPE) && TYPE_CXX_ODR_P (node))