From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM12-DM6-obe.outbound.protection.outlook.com (mail-dm6nam12on20701.outbound.protection.outlook.com [IPv6:2a01:111:f403:2417::701]) by sourceware.org (Postfix) with ESMTPS id AAF293871030 for ; Wed, 26 Jun 2024 14:50:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AAF293871030 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=os.amperecomputing.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=os.amperecomputing.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AAF293871030 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=2a01:111:f403:2417::701 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1719413424; cv=pass; b=n7PND3s/7qJxVT6Nc2bkku3LO4lZcst/nltA9WztrKpgqwSG8xkcBCdIg7lYCchGb0DBKlSsBWMVpKBGKHlCML3E4YJQfGzji044CCLG/HHxgrfyIVMFdNmYavkac4x991QTdNNJ2olV7VzjvaAETW3bCmP8qfPsb3jhZSV+HGw= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1719413424; c=relaxed/simple; bh=qRc/GA4hyJf6zMmDOUHF94xsOkWIypChQ1RR60OmdII=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=C5C+bq4+9x/E8qh4v9+dZGFM0g+zymUu1pemLZlSFEs6YDLcW8GOcbrVsYzRpqV715Ill+wU36gi7AhJLXw+Q+v/cGp4bhPeg2FZBjv28MhK1enkoPFEcV7WLYLbbhRAKLBV1FsOlBy8Px727h8doFXg0Zrb7NemotxJMkOjoR0= ARC-Authentication-Results: i=2; server2.sourceware.org ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Ah8GndhoKyiW5zIUciZmORf4zRTWOMX5A7fjhJSZPWvdlj+6oxHkHw9Zs7IdxMtW9ptp3ONsM21zisCHmW270zrjcQnQCxNo1LS0tps7TqC4QTUn/N2ozOxhJwp7OXvzMptGVscq//SW04goLll8rVihKgpG0aSXavwOp4hxLMsBKIanU04S715/BpqGlN4DtYP87CKLdEeQI9kB9P3yWaMXaDMB7x7GffLffuh4vyoQf17hERGnSQnwYsRsE/yk8Hl7NsCcEHBo13Q3qas7wIggc8aXXGd7WceriQA3bAdSXzaw2+BhYbBST9KkNvR4B5/Eizs7advzEKApz9dE+g== 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=/V/JFt3pbMIANEkoqdW0/IV3MT0ODKet8Q3Ua5WkjF0=; b=BceqMNvvUI9K95U1d+AXcWDIgzpgs4UIEflmKcYMu03sNAat5+3T0H95rAK8rbw5nEO6qbk30A19guIAs5PbwbVUc5FMrS7gc6TCs9s1R+Knw4n4/0wtChq/eomSibpbyLoa4KbmrQWf11NOvgKZ+sZAVaoVd0sW1TWJA9BPkdhPMHpqbWMj/W+79xVhT8gCFHsivUfmRQvRYStFeyrXqTh0oVnHSqgplt04InN4YoNJls8NnvLAbsDHddCYciJ7wag62vVvO5GgNukUtkZL84cFbjac8hMwOJC3HakiVGCvGVuph2d8aeUaHIctZt3HQnLStZl0S7hOrY6q8eSUlg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/V/JFt3pbMIANEkoqdW0/IV3MT0ODKet8Q3Ua5WkjF0=; b=JN9hB0CkQhXONj3v3L5T53p5S7ZbK/2XIv0K3QpprdfBZB1uuVUlJwg1Hwjn7HFRMIr2CA6vyqFbss5In799PGCb4JLe+/5s/kXbnjgnhdgT9NywDG+z3ARu6+GyNaRk2PS5UfwH84yEqCR0DXgfKhtSHAavT72+U3eE0wY+EUg= Received: from LV2PR01MB7839.prod.exchangelabs.com (2603:10b6:408:14f::13) by PH0PR01MB6618.prod.exchangelabs.com (2603:10b6:510:78::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.32; Wed, 26 Jun 2024 14:50:06 +0000 Received: from LV2PR01MB7839.prod.exchangelabs.com ([fe80::2ac3:5a77:36fd:9c63]) by LV2PR01MB7839.prod.exchangelabs.com ([fe80::2ac3:5a77:36fd:9c63%4]) with mapi id 15.20.7698.025; Wed, 26 Jun 2024 14:50:06 +0000 From: Feng Xue OS To: Richard Biener CC: "gcc-patches@gcc.gnu.org" Subject: Re: [PATCH 7/8] vect: Support multiple lane-reducing operations for loop reduction [PR114440] Thread-Topic: [PATCH 7/8] vect: Support multiple lane-reducing operations for loop reduction [PR114440] Thread-Index: AQHaww0x/TTxzniavkuqtVlcAVxhibHVait1gAF8CYCAATEoYoACEl73 Date: Wed, 26 Jun 2024 14:50:06 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: msip_labels: MSIP_Label_5b82cb1d-c2e0-4643-920a-bbe7b2d7cc47_Enabled=True;MSIP_Label_5b82cb1d-c2e0-4643-920a-bbe7b2d7cc47_SiteId=3bc2b170-fd94-476d-b0ce-4229bdc904a7;MSIP_Label_5b82cb1d-c2e0-4643-920a-bbe7b2d7cc47_SetDate=2024-06-26T14:50:05.842Z;MSIP_Label_5b82cb1d-c2e0-4643-920a-bbe7b2d7cc47_Name=Confidential;MSIP_Label_5b82cb1d-c2e0-4643-920a-bbe7b2d7cc47_ContentBits=0;MSIP_Label_5b82cb1d-c2e0-4643-920a-bbe7b2d7cc47_Method=Standard; authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=os.amperecomputing.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: LV2PR01MB7839:EE_|PH0PR01MB6618:EE_ x-ms-office365-filtering-correlation-id: b288cba8-75e1-4ab6-c96f-08dc95ef44f0 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0;ARA:13230038|366014|376012|1800799022|38070700016; x-microsoft-antispam-message-info: =?us-ascii?Q?6Q8beBE2+w4rbT1HHs9xCgedwr0IQuJRaS5LzL2+N770tdLYNeYeOtT9eMRM?= =?us-ascii?Q?6cD/H9kZyZjL9BHIIgGNQu8lAZGtBtULwOWPJZH2wyPnPD77ZPebu04MezzT?= =?us-ascii?Q?AxRdWG/3lllOdvnmM9DHPpur3Zr2ScRTnOKyHsTH+s1jikxIR1YRnSHcb6tM?= =?us-ascii?Q?UbWF3XU1g0hrWGz4A6R4XkscNZ+3obyz9CVTZSXyPS3wMWDJ0DB0lj/Hp9nt?= =?us-ascii?Q?REX11mfl67mW3ToIEjpsjTS6z9N8yr9Y7a+hlw8zTB8B/AYL/+528+voQoXl?= =?us-ascii?Q?OX/mSy5aMCJNpRm3xBzRDTOEyQAm2b52Jt8N2gU21B9zKG/I6gySONSVzZqd?= =?us-ascii?Q?0Q0AHRo4k3wbAG71QDfx5V9MWhPrQhbCX9UsfTKvL/gUtiHZ/LjouZ3GVQ21?= =?us-ascii?Q?FxmyKFEnNp773bl/1BlgMajdDOsTrCodv8EQaJZara3tO1vlE7aYHtIYLxds?= =?us-ascii?Q?14ZjNe+7JcUB+kvouNjOrSezJkvTmPi0Ol9d2SVQAU27n/LrVwKaBrPD0ILh?= =?us-ascii?Q?r3SpEOAdppzf6nkc0/tJga/OBGLwCINg8c8zc65vMQgx3IUm0TSx6SWdrt9H?= =?us-ascii?Q?FEMNjp2nVEoL3PzII0yjAgY3NXyopGG//i8Jr8LQxKbzqXo6bJHtwYFxJUnb?= =?us-ascii?Q?6MFoJgddgXJPKvr4PrRrd1Lfsu9yEEXAQ7TvPYC2NpsMAxDy5nj7qc8eWKEM?= =?us-ascii?Q?hgj0NCs0MHuMfNjMCcR7PQMLuRPJErbEkw5b94+IDyYPXPksx/QbpXAFnjWG?= =?us-ascii?Q?f4kzJc78BQqyuIhTImKK/m2aExemKTHsCOtw9aAPdh0e4gUU94rRiFqbsezc?= =?us-ascii?Q?UqSA/JqlINGtsZzo51XSMEBbEuwUS984hG1687zbXbbIbQh6J3Wk9RaK/P58?= =?us-ascii?Q?ovTv3qMh7oJoQCwkQb+tpKNRqj6LhAys8GCg1vwvadZef83Qq77qASCtglsD?= =?us-ascii?Q?mDLA7Mm70j3GzuqKdsrrO04clNQ8dsX1XfMQUKWtNxEyQNUoVm/vOqpxelM0?= =?us-ascii?Q?8SUE4/D3CgQF7oMsMy8iXsMqTY5fYdqElvjZ0zHYvpYJACIJZ85xC0Ml7dNi?= =?us-ascii?Q?t8uMA+2KStaxk338erFzWeTn6RNeWkMF9EENuPRbhOVecdHj+MC/CyjWBL3a?= =?us-ascii?Q?O2OqjrbiKtUEaWz2ZvuPGKN4IYQ6SBxKDC2drzcRAgRCCz+LbN+nkpCCTCmV?= =?us-ascii?Q?xjFbFG6n63IEmUQP3mTKwWv4Fp3/J5a1ZXLtIbCi9qduvsgx9NkdOxtZ6eRk?= =?us-ascii?Q?q9lfPX0rZgxkuUKG67uTtgGTVSv6EogZfLmIdQ86QyZ0AV+4Q1FZ15PElBLA?= =?us-ascii?Q?6AxiqAwydwgR7q5yYpxrBLUz?= x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LV2PR01MB7839.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(13230038)(366014)(376012)(1800799022)(38070700016);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?7POfXyqy/bCVng/Bg/2P3tMlpC5jWTLAN2AQ7k5LMYd+mi60XP9JdLq0CsEA?= =?us-ascii?Q?jJTD4kAVKwL3qW1q9RXY3K57Z7ID/pLGIaSgcmpBaeJ0tXyRhvPE839c8cB9?= =?us-ascii?Q?SZP/DVHn3p+Zqy/ZUtGnv8zppVeCxabIcZZkvylKHNjIpoidLAFDjASldZoV?= =?us-ascii?Q?gKQrD1Y9xx7e4tntfnb9VGnLb0MUIG7PvSLOF6uCtG2K0Sl05fh65mjAy8ua?= =?us-ascii?Q?5LnDETVpBCee/sUnVxIUofwzziZ+aQ+qQBenUu3iKNkgW5ecGSP7eUb6AgOt?= =?us-ascii?Q?2/NKovy1/T3qNqD5/A7R341WKUvVNJDdFu8BgG1PZ3epZv75ohTYEPDsja0t?= =?us-ascii?Q?cgZbm/DSzcpPNzh59lUwz7RhUtAdY9EVmweU6t9WISbPrjVIrwmkzMJySLpT?= =?us-ascii?Q?y8fQxWBEyNkFLbnAIQduIpvJimsc9DdVsDE+BtGit2IFgkh+BDlTbOgJbjtC?= =?us-ascii?Q?pN/J7Hn6OuXdl6Flf7QeMmcu5KSK1tSfwqvM9lBmeD8jfOmF+vRyJwTLBIIH?= =?us-ascii?Q?8w56SstSMLheo5WAJzyjEuKD0++EV3ofwsnKx0kIvwJDRoEZnJVh0qlUZknf?= =?us-ascii?Q?Vhv12omPF1FNUUPI51vpUka4xFzK1XrGXj8+yRMVfYttKlBcwpV/oByuabgd?= =?us-ascii?Q?GKkQbmedKhY20ZP8cKsYWsLkVt7pQ4zi5mx1DdFoUYSiIqKF6T2sH8te23W3?= =?us-ascii?Q?k1/ExGdIfUuv+x1rc0fxnxkV6bi4x3+zhPfQ2b0Gk6MTjxOTBO2NL1cYuW9c?= =?us-ascii?Q?mfFJ4QEGEgc1C+OraPMBqFtsTWqgNliuGY45z9PLVMVn7qdsVoPa+omnPYwD?= =?us-ascii?Q?G7GrqhO60WDkyJFgmqZjkRD4jItlbIo8gycdPoozT+kGJD7p7YOc82Nm8RDh?= =?us-ascii?Q?13WADM9fRxX34jkE4kJay2izVu0C9pBFm5dwf0+6YHq/bXX463Mp6f9nRQEU?= =?us-ascii?Q?Zxm5zV5IQT4Pbg20nCYRRVnoo+WZ91+XlENZPX1D1GYy2lv1PmH7G/yuO0R5?= =?us-ascii?Q?8Ua1Gvdh1Nfex+j8HMkClWBZPaUYXeyTCG2Nph+gMtHyVqqUj6w//Dtb8+5g?= =?us-ascii?Q?D5UekDyFakkM/BSk/YxjkRl53pS+Hoj2IE/adnqS3EKWqhd1pnAZHcrikK5e?= =?us-ascii?Q?Ha8OkppluaEupK/aZLgby/3K4sNngdwtAIwdd+IAH2kVeHQVwp7seZ95Qkh1?= =?us-ascii?Q?RKgyb09LYfkGpRBi4METOXOOtZe3BQWO8yL0GfaiUHNcvdryEK85rcwCIajb?= =?us-ascii?Q?2li5LSxii+33Zf/jVOJ71lsN98VLiJMoUwv/46B+52LW+HBErMlfs6SrY9kZ?= =?us-ascii?Q?g5V1c0UFnIxIOPQQC9poYSUPB34nHY7twKxfwNByaZZeNT8QwT9upDSjeZfR?= =?us-ascii?Q?WwBNuObnvoyMsLbcD1GDf2dNv2PPFWRpBq9pc9fTNmbBXOcIggjFpr594lE4?= =?us-ascii?Q?Z+4+mWHPHO9TeYNXvJrVu0Au702Mdi7sleiVJwJtP1Ad0zRuKj5UabAKljIx?= =?us-ascii?Q?X9KzatFPfC0IflqGhpYLjQYI/SUaUYA1Q7jodOOCumbBD0I77wH/+EO29Wu+?= =?us-ascii?Q?iT6TErD0xTsuFQ5vjFoOc7gZcDb0viXGkV+OYEv0?= Content-Type: multipart/mixed; boundary="_002_LV2PR01MB78391AB09E644D51CFB34F2FF7D62LV2PR01MB7839prod_" MIME-Version: 1.0 X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: LV2PR01MB7839.prod.exchangelabs.com X-MS-Exchange-CrossTenant-Network-Message-Id: b288cba8-75e1-4ab6-c96f-08dc95ef44f0 X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Jun 2024 14:50:06.5728 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: DCjerzHf1NFOBa5gWCUPQMTvV8RxGiF4tiE0VTKJI2SZ2S+N+O5q5SaY0leu0yHI0VgY0ALL3XngLpJ830iHLORnzsAQ6e9ur/zgP2R8Its= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6618 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,GIT_PATCH_0,SPF_HELO_PASS,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: --_002_LV2PR01MB78391AB09E644D51CFB34F2FF7D62LV2PR01MB7839prod_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Updated the patch. For lane-reducing operation(dot-prod/widen-sum/sad) in loop reduction, curr= ent vectorizer could only handle the pattern if the reduction chain does not contain other operation, no matter the other is normal or lane-reducing. Actually, to allow multiple arbitrary lane-reducing operations, we need to support vectorization of loop reduction chain with mixed input vectypes. Si= nce lanes of vectype may vary with operation, the effective ncopies of vectoriz= ed statements for operation also may not be same to each other, this causes mismatch on vectorized def-use cycles. A simple way is to align all operati= ons with the one that has the most ncopies, the gap could be complemented by generating extra trivial pass-through copies. For example: int sum =3D 0; for (i) { sum +=3D d0[i] * d1[i]; // dot-prod sum +=3D w[i]; // widen-sum sum +=3D abs(s0[i] - s1[i]); // sad sum +=3D n[i]; // normal } The vector size is 128-bit vectorization factor is 16. Reduction statements would be transformed as: vector<4> int sum_v0 =3D { 0, 0, 0, 0 }; vector<4> int sum_v1 =3D { 0, 0, 0, 0 }; vector<4> int sum_v2 =3D { 0, 0, 0, 0 }; vector<4> int sum_v3 =3D { 0, 0, 0, 0 }; for (i / 16) { sum_v0 =3D DOT_PROD (d0_v0[i: 0 ~ 15], d1_v0[i: 0 ~ 15], sum_v0); sum_v1 =3D sum_v1; // copy sum_v2 =3D sum_v2; // copy sum_v3 =3D sum_v3; // copy sum_v0 =3D WIDEN_SUM (w_v0[i: 0 ~ 15], sum_v0); sum_v1 =3D sum_v1; // copy sum_v2 =3D sum_v2; // copy sum_v3 =3D sum_v3; // copy sum_v0 =3D SAD (s0_v0[i: 0 ~ 7 ], s1_v0[i: 0 ~ 7 ], sum_v0); sum_v1 =3D SAD (s0_v1[i: 8 ~ 15], s1_v1[i: 8 ~ 15], sum_v1); sum_v2 =3D sum_v2; // copy sum_v3 =3D sum_v3; // copy sum_v0 +=3D n_v0[i: 0 ~ 3 ]; sum_v1 +=3D n_v1[i: 4 ~ 7 ]; sum_v2 +=3D n_v2[i: 8 ~ 11]; sum_v3 +=3D n_v3[i: 12 ~ 15]; } 2024-03-22 Feng Xue gcc/ PR tree-optimization/114440 * tree-vectorizer.h (vectorizable_lane_reducing): New function declaration. * tree-vect-stmts.cc (vect_analyze_stmt): Call new function vectorizable_lane_reducing to analyze lane-reducing operation. * tree-vect-loop.cc (vect_model_reduction_cost): Remove cost comput= ation code related to emulated_mixed_dot_prod. (vect_reduction_update_partial_vector_usage): Compute ncopies as th= e original means for single-lane slp node. (vectorizable_lane_reducing): New function. (vectorizable_reduction): Allow multiple lane-reducing operations i= n loop reduction. Move some original lane-reducing related code to vectorizable_lane_reducing. (vect_transform_reduction): Extend transformation to support reduct= ion statements with mixed input vectypes. gcc/testsuite/ PR tree-optimization/114440 * gcc.dg/vect/vect-reduc-chain-1.c * gcc.dg/vect/vect-reduc-chain-2.c * gcc.dg/vect/vect-reduc-chain-3.c * gcc.dg/vect/vect-reduc-chain-dot-slp-1.c * gcc.dg/vect/vect-reduc-chain-dot-slp-2.c * gcc.dg/vect/vect-reduc-chain-dot-slp-3.c * gcc.dg/vect/vect-reduc-chain-dot-slp-4.c * gcc.dg/vect/vect-reduc-dot-slp-1.c --- .../gcc.dg/vect/vect-reduc-chain-1.c | 62 ++++ .../gcc.dg/vect/vect-reduc-chain-2.c | 77 ++++ .../gcc.dg/vect/vect-reduc-chain-3.c | 66 ++++ .../gcc.dg/vect/vect-reduc-chain-dot-slp-1.c | 95 +++++ .../gcc.dg/vect/vect-reduc-chain-dot-slp-2.c | 67 ++++ .../gcc.dg/vect/vect-reduc-chain-dot-slp-3.c | 79 +++++ .../gcc.dg/vect/vect-reduc-chain-dot-slp-4.c | 63 ++++ .../gcc.dg/vect/vect-reduc-dot-slp-1.c | 60 ++++ gcc/tree-vect-loop.cc | 333 ++++++++++++++---- gcc/tree-vect-stmts.cc | 2 + gcc/tree-vectorizer.h | 2 + 11 files changed, 836 insertions(+), 70 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-1.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-2.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-3.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-1.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-2.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-3.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-4.c create mode 100644 gcc/testsuite/gcc.dg/vect/vect-reduc-dot-slp-1.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-1.c b/gcc/testsuite= /gcc.dg/vect/vect-reduc-chain-1.c new file mode 100644 index 00000000000..04bfc419dbd --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-1.c @@ -0,0 +1,62 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#define N 50 + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res, + SIGNEDNESS_2 char *restrict a, + SIGNEDNESS_2 char *restrict b, + SIGNEDNESS_2 char *restrict c, + SIGNEDNESS_2 char *restrict d, + SIGNEDNESS_1 int *restrict e) +{ + for (int i =3D 0; i < N; ++i) + { + res +=3D a[i] * b[i]; + res +=3D c[i] * d[i]; + res +=3D e[i]; + } + return res; +} + +#define BASE ((SIGNEDNESS_2 int) -1 < 0 ? -126 : 4) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 char a[N], b[N]; + SIGNEDNESS_2 char c[N], d[N]; + SIGNEDNESS_1 int e[N]; + int expected =3D 0x12345; + for (int i =3D 0; i < N; ++i) + { + a[i] =3D BASE + i * 5; + b[i] =3D BASE + OFFSET + i * 4; + c[i] =3D BASE + i * 2; + d[i] =3D BASE + OFFSET + i * 3; + e[i] =3D i; + asm volatile ("" ::: "memory"); + expected +=3D a[i] * b[i]; + expected +=3D c[i] * d[i]; + expected +=3D e[i]; + } + if (f (0x12345, a, b, c, d, e) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump-times "vectorizing statement: \\S+ =3D DOT_= PROD_EXPR" 2 "vect" { target vect_sdot_qi } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-2.c b/gcc/testsuite= /gcc.dg/vect/vect-reduc-chain-2.c new file mode 100644 index 00000000000..6c803b80120 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-2.c @@ -0,0 +1,77 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#define N 50 + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 unsigned +#define SIGNEDNESS_3 signed +#define SIGNEDNESS_4 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +fn (SIGNEDNESS_1 int res, + SIGNEDNESS_2 char *restrict a, + SIGNEDNESS_2 char *restrict b, + SIGNEDNESS_3 char *restrict c, + SIGNEDNESS_3 char *restrict d, + SIGNEDNESS_4 short *restrict e, + SIGNEDNESS_4 short *restrict f, + SIGNEDNESS_1 int *restrict g) +{ + for (int i =3D 0; i < N; ++i) + { + res +=3D a[i] * b[i]; + res +=3D i + 1; + res +=3D c[i] * d[i]; + res +=3D e[i] * f[i]; + res +=3D g[i]; + } + return res; +} + +#define BASE2 ((SIGNEDNESS_2 int) -1 < 0 ? -126 : 4) +#define BASE3 ((SIGNEDNESS_3 int) -1 < 0 ? -126 : 4) +#define BASE4 ((SIGNEDNESS_4 int) -1 < 0 ? -1026 : 373) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 char a[N], b[N]; + SIGNEDNESS_3 char c[N], d[N]; + SIGNEDNESS_4 short e[N], f[N]; + SIGNEDNESS_1 int g[N]; + int expected =3D 0x12345; + for (int i =3D 0; i < N; ++i) + { + a[i] =3D BASE2 + i * 5; + b[i] =3D BASE2 + OFFSET + i * 4; + c[i] =3D BASE3 + i * 2; + d[i] =3D BASE3 + OFFSET + i * 3; + e[i] =3D BASE4 + i * 6; + f[i] =3D BASE4 + OFFSET + i * 5; + g[i] =3D i; + asm volatile ("" ::: "memory"); + expected +=3D a[i] * b[i]; + expected +=3D i + 1; + expected +=3D c[i] * d[i]; + expected +=3D e[i] * f[i]; + expected +=3D g[i]; + } + if (fn (0x12345, a, b, c, d, e, f, g) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump "vectorizing statement: \\S+ =3D DOT_PROD_E= XPR" "vect" { target { vect_sdot_qi } } } } */ +/* { dg-final { scan-tree-dump "vectorizing statement: \\S+ =3D DOT_PROD_E= XPR" "vect" { target { vect_udot_qi } } } } */ +/* { dg-final { scan-tree-dump "vectorizing statement: \\S+ =3D DOT_PROD_E= XPR" "vect" { target { vect_sdot_hi } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-3.c b/gcc/testsuite= /gcc.dg/vect/vect-reduc-chain-3.c new file mode 100644 index 00000000000..a41e4b176c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-3.c @@ -0,0 +1,66 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ + +#include "tree-vect.h" + +#define N 50 + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 unsigned +#define SIGNEDNESS_3 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res, + SIGNEDNESS_2 char *restrict a, + SIGNEDNESS_2 char *restrict b, + SIGNEDNESS_3 short *restrict c, + SIGNEDNESS_3 short *restrict d, + SIGNEDNESS_1 int *restrict e) +{ + for (int i =3D 0; i < N; ++i) + { + short diff =3D a[i] - b[i]; + SIGNEDNESS_2 short abs =3D diff < 0 ? -diff : diff; + res +=3D abs; + res +=3D c[i] * d[i]; + res +=3D e[i]; + } + return res; +} + +#define BASE2 ((SIGNEDNESS_2 int) -1 < 0 ? -126 : 4) +#define BASE3 ((SIGNEDNESS_3 int) -1 < 0 ? -1236 : 373) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 char a[N], b[N]; + SIGNEDNESS_3 short c[N], d[N]; + SIGNEDNESS_1 int e[N]; + int expected =3D 0x12345; + for (int i =3D 0; i < N; ++i) + { + a[i] =3D BASE2 + i * 5; + b[i] =3D BASE2 - i * 4; + c[i] =3D BASE3 + i * 2; + d[i] =3D BASE3 + OFFSET + i * 3; + e[i] =3D i; + asm volatile ("" ::: "memory"); + short diff =3D a[i] - b[i]; + SIGNEDNESS_2 short abs =3D diff < 0 ? -diff : diff; + expected +=3D abs; + expected +=3D c[i] * d[i]; + expected +=3D e[i]; + } + if (f (0x12345, a, b, c, d, e) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vectorizing statement: \\S+ =3D SAD_EXPR" = "vect" { target vect_udot_qi } } } */ +/* { dg-final { scan-tree-dump "vectorizing statement: \\S+ =3D DOT_PROD_E= XPR" "vect" { target vect_sdot_hi } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-1.c b/gcc/t= estsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-1.c new file mode 100644 index 00000000000..c2831fbcc8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-1.c @@ -0,0 +1,95 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res, + SIGNEDNESS_2 char *a, + SIGNEDNESS_2 char *b, + int step, int n) +{ + for (int i =3D 0; i < n; i++) + { + res +=3D a[0] * b[0]; + res +=3D a[1] * b[1]; + res +=3D a[2] * b[2]; + res +=3D a[3] * b[3]; + res +=3D a[4] * b[4]; + res +=3D a[5] * b[5]; + res +=3D a[6] * b[6]; + res +=3D a[7] * b[7]; + res +=3D a[8] * b[8]; + res +=3D a[9] * b[9]; + res +=3D a[10] * b[10]; + res +=3D a[11] * b[11]; + res +=3D a[12] * b[12]; + res +=3D a[13] * b[13]; + res +=3D a[14] * b[14]; + res +=3D a[15] * b[15]; + + a +=3D step; + b +=3D step; + } + + return res; +} + +#define BASE ((SIGNEDNESS_2 int) -1 < 0 ? -126 : 4) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 char a[100], b[100]; + int expected =3D 0x12345; + int step =3D 16; + int n =3D 2; + int t =3D 0; + + for (int i =3D 0; i < sizeof (a) / sizeof (a[0]); ++i) + { + a[i] =3D BASE + i * 5; + b[i] =3D BASE + OFFSET + i * 4; + asm volatile ("" ::: "memory"); + } + + for (int i =3D 0; i < n; i++) + { + asm volatile ("" ::: "memory"); + expected +=3D a[t + 0] * b[t + 0]; + expected +=3D a[t + 1] * b[t + 1]; + expected +=3D a[t + 2] * b[t + 2]; + expected +=3D a[t + 3] * b[t + 3]; + expected +=3D a[t + 4] * b[t + 4]; + expected +=3D a[t + 5] * b[t + 5]; + expected +=3D a[t + 6] * b[t + 6]; + expected +=3D a[t + 7] * b[t + 7]; + expected +=3D a[t + 8] * b[t + 8]; + expected +=3D a[t + 9] * b[t + 9]; + expected +=3D a[t + 10] * b[t + 10]; + expected +=3D a[t + 11] * b[t + 11]; + expected +=3D a[t + 12] * b[t + 12]; + expected +=3D a[t + 13] * b[t + 13]; + expected +=3D a[t + 14] * b[t + 14]; + expected +=3D a[t + 15] * b[t + 15]; + t +=3D step; + } + + if (f (0x12345, a, b, step, n) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorizing statement: \\S+ =3D DOT_= PROD_EXPR" 16 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-2.c b/gcc/t= estsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-2.c new file mode 100644 index 00000000000..4114264a364 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-2.c @@ -0,0 +1,67 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res, + SIGNEDNESS_2 char *a, + SIGNEDNESS_2 char *b, + int n) +{ + for (int i =3D 0; i < n; i++) + { + res +=3D a[5 * i + 0] * b[5 * i + 0]; + res +=3D a[5 * i + 1] * b[5 * i + 1]; + res +=3D a[5 * i + 2] * b[5 * i + 2]; + res +=3D a[5 * i + 3] * b[5 * i + 3]; + res +=3D a[5 * i + 4] * b[5 * i + 4]; + } + + return res; +} + +#define BASE ((SIGNEDNESS_2 int) -1 < 0 ? -126 : 4) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 char a[100], b[100]; + int expected =3D 0x12345; + int n =3D 18; + + for (int i =3D 0; i < sizeof (a) / sizeof (a[0]); ++i) + { + a[i] =3D BASE + i * 5; + b[i] =3D BASE + OFFSET + i * 4; + asm volatile ("" ::: "memory"); + } + + for (int i =3D 0; i < n; i++) + { + asm volatile ("" ::: "memory"); + expected +=3D a[5 * i + 0] * b[5 * i + 0]; + expected +=3D a[5 * i + 1] * b[5 * i + 1]; + expected +=3D a[5 * i + 2] * b[5 * i + 2]; + expected +=3D a[5 * i + 3] * b[5 * i + 3]; + expected +=3D a[5 * i + 4] * b[5 * i + 4]; + } + + if (f (0x12345, a, b, n) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorizing statement: \\S+ =3D DOT_= PROD_EXPR" 5 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-3.c b/gcc/t= estsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-3.c new file mode 100644 index 00000000000..2cdecc36d16 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-3.c @@ -0,0 +1,79 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res, + SIGNEDNESS_2 short *a, + SIGNEDNESS_2 short *b, + int step, int n) +{ + for (int i =3D 0; i < n; i++) + { + res +=3D a[0] * b[0]; + res +=3D a[1] * b[1]; + res +=3D a[2] * b[2]; + res +=3D a[3] * b[3]; + res +=3D a[4] * b[4]; + res +=3D a[5] * b[5]; + res +=3D a[6] * b[6]; + res +=3D a[7] * b[7]; + + a +=3D step; + b +=3D step; + } + + return res; +} + +#define BASE ((SIGNEDNESS_2 int) -1 < 0 ? -1026 : 373) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 short a[100], b[100]; + int expected =3D 0x12345; + int step =3D 8; + int n =3D 2; + int t =3D 0; + + for (int i =3D 0; i < sizeof (a) / sizeof (a[0]); ++i) + { + a[i] =3D BASE + i * 5; + b[i] =3D BASE + OFFSET + i * 4; + asm volatile ("" ::: "memory"); + } + + for (int i =3D 0; i < n; i++) + { + asm volatile ("" ::: "memory"); + expected +=3D a[t + 0] * b[t + 0]; + expected +=3D a[t + 1] * b[t + 1]; + expected +=3D a[t + 2] * b[t + 2]; + expected +=3D a[t + 3] * b[t + 3]; + expected +=3D a[t + 4] * b[t + 4]; + expected +=3D a[t + 5] * b[t + 5]; + expected +=3D a[t + 6] * b[t + 6]; + expected +=3D a[t + 7] * b[t + 7]; + t +=3D step; + } + + if (f (0x12345, a, b, step, n) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorizing statement: \\S+ =3D DOT_= PROD_EXPR" 8 "vect" { target vect_sdot_hi } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-4.c b/gcc/t= estsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-4.c new file mode 100644 index 00000000000..32c0f30c77b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-chain-dot-slp-4.c @@ -0,0 +1,63 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res, + SIGNEDNESS_2 short *a, + SIGNEDNESS_2 short *b, + int n) +{ + for (int i =3D 0; i < n; i++) + { + res +=3D a[3 * i + 0] * b[3 * i + 0]; + res +=3D a[3 * i + 1] * b[3 * i + 1]; + res +=3D a[3 * i + 2] * b[3 * i + 2]; + } + + return res; +} + +#define BASE ((SIGNEDNESS_2 int) -1 < 0 ? -1026 : 373) +#define OFFSET 20 + +int +main (void) +{ + check_vect (); + + SIGNEDNESS_2 short a[100], b[100]; + int expected =3D 0x12345; + int n =3D 18; + + for (int i =3D 0; i < sizeof (a) / sizeof (a[0]); ++i) + { + a[i] =3D BASE + i * 5; + b[i] =3D BASE + OFFSET + i * 4; + asm volatile ("" ::: "memory"); + } + + for (int i =3D 0; i < n; i++) + { + asm volatile ("" ::: "memory"); + expected +=3D a[3 * i + 0] * b[3 * i + 0]; + expected +=3D a[3 * i + 1] * b[3 * i + 1]; + expected +=3D a[3 * i + 2] * b[3 * i + 2]; + } + + if (f (0x12345, a, b, n) !=3D expected) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorizing statement: \\S+ =3D DOT_= PROD_EXPR" 3 "vect" { target vect_sdot_hi } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-slp-1.c b/gcc/testsui= te/gcc.dg/vect/vect-reduc-dot-slp-1.c new file mode 100644 index 00000000000..84c82b023d4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-slp-1.c @@ -0,0 +1,60 @@ +/* Disabling epilogues until we find a better way to deal with scans. */ +/* { dg-do compile } */ +/* { dg-additional-options "--param vect-epilogues-nomask=3D0 -fdump-tree-= optimized" } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target arm_v8_2a_dotprod_neon_hw { target { aarc= h64*-*-* || arm*-*-* } } } */ +/* { dg-add-options arm_v8_2a_dotprod_neon } */ + +#include "tree-vect.h" + +#ifndef SIGNEDNESS_1 +#define SIGNEDNESS_1 signed +#define SIGNEDNESS_2 signed +#endif + +SIGNEDNESS_1 int __attribute__ ((noipa)) +f (SIGNEDNESS_1 int res0, + SIGNEDNESS_1 int res1, + SIGNEDNESS_1 int res2, + SIGNEDNESS_1 int res3, + SIGNEDNESS_1 int res4, + SIGNEDNESS_1 int res5, + SIGNEDNESS_1 int res6, + SIGNEDNESS_1 int res7, + SIGNEDNESS_1 int res8, + SIGNEDNESS_1 int res9, + SIGNEDNESS_1 int resA, + SIGNEDNESS_1 int resB, + SIGNEDNESS_1 int resC, + SIGNEDNESS_1 int resD, + SIGNEDNESS_1 int resE, + SIGNEDNESS_1 int resF, + SIGNEDNESS_2 char *a, + SIGNEDNESS_2 char *b) +{ + for (int i =3D 0; i < 64; i +=3D 16) + { + res0 +=3D a[i + 0x00] * b[i + 0x00]; + res1 +=3D a[i + 0x01] * b[i + 0x01]; + res2 +=3D a[i + 0x02] * b[i + 0x02]; + res3 +=3D a[i + 0x03] * b[i + 0x03]; + res4 +=3D a[i + 0x04] * b[i + 0x04]; + res5 +=3D a[i + 0x05] * b[i + 0x05]; + res6 +=3D a[i + 0x06] * b[i + 0x06]; + res7 +=3D a[i + 0x07] * b[i + 0x07]; + res8 +=3D a[i + 0x08] * b[i + 0x08]; + res9 +=3D a[i + 0x09] * b[i + 0x09]; + resA +=3D a[i + 0x0A] * b[i + 0x0A]; + resB +=3D a[i + 0x0B] * b[i + 0x0B]; + resC +=3D a[i + 0x0C] * b[i + 0x0C]; + resD +=3D a[i + 0x0D] * b[i + 0x0D]; + resE +=3D a[i + 0x0E] * b[i + 0x0E]; + resF +=3D a[i + 0x0F] * b[i + 0x0F]; + } + + return res0 ^ res1 ^ res2 ^ res3 ^ res4 ^ res5 ^ res6 ^ res7 ^ + res8 ^ res9 ^ resA ^ resB ^ resC ^ resD ^ resE ^ resF; +} + +/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "ve= ct" } } */ +/* { dg-final { scan-tree-dump-not "DOT_PROD_EXPR" "optimized" } } */ diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 419f4b08d2b..6bfb0e72905 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -5324,8 +5324,6 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, if (!gimple_extract_op (orig_stmt_info->stmt, &op)) gcc_unreachable (); - bool emulated_mixed_dot_prod =3D vect_is_emulated_mixed_dot_prod (stmt_i= nfo); - if (reduction_type =3D=3D EXTRACT_LAST_REDUCTION) /* No extra instructions are needed in the prologue. The loop body operations are costed in vectorizable_condition. */ @@ -5360,12 +5358,8 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, initial result of the data reduction, initial value of the index reduction. */ prologue_stmts =3D 4; - else if (emulated_mixed_dot_prod) - /* We need the initial reduction value and two invariants: - one that contains the minimum signed value and one that - contains half of its negative. */ - prologue_stmts =3D 3; else + /* We need the initial reduction value. */ prologue_stmts =3D 1; prologue_cost +=3D record_stmt_cost (cost_vec, prologue_stmts, scalar_to_vec, stmt_info, 0, @@ -7466,7 +7460,10 @@ vect_reduction_update_partial_vector_usage (loop_vec= _info loop_vinfo, vec_loop_lens *lens =3D &LOOP_VINFO_LENS (loop_vinfo); unsigned nvectors; - if (slp_node) + /* TODO: The number of vector statements for lane-reducing op is ove= r- + estimated, we have to recompute it when the containing slp node is + single-lane. Need a general means to correct this value. */ + if (slp_node && SLP_TREE_LANES (slp_node) > 1) nvectors =3D SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); else nvectors =3D vect_get_num_copies (loop_vinfo, vectype_in); @@ -7478,6 +7475,154 @@ vect_reduction_update_partial_vector_usage (loop_ve= c_info loop_vinfo, } } +/* Check if STMT_INFO is a lane-reducing operation that can be vectorized = in + the context of LOOP_VINFO, and vector cost will be recorded in COST_VEC= . + Now there are three such kinds of operations: dot-prod/widen-sum/sad + (sum-of-absolute-differences). + + For a lane-reducing operation, the loop reduction path that it lies in, + may contain normal operation, or other lane-reducing operation of diffe= rent + input type size, an example as: + + int sum =3D 0; + for (i) + { + ... + sum +=3D d0[i] * d1[i]; // dot-prod + sum +=3D w[i]; // widen-sum + sum +=3D abs(s0[i] - s1[i]); // sad + sum +=3D n[i]; // normal + ... + } + + Vectorization factor is essentially determined by operation whose input + vectype has the most lanes ("vector(16) char" in the example), while we + need to choose input vectype with the least lanes ("vector(4) int" in t= he + example) for the reduction PHI statement. */ + +bool +vectorizable_lane_reducing (loop_vec_info loop_vinfo, stmt_vec_info stmt_i= nfo, + slp_tree slp_node, stmt_vector_for_cost *cost_v= ec) +{ + gimple *stmt =3D stmt_info->stmt; + + if (!lane_reducing_stmt_p (stmt)) + return false; + + tree type =3D TREE_TYPE (gimple_assign_lhs (stmt)); + + if (!INTEGRAL_TYPE_P (type) && !SCALAR_FLOAT_TYPE_P (type)) + return false; + + /* Do not try to vectorize bit-precision reductions. */ + if (!type_has_mode_precision_p (type)) + return false; + + /* A lane-reducing op should be contained in some slp node. */ + if (!slp_node) + return false; + + for (int i =3D 0; i < (int) gimple_num_ops (stmt) - 1; i++) + { + stmt_vec_info def_stmt_info; + slp_tree slp_op; + tree op; + tree vectype; + enum vect_def_type dt; + + if (!vect_is_simple_use (loop_vinfo, stmt_info, slp_node, i, &op, + &slp_op, &dt, &vectype, &def_stmt_info)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "use not simple.\n"); + return false; + } + + if (!vectype) + { + vectype =3D get_vectype_for_scalar_type (loop_vinfo, TREE_TYPE (o= p), + slp_op); + if (!vectype) + return false; + } + + if (!vect_maybe_update_slp_op_vectype (slp_op, vectype)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "incompatible vector types for invariants\n"); + return false; + } + + if (i =3D=3D STMT_VINFO_REDUC_IDX (stmt_info)) + continue; + + /* There should be at most one cycle def in the stmt. */ + if (VECTORIZABLE_CYCLE_DEF (dt)) + return false; + } + + stmt_vec_info reduc_info =3D STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_= info)); + + /* TODO: Support lane-reducing operation that does not directly particip= ate + in loop reduction. */ + if (!reduc_info || STMT_VINFO_REDUC_IDX (stmt_info) < 0) + return false; + + /* Lane-reducing pattern inside any inner loop of LOOP_VINFO is not + recoginized. */ + gcc_assert (STMT_VINFO_DEF_TYPE (reduc_info) =3D=3D vect_reduction_def); + gcc_assert (STMT_VINFO_REDUC_TYPE (reduc_info) =3D=3D TREE_CODE_REDUCTIO= N); + + tree vectype_in =3D STMT_VINFO_REDUC_VECTYPE_IN (stmt_info); + int ncopies_for_cost; + + if (SLP_TREE_LANES (slp_node) > 1) + { + /* Now lane-reducing operations in a non-single-lane slp node should= only + come from the same loop reduction path. */ + gcc_assert (REDUC_GROUP_FIRST_ELEMENT (stmt_info)); + ncopies_for_cost =3D 1; + } + else + { + ncopies_for_cost =3D vect_get_num_copies (loop_vinfo, vectype_in); + gcc_assert (ncopies_for_cost >=3D 1); + } + + if (vect_is_emulated_mixed_dot_prod (stmt_info)) + { + /* We need extra two invariants: one that contains the minimum signe= d + value and one that contains half of its negative. */ + int prologue_stmts =3D 2; + unsigned cost =3D record_stmt_cost (cost_vec, prologue_stmts, + scalar_to_vec, stmt_info, 0, + vect_prologue); + if (dump_enabled_p ()) + dump_printf (MSG_NOTE, "vectorizable_lane_reducing: " + "extra prologue_cost =3D %d .\n", cost); + + /* Three dot-products and a subtraction. */ + ncopies_for_cost *=3D 4; + } + + record_stmt_cost (cost_vec, ncopies_for_cost, vector_stmt, stmt_info, 0, + vect_body); + + if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)) + { + enum tree_code code =3D gimple_assign_rhs_code (stmt); + vect_reduction_update_partial_vector_usage (loop_vinfo, reduc_info, + slp_node, code, type, + vectype_in); + } + + /* Transform via vect_transform_reduction. */ + STMT_VINFO_TYPE (stmt_info) =3D reduc_vec_info_type; + return true; +} + /* Function vectorizable_reduction. Check if STMT_INFO performs a reduction operation that can be vectorize= d. @@ -7811,18 +7956,6 @@ vectorizable_reduction (loop_vec_info loop_vinfo, if (!type_has_mode_precision_p (op.type)) return false; - /* For lane-reducing ops we're reducing the number of reduction PHIs - which means the only use of that may be in the lane-reducing operatio= n. */ - if (lane_reducing - && reduc_chain_length !=3D 1 - && !only_slp_reduc_chain) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "lane-reducing reduction with extra stmts.\n"); - return false; - } - /* Lane-reducing ops also never can be used in a SLP reduction group since we'll mix lanes belonging to different reductions. But it's OK to use them in a reduction chain or when the reduction group @@ -8362,14 +8495,11 @@ vectorizable_reduction (loop_vec_info loop_vinfo, && loop_vinfo->suggested_unroll_factor =3D=3D 1) single_defuse_cycle =3D true; - if (single_defuse_cycle || lane_reducing) + if (single_defuse_cycle && !lane_reducing) { gcc_assert (op.code !=3D COND_EXPR); - /* 4. Supportable by target? */ - bool ok =3D true; - - /* 4.1. check support for the operation in the loop + /* 4. check support for the operation in the loop This isn't necessary for the lane reduction codes, since they can only be produced by pattern matching, and it's up to the @@ -8378,14 +8508,13 @@ vectorizable_reduction (loop_vec_info loop_vinfo, mixed-sign dot-products can be implemented using signed dot-products. */ machine_mode vec_mode =3D TYPE_MODE (vectype_in); - if (!lane_reducing - && !directly_supported_p (op.code, vectype_in, optab_vector)) + if (!directly_supported_p (op.code, vectype_in, optab_vector)) { if (dump_enabled_p ()) dump_printf (MSG_NOTE, "op not supported by target.\n"); if (maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD) || !vect_can_vectorize_without_simd_p (op.code)) - ok =3D false; + single_defuse_cycle =3D false; else if (dump_enabled_p ()) dump_printf (MSG_NOTE, "proceeding using word mode.\n"); @@ -8398,16 +8527,6 @@ vectorizable_reduction (loop_vec_info loop_vinfo, dump_printf (MSG_NOTE, "using word mode not possible.\n"); return false; } - - /* lane-reducing operations have to go through vect_transform_reduct= ion. - For the other cases try without the single cycle optimization. *= / - if (!ok) - { - if (lane_reducing) - return false; - else - single_defuse_cycle =3D false; - } } if (dump_enabled_p () && single_defuse_cycle) dump_printf_loc (MSG_NOTE, vect_location, @@ -8415,22 +8534,14 @@ vectorizable_reduction (loop_vec_info loop_vinfo, "multiple vectors to one in the loop body\n"); STMT_VINFO_FORCE_SINGLE_CYCLE (reduc_info) =3D single_defuse_cycle; - /* If the reduction stmt is one of the patterns that have lane - reduction embedded we cannot handle the case of ! single_defuse_cycle= . */ - if ((ncopies > 1 && ! single_defuse_cycle) - && lane_reducing) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "multi def-use cycle not possible for lane-reducin= g " - "reduction operation\n"); - return false; - } + /* For lane-reducing operation, the below processing related to single + defuse-cycle will be done in its own vectorizable function. One more + thing to note is that the operation must not be involved in fold-left + reduction. */ + single_defuse_cycle &=3D !lane_reducing; if (slp_node - && !(!single_defuse_cycle - && !lane_reducing - && reduction_type !=3D FOLD_LEFT_REDUCTION)) + && (single_defuse_cycle || reduction_type =3D=3D FOLD_LEFT_REDUCTION= )) for (i =3D 0; i < (int) op.num_ops; i++) if (!vect_maybe_update_slp_op_vectype (slp_op[i], vectype_op[i])) { @@ -8443,28 +8554,20 @@ vectorizable_reduction (loop_vec_info loop_vinfo, vect_model_reduction_cost (loop_vinfo, stmt_info, reduc_fn, reduction_type, ncopies, cost_vec); /* Cost the reduction op inside the loop if transformed via - vect_transform_reduction. Otherwise this is costed by the - separate vectorizable_* routines. */ - if (single_defuse_cycle || lane_reducing) - { - int factor =3D 1; - if (vect_is_emulated_mixed_dot_prod (stmt_info)) - /* Three dot-products and a subtraction. */ - factor =3D 4; - record_stmt_cost (cost_vec, ncopies * factor, vector_stmt, - stmt_info, 0, vect_body); - } + vect_transform_reduction for non-lane-reducing operation. Otherwise + this is costed by the separate vectorizable_* routines. */ + if (single_defuse_cycle) + record_stmt_cost (cost_vec, ncopies, vector_stmt, stmt_info, 0, vect_b= ody); if (dump_enabled_p () && reduction_type =3D=3D FOLD_LEFT_REDUCTION) dump_printf_loc (MSG_NOTE, vect_location, "using an in-order (fold-left) reduction.\n"); STMT_VINFO_TYPE (orig_stmt_of_analysis) =3D cycle_phi_info_type; - /* All but single defuse-cycle optimized, lane-reducing and fold-left - reductions go through their own vectorizable_* routines. */ - if (!single_defuse_cycle - && !lane_reducing - && reduction_type !=3D FOLD_LEFT_REDUCTION) + + /* All but single defuse-cycle optimized and fold-left reductions go + through their own vectorizable_* routines. */ + if (!single_defuse_cycle && reduction_type !=3D FOLD_LEFT_REDUCTION) { stmt_vec_info tem =3D vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (phi_info)); @@ -8654,6 +8757,15 @@ vect_transform_reduction (loop_vec_info loop_vinfo, bool lane_reducing =3D lane_reducing_op_p (code); gcc_assert (single_defuse_cycle || lane_reducing); + if (lane_reducing) + { + /* The last operand of lane-reducing op is for reduction. */ + gcc_assert (reduc_index =3D=3D (int) op.num_ops - 1); + + /* Now lane-reducing op is contained in some slp node. */ + gcc_assert (slp_node); + } + /* Create the destination vector */ tree scalar_dest =3D gimple_get_lhs (stmt_info->stmt); tree vec_dest =3D vect_create_destination_var (scalar_dest, vectype_out)= ; @@ -8698,6 +8810,62 @@ vect_transform_reduction (loop_vec_info loop_vinfo, reduc_index =3D=3D 2 ? op.ops[2] : NULL_TREE, &vec_oprnds[2]); } + else if (lane_reducing && SLP_TREE_LANES (slp_node) =3D=3D 1) + { + /* For lane-reducing op covered by single-lane slp node, the input + vectype of the reduction PHI determines copies of vectorized def-u= se + cycles, which might be more than effective copies of vectorized la= ne- + reducing reduction statements. This could be complemented by + generating extra trivial pass-through copies. For example: + + int sum =3D 0; + for (i) + { + sum +=3D d0[i] * d1[i]; // dot-prod + sum +=3D abs(s0[i] - s1[i]); // sad + sum +=3D n[i]; // normal + } + + The vector size is 128-bit?vectorization factor is 16. Reduction + statements would be transformed as: + + vector<4> int sum_v0 =3D { 0, 0, 0, 0 }; + vector<4> int sum_v1 =3D { 0, 0, 0, 0 }; + vector<4> int sum_v2 =3D { 0, 0, 0, 0 }; + vector<4> int sum_v3 =3D { 0, 0, 0, 0 }; + + for (i / 16) + { + sum_v0 =3D DOT_PROD (d0_v0[i: 0 ~ 15], d1_v0[i: 0 ~ 15], sum= _v0); + sum_v1 =3D sum_v1; // copy + sum_v2 =3D sum_v2; // copy + sum_v3 =3D sum_v3; // copy + + sum_v0 =3D SAD (s0_v0[i: 0 ~ 7 ], s1_v0[i: 0 ~ 7 ], sum_v0); + sum_v1 =3D SAD (s0_v1[i: 8 ~ 15], s1_v1[i: 8 ~ 15], sum_v1); + sum_v2 =3D sum_v2; // copy + sum_v3 =3D sum_v3; // copy + + sum_v0 +=3D n_v0[i: 0 ~ 3 ]; + sum_v1 +=3D n_v1[i: 4 ~ 7 ]; + sum_v2 +=3D n_v2[i: 8 ~ 11]; + sum_v3 +=3D n_v3[i: 12 ~ 15]; + } + */ + unsigned using_ncopies =3D vec_oprnds[0].length (); + unsigned reduc_ncopies =3D vec_oprnds[reduc_index].length (); + + gcc_assert (using_ncopies <=3D reduc_ncopies); + + if (using_ncopies < reduc_ncopies) + { + for (unsigned i =3D 0; i < op.num_ops - 1; i++) + { + gcc_assert (vec_oprnds[i].length () =3D=3D using_ncopies); + vec_oprnds[i].safe_grow_cleared (reduc_ncopies); + } + } + } bool emulated_mixed_dot_prod =3D vect_is_emulated_mixed_dot_prod (stmt_i= nfo); unsigned num =3D vec_oprnds[reduc_index =3D=3D 0 ? 1 : 0].length (); @@ -8706,7 +8874,18 @@ vect_transform_reduction (loop_vec_info loop_vinfo, { gimple *new_stmt; tree vop[3] =3D { vec_oprnds[0][i], vec_oprnds[1][i], NULL_TREE }; - if (masked_loop_p && !mask_by_cond_expr) + + if (!vop[0] || !vop[1]) + { + tree reduc_vop =3D vec_oprnds[reduc_index][i]; + + /* Insert trivial copy if no need to generate vectorized + statement. */ + gcc_assert (reduc_vop); + + new_stmt =3D SSA_NAME_DEF_STMT (reduc_vop); + } + else if (masked_loop_p && !mask_by_cond_expr) { /* No conditional ifns have been defined for lane-reducing op yet. */ @@ -8735,8 +8914,22 @@ vect_transform_reduction (loop_vec_info loop_vinfo, if (masked_loop_p && mask_by_cond_expr) { + unsigned nvectors =3D vec_num * ncopies; + tree stmt_vectype_in =3D vectype_in; + + /* For single-lane slp node on lane-reducing op, we need to + compute exact number of vector stmts from its input vectyp= e, + since the value got from the slp node is over-estimated. + TODO: properly set the number this somewhere, so that this + fixup could be removed. */ + if (lane_reducing && SLP_TREE_LANES (slp_node) =3D=3D 1) + { + stmt_vectype_in =3D STMT_VINFO_REDUC_VECTYPE_IN (stmt_inf= o); + nvectors =3D vect_get_num_copies (loop_vinfo, vectype_in)= ; + } + tree mask =3D vect_get_loop_mask (loop_vinfo, gsi, masks, - vec_num * ncopies, vectype_in= , i); + nvectors, stmt_vectype_in, i)= ; build_vect_cond_expr (code, vop, mask, gsi); } diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 840e162c7f0..845647b4399 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -13350,6 +13350,8 @@ vect_analyze_stmt (vec_info *vinfo, NULL, NULL, node, cost_vec) || vectorizable_load (vinfo, stmt_info, NULL, NULL, node, cost_ve= c) || vectorizable_store (vinfo, stmt_info, NULL, NULL, node, cost_v= ec) + || vectorizable_lane_reducing (as_a (vinfo), + stmt_info, node, cost_vec) || vectorizable_reduction (as_a (vinfo), stmt_inf= o, node, node_instance, cost_vec) || vectorizable_induction (as_a (vinfo), stmt_inf= o, diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 60224f4e284..94736736dcc 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -2455,6 +2455,8 @@ extern loop_vec_info vect_create_loop_vinfo (class lo= op *, vec_info_shared *, extern bool vectorizable_live_operation (vec_info *, stmt_vec_info, slp_tree, slp_instance, int, bool, stmt_vector_for_cost *); +extern bool vectorizable_lane_reducing (loop_vec_info, stmt_vec_info, + slp_tree, stmt_vector_for_cost *); extern bool vectorizable_reduction (loop_vec_info, stmt_vec_info, slp_tree, slp_instance, stmt_vector_for_cost *); -- 2.17.1 ________________________________________ From: Feng Xue OS Sent: Tuesday, June 25, 2024 5:32 PM To: Richard Biener Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH 7/8] vect: Support multiple lane-reducing operations fo= r loop reduction [PR114440] >> >> >> - if (slp_node) >> >> + if (slp_node && SLP_TREE_LANES (slp_node) > 1) >> > >> > Hmm, that looks wrong. It looks like SLP_TREE_NUMBER_OF_VEC_STMTS is = off >> > instead, which is bad. >> > >> >> nvectors =3D SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); >> >> else >> >> nvectors =3D vect_get_num_copies (loop_vinfo, vectype_in); >> >> @@ -7478,6 +7472,152 @@ vect_reduction_update_partial_vector_usage (l= oop_vec_info loop_vinfo, >> >> } >> >> } >> >> >> >> +/* Check if STMT_INFO is a lane-reducing operation that can be vecto= rized in >> >> + the context of LOOP_VINFO, and vector cost will be recorded in CO= ST_VEC. >> >> + Now there are three such kinds of operations: dot-prod/widen-sum/= sad >> >> + (sum-of-absolute-differences). >> >> + >> >> + For a lane-reducing operation, the loop reduction path that it li= es in, >> >> + may contain normal operation, or other lane-reducing operation of= different >> >> + input type size, an example as: >> >> + >> >> + int sum =3D 0; >> >> + for (i) >> >> + { >> >> + ... >> >> + sum +=3D d0[i] * d1[i]; // dot-prod >> >> + sum +=3D w[i]; // widen-sum >> >> + sum +=3D abs(s0[i] - s1[i]); // sad >> >> + sum +=3D n[i]; // normal >> >> + ... >> >> + } >> >> + >> >> + Vectorization factor is essentially determined by operation whose= input >> >> + vectype has the most lanes ("vector(16) char" in the example), wh= ile we >> >> + need to choose input vectype with the least lanes ("vector(4) int= " in the >> >> + example) for the reduction PHI statement. */ >> >> + >> >> +bool >> >> +vectorizable_lane_reducing (loop_vec_info loop_vinfo, stmt_vec_info = stmt_info, >> >> + slp_tree slp_node, stmt_vector_for_cost *= cost_vec) >> >> +{ >> >> + gimple *stmt =3D stmt_info->stmt; >> >> + >> >> + if (!lane_reducing_stmt_p (stmt)) >> >> + return false; >> >> + >> >> + tree type =3D TREE_TYPE (gimple_assign_lhs (stmt)); >> >> + >> >> + if (!INTEGRAL_TYPE_P (type) && !SCALAR_FLOAT_TYPE_P (type)) >> >> + return false; >> >> + >> >> + /* Do not try to vectorize bit-precision reductions. */ >> >> + if (!type_has_mode_precision_p (type)) >> >> + return false; >> >> + >> >> + if (!slp_node) >> >> + return false; >> >> + >> >> + for (int i =3D 0; i < (int) gimple_num_ops (stmt) - 1; i++) >> >> + { >> >> + stmt_vec_info def_stmt_info; >> >> + slp_tree slp_op; >> >> + tree op; >> >> + tree vectype; >> >> + enum vect_def_type dt; >> >> + >> >> + if (!vect_is_simple_use (loop_vinfo, stmt_info, slp_node, i, &= op, >> >> + &slp_op, &dt, &vectype, &def_stmt_info= )) >> >> + { >> >> + if (dump_enabled_p ()) >> >> + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, >> >> + "use not simple.\n"); >> >> + return false; >> >> + } >> >> + >> >> + if (!vectype) >> >> + { >> >> + vectype =3D get_vectype_for_scalar_type (loop_vinfo, TREE_T= YPE (op), >> >> + slp_op); >> >> + if (!vectype) >> >> + return false; >> >> + } >> >> + >> >> + if (!vect_maybe_update_slp_op_vectype (slp_op, vectype)) >> >> + { >> >> + if (dump_enabled_p ()) >> >> + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, >> >> + "incompatible vector types for invariant= s\n"); >> >> + return false; >> >> + } >> >> + >> >> + if (i =3D=3D STMT_VINFO_REDUC_IDX (stmt_info)) >> >> + continue; >> >> + >> >> + /* There should be at most one cycle def in the stmt. */ >> >> + if (VECTORIZABLE_CYCLE_DEF (dt)) >> >> + return false; >> >> + } >> >> + >> >> + stmt_vec_info reduc_info =3D STMT_VINFO_REDUC_DEF (vect_orig_stmt = (stmt_info)); >> >> + >> >> + /* TODO: Support lane-reducing operation that does not directly pa= rticipate >> >> + in loop reduction. */ >> >> + if (!reduc_info || STMT_VINFO_REDUC_IDX (stmt_info) < 0) >> >> + return false; >> >> + >> >> + /* Lane-reducing pattern inside any inner loop of LOOP_VINFO is no= t >> >> + recoginized. */ >> >> + gcc_assert (STMT_VINFO_DEF_TYPE (reduc_info) =3D=3D vect_reduction= _def); >> >> + gcc_assert (STMT_VINFO_REDUC_TYPE (reduc_info) =3D=3D TREE_CODE_RE= DUCTION); >> >> + >> >> + tree vectype_in =3D STMT_VINFO_REDUC_VECTYPE_IN (stmt_info); >> >> + int ncopies_for_cost; >> >> + >> >> + if (SLP_TREE_LANES (slp_node) > 1) >> >> + { >> >> + /* Now lane-reducing operations in a non-single-lane slp node = should only >> >> + come from the same loop reduction path. */ >> >> + gcc_assert (REDUC_GROUP_FIRST_ELEMENT (stmt_info)); >> >> + ncopies_for_cost =3D 1; >> >> + } >> >> + else >> >> + { >> >> + ncopies_for_cost =3D vect_get_num_copies (loop_vinfo, vectype_= in); >> > >> > OK, so the fact that the ops are lane-reducing means they effectively >> > change the VF for the result. That's only possible as we tightly cont= rol >> > code generation and "adjust" to the expected VF (by inserting the copi= es >> > you mentioned above), but only up to the highest number of outputs >> > created in the reduction chain. In that sense instead of talking and = recording >> > "input vector types" wouldn't it make more sense to record the effecti= ve >> > vectorization factor for the reduction instance? That VF would be at = most >> > the loops VF but could be as low as 1. Once we have a non-lane-reduci= ng >> > operation in the reduction chain it would be always equal to the loops= VF. >> > >> > ncopies would then be always determined by that reduction instance VF = and >> > the accumulator vector type (STMT_VINFO_VECTYPE). This reduction >> > instance VF would also trivially indicate the force-single-def-use-cyc= le >> > case, possibly simplifying code? >> >> I tried to add such an effective VF, while the vectype_in is still neede= d in some >> scenarios, such as when checking whether a dot-prod stmt is emulated or = not. >> The former could be deduced from the later, so recording both things see= ms >> to be redundant. Another consideration is that for normal op, ncopies >> is determined from type (STMT_VINFO_VECTYPE), but for lane-reducing op, >> it is from VF. So, a better means to make them unified? > > AFAICS reductions are special in that they, for the accumulation SSA cycl= e, > do not adhere to the loops VF but as optimization can chose a smaller one= . > OTOH STMT_VINFO_VECTYPE is for the vector type used for individual > operations which even for lane-reducing ops is adhered to - those just > may use a smaller VF, that of the reduction SSA cycle. > > So what's redundant is STMT_VINFO_REDUC_VECTYPE_IN - or rather > it's not fully redundant but needlessly replicated over all stmts partici= pating > in the reduction instead of recording the reduction VF in the reduc_info = and > using that (plus STMT_VINFO_VECTYPE) to compute the effective ncopies > for stmts in the reduction cycle. > > At least that was my idea ... > For lane-reducing ops and single-defuse-cycle optimization, we could assume no lane would be reduced, and always generate vectorization statements according to the normal VF, if placeholder is needed, just insert some triv= ial statement like zero-initialization, or pass-through copy. And define a"effe= ctive VF or ncopies" to control lane-reducing related aspects in analysis and codegen (= such as the below vect_get_loop_mask). Since all things will become SLP-based f= inally, I think a suitable place to add such a field might be in slp_node, as a sup= plement to "vect_stmts_size", and it is expected to be adjusted in vectorizable_reduct= ion. So could we do the refinement as separate patches when non-slp code path is to= be removed? >> >> + gcc_assert (ncopies_for_cost >=3D 1); >> >> + } >> >> + >> >> + if (vect_is_emulated_mixed_dot_prod (stmt_info)) >> >> + { >> >> + /* We need extra two invariants: one that contains the minimum= signed >> >> + value and one that contains half of its negative. */ >> >> + int prologue_stmts =3D 2; >> >> + unsigned cost =3D record_stmt_cost (cost_vec, prologue_stmts, >> >> + scalar_to_vec, stmt_info, 0, >> >> + vect_prologue); >> >> + if (dump_enabled_p ()) >> >> + dump_printf (MSG_NOTE, "vectorizable_lane_reducing: " >> >> + "extra prologue_cost =3D %d .\n", cost); >> >> + >> >> + /* Three dot-products and a subtraction. */ >> >> + ncopies_for_cost *=3D 4; >> >> + } >> >> + >> >> + record_stmt_cost (cost_vec, ncopies_for_cost, vector_stmt, stmt_in= fo, 0, >> >> + vect_body); >> >> + >> >> + if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)) >> >> + { >> >> + enum tree_code code =3D gimple_assign_rhs_code (stmt); >> >> + vect_reduction_update_partial_vector_usage (loop_vinfo, reduc_= info, >> >> + slp_node, code, typ= e, >> >> + vectype_in); >> >> + } >> >> + >> > >> > Add a comment: >> > >> > /* Transform via vect_transform_reduction. */ >> > >> >> + STMT_VINFO_TYPE (stmt_info) =3D reduc_vec_info_type; >> >> + return true; >> >> +} >> >> + >> >> /* Function vectorizable_reduction. >> >> >> >> Check if STMT_INFO performs a reduction operation that can be vec= torized. >> >> @@ -7804,18 +7944,6 @@ vectorizable_reduction (loop_vec_info loop_vin= fo, >> >> if (!type_has_mode_precision_p (op.type)) >> >> return false; >> >> >> >> - /* For lane-reducing ops we're reducing the number of reduction PH= Is >> >> - which means the only use of that may be in the lane-reducing op= eration. */ >> >> - if (lane_reducing >> >> - && reduc_chain_length !=3D 1 >> >> - && !only_slp_reduc_chain) >> >> - { >> >> - if (dump_enabled_p ()) >> >> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, >> >> - "lane-reducing reduction with extra stmts.\n= "); >> >> - return false; >> >> - } >> >> - >> >> /* Lane-reducing ops also never can be used in a SLP reduction gro= up >> >> since we'll mix lanes belonging to different reductions. But i= t's >> >> OK to use them in a reduction chain or when the reduction group >> >> @@ -8354,14 +8482,11 @@ vectorizable_reduction (loop_vec_info loop_vi= nfo, >> >> && loop_vinfo->suggested_unroll_factor =3D=3D 1) >> >> single_defuse_cycle =3D true; >> >> >> >> - if (single_defuse_cycle || lane_reducing) >> >> + if (single_defuse_cycle && !lane_reducing) >> > >> > If there's also a non-lane-reducing plus in the chain don't we have to >> > check for that reduction op? So shouldn't it be >> > single_defuse_cycle && ... fact that we don't record >> > (non-lane-reducing op there) ... >> >> Quite not understand this point. For a non-lane-reducing op in the chai= n, >> it should be handled in its own vectorizable_xxx function? The below che= ck >> is only for the first statement (vect_reduction_def) in the reduction. > > Hmm. So we have vectorizable_lane_reducing_* for the check on the > lane-reducing stmts, vectorizable_* for !single-def-use stmts. And the > following is then just for the case there's a single def that's not > lane-reducing > and we're forcing a single-def-use and thus go via vect_transform_reducti= on? Yes. Non-lane-reducing with single-defuse-cycle is handled in the function. This logic is same as the original. >> > >> >> { >> >> gcc_assert (op.code !=3D COND_EXPR); >> >> >> >> - /* 4. Supportable by target? */ >> >> - bool ok =3D true; >> >> - >> >> - /* 4.1. check support for the operation in the loop >> >> + /* 4. check support for the operation in the loop >> >> >> >> This isn't necessary for the lane reduction codes, since the= y >> >> can only be produced by pattern matching, and it's up to the >> >> @@ -8370,14 +8495,13 @@ vectorizable_reduction (loop_vec_info loop_vi= nfo, >> >> mixed-sign dot-products can be implemented using signed >> >> dot-products. */ >> >> machine_mode vec_mode =3D TYPE_MODE (vectype_in); >> >> - if (!lane_reducing >> >> - && !directly_supported_p (op.code, vectype_in, optab_vector= )) >> >> + if (!directly_supported_p (op.code, vectype_in, optab_vector)) >> >> { >> >> if (dump_enabled_p ()) >> >> dump_printf (MSG_NOTE, "op not supported by target.\n"); >> >> if (maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD) >> >> || !vect_can_vectorize_without_simd_p (op.code)) >> >> - ok =3D false; >> >> + single_defuse_cycle =3D false; >> >> else >> >> if (dump_enabled_p ()) >> >> dump_printf (MSG_NOTE, "proceeding using word mode.\n")= ; >> >> @@ -8390,16 +8514,6 @@ vectorizable_reduction (loop_vec_info loop_vin= fo, >> >> dump_printf (MSG_NOTE, "using word mode not possible.\n")= ; >> >> return false; >> >> } >> >> - >> >> - /* lane-reducing operations have to go through vect_transform_= reduction. >> >> - For the other cases try without the single cycle optimizati= on. */ >> >> - if (!ok) >> >> - { >> >> - if (lane_reducing) >> >> - return false; >> >> - else >> >> - single_defuse_cycle =3D false; >> >> - } >> >> } >> >> if (dump_enabled_p () && single_defuse_cycle) >> >> dump_printf_loc (MSG_NOTE, vect_location, >> >> @@ -8407,22 +8521,14 @@ vectorizable_reduction (loop_vec_info loop_vi= nfo, >> >> "multiple vectors to one in the loop body\n"); >> >> STMT_VINFO_FORCE_SINGLE_CYCLE (reduc_info) =3D single_defuse_cycle= ; >> >> >> >> - /* If the reduction stmt is one of the patterns that have lane >> >> - reduction embedded we cannot handle the case of ! single_defuse= _cycle. */ >> >> - if ((ncopies > 1 && ! single_defuse_cycle) >> >> - && lane_reducing) >> >> - { >> >> - if (dump_enabled_p ()) >> >> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, >> >> - "multi def-use cycle not possible for lane-r= educing " >> >> - "reduction operation\n"); >> >> - return false; >> >> - } >> >> + /* For lane-reducing operation, the below processing related to si= ngle >> >> + defuse-cycle will be done in its own vectorizable function. On= e more >> >> + thing to note is that the operation must not be involved in fol= d-left >> >> + reduction. */ >> >> + single_defuse_cycle &=3D !lane_reducing; >> >> >> >> if (slp_node >> >> - && !(!single_defuse_cycle >> >> - && !lane_reducing >> >> - && reduction_type !=3D FOLD_LEFT_REDUCTION)) >> >> + && (single_defuse_cycle || reduction_type =3D=3D FOLD_LEFT_RED= UCTION)) >> >> for (i =3D 0; i < (int) op.num_ops; i++) >> >> if (!vect_maybe_update_slp_op_vectype (slp_op[i], vectype_op[i= ])) >> >> { >> >> @@ -8435,28 +8541,20 @@ vectorizable_reduction (loop_vec_info loop_vi= nfo, >> >> vect_model_reduction_cost (loop_vinfo, stmt_info, reduc_fn, >> >> reduction_type, ncopies, cost_vec); >> >> /* Cost the reduction op inside the loop if transformed via >> >> - vect_transform_reduction. Otherwise this is costed by the >> >> - separate vectorizable_* routines. */ >> >> - if (single_defuse_cycle || lane_reducing) >> >> - { >> >> - int factor =3D 1; >> >> - if (vect_is_emulated_mixed_dot_prod (stmt_info)) >> >> - /* Three dot-products and a subtraction. */ >> >> - factor =3D 4; >> >> - record_stmt_cost (cost_vec, ncopies * factor, vector_stmt, >> >> - stmt_info, 0, vect_body); >> >> - } >> >> + vect_transform_reduction for non-lane-reducing operation. Othe= rwise >> >> + this is costed by the separate vectorizable_* routines. */ >> >> + if (single_defuse_cycle) >> >> + record_stmt_cost (cost_vec, ncopies, vector_stmt, stmt_info, 0, = vect_body); >> >> >> >> if (dump_enabled_p () >> >> && reduction_type =3D=3D FOLD_LEFT_REDUCTION) >> >> dump_printf_loc (MSG_NOTE, vect_location, >> >> "using an in-order (fold-left) reduction.\n"); >> >> STMT_VINFO_TYPE (orig_stmt_of_analysis) =3D cycle_phi_info_type; >> >> - /* All but single defuse-cycle optimized, lane-reducing and fold-l= eft >> >> - reductions go through their own vectorizable_* routines. */ >> >> - if (!single_defuse_cycle >> >> - && !lane_reducing >> >> - && reduction_type !=3D FOLD_LEFT_REDUCTION) >> >> + >> >> + /* All but single defuse-cycle optimized and fold-left reductions = go >> >> + through their own vectorizable_* routines. */ >> >> + if (!single_defuse_cycle && reduction_type !=3D FOLD_LEFT_REDUCTIO= N) >> >> { >> >> stmt_vec_info tem >> >> =3D vect_stmt_to_vectorize (STMT_VINFO_REDUC_DEF (phi_info)); >> >> @@ -8646,6 +8744,15 @@ vect_transform_reduction (loop_vec_info loop_v= info, >> >> bool lane_reducing =3D lane_reducing_op_p (code); >> >> gcc_assert (single_defuse_cycle || lane_reducing); >> >> >> >> + if (lane_reducing) >> >> + { >> >> + /* The last operand of lane-reducing op is for reduction. */ >> >> + gcc_assert (reduc_index =3D=3D (int) op.num_ops - 1); >> >> + >> >> + /* Now all lane-reducing ops are covered by some slp node. */ >> >> + gcc_assert (slp_node); >> >> + } >> >> + >> >> /* Create the destination vector */ >> >> tree scalar_dest =3D gimple_get_lhs (stmt_info->stmt); >> >> tree vec_dest =3D vect_create_destination_var (scalar_dest, vectyp= e_out); >> >> @@ -8689,6 +8796,58 @@ vect_transform_reduction (loop_vec_info loop_v= info, >> >> reduc_index =3D=3D 2 ? op.ops[2] : NULL_TREE= , >> >> &vec_oprnds[2]); >> >> } >> >> + else if (lane_reducing && SLP_TREE_LANES (slp_node) =3D=3D 1 >> >> + && vec_oprnds[0].length () < vec_oprnds[reduc_index].lengt= h ()) >> >> + { >> >> + /* For lane-reducing op covered by single-lane slp node, the i= nput >> >> + vectype of the reduction PHI determines copies of vectorized= def-use >> >> + cycles, which might be more than effective copies of vectori= zed lane- >> >> + reducing reduction statements. This could be complemented b= y >> >> + generating extra trivial pass-through copies. For example: >> >> + >> >> + int sum =3D 0; >> >> + for (i) >> >> + { >> >> + sum +=3D d0[i] * d1[i]; // dot-prod >> >> + sum +=3D abs(s0[i] - s1[i]); // sad >> >> + sum +=3D n[i]; // normal >> >> + } >> >> + >> >> + The vector size is 128-bit,vectorization factor is 16. Redu= ction >> >> + statements would be transformed as: >> >> + >> >> + vector<4> int sum_v0 =3D { 0, 0, 0, 0 }; >> >> + vector<4> int sum_v1 =3D { 0, 0, 0, 0 }; >> >> + vector<4> int sum_v2 =3D { 0, 0, 0, 0 }; >> >> + vector<4> int sum_v3 =3D { 0, 0, 0, 0 }; >> >> + >> >> + for (i / 16) >> >> + { >> >> + sum_v0 =3D DOT_PROD (d0_v0[i: 0 ~ 15], d1_v0[i: 0 ~ 15= ], sum_v0); >> >> + sum_v1 =3D sum_v1; // copy >> >> + sum_v2 =3D sum_v2; // copy >> >> + sum_v3 =3D sum_v3; // copy >> >> + >> >> + sum_v0 =3D SAD (s0_v0[i: 0 ~ 7 ], s1_v0[i: 0 ~ 7 ], su= m_v0); >> >> + sum_v1 =3D SAD (s0_v1[i: 8 ~ 15], s1_v1[i: 8 ~ 15], su= m_v1); >> >> + sum_v2 =3D sum_v2; // copy >> >> + sum_v3 =3D sum_v3; // copy >> >> + >> >> + sum_v0 +=3D n_v0[i: 0 ~ 3 ]; >> >> + sum_v1 +=3D n_v1[i: 4 ~ 7 ]; >> >> + sum_v2 +=3D n_v2[i: 8 ~ 11]; >> >> + sum_v3 +=3D n_v3[i: 12 ~ 15]; >> >> + } >> >> + */ >> >> + unsigned using_ncopies =3D vec_oprnds[0].length (); >> >> + unsigned reduc_ncopies =3D vec_oprnds[reduc_index].length (); >> >> + >> > >> > assert reduc_ncopies >=3D using_ncopies? Maybe assert >> > reduc_index =3D=3D op.num_ops - 1 given you use one above >> > and the other below? Or simply iterate till op.num_ops >> > and sip i =3D=3D reduc_index. >> > >> >> + for (unsigned i =3D 0; i < op.num_ops - 1; i++) >> >> + { >> >> + gcc_assert (vec_oprnds[i].length () =3D=3D using_ncopies); >> >> + vec_oprnds[i].safe_grow_cleared (reduc_ncopies); >> >> + } >> >> + } >> >> >> >> bool emulated_mixed_dot_prod =3D vect_is_emulated_mixed_dot_prod (= stmt_info); >> >> unsigned num =3D vec_oprnds[reduc_index =3D=3D 0 ? 1 : 0].length (= ); >> >> @@ -8697,7 +8856,21 @@ vect_transform_reduction (loop_vec_info loop_v= info, >> >> { >> >> gimple *new_stmt; >> >> tree vop[3] =3D { vec_oprnds[0][i], vec_oprnds[1][i], NULL_TRE= E }; >> >> - if (masked_loop_p && !mask_by_cond_expr) >> >> + >> >> + if (!vop[0] || !vop[1]) >> >> + { >> >> + tree reduc_vop =3D vec_oprnds[reduc_index][i]; >> >> + >> >> + /* Insert trivial copy if no need to generate vectorized >> >> + statement. */ >> >> + gcc_assert (reduc_vop); >> >> + >> >> + new_stmt =3D gimple_build_assign (vec_dest, reduc_vop); >> >> + new_temp =3D make_ssa_name (vec_dest, new_stmt); >> >> + gimple_set_lhs (new_stmt, new_temp); >> >> + vect_finish_stmt_generation (loop_vinfo, stmt_info, new_stm= t, gsi); >> > >> > I think you could simply do >> > >> > slp_node->push_vec_def (reduc_vop); >> > continue; >> > >> > without any code generation. >> > >> >> OK, that would be easy. Here comes another question, this patch assumes >> lane-reducing op would always be contained in a slp node, since single-l= ane >> slp node feature has been enabled. But I got some regression if I enforc= ed >> such constraint on lane-reducing op check. Those cases are founded to >> be unvectorizable with single-lane slp, so this should not be what we wa= nt? >> and need to be fixed? > > Yes, in the end we need to chase down all unsupported cases and fix them > (there's known issues with load permutes, I'm working on that - hopefully > when finding a continuous stretch of time...). > >> >> >> + } >> >> + else if (masked_loop_p && !mask_by_cond_expr) >> >> { >> >> /* No conditional ifns have been defined for lane-reducing = op >> >> yet. */ >> >> @@ -8726,8 +8899,19 @@ vect_transform_reduction (loop_vec_info loop_v= info, >> >> >> >> if (masked_loop_p && mask_by_cond_expr) >> >> { >> >> + tree stmt_vectype_in =3D vectype_in; >> >> + unsigned nvectors =3D vec_num * ncopies; >> >> + >> >> + if (lane_reducing && SLP_TREE_LANES (slp_node) =3D=3D 1= ) >> >> + { >> >> + /* Input vectype of the reduction PHI may be deffer= ent from >> > >> > different >> > >> >> + that of lane-reducing operation. */ >> >> + stmt_vectype_in =3D STMT_VINFO_REDUC_VECTYPE_IN (st= mt_info); >> >> + nvectors =3D vect_get_num_copies (loop_vinfo, stmt_= vectype_in); >> > >> > I think this again points to a wrong SLP_TREE_NUMBER_OF_VEC_STMTS. >> >> To partially vectorizing a dot_prod<16 * char> with 128-bit vector width= , >> we should pass (nvector=3D4, vectype=3D<4 *int>) instead of (nvector=3D1= , vectype=3D<16 *char>) >> to vect_get_loop_mask? > > Probably - it depends on the vectorization factor. What I wanted to > point out is that > vec_num (likely from SLP_TREE_NUMBER_OF_VEC_STMTS) is wrong. The > place setting SLP_TREE_NUMBER_OF_VEC_STMTS needs to be adjusted, > or we should forgo with it (but that's possibly a post-only-SLP > cleanup to be done). > > See vect_slp_analyze_node_operations_1 where that's computed. For reduct= ions > it's probably not quite right (and we might have latent issues like > those you are > "fixing" with code like above). The order we analyze stmts might also be= not > optimal for reductions with SLP - in fact given that stmt analysis > relies on a fixed VF > it would probably make sense to determine the reduction VF in advance as = well. > But again this sounds like post-only-SLP cleanup opportunities. > > In the end I might suggest to always use reduct-VF and vectype to determi= ne > the number of vector stmts rather than computing ncopies/vec_num separate= ly. > Thanks, Feng --_002_LV2PR01MB78391AB09E644D51CFB34F2FF7D62LV2PR01MB7839prod_ Content-Type: text/x-patch; name="0002-vect-Support-multiple-lane-reducing-operations-for-l.patch" Content-Description: 0002-vect-Support-multiple-lane-reducing-operations-for-l.patch Content-Disposition: attachment; filename="0002-vect-Support-multiple-lane-reducing-operations-for-l.patch"; size=41377; creation-date="Wed, 26 Jun 2024 14:49:57 GMT"; modification-date="Wed, 26 Jun 2024 14:49:57 GMT" Content-Transfer-Encoding: base64 RnJvbSA1MTZkNjY4OWExYzkxNmM0YWE4ZTU5YTM2YzFmOGExNTlkZjk5ZjEzIE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBGZW5nIFh1ZSA8Znh1ZUBvcy5hbXBlcmVjb21wdXRpbmcuY29t PgpEYXRlOiBXZWQsIDI5IE1heSAyMDI0IDE3OjIyOjM2ICswODAwClN1YmplY3Q6IFtQQVRDSCAy LzNdIHZlY3Q6IFN1cHBvcnQgbXVsdGlwbGUgbGFuZS1yZWR1Y2luZyBvcGVyYXRpb25zIGZvciBs b29wCiByZWR1Y3Rpb24gW1BSMTE0NDQwXQoKRm9yIGxhbmUtcmVkdWNpbmcgb3BlcmF0aW9uKGRv dC1wcm9kL3dpZGVuLXN1bS9zYWQpIGluIGxvb3AgcmVkdWN0aW9uLCBjdXJyZW50CnZlY3Rvcml6 ZXIgY291bGQgb25seSBoYW5kbGUgdGhlIHBhdHRlcm4gaWYgdGhlIHJlZHVjdGlvbiBjaGFpbiBk b2VzIG5vdApjb250YWluIG90aGVyIG9wZXJhdGlvbiwgbm8gbWF0dGVyIHRoZSBvdGhlciBpcyBu b3JtYWwgb3IgbGFuZS1yZWR1Y2luZy4KCkFjdHVhbGx5LCB0byBhbGxvdyBtdWx0aXBsZSBhcmJp dHJhcnkgbGFuZS1yZWR1Y2luZyBvcGVyYXRpb25zLCB3ZSBuZWVkIHRvCnN1cHBvcnQgdmVjdG9y aXphdGlvbiBvZiBsb29wIHJlZHVjdGlvbiBjaGFpbiB3aXRoIG1peGVkIGlucHV0IHZlY3R5cGVz LiBTaW5jZQpsYW5lcyBvZiB2ZWN0eXBlIG1heSB2YXJ5IHdpdGggb3BlcmF0aW9uLCB0aGUgZWZm ZWN0aXZlIG5jb3BpZXMgb2YgdmVjdG9yaXplZApzdGF0ZW1lbnRzIGZvciBvcGVyYXRpb24gYWxz byBtYXkgbm90IGJlIHNhbWUgdG8gZWFjaCBvdGhlciwgdGhpcyBjYXVzZXMKbWlzbWF0Y2ggb24g dmVjdG9yaXplZCBkZWYtdXNlIGN5Y2xlcy4gQSBzaW1wbGUgd2F5IGlzIHRvIGFsaWduIGFsbCBv cGVyYXRpb25zCndpdGggdGhlIG9uZSB0aGF0IGhhcyB0aGUgbW9zdCBuY29waWVzLCB0aGUgZ2Fw IGNvdWxkIGJlIGNvbXBsZW1lbnRlZCBieQpnZW5lcmF0aW5nIGV4dHJhIHRyaXZpYWwgcGFzcy10 aHJvdWdoIGNvcGllcy4gRm9yIGV4YW1wbGU6CgogICBpbnQgc3VtID0gMDsKICAgZm9yIChpKQog ICAgIHsKICAgICAgIHN1bSArPSBkMFtpXSAqIGQxW2ldOyAgICAgIC8vIGRvdC1wcm9kIDx2ZWN0 b3IoMTYpIGNoYXI+CiAgICAgICBzdW0gKz0gd1tpXTsgICAgICAgICAgICAgICAvLyB3aWRlbi1z dW0gPHZlY3RvcigxNikgY2hhcj4KICAgICAgIHN1bSArPSBhYnMoczBbaV0gLSBzMVtpXSk7IC8v IHNhZCA8dmVjdG9yKDgpIHNob3J0PgogICAgICAgc3VtICs9IG5baV07ICAgICAgICAgICAgICAg Ly8gbm9ybWFsIDx2ZWN0b3IoNCkgaW50PgogICAgIH0KClRoZSB2ZWN0b3Igc2l6ZSBpcyAxMjgt Yml0IHZlY3Rvcml6YXRpb24gZmFjdG9yIGlzIDE2LiBSZWR1Y3Rpb24gc3RhdGVtZW50cwp3b3Vs ZCBiZSB0cmFuc2Zvcm1lZCBhczoKCiAgIHZlY3Rvcjw0PiBpbnQgc3VtX3YwID0geyAwLCAwLCAw LCAwIH07CiAgIHZlY3Rvcjw0PiBpbnQgc3VtX3YxID0geyAwLCAwLCAwLCAwIH07CiAgIHZlY3Rv cjw0PiBpbnQgc3VtX3YyID0geyAwLCAwLCAwLCAwIH07CiAgIHZlY3Rvcjw0PiBpbnQgc3VtX3Yz ID0geyAwLCAwLCAwLCAwIH07CgogICBmb3IgKGkgLyAxNikKICAgICB7CiAgICAgICBzdW1fdjAg PSBET1RfUFJPRCAoZDBfdjBbaTogMCB+IDE1XSwgZDFfdjBbaTogMCB+IDE1XSwgc3VtX3YwKTsK ICAgICAgIHN1bV92MSA9IHN1bV92MTsgIC8vIGNvcHkKICAgICAgIHN1bV92MiA9IHN1bV92Mjsg IC8vIGNvcHkKICAgICAgIHN1bV92MyA9IHN1bV92MzsgIC8vIGNvcHkKCiAgICAgICBzdW1fdjAg PSBXSURFTl9TVU0gKHdfdjBbaTogMCB+IDE1XSwgc3VtX3YwKTsKICAgICAgIHN1bV92MSA9IHN1 bV92MTsgIC8vIGNvcHkKICAgICAgIHN1bV92MiA9IHN1bV92MjsgIC8vIGNvcHkKICAgICAgIHN1 bV92MyA9IHN1bV92MzsgIC8vIGNvcHkKCiAgICAgICBzdW1fdjAgPSBTQUQgKHMwX3YwW2k6IDAg fiA3IF0sIHMxX3YwW2k6IDAgfiA3IF0sIHN1bV92MCk7CiAgICAgICBzdW1fdjEgPSBTQUQgKHMw X3YxW2k6IDggfiAxNV0sIHMxX3YxW2k6IDggfiAxNV0sIHN1bV92MSk7CiAgICAgICBzdW1fdjIg PSBzdW1fdjI7ICAvLyBjb3B5CiAgICAgICBzdW1fdjMgPSBzdW1fdjM7ICAvLyBjb3B5CgogICAg ICAgc3VtX3YwICs9IG5fdjBbaTogMCAgfiAzIF07CiAgICAgICBzdW1fdjEgKz0gbl92MVtpOiA0 ICB+IDcgXTsKICAgICAgIHN1bV92MiArPSBuX3YyW2k6IDggIH4gMTFdOwogICAgICAgc3VtX3Yz ICs9IG5fdjNbaTogMTIgfiAxNV07CiAgICAgfQoKMjAyNC0wMy0yMiBGZW5nIFh1ZSA8Znh1ZUBv cy5hbXBlcmVjb21wdXRpbmcuY29tPgoKZ2NjLwoJUFIgdHJlZS1vcHRpbWl6YXRpb24vMTE0NDQw CgkqIHRyZWUtdmVjdG9yaXplci5oICh2ZWN0b3JpemFibGVfbGFuZV9yZWR1Y2luZyk6IE5ldyBm dW5jdGlvbgoJZGVjbGFyYXRpb24uCgkqIHRyZWUtdmVjdC1zdG10cy5jYyAodmVjdF9hbmFseXpl X3N0bXQpOiBDYWxsIG5ldyBmdW5jdGlvbgoJdmVjdG9yaXphYmxlX2xhbmVfcmVkdWNpbmcgdG8g YW5hbHl6ZSBsYW5lLXJlZHVjaW5nIG9wZXJhdGlvbi4KCSogdHJlZS12ZWN0LWxvb3AuY2MgKHZl Y3RfbW9kZWxfcmVkdWN0aW9uX2Nvc3QpOiBSZW1vdmUgY29zdCBjb21wdXRhdGlvbgoJY29kZSBy ZWxhdGVkIHRvCWVtdWxhdGVkX21peGVkX2RvdF9wcm9kLgoJKHZlY3RfcmVkdWN0aW9uX3VwZGF0 ZV9wYXJ0aWFsX3ZlY3Rvcl91c2FnZSk6IENvbXB1dGUgbmNvcGllcyBhcyB0aGUKCW9yaWdpbmFs IG1lYW5zIGZvciBzaW5nbGUtbGFuZSBzbHAgbm9kZS4KCSh2ZWN0b3JpemFibGVfbGFuZV9yZWR1 Y2luZyk6IE5ldyBmdW5jdGlvbi4KCSh2ZWN0b3JpemFibGVfcmVkdWN0aW9uKTogQWxsb3cgbXVs dGlwbGUgbGFuZS1yZWR1Y2luZyBvcGVyYXRpb25zIGluCglsb29wIHJlZHVjdGlvbi4gTW92ZSBz b21lIG9yaWdpbmFsIGxhbmUtcmVkdWNpbmcgcmVsYXRlZCBjb2RlIHRvCgl2ZWN0b3JpemFibGVf bGFuZV9yZWR1Y2luZy4KCSh2ZWN0X3RyYW5zZm9ybV9yZWR1Y3Rpb24pOiBFeHRlbmQgdHJhbnNm b3JtYXRpb24gdG8gc3VwcG9ydCByZWR1Y3Rpb24KCXN0YXRlbWVudHMgd2l0aCBtaXhlZCBpbnB1 dCB2ZWN0eXBlcy4KCmdjYy90ZXN0c3VpdGUvCglQUiB0cmVlLW9wdGltaXphdGlvbi8xMTQ0NDAK CSogZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi0xLmMKCSogZ2NjLmRnL3ZlY3QvdmVjdC1y ZWR1Yy1jaGFpbi0yLmMKCSogZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi0zLmMKCSogZ2Nj LmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTEuYwoJKiBnY2MuZGcvdmVjdC92ZWN0 LXJlZHVjLWNoYWluLWRvdC1zbHAtMi5jCgkqIGdjYy5kZy92ZWN0L3ZlY3QtcmVkdWMtY2hhaW4t ZG90LXNscC0zLmMKCSogZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTQuYwoJ KiBnY2MuZGcvdmVjdC92ZWN0LXJlZHVjLWRvdC1zbHAtMS5jCi0tLQogLi4uL2djYy5kZy92ZWN0 L3ZlY3QtcmVkdWMtY2hhaW4tMS5jICAgICAgICAgIHwgIDYyICsrKysKIC4uLi9nY2MuZGcvdmVj dC92ZWN0LXJlZHVjLWNoYWluLTIuYyAgICAgICAgICB8ICA3NyArKysrCiAuLi4vZ2NjLmRnL3Zl Y3QvdmVjdC1yZWR1Yy1jaGFpbi0zLmMgICAgICAgICAgfCAgNjYgKysrKwogLi4uL2djYy5kZy92 ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tZG90LXNscC0xLmMgIHwgIDk1ICsrKysrCiAuLi4vZ2NjLmRn L3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTIuYyAgfCAgNjcgKysrKwogLi4uL2djYy5k Zy92ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tZG90LXNscC0zLmMgIHwgIDc5ICsrKysrCiAuLi4vZ2Nj LmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTQuYyAgfCAgNjMgKysrKwogLi4uL2dj Yy5kZy92ZWN0L3ZlY3QtcmVkdWMtZG90LXNscC0xLmMgICAgICAgIHwgIDYwICsrKysKIGdjYy90 cmVlLXZlY3QtbG9vcC5jYyAgICAgICAgICAgICAgICAgICAgICAgICB8IDMzMyArKysrKysrKysr KysrKy0tLS0KIGdjYy90cmVlLXZlY3Qtc3RtdHMuY2MgICAgICAgICAgICAgICAgICAgICAgICB8 ICAgMiArCiBnY2MvdHJlZS12ZWN0b3JpemVyLmggICAgICAgICAgICAgICAgICAgICAgICAgfCAg IDIgKwogMTEgZmlsZXMgY2hhbmdlZCwgODM2IGluc2VydGlvbnMoKyksIDcwIGRlbGV0aW9ucygt KQogY3JlYXRlIG1vZGUgMTAwNjQ0IGdjYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1 Yy1jaGFpbi0xLmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2djYy5kZy92ZWN0 L3ZlY3QtcmVkdWMtY2hhaW4tMi5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZ2NjL3Rlc3RzdWl0ZS9n Y2MuZGcvdmVjdC92ZWN0LXJlZHVjLWNoYWluLTMuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGdjYy90 ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTEuYwogY3JlYXRl IG1vZGUgMTAwNjQ0IGdjYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1k b3Qtc2xwLTIuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGdjYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3Qv dmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTMuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGdjYy90ZXN0 c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTQuYwogY3JlYXRlIG1v ZGUgMTAwNjQ0IGdjYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1kb3Qtc2xwLTEu YwoKZGlmZiAtLWdpdCBhL2djYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFp bi0xLmMgYi9nY2MvdGVzdHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tMS5jCm5l dyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwLi4wNGJmYzQxOWRiZAotLS0gL2Rl di9udWxsCisrKyBiL2djYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi0x LmMKQEAgLTAsMCArMSw2MiBAQAorLyogRGlzYWJsaW5nIGVwaWxvZ3VlcyB1bnRpbCB3ZSBmaW5k IGEgYmV0dGVyIHdheSB0byBkZWFsIHdpdGggc2NhbnMuICAqLworLyogeyBkZy1hZGRpdGlvbmFs LW9wdGlvbnMgIi0tcGFyYW0gdmVjdC1lcGlsb2d1ZXMtbm9tYXNrPTAiIH0gKi8KKy8qIHsgZGct cmVxdWlyZS1lZmZlY3RpdmUtdGFyZ2V0IHZlY3RfaW50IH0gKi8KKy8qIHsgZGctcmVxdWlyZS1l ZmZlY3RpdmUtdGFyZ2V0IGFybV92OF8yYV9kb3Rwcm9kX25lb25faHcgeyB0YXJnZXQgeyBhYXJj aDY0Ki0qLSogfHwgYXJtKi0qLSogfSB9IH0gKi8KKy8qIHsgZGctYWRkLW9wdGlvbnMgYXJtX3Y4 XzJhX2RvdHByb2RfbmVvbiB9ICAqLworCisjaW5jbHVkZSAidHJlZS12ZWN0LmgiCisKKyNkZWZp bmUgTiA1MAorCisjaWZuZGVmIFNJR05FRE5FU1NfMQorI2RlZmluZSBTSUdORURORVNTXzEgc2ln bmVkCisjZGVmaW5lIFNJR05FRE5FU1NfMiBzaWduZWQKKyNlbmRpZgorCitTSUdORURORVNTXzEg aW50IF9fYXR0cmlidXRlX18gKChub2lwYSkpCitmIChTSUdORURORVNTXzEgaW50IHJlcywKKyAg IFNJR05FRE5FU1NfMiBjaGFyICpyZXN0cmljdCBhLAorICAgU0lHTkVETkVTU18yIGNoYXIgKnJl c3RyaWN0IGIsCisgICBTSUdORURORVNTXzIgY2hhciAqcmVzdHJpY3QgYywKKyAgIFNJR05FRE5F U1NfMiBjaGFyICpyZXN0cmljdCBkLAorICAgU0lHTkVETkVTU18xIGludCAqcmVzdHJpY3QgZSkK K3sKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyArK2kpCisgICAgeworICAgICAgcmVzICs9IGFb aV0gKiBiW2ldOworICAgICAgcmVzICs9IGNbaV0gKiBkW2ldOworICAgICAgcmVzICs9IGVbaV07 CisgICAgfQorICByZXR1cm4gcmVzOworfQorCisjZGVmaW5lIEJBU0UgKChTSUdORURORVNTXzIg aW50KSAtMSA8IDAgPyAtMTI2IDogNCkKKyNkZWZpbmUgT0ZGU0VUIDIwCisKK2ludAorbWFpbiAo dm9pZCkKK3sKKyAgY2hlY2tfdmVjdCAoKTsKKworICBTSUdORURORVNTXzIgY2hhciBhW05dLCBi W05dOworICBTSUdORURORVNTXzIgY2hhciBjW05dLCBkW05dOworICBTSUdORURORVNTXzEgaW50 IGVbTl07CisgIGludCBleHBlY3RlZCA9IDB4MTIzNDU7CisgIGZvciAoaW50IGkgPSAwOyBpIDwg TjsgKytpKQorICAgIHsKKyAgICAgIGFbaV0gPSBCQVNFICsgaSAqIDU7CisgICAgICBiW2ldID0g QkFTRSArIE9GRlNFVCArIGkgKiA0OworICAgICAgY1tpXSA9IEJBU0UgKyBpICogMjsKKyAgICAg IGRbaV0gPSBCQVNFICsgT0ZGU0VUICsgaSAqIDM7CisgICAgICBlW2ldID0gaTsKKyAgICAgIGFz bSB2b2xhdGlsZSAoIiIgOjo6ICJtZW1vcnkiKTsKKyAgICAgIGV4cGVjdGVkICs9IGFbaV0gKiBi W2ldOworICAgICAgZXhwZWN0ZWQgKz0gY1tpXSAqIGRbaV07CisgICAgICBleHBlY3RlZCArPSBl W2ldOworICAgIH0KKyAgaWYgKGYgKDB4MTIzNDUsIGEsIGIsIGMsIGQsIGUpICE9IGV4cGVjdGVk KQorICAgIF9fYnVpbHRpbl9hYm9ydCAoKTsKK30KKworLyogeyBkZy1maW5hbCB7IHNjYW4tdHJl ZS1kdW1wICJ2ZWN0X3JlY29nX2RvdF9wcm9kX3BhdHRlcm46IGRldGVjdGVkIiAidmVjdCIgfSB9 ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi10cmVlLWR1bXAtdGltZXMgInZlY3Rvcml6aW5nIHN0 YXRlbWVudDogXFxTKyA9IERPVF9QUk9EX0VYUFIiIDIgInZlY3QiIHsgdGFyZ2V0IHZlY3Rfc2Rv dF9xaSB9IH0gfSAqLwpkaWZmIC0tZ2l0IGEvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcvdmVjdC92ZWN0 LXJlZHVjLWNoYWluLTIuYyBiL2djYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1j aGFpbi0yLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLjZjODAzYjgw MTIwCi0tLSAvZGV2L251bGwKKysrIGIvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcvdmVjdC92ZWN0LXJl ZHVjLWNoYWluLTIuYwpAQCAtMCwwICsxLDc3IEBACisvKiBEaXNhYmxpbmcgZXBpbG9ndWVzIHVu dGlsIHdlIGZpbmQgYSBiZXR0ZXIgd2F5IHRvIGRlYWwgd2l0aCBzY2Fucy4gICovCisvKiB7IGRn LWFkZGl0aW9uYWwtb3B0aW9ucyAiLS1wYXJhbSB2ZWN0LWVwaWxvZ3Vlcy1ub21hc2s9MCIgfSAq LworLyogeyBkZy1yZXF1aXJlLWVmZmVjdGl2ZS10YXJnZXQgdmVjdF9pbnQgfSAqLworLyogeyBk Zy1yZXF1aXJlLWVmZmVjdGl2ZS10YXJnZXQgYXJtX3Y4XzJhX2RvdHByb2RfbmVvbl9odyB7IHRh cmdldCB7IGFhcmNoNjQqLSotKiB8fCBhcm0qLSotKiB9IH0gfSAqLworLyogeyBkZy1hZGQtb3B0 aW9ucyBhcm1fdjhfMmFfZG90cHJvZF9uZW9uIH0gICovCisKKyNpbmNsdWRlICJ0cmVlLXZlY3Qu aCIKKworI2RlZmluZSBOIDUwCisKKyNpZm5kZWYgU0lHTkVETkVTU18xCisjZGVmaW5lIFNJR05F RE5FU1NfMSBzaWduZWQKKyNkZWZpbmUgU0lHTkVETkVTU18yIHVuc2lnbmVkCisjZGVmaW5lIFNJ R05FRE5FU1NfMyBzaWduZWQKKyNkZWZpbmUgU0lHTkVETkVTU180IHNpZ25lZAorI2VuZGlmCisK K1NJR05FRE5FU1NfMSBpbnQgX19hdHRyaWJ1dGVfXyAoKG5vaXBhKSkKK2ZuIChTSUdORURORVNT XzEgaW50IHJlcywKKyAgIFNJR05FRE5FU1NfMiBjaGFyICpyZXN0cmljdCBhLAorICAgU0lHTkVE TkVTU18yIGNoYXIgKnJlc3RyaWN0IGIsCisgICBTSUdORURORVNTXzMgY2hhciAqcmVzdHJpY3Qg YywKKyAgIFNJR05FRE5FU1NfMyBjaGFyICpyZXN0cmljdCBkLAorICAgU0lHTkVETkVTU180IHNo b3J0ICpyZXN0cmljdCBlLAorICAgU0lHTkVETkVTU180IHNob3J0ICpyZXN0cmljdCBmLAorICAg U0lHTkVETkVTU18xIGludCAqcmVzdHJpY3QgZykKK3sKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCBO OyArK2kpCisgICAgeworICAgICAgcmVzICs9IGFbaV0gKiBiW2ldOworICAgICAgcmVzICs9IGkg KyAxOworICAgICAgcmVzICs9IGNbaV0gKiBkW2ldOworICAgICAgcmVzICs9IGVbaV0gKiBmW2ld OworICAgICAgcmVzICs9IGdbaV07CisgICAgfQorICByZXR1cm4gcmVzOworfQorCisjZGVmaW5l IEJBU0UyICgoU0lHTkVETkVTU18yIGludCkgLTEgPCAwID8gLTEyNiA6IDQpCisjZGVmaW5lIEJB U0UzICgoU0lHTkVETkVTU18zIGludCkgLTEgPCAwID8gLTEyNiA6IDQpCisjZGVmaW5lIEJBU0U0 ICgoU0lHTkVETkVTU180IGludCkgLTEgPCAwID8gLTEwMjYgOiAzNzMpCisjZGVmaW5lIE9GRlNF VCAyMAorCitpbnQKK21haW4gKHZvaWQpCit7CisgIGNoZWNrX3ZlY3QgKCk7CisKKyAgU0lHTkVE TkVTU18yIGNoYXIgYVtOXSwgYltOXTsKKyAgU0lHTkVETkVTU18zIGNoYXIgY1tOXSwgZFtOXTsK KyAgU0lHTkVETkVTU180IHNob3J0IGVbTl0sIGZbTl07CisgIFNJR05FRE5FU1NfMSBpbnQgZ1tO XTsKKyAgaW50IGV4cGVjdGVkID0gMHgxMjM0NTsKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyAr K2kpCisgICAgeworICAgICAgYVtpXSA9IEJBU0UyICsgaSAqIDU7CisgICAgICBiW2ldID0gQkFT RTIgKyBPRkZTRVQgKyBpICogNDsKKyAgICAgIGNbaV0gPSBCQVNFMyArIGkgKiAyOworICAgICAg ZFtpXSA9IEJBU0UzICsgT0ZGU0VUICsgaSAqIDM7CisgICAgICBlW2ldID0gQkFTRTQgKyBpICog NjsKKyAgICAgIGZbaV0gPSBCQVNFNCArIE9GRlNFVCArIGkgKiA1OworICAgICAgZ1tpXSA9IGk7 CisgICAgICBhc20gdm9sYXRpbGUgKCIiIDo6OiAibWVtb3J5Iik7CisgICAgICBleHBlY3RlZCAr PSBhW2ldICogYltpXTsKKyAgICAgIGV4cGVjdGVkICs9IGkgKyAxOworICAgICAgZXhwZWN0ZWQg Kz0gY1tpXSAqIGRbaV07CisgICAgICBleHBlY3RlZCArPSBlW2ldICogZltpXTsKKyAgICAgIGV4 cGVjdGVkICs9IGdbaV07CisgICAgfQorICBpZiAoZm4gKDB4MTIzNDUsIGEsIGIsIGMsIGQsIGUs IGYsIGcpICE9IGV4cGVjdGVkKQorICAgIF9fYnVpbHRpbl9hYm9ydCAoKTsKK30KKworLyogeyBk Zy1maW5hbCB7IHNjYW4tdHJlZS1kdW1wICJ2ZWN0X3JlY29nX2RvdF9wcm9kX3BhdHRlcm46IGRl dGVjdGVkIiAidmVjdCIgfSB9ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi10cmVlLWR1bXAgInZl Y3Rvcml6aW5nIHN0YXRlbWVudDogXFxTKyA9IERPVF9QUk9EX0VYUFIiICJ2ZWN0IiB7IHRhcmdl dCB7IHZlY3Rfc2RvdF9xaSB9IH0gfSB9ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi10cmVlLWR1 bXAgInZlY3Rvcml6aW5nIHN0YXRlbWVudDogXFxTKyA9IERPVF9QUk9EX0VYUFIiICJ2ZWN0IiB7 IHRhcmdldCB7IHZlY3RfdWRvdF9xaSB9IH0gfSB9ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi10 cmVlLWR1bXAgInZlY3Rvcml6aW5nIHN0YXRlbWVudDogXFxTKyA9IERPVF9QUk9EX0VYUFIiICJ2 ZWN0IiB7IHRhcmdldCB7IHZlY3Rfc2RvdF9oaSB9IH0gfSB9ICovCmRpZmYgLS1naXQgYS9nY2Mv dGVzdHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tMy5jIGIvZ2NjL3Rlc3RzdWl0 ZS9nY2MuZGcvdmVjdC92ZWN0LXJlZHVjLWNoYWluLTMuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NApp bmRleCAwMDAwMDAwMDAwMC4uYTQxZTRiMTc2YzQKLS0tIC9kZXYvbnVsbAorKysgYi9nY2MvdGVz dHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tMy5jCkBAIC0wLDAgKzEsNjYgQEAK Ky8qIERpc2FibGluZyBlcGlsb2d1ZXMgdW50aWwgd2UgZmluZCBhIGJldHRlciB3YXkgdG8gZGVh bCB3aXRoIHNjYW5zLiAgKi8KKy8qIHsgZGctYWRkaXRpb25hbC1vcHRpb25zICItLXBhcmFtIHZl Y3QtZXBpbG9ndWVzLW5vbWFzaz0wIiB9ICovCisvKiB7IGRnLXJlcXVpcmUtZWZmZWN0aXZlLXRh cmdldCB2ZWN0X2ludCB9ICovCisKKyNpbmNsdWRlICJ0cmVlLXZlY3QuaCIKKworI2RlZmluZSBO IDUwCisKKyNpZm5kZWYgU0lHTkVETkVTU18xCisjZGVmaW5lIFNJR05FRE5FU1NfMSBzaWduZWQK KyNkZWZpbmUgU0lHTkVETkVTU18yIHVuc2lnbmVkCisjZGVmaW5lIFNJR05FRE5FU1NfMyBzaWdu ZWQKKyNlbmRpZgorCitTSUdORURORVNTXzEgaW50IF9fYXR0cmlidXRlX18gKChub2lwYSkpCitm IChTSUdORURORVNTXzEgaW50IHJlcywKKyAgIFNJR05FRE5FU1NfMiBjaGFyICpyZXN0cmljdCBh LAorICAgU0lHTkVETkVTU18yIGNoYXIgKnJlc3RyaWN0IGIsCisgICBTSUdORURORVNTXzMgc2hv cnQgKnJlc3RyaWN0IGMsCisgICBTSUdORURORVNTXzMgc2hvcnQgKnJlc3RyaWN0IGQsCisgICBT SUdORURORVNTXzEgaW50ICpyZXN0cmljdCBlKQoreworICBmb3IgKGludCBpID0gMDsgaSA8IE47 ICsraSkKKyAgICB7CisgICAgICBzaG9ydCBkaWZmID0gYVtpXSAtIGJbaV07CisgICAgICBTSUdO RURORVNTXzIgc2hvcnQgYWJzID0gZGlmZiA8IDAgPyAtZGlmZiA6IGRpZmY7CisgICAgICByZXMg Kz0gYWJzOworICAgICAgcmVzICs9IGNbaV0gKiBkW2ldOworICAgICAgcmVzICs9IGVbaV07Cisg ICAgfQorICByZXR1cm4gcmVzOworfQorCisjZGVmaW5lIEJBU0UyICgoU0lHTkVETkVTU18yIGlu dCkgLTEgPCAwID8gLTEyNiA6IDQpCisjZGVmaW5lIEJBU0UzICgoU0lHTkVETkVTU18zIGludCkg LTEgPCAwID8gLTEyMzYgOiAzNzMpCisjZGVmaW5lIE9GRlNFVCAyMAorCitpbnQKK21haW4gKHZv aWQpCit7CisgIGNoZWNrX3ZlY3QgKCk7CisKKyAgU0lHTkVETkVTU18yIGNoYXIgYVtOXSwgYltO XTsKKyAgU0lHTkVETkVTU18zIHNob3J0IGNbTl0sIGRbTl07CisgIFNJR05FRE5FU1NfMSBpbnQg ZVtOXTsKKyAgaW50IGV4cGVjdGVkID0gMHgxMjM0NTsKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCBO OyArK2kpCisgICAgeworICAgICAgYVtpXSA9IEJBU0UyICsgaSAqIDU7CisgICAgICBiW2ldID0g QkFTRTIgLSBpICogNDsKKyAgICAgIGNbaV0gPSBCQVNFMyArIGkgKiAyOworICAgICAgZFtpXSA9 IEJBU0UzICsgT0ZGU0VUICsgaSAqIDM7CisgICAgICBlW2ldID0gaTsKKyAgICAgIGFzbSB2b2xh dGlsZSAoIiIgOjo6ICJtZW1vcnkiKTsKKyAgICAgIHNob3J0IGRpZmYgPSBhW2ldIC0gYltpXTsK KyAgICAgIFNJR05FRE5FU1NfMiBzaG9ydCBhYnMgPSBkaWZmIDwgMCA/IC1kaWZmIDogZGlmZjsK KyAgICAgIGV4cGVjdGVkICs9IGFiczsKKyAgICAgIGV4cGVjdGVkICs9IGNbaV0gKiBkW2ldOwor ICAgICAgZXhwZWN0ZWQgKz0gZVtpXTsKKyAgICB9CisgIGlmIChmICgweDEyMzQ1LCBhLCBiLCBj LCBkLCBlKSAhPSBleHBlY3RlZCkKKyAgICBfX2J1aWx0aW5fYWJvcnQgKCk7Cit9CisKKy8qIHsg ZGctZmluYWwgeyBzY2FuLXRyZWUtZHVtcCAidmVjdG9yaXppbmcgc3RhdGVtZW50OiBcXFMrID0g U0FEX0VYUFIiICJ2ZWN0IiB7IHRhcmdldCB2ZWN0X3Vkb3RfcWkgfSB9IH0gKi8KKy8qIHsgZGct ZmluYWwgeyBzY2FuLXRyZWUtZHVtcCAidmVjdG9yaXppbmcgc3RhdGVtZW50OiBcXFMrID0gRE9U X1BST0RfRVhQUiIgInZlY3QiIHsgdGFyZ2V0IHZlY3Rfc2RvdF9oaSB9IH0gfSAqLwpkaWZmIC0t Z2l0IGEvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcvdmVjdC92ZWN0LXJlZHVjLWNoYWluLWRvdC1zbHAt MS5jIGIvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcvdmVjdC92ZWN0LXJlZHVjLWNoYWluLWRvdC1zbHAt MS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwLi5jMjgzMWZiY2M4ZQot LS0gL2Rldi9udWxsCisrKyBiL2djYy90ZXN0c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1j aGFpbi1kb3Qtc2xwLTEuYwpAQCAtMCwwICsxLDk1IEBACisvKiBEaXNhYmxpbmcgZXBpbG9ndWVz IHVudGlsIHdlIGZpbmQgYSBiZXR0ZXIgd2F5IHRvIGRlYWwgd2l0aCBzY2Fucy4gICovCisvKiB7 IGRnLWFkZGl0aW9uYWwtb3B0aW9ucyAiLS1wYXJhbSB2ZWN0LWVwaWxvZ3Vlcy1ub21hc2s9MCIg fSAqLworLyogeyBkZy1yZXF1aXJlLWVmZmVjdGl2ZS10YXJnZXQgdmVjdF9pbnQgfSAqLworLyog eyBkZy1yZXF1aXJlLWVmZmVjdGl2ZS10YXJnZXQgYXJtX3Y4XzJhX2RvdHByb2RfbmVvbl9odyB7 IHRhcmdldCB7IGFhcmNoNjQqLSotKiB8fCBhcm0qLSotKiB9IH0gfSAqLworLyogeyBkZy1hZGQt b3B0aW9ucyBhcm1fdjhfMmFfZG90cHJvZF9uZW9uIH0gICovCisKKyNpbmNsdWRlICJ0cmVlLXZl Y3QuaCIKKworI2lmbmRlZiBTSUdORURORVNTXzEKKyNkZWZpbmUgU0lHTkVETkVTU18xIHNpZ25l ZAorI2RlZmluZSBTSUdORURORVNTXzIgc2lnbmVkCisjZW5kaWYKKworU0lHTkVETkVTU18xIGlu dCBfX2F0dHJpYnV0ZV9fICgobm9pcGEpKQorZiAoU0lHTkVETkVTU18xIGludCByZXMsCisgICBT SUdORURORVNTXzIgY2hhciAqYSwKKyAgIFNJR05FRE5FU1NfMiBjaGFyICpiLAorICAgaW50IHN0 ZXAsIGludCBuKQoreworICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykKKyAgICB7CisgICAg ICByZXMgKz0gYVswXSAqIGJbMF07CisgICAgICByZXMgKz0gYVsxXSAqIGJbMV07CisgICAgICBy ZXMgKz0gYVsyXSAqIGJbMl07CisgICAgICByZXMgKz0gYVszXSAqIGJbM107CisgICAgICByZXMg Kz0gYVs0XSAqIGJbNF07CisgICAgICByZXMgKz0gYVs1XSAqIGJbNV07CisgICAgICByZXMgKz0g YVs2XSAqIGJbNl07CisgICAgICByZXMgKz0gYVs3XSAqIGJbN107CisgICAgICByZXMgKz0gYVs4 XSAqIGJbOF07CisgICAgICByZXMgKz0gYVs5XSAqIGJbOV07CisgICAgICByZXMgKz0gYVsxMF0g KiBiWzEwXTsKKyAgICAgIHJlcyArPSBhWzExXSAqIGJbMTFdOworICAgICAgcmVzICs9IGFbMTJd ICogYlsxMl07CisgICAgICByZXMgKz0gYVsxM10gKiBiWzEzXTsKKyAgICAgIHJlcyArPSBhWzE0 XSAqIGJbMTRdOworICAgICAgcmVzICs9IGFbMTVdICogYlsxNV07CisKKyAgICAgIGEgKz0gc3Rl cDsKKyAgICAgIGIgKz0gc3RlcDsKKyAgICB9CisKKyAgcmV0dXJuIHJlczsKK30KKworI2RlZmlu ZSBCQVNFICgoU0lHTkVETkVTU18yIGludCkgLTEgPCAwID8gLTEyNiA6IDQpCisjZGVmaW5lIE9G RlNFVCAyMAorCitpbnQKK21haW4gKHZvaWQpCit7CisgIGNoZWNrX3ZlY3QgKCk7CisKKyAgU0lH TkVETkVTU18yIGNoYXIgYVsxMDBdLCBiWzEwMF07CisgIGludCBleHBlY3RlZCA9IDB4MTIzNDU7 CisgIGludCBzdGVwID0gMTY7CisgIGludCBuID0gMjsKKyAgaW50IHQgPSAwOworCisgIGZvciAo aW50IGkgPSAwOyBpIDwgc2l6ZW9mIChhKSAvIHNpemVvZiAoYVswXSk7ICsraSkKKyAgICB7Cisg ICAgICBhW2ldID0gQkFTRSArIGkgKiA1OworICAgICAgYltpXSA9IEJBU0UgKyBPRkZTRVQgKyBp ICogNDsKKyAgICAgIGFzbSB2b2xhdGlsZSAoIiIgOjo6ICJtZW1vcnkiKTsKKyAgICB9CisKKyAg Zm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCisgICAgeworICAgICAgYXNtIHZvbGF0aWxlICgi IiA6OjogIm1lbW9yeSIpOworICAgICAgZXhwZWN0ZWQgKz0gYVt0ICsgMF0gKiBiW3QgKyAwXTsK KyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDFdICogYlt0ICsgMV07CisgICAgICBleHBlY3RlZCAr PSBhW3QgKyAyXSAqIGJbdCArIDJdOworICAgICAgZXhwZWN0ZWQgKz0gYVt0ICsgM10gKiBiW3Qg KyAzXTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDRdICogYlt0ICsgNF07CisgICAgICBleHBl Y3RlZCArPSBhW3QgKyA1XSAqIGJbdCArIDVdOworICAgICAgZXhwZWN0ZWQgKz0gYVt0ICsgNl0g KiBiW3QgKyA2XTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDddICogYlt0ICsgN107CisgICAg ICBleHBlY3RlZCArPSBhW3QgKyA4XSAqIGJbdCArIDhdOworICAgICAgZXhwZWN0ZWQgKz0gYVt0 ICsgOV0gKiBiW3QgKyA5XTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDEwXSAqIGJbdCArIDEw XTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDExXSAqIGJbdCArIDExXTsKKyAgICAgIGV4cGVj dGVkICs9IGFbdCArIDEyXSAqIGJbdCArIDEyXTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDEz XSAqIGJbdCArIDEzXTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDE0XSAqIGJbdCArIDE0XTsK KyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDE1XSAqIGJbdCArIDE1XTsKKyAgICAgIHQgKz0gc3Rl cDsKKyAgICB9CisKKyAgaWYgKGYgKDB4MTIzNDUsIGEsIGIsIHN0ZXAsIG4pICE9IGV4cGVjdGVk KQorICAgIF9fYnVpbHRpbl9hYm9ydCAoKTsKK30KKworLyogeyBkZy1maW5hbCB7IHNjYW4tdHJl ZS1kdW1wICJ2ZWN0X3JlY29nX2RvdF9wcm9kX3BhdHRlcm46IGRldGVjdGVkIiAidmVjdCIgfSB9 ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi10cmVlLWR1bXAgInZlY3Rvcml6aW5nIHN0bXRzIHVz aW5nIFNMUCIgInZlY3QiIH0gfSAqLworLyogeyBkZy1maW5hbCB7IHNjYW4tdHJlZS1kdW1wLXRp bWVzICJ2ZWN0b3JpemluZyBzdGF0ZW1lbnQ6IFxcUysgPSBET1RfUFJPRF9FWFBSIiAxNiAidmVj dCIgfSB9ICovCmRpZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVk dWMtY2hhaW4tZG90LXNscC0yLmMgYi9nY2MvdGVzdHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVk dWMtY2hhaW4tZG90LXNscC0yLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAw MDAuLjQxMTQyNjRhMzY0Ci0tLSAvZGV2L251bGwKKysrIGIvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcv dmVjdC92ZWN0LXJlZHVjLWNoYWluLWRvdC1zbHAtMi5jCkBAIC0wLDAgKzEsNjcgQEAKKy8qIERp c2FibGluZyBlcGlsb2d1ZXMgdW50aWwgd2UgZmluZCBhIGJldHRlciB3YXkgdG8gZGVhbCB3aXRo IHNjYW5zLiAgKi8KKy8qIHsgZGctYWRkaXRpb25hbC1vcHRpb25zICItLXBhcmFtIHZlY3QtZXBp bG9ndWVzLW5vbWFzaz0wIiB9ICovCisvKiB7IGRnLXJlcXVpcmUtZWZmZWN0aXZlLXRhcmdldCB2 ZWN0X2ludCB9ICovCisvKiB7IGRnLXJlcXVpcmUtZWZmZWN0aXZlLXRhcmdldCBhcm1fdjhfMmFf ZG90cHJvZF9uZW9uX2h3IHsgdGFyZ2V0IHsgYWFyY2g2NCotKi0qIHx8IGFybSotKi0qIH0gfSB9 ICovCisvKiB7IGRnLWFkZC1vcHRpb25zIGFybV92OF8yYV9kb3Rwcm9kX25lb24gfSAgKi8KKwor I2luY2x1ZGUgInRyZWUtdmVjdC5oIgorCisjaWZuZGVmIFNJR05FRE5FU1NfMQorI2RlZmluZSBT SUdORURORVNTXzEgc2lnbmVkCisjZGVmaW5lIFNJR05FRE5FU1NfMiBzaWduZWQKKyNlbmRpZgor CitTSUdORURORVNTXzEgaW50IF9fYXR0cmlidXRlX18gKChub2lwYSkpCitmIChTSUdORURORVNT XzEgaW50IHJlcywKKyAgIFNJR05FRE5FU1NfMiBjaGFyICphLAorICAgU0lHTkVETkVTU18yIGNo YXIgKmIsCisgICBpbnQgbikKK3sKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCisgICAg eworICAgICAgcmVzICs9IGFbNSAqIGkgKyAwXSAqIGJbNSAqIGkgKyAwXTsKKyAgICAgIHJlcyAr PSBhWzUgKiBpICsgMV0gKiBiWzUgKiBpICsgMV07CisgICAgICByZXMgKz0gYVs1ICogaSArIDJd ICogYls1ICogaSArIDJdOworICAgICAgcmVzICs9IGFbNSAqIGkgKyAzXSAqIGJbNSAqIGkgKyAz XTsKKyAgICAgIHJlcyArPSBhWzUgKiBpICsgNF0gKiBiWzUgKiBpICsgNF07CisgICAgfQorCisg IHJldHVybiByZXM7Cit9CisKKyNkZWZpbmUgQkFTRSAoKFNJR05FRE5FU1NfMiBpbnQpIC0xIDwg MCA/IC0xMjYgOiA0KQorI2RlZmluZSBPRkZTRVQgMjAKKworaW50CittYWluICh2b2lkKQorewor ICBjaGVja192ZWN0ICgpOworCisgIFNJR05FRE5FU1NfMiBjaGFyIGFbMTAwXSwgYlsxMDBdOwor ICBpbnQgZXhwZWN0ZWQgPSAweDEyMzQ1OworICBpbnQgbiA9IDE4OworCisgIGZvciAoaW50IGkg PSAwOyBpIDwgc2l6ZW9mIChhKSAvIHNpemVvZiAoYVswXSk7ICsraSkKKyAgICB7CisgICAgICBh W2ldID0gQkFTRSArIGkgKiA1OworICAgICAgYltpXSA9IEJBU0UgKyBPRkZTRVQgKyBpICogNDsK KyAgICAgIGFzbSB2b2xhdGlsZSAoIiIgOjo6ICJtZW1vcnkiKTsKKyAgICB9CisKKyAgZm9yIChp bnQgaSA9IDA7IGkgPCBuOyBpKyspCisgICAgeworICAgICAgYXNtIHZvbGF0aWxlICgiIiA6Ojog Im1lbW9yeSIpOworICAgICAgZXhwZWN0ZWQgKz0gYVs1ICogaSArIDBdICogYls1ICogaSArIDBd OworICAgICAgZXhwZWN0ZWQgKz0gYVs1ICogaSArIDFdICogYls1ICogaSArIDFdOworICAgICAg ZXhwZWN0ZWQgKz0gYVs1ICogaSArIDJdICogYls1ICogaSArIDJdOworICAgICAgZXhwZWN0ZWQg Kz0gYVs1ICogaSArIDNdICogYls1ICogaSArIDNdOworICAgICAgZXhwZWN0ZWQgKz0gYVs1ICog aSArIDRdICogYls1ICogaSArIDRdOworICAgIH0KKworICBpZiAoZiAoMHgxMjM0NSwgYSwgYiwg bikgIT0gZXhwZWN0ZWQpCisgICAgX19idWlsdGluX2Fib3J0ICgpOworfQorCisvKiB7IGRnLWZp bmFsIHsgc2Nhbi10cmVlLWR1bXAgInZlY3RfcmVjb2dfZG90X3Byb2RfcGF0dGVybjogZGV0ZWN0 ZWQiICJ2ZWN0IiB9IH0gKi8KKy8qIHsgZGctZmluYWwgeyBzY2FuLXRyZWUtZHVtcCAidmVjdG9y aXppbmcgc3RtdHMgdXNpbmcgU0xQIiAidmVjdCIgfSB9ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nh bi10cmVlLWR1bXAtdGltZXMgInZlY3Rvcml6aW5nIHN0YXRlbWVudDogXFxTKyA9IERPVF9QUk9E X0VYUFIiIDUgInZlY3QiIH0gfSAqLwpkaWZmIC0tZ2l0IGEvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcv dmVjdC92ZWN0LXJlZHVjLWNoYWluLWRvdC1zbHAtMy5jIGIvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcv dmVjdC92ZWN0LXJlZHVjLWNoYWluLWRvdC1zbHAtMy5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0Cmlu ZGV4IDAwMDAwMDAwMDAwLi4yY2RlY2MzNmQxNgotLS0gL2Rldi9udWxsCisrKyBiL2djYy90ZXN0 c3VpdGUvZ2NjLmRnL3ZlY3QvdmVjdC1yZWR1Yy1jaGFpbi1kb3Qtc2xwLTMuYwpAQCAtMCwwICsx LDc5IEBACisvKiBEaXNhYmxpbmcgZXBpbG9ndWVzIHVudGlsIHdlIGZpbmQgYSBiZXR0ZXIgd2F5 IHRvIGRlYWwgd2l0aCBzY2Fucy4gICovCisvKiB7IGRnLWFkZGl0aW9uYWwtb3B0aW9ucyAiLS1w YXJhbSB2ZWN0LWVwaWxvZ3Vlcy1ub21hc2s9MCIgfSAqLworLyogeyBkZy1yZXF1aXJlLWVmZmVj dGl2ZS10YXJnZXQgdmVjdF9pbnQgfSAqLworLyogeyBkZy1yZXF1aXJlLWVmZmVjdGl2ZS10YXJn ZXQgYXJtX3Y4XzJhX2RvdHByb2RfbmVvbl9odyB7IHRhcmdldCB7IGFhcmNoNjQqLSotKiB8fCBh cm0qLSotKiB9IH0gfSAqLworLyogeyBkZy1hZGQtb3B0aW9ucyBhcm1fdjhfMmFfZG90cHJvZF9u ZW9uIH0gICovCisKKyNpbmNsdWRlICJ0cmVlLXZlY3QuaCIKKworI2lmbmRlZiBTSUdORURORVNT XzEKKyNkZWZpbmUgU0lHTkVETkVTU18xIHNpZ25lZAorI2RlZmluZSBTSUdORURORVNTXzIgc2ln bmVkCisjZW5kaWYKKworU0lHTkVETkVTU18xIGludCBfX2F0dHJpYnV0ZV9fICgobm9pcGEpKQor ZiAoU0lHTkVETkVTU18xIGludCByZXMsCisgICBTSUdORURORVNTXzIgc2hvcnQgKmEsCisgICBT SUdORURORVNTXzIgc2hvcnQgKmIsCisgICBpbnQgc3RlcCwgaW50IG4pCit7CisgIGZvciAoaW50 IGkgPSAwOyBpIDwgbjsgaSsrKQorICAgIHsKKyAgICAgIHJlcyArPSBhWzBdICogYlswXTsKKyAg ICAgIHJlcyArPSBhWzFdICogYlsxXTsKKyAgICAgIHJlcyArPSBhWzJdICogYlsyXTsKKyAgICAg IHJlcyArPSBhWzNdICogYlszXTsKKyAgICAgIHJlcyArPSBhWzRdICogYls0XTsKKyAgICAgIHJl cyArPSBhWzVdICogYls1XTsKKyAgICAgIHJlcyArPSBhWzZdICogYls2XTsKKyAgICAgIHJlcyAr PSBhWzddICogYls3XTsKKworICAgICAgYSArPSBzdGVwOworICAgICAgYiArPSBzdGVwOworICAg IH0KKworICByZXR1cm4gcmVzOworfQorCisjZGVmaW5lIEJBU0UgKChTSUdORURORVNTXzIgaW50 KSAtMSA8IDAgPyAtMTAyNiA6IDM3MykKKyNkZWZpbmUgT0ZGU0VUIDIwCisKK2ludAorbWFpbiAo dm9pZCkKK3sKKyAgY2hlY2tfdmVjdCAoKTsKKworICBTSUdORURORVNTXzIgc2hvcnQgYVsxMDBd LCBiWzEwMF07CisgIGludCBleHBlY3RlZCA9IDB4MTIzNDU7CisgIGludCBzdGVwID0gODsKKyAg aW50IG4gPSAyOworICBpbnQgdCA9IDA7CisKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCBzaXplb2Yg KGEpIC8gc2l6ZW9mIChhWzBdKTsgKytpKQorICAgIHsKKyAgICAgIGFbaV0gPSBCQVNFICsgaSAq IDU7CisgICAgICBiW2ldID0gQkFTRSArIE9GRlNFVCArIGkgKiA0OworICAgICAgYXNtIHZvbGF0 aWxlICgiIiA6OjogIm1lbW9yeSIpOworICAgIH0KKworICBmb3IgKGludCBpID0gMDsgaSA8IG47 IGkrKykKKyAgICB7CisgICAgICBhc20gdm9sYXRpbGUgKCIiIDo6OiAibWVtb3J5Iik7CisgICAg ICBleHBlY3RlZCArPSBhW3QgKyAwXSAqIGJbdCArIDBdOworICAgICAgZXhwZWN0ZWQgKz0gYVt0 ICsgMV0gKiBiW3QgKyAxXTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDJdICogYlt0ICsgMl07 CisgICAgICBleHBlY3RlZCArPSBhW3QgKyAzXSAqIGJbdCArIDNdOworICAgICAgZXhwZWN0ZWQg Kz0gYVt0ICsgNF0gKiBiW3QgKyA0XTsKKyAgICAgIGV4cGVjdGVkICs9IGFbdCArIDVdICogYlt0 ICsgNV07CisgICAgICBleHBlY3RlZCArPSBhW3QgKyA2XSAqIGJbdCArIDZdOworICAgICAgZXhw ZWN0ZWQgKz0gYVt0ICsgN10gKiBiW3QgKyA3XTsKKyAgICAgIHQgKz0gc3RlcDsKKyAgICB9CisK KyAgaWYgKGYgKDB4MTIzNDUsIGEsIGIsIHN0ZXAsIG4pICE9IGV4cGVjdGVkKQorICAgIF9fYnVp bHRpbl9hYm9ydCAoKTsKK30KKworLyogeyBkZy1maW5hbCB7IHNjYW4tdHJlZS1kdW1wICJ2ZWN0 X3JlY29nX2RvdF9wcm9kX3BhdHRlcm46IGRldGVjdGVkIiAidmVjdCIgfSB9ICovCisvKiB7IGRn LWZpbmFsIHsgc2Nhbi10cmVlLWR1bXAgInZlY3Rvcml6aW5nIHN0bXRzIHVzaW5nIFNMUCIgInZl Y3QiIH0gfSAqLworLyogeyBkZy1maW5hbCB7IHNjYW4tdHJlZS1kdW1wLXRpbWVzICJ2ZWN0b3Jp emluZyBzdGF0ZW1lbnQ6IFxcUysgPSBET1RfUFJPRF9FWFBSIiA4ICJ2ZWN0IiAgeyB0YXJnZXQg dmVjdF9zZG90X2hpIH0gfSB9ICovCmRpZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2djYy5kZy92 ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tZG90LXNscC00LmMgYi9nY2MvdGVzdHN1aXRlL2djYy5kZy92 ZWN0L3ZlY3QtcmVkdWMtY2hhaW4tZG90LXNscC00LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5k ZXggMDAwMDAwMDAwMDAuLjMyYzBmMzBjNzdiCi0tLSAvZGV2L251bGwKKysrIGIvZ2NjL3Rlc3Rz dWl0ZS9nY2MuZGcvdmVjdC92ZWN0LXJlZHVjLWNoYWluLWRvdC1zbHAtNC5jCkBAIC0wLDAgKzEs NjMgQEAKKy8qIERpc2FibGluZyBlcGlsb2d1ZXMgdW50aWwgd2UgZmluZCBhIGJldHRlciB3YXkg dG8gZGVhbCB3aXRoIHNjYW5zLiAgKi8KKy8qIHsgZGctYWRkaXRpb25hbC1vcHRpb25zICItLXBh cmFtIHZlY3QtZXBpbG9ndWVzLW5vbWFzaz0wIiB9ICovCisvKiB7IGRnLXJlcXVpcmUtZWZmZWN0 aXZlLXRhcmdldCB2ZWN0X2ludCB9ICovCisvKiB7IGRnLXJlcXVpcmUtZWZmZWN0aXZlLXRhcmdl dCBhcm1fdjhfMmFfZG90cHJvZF9uZW9uX2h3IHsgdGFyZ2V0IHsgYWFyY2g2NCotKi0qIHx8IGFy bSotKi0qIH0gfSB9ICovCisvKiB7IGRnLWFkZC1vcHRpb25zIGFybV92OF8yYV9kb3Rwcm9kX25l b24gfSAgKi8KKworI2luY2x1ZGUgInRyZWUtdmVjdC5oIgorCisjaWZuZGVmIFNJR05FRE5FU1Nf MQorI2RlZmluZSBTSUdORURORVNTXzEgc2lnbmVkCisjZGVmaW5lIFNJR05FRE5FU1NfMiBzaWdu ZWQKKyNlbmRpZgorCitTSUdORURORVNTXzEgaW50IF9fYXR0cmlidXRlX18gKChub2lwYSkpCitm IChTSUdORURORVNTXzEgaW50IHJlcywKKyAgIFNJR05FRE5FU1NfMiBzaG9ydCAqYSwKKyAgIFNJ R05FRE5FU1NfMiBzaG9ydCAqYiwKKyAgIGludCBuKQoreworICBmb3IgKGludCBpID0gMDsgaSA8 IG47IGkrKykKKyAgICB7CisgICAgICByZXMgKz0gYVszICogaSArIDBdICogYlszICogaSArIDBd OworICAgICAgcmVzICs9IGFbMyAqIGkgKyAxXSAqIGJbMyAqIGkgKyAxXTsKKyAgICAgIHJlcyAr PSBhWzMgKiBpICsgMl0gKiBiWzMgKiBpICsgMl07CisgICAgfQorCisgIHJldHVybiByZXM7Cit9 CisKKyNkZWZpbmUgQkFTRSAoKFNJR05FRE5FU1NfMiBpbnQpIC0xIDwgMCA/IC0xMDI2IDogMzcz KQorI2RlZmluZSBPRkZTRVQgMjAKKworaW50CittYWluICh2b2lkKQoreworICBjaGVja192ZWN0 ICgpOworCisgIFNJR05FRE5FU1NfMiBzaG9ydCBhWzEwMF0sIGJbMTAwXTsKKyAgaW50IGV4cGVj dGVkID0gMHgxMjM0NTsKKyAgaW50IG4gPSAxODsKKworICBmb3IgKGludCBpID0gMDsgaSA8IHNp emVvZiAoYSkgLyBzaXplb2YgKGFbMF0pOyArK2kpCisgICAgeworICAgICAgYVtpXSA9IEJBU0Ug KyBpICogNTsKKyAgICAgIGJbaV0gPSBCQVNFICsgT0ZGU0VUICsgaSAqIDQ7CisgICAgICBhc20g dm9sYXRpbGUgKCIiIDo6OiAibWVtb3J5Iik7CisgICAgfQorCisgIGZvciAoaW50IGkgPSAwOyBp IDwgbjsgaSsrKQorICAgIHsKKyAgICAgIGFzbSB2b2xhdGlsZSAoIiIgOjo6ICJtZW1vcnkiKTsK KyAgICAgIGV4cGVjdGVkICs9IGFbMyAqIGkgKyAwXSAqIGJbMyAqIGkgKyAwXTsKKyAgICAgIGV4 cGVjdGVkICs9IGFbMyAqIGkgKyAxXSAqIGJbMyAqIGkgKyAxXTsKKyAgICAgIGV4cGVjdGVkICs9 IGFbMyAqIGkgKyAyXSAqIGJbMyAqIGkgKyAyXTsKKyAgICB9CisKKyAgaWYgKGYgKDB4MTIzNDUs IGEsIGIsIG4pICE9IGV4cGVjdGVkKQorICAgIF9fYnVpbHRpbl9hYm9ydCAoKTsKK30KKworLyog eyBkZy1maW5hbCB7IHNjYW4tdHJlZS1kdW1wICJ2ZWN0X3JlY29nX2RvdF9wcm9kX3BhdHRlcm46 IGRldGVjdGVkIiAidmVjdCIgfSB9ICovCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi10cmVlLWR1bXAg InZlY3Rvcml6aW5nIHN0bXRzIHVzaW5nIFNMUCIgInZlY3QiIH0gfSAqLworLyogeyBkZy1maW5h bCB7IHNjYW4tdHJlZS1kdW1wLXRpbWVzICJ2ZWN0b3JpemluZyBzdGF0ZW1lbnQ6IFxcUysgPSBE T1RfUFJPRF9FWFBSIiAzICJ2ZWN0IiAgeyB0YXJnZXQgdmVjdF9zZG90X2hpIH0gfSB9ICovCmRp ZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVkdWMtZG90LXNscC0x LmMgYi9nY2MvdGVzdHN1aXRlL2djYy5kZy92ZWN0L3ZlY3QtcmVkdWMtZG90LXNscC0xLmMKbmV3 IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLjg0YzgyYjAyM2Q0Ci0tLSAvZGV2 L251bGwKKysrIGIvZ2NjL3Rlc3RzdWl0ZS9nY2MuZGcvdmVjdC92ZWN0LXJlZHVjLWRvdC1zbHAt MS5jCkBAIC0wLDAgKzEsNjAgQEAKKy8qIERpc2FibGluZyBlcGlsb2d1ZXMgdW50aWwgd2UgZmlu ZCBhIGJldHRlciB3YXkgdG8gZGVhbCB3aXRoIHNjYW5zLiAgKi8KKy8qIHsgZGctZG8gY29tcGls ZSB9ICovCisvKiB7IGRnLWFkZGl0aW9uYWwtb3B0aW9ucyAiLS1wYXJhbSB2ZWN0LWVwaWxvZ3Vl cy1ub21hc2s9MCAtZmR1bXAtdHJlZS1vcHRpbWl6ZWQiIH0gKi8KKy8qIHsgZGctcmVxdWlyZS1l ZmZlY3RpdmUtdGFyZ2V0IHZlY3RfaW50IH0gKi8KKy8qIHsgZGctcmVxdWlyZS1lZmZlY3RpdmUt dGFyZ2V0IGFybV92OF8yYV9kb3Rwcm9kX25lb25faHcgeyB0YXJnZXQgeyBhYXJjaDY0Ki0qLSog fHwgYXJtKi0qLSogfSB9IH0gKi8KKy8qIHsgZGctYWRkLW9wdGlvbnMgYXJtX3Y4XzJhX2RvdHBy b2RfbmVvbiB9ICAqLworCisjaW5jbHVkZSAidHJlZS12ZWN0LmgiCisKKyNpZm5kZWYgU0lHTkVE TkVTU18xCisjZGVmaW5lIFNJR05FRE5FU1NfMSBzaWduZWQKKyNkZWZpbmUgU0lHTkVETkVTU18y IHNpZ25lZAorI2VuZGlmCisKK1NJR05FRE5FU1NfMSBpbnQgX19hdHRyaWJ1dGVfXyAoKG5vaXBh KSkKK2YgKFNJR05FRE5FU1NfMSBpbnQgcmVzMCwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzMSwK KyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzMiwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzMywKKyAg IFNJR05FRE5FU1NfMSBpbnQgcmVzNCwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzNSwKKyAgIFNJ R05FRE5FU1NfMSBpbnQgcmVzNiwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzNywKKyAgIFNJR05F RE5FU1NfMSBpbnQgcmVzOCwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzOSwKKyAgIFNJR05FRE5F U1NfMSBpbnQgcmVzQSwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzQiwKKyAgIFNJR05FRE5FU1Nf MSBpbnQgcmVzQywKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzRCwKKyAgIFNJR05FRE5FU1NfMSBp bnQgcmVzRSwKKyAgIFNJR05FRE5FU1NfMSBpbnQgcmVzRiwKKyAgIFNJR05FRE5FU1NfMiBjaGFy ICphLAorICAgU0lHTkVETkVTU18yIGNoYXIgKmIpCit7CisgIGZvciAoaW50IGkgPSAwOyBpIDwg NjQ7IGkgKz0gMTYpCisgICAgeworICAgICAgcmVzMCArPSBhW2kgKyAweDAwXSAqIGJbaSArIDB4 MDBdOworICAgICAgcmVzMSArPSBhW2kgKyAweDAxXSAqIGJbaSArIDB4MDFdOworICAgICAgcmVz MiArPSBhW2kgKyAweDAyXSAqIGJbaSArIDB4MDJdOworICAgICAgcmVzMyArPSBhW2kgKyAweDAz XSAqIGJbaSArIDB4MDNdOworICAgICAgcmVzNCArPSBhW2kgKyAweDA0XSAqIGJbaSArIDB4MDRd OworICAgICAgcmVzNSArPSBhW2kgKyAweDA1XSAqIGJbaSArIDB4MDVdOworICAgICAgcmVzNiAr PSBhW2kgKyAweDA2XSAqIGJbaSArIDB4MDZdOworICAgICAgcmVzNyArPSBhW2kgKyAweDA3XSAq IGJbaSArIDB4MDddOworICAgICAgcmVzOCArPSBhW2kgKyAweDA4XSAqIGJbaSArIDB4MDhdOwor ICAgICAgcmVzOSArPSBhW2kgKyAweDA5XSAqIGJbaSArIDB4MDldOworICAgICAgcmVzQSArPSBh W2kgKyAweDBBXSAqIGJbaSArIDB4MEFdOworICAgICAgcmVzQiArPSBhW2kgKyAweDBCXSAqIGJb aSArIDB4MEJdOworICAgICAgcmVzQyArPSBhW2kgKyAweDBDXSAqIGJbaSArIDB4MENdOworICAg ICAgcmVzRCArPSBhW2kgKyAweDBEXSAqIGJbaSArIDB4MERdOworICAgICAgcmVzRSArPSBhW2kg KyAweDBFXSAqIGJbaSArIDB4MEVdOworICAgICAgcmVzRiArPSBhW2kgKyAweDBGXSAqIGJbaSAr IDB4MEZdOworICAgIH0KKworICByZXR1cm4gcmVzMCBeIHJlczEgXiByZXMyIF4gcmVzMyBeIHJl czQgXiByZXM1IF4gcmVzNiBeIHJlczcgXgorICAgICAgICAgcmVzOCBeIHJlczkgXiByZXNBIF4g cmVzQiBeIHJlc0MgXiByZXNEIF4gcmVzRSBeIHJlc0Y7Cit9CisKKy8qIHsgZGctZmluYWwgeyBz Y2FuLXRyZWUtZHVtcCAidmVjdF9yZWNvZ19kb3RfcHJvZF9wYXR0ZXJuOiBkZXRlY3RlZCIgInZl Y3QiIH0gfSAqLworLyogeyBkZy1maW5hbCB7IHNjYW4tdHJlZS1kdW1wLW5vdCAiRE9UX1BST0Rf RVhQUiIgIm9wdGltaXplZCIgfSB9ICovCmRpZmYgLS1naXQgYS9nY2MvdHJlZS12ZWN0LWxvb3Au Y2MgYi9nY2MvdHJlZS12ZWN0LWxvb3AuY2MKaW5kZXggNDE5ZjRiMDhkMmIuLjZiZmIwZTcyOTA1 IDEwMDY0NAotLS0gYS9nY2MvdHJlZS12ZWN0LWxvb3AuY2MKKysrIGIvZ2NjL3RyZWUtdmVjdC1s b29wLmNjCkBAIC01MzI0LDggKzUzMjQsNiBAQCB2ZWN0X21vZGVsX3JlZHVjdGlvbl9jb3N0IChs b29wX3ZlY19pbmZvIGxvb3BfdmluZm8sCiAgIGlmICghZ2ltcGxlX2V4dHJhY3Rfb3AgKG9yaWdf c3RtdF9pbmZvLT5zdG10LCAmb3ApKQogICAgIGdjY191bnJlYWNoYWJsZSAoKTsKIAotICBib29s IGVtdWxhdGVkX21peGVkX2RvdF9wcm9kID0gdmVjdF9pc19lbXVsYXRlZF9taXhlZF9kb3RfcHJv ZCAoc3RtdF9pbmZvKTsKLQogICBpZiAocmVkdWN0aW9uX3R5cGUgPT0gRVhUUkFDVF9MQVNUX1JF RFVDVElPTikKICAgICAvKiBObyBleHRyYSBpbnN0cnVjdGlvbnMgYXJlIG5lZWRlZCBpbiB0aGUg cHJvbG9ndWUuICBUaGUgbG9vcCBib2R5CiAgICAgICAgb3BlcmF0aW9ucyBhcmUgY29zdGVkIGlu IHZlY3Rvcml6YWJsZV9jb25kaXRpb24uICAqLwpAQCAtNTM2MCwxMiArNTM1OCw4IEBAIHZlY3Rf bW9kZWxfcmVkdWN0aW9uX2Nvc3QgKGxvb3BfdmVjX2luZm8gbG9vcF92aW5mbywKIAkgICBpbml0 aWFsIHJlc3VsdCBvZiB0aGUgZGF0YSByZWR1Y3Rpb24sIGluaXRpYWwgdmFsdWUgb2YgdGhlIGlu ZGV4CiAJICAgcmVkdWN0aW9uLiAgKi8KIAlwcm9sb2d1ZV9zdG10cyA9IDQ7Ci0gICAgICBlbHNl IGlmIChlbXVsYXRlZF9taXhlZF9kb3RfcHJvZCkKLQkvKiBXZSBuZWVkIHRoZSBpbml0aWFsIHJl ZHVjdGlvbiB2YWx1ZSBhbmQgdHdvIGludmFyaWFudHM6Ci0JICAgb25lIHRoYXQgY29udGFpbnMg dGhlIG1pbmltdW0gc2lnbmVkIHZhbHVlIGFuZCBvbmUgdGhhdAotCSAgIGNvbnRhaW5zIGhhbGYg b2YgaXRzIG5lZ2F0aXZlLiAgKi8KLQlwcm9sb2d1ZV9zdG10cyA9IDM7CiAgICAgICBlbHNlCisJ LyogV2UgbmVlZCB0aGUgaW5pdGlhbCByZWR1Y3Rpb24gdmFsdWUuICAqLwogCXByb2xvZ3VlX3N0 bXRzID0gMTsKICAgICAgIHByb2xvZ3VlX2Nvc3QgKz0gcmVjb3JkX3N0bXRfY29zdCAoY29zdF92 ZWMsIHByb2xvZ3VlX3N0bXRzLAogCQkJCQkgc2NhbGFyX3RvX3ZlYywgc3RtdF9pbmZvLCAwLApA QCAtNzQ2Niw3ICs3NDYwLDEwIEBAIHZlY3RfcmVkdWN0aW9uX3VwZGF0ZV9wYXJ0aWFsX3ZlY3Rv cl91c2FnZSAobG9vcF92ZWNfaW5mbyBsb29wX3ZpbmZvLAogICAgICAgdmVjX2xvb3BfbGVucyAq bGVucyA9ICZMT09QX1ZJTkZPX0xFTlMgKGxvb3BfdmluZm8pOwogICAgICAgdW5zaWduZWQgbnZl Y3RvcnM7CiAKLSAgICAgIGlmIChzbHBfbm9kZSkKKyAgICAgIC8qIFRPRE86IFRoZSBudW1iZXIg b2YgdmVjdG9yIHN0YXRlbWVudHMgZm9yIGxhbmUtcmVkdWNpbmcgb3AgaXMgb3Zlci0KKwkgZXN0 aW1hdGVkLCB3ZSBoYXZlIHRvIHJlY29tcHV0ZSBpdCB3aGVuIHRoZSBjb250YWluaW5nIHNscCBu b2RlIGlzCisJIHNpbmdsZS1sYW5lLiAgTmVlZCBhIGdlbmVyYWwgbWVhbnMgdG8gY29ycmVjdCB0 aGlzIHZhbHVlLiAgKi8KKyAgICAgIGlmIChzbHBfbm9kZSAmJiBTTFBfVFJFRV9MQU5FUyAoc2xw X25vZGUpID4gMSkKIAludmVjdG9ycyA9IFNMUF9UUkVFX05VTUJFUl9PRl9WRUNfU1RNVFMgKHNs cF9ub2RlKTsKICAgICAgIGVsc2UKIAludmVjdG9ycyA9IHZlY3RfZ2V0X251bV9jb3BpZXMgKGxv b3BfdmluZm8sIHZlY3R5cGVfaW4pOwpAQCAtNzQ3OCw2ICs3NDc1LDE1NCBAQCB2ZWN0X3JlZHVj dGlvbl91cGRhdGVfcGFydGlhbF92ZWN0b3JfdXNhZ2UgKGxvb3BfdmVjX2luZm8gbG9vcF92aW5m bywKICAgICB9CiB9CiAKKy8qIENoZWNrIGlmIFNUTVRfSU5GTyBpcyBhIGxhbmUtcmVkdWNpbmcg b3BlcmF0aW9uIHRoYXQgY2FuIGJlIHZlY3Rvcml6ZWQgaW4KKyAgIHRoZSBjb250ZXh0IG9mIExP T1BfVklORk8sIGFuZCB2ZWN0b3IgY29zdCB3aWxsIGJlIHJlY29yZGVkIGluIENPU1RfVkVDLgor ICAgTm93IHRoZXJlIGFyZSB0aHJlZSBzdWNoIGtpbmRzIG9mIG9wZXJhdGlvbnM6IGRvdC1wcm9k L3dpZGVuLXN1bS9zYWQKKyAgIChzdW0tb2YtYWJzb2x1dGUtZGlmZmVyZW5jZXMpLgorCisgICBG b3IgYSBsYW5lLXJlZHVjaW5nIG9wZXJhdGlvbiwgdGhlIGxvb3AgcmVkdWN0aW9uIHBhdGggdGhh dCBpdCBsaWVzIGluLAorICAgbWF5IGNvbnRhaW4gbm9ybWFsIG9wZXJhdGlvbiwgb3Igb3RoZXIg bGFuZS1yZWR1Y2luZyBvcGVyYXRpb24gb2YgZGlmZmVyZW50CisgICBpbnB1dCB0eXBlIHNpemUs IGFuIGV4YW1wbGUgYXM6CisKKyAgICAgaW50IHN1bSA9IDA7CisgICAgIGZvciAoaSkKKyAgICAg ICB7CisgICAgICAgICAuLi4KKyAgICAgICAgIHN1bSArPSBkMFtpXSAqIGQxW2ldOyAgICAgICAv LyBkb3QtcHJvZCA8dmVjdG9yKDE2KSBjaGFyPgorICAgICAgICAgc3VtICs9IHdbaV07ICAgICAg ICAgICAgICAgIC8vIHdpZGVuLXN1bSA8dmVjdG9yKDE2KSBjaGFyPgorICAgICAgICAgc3VtICs9 IGFicyhzMFtpXSAtIHMxW2ldKTsgIC8vIHNhZCA8dmVjdG9yKDgpIHNob3J0PgorICAgICAgICAg c3VtICs9IG5baV07ICAgICAgICAgICAgICAgIC8vIG5vcm1hbCA8dmVjdG9yKDQpIGludD4KKyAg ICAgICAgIC4uLgorICAgICAgIH0KKworICAgVmVjdG9yaXphdGlvbiBmYWN0b3IgaXMgZXNzZW50 aWFsbHkgZGV0ZXJtaW5lZCBieSBvcGVyYXRpb24gd2hvc2UgaW5wdXQKKyAgIHZlY3R5cGUgaGFz IHRoZSBtb3N0IGxhbmVzICgidmVjdG9yKDE2KSBjaGFyIiBpbiB0aGUgZXhhbXBsZSksIHdoaWxl IHdlCisgICBuZWVkIHRvIGNob29zZSBpbnB1dCB2ZWN0eXBlIHdpdGggdGhlIGxlYXN0IGxhbmVz ICgidmVjdG9yKDQpIGludCIgaW4gdGhlCisgICBleGFtcGxlKSBmb3IgdGhlIHJlZHVjdGlvbiBQ SEkgc3RhdGVtZW50LiAgKi8KKworYm9vbAordmVjdG9yaXphYmxlX2xhbmVfcmVkdWNpbmcgKGxv b3BfdmVjX2luZm8gbG9vcF92aW5mbywgc3RtdF92ZWNfaW5mbyBzdG10X2luZm8sCisJCQkgICAg c2xwX3RyZWUgc2xwX25vZGUsIHN0bXRfdmVjdG9yX2Zvcl9jb3N0ICpjb3N0X3ZlYykKK3sKKyAg Z2ltcGxlICpzdG10ID0gc3RtdF9pbmZvLT5zdG10OworCisgIGlmICghbGFuZV9yZWR1Y2luZ19z dG10X3AgKHN0bXQpKQorICAgIHJldHVybiBmYWxzZTsKKworICB0cmVlIHR5cGUgPSBUUkVFX1RZ UEUgKGdpbXBsZV9hc3NpZ25fbGhzIChzdG10KSk7CisKKyAgaWYgKCFJTlRFR1JBTF9UWVBFX1Ag KHR5cGUpICYmICFTQ0FMQVJfRkxPQVRfVFlQRV9QICh0eXBlKSkKKyAgICByZXR1cm4gZmFsc2U7 CisKKyAgLyogRG8gbm90IHRyeSB0byB2ZWN0b3JpemUgYml0LXByZWNpc2lvbiByZWR1Y3Rpb25z LiAgKi8KKyAgaWYgKCF0eXBlX2hhc19tb2RlX3ByZWNpc2lvbl9wICh0eXBlKSkKKyAgICByZXR1 cm4gZmFsc2U7CisKKyAgLyogQSBsYW5lLXJlZHVjaW5nIG9wIHNob3VsZCBiZSBjb250YWluZWQg aW4gc29tZSBzbHAgbm9kZS4gICovCisgIGlmICghc2xwX25vZGUpCisgICAgcmV0dXJuIGZhbHNl OworCisgIGZvciAoaW50IGkgPSAwOyBpIDwgKGludCkgZ2ltcGxlX251bV9vcHMgKHN0bXQpIC0g MTsgaSsrKQorICAgIHsKKyAgICAgIHN0bXRfdmVjX2luZm8gZGVmX3N0bXRfaW5mbzsKKyAgICAg IHNscF90cmVlIHNscF9vcDsKKyAgICAgIHRyZWUgb3A7CisgICAgICB0cmVlIHZlY3R5cGU7Cisg ICAgICBlbnVtIHZlY3RfZGVmX3R5cGUgZHQ7CisKKyAgICAgIGlmICghdmVjdF9pc19zaW1wbGVf dXNlIChsb29wX3ZpbmZvLCBzdG10X2luZm8sIHNscF9ub2RlLCBpLCAmb3AsCisJCQkgICAgICAg JnNscF9vcCwgJmR0LCAmdmVjdHlwZSwgJmRlZl9zdG10X2luZm8pKQorCXsKKwkgIGlmIChkdW1w X2VuYWJsZWRfcCAoKSkKKwkgICAgZHVtcF9wcmludGZfbG9jIChNU0dfTUlTU0VEX09QVElNSVpB VElPTiwgdmVjdF9sb2NhdGlvbiwKKwkJCSAgICAgInVzZSBub3Qgc2ltcGxlLlxuIik7CisJICBy ZXR1cm4gZmFsc2U7CisJfQorCisgICAgICBpZiAoIXZlY3R5cGUpCisJeworCSAgdmVjdHlwZSA9 IGdldF92ZWN0eXBlX2Zvcl9zY2FsYXJfdHlwZSAobG9vcF92aW5mbywgVFJFRV9UWVBFIChvcCks CisJCQkJCQkgc2xwX29wKTsKKwkgIGlmICghdmVjdHlwZSkKKwkgICAgcmV0dXJuIGZhbHNlOwor CX0KKworICAgICAgaWYgKCF2ZWN0X21heWJlX3VwZGF0ZV9zbHBfb3BfdmVjdHlwZSAoc2xwX29w LCB2ZWN0eXBlKSkKKwl7CisJICBpZiAoZHVtcF9lbmFibGVkX3AgKCkpCisJICAgIGR1bXBfcHJp bnRmX2xvYyAoTVNHX01JU1NFRF9PUFRJTUlaQVRJT04sIHZlY3RfbG9jYXRpb24sCisJCQkgICAg ICJpbmNvbXBhdGlibGUgdmVjdG9yIHR5cGVzIGZvciBpbnZhcmlhbnRzXG4iKTsKKwkgIHJldHVy biBmYWxzZTsKKwl9CisKKyAgICAgIGlmIChpID09IFNUTVRfVklORk9fUkVEVUNfSURYIChzdG10 X2luZm8pKQorCWNvbnRpbnVlOworCisgICAgICAvKiBUaGVyZSBzaG91bGQgYmUgYXQgbW9zdCBv bmUgY3ljbGUgZGVmIGluIHRoZSBzdG10LiAgKi8KKyAgICAgIGlmIChWRUNUT1JJWkFCTEVfQ1lD TEVfREVGIChkdCkpCisJcmV0dXJuIGZhbHNlOworICAgIH0KKworICBzdG10X3ZlY19pbmZvIHJl ZHVjX2luZm8gPSBTVE1UX1ZJTkZPX1JFRFVDX0RFRiAodmVjdF9vcmlnX3N0bXQgKHN0bXRfaW5m bykpOworCisgIC8qIFRPRE86IFN1cHBvcnQgbGFuZS1yZWR1Y2luZyBvcGVyYXRpb24gdGhhdCBk b2VzIG5vdCBkaXJlY3RseSBwYXJ0aWNpcGF0ZQorICAgICBpbiBsb29wIHJlZHVjdGlvbi4gICov CisgIGlmICghcmVkdWNfaW5mbyB8fCBTVE1UX1ZJTkZPX1JFRFVDX0lEWCAoc3RtdF9pbmZvKSA8 IDApCisgICAgcmV0dXJuIGZhbHNlOworCisgIC8qIExhbmUtcmVkdWNpbmcgcGF0dGVybiBpbnNp ZGUgYW55IGlubmVyIGxvb3Agb2YgTE9PUF9WSU5GTyBpcyBub3QKKyAgICAgcmVjb2dpbml6ZWQu ICAqLworICBnY2NfYXNzZXJ0IChTVE1UX1ZJTkZPX0RFRl9UWVBFIChyZWR1Y19pbmZvKSA9PSB2 ZWN0X3JlZHVjdGlvbl9kZWYpOworICBnY2NfYXNzZXJ0IChTVE1UX1ZJTkZPX1JFRFVDX1RZUEUg KHJlZHVjX2luZm8pID09IFRSRUVfQ09ERV9SRURVQ1RJT04pOworCisgIHRyZWUgdmVjdHlwZV9p biA9IFNUTVRfVklORk9fUkVEVUNfVkVDVFlQRV9JTiAoc3RtdF9pbmZvKTsKKyAgaW50IG5jb3Bp ZXNfZm9yX2Nvc3Q7CisKKyAgaWYgKFNMUF9UUkVFX0xBTkVTIChzbHBfbm9kZSkgPiAxKQorICAg IHsKKyAgICAgIC8qIE5vdyBsYW5lLXJlZHVjaW5nIG9wZXJhdGlvbnMgaW4gYSBub24tc2luZ2xl LWxhbmUgc2xwIG5vZGUgc2hvdWxkIG9ubHkKKwkgY29tZSBmcm9tIHRoZSBzYW1lIGxvb3AgcmVk dWN0aW9uIHBhdGguICAqLworICAgICAgZ2NjX2Fzc2VydCAoUkVEVUNfR1JPVVBfRklSU1RfRUxF TUVOVCAoc3RtdF9pbmZvKSk7CisgICAgICBuY29waWVzX2Zvcl9jb3N0ID0gMTsKKyAgICB9Cisg IGVsc2UKKyAgICB7CisgICAgICBuY29waWVzX2Zvcl9jb3N0ID0gdmVjdF9nZXRfbnVtX2NvcGll cyAobG9vcF92aW5mbywgdmVjdHlwZV9pbik7CisgICAgICBnY2NfYXNzZXJ0IChuY29waWVzX2Zv cl9jb3N0ID49IDEpOworICAgIH0KKworICBpZiAodmVjdF9pc19lbXVsYXRlZF9taXhlZF9kb3Rf cHJvZCAoc3RtdF9pbmZvKSkKKyAgICB7CisgICAgICAvKiBXZSBuZWVkIGV4dHJhIHR3byBpbnZh cmlhbnRzOiBvbmUgdGhhdCBjb250YWlucyB0aGUgbWluaW11bSBzaWduZWQKKwkgdmFsdWUgYW5k IG9uZSB0aGF0IGNvbnRhaW5zIGhhbGYgb2YgaXRzIG5lZ2F0aXZlLiAgKi8KKyAgICAgIGludCBw cm9sb2d1ZV9zdG10cyA9IDI7CisgICAgICB1bnNpZ25lZCBjb3N0ID0gcmVjb3JkX3N0bXRfY29z dCAoY29zdF92ZWMsIHByb2xvZ3VlX3N0bXRzLAorCQkJCQlzY2FsYXJfdG9fdmVjLCBzdG10X2lu Zm8sIDAsCisJCQkJCXZlY3RfcHJvbG9ndWUpOworICAgICAgaWYgKGR1bXBfZW5hYmxlZF9wICgp KQorCWR1bXBfcHJpbnRmIChNU0dfTk9URSwgInZlY3Rvcml6YWJsZV9sYW5lX3JlZHVjaW5nOiAi CisJCSAgICAgImV4dHJhIHByb2xvZ3VlX2Nvc3QgPSAlZCAuXG4iLCBjb3N0KTsKKworICAgICAg LyogVGhyZWUgZG90LXByb2R1Y3RzIGFuZCBhIHN1YnRyYWN0aW9uLiAgKi8KKyAgICAgIG5jb3Bp ZXNfZm9yX2Nvc3QgKj0gNDsKKyAgICB9CisKKyAgcmVjb3JkX3N0bXRfY29zdCAoY29zdF92ZWMs IG5jb3BpZXNfZm9yX2Nvc3QsIHZlY3Rvcl9zdG10LCBzdG10X2luZm8sIDAsCisJCSAgICB2ZWN0 X2JvZHkpOworCisgIGlmIChMT09QX1ZJTkZPX0NBTl9VU0VfUEFSVElBTF9WRUNUT1JTX1AgKGxv b3BfdmluZm8pKQorICAgIHsKKyAgICAgIGVudW0gdHJlZV9jb2RlIGNvZGUgPSBnaW1wbGVfYXNz aWduX3Joc19jb2RlIChzdG10KTsKKyAgICAgIHZlY3RfcmVkdWN0aW9uX3VwZGF0ZV9wYXJ0aWFs X3ZlY3Rvcl91c2FnZSAobG9vcF92aW5mbywgcmVkdWNfaW5mbywKKwkJCQkJCSAgc2xwX25vZGUs IGNvZGUsIHR5cGUsCisJCQkJCQkgIHZlY3R5cGVfaW4pOworICAgIH0KKworICAvKiBUcmFuc2Zv cm0gdmlhIHZlY3RfdHJhbnNmb3JtX3JlZHVjdGlvbi4gICovCisgIFNUTVRfVklORk9fVFlQRSAo c3RtdF9pbmZvKSA9IHJlZHVjX3ZlY19pbmZvX3R5cGU7CisgIHJldHVybiB0cnVlOworfQorCiAv KiBGdW5jdGlvbiB2ZWN0b3JpemFibGVfcmVkdWN0aW9uLgogCiAgICBDaGVjayBpZiBTVE1UX0lO Rk8gcGVyZm9ybXMgYSByZWR1Y3Rpb24gb3BlcmF0aW9uIHRoYXQgY2FuIGJlIHZlY3Rvcml6ZWQu CkBAIC03ODExLDE4ICs3OTU2LDYgQEAgdmVjdG9yaXphYmxlX3JlZHVjdGlvbiAobG9vcF92ZWNf aW5mbyBsb29wX3ZpbmZvLAogICBpZiAoIXR5cGVfaGFzX21vZGVfcHJlY2lzaW9uX3AgKG9wLnR5 cGUpKQogICAgIHJldHVybiBmYWxzZTsKIAotICAvKiBGb3IgbGFuZS1yZWR1Y2luZyBvcHMgd2Un cmUgcmVkdWNpbmcgdGhlIG51bWJlciBvZiByZWR1Y3Rpb24gUEhJcwotICAgICB3aGljaCBtZWFu cyB0aGUgb25seSB1c2Ugb2YgdGhhdCBtYXkgYmUgaW4gdGhlIGxhbmUtcmVkdWNpbmcgb3BlcmF0 aW9uLiAgKi8KLSAgaWYgKGxhbmVfcmVkdWNpbmcKLSAgICAgICYmIHJlZHVjX2NoYWluX2xlbmd0 aCAhPSAxCi0gICAgICAmJiAhb25seV9zbHBfcmVkdWNfY2hhaW4pCi0gICAgewotICAgICAgaWYg KGR1bXBfZW5hYmxlZF9wICgpKQotCWR1bXBfcHJpbnRmX2xvYyAoTVNHX01JU1NFRF9PUFRJTUla QVRJT04sIHZlY3RfbG9jYXRpb24sCi0JCQkgImxhbmUtcmVkdWNpbmcgcmVkdWN0aW9uIHdpdGgg ZXh0cmEgc3RtdHMuXG4iKTsKLSAgICAgIHJldHVybiBmYWxzZTsKLSAgICB9Ci0KICAgLyogTGFu ZS1yZWR1Y2luZyBvcHMgYWxzbyBuZXZlciBjYW4gYmUgdXNlZCBpbiBhIFNMUCByZWR1Y3Rpb24g Z3JvdXAKICAgICAgc2luY2Ugd2UnbGwgbWl4IGxhbmVzIGJlbG9uZ2luZyB0byBkaWZmZXJlbnQg cmVkdWN0aW9ucy4gIEJ1dCBpdCdzCiAgICAgIE9LIHRvIHVzZSB0aGVtIGluIGEgcmVkdWN0aW9u IGNoYWluIG9yIHdoZW4gdGhlIHJlZHVjdGlvbiBncm91cApAQCAtODM2MiwxNCArODQ5NSwxMSBA QCB2ZWN0b3JpemFibGVfcmVkdWN0aW9uIChsb29wX3ZlY19pbmZvIGxvb3BfdmluZm8sCiAgICAg ICAmJiBsb29wX3ZpbmZvLT5zdWdnZXN0ZWRfdW5yb2xsX2ZhY3RvciA9PSAxKQogICAgIHNpbmds ZV9kZWZ1c2VfY3ljbGUgPSB0cnVlOwogCi0gIGlmIChzaW5nbGVfZGVmdXNlX2N5Y2xlIHx8IGxh bmVfcmVkdWNpbmcpCisgIGlmIChzaW5nbGVfZGVmdXNlX2N5Y2xlICYmICFsYW5lX3JlZHVjaW5n KQogICAgIHsKICAgICAgIGdjY19hc3NlcnQgKG9wLmNvZGUgIT0gQ09ORF9FWFBSKTsKIAotICAg ICAgLyogNC4gU3VwcG9ydGFibGUgYnkgdGFyZ2V0PyAgKi8KLSAgICAgIGJvb2wgb2sgPSB0cnVl OwotCi0gICAgICAvKiA0LjEuIGNoZWNrIHN1cHBvcnQgZm9yIHRoZSBvcGVyYXRpb24gaW4gdGhl IGxvb3AKKyAgICAgIC8qIDQuIGNoZWNrIHN1cHBvcnQgZm9yIHRoZSBvcGVyYXRpb24gaW4gdGhl IGxvb3AKIAogCSBUaGlzIGlzbid0IG5lY2Vzc2FyeSBmb3IgdGhlIGxhbmUgcmVkdWN0aW9uIGNv ZGVzLCBzaW5jZSB0aGV5CiAJIGNhbiBvbmx5IGJlIHByb2R1Y2VkIGJ5IHBhdHRlcm4gbWF0Y2hp bmcsIGFuZCBpdCdzIHVwIHRvIHRoZQpAQCAtODM3OCwxNCArODUwOCwxMyBAQCB2ZWN0b3JpemFi bGVfcmVkdWN0aW9uIChsb29wX3ZlY19pbmZvIGxvb3BfdmluZm8sCiAJIG1peGVkLXNpZ24gZG90 LXByb2R1Y3RzIGNhbiBiZSBpbXBsZW1lbnRlZCB1c2luZyBzaWduZWQKIAkgZG90LXByb2R1Y3Rz LiAgKi8KICAgICAgIG1hY2hpbmVfbW9kZSB2ZWNfbW9kZSA9IFRZUEVfTU9ERSAodmVjdHlwZV9p bik7Ci0gICAgICBpZiAoIWxhbmVfcmVkdWNpbmcKLQkgICYmICFkaXJlY3RseV9zdXBwb3J0ZWRf cCAob3AuY29kZSwgdmVjdHlwZV9pbiwgb3B0YWJfdmVjdG9yKSkKKyAgICAgIGlmICghZGlyZWN0 bHlfc3VwcG9ydGVkX3AgKG9wLmNvZGUsIHZlY3R5cGVfaW4sIG9wdGFiX3ZlY3RvcikpCiAgICAg ICAgIHsKICAgICAgICAgICBpZiAoZHVtcF9lbmFibGVkX3AgKCkpCiAgICAgICAgICAgICBkdW1w X3ByaW50ZiAoTVNHX05PVEUsICJvcCBub3Qgc3VwcG9ydGVkIGJ5IHRhcmdldC5cbiIpOwogCSAg aWYgKG1heWJlX25lIChHRVRfTU9ERV9TSVpFICh2ZWNfbW9kZSksIFVOSVRTX1BFUl9XT1JEKQog CSAgICAgIHx8ICF2ZWN0X2Nhbl92ZWN0b3JpemVfd2l0aG91dF9zaW1kX3AgKG9wLmNvZGUpKQot CSAgICBvayA9IGZhbHNlOworCSAgICBzaW5nbGVfZGVmdXNlX2N5Y2xlID0gZmFsc2U7CiAJICBl bHNlCiAJICAgIGlmIChkdW1wX2VuYWJsZWRfcCAoKSkKIAkgICAgICBkdW1wX3ByaW50ZiAoTVNH X05PVEUsICJwcm9jZWVkaW5nIHVzaW5nIHdvcmQgbW9kZS5cbiIpOwpAQCAtODM5OCwxNiArODUy Nyw2IEBAIHZlY3Rvcml6YWJsZV9yZWR1Y3Rpb24gKGxvb3BfdmVjX2luZm8gbG9vcF92aW5mbywK IAkgICAgZHVtcF9wcmludGYgKE1TR19OT1RFLCAidXNpbmcgd29yZCBtb2RlIG5vdCBwb3NzaWJs ZS5cbiIpOwogCSAgcmV0dXJuIGZhbHNlOwogCX0KLQotICAgICAgLyogbGFuZS1yZWR1Y2luZyBv cGVyYXRpb25zIGhhdmUgdG8gZ28gdGhyb3VnaCB2ZWN0X3RyYW5zZm9ybV9yZWR1Y3Rpb24uCi0g ICAgICAgICBGb3IgdGhlIG90aGVyIGNhc2VzIHRyeSB3aXRob3V0IHRoZSBzaW5nbGUgY3ljbGUg b3B0aW1pemF0aW9uLiAgKi8KLSAgICAgIGlmICghb2spCi0JewotCSAgaWYgKGxhbmVfcmVkdWNp bmcpCi0JICAgIHJldHVybiBmYWxzZTsKLQkgIGVsc2UKLQkgICAgc2luZ2xlX2RlZnVzZV9jeWNs ZSA9IGZhbHNlOwotCX0KICAgICB9CiAgIGlmIChkdW1wX2VuYWJsZWRfcCAoKSAmJiBzaW5nbGVf ZGVmdXNlX2N5Y2xlKQogICAgIGR1bXBfcHJpbnRmX2xvYyAoTVNHX05PVEUsIHZlY3RfbG9jYXRp b24sCkBAIC04NDE1LDIyICs4NTM0LDE0IEBAIHZlY3Rvcml6YWJsZV9yZWR1Y3Rpb24gKGxvb3Bf dmVjX2luZm8gbG9vcF92aW5mbywKIAkJICAgICAibXVsdGlwbGUgdmVjdG9ycyB0byBvbmUgaW4g dGhlIGxvb3AgYm9keVxuIik7CiAgIFNUTVRfVklORk9fRk9SQ0VfU0lOR0xFX0NZQ0xFIChyZWR1 Y19pbmZvKSA9IHNpbmdsZV9kZWZ1c2VfY3ljbGU7CiAKLSAgLyogSWYgdGhlIHJlZHVjdGlvbiBz dG10IGlzIG9uZSBvZiB0aGUgcGF0dGVybnMgdGhhdCBoYXZlIGxhbmUKLSAgICAgcmVkdWN0aW9u IGVtYmVkZGVkIHdlIGNhbm5vdCBoYW5kbGUgdGhlIGNhc2Ugb2YgISBzaW5nbGVfZGVmdXNlX2N5 Y2xlLiAgKi8KLSAgaWYgKChuY29waWVzID4gMSAmJiAhIHNpbmdsZV9kZWZ1c2VfY3ljbGUpCi0g ICAgICAmJiBsYW5lX3JlZHVjaW5nKQotICAgIHsKLSAgICAgIGlmIChkdW1wX2VuYWJsZWRfcCAo KSkKLQlkdW1wX3ByaW50Zl9sb2MgKE1TR19NSVNTRURfT1BUSU1JWkFUSU9OLCB2ZWN0X2xvY2F0 aW9uLAotCQkJICJtdWx0aSBkZWYtdXNlIGN5Y2xlIG5vdCBwb3NzaWJsZSBmb3IgbGFuZS1yZWR1 Y2luZyAiCi0JCQkgInJlZHVjdGlvbiBvcGVyYXRpb25cbiIpOwotICAgICAgcmV0dXJuIGZhbHNl OwotICAgIH0KKyAgLyogRm9yIGxhbmUtcmVkdWNpbmcgb3BlcmF0aW9uLCB0aGUgYmVsb3cgcHJv Y2Vzc2luZyByZWxhdGVkIHRvIHNpbmdsZQorICAgICBkZWZ1c2UtY3ljbGUgd2lsbCBiZSBkb25l IGluIGl0cyBvd24gdmVjdG9yaXphYmxlIGZ1bmN0aW9uLiAgT25lIG1vcmUKKyAgICAgdGhpbmcg dG8gbm90ZSBpcyB0aGF0IHRoZSBvcGVyYXRpb24gbXVzdCBub3QgYmUgaW52b2x2ZWQgaW4gZm9s ZC1sZWZ0CisgICAgIHJlZHVjdGlvbi4gICovCisgIHNpbmdsZV9kZWZ1c2VfY3ljbGUgJj0gIWxh bmVfcmVkdWNpbmc7CiAKICAgaWYgKHNscF9ub2RlCi0gICAgICAmJiAhKCFzaW5nbGVfZGVmdXNl X2N5Y2xlCi0JICAgJiYgIWxhbmVfcmVkdWNpbmcKLQkgICAmJiByZWR1Y3Rpb25fdHlwZSAhPSBG T0xEX0xFRlRfUkVEVUNUSU9OKSkKKyAgICAgICYmIChzaW5nbGVfZGVmdXNlX2N5Y2xlIHx8IHJl ZHVjdGlvbl90eXBlID09IEZPTERfTEVGVF9SRURVQ1RJT04pKQogICAgIGZvciAoaSA9IDA7IGkg PCAoaW50KSBvcC5udW1fb3BzOyBpKyspCiAgICAgICBpZiAoIXZlY3RfbWF5YmVfdXBkYXRlX3Ns cF9vcF92ZWN0eXBlIChzbHBfb3BbaV0sIHZlY3R5cGVfb3BbaV0pKQogCXsKQEAgLTg0NDMsMjgg Kzg1NTQsMjAgQEAgdmVjdG9yaXphYmxlX3JlZHVjdGlvbiAobG9vcF92ZWNfaW5mbyBsb29wX3Zp bmZvLAogICB2ZWN0X21vZGVsX3JlZHVjdGlvbl9jb3N0IChsb29wX3ZpbmZvLCBzdG10X2luZm8s IHJlZHVjX2ZuLAogCQkJICAgICByZWR1Y3Rpb25fdHlwZSwgbmNvcGllcywgY29zdF92ZWMpOwog ICAvKiBDb3N0IHRoZSByZWR1Y3Rpb24gb3AgaW5zaWRlIHRoZSBsb29wIGlmIHRyYW5zZm9ybWVk IHZpYQotICAgICB2ZWN0X3RyYW5zZm9ybV9yZWR1Y3Rpb24uICBPdGhlcndpc2UgdGhpcyBpcyBj b3N0ZWQgYnkgdGhlCi0gICAgIHNlcGFyYXRlIHZlY3Rvcml6YWJsZV8qIHJvdXRpbmVzLiAgKi8K LSAgaWYgKHNpbmdsZV9kZWZ1c2VfY3ljbGUgfHwgbGFuZV9yZWR1Y2luZykKLSAgICB7Ci0gICAg ICBpbnQgZmFjdG9yID0gMTsKLSAgICAgIGlmICh2ZWN0X2lzX2VtdWxhdGVkX21peGVkX2RvdF9w cm9kIChzdG10X2luZm8pKQotCS8qIFRocmVlIGRvdC1wcm9kdWN0cyBhbmQgYSBzdWJ0cmFjdGlv bi4gICovCi0JZmFjdG9yID0gNDsKLSAgICAgIHJlY29yZF9zdG10X2Nvc3QgKGNvc3RfdmVjLCBu Y29waWVzICogZmFjdG9yLCB2ZWN0b3Jfc3RtdCwKLQkJCXN0bXRfaW5mbywgMCwgdmVjdF9ib2R5 KTsKLSAgICB9CisgICAgIHZlY3RfdHJhbnNmb3JtX3JlZHVjdGlvbiBmb3Igbm9uLWxhbmUtcmVk dWNpbmcgb3BlcmF0aW9uLiAgT3RoZXJ3aXNlCisgICAgIHRoaXMgaXMgY29zdGVkIGJ5IHRoZSBz ZXBhcmF0ZSB2ZWN0b3JpemFibGVfKiByb3V0aW5lcy4gICovCisgIGlmIChzaW5nbGVfZGVmdXNl X2N5Y2xlKQorICAgIHJlY29yZF9zdG10X2Nvc3QgKGNvc3RfdmVjLCBuY29waWVzLCB2ZWN0b3Jf c3RtdCwgc3RtdF9pbmZvLCAwLCB2ZWN0X2JvZHkpOwogCiAgIGlmIChkdW1wX2VuYWJsZWRfcCAo KQogICAgICAgJiYgcmVkdWN0aW9uX3R5cGUgPT0gRk9MRF9MRUZUX1JFRFVDVElPTikKICAgICBk dW1wX3ByaW50Zl9sb2MgKE1TR19OT1RFLCB2ZWN0X2xvY2F0aW9uLAogCQkgICAgICJ1c2luZyBh biBpbi1vcmRlciAoZm9sZC1sZWZ0KSByZWR1Y3Rpb24uXG4iKTsKICAgU1RNVF9WSU5GT19UWVBF IChvcmlnX3N0bXRfb2ZfYW5hbHlzaXMpID0gY3ljbGVfcGhpX2luZm9fdHlwZTsKLSAgLyogQWxs IGJ1dCBzaW5nbGUgZGVmdXNlLWN5Y2xlIG9wdGltaXplZCwgbGFuZS1yZWR1Y2luZyBhbmQgZm9s ZC1sZWZ0Ci0gICAgIHJlZHVjdGlvbnMgZ28gdGhyb3VnaCB0aGVpciBvd24gdmVjdG9yaXphYmxl Xyogcm91dGluZXMuICAqLwotICBpZiAoIXNpbmdsZV9kZWZ1c2VfY3ljbGUKLSAgICAgICYmICFs YW5lX3JlZHVjaW5nCi0gICAgICAmJiByZWR1Y3Rpb25fdHlwZSAhPSBGT0xEX0xFRlRfUkVEVUNU SU9OKQorCisgIC8qIEFsbCBidXQgc2luZ2xlIGRlZnVzZS1jeWNsZSBvcHRpbWl6ZWQgYW5kIGZv bGQtbGVmdCByZWR1Y3Rpb25zIGdvCisgICAgIHRocm91Z2ggdGhlaXIgb3duIHZlY3Rvcml6YWJs ZV8qIHJvdXRpbmVzLiAgKi8KKyAgaWYgKCFzaW5nbGVfZGVmdXNlX2N5Y2xlICYmIHJlZHVjdGlv bl90eXBlICE9IEZPTERfTEVGVF9SRURVQ1RJT04pCiAgICAgewogICAgICAgc3RtdF92ZWNfaW5m byB0ZW0KIAk9IHZlY3Rfc3RtdF90b192ZWN0b3JpemUgKFNUTVRfVklORk9fUkVEVUNfREVGIChw aGlfaW5mbykpOwpAQCAtODY1NCw2ICs4NzU3LDE1IEBAIHZlY3RfdHJhbnNmb3JtX3JlZHVjdGlv biAobG9vcF92ZWNfaW5mbyBsb29wX3ZpbmZvLAogICBib29sIGxhbmVfcmVkdWNpbmcgPSBsYW5l X3JlZHVjaW5nX29wX3AgKGNvZGUpOwogICBnY2NfYXNzZXJ0IChzaW5nbGVfZGVmdXNlX2N5Y2xl IHx8IGxhbmVfcmVkdWNpbmcpOwogCisgIGlmIChsYW5lX3JlZHVjaW5nKQorICAgIHsKKyAgICAg IC8qIFRoZSBsYXN0IG9wZXJhbmQgb2YgbGFuZS1yZWR1Y2luZyBvcCBpcyBmb3IgcmVkdWN0aW9u LiAgKi8KKyAgICAgIGdjY19hc3NlcnQgKHJlZHVjX2luZGV4ID09IChpbnQpIG9wLm51bV9vcHMg LSAxKTsKKworICAgICAgLyogTm93IGxhbmUtcmVkdWNpbmcgb3AgaXMgY29udGFpbmVkIGluIHNv bWUgc2xwIG5vZGUuICAqLworICAgICAgZ2NjX2Fzc2VydCAoc2xwX25vZGUpOworICAgfQorCiAg IC8qIENyZWF0ZSB0aGUgZGVzdGluYXRpb24gdmVjdG9yICAqLwogICB0cmVlIHNjYWxhcl9kZXN0 ID0gZ2ltcGxlX2dldF9saHMgKHN0bXRfaW5mby0+c3RtdCk7CiAgIHRyZWUgdmVjX2Rlc3QgPSB2 ZWN0X2NyZWF0ZV9kZXN0aW5hdGlvbl92YXIgKHNjYWxhcl9kZXN0LCB2ZWN0eXBlX291dCk7CkBA IC04Njk4LDYgKzg4MTAsNjIgQEAgdmVjdF90cmFuc2Zvcm1fcmVkdWN0aW9uIChsb29wX3ZlY19p bmZvIGxvb3BfdmluZm8sCiAJCQkgcmVkdWNfaW5kZXggPT0gMiA/IG9wLm9wc1syXSA6IE5VTExf VFJFRSwKIAkJCSAmdmVjX29wcm5kc1syXSk7CiAgICAgfQorICBlbHNlIGlmIChsYW5lX3JlZHVj aW5nICYmIFNMUF9UUkVFX0xBTkVTIChzbHBfbm9kZSkgPT0gMSkKKyAgICB7CisgICAgICAvKiBG b3IgbGFuZS1yZWR1Y2luZyBvcCBjb3ZlcmVkIGJ5IHNpbmdsZS1sYW5lIHNscCBub2RlLCB0aGUg aW5wdXQKKwkgdmVjdHlwZSBvZiB0aGUgcmVkdWN0aW9uIFBISSBkZXRlcm1pbmVzIGNvcGllcyBv ZiB2ZWN0b3JpemVkIGRlZi11c2UKKwkgY3ljbGVzLCB3aGljaCBtaWdodCBiZSBtb3JlIHRoYW4g ZWZmZWN0aXZlIGNvcGllcyBvZiB2ZWN0b3JpemVkIGxhbmUtCisJIHJlZHVjaW5nIHJlZHVjdGlv biBzdGF0ZW1lbnRzLiAgVGhpcyBjb3VsZCBiZSBjb21wbGVtZW50ZWQgYnkKKwkgZ2VuZXJhdGlu ZyBleHRyYSB0cml2aWFsIHBhc3MtdGhyb3VnaCBjb3BpZXMuICBGb3IgZXhhbXBsZToKKworCSAg IGludCBzdW0gPSAwOworCSAgIGZvciAoaSkKKwkgICAgIHsKKwkgICAgICAgc3VtICs9IGQwW2ld ICogZDFbaV07ICAgICAgLy8gZG90LXByb2QgPHZlY3RvcigxNikgY2hhcj4KKwkgICAgICAgc3Vt ICs9IGFicyhzMFtpXSAtIHMxW2ldKTsgLy8gc2FkIDx2ZWN0b3IoOCkgc2hvcnQ+CisJICAgICAg IHN1bSArPSBuW2ldOyAgICAgICAgICAgICAgIC8vIG5vcm1hbCA8dmVjdG9yKDQpIGludD4KKwkg ICAgIH0KKworCSBUaGUgdmVjdG9yIHNpemUgaXMgMTI4LWJpdO+8jHZlY3Rvcml6YXRpb24gZmFj dG9yIGlzIDE2LiAgUmVkdWN0aW9uCisJIHN0YXRlbWVudHMgd291bGQgYmUgdHJhbnNmb3JtZWQg YXM6CisKKwkgICB2ZWN0b3I8ND4gaW50IHN1bV92MCA9IHsgMCwgMCwgMCwgMCB9OworCSAgIHZl Y3Rvcjw0PiBpbnQgc3VtX3YxID0geyAwLCAwLCAwLCAwIH07CisJICAgdmVjdG9yPDQ+IGludCBz dW1fdjIgPSB7IDAsIDAsIDAsIDAgfTsKKwkgICB2ZWN0b3I8ND4gaW50IHN1bV92MyA9IHsgMCwg MCwgMCwgMCB9OworCisJICAgZm9yIChpIC8gMTYpCisJICAgICB7CisJICAgICAgIHN1bV92MCA9 IERPVF9QUk9EIChkMF92MFtpOiAwIH4gMTVdLCBkMV92MFtpOiAwIH4gMTVdLCBzdW1fdjApOwor CSAgICAgICBzdW1fdjEgPSBzdW1fdjE7ICAvLyBjb3B5CisJICAgICAgIHN1bV92MiA9IHN1bV92 MjsgIC8vIGNvcHkKKwkgICAgICAgc3VtX3YzID0gc3VtX3YzOyAgLy8gY29weQorCisJICAgICAg IHN1bV92MCA9IFNBRCAoczBfdjBbaTogMCB+IDcgXSwgczFfdjBbaTogMCB+IDcgXSwgc3VtX3Yw KTsKKwkgICAgICAgc3VtX3YxID0gU0FEIChzMF92MVtpOiA4IH4gMTVdLCBzMV92MVtpOiA4IH4g MTVdLCBzdW1fdjEpOworCSAgICAgICBzdW1fdjIgPSBzdW1fdjI7ICAvLyBjb3B5CisJICAgICAg IHN1bV92MyA9IHN1bV92MzsgIC8vIGNvcHkKKworCSAgICAgICBzdW1fdjAgKz0gbl92MFtpOiAw ICB+IDMgXTsKKwkgICAgICAgc3VtX3YxICs9IG5fdjFbaTogNCAgfiA3IF07CisJICAgICAgIHN1 bV92MiArPSBuX3YyW2k6IDggIH4gMTFdOworCSAgICAgICBzdW1fdjMgKz0gbl92M1tpOiAxMiB+ IDE1XTsKKwkgICAgIH0KKwkqLworICAgICAgdW5zaWduZWQgdXNpbmdfbmNvcGllcyA9IHZlY19v cHJuZHNbMF0ubGVuZ3RoICgpOworICAgICAgdW5zaWduZWQgcmVkdWNfbmNvcGllcyA9IHZlY19v cHJuZHNbcmVkdWNfaW5kZXhdLmxlbmd0aCAoKTsKKworICAgICAgZ2NjX2Fzc2VydCAodXNpbmdf bmNvcGllcyA8PSByZWR1Y19uY29waWVzKTsKKworICAgICAgaWYgKHVzaW5nX25jb3BpZXMgPCBy ZWR1Y19uY29waWVzKQorCXsKKwkgIGZvciAodW5zaWduZWQgaSA9IDA7IGkgPCBvcC5udW1fb3Bz IC0gMTsgaSsrKQorCSAgICB7CisJICAgICAgZ2NjX2Fzc2VydCAodmVjX29wcm5kc1tpXS5sZW5n dGggKCkgPT0gdXNpbmdfbmNvcGllcyk7CisJICAgICAgdmVjX29wcm5kc1tpXS5zYWZlX2dyb3df Y2xlYXJlZCAocmVkdWNfbmNvcGllcyk7CisJICAgIH0KKwl9CisgICAgfQogCiAgIGJvb2wgZW11 bGF0ZWRfbWl4ZWRfZG90X3Byb2QgPSB2ZWN0X2lzX2VtdWxhdGVkX21peGVkX2RvdF9wcm9kIChz dG10X2luZm8pOwogICB1bnNpZ25lZCBudW0gPSB2ZWNfb3BybmRzW3JlZHVjX2luZGV4ID09IDAg PyAxIDogMF0ubGVuZ3RoICgpOwpAQCAtODcwNiw3ICs4ODc0LDE4IEBAIHZlY3RfdHJhbnNmb3Jt X3JlZHVjdGlvbiAobG9vcF92ZWNfaW5mbyBsb29wX3ZpbmZvLAogICAgIHsKICAgICAgIGdpbXBs ZSAqbmV3X3N0bXQ7CiAgICAgICB0cmVlIHZvcFszXSA9IHsgdmVjX29wcm5kc1swXVtpXSwgdmVj X29wcm5kc1sxXVtpXSwgTlVMTF9UUkVFIH07Ci0gICAgICBpZiAobWFza2VkX2xvb3BfcCAmJiAh bWFza19ieV9jb25kX2V4cHIpCisKKyAgICAgIGlmICghdm9wWzBdIHx8ICF2b3BbMV0pCisJewor CSAgdHJlZSByZWR1Y192b3AgPSB2ZWNfb3BybmRzW3JlZHVjX2luZGV4XVtpXTsKKworCSAgLyog SW5zZXJ0IHRyaXZpYWwgY29weSBpZiBubyBuZWVkIHRvIGdlbmVyYXRlIHZlY3Rvcml6ZWQKKwkg ICAgIHN0YXRlbWVudC4gICovCisJICBnY2NfYXNzZXJ0IChyZWR1Y192b3ApOworCisJICBuZXdf c3RtdCA9IFNTQV9OQU1FX0RFRl9TVE1UIChyZWR1Y192b3ApOworCX0KKyAgICAgIGVsc2UgaWYg KG1hc2tlZF9sb29wX3AgJiYgIW1hc2tfYnlfY29uZF9leHByKQogCXsKIAkgIC8qIE5vIGNvbmRp dGlvbmFsIGlmbnMgaGF2ZSBiZWVuIGRlZmluZWQgZm9yIGxhbmUtcmVkdWNpbmcgb3AKIAkgICAg IHlldC4gICovCkBAIC04NzM1LDggKzg5MTQsMjIgQEAgdmVjdF90cmFuc2Zvcm1fcmVkdWN0aW9u IChsb29wX3ZlY19pbmZvIGxvb3BfdmluZm8sCiAKIAkgIGlmIChtYXNrZWRfbG9vcF9wICYmIG1h c2tfYnlfY29uZF9leHByKQogCSAgICB7CisJICAgICAgdW5zaWduZWQgbnZlY3RvcnMgPSB2ZWNf bnVtICogbmNvcGllczsKKwkgICAgICB0cmVlIHN0bXRfdmVjdHlwZV9pbiA9IHZlY3R5cGVfaW47 CisKKwkgICAgICAvKiBGb3Igc2luZ2xlLWxhbmUgc2xwIG5vZGUgb24gbGFuZS1yZWR1Y2luZyBv cCwgd2UgbmVlZCB0bworCQkgY29tcHV0ZSBleGFjdCBudW1iZXIgb2YgdmVjdG9yIHN0bXRzIGZy b20gaXRzIGlucHV0IHZlY3R5cGUsCisJCSBzaW5jZSB0aGUgdmFsdWUgZ290IGZyb20gdGhlIHNs cCBub2RlIGlzIG92ZXItZXN0aW1hdGVkLgorCQkgVE9ETzogcHJvcGVybHkgc2V0IHRoZSBudW1i ZXIgdGhpcyBzb21ld2hlcmUsIHNvIHRoYXQgdGhpcworCQkgZml4dXAgY291bGQgYmUgcmVtb3Zl ZC4gICovCisJICAgICAgaWYgKGxhbmVfcmVkdWNpbmcgJiYgU0xQX1RSRUVfTEFORVMgKHNscF9u b2RlKSA9PSAxKQorCQl7CisJCSAgc3RtdF92ZWN0eXBlX2luID0gU1RNVF9WSU5GT19SRURVQ19W RUNUWVBFX0lOIChzdG10X2luZm8pOworCQkgIG52ZWN0b3JzID0gdmVjdF9nZXRfbnVtX2NvcGll cyAobG9vcF92aW5mbywgdmVjdHlwZV9pbik7CisJCX0KKwogCSAgICAgIHRyZWUgbWFzayA9IHZl Y3RfZ2V0X2xvb3BfbWFzayAobG9vcF92aW5mbywgZ3NpLCBtYXNrcywKLQkJCQkJICAgICAgdmVj X251bSAqIG5jb3BpZXMsIHZlY3R5cGVfaW4sIGkpOworCQkJCQkgICAgICBudmVjdG9ycywgc3Rt dF92ZWN0eXBlX2luLCBpKTsKIAkgICAgICBidWlsZF92ZWN0X2NvbmRfZXhwciAoY29kZSwgdm9w LCBtYXNrLCBnc2kpOwogCSAgICB9CiAKZGlmZiAtLWdpdCBhL2djYy90cmVlLXZlY3Qtc3RtdHMu Y2MgYi9nY2MvdHJlZS12ZWN0LXN0bXRzLmNjCmluZGV4IDg0MGUxNjJjN2YwLi44NDU2NDdiNDM5 OSAxMDA2NDQKLS0tIGEvZ2NjL3RyZWUtdmVjdC1zdG10cy5jYworKysgYi9nY2MvdHJlZS12ZWN0 LXN0bXRzLmNjCkBAIC0xMzM1MCw2ICsxMzM1MCw4IEBAIHZlY3RfYW5hbHl6ZV9zdG10ICh2ZWNf aW5mbyAqdmluZm8sCiAJCQkJICAgICAgTlVMTCwgTlVMTCwgbm9kZSwgY29zdF92ZWMpCiAJICB8 fCB2ZWN0b3JpemFibGVfbG9hZCAodmluZm8sIHN0bXRfaW5mbywgTlVMTCwgTlVMTCwgbm9kZSwg Y29zdF92ZWMpCiAJICB8fCB2ZWN0b3JpemFibGVfc3RvcmUgKHZpbmZvLCBzdG10X2luZm8sIE5V TEwsIE5VTEwsIG5vZGUsIGNvc3RfdmVjKQorCSAgfHwgdmVjdG9yaXphYmxlX2xhbmVfcmVkdWNp bmcgKGFzX2EgPGxvb3BfdmVjX2luZm8+ICh2aW5mbyksCisJCQkJCSBzdG10X2luZm8sIG5vZGUs IGNvc3RfdmVjKQogCSAgfHwgdmVjdG9yaXphYmxlX3JlZHVjdGlvbiAoYXNfYSA8bG9vcF92ZWNf aW5mbz4gKHZpbmZvKSwgc3RtdF9pbmZvLAogCQkJCSAgICAgbm9kZSwgbm9kZV9pbnN0YW5jZSwg Y29zdF92ZWMpCiAJICB8fCB2ZWN0b3JpemFibGVfaW5kdWN0aW9uIChhc19hIDxsb29wX3ZlY19p bmZvPiAodmluZm8pLCBzdG10X2luZm8sCmRpZmYgLS1naXQgYS9nY2MvdHJlZS12ZWN0b3JpemVy LmggYi9nY2MvdHJlZS12ZWN0b3JpemVyLmgKaW5kZXggNjAyMjRmNGUyODQuLjk0NzM2NzM2ZGNj IDEwMDY0NAotLS0gYS9nY2MvdHJlZS12ZWN0b3JpemVyLmgKKysrIGIvZ2NjL3RyZWUtdmVjdG9y aXplci5oCkBAIC0yNDU1LDYgKzI0NTUsOCBAQCBleHRlcm4gbG9vcF92ZWNfaW5mbyB2ZWN0X2Ny ZWF0ZV9sb29wX3ZpbmZvIChjbGFzcyBsb29wICosIHZlY19pbmZvX3NoYXJlZCAqLAogZXh0ZXJu IGJvb2wgdmVjdG9yaXphYmxlX2xpdmVfb3BlcmF0aW9uICh2ZWNfaW5mbyAqLCBzdG10X3ZlY19p bmZvLAogCQkJCQkgc2xwX3RyZWUsIHNscF9pbnN0YW5jZSwgaW50LAogCQkJCQkgYm9vbCwgc3Rt dF92ZWN0b3JfZm9yX2Nvc3QgKik7CitleHRlcm4gYm9vbCB2ZWN0b3JpemFibGVfbGFuZV9yZWR1 Y2luZyAobG9vcF92ZWNfaW5mbywgc3RtdF92ZWNfaW5mbywKKwkJCQkJc2xwX3RyZWUsIHN0bXRf dmVjdG9yX2Zvcl9jb3N0ICopOwogZXh0ZXJuIGJvb2wgdmVjdG9yaXphYmxlX3JlZHVjdGlvbiAo bG9vcF92ZWNfaW5mbywgc3RtdF92ZWNfaW5mbywKIAkJCQkgICAgc2xwX3RyZWUsIHNscF9pbnN0 YW5jZSwKIAkJCQkgICAgc3RtdF92ZWN0b3JfZm9yX2Nvc3QgKik7Ci0tIAoyLjE3LjEKCg== --_002_LV2PR01MB78391AB09E644D51CFB34F2FF7D62LV2PR01MB7839prod_--