From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2086.outbound.protection.outlook.com [40.107.22.86]) by sourceware.org (Postfix) with ESMTPS id EC6C13857005 for ; Wed, 27 Jul 2022 10:41:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EC6C13857005 ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=RXminG3AWEP3v59ljf9YYI97LP7T+o+S+PtPIvFbGGedazqGCVKitF0YtZTLsHDuX0gcosmCcObdSGWydYhTRhJB0mFWF0RIOKuzj9ra7RT5bOcv0KeY1/B88SSOhlOoA86sKciOyFd4Hfj4Fta8rHXPWlwrKZC+p3JcEEMtEarTb2CUvjU7NY2y81NVqF/Dt5EJGHpzSSvhIbu8H2dznywHmJiciCh+KGKg/uqWD/hs+345VfnCRBhxgZzCitdJ+z41axFH+c7X37x40MrXW6biLaSP6CBKcJuSoE2W1VseoMIAeWGSVi/Ii+S9DrQahqUR0PC7ACLnHjcTcXtIJg== 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=JRjCC1Z/kYfBk3ZZTZMKbtsjeW9C6b3mNAIjKxTWto0=; b=UvDyHKRU2ThZs/J0lmaTnBHYIoTguo7N7y+zHGx66hCLWWbOxut+RcrMdSspyLpLHuONf7NQLZ1ujADXJSOpYIxxwiTVjcUJL6TZ7MUiEJ9WVOgZUXXrvBj/KVP2qBstY97OyRpkG/JDsLim8uP8YeltB8QL+9JlgwkiN/nc42xE5zU4tah/CY3rcK430QemPBLUkqPHF+KMUeJCDZUMKaEY1AM3dZBUW6y9nOe+HfYu/yg0MkT1yJvt2TF7EW6B42cqp8cwy2F3IWFkAGZqD3eGWf2uWMTiSbB2+x62WbpmoISAtcVeGDLfzuk+u5OB2jPkOOJHOF7djUmBQaH75A== 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 AS9PR06CA0023.eurprd06.prod.outlook.com (2603:10a6:20b:462::28) by AM0PR08MB3617.eurprd08.prod.outlook.com (2603:10a6:208:db::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5438.20; Wed, 27 Jul 2022 10:40:58 +0000 Received: from VE1EUR03FT064.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:462:cafe::84) by AS9PR06CA0023.outlook.office365.com (2603:10a6:20b:462::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5482.7 via Frontend Transport; Wed, 27 Jul 2022 10:40:57 +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 VE1EUR03FT064.mail.protection.outlook.com (10.152.19.210) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5458.17 via Frontend Transport; Wed, 27 Jul 2022 10:40:57 +0000 Received: ("Tessian outbound cc6a8ab50b6b:v123"); Wed, 27 Jul 2022 10:40:57 +0000 X-CR-MTA-TID: 64aa7808 Received: from df5b92f1ebbe.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 3B5B3787-6217-453F-89DF-D2463FFB1365.1; Wed, 27 Jul 2022 10:40:50 +0000 Received: from EUR05-AM6-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id df5b92f1ebbe.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 27 Jul 2022 10:40:50 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LRqW1/DIOKF4DBG0XM117HLqkHk3cxUuNZE/Zi5mxD7dRoqDD6LZfcxPk2yFVq+RDWJc/hV/bKAhIAdztjlOZCMNChUia5l0BFiTsj6g9ntSWtIzPNhyhtBqxthGy9i5dI77u4Xh4h7AmrWs7XvQib483fUj5Z5MaEqWcP9vOEc1LIXmhAHVadYmHq5XuhS9g2dz5cRkDC2eyswc05edALLPXybIiVBka3gzbBSK/AvQMa1+DOQfS4eFz9aIvOTwXA0WAzhrBiuDRsMqWl5XLeVH+ry9t0z2DFHgbIrputrqHNDI0QFwlkm5w/47Df48+aAIeHDhDuMCr56yqhCOwA== 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=JRjCC1Z/kYfBk3ZZTZMKbtsjeW9C6b3mNAIjKxTWto0=; b=HL1uW64PXQXx+bHBWZeBno47tH5rUCCewFlv4yWOZCibDOyYEIrTuMyi95tHQOeXN3nyznnPP7LHPdn0eP0Oq+qC8yARC4qHRTSktid2C12gkS0dHBZxkS5058CsZt/Sum0dSTMsdoSnlfHSC+5ayx6cEecZZfbtZxGwNsmMZSOgmvfb6R0JV7bTJgvudLrGXt4uf5W6oEkN7h0utNO3yA+PU7hQaA9tNXyyUylYb4pez3FRa/sZQWdajNrPZLuRh5bIWrJjEiC6KoBhkAy8g1YtPttnDHz8ujqAP+tWdhHbAY60TRxfSQTwxT8wGi/Ybew+4xqd22pj0Eq7dlt7pQ== 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 Received: from AM0PR08MB5316.eurprd08.prod.outlook.com (2603:10a6:208:185::14) by DBBPR08MB4776.eurprd08.prod.outlook.com (2603:10a6:10:f2::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5438.20; Wed, 27 Jul 2022 10:40:47 +0000 Received: from AM0PR08MB5316.eurprd08.prod.outlook.com ([fe80::d023:733:e87b:1395]) by AM0PR08MB5316.eurprd08.prod.outlook.com ([fe80::d023:733:e87b:1395%5]) with mapi id 15.20.5458.024; Wed, 27 Jul 2022 10:40:47 +0000 From: Tamar Christina To: Richard Biener CC: "gcc-patches@gcc.gnu.org" , nd , "jakub@redhat.com" Subject: RE: [PATCH 2/2]middle-end: Support recognition of three-way max/min. Thread-Topic: [PATCH 2/2]middle-end: Support recognition of three-way max/min. Thread-Index: AQHYgXGf5qeydB2BT0ON9B9LcfwJDa1X/qYAgBgCxwCACt+kgIAXYhTQ Date: Wed, 27 Jul 2022 10:40:47 +0000 Message-ID: References: <29n37062-n3s3-71o9-8411-r851o15ss72@fhfr.qr> In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ts-tracking-id: 03D0C554D4F0CF469AB2764458A9E2A5.0 x-checkrecipientchecked: true Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-MS-Office365-Filtering-Correlation-Id: df7be156-c86d-420e-0091-08da6fbc7d7a x-ms-traffictypediagnostic: DBBPR08MB4776:EE_|VE1EUR03FT064:EE_|AM0PR08MB3617:EE_ 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: eQEJm304+xPrfL64/GN/6ccY5nLKcOV+j93EJ/M0Uqn/a3ApFisFav02jx4cWwp3hZL9nK0SC3DUGSDpjviRS/FERFkUQjs6Kuj7TQshbxZvbtkzNnFuBnJ7aMYQvyeIa4lykZ6csoo0D59diMQTiy0XghoXyYuUppWIvokBdUQlCdEjm5Nt0iA7txetb8Bt4sRtqmgcyeZBI7Yfr8ajR9cillANuDL727R71rW0qkpvRBEqQ2hpwXSeQPFKqpVpyTHsiBARg2tVc7C8SCM024O69xCBiVHG1frGOE5p7h93eDFIIxRB6Co0t2WNl3enJTR48jtP5J/Lm+DgTtLB98ZfeJp+RLwx+XtQ8YervX+2LFSEs96ze5BNKmVazC0shgEU9+s/4rdC0g7Zk5a+Ha86X183lfCav7olrhx0pIQrhSmaNdi6/7ORAGe1RQ5+H5gFPd/sFwL3gsupw8t1KetIAvKb8tOpkd8xSQT0uDsRDgTqM+joH08IIQMFZW1cBzzVG0d0QjJC2+kOredMVXiDoRt+Wd8LMRQ6T1NDX2qTA7qi3FV1/QW8gUvfHjnps00qcAGy5iBmN0NZnaV02aQQ7Hn82LeXC8m2dotwBzHdp8yRwBiQrfpKFm1MKb7NGHPhfTnolCQKnql6Pp0sOEclXdxBEtwHVOve2HZh6pZq9dXF5H3bBls3wckKgXftxPTrRf8rHlF8DEtg/ALGXU/9P5ftgbPr8rvi4ym62EUN7gK4U70N50tgg6d8bCUTPAFohknWePRon39zE4avuTigFGaSr0XA9pWCq/EfT7vRy42LVArQV1XC9IpNUAr95UyNDsoLtoPIiLWSPmQVaK49Wa2viWGfP77RGRp7k9sOpcywQ6LDKl2r+8twanXd X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM0PR08MB5316.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(39860400002)(396003)(346002)(366004)(136003)(376002)(38100700002)(86362001)(33656002)(38070700005)(5660300002)(6506007)(9686003)(26005)(41300700001)(2906002)(186003)(7696005)(83380400001)(76116006)(53546011)(66476007)(71200400001)(66446008)(54906003)(478600001)(316002)(8936002)(52536014)(4326008)(8676002)(66556008)(30864003)(66946007)(55016003)(6916009)(122000001)(64756008)(84970400001)(559001)(579004); DIR:OUT; SFP:1101; Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4776 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: VE1EUR03FT064.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: f88f6461-5568-4f07-052c-08da6fbc7798 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: MMniSzsDaxA2VB/WUi3txKY6rpA/DbvnkzkjQb5y5r+F8OhYaHbjq1XNBOx371velar8awpHpvwVa37n26nbP1+pbwv/+T8gzr6ZsbL/jz2v2tbpyekgBHZl9he5sg9GKM4tsYmTJe+y9qpY43pj36/XvcT1GSFEz7OvcBD9Di8Dt9D2Jy81eCxy4pXZKySN+dz+c5tO3VgzxrgHbqkw7CPFoOTCJZUbez0irVPP4weGBESsdt1totKkyao8OKAXCPfiyWKycPNmKlvzBM59FKj/Vofj1MoGndyqdHF1DHN3ie7yxnrRgXXactTTg/QXepXHjj5eLe9tyzzkkfvZXtxt3Gs0wsfnav23YgE02RmOSFV6kEL/V9qOwjCKHLisK0+AFaepHB+5qgeDGift/fQCuiPw1fWiqTm32k4f2wwFzUY+apwlO54uHWhhRcB/8Xut1ohdqAzdQJIgeXkZQC/sU/4kROyuLXpr0rZgd/SSEw7Fbv1IS833P6wx/ZPIRoP9poWCh3mUgwy/PhKrinumO/P6LcEqj8ebreULz+KqIwAPPlY8FnbLw3+3hwB74YPhVuq6aHOi5LNQ4mu6rgKDuAYxzzfwnCrzzdS5qKejKJtTFNZZsZzoIC3suPGW+2y0QarYm2FFrNTTvThSKOZsJ5OjxKdcYOUqrsj65jz0Afc4t98aCwdutj+UmQTyVUTU9v48g30FBowq0TMfnqMbjAOA0Rxcn5XL1MnD0bp9/TxlMdcn+IJ09eVWsjx/kgLYiNzv96L6k/aXdghXVQB2bJXGPOylNEMtP3pVlQs4wF1DroYxiqrin+KDT0On3LLLW87cujWEFIn53Hj32AqXy/x05w0btRL8ujAmfNAYWsjnr0ZD8b+r3RGfCEAK 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:(13230016)(4636009)(39860400002)(136003)(346002)(396003)(376002)(36840700001)(40470700004)(46966006)(6862004)(8676002)(70206006)(30864003)(70586007)(336012)(52536014)(186003)(107886003)(33656002)(5660300002)(40460700003)(8936002)(2906002)(356005)(54906003)(316002)(83380400001)(82740400003)(478600001)(81166007)(53546011)(7696005)(84970400001)(26005)(86362001)(36860700001)(41300700001)(6506007)(40480700001)(47076005)(55016003)(9686003)(82310400005)(4326008)(579004); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jul 2022 10:40:57.4551 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: df7be156-c86d-420e-0091-08da6fbc7d7a 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: VE1EUR03FT064.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR08MB3617 X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Jul 2022 10:41:08 -0000 > -----Original Message----- > From: Richard Biener > Sent: Tuesday, July 12, 2022 2:19 PM > To: Tamar Christina > Cc: gcc-patches@gcc.gnu.org; nd ; jakub@redhat.com > Subject: RE: [PATCH 2/2]middle-end: Support recognition of three-way > max/min. >=20 > On Tue, 5 Jul 2022, Tamar Christina wrote: >=20 > > > > } > > > > + else if (EDGE_SUCC (bb1, 0)->dest =3D=3D EDGE_SUCC (bb2, 0)-= >dest > > > > + && single_succ_p (bb1) > > > > + && single_succ_p (bb2) > > > > + && single_pred_p (bb1) > > > > + && single_pred_p (bb2) > > > > + && single_succ_p (EDGE_SUCC (bb1, 0)->dest)) > > > > > > please do the single_succ/pred checks below where appropriate, also > > > what's the last check about? > > > > Done. > > > > > why does the merge block need a single successor? > > > > I was using it to fix an ICE, but I realize that's not the right fix. > > I'm now checking If the BB is empty instead, in which case it's just a > > fall through edge so don't treat it as a diamond. > > > > > > > > > + { > > > > + gimple_stmt_iterator it1 =3D gsi_start_nondebug_after_labels_bb > > > (bb1); > > > > + gimple_stmt_iterator it2 =3D gsi_start_nondebug_after_labels_bb > > > (bb2); > > > > + if (gsi_one_before_end_p (it1) && gsi_one_before_end_p (it2)) > > > > + { > > > > + gimple *stmt1 =3D gsi_stmt (it1); > > > > + gimple *stmt2 =3D gsi_stmt (it2); > > > > + if (is_gimple_assign (stmt1) && is_gimple_assign (stmt2)) > > > > + { > > > > + enum tree_code code1 =3D gimple_assign_rhs_code (stmt1); > > > > + enum tree_code code2 =3D gimple_assign_rhs_code (stmt2); > > > > + diamond_minmax_p > > > > + =3D (code1 =3D=3D MIN_EXPR || code1 =3D=3D MAX_EXPR) > > > > + && (code2 =3D=3D MIN_EXPR || code2 =3D=3D MAX_EXPR); > > > > + } > > > > + } > > > > + } > > > > > > I'd generalize this to general diamond detection, simply cutting off > > > *_replacement workers that do not handle diamonds and do appropriate > > > checks in minmax_replacement only. > > > > > > > Done. > > > > > > else > > > > continue; > > > > > > > > @@ -316,6 +340,13 @@ tree_ssa_phiopt_worker (bool do_store_elim, > > > bool do_hoist_loads, bool early_p) > > > > if (!candorest) > > > > continue; > > > > > > > > + /* Check that we're looking for nested phis. */ > > > > + if (phis =3D=3D NULL && diamond_minmax_p) > > > > + { > > > > + phis =3D phi_nodes (EDGE_SUCC (bb2, 0)->dest); > > > > + e2 =3D EDGE_SUCC (bb2, 0); > > > > + } > > > > + > > > > > > instead > > > > > > basic_block merge =3D diamond_p ? EDGE_SUCC (bb2, 0)->dest = : bb2; > > > gimple_seq phis =3D phi_nodes (merge); > > > > > > > Done. > > > > > > > > > phi =3D single_non_singleton_phi_for_edges (phis, e1, e2); > > > > if (!phi) > > > > continue; > > > > @@ -329,6 +360,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, > > > > bool do_hoist_loads, bool early_p) > > > > > > > > gphi *newphi; > > > > if (single_pred_p (bb1) > > > > + && !diamond_minmax_p > > > > && (newphi =3D factor_out_conditional_conversion (e1, e2, p= hi, > > > > arg0, arg1, > > > > cond_stmt))) > > > > @@ -343,20 +375,25 @@ tree_ssa_phiopt_worker (bool > do_store_elim, > > > bool do_hoist_loads, bool early_p) > > > > } > > > > > > > > /* Do the replacement of conditional if it can be done. */ > > > > - if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, > > > arg1)) > > > > + if (!early_p > > > > + && !diamond_minmax_p > > > > + && two_value_replacement (bb, bb1, e2, phi, arg0, arg1)) > > > > cfgchanged =3D true; > > > > - else if (match_simplify_replacement (bb, bb1, e1, e2, phi, > > > > - arg0, arg1, > > > > - early_p)) > > > > + else if (!diamond_minmax_p > > > > + && match_simplify_replacement (bb, bb1, e1, e2, phi, > > > > + arg0, arg1, early_p)) > > > > cfgchanged =3D true; > > > > else if (!early_p > > > > + && !diamond_minmax_p > > > > && single_pred_p (bb1) > > > > && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, > > > e2, > > > > phi, arg0, arg1)) > > > > cfgchanged =3D true; > > > > - else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) > > > > + else if (minmax_replacement (bb, bb1, bb2, e1, e2, phi, arg0, a= rg1, > > > > + diamond_minmax_p)) > > > > cfgchanged =3D true; > > > > else if (single_pred_p (bb1) > > > > + && !diamond_minmax_p > > > > && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, > > > arg1)) > > > > cfgchanged =3D true; > > > > } > > > > @@ -385,7 +422,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, > > > > bool do_hoist_loads, bool early_p) > > > > > > > > static void > > > > replace_phi_edge_with_variable (basic_block cond_block, > > > > - edge e, gphi *phi, tree new_tree) > > > > + edge e, gphi *phi, tree new_tree, bool > > > delete_bb =3D true) > > > > { > > > > basic_block bb =3D gimple_bb (phi); > > > > gimple_stmt_iterator gsi; > > > > @@ -428,7 +465,7 @@ replace_phi_edge_with_variable (basic_block > > > cond_block, > > > > edge_to_remove =3D EDGE_SUCC (cond_block, 1); > > > > else > > > > edge_to_remove =3D EDGE_SUCC (cond_block, 0); > > > > - if (EDGE_COUNT (edge_to_remove->dest->preds) =3D=3D 1) > > > > + if (EDGE_COUNT (edge_to_remove->dest->preds) =3D=3D 1 && > delete_bb) > > > > > > why do you need this change? > > > > When this function replaces the edge it doesn't seem to update the > dominators. > > Since It's replacing the middle BB we then end up with an error > > > > gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c:17:1: error: dominator of 5 > > should be 4, not 2 > > > > during early verify. So instead, I replace the BB but defer its > > deletion until cleanup which removes it and updates the dominators. >=20 > Hmm, for a diamond shouldn't you replace >=20 > if (EDGE_SUCC (cond_block, 0)->dest =3D=3D bb) > edge_to_remove =3D EDGE_SUCC (cond_block, 1); > else > edge_to_remove =3D EDGE_SUCC (cond_block, 0); >=20 > with >=20 > if (EDGE_SUCC (cond_block, 0)->dest =3D=3D bb) > edge_to_remove =3D EDGE_SUCC (cond_block, 1); > else if (EDGE_SUCC (cond_block, 1)->dest =3D=3D bb) > edge_to_remove =3D EDGE_SUCC (cond_block, 0); >=20 > thus, the code expects to be left with a fallthru to the PHI block which = is > expected to have the immediate dominator being cond_block but with a > diamond there's a (possibly empty) block inbetween and dominators are > wrong. Agreed, but the (EDGE_SUCC (cond_block, 1)->dest =3D=3D bb) doesn't seem li= ke the Right one since for a diamond there will be a block in between the two. Di= d you perhaps mean EDGE_SUCC (EDGE_SUCC (cond_block, 1)->dest, 0)->dest =3D=3D bb? i.e. = that that destination across the diamond be bb, and then you remove the middle block? For the minmax diamond we want both edges removed, since all the code in th= e middle BBs are now dead. But this is probably not true in the general sense. >>> p debug (cond_block) : xc_3 =3D ~xc_2(D); xm_5 =3D ~xm_4(D); xy_7 =3D ~xy_6(D); _10 =3D MAX_EXPR ; _12 =3D MIN_EXPR <_10, xm_4(D)>; _13 =3D ~_12; if (xc_3 < xm_5) goto ; [INV] else goto ; [INV] >>> p debug (EDGE_SUCC (cond_block, 0)->dest) : xk_9 =3D MAX_EXPR ; goto ; [INV] >>> p debug (EDGE_SUCC (cond_block, 1)->dest) : xk_8 =3D MAX_EXPR ; >>> p debug (bb) : # xk_1 =3D PHI return xk_1; $6 =3D void So something like this? diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 72d7b40a501..c107eeea1aa 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -400,7 +400,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoi= st_loads, bool early_p) static void replace_phi_edge_with_variable (basic_block cond_block, - edge e, gphi *phi, tree new_tree, bool dele= te_bb =3D true) + edge e, gphi *phi, tree new_tree, bool diam= ond_p =3D false) { basic_block bb =3D gimple_bb (phi); gimple_stmt_iterator gsi; @@ -439,9 +439,9 @@ replace_phi_edge_with_variable (basic_block cond_block, edge edge_to_remove; if (EDGE_SUCC (cond_block, 0)->dest =3D=3D bb) edge_to_remove =3D EDGE_SUCC (cond_block, 1); - else + else if (!diamond_p || (diamond_p && EDGE_SUCC (EDGE_SUCC (cond_block, 1= )->dest, 0)->dest =3D=3D bb)) edge_to_remove =3D EDGE_SUCC (cond_block, 0); - if (EDGE_COUNT (edge_to_remove->dest->preds) =3D=3D 1 && delete_bb) + if (EDGE_COUNT (edge_to_remove->dest->preds) =3D=3D 1 && !diamond_p) { e->flags |=3D EDGE_FALLTHRU; e->flags &=3D ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); @@ -2147,7 +2147,7 @@ minmax_replacement (basic_block cond_bb, basic_block = middle_bb, basic_block alt_ gsi =3D gsi_last_bb (cond_bb); gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); - replace_phi_edge_with_variable (cond_bb, e1, phi, result, false); + replace_phi_edge_with_variable (cond_bb, e1, phi, result, threeway_p= ); return true; } Cheers, Tamar >=20 > So I think you simply need to handle this properly (and then fall through= to > the else). >=20 >=20 > > > > > > Did you check whether the new case works when the merge block has > > > more than two incoming edges? > > > > > > > Yes, added a new testcase for it. > > > > > > + else if (middle_bb !=3D alt_middle_bb && threeway_p) > > > > + { > > > > + /* Recognize the following case: > > > > + > > > > + if (smaller < larger) > > > > + a =3D MIN (smaller, c); > > > > + else > > > > + b =3D MIN (larger, c); > > > > + x =3D PHI > > > > + > > > > + This is equivalent to > > > > + > > > > + a =3D MIN (smaller, c); > > > > + x =3D MIN (larger, a); */ > > > > + > > > > + gimple *assign =3D last_and_only_stmt (middle_bb); > > > > + tree lhs, op0, op1, bound; > > > > + tree alt_lhs, alt_op0, alt_op1; > > > > + bool invert =3D false; > > > > + > > > > + if (!single_pred_p (middle_bb) > > > > + || !single_pred_p (alt_middle_bb)) > > > > + return false; > > > > + > > > > + if (!assign > > > > + || gimple_code (assign) !=3D GIMPLE_ASSIGN) > > > > + return false; > > > > + > > > > + lhs =3D gimple_assign_lhs (assign); > > > > + ass_code =3D gimple_assign_rhs_code (assign); > > > > + if (ass_code !=3D MAX_EXPR && ass_code !=3D MIN_EXPR) > > > > + return false; > > > > + > > > > + op0 =3D gimple_assign_rhs1 (assign); > > > > + op1 =3D gimple_assign_rhs2 (assign); > > > > + > > > > + assign =3D last_and_only_stmt (alt_middle_bb); > > > > + if (!assign > > > > + || gimple_code (assign) !=3D GIMPLE_ASSIGN) > > > > + return false; > > > > + > > > > + alt_lhs =3D gimple_assign_lhs (assign); > > > > + if (ass_code !=3D gimple_assign_rhs_code (assign)) > > > > + return false; > > > > + > > > > + alt_op0 =3D gimple_assign_rhs1 (assign); > > > > + alt_op1 =3D gimple_assign_rhs2 (assign); > > > > + > > > > + if (!operand_equal_for_phi_arg_p (lhs, arg_true) > > > > + || !operand_equal_for_phi_arg_p (alt_lhs, arg_false)) > > > > + return false; > > > > + > > > > + if ((operand_equal_for_phi_arg_p (op0, smaller) > > > > + || (alt_smaller > > > > + && operand_equal_for_phi_arg_p (op0, alt_smaller))) > > > > + && (operand_equal_for_phi_arg_p (alt_op0, larger) > > > > + || (alt_larger > > > > + && operand_equal_for_phi_arg_p (alt_op0, alt_larger)))) > > > > + { > > > > + /* We got here if the condition is true, i.e., SMALLER < LARGER= . */ > > > > + if (!operand_equal_for_phi_arg_p (op1, alt_op1)) > > > > + return false; > > > > + > > > > + if ((arg0 =3D strip_bit_not (op0)) !=3D NULL > > > > + && (arg1 =3D strip_bit_not (alt_op0)) !=3D NULL > > > > + && (bound =3D strip_bit_not (op1)) !=3D NULL) > > > > + { > > > > + minmax =3D MAX_EXPR; > > > > + ass_code =3D invert_minmax_code (ass_code); > > > > + invert =3D true; > > > > + } > > > > + else > > > > + { > > > > + bound =3D op1; > > > > + minmax =3D MIN_EXPR; > > > > + arg0 =3D op0; > > > > + arg1 =3D alt_op0; > > > > + } > > > > + } > > > > + else if ((operand_equal_for_phi_arg_p (op0, larger) > > > > + || (alt_larger > > > > + && operand_equal_for_phi_arg_p (op0, alt_larger))) > > > > + && (operand_equal_for_phi_arg_p (alt_op0, smaller) > > > > + || (alt_smaller > > > > + && operand_equal_for_phi_arg_p (alt_op0, > > > alt_smaller)))) > > > > + { > > > > + /* We got here if the condition is true, i.e., SMALLER > LARGER= . */ > > > > + if (!operand_equal_for_phi_arg_p (op1, alt_op1)) > > > > + return false; > > > > + > > > > + if ((arg0 =3D strip_bit_not (op0)) !=3D NULL > > > > + && (arg1 =3D strip_bit_not (alt_op0)) !=3D NULL > > > > + && (bound =3D strip_bit_not (op1)) !=3D NULL) > > > > + { > > > > + minmax =3D MIN_EXPR; > > > > + ass_code =3D invert_minmax_code (ass_code); > > > > + invert =3D true; > > > > + } > > > > + else > > > > + { > > > > + bound =3D op1; > > > > + minmax =3D MAX_EXPR; > > > > + arg0 =3D op0; > > > > + arg1 =3D alt_op0; > > > > + } > > > > + } > > > > + else > > > > + return false; > > > > > > Did you check you have coverage for all cases above in your testcases= ? > > > > I've added some more, should now have full coverage. >=20 > Great. >=20 > > > > > > > + /* Reset any range information from the basic block. */ > > > > + reset_flow_sensitive_info_in_bb (cond_bb); > > > > > > Huh. You need to reset flow-sensitive info of the middle-bb stmt > > > that prevails only... > > > > > > > + /* Emit the statement to compute min/max. */ > > > > + gimple_seq stmts =3D NULL; > > > > + tree phi_result =3D PHI_RESULT (phi); > > > > + result =3D gimple_build (&stmts, minmax, TREE_TYPE > > > > + (phi_result), arg0, > > > bound); > > > > + result =3D gimple_build (&stmts, ass_code, TREE_TYPE > > > > + (phi_result), result, arg1); > > > > > > ... but you are re-building both here. And also you drop locations, > > > the preserved min/max should keep the old, the new should get the > > > location of ... hmm, the condition possibly? > > > > Done, also added a testcase which checks that it still works when -g. > > > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > > > > Ok for master? >=20 > Besides the above issue it looks good to me. >=20 > Thanks and sorry for the delay. > Richard. >=20 > > Thanks, > > Tamar > > > > gcc/ChangeLog: > > > > * tree-ssa-phiopt.cc (minmax_replacement): Optionally search for > the phi > > sequence of a three-way conditional. > > (replace_phi_edge_with_variable): Support deferring of BB removal. > > (tree_ssa_phiopt_worker): Detect diamond phi structure for three- > way > > min/max. > > (strip_bit_not, invert_minmax_code): New. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.dg/tree-ssa/split-path-1.c: Disable phi-opts so we don't > optimize > > code away. > > * gcc.dg/tree-ssa/minmax-10.c: New test. > > * gcc.dg/tree-ssa/minmax-11.c: New test. > > * gcc.dg/tree-ssa/minmax-12.c: New test. > > * gcc.dg/tree-ssa/minmax-13.c: New test. > > * gcc.dg/tree-ssa/minmax-14.c: New test. > > * gcc.dg/tree-ssa/minmax-15.c: New test. > > * gcc.dg/tree-ssa/minmax-16.c: New test. > > * gcc.dg/tree-ssa/minmax-3.c: New test. > > * gcc.dg/tree-ssa/minmax-4.c: New test. > > * gcc.dg/tree-ssa/minmax-5.c: New test. > > * gcc.dg/tree-ssa/minmax-6.c: New test. > > * gcc.dg/tree-ssa/minmax-7.c: New test. > > * gcc.dg/tree-ssa/minmax-8.c: New test. > > * gcc.dg/tree-ssa/minmax-9.c: New test. > > > > --- inline copy of patch --- > > > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..589953684416a9d263084deb5 > 8f6 > > cde7094dd517 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c > > @@ -0,0 +1,20 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-optimized" } */ > > + > > +#include > > + > > +uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + xc=3D~xc; > > + xm=3D~xm; > > + xy=3D~xy; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xc > xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm > xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */ > > +/* { dg-final { scan-tree-dump-times "=3D ~" 1 "optimized" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..1c2ef01b5d1e639fbf95bb5ca4 > 73 > > b63cc98e9df1 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c > > @@ -0,0 +1,21 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-optimized" } */ > > + > > +#include > > + > > +uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + xc=3D~xc; > > + xm=3D~xm; > > + xy=3D~xy; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xc < xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */ > > +/* { dg-final { scan-tree-dump-times "=3D ~" 1 "optimized" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..3d0c07d9b57dd689bcb896539 > 377 > > 27ab441e7f2b > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c > > @@ -0,0 +1,20 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + xc=3D~xc; > > + xm=3D~xm; > > + xy=3D~xy; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xy < xc ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..c0d0f27c8027ae87654532d1b9 > 19 > > cfeccf4413e0 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c > > @@ -0,0 +1,19 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + xc=3D~xc; > > + xm=3D~xm; > > + xy=3D~xy; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xc > xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..9c0cadbf7e3119527cb2007d01 > fe > > 4c7dd772c069 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c > > @@ -0,0 +1,21 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-optimized" } */ > > + > > +#include > > + > > +uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + xc=3D~xc; > > + xm=3D~xm; > > + xy=3D~xy; > > + if (xc < xm) { > > + xk =3D (uint8_t) (xc > xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm > xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */ > > +/* { dg-final { scan-tree-dump-times "=3D ~" 1 "optimized" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..1d97a16564f069b4348ff325c4f > d > > 713a224f838a > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c > > @@ -0,0 +1,21 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > +#include > > + > > +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy, bool m) { > > + uint8_t xk; > > + if (xc) > > + { > > + if (xc < xm) { > > + xk =3D (uint8_t) (xc < xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + } > > + > > + return xk; > > +} > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..89377a2cb341bdafa6ba145c61 > c1 > > f966af536839 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt -g" } */ > > + > > +#include > > + > > +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc < xm) { > > + xk =3D (uint8_t) (xc < xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..de3b2e946e81701e3b75f580e > 6a8 > > 43695a05786e > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc < xm) { > > + xk =3D (uint8_t) (xc < xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..0b6d667be868c2405eaefd17c > b52 > > 2da44bafa0e2 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xc > xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm > xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..650601a3cc75d09a9e6e54a35f > 5b > > 9993074f8510 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xc < xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..a628f6d99222958cfd8c410f0e > 85 > > 639e3a49dd4b > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xy < xc ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..cb42412c4ada433b2f59df0a8b > ef > > 9fa7b1c5e104 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c > > @@ -0,0 +1,16 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc > xm) { > > + xk =3D (uint8_t) (xc > xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..9cd050e932376bc50bd6ae60c > b65 > > 4fcab0bfdd1c > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-phiopt" } */ > > + > > +#include > > + > > +uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + if (xc < xm) { > > + xk =3D (uint8_t) (xc > xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm > xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c > > b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c > > new file mode 100644 > > index > > > 0000000000000000000000000000000000000000..24f580271c3ac3945860b506d4 > dc > > 7d178a826093 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c > > @@ -0,0 +1,20 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O -fdump-tree-optimized" } */ > > + > > +#include > > + > > +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { > > + uint8_t xk; > > + xc=3D~xc; > > + xm=3D~xm; > > + xy=3D~xy; > > + if (xc < xm) { > > + xk =3D (uint8_t) (xc < xy ? xc : xy); > > + } else { > > + xk =3D (uint8_t) (xm < xy ? xm : xy); > > + } > > + return xk; > > +} > > + > > +/* { dg-final { scan-tree-dump-times "=3D ~" 1 "optimized" } } */ > > +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */ > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c > > b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c > > index > > > 8b23ef4c7a3484cdc1647ee6d1b150f15685beff..902dde44a50e171b4f34ba724 > 7d7 > > 5a32d2c860ed 100644 > > --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c > > @@ -1,5 +1,5 @@ > > /* { dg-do run } */ > > -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details > > --param max-jump-thread-duplication-stmts=3D20" } */ > > +/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details > > +--param max-jump-thread-duplication-stmts=3D20 -fno-ssa-phiopt" } */ > > > > #include > > #include > > diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index > > > e61d9736937573d773acdf3e43a7c76074bfb2c7..df543b22cd720538c14bcea72f > c7 > > 8a8dec9bf12b 100644 > > --- a/gcc/tree-ssa-phiopt.cc > > +++ b/gcc/tree-ssa-phiopt.cc > > @@ -63,8 +63,8 @@ static gphi *factor_out_conditional_conversion (edge, > edge, gphi *, tree, tree, > > gimple *); > > static int value_replacement (basic_block, basic_block, > > edge, edge, gphi *, tree, tree); -static bool > > minmax_replacement (basic_block, basic_block, > > - edge, edge, gphi *, tree, tree); > > +static bool minmax_replacement (basic_block, basic_block, basic_block, > > + edge, edge, gphi *, tree, tree, bool); > > static bool spaceship_replacement (basic_block, basic_block, > > edge, edge, gphi *, tree, tree); static bool > > cond_removal_in_builtin_zero_pattern (basic_block, basic_block, @@ > > -74,7 +74,7 @@ static bool cond_store_replacement (basic_block, > basic_block, edge, edge, > > hash_set *); > > static bool cond_if_else_store_replacement (basic_block, basic_block, > > basic_block); static hash_set * get_non_trapping (); -static > > void replace_phi_edge_with_variable (basic_block, edge, gphi *, tree); > > +static void replace_phi_edge_with_variable (basic_block, edge, gphi > > +*, tree, bool); > > static void hoist_adjacent_loads (basic_block, basic_block, > > basic_block, basic_block); > > static bool gate_hoist_loads (void); > > @@ -200,6 +200,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool > do_hoist_loads, bool early_p) > > basic_block bb1, bb2; > > edge e1, e2; > > tree arg0, arg1; > > + bool diamond_p =3D false; > > > > bb =3D bb_order[i]; > > > > @@ -266,6 +267,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool > do_hoist_loads, bool early_p) > > hoist_adjacent_loads (bb, bb1, bb2, bb3); > > continue; > > } > > + else if (EDGE_SUCC (bb1, 0)->dest =3D=3D EDGE_SUCC (bb2, 0)->des= t > > + && !empty_block_p (bb1)) > > + diamond_p =3D true; > > else > > continue; > > > > @@ -294,10 +298,13 @@ tree_ssa_phiopt_worker (bool do_store_elim, > bool do_hoist_loads, bool early_p) > > } > > else > > { > > - gimple_seq phis =3D phi_nodes (bb2); > > gimple_stmt_iterator gsi; > > bool candorest =3D true; > > > > + /* Check that we're looking for nested phis. */ > > + basic_block merge =3D diamond_p ? EDGE_SUCC (bb2, 0)->dest : bb2; > > + gimple_seq phis =3D phi_nodes (merge); > > + > > /* Value replacement can work with more than one PHI > > so try that first. */ > > if (!early_p) > > @@ -317,6 +324,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool > do_hoist_loads, bool early_p) > > if (!candorest) > > continue; > > > > + e2 =3D diamond_p ? EDGE_SUCC (bb2, 0) : e2; > > phi =3D single_non_singleton_phi_for_edges (phis, e1, e2); > > if (!phi) > > continue; > > @@ -330,6 +338,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool > > do_hoist_loads, bool early_p) > > > > gphi *newphi; > > if (single_pred_p (bb1) > > + && !diamond_p > > && (newphi =3D factor_out_conditional_conversion (e1, e2, phi, > > arg0, arg1, > > cond_stmt))) > > @@ -344,20 +353,25 @@ tree_ssa_phiopt_worker (bool do_store_elim, > bool do_hoist_loads, bool early_p) > > } > > > > /* Do the replacement of conditional if it can be done. */ > > - if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, > arg1)) > > + if (!early_p > > + && !diamond_p > > + && two_value_replacement (bb, bb1, e2, phi, arg0, arg1)) > > cfgchanged =3D true; > > - else if (match_simplify_replacement (bb, bb1, e1, e2, phi, > > - arg0, arg1, > > - early_p)) > > + else if (!diamond_p > > + && match_simplify_replacement (bb, bb1, e1, e2, phi, > > + arg0, arg1, early_p)) > > cfgchanged =3D true; > > else if (!early_p > > + && !diamond_p > > && single_pred_p (bb1) > > && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, > e2, > > phi, arg0, arg1)) > > cfgchanged =3D true; > > - else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) > > + else if (minmax_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1, > > + diamond_p)) > > cfgchanged =3D true; > > else if (single_pred_p (bb1) > > + && !diamond_p > > && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, > arg1)) > > cfgchanged =3D true; > > } > > @@ -386,7 +400,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool > > do_hoist_loads, bool early_p) > > > > static void > > replace_phi_edge_with_variable (basic_block cond_block, > > - edge e, gphi *phi, tree new_tree) > > + edge e, gphi *phi, tree new_tree, bool > delete_bb =3D true) > > { > > basic_block bb =3D gimple_bb (phi); > > gimple_stmt_iterator gsi; > > @@ -427,7 +441,7 @@ replace_phi_edge_with_variable (basic_block > cond_block, > > edge_to_remove =3D EDGE_SUCC (cond_block, 1); > > else > > edge_to_remove =3D EDGE_SUCC (cond_block, 0); > > - if (EDGE_COUNT (edge_to_remove->dest->preds) =3D=3D 1) > > + if (EDGE_COUNT (edge_to_remove->dest->preds) =3D=3D 1 && delete_bb) > > { > > e->flags |=3D EDGE_FALLTHRU; > > e->flags &=3D ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); @@ - > 1733,15 > > +1747,52 @@ value_replacement (basic_block cond_bb, basic_block > middle_bb, > > return 0; > > } > > > > +/* If VAR is an SSA_NAME that points to a BIT_NOT_EXPR then return the > TREE for > > + the value being inverted. */ > > + > > +static tree > > +strip_bit_not (tree var) > > +{ > > + if (TREE_CODE (var) !=3D SSA_NAME) > > + return NULL_TREE; > > + > > + gimple *assign =3D SSA_NAME_DEF_STMT (var); if (gimple_code (assign= ) > > + !=3D GIMPLE_ASSIGN) > > + return NULL_TREE; > > + > > + if (gimple_assign_rhs_code (assign) !=3D BIT_NOT_EXPR) > > + return NULL_TREE; > > + > > + return gimple_assign_rhs1 (assign); } > > + > > +/* Invert a MIN to a MAX or a MAX to a MIN expression CODE. */ > > + > > +enum tree_code > > +invert_minmax_code (enum tree_code code) { > > + switch (code) { > > + case MIN_EXPR: > > + return MAX_EXPR; > > + case MAX_EXPR: > > + return MIN_EXPR; > > + default: > > + gcc_unreachable (); > > + } > > +} > > + > > /* The function minmax_replacement does the main work of doing the > minmax > > replacement. Return true if the replacement is done. Otherwise r= eturn > > false. > > BB is the basic block where the replacement is going to be done on= . > ARG0 > > - is argument 0 from the PHI. Likewise for ARG1. */ > > + is argument 0 from the PHI. Likewise for ARG1. > > + > > + If THREEWAY_P then expect the BB to be laid out in diamond shape w= ith > each > > + BB containing only a MIN or MAX expression. */ > > > > static bool > > -minmax_replacement (basic_block cond_bb, basic_block middle_bb, > > - edge e0, edge e1, gphi *phi, tree arg0, tree arg1) > > +minmax_replacement (basic_block cond_bb, basic_block middle_bb, > basic_block alt_middle_bb, > > + edge e0, edge e1, gphi *phi, tree arg0, tree arg1, bool > > +threeway_p) > > { > > tree result; > > edge true_edge, false_edge; > > @@ -1896,16 +1947,20 @@ minmax_replacement (basic_block cond_bb, > basic_block middle_bb, > > if (false_edge->dest =3D=3D middle_bb) > > false_edge =3D EDGE_SUCC (false_edge->dest, 0); > > > > + /* When THREEWAY_P then e1 will point to the edge of the final > transition > > + from middle-bb to end. */ > > if (true_edge =3D=3D e0) > > { > > - gcc_assert (false_edge =3D=3D e1); > > + if (!threeway_p) > > + gcc_assert (false_edge =3D=3D e1); > > arg_true =3D arg0; > > arg_false =3D arg1; > > } > > else > > { > > gcc_assert (false_edge =3D=3D e0); > > - gcc_assert (true_edge =3D=3D e1); > > + if (!threeway_p) > > + gcc_assert (true_edge =3D=3D e1); > > arg_true =3D arg1; > > arg_false =3D arg0; > > } > > @@ -1937,6 +1992,165 @@ minmax_replacement (basic_block cond_bb, > basic_block middle_bb, > > else > > return false; > > } > > + else if (middle_bb !=3D alt_middle_bb && threeway_p) > > + { > > + /* Recognize the following case: > > + > > + if (smaller < larger) > > + a =3D MIN (smaller, c); > > + else > > + b =3D MIN (larger, c); > > + x =3D PHI > > + > > + This is equivalent to > > + > > + a =3D MIN (smaller, c); > > + x =3D MIN (larger, a); */ > > + > > + gimple *assign =3D last_and_only_stmt (middle_bb); > > + tree lhs, op0, op1, bound; > > + tree alt_lhs, alt_op0, alt_op1; > > + bool invert =3D false; > > + > > + if (!single_pred_p (middle_bb) > > + || !single_pred_p (alt_middle_bb) > > + || !single_succ_p (middle_bb) > > + || !single_succ_p (alt_middle_bb)) > > + return false; > > + > > + /* When THREEWAY_P then e1 will point to the edge of the final > transition > > + from middle-bb to end. */ > > + if (true_edge =3D=3D e0) > > + gcc_assert (false_edge =3D=3D EDGE_PRED (e1->src, 0)); > > + else > > + gcc_assert (true_edge =3D=3D EDGE_PRED (e1->src, 0)); > > + > > + bool valid_minmax_p =3D false; > > + gimple_stmt_iterator it1 > > + =3D gsi_start_nondebug_after_labels_bb (middle_bb); > > + gimple_stmt_iterator it2 > > + =3D gsi_start_nondebug_after_labels_bb (alt_middle_bb); > > + if (gsi_one_nondebug_before_end_p (it1) > > + && gsi_one_nondebug_before_end_p (it2)) > > + { > > + gimple *stmt1 =3D gsi_stmt (it1); > > + gimple *stmt2 =3D gsi_stmt (it2); > > + if (is_gimple_assign (stmt1) && is_gimple_assign (stmt2)) > > + { > > + enum tree_code code1 =3D gimple_assign_rhs_code (stmt1); > > + enum tree_code code2 =3D gimple_assign_rhs_code (stmt2); > > + valid_minmax_p =3D (code1 =3D=3D MIN_EXPR || code1 =3D=3D MAX_E= XPR) > > + && (code2 =3D=3D MIN_EXPR || code2 =3D=3D > MAX_EXPR); > > + } > > + } > > + > > + if (!valid_minmax_p) > > + return false; > > + > > + if (!assign > > + || gimple_code (assign) !=3D GIMPLE_ASSIGN) > > + return false; > > + > > + lhs =3D gimple_assign_lhs (assign); > > + ass_code =3D gimple_assign_rhs_code (assign); > > + if (ass_code !=3D MAX_EXPR && ass_code !=3D MIN_EXPR) > > + return false; > > + > > + op0 =3D gimple_assign_rhs1 (assign); > > + op1 =3D gimple_assign_rhs2 (assign); > > + > > + assign =3D last_and_only_stmt (alt_middle_bb); > > + if (!assign > > + || gimple_code (assign) !=3D GIMPLE_ASSIGN) > > + return false; > > + > > + alt_lhs =3D gimple_assign_lhs (assign); > > + if (ass_code !=3D gimple_assign_rhs_code (assign)) > > + return false; > > + > > + if (!operand_equal_for_phi_arg_p (lhs, arg_true) > > + || !operand_equal_for_phi_arg_p (alt_lhs, arg_false)) > > + return false; > > + > > + alt_op0 =3D gimple_assign_rhs1 (assign); > > + alt_op1 =3D gimple_assign_rhs2 (assign); > > + > > + if ((operand_equal_for_phi_arg_p (op0, smaller) > > + || (alt_smaller > > + && operand_equal_for_phi_arg_p (op0, alt_smaller))) > > + && (operand_equal_for_phi_arg_p (alt_op0, larger) > > + || (alt_larger > > + && operand_equal_for_phi_arg_p (alt_op0, alt_larger)))) > > + { > > + /* We got here if the condition is true, i.e., SMALLER < LARGER. *= / > > + if (!operand_equal_for_phi_arg_p (op1, alt_op1)) > > + return false; > > + > > + if ((arg0 =3D strip_bit_not (op0)) !=3D NULL > > + && (arg1 =3D strip_bit_not (alt_op0)) !=3D NULL > > + && (bound =3D strip_bit_not (op1)) !=3D NULL) > > + { > > + minmax =3D MAX_EXPR; > > + ass_code =3D invert_minmax_code (ass_code); > > + invert =3D true; > > + } > > + else > > + { > > + bound =3D op1; > > + minmax =3D MIN_EXPR; > > + arg0 =3D op0; > > + arg1 =3D alt_op0; > > + } > > + } > > + else if ((operand_equal_for_phi_arg_p (op0, larger) > > + || (alt_larger > > + && operand_equal_for_phi_arg_p (op0, alt_larger))) > > + && (operand_equal_for_phi_arg_p (alt_op0, smaller) > > + || (alt_smaller > > + && operand_equal_for_phi_arg_p (alt_op0, > alt_smaller)))) > > + { > > + /* We got here if the condition is true, i.e., SMALLER > LARGER. *= / > > + if (!operand_equal_for_phi_arg_p (op1, alt_op1)) > > + return false; > > + > > + if ((arg0 =3D strip_bit_not (op0)) !=3D NULL > > + && (arg1 =3D strip_bit_not (alt_op0)) !=3D NULL > > + && (bound =3D strip_bit_not (op1)) !=3D NULL) > > + { > > + minmax =3D MIN_EXPR; > > + ass_code =3D invert_minmax_code (ass_code); > > + invert =3D true; > > + } > > + else > > + { > > + bound =3D op1; > > + minmax =3D MAX_EXPR; > > + arg0 =3D op0; > > + arg1 =3D alt_op0; > > + } > > + } > > + else > > + return false; > > + > > + /* Emit the statement to compute min/max. */ > > + location_t locus =3D gimple_location (last_stmt (cond_bb)); > > + gimple_seq stmts =3D NULL; > > + tree phi_result =3D PHI_RESULT (phi); > > + result =3D gimple_build (&stmts, locus, minmax, TREE_TYPE (phi_r= esult), > > + arg0, bound); > > + result =3D gimple_build (&stmts, locus, ass_code, TREE_TYPE > (phi_result), > > + result, arg1); > > + if (invert) > > + result =3D gimple_build (&stmts, locus, BIT_NOT_EXPR, TREE_TYPE > (phi_result), > > + result); > > + > > + gsi =3D gsi_last_bb (cond_bb); > > + gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); > > + > > + replace_phi_edge_with_variable (cond_bb, e1, phi, result, > > + false); > > + > > + return true; > > + } > > else > > { > > /* Recognize the following case, assuming d <=3D u: > > >=20 > -- > Richard Biener > SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 > Nuernberg, Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, > Boudien Moerman; HRB 36809 (AG Nuernberg)