Message ID | patch-16259-tamar@arm.com |
---|---|
State | New, archived |
Headers |
Return-Path: <gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp120772wrt; Fri, 23 Sep 2022 02:20:15 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4xcFlm7FOEA9mzRqFSrLDa3V8/irgvdYwp8ntwjuWfJnUniogpQsxihAMzQnbinTJ/0u0z X-Received: by 2002:a17:907:2d91:b0:782:7301:6602 with SMTP id gt17-20020a1709072d9100b0078273016602mr4165648ejc.107.1663924815186; Fri, 23 Sep 2022 02:20:15 -0700 (PDT) Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id t3-20020a056402524300b004485508bcfbsi8539260edd.30.2022.09.23.02.20.14 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Sep 2022 02:20:15 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=mGd6SHX0; arc=fail (signature failed); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D1519385781D for <ouuuleilei@gmail.com>; Fri, 23 Sep 2022 09:20:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D1519385781D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663924813; bh=VIkzliJbhwjGR9BrQASKlQiJmAocHzgybj0GsBDKuoY=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=mGd6SHX0kz8Gua/Iw2Et/YLkSUEOniEgkiZ9if7rEonElrUhtGqTroqWzKXTcKFnl IVgKSzW6okhoR0FqRYwC2CIdvsZEY21bxiKK/IJP06yLyNL5b1CFD65gbvSbR9j5uf +DsdKovdnxWxTZHxQYYEcr6kE3OPGBurXJk3qzK8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from EUR03-DBA-obe.outbound.protection.outlook.com (mail-dbaeur03on2074.outbound.protection.outlook.com [40.107.104.74]) by sourceware.org (Postfix) with ESMTPS id 3352D385828B for <gcc-patches@gcc.gnu.org>; Fri, 23 Sep 2022 09:19:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3352D385828B ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=gl1GrCrwT0HaauFbsJtcezQzZuHZCkdfZk4rH0tWOxKxhMUszUk2xGoL7IRS1kkpMtt5hmsXvooqCbcIIdCk5Bo7Hy6YBT8CG5Si4295rJkfPZLQz5CH4a5HdRVYKsDBFo0RO9VVb5sJVHUZ6MyFh1nW7mSY+s4MKYy0zVNB8i+IOyEWUxMkmGzvWg7BVhJrqiEyxiK2HgNSyLuCUBnoNzVjD1Zi4UkeUrVtP2evPDHp0oTPD+QNDD+lqpJhlbhbpMZ8ByNzzTW8aB0SHeWrG6DaEIWViJ5Dsa1KoNzQWrcATui9nY0AqABwxM/XiSHgjTv6xJcctvWfjBUtC9AC0A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=VIkzliJbhwjGR9BrQASKlQiJmAocHzgybj0GsBDKuoY=; b=XvmSko7p2frbUdPkD0nDyExORxHkHhC8qbn6N1mKIJ5VUHj5yaGA7kA64kVlExXUt7yOUMGA2OtiOFplLjclDCrJ3LhkWj/ADYhUXClx+N3kqohICdJXm3N9uosFQ+xc+yl/ZZO3g5oyB2/GITavBbcKGm25eOLGFnOJPg9ehfpdsYynwfkYou80DSxeAR7IUQHRhR+zGL3ZUFzoT0QvynBi1nrtXpJXA4aIJDLDuc0UIqn45kI9maRXq/wY9QlHHxluey4RSLNGd6EYfQZoE/KEqaWY66i2mutKYMZ7PFlQ2125jig0bCsadyeWdNyEXqTgx/u1r3/sWdVJTgVRfQ== ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 63.35.35.123) smtp.rcpttodomain=gcc.gnu.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=arm.com] dkim=[1,1,header.d=arm.com] dmarc=[1,1,header.from=arm.com]) Received: from DU2PR04CA0030.eurprd04.prod.outlook.com (2603:10a6:10:3b::35) by DU0PR08MB9680.eurprd08.prod.outlook.com (2603:10a6:10:444::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5654.16; Fri, 23 Sep 2022 09:19:21 +0000 Received: from DBAEUR03FT044.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:3b:cafe::af) by DU2PR04CA0030.outlook.office365.com (2603:10a6:10:3b::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5654.20 via Frontend Transport; Fri, 23 Sep 2022 09:19:21 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DBAEUR03FT044.mail.protection.outlook.com (100.127.142.189) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5654.14 via Frontend Transport; Fri, 23 Sep 2022 09:19:21 +0000 Received: ("Tessian outbound 0a0431bdcdb4:v124"); Fri, 23 Sep 2022 09:19:21 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 0aa4c897fc2cdbf5 X-CR-MTA-TID: 64aa7808 Received: from 6c0dfce68c84.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id B45226D1-E605-478D-A2F7-666E6F03EA7C.1; Fri, 23 Sep 2022 09:18:21 +0000 Received: from EUR01-VE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 6c0dfce68c84.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Fri, 23 Sep 2022 09:18:21 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=dfzdpDC24yRAX4CxCuJmf91UBm8KIkKcdEtzUwXIFphNwy4ZYxgMgUzz+dhgbB+P3sn4f0QQ47Wy9Ne//ufLn9V/fO8iY/hD3j+ytWejR0NIJ1I09NrMMm7psz/zAJBXFg5Z64D2bI1xn5oxTDuHwMfkjqNeb9dfiuYbHY+ksy9gKo0ZW0KvZJ13KIdhSpliI97vszG+RE8QOKT+UBKaHejfhmFf1zYOYKRAwp7n3MvYkaGhXzetb1uJwWlONat0Mu2d5ndxWHhjzt2gkCUisXdPEDKBXLRRWNiA6F/1e5ZFrJLJ807nBV0Eo8/GLwaTE3B4ICZbTkt34ontL6giYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=VIkzliJbhwjGR9BrQASKlQiJmAocHzgybj0GsBDKuoY=; b=m5kIQYLFkq5zCJ8m0RgKwpybt0ObjSjsy1HHLvyCblP2XKqKA8PtyddjHiKkQF+EocMDboF0iZ7Zf2PMaEq1KZLJcdl+RVvNH0p/qXtaZ75M5xx+PV0jpTxmRoj6lFpv22iwsaeT9hg2wWLfB5PMjKqoo4NtS4TwA+5of2jKuDbWczGbcWuEAiSQtXWFxtt/41srUYQbvVnu0ZDc5QzrHjAvZqnJ2F5epz+P5c/mmvMez4X0b/gN7N+u6aocprRTXBxgtwaGpAKwkc5hgLQFZmcFeGoTCmb8B+DCUAK8jpi2nJubAZ3b+4QpPQrnqWgxzk3bDYBbiL10k+jyFz0neg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from VI1PR08MB5325.eurprd08.prod.outlook.com (2603:10a6:803:13e::17) by DU0PR08MB8113.eurprd08.prod.outlook.com (2603:10a6:10:3e9::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5632.18; Fri, 23 Sep 2022 09:18:18 +0000 Received: from VI1PR08MB5325.eurprd08.prod.outlook.com ([fe80::6529:66e5:e7d4:1a40]) by VI1PR08MB5325.eurprd08.prod.outlook.com ([fe80::6529:66e5:e7d4:1a40%4]) with mapi id 15.20.5632.021; Fri, 23 Sep 2022 09:18:17 +0000 Date: Fri, 23 Sep 2022 10:18:14 +0100 To: gcc-patches@gcc.gnu.org Subject: [PATCH]middle-end Recognize more conditional comparisons idioms. Message-ID: <patch-16259-tamar@arm.com> Content-Type: multipart/mixed; boundary="a4OQZmT44pT8FGRk" Content-Disposition: inline X-ClientProxiedBy: LO2P265CA0350.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:d::26) To VI1PR08MB5325.eurprd08.prod.outlook.com (2603:10a6:803:13e::17) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: VI1PR08MB5325:EE_|DU0PR08MB8113:EE_|DBAEUR03FT044:EE_|DU0PR08MB9680:EE_ X-MS-Office365-Filtering-Correlation-Id: 6e618b2f-b652-459a-0fff-08da9d44b350 x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: hf7iovnd08s/zF0Cbr/YEYaVhUNO08KPj90r3GH+9eemaoR+5SVnyY9wCVrnSaQlqG+aQ0Z834KgFE+pn42DRLpfbkFsvIeC5U9tBBuKwBqWzRcrEdTx9m4ppwuiZBBOpa48eAONHENaxn8F980C93tak3PF5Z7R5yxlIAyqZtu1+/niVvb+d4bo4u+zoCNZs8whNrYG3ZRt+Epx4/J2UBUCBuFK0pmy48pcydnqOqxlZLxDJoHMUfxXfFCTWbZYTlzT4LKTpk46hJ/iUAQrGD4+6RO0NENGEFK4V5cXsHnljJjs9m8UCLWyvtY9ABza7+cy1TkuzsPiuqEwiuNbi+5f//7Ea3fa3cMijou9zRmKmh5o67N0ZCAvrZxeKTy7MELxqst6IQhnkzSpZWU/xcHDe+FtGnZK6LRffniwqPSpHTP3zCNsno1XdKZ4MK32BB+FFFoRwD0yTwV0hjINNxo7A1cVnmxQr98HMYnQyGCYtesEIiy6YsLp1ju2ez3sArcAA1NAEaBEsqbL4GiSAuViRebAAAcUV8WKgDEDCLcjGVXULxhCIZYEDzLxgK44OOi5IogQijtcXOUGrnrzSa4tR6bHTAQgL//F4Ot5ZLnx2DXpOc5HdLB4OxpWsal/K4I7NGyuIycYSC8v1B1ZckKUYjncjH8H6q2J4bZr18SqQKgp+nO73gB3afDzodF02/LrlhBPaYzqx+/8VZzV0J6zL7JhmK3S471m7D2ZPgoApKsUWggWqMd0j5JCF2Nnp/auMc4bUbK6LdSYV6B3iW6gMtfVbvjZaf76EJPCqRTUZz/Wm2fVd+VzuDB6ME2zKUIYTkV6NAVAwVBbdCLgsvTxgSlYDb2mBwngD+Hs0A0= X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR08MB5325.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230022)(4636009)(39860400002)(346002)(136003)(366004)(376002)(396003)(451199015)(316002)(26005)(6512007)(66899012)(33964004)(44144004)(41300700001)(38100700002)(6666004)(235185007)(44832011)(66946007)(2616005)(5660300002)(66476007)(66556008)(84970400001)(8676002)(4326008)(478600001)(6506007)(36756003)(6486002)(86362001)(2906002)(186003)(8936002)(83380400001)(6916009)(4216001)(2700100001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DU0PR08MB8113 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DBAEUR03FT044.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 72a84c0b-9b12-4acc-1c04-08da9d448cfc X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: WV9A4xyKoOEHY2pgOq4F1klC+rOLU46uh/Xay7Hqk+jqkisEnI5hO31D400VJjSypDl6GIn7oxsg0GUHtl51pISbw/RxYG1CPTc96CnW30YDSBEF3ffonoqTq5ZegEL07gReQ5hLnHBBlZQkxeQkt1ia1NvrheVpP9W1aViCCP+vnx89sGa9Kn1XPCp5aqO1+BkUf96QvrSNENdTc2STo1/MeFb85gIHbQnr6RXlbf1CotGlFlFDOJlV/zbVtXsaiERwCscjkNN5ja8MKIGUlH8x38w7Y+HvwlAm8b7VJm64AKc3v3QuOlJwdFPtZwDNIFExHJ0Yf89IawJgWAtCW34mXm/uE+goccMUBJYcgXzW1J/Hk0BWjtkTwrR9eJeQ/1T57RhkqOyqdYMO6IUEalFeIfLSNSrHctzzNaGngW7Qxw7+8C6tOvGCsvpu/46GH2ATtzfiwj1jOca4sTfUil8f1U/uotiLlVg18GKVPVmyCnpKRj0HATzekMuxrwOEpH07GCV7ZM8TV4KH659KkoqJSjX6ytLoxLLBTKKeo5HMp1W5hACwJ5l3P68CRPP7loeAGWYTznNeSDHfj14w9miUY8eMD9h0M5prp7R9t8ntpjvyNsbFE+T93kiH7tJWHbmSxw/TK+yEDyHRW4O7yInsIYUoVm5AjKXFbmxjM/KC5xeOhRQLohEpGrt51LwqvLslnQPc2bYbrLg8kLY0im9uStpNjEaFx3V76o/ER7hy2dgzqMhcHaL2Vp0M1RmLPiFqXLTTNBSD9JfiteF0yTHkl6zaKgaDV1rYU4jeGHxe48OeEdwEqC2tXuq7JU8a4PLEPKTYwGblSbfT6cJAQEtf9KoMT9x6nTmC8QCGw2zQYfm9jKKn4ojo67n+oBau/f+40BQYUg7T/cfzxVE+Tw== X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230022)(4636009)(376002)(39860400002)(136003)(396003)(346002)(451199015)(36840700001)(46966006)(40470700004)(86362001)(6506007)(33964004)(336012)(82310400005)(186003)(83380400001)(40480700001)(2616005)(82740400003)(47076005)(107886003)(44144004)(6666004)(6512007)(41300700001)(36860700001)(26005)(66899012)(84970400001)(36756003)(81166007)(40460700003)(356005)(4326008)(44832011)(8936002)(8676002)(6916009)(5660300002)(70206006)(235185007)(316002)(2906002)(6486002)(70586007)(478600001)(4216001)(2700100001); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Sep 2022 09:19:21.7895 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6e618b2f-b652-459a-0fff-08da9d44b350 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: DBAEUR03FT044.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DU0PR08MB9680 X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_DMARC_NONE, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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 <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Tamar Christina via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Tamar Christina <tamar.christina@arm.com> Cc: nd@arm.com, rguenther@suse.de Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org> X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1744751627126149497?= X-GMAIL-MSGID: =?utf-8?q?1744751627126149497?= |
Series |
middle-end Recognize more conditional comparisons idioms.
|
|
Commit Message
Tamar Christina
Sept. 23, 2022, 9:18 a.m. UTC
Hi All, GCC currently recognizes some of these for signed but not unsigned types. It also has trouble dealing with casts in between because these are handled by the fold machinery. This moves the pattern detection to match.pd instead. We fold e.g.: uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { uint32_t result; uint32_t m = (a >= b) - 1; result = (c & m) | (d & ~m); return result; } into a >= b ? c : d for all integral types. Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/ChangeLog: * match.pd: New cond select pattern. gcc/testsuite/ChangeLog: * gcc.dg/select_cond_1.c: New test. * gcc.dg/select_cond_2.c: New test. * gcc.dg/select_cond_3.c: New test. --- inline copy of patch -- diff --git a/gcc/match.pd b/gcc/match.pd index 39da61bf117a6eb2924fc8a6473fb37ddadd60e9..7b8f50410acfd0afafc5606e972cfc4e125d3a5d 100644 -- diff --git a/gcc/match.pd b/gcc/match.pd index 39da61bf117a6eb2924fc8a6473fb37ddadd60e9..7b8f50410acfd0afafc5606e972cfc4e125d3a5d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3577,6 +3577,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) (max @2 @1)) +/* (a & ((c `op` d) - 1)) | (b & ~((c `op` d) - 1)) -> c `op` d ? a : b. */ +(for op (simple_comparison) + (simplify + (bit_xor:c + (convert2? @0) + (bit_and:c + (convert2? (bit_xor:c @1 @0)) + (convert3? (negate (convert? (op@4 @2 @3)))))) + /* Alternative form, where some canonicalization were not done due to the + arguments being signed. */ + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) + (convert:type (cond @4 @1 @0)))) + (simplify + (bit_ior:c + (mult:c @0 (convert (convert2? (op@4 @2 @3)))) + (bit_and:c @1 (convert (plus:c integer_minus_onep (convert (op@4 @2 @3)))))) + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) + (cond @4 @0 @1)))) + /* Simplifications of shift and rotates. */ (for rotate (lrotate rrotate) diff --git a/gcc/testsuite/gcc.dg/select_cond_1.c b/gcc/testsuite/gcc.dg/select_cond_1.c new file mode 100644 index 0000000000000000000000000000000000000000..9eb9959baafe5fffeec24e4e3ae656f8fcfe943c --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_1.c @@ -0,0 +1,97 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a <= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a > b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a < b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a == b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a != b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} 6 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max1_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min1_32u (5, 3, 7 , 8) != 8) + abort (); + + if (max1_32u (5, 3, 7 , 8) != 7) + abort (); + + if (min2_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max2_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min2_32u (5, 3, 7 , 8) != 8) + abort (); + + if (max2_32u (5, 3, 7 , 8) != 7) + abort (); + + if (min3_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max3_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min3_32u (5, 3, 7 , 8) != 7) + abort (); + + if (max3_32u (5, 3, 7 , 8) != 8) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/select_cond_2.c b/gcc/testsuite/gcc.dg/select_cond_2.c new file mode 100644 index 0000000000000000000000000000000000000000..623b2272ee7b4b00130d5e9fb8c781dbc5d4189e --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_2.c @@ -0,0 +1,99 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +uint32_t min1_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max1_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a <= b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min2_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a > b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max2_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a < b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min3_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a == b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max3_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a != b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-not {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} "optimized" } } */ +/* { dg-final { scan-tree-dump-times {MIN_EXPR} 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {MAX_EXPR} 2 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u (7 , 8) != 7) + abort (); + + if (max1_32u (7 , 8) != 8) + abort (); + + if (min1_32u (7 , 8) != 7) + abort (); + + if (max1_32u (7, 8) != 8) + abort (); + + if (min2_32u (7 , 8) != 7) + abort (); + + if (max2_32u (7 , 8) != 8) + abort (); + + if (min2_32u (7 , 8) != 7) + abort (); + + if (max2_32u (7 , 8) != 8) + abort (); + + if (min3_32u (7 , 8) != 7) + abort (); + + if (max3_32u (7 , 8) != 8) + abort (); + + if (min3_32u (7 , 8) != 7) + abort (); + + if (max3_32u (7 , 8) != 8) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/select_cond_3.c b/gcc/testsuite/gcc.dg/select_cond_3.c new file mode 100644 index 0000000000000000000000000000000000000000..754e73b121ce360564481b1fa7e1dd4fb27642a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_3.c @@ -0,0 +1,101 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +int32_t min1_32u1(int32_t a, int32_t b, int32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u2(uint32_t a, uint32_t b, int32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u3(uint32_t a, uint32_t b, uint32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u4(uint32_t a, uint32_t b, int32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u5(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u6(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u7(uint8_t a, uint16_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u8(uint32_t a, uint64_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c[^ ]+ : d[^ ]+;} 8 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u1 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u2 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u3 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u4 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u5 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u6 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u7 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u8 (3, 5, 7 , 8) != 7) + abort (); + + return 0; +}
Comments
On Fri, 23 Sep 2022, Tamar Christina wrote: > Hi All, > > GCC currently recognizes some of these for signed but not unsigned types. > It also has trouble dealing with casts in between because these are handled > by the fold machinery. > > This moves the pattern detection to match.pd instead. where's the other copy and is it possible to remove it with this patch? > We fold e.g.: > > uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > uint32_t result; > uint32_t m = (a >= b) - 1; > result = (c & m) | (d & ~m); > return result; > } > > into a >= b ? c : d for all integral types. > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > > Ok for master? > > Thanks, > Tamar > > gcc/ChangeLog: > > * match.pd: New cond select pattern. > > gcc/testsuite/ChangeLog: > > * gcc.dg/select_cond_1.c: New test. > * gcc.dg/select_cond_2.c: New test. > * gcc.dg/select_cond_3.c: New test. > > --- inline copy of patch -- > diff --git a/gcc/match.pd b/gcc/match.pd > index 39da61bf117a6eb2924fc8a6473fb37ddadd60e9..7b8f50410acfd0afafc5606e972cfc4e125d3a5d 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -3577,6 +3577,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) > (max @2 @1)) > > +/* (a & ((c `op` d) - 1)) | (b & ~((c `op` d) - 1)) -> c `op` d ? a : b. */ > +(for op (simple_comparison) > + (simplify > + (bit_xor:c > + (convert2? @0) > + (bit_and:c > + (convert2? (bit_xor:c @1 @0)) > + (convert3? (negate (convert? (op@4 @2 @3)))))) I have a hard time matching this up with the comment above. It looks like (T2)@0 ^ ((T2)(@1 ^ @0) & (T3)(-(T)(@2 <=> @3)) I suppose we've canonicalized (a & x) | (b & ~x) somehow. It also looks like we move coversions inside a negate but not outside or into a bit_and? Can we do a better job here to avoid the explosions in the number of patterns? > + /* Alternative form, where some canonicalization were not done due to the > + arguments being signed. */ these two comment lines belong ... > + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) > + (convert:type (cond @4 @1 @0)))) ... here? > + (simplify > + (bit_ior:c > + (mult:c @0 (convert (convert2? (op@4 @2 @3)))) > + (bit_and:c @1 (convert (plus:c integer_minus_onep (convert (op@4 @2 @3)))))) can you add a comment with what you match here as well? You are using (op@4 @2 @3) twice, the point of the @4 capture is that the second occurance could be just @4. I wonder how we arrived at the multiplication here? That seems somewhat premature :/ Thanks, Richard. > + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) > + (cond @4 @0 @1)))) > + > /* Simplifications of shift and rotates. */ > > (for rotate (lrotate rrotate) > diff --git a/gcc/testsuite/gcc.dg/select_cond_1.c b/gcc/testsuite/gcc.dg/select_cond_1.c > new file mode 100644 > index 0000000000000000000000000000000000000000..9eb9959baafe5fffeec24e4e3ae656f8fcfe943c > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/select_cond_1.c > @@ -0,0 +1,97 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ > + > +#include <stdint.h> > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a <= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a > b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a < b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a == b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a != b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} 6 "optimized" } } */ > + > +extern void abort (); > + > +int main () { > + > + if (min1_32u (3, 5, 7 , 8) != 7) > + abort (); > + > + if (max1_32u (3, 5, 7 , 8) != 8) > + abort (); > + > + if (min1_32u (5, 3, 7 , 8) != 8) > + abort (); > + > + if (max1_32u (5, 3, 7 , 8) != 7) > + abort (); > + > + if (min2_32u (3, 5, 7 , 8) != 7) > + abort (); > + > + if (max2_32u (3, 5, 7 , 8) != 8) > + abort (); > + > + if (min2_32u (5, 3, 7 , 8) != 8) > + abort (); > + > + if (max2_32u (5, 3, 7 , 8) != 7) > + abort (); > + > + if (min3_32u (3, 5, 7 , 8) != 7) > + abort (); > + > + if (max3_32u (3, 5, 7 , 8) != 8) > + abort (); > + > + if (min3_32u (5, 3, 7 , 8) != 7) > + abort (); > + > + if (max3_32u (5, 3, 7 , 8) != 8) > + abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/select_cond_2.c b/gcc/testsuite/gcc.dg/select_cond_2.c > new file mode 100644 > index 0000000000000000000000000000000000000000..623b2272ee7b4b00130d5e9fb8c781dbc5d4189e > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/select_cond_2.c > @@ -0,0 +1,99 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ > + > +#include <stdint.h> > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max1_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a <= b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min2_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a > b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max2_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a < b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min3_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a == b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max3_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a != b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +/* { dg-final { scan-tree-dump-not {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} "optimized" } } */ > +/* { dg-final { scan-tree-dump-times {MIN_EXPR} 2 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times {MAX_EXPR} 2 "optimized" } } */ > + > +extern void abort (); > + > +int main () { > + > + if (min1_32u (7 , 8) != 7) > + abort (); > + > + if (max1_32u (7 , 8) != 8) > + abort (); > + > + if (min1_32u (7 , 8) != 7) > + abort (); > + > + if (max1_32u (7, 8) != 8) > + abort (); > + > + if (min2_32u (7 , 8) != 7) > + abort (); > + > + if (max2_32u (7 , 8) != 8) > + abort (); > + > + if (min2_32u (7 , 8) != 7) > + abort (); > + > + if (max2_32u (7 , 8) != 8) > + abort (); > + > + if (min3_32u (7 , 8) != 7) > + abort (); > + > + if (max3_32u (7 , 8) != 8) > + abort (); > + > + if (min3_32u (7 , 8) != 7) > + abort (); > + > + if (max3_32u (7 , 8) != 8) > + abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/select_cond_3.c b/gcc/testsuite/gcc.dg/select_cond_3.c > new file mode 100644 > index 0000000000000000000000000000000000000000..754e73b121ce360564481b1fa7e1dd4fb27642a3 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/select_cond_3.c > @@ -0,0 +1,101 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ > + > +#include <stdint.h> > + > +__attribute__((noipa, noinline)) > +int32_t min1_32u1(int32_t a, int32_t b, int32_t c, int32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u2(uint32_t a, uint32_t b, int32_t c, int32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u3(uint32_t a, uint32_t b, uint32_t c, int32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u4(uint32_t a, uint32_t b, int32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u5(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u6(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + int32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u7(uint8_t a, uint16_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + int32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u8(uint32_t a, uint64_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + int32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c[^ ]+ : d[^ ]+;} 8 "optimized" } } */ > + > +extern void abort (); > + > +int main () { > + > + if (min1_32u1 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u2 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u3 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u4 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u5 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u6 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u7 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u8 (3, 5, 7 , 8) != 7) > + abort (); > + > + return 0; > +} > > > > >
> > This moves the pattern detection to match.pd instead. > > where's the other copy and is it possible to remove it with this patch? > It looks like it's spread over various passes. Starting with forwardprop. > > > + (simplify > > + (bit_ior:c > > + (mult:c @0 (convert (convert2? (op@4 @2 @3)))) > > + (bit_and:c @1 (convert (plus:c integer_minus_onep (convert (op@4 > > + @2 @3)))))) > > can you add a comment with what you match here as well? You are using > (op@4 @2 @3) twice, the point of the @4 capture is that the second > occurance could be just @4. I wonder how we arrived at the multiplication > here? That seems somewhat premature :/ That's being done by forwardprop. To remove the various converts I broke down the operations into several Smaller steps that on their own are sound optimizations. When taken all together it reduced the versions with casts down to the final optimized version. Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/ChangeLog: * match.pd: New cond select pattern. (inverted_simple_comparison): New. gcc/testsuite/ChangeLog: * gcc.dg/select_cond_1.c: New test. * gcc.dg/select_cond_2.c: New test. * gcc.dg/select_cond_3.c: New test. --- inline copy of patch --- diff --git a/gcc/match.pd b/gcc/match.pd index 45f8941396ffd843f1bb23ab638c3b8c6d0d54b6..84d931c5d559ef1a605ea1121fbe655fcf870195 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -51,8 +51,9 @@ along with GCC; see the file COPYING3. If not see unge ungt ne eq unlt unle ordered unordered ge gt le lt ltgt uneq) (define_operator_list swapped_tcc_comparison gt ge eq ne le lt unordered ordered ungt unge unlt unle uneq ltgt) -(define_operator_list simple_comparison lt le eq ne ge gt) -(define_operator_list swapped_simple_comparison gt ge eq ne le lt) +(define_operator_list simple_comparison lt le eq ne ge gt) +(define_operator_list inverted_simple_comparison ge gt ne eq lt le) +(define_operator_list swapped_simple_comparison gt ge eq ne le lt) #include "cfn-operators.pd" @@ -2081,7 +2082,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!canonicalize_math_p ()) (for cmp (gt lt ge le) (simplify - (mult (convert (cmp @0 @1)) @2) + (mult:c (convert (cmp @0 @1)) @2) (cond (cmp @0 @1) @2 { build_zero_cst (type); })))) /* For integral types with undefined overflow and C != 0 fold @@ -3551,6 +3552,63 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) (max @2 @1)) +/* (a & ((c `cmp` d) - 1)) | (b & ~((c `cmp` d) - 1)) -> c `cmp` d ? a : b. + by matching the canonicanized xor form. This relies on: 0 ^ a == a and + (a ^ b) ^ a == b. So (((a ^ b) & -((unsigned T)(c `cmp` d))) ^ b) into + c `cmp` d ? a : b. */ +(for cmp (simple_comparison) + icmp (inverted_simple_comparison) + (simplify + (bit_xor:c + @0 + (bit_and:c + (bit_xor:c @1 @0) + (negate (cmp@4 @2 @3)))) + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) + (convert:type (cond @4 @1 @0)))) + /* ((unsigned T)(((signed T) (a `cmp` b)) + -1)) -> a `icmp` b ? -1 : 0. */ + (simplify + (convert (plus:c integer_minus_onep (convert2?@1 (cmp@2 @3 @4)))) + (if (tree_zero_one_valued_p (@2) + && INTEGRAL_TYPE_P (type) + && TYPE_UNSIGNED (type) + && !TYPE_UNSIGNED (TREE_TYPE (@1)) + && useless_type_conversion_p (unsigned_type_for (TREE_TYPE (@1)), type)) + (cond (icmp @3 @4) { build_all_ones_cst (type); } + { build_zero_cst (type); }))) + /* ((-(unsigned T)(a `cmp` b)) & c) -> a `cmp` b ? c : 0. */ + (simplify + (bit_and:c + (convert2?@5 (negate@4 (convert (cmp@0 @1 @2)))) @3) + (if (tree_zero_one_valued_p (@0) + && INTEGRAL_TYPE_P (type) + && TYPE_UNSIGNED (TREE_TYPE (@4)) + && useless_type_conversion_p (unsigned_type_for (TREE_TYPE (@5)), + TREE_TYPE (@4))) + (cond (cmp @1 @2) @3 { build_zero_cst (type); }))) + /* (a `cmp` b) ? d : (a `icmp` b) ? c : e -> a `cmp` b ? d : c. */ + (simplify + (cond (cmp@0 @1 @2) @4 + (cond (icmp @1 @2) @3 @5)) + (cond @0 @4 @3)) + + /* (a `cmp` b) ? ((a `icmp` b) ? <dead> : c) : d -> a `cmp` b ? c : d. */ + (simplify + (cond (cmp@0 @1 @2) + (cond (icmp @1 @2) @3 @4) @5) + (cond @0 @4 @5))) + +(for op (bit_ior bit_and bit_xor) + /* (a `op` (b ? 0 : c) -> b ? a `op` 0 : a `op` c + and (a `op` (b ? c : 0) -> b ? a `op` c : a `op` 0 + we only fold 0 because one operand is guaranteed to simplify. */ + (simplify + (op:c (cond @0 zerop@3 @1) @2) + (cond @0 (op @3 @2) (op @1 @2))) + (simplify + (op:c (cond @0 @1 zerop@3) @2) + (cond @0 (op @1 @2) (op @3 @2)))) + /* Simplifications of shift and rotates. */ (for rotate (lrotate rrotate) diff --git a/gcc/testsuite/gcc.dg/select_cond_1.c b/gcc/testsuite/gcc.dg/select_cond_1.c new file mode 100644 index 0000000000000000000000000000000000000000..9eb9959baafe5fffeec24e4e3ae656f8fcfe943c --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_1.c @@ -0,0 +1,97 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a <= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a > b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a < b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a == b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a != b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} 6 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max1_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min1_32u (5, 3, 7 , 8) != 8) + abort (); + + if (max1_32u (5, 3, 7 , 8) != 7) + abort (); + + if (min2_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max2_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min2_32u (5, 3, 7 , 8) != 8) + abort (); + + if (max2_32u (5, 3, 7 , 8) != 7) + abort (); + + if (min3_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max3_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min3_32u (5, 3, 7 , 8) != 7) + abort (); + + if (max3_32u (5, 3, 7 , 8) != 8) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/select_cond_2.c b/gcc/testsuite/gcc.dg/select_cond_2.c new file mode 100644 index 0000000000000000000000000000000000000000..623b2272ee7b4b00130d5e9fb8c781dbc5d4189e --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_2.c @@ -0,0 +1,99 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +uint32_t min1_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max1_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a <= b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min2_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a > b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max2_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a < b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min3_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a == b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max3_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a != b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-not {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} "optimized" } } */ +/* { dg-final { scan-tree-dump-times {MIN_EXPR} 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {MAX_EXPR} 2 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u (7 , 8) != 7) + abort (); + + if (max1_32u (7 , 8) != 8) + abort (); + + if (min1_32u (7 , 8) != 7) + abort (); + + if (max1_32u (7, 8) != 8) + abort (); + + if (min2_32u (7 , 8) != 7) + abort (); + + if (max2_32u (7 , 8) != 8) + abort (); + + if (min2_32u (7 , 8) != 7) + abort (); + + if (max2_32u (7 , 8) != 8) + abort (); + + if (min3_32u (7 , 8) != 7) + abort (); + + if (max3_32u (7 , 8) != 8) + abort (); + + if (min3_32u (7 , 8) != 7) + abort (); + + if (max3_32u (7 , 8) != 8) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/select_cond_3.c b/gcc/testsuite/gcc.dg/select_cond_3.c new file mode 100644 index 0000000000000000000000000000000000000000..80087d4a0bd37066dbd44335aa3d1bf13fe3fa95 --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_3.c @@ -0,0 +1,101 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +int32_t min1_32u1(int32_t a, int32_t b, int32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u2(uint32_t a, uint32_t b, int32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u3(uint32_t a, uint32_t b, uint32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u4(uint32_t a, uint32_t b, int32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u5(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u6(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u7(uint8_t a, uint16_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u8(uint32_t a, uint64_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? [^ ]+ : [^ ]+;} 8 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u1 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u2 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u3 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u4 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u5 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u6 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u7 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u8 (3, 5, 7 , 8) != 7) + abort (); + + return 0; +}
On Mon, 31 Oct 2022, Tamar Christina wrote: > > > This moves the pattern detection to match.pd instead. > > > > where's the other copy and is it possible to remove it with this patch? > > > > It looks like it's spread over various passes. Starting with forwardprop. Can you be more specific? If forwprop contains special pattern matching for these please extend that instead. > > > > > + (simplify > > > + (bit_ior:c > > > + (mult:c @0 (convert (convert2? (op@4 @2 @3)))) > > > + (bit_and:c @1 (convert (plus:c integer_minus_onep (convert (op@4 > > > + @2 @3)))))) > > > > can you add a comment with what you match here as well? You are using > > (op@4 @2 @3) twice, the point of the @4 capture is that the second > > occurance could be just @4. I wonder how we arrived at the multiplication > > here? That seems somewhat premature :/ > > That's being done by forwardprop. That's maybe the pass where the multiplication comes from but it's likely some match.pd pattern that triggers instead? > To remove the various converts I broke down the operations into several > Smaller steps that on their own are sound optimizations. When taken all > together it reduced the versions with casts down to the final optimized version. > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > > Ok for master? > > Thanks, > Tamar > > gcc/ChangeLog: > > * match.pd: New cond select pattern. > (inverted_simple_comparison): New. > > gcc/testsuite/ChangeLog: > > * gcc.dg/select_cond_1.c: New test. > * gcc.dg/select_cond_2.c: New test. > * gcc.dg/select_cond_3.c: New test. > > --- inline copy of patch --- > > diff --git a/gcc/match.pd b/gcc/match.pd > index 45f8941396ffd843f1bb23ab638c3b8c6d0d54b6..84d931c5d559ef1a605ea1121fbe655fcf870195 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -51,8 +51,9 @@ along with GCC; see the file COPYING3. If not see > unge ungt ne eq unlt unle ordered unordered ge gt le lt ltgt uneq) > (define_operator_list swapped_tcc_comparison > gt ge eq ne le lt unordered ordered ungt unge unlt unle uneq ltgt) > -(define_operator_list simple_comparison lt le eq ne ge gt) > -(define_operator_list swapped_simple_comparison gt ge eq ne le lt) > +(define_operator_list simple_comparison lt le eq ne ge gt) > +(define_operator_list inverted_simple_comparison ge gt ne eq lt le) > +(define_operator_list swapped_simple_comparison gt ge eq ne le lt) > > #include "cfn-operators.pd" > > @@ -2081,7 +2082,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (if (!canonicalize_math_p ()) > (for cmp (gt lt ge le) > (simplify > - (mult (convert (cmp @0 @1)) @2) > + (mult:c (convert (cmp @0 @1)) @2) > (cond (cmp @0 @1) @2 { build_zero_cst (type); })))) That looks OK. > /* For integral types with undefined overflow and C != 0 fold > @@ -3551,6 +3552,63 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) > (max @2 @1)) > > +/* (a & ((c `cmp` d) - 1)) | (b & ~((c `cmp` d) - 1)) -> c `cmp` d ? a : b. > + by matching the canonicanized xor form. This relies on: 0 ^ a == a and > + (a ^ b) ^ a == b. So (((a ^ b) & -((unsigned T)(c `cmp` d))) ^ b) into > + c `cmp` d ? a : b. */ > +(for cmp (simple_comparison) > + icmp (inverted_simple_comparison) > + (simplify > + (bit_xor:c > + @0 > + (bit_and:c > + (bit_xor:c @1 @0) > + (negate (cmp@4 @2 @3)))) > + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) > + (convert:type (cond @4 @1 @0)))) > + /* ((unsigned T)(((signed T) (a `cmp` b)) + -1)) -> a `icmp` b ? -1 : 0. */ > + (simplify > + (convert (plus:c integer_minus_onep (convert2?@1 (cmp@2 @3 @4)))) > + (if (tree_zero_one_valued_p (@2) > + && INTEGRAL_TYPE_P (type) > + && TYPE_UNSIGNED (type) > + && !TYPE_UNSIGNED (TREE_TYPE (@1)) > + && useless_type_conversion_p (unsigned_type_for (TREE_TYPE (@1)), type)) > + (cond (icmp @3 @4) { build_all_ones_cst (type); } > + { build_zero_cst (type); }))) > + /* ((-(unsigned T)(a `cmp` b)) & c) -> a `cmp` b ? c : 0. */ > + (simplify > + (bit_and:c > + (convert2?@5 (negate@4 (convert (cmp@0 @1 @2)))) @3) > + (if (tree_zero_one_valued_p (@0) > + && INTEGRAL_TYPE_P (type) > + && TYPE_UNSIGNED (TREE_TYPE (@4)) > + && useless_type_conversion_p (unsigned_type_for (TREE_TYPE (@5)), > + TREE_TYPE (@4))) > + (cond (cmp @1 @2) @3 { build_zero_cst (type); }))) Can you split out the above three patterns? > + /* (a `cmp` b) ? d : (a `icmp` b) ? c : e -> a `cmp` b ? d : c. */ > + (simplify > + (cond (cmp@0 @1 @2) @4 > + (cond (icmp @1 @2) @3 @5)) > + (cond @0 @4 @3)) > + > + /* (a `cmp` b) ? ((a `icmp` b) ? <dead> : c) : d -> a `cmp` b ? c : d. */ > + (simplify > + (cond (cmp@0 @1 @2) > + (cond (icmp @1 @2) @3 @4) @5) > + (cond @0 @4 @5))) Can you put the two above next to the set of related (for cnd (cond vec_cond) /* A ? B : (A ? X : C) -> A ? B : C. */ (simplify (cnd @0 (cnd @0 @1 @2) @3) (cnd @0 @1 @3)) (simplify (cnd @0 @1 (cnd @0 @2 @3)) (cnd @0 @1 @3)) ... please? I wonder if these aren't already handled by /* A ? B : (!A ? C : X) -> A ? B : C. */ /* ??? This matches embedded conditions open-coded because genmatch would generate matching code for conditions in separate stmts only. The following is still important to merge then and else arm cases from if-conversion. */ (simplify (cnd @0 @1 (cnd @2 @3 @4)) (if (inverse_conditions_p (@0, @2)) (cnd @0 @1 @3))) (simplify (cnd @0 (cnd @1 @2 @3) @4) (if (inverse_conditions_p (@0, @1)) (cnd @0 @3 @4))) more specifically if not inverse_conditions_p should be enhanced to follow the SSA def chain here? > +(for op (bit_ior bit_and bit_xor) > + /* (a `op` (b ? 0 : c) -> b ? a `op` 0 : a `op` c > + and (a `op` (b ? c : 0) -> b ? a `op` c : a `op` 0 > + we only fold 0 because one operand is guaranteed to simplify. */ > + (simplify > + (op:c (cond @0 zerop@3 @1) @2) > + (cond @0 (op @3 @2) (op @1 @2))) > + (simplify > + (op:c (cond @0 @1 zerop@3) @2) > + (cond @0 (op @1 @2) (op @3 @2)))) > + Not sure if I said it before but we have fold_binary_op_with_conditional_arg doing this on GENERIC so the above should be #if GIMPLE and possibly next to #if GIMPLE /* From fold_binary_op_with_conditional_arg handle the case of rewriting (a ? b : c) > d to a ? (b > d) : (c > d) when the compares simplify. */ (for cmp (simple_comparison) (simplify (cmp:c (cond @0 @1 @2) @3) /* Do not move possibly trapping operations into the conditional as this pessimizes code and causes gimplification issues when applied late. */ (if (!FLOAT_TYPE_P (TREE_TYPE (@3)) || !operation_could_trap_p (cmp, true, false, @3)) (cond @0 (cmp! @1 @3) (cmp! @2 @3))))) #endif covering fold_binary_op_with_conditional_arg in a more general way would be nice but it's hard (or rather expensive) to express in match.pd terms since you have to enumerate each and every supported outer operation. Thanks, Richard. > /* Simplifications of shift and rotates. */ > > (for rotate (lrotate rrotate) > diff --git a/gcc/testsuite/gcc.dg/select_cond_1.c b/gcc/testsuite/gcc.dg/select_cond_1.c > new file mode 100644 > index 0000000000000000000000000000000000000000..9eb9959baafe5fffeec24e4e3ae656f8fcfe943c > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/select_cond_1.c > @@ -0,0 +1,97 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ > + > +#include <stdint.h> > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a <= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a > b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a < b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a == b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a != b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} 6 "optimized" } } */ > + > +extern void abort (); > + > +int main () { > + > + if (min1_32u (3, 5, 7 , 8) != 7) > + abort (); > + > + if (max1_32u (3, 5, 7 , 8) != 8) > + abort (); > + > + if (min1_32u (5, 3, 7 , 8) != 8) > + abort (); > + > + if (max1_32u (5, 3, 7 , 8) != 7) > + abort (); > + > + if (min2_32u (3, 5, 7 , 8) != 7) > + abort (); > + > + if (max2_32u (3, 5, 7 , 8) != 8) > + abort (); > + > + if (min2_32u (5, 3, 7 , 8) != 8) > + abort (); > + > + if (max2_32u (5, 3, 7 , 8) != 7) > + abort (); > + > + if (min3_32u (3, 5, 7 , 8) != 7) > + abort (); > + > + if (max3_32u (3, 5, 7 , 8) != 8) > + abort (); > + > + if (min3_32u (5, 3, 7 , 8) != 7) > + abort (); > + > + if (max3_32u (5, 3, 7 , 8) != 8) > + abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/select_cond_2.c b/gcc/testsuite/gcc.dg/select_cond_2.c > new file mode 100644 > index 0000000000000000000000000000000000000000..623b2272ee7b4b00130d5e9fb8c781dbc5d4189e > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/select_cond_2.c > @@ -0,0 +1,99 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ > + > +#include <stdint.h> > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max1_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a <= b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min2_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a > b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max2_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a < b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min3_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a == b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t max3_32u(uint32_t a, uint32_t b) { > + uint32_t result; > + uint32_t m = (a != b) - 1; > + result = (a & m) | (b & ~m); > + return result; > +} > + > +/* { dg-final { scan-tree-dump-not {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} "optimized" } } */ > +/* { dg-final { scan-tree-dump-times {MIN_EXPR} 2 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times {MAX_EXPR} 2 "optimized" } } */ > + > +extern void abort (); > + > +int main () { > + > + if (min1_32u (7 , 8) != 7) > + abort (); > + > + if (max1_32u (7 , 8) != 8) > + abort (); > + > + if (min1_32u (7 , 8) != 7) > + abort (); > + > + if (max1_32u (7, 8) != 8) > + abort (); > + > + if (min2_32u (7 , 8) != 7) > + abort (); > + > + if (max2_32u (7 , 8) != 8) > + abort (); > + > + if (min2_32u (7 , 8) != 7) > + abort (); > + > + if (max2_32u (7 , 8) != 8) > + abort (); > + > + if (min3_32u (7 , 8) != 7) > + abort (); > + > + if (max3_32u (7 , 8) != 8) > + abort (); > + > + if (min3_32u (7 , 8) != 7) > + abort (); > + > + if (max3_32u (7 , 8) != 8) > + abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/select_cond_3.c b/gcc/testsuite/gcc.dg/select_cond_3.c > new file mode 100644 > index 0000000000000000000000000000000000000000..80087d4a0bd37066dbd44335aa3d1bf13fe3fa95 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/select_cond_3.c > @@ -0,0 +1,101 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ > + > +#include <stdint.h> > + > +__attribute__((noipa, noinline)) > +int32_t min1_32u1(int32_t a, int32_t b, int32_t c, int32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u2(uint32_t a, uint32_t b, int32_t c, int32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u3(uint32_t a, uint32_t b, uint32_t c, int32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u4(uint32_t a, uint32_t b, int32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u5(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + uint32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u6(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + int32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u7(uint8_t a, uint16_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + int32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +__attribute__((noipa, noinline)) > +uint32_t min1_32u8(uint32_t a, uint64_t b, uint32_t c, uint32_t d) { > + uint32_t result; > + int32_t m = (a >= b) - 1; > + result = (c & m) | (d & ~m); > + return result; > +} > + > +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? [^ ]+ : [^ ]+;} 8 "optimized" } } */ > + > +extern void abort (); > + > +int main () { > + > + if (min1_32u1 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u2 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u3 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u4 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u5 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u6 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u7 (3, 5, 7 , 8) != 7) > + abort (); > + > + if (min1_32u8 (3, 5, 7 , 8) != 7) > + abort (); > + > + return 0; > +} >
--- a/gcc/match.pd +++ b/gcc/match.pd @@ -3577,6 +3577,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) (max @2 @1)) +/* (a & ((c `op` d) - 1)) | (b & ~((c `op` d) - 1)) -> c `op` d ? a : b. */ +(for op (simple_comparison) + (simplify + (bit_xor:c + (convert2? @0) + (bit_and:c + (convert2? (bit_xor:c @1 @0)) + (convert3? (negate (convert? (op@4 @2 @3)))))) + /* Alternative form, where some canonicalization were not done due to the + arguments being signed. */ + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) + (convert:type (cond @4 @1 @0)))) + (simplify + (bit_ior:c + (mult:c @0 (convert (convert2? (op@4 @2 @3)))) + (bit_and:c @1 (convert (plus:c integer_minus_onep (convert (op@4 @2 @3)))))) + (if (INTEGRAL_TYPE_P (type) && tree_zero_one_valued_p (@4)) + (cond @4 @0 @1)))) + /* Simplifications of shift and rotates. */ (for rotate (lrotate rrotate) diff --git a/gcc/testsuite/gcc.dg/select_cond_1.c b/gcc/testsuite/gcc.dg/select_cond_1.c new file mode 100644 index 0000000000000000000000000000000000000000..9eb9959baafe5fffeec24e4e3ae656f8fcfe943c --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_1.c @@ -0,0 +1,97 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +uint32_t min1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max1_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a <= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a > b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max2_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a < b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a == b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max3_32u(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a != b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} 6 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max1_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min1_32u (5, 3, 7 , 8) != 8) + abort (); + + if (max1_32u (5, 3, 7 , 8) != 7) + abort (); + + if (min2_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max2_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min2_32u (5, 3, 7 , 8) != 8) + abort (); + + if (max2_32u (5, 3, 7 , 8) != 7) + abort (); + + if (min3_32u (3, 5, 7 , 8) != 7) + abort (); + + if (max3_32u (3, 5, 7 , 8) != 8) + abort (); + + if (min3_32u (5, 3, 7 , 8) != 7) + abort (); + + if (max3_32u (5, 3, 7 , 8) != 8) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/select_cond_2.c b/gcc/testsuite/gcc.dg/select_cond_2.c new file mode 100644 index 0000000000000000000000000000000000000000..623b2272ee7b4b00130d5e9fb8c781dbc5d4189e --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_2.c @@ -0,0 +1,99 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +uint32_t min1_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max1_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a <= b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min2_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a > b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max2_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a < b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min3_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a == b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t max3_32u(uint32_t a, uint32_t b) { + uint32_t result; + uint32_t m = (a != b) - 1; + result = (a & m) | (b & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-not {_[0-9]+ \? c_[0-9]+\(D\) : d_[0-9]+\(D\)} "optimized" } } */ +/* { dg-final { scan-tree-dump-times {MIN_EXPR} 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {MAX_EXPR} 2 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u (7 , 8) != 7) + abort (); + + if (max1_32u (7 , 8) != 8) + abort (); + + if (min1_32u (7 , 8) != 7) + abort (); + + if (max1_32u (7, 8) != 8) + abort (); + + if (min2_32u (7 , 8) != 7) + abort (); + + if (max2_32u (7 , 8) != 8) + abort (); + + if (min2_32u (7 , 8) != 7) + abort (); + + if (max2_32u (7 , 8) != 8) + abort (); + + if (min3_32u (7 , 8) != 7) + abort (); + + if (max3_32u (7 , 8) != 8) + abort (); + + if (min3_32u (7 , 8) != 7) + abort (); + + if (max3_32u (7 , 8) != 8) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/select_cond_3.c b/gcc/testsuite/gcc.dg/select_cond_3.c new file mode 100644 index 0000000000000000000000000000000000000000..754e73b121ce360564481b1fa7e1dd4fb27642a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/select_cond_3.c @@ -0,0 +1,101 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99 -fdump-tree-optimized -save-temps" } */ + +#include <stdint.h> + +__attribute__((noipa, noinline)) +int32_t min1_32u1(int32_t a, int32_t b, int32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u2(uint32_t a, uint32_t b, int32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u3(uint32_t a, uint32_t b, uint32_t c, int32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u4(uint32_t a, uint32_t b, int32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u5(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + uint32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u6(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u7(uint8_t a, uint16_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +__attribute__((noipa, noinline)) +uint32_t min1_32u8(uint32_t a, uint64_t b, uint32_t c, uint32_t d) { + uint32_t result; + int32_t m = (a >= b) - 1; + result = (c & m) | (d & ~m); + return result; +} + +/* { dg-final { scan-tree-dump-times {_[0-9]+ \? c[^ ]+ : d[^ ]+;} 8 "optimized" } } */ + +extern void abort (); + +int main () { + + if (min1_32u1 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u2 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u3 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u4 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u5 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u6 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u7 (3, 5, 7 , 8) != 7) + abort (); + + if (min1_32u8 (3, 5, 7 , 8) != 7) + abort (); + + return 0; +}