From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by sourceware.org (Postfix) with ESMTPS id 7AB6F3858D20 for ; Fri, 28 Jul 2023 12:57:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7AB6F3858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-314417861b9so1951269f8f.0 for ; Fri, 28 Jul 2023 05:57:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1690549076; x=1691153876; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=kAE+Q7Bjqsz3FZkdOtMqF2EWimseWejJws/DQustYkk=; b=hTIPsuNB9keAcHlD7//j6gX9jNDQn9+q+UsgP4spwCAXrlId24bBzSbGcNqHy9BTSR 7jimC1lsdj5LGU/uFQN0nrtQm8Gc3ZuVInqfAvWgdoA9qH13n0mutdnml+Pob2Io4FZQ bVK1nJSZ5QfmFGjJ+D4vuv3dLbtnxkmkEI0BiVaWLXJzTELL5NhCqkPanXY3Aj5ED1TR 3bapoyHJeln0+AHyCzz4zfumvsPxFI/wxeCrm+PZrsGIWIWcgeKvpn70SkZNLLF8meV2 xdaNKAgtc5GttUx5/YuG1znYXiT5exneb5xI0iG1VUYdBuadqdh2Bfxk3xAtmg4821RZ vR6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690549076; x=1691153876; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=kAE+Q7Bjqsz3FZkdOtMqF2EWimseWejJws/DQustYkk=; b=huaQWiwdSryNJACdHA3dmRoLUDQ6k+rROQ1/yTF+7YLw9tR0MqAikynxwwVqXM20t8 1r6lME0gXGVdx66veyJrdx1bR2kxOnlKxdemim6BjhU9pD9MA6bWnF+r31cPaEL48cKY kBUc3UFZzFfafA7scKuQfTn97bbP6ZAr53WfUoqVJqIbmmjhcA0W/jGBrTKnH1C5VYQH 6ztE1FpzHKIjdibq2B664E643auNyR30TZlKVMaFrEpFVwXl9loZQBoEGfT1XLJz+/Wu 0frqVsKjZe+m+R0Z27TtX4FbY8V6r54RFpvIKgztYrY3Go9lzZLhmghiY//2OBmsUC12 EjUQ== X-Gm-Message-State: ABy/qLZno416vnp9LlyiuSr6aakrugatD8X2nMSwrmBE4n547t1Tukrv KiXsuzAxe+1rCT9ZfjpQBv7hew7U3cptBjZpy6i1JA== X-Google-Smtp-Source: APBJJlEBbhWwd8I2jEDzvmUbTSHhLot2XW8TLflqlSwndPt7avPlMrXSj37Aa/N2wizXqL2L0s/9bWwmS5t4xuSp2Ok= X-Received: by 2002:adf:e504:0:b0:317:612e:b764 with SMTP id j4-20020adfe504000000b00317612eb764mr2029394wrm.58.1690549076045; Fri, 28 Jul 2023 05:57:56 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Prathamesh Kulkarni Date: Fri, 28 Jul 2023 18:27:19 +0530 Message-ID: Subject: Re: [RFC] [v2] Extend fold_vec_perm to handle VLA vectors To: Prathamesh Kulkarni , gcc Patches , richard.sandiford@arm.com Content-Type: multipart/mixed; boundary="0000000000002767ae06018ba112" X-Spam-Status: No, score=-8.9 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SCC_5_SHORT_WORD_LINES,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE 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: --0000000000002767ae06018ba112 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, 25 Jul 2023 at 18:25, Richard Sandiford wrote: > > Hi, > > Thanks for the rework and sorry for the slow review. Hi Richard, Thanks for the suggestions! Please find my responses inline below. > > Prathamesh Kulkarni writes: > > Hi Richard, > > This is reworking of patch to extend fold_vec_perm to handle VLA vector= s. > > The attached patch unifies handling of VLS and VLA vector_csts, while > > using fallback code > > for ctors. > > > > For VLS vector, the patch ignores underlying encoding, and > > uses npatterns =3D nelts, and nelts_per_pattern =3D 1. > > > > For VLA patterns, if sel has a stepped sequence, then it > > only chooses elements from a particular pattern of a particular > > input vector. > > > > To make things simpler, the patch imposes following constraints: > > (a) op0_npatterns, op1_npatterns and sel_npatterns are powers of 2. > > (b) The step size for a stepped sequence is a power of 2, and > > multiple of npatterns of chosen input vector. > > (c) Runtime vector length of sel is a multiple of sel_npatterns. > > So, we don't handle sel.length =3D 2 + 2x and npatterns =3D 4. > > > > Eg: > > op0, op1: npatterns =3D 2, nelts_per_pattern =3D 3 > > op0_len =3D op1_len =3D 16 + 16x. > > sel =3D { 0, 0, 2, 0, 4, 0, ... } > > npatterns =3D 2, nelts_per_pattern =3D 3. > > > > For pattern {0, 2, 4, ...} > > Let, > > a1 =3D 2 > > S =3D step size =3D 2 > > > > Let Esel denote number of elements per pattern in sel at runtime. > > Esel =3D (16 + 16x) / npatterns_sel > > =3D (16 + 16x) / 2 > > =3D (8 + 8x) > > > > So, last element of pattern: > > ae =3D a1 + (Esel - 2) * S > > =3D 2 + (8 + 8x - 2) * 2 > > =3D 14 + 16x > > > > a1 /trunc arg0_len =3D 2 / (16 + 16x) =3D 0 > > ae /trunc arg0_len =3D (14 + 16x) / (16 + 16x) =3D 0 > > Since both are equal with quotient =3D 0, we select elements from op0. > > > > Since step size (S) is a multiple of npatterns(op0), we select > > all elements from same pattern of op0. > > > > res_npatterns =3D max (op0_npatterns, max (op1_npatterns, sel_npatterns= )) > > =3D max (2, max (2, 2) > > =3D 2 > > > > res_nelts_per_pattern =3D max (op0_nelts_per_pattern, > > max (op1_nelts_per_patt= ern, > > sel_nelts_per_= pattern)) > > =3D max (3, max (3, 3)) > > =3D 3 > > > > So res has encoding with npatterns =3D 2, nelts_per_pattern =3D 3. > > res: { op0[0], op0[0], op0[2], op0[0], op0[4], op0[0], ... } > > > > Unfortunately, this results in an issue for poly_int_cst index: > > For example, > > op0, op1: npatterns =3D 1, nelts_per_pattern =3D 3 > > op0_len =3D op1_len =3D 4 + 4x > > > > sel: { 4 + 4x, 5 + 4x, 6 + 4x, ... } // should choose op1 > > > > In this case, > > a1 =3D 5 + 4x > > S =3D (6 + 4x) - (5 + 4x) =3D 1 > > Esel =3D 4 + 4x > > > > ae =3D a1 + (esel - 2) * S > > =3D (5 + 4x) + (4 + 4x - 2) * 1 > > =3D 7 + 8x > > > > IIUC, 7 + 8x will always be index for last element of op1 ? > > if x =3D 0, len =3D 4, 7 + 8x =3D 7 > > if x =3D 1, len =3D 8, 7 + 8x =3D 15, etc. > > So the stepped sequence will always choose elements > > from op1 regardless of vector length for above case ? > > > > However, > > ae /trunc op0_len > > =3D (7 + 8x) / (4 + 4x) > > which is not defined because 7/4 !=3D 8/4 > > and we return NULL_TREE, but I suppose the expected result would be: > > res: { op1[0], op1[1], op1[2], ... } ? > > > > The patch passes bootstrap+test on aarch64-linux-gnu with and without s= ve, > > and on x86_64-unknown-linux-gnu. > > I would be grateful for suggestions on how to proceed. > > > > Thanks, > > Prathamesh > > > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc > > index a02ede79fed..8028b3e8e9a 100644 > > --- a/gcc/fold-const.cc > > +++ b/gcc/fold-const.cc > > @@ -85,6 +85,10 @@ along with GCC; see the file COPYING3. If not see > > #include "vec-perm-indices.h" > > #include "asan.h" > > #include "gimple-range.h" > > +#include > > +#include "tree-pretty-print.h" > > +#include "gimple-pretty-print.h" > > +#include "print-tree.h" > > > > /* Nonzero if we are folding constants inside an initializer or a C++ > > manifestly-constant-evaluated context; zero otherwise. > > @@ -10493,15 +10497,9 @@ fold_mult_zconjz (location_t loc, tree type, t= ree expr) > > static bool > > vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts) > > { > > - unsigned HOST_WIDE_INT i, nunits; > > + unsigned HOST_WIDE_INT i; > > > > - if (TREE_CODE (arg) =3D=3D VECTOR_CST > > - && VECTOR_CST_NELTS (arg).is_constant (&nunits)) > > - { > > - for (i =3D 0; i < nunits; ++i) > > - elts[i] =3D VECTOR_CST_ELT (arg, i); > > - } > > - else if (TREE_CODE (arg) =3D=3D CONSTRUCTOR) > > + if (TREE_CODE (arg) =3D=3D CONSTRUCTOR) > > { > > constructor_elt *elt; > > > > @@ -10519,6 +10517,230 @@ vec_cst_ctor_to_array (tree arg, unsigned int= nelts, tree *elts) > > return true; > > } > > > > +/* Return a vector with (NPATTERNS, NELTS_PER_PATTERN) encoding. */ > > + > > +static tree > > +vector_cst_reshape (tree vec, unsigned npatterns, unsigned nelts_per_p= attern) > > +{ > > + gcc_assert (pow2p_hwi (npatterns)); > > + > > + if (VECTOR_CST_NPATTERNS (vec) =3D=3D npatterns > > + && VECTOR_CST_NELTS_PER_PATTERN (vec) =3D=3D nelts_per_pattern) > > + return vec; > > + > > + tree v =3D make_vector (exact_log2 (npatterns), nelts_per_pattern); > > + TREE_TYPE (v) =3D TREE_TYPE (vec); > > + > > + unsigned nelts =3D npatterns * nelts_per_pattern; > > + for (unsigned i =3D 0; i < nelts; i++) > > + VECTOR_CST_ENCODED_ELT(v, i) =3D vector_cst_elt (vec, i); > > + return v; > > +} > > + > > +/* Helper routine for fold_vec_perm_vla to check if ARG is a suitable > > + operand for VLA vec_perm folding. If arg is VLS, then set > > + NPATTERNS =3D nelts and NELTS_PER_PATTERN =3D 1. */ > > + > > +static tree > > +valid_operand_for_fold_vec_perm_cst_p (tree arg) > > +{ > > + if (TREE_CODE (arg) !=3D VECTOR_CST) > > + return NULL_TREE; > > + > > + unsigned HOST_WIDE_INT nelts; > > + unsigned npatterns, nelts_per_pattern; > > + if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)).is_constant (&nelts)) > > + { > > + npatterns =3D nelts; > > + nelts_per_pattern =3D 1; > > + } > > + else > > + { > > + npatterns =3D VECTOR_CST_NPATTERNS (arg); > > + nelts_per_pattern =3D VECTOR_CST_NELTS_PER_PATTERN (arg); > > + } > > + > > + if (!pow2p_hwi (npatterns)) > > + return NULL_TREE; > > + > > + return vector_cst_reshape (arg, npatterns, nelts_per_pattern); > > +} > > I don't think we should reshape the vectors for VLS, since it would > create more nodes for GC to clean up later. Also, the "compact" encoding > is canonical even for VLS, so the reshaping would effectively create > noncanonical constants (even if only temporarily). Removed in the attached patch. > > Instead, I think we should change the later: > > > + if (!valid_mask_for_fold_vec_perm_cst_p (arg0, arg1, sel, sel_npatte= rns, > > + sel_nelts_per_pattern, reason,= verbose)) > > + return NULL_TREE; > > so that it comes after the computation of res_npatterns and > res_nelts_per_pattern. Then, if valid_mask_for_fold_vec_perm_cst_p > returns false, and if the result type has a constant number of elements, > we should: > > * set res_npatterns to that number of elements > * set res_nelts_per_pattern to 1 > * continue instead of returning null Assuming we don't enforce only VLA or only VLS for input vectors and sel, won't that be still an issue if res (and sel) is VLS, and input vectors are VLA ? For eg: arg0, arg1 are type VNx4SI with npatterns =3D 2, nelts_per_pattern =3D 3, s= tep =3D 2 sel is V4SI constant with encoding { 0, 2, 4, ... } and res_type is V4SI. In this case, when it comes to index 4, the vector selection becomes ambigu= ous, since it can be arg1 for len =3D 4 + 4x, and arg0 for lengths > 4 + 4x ? In the attached patch if sel is not a suitable mask, and input vectors have constant length, then it sets: res_npatterns =3D nelts of input vector res_nelts_per_pattern =3D 1 Does that look OK ? This part of the code has few tests in test_mixed(). > > The loop that follows will then do the correct thing for each element. > > The check for a power of 2 would then go in > valid_mask_for_fold_vec_perm_cst_p rather than > valid_operand_for_fold_vec_perm_cst_p. > > With that change, I think: > > > + > > +/* Helper routine for fold_vec_perm_cst to check if SEL is a suitable > > + mask for VLA vec_perm folding. Set SEL_NPATTERNS and SEL_NELTS_PER_= PATTERN > > + similarly. */ > > + > > +static bool > > +valid_mask_for_fold_vec_perm_cst_p (tree arg0, tree arg1, > > + const vec_perm_indices &sel, > > + unsigned& sel_npatterns, > > + unsigned& sel_nelts_per_pattern, > > + char *reason =3D NULL, > > + bool verbose =3D false) > > +{ > > + unsigned HOST_WIDE_INT nelts; > > + if (sel.length ().is_constant (&nelts)) > > + { > > + sel_npatterns =3D nelts; > > + sel_nelts_per_pattern =3D 1; > > + } > > + else > > + { > > + sel_npatterns =3D sel.encoding ().npatterns (); > > + sel_nelts_per_pattern =3D sel.encoding ().nelts_per_pattern (); > > + } > > ...we should use the "else" code unconditionally. Done. > > The function comment should describe "reason" and "verbose". It looks > like these are debug parameters, is that right? Yes, verbose is just for printf debugging, and reason is used in unit-tests= when result is NULL_TREE, to verify that it's NULL for the intended reason, and not due to something else. > > > + > > + if (!pow2p_hwi (sel_npatterns)) > > + { > > + if (reason) > > + strcpy (reason, "sel_npatterns is not power of 2"); > > + return false; > > + } > > + > > + /* We want to avoid cases where sel.length is not a multiple of npat= terns. > > + For eg: sel.length =3D 2 + 2x, and sel npatterns =3D 4. */ > > + poly_uint64 esel; > > + if (!multiple_p (sel.length (), sel_npatterns, &esel)) > > + { > > + if (reason) > > + strcpy (reason, "sel.length is not multiple of sel_npatterns"); > > + return false; > > + } > > + > > + if (sel_nelts_per_pattern < 3) > > + return true; > > + > > + for (unsigned pattern =3D 0; pattern < sel_npatterns; pattern++) > > + { > > + poly_uint64 a1 =3D sel[pattern + sel_npatterns]; > > + poly_uint64 a2 =3D sel[pattern + 2 * sel_npatterns]; > > + > > + poly_uint64 step =3D a2 - a1; > > + if (!step.is_constant ()) > > + { > > + if (reason) > > + strcpy (reason, "step is not constant"); > > + return false; > > + } > > + int S =3D step.to_constant (); > > + if (S =3D=3D 0) > > + continue; > > Might be simpler as: > > HOST_WIDE_INT step; > if (!(a2 - a1).is_constant (&step)) > { > ... > } This resulted in following error: ../../gcc/gcc/fold-const.cc:10563:34: error: no matching function for call to =E2=80=98poly_int<2, long unsigned int>::is_constant(long int*)=E2= =80=99 10563 | if (!(a2 - a1).is_constant (&S)) | ~~~~~~~~~~~~~~~~~~~~~~^~~~ > if (step =3D=3D 0) > continue; > > > + > > + // FIXME: Punt on S < 0 for now, revisit later. > > + if (S < 0) > > + return false; > > + > > + if (!pow2p_hwi (S)) > > + { > > + if (reason) > > + strcpy (reason, "step is not power of 2"); > > + return false; > > + } > > + > > + poly_uint64 ae =3D a1 + (esel - 2) * S; > > + poly_uint64 arg_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + uint64_t q1, qe; > > + poly_uint64 r1, re; > > + > > + /* Ensure that stepped sequence of the pattern selects elements > > + only from the same input vector. */ > > + if (!(can_div_trunc_p (a1, arg_len, &q1, &r1) > > + && can_div_trunc_p (ae, arg_len, &qe, &re) > > + && (q1 =3D=3D qe))) > > Nit: redundant brackets around q1 =3D=3D qe Fixed, thanks. > > > + { > > + if (reason) > > + strcpy (reason, "crossed input vectors"); > > + return false; > > + } > > + unsigned arg_npatterns > > + =3D ((q1 & 0) =3D=3D 0) ? VECTOR_CST_NPATTERNS (arg0) > > + : VECTOR_CST_NPATTERNS (arg1); > > + > > + gcc_assert (pow2p_hwi (arg_npatterns)); > > + if (S < arg_npatterns) > > Since (as the reason string says) the condition is logically that the > step is a multiple of the number of patterns, rather than simply bigger, > I think it's more obvious to write it as: > > if (!multiple_p (step, arg_npatterns)) > > without the gcc_assert. Fixed, thanks. > > > + { > > + if (reason) > > + strcpy (reason, "S is not multiple of npatterns"); > > + return false; > > + } > > + } > > + > > + return true; > > +} > > + > > +/* Try to fold permutation of ARG0 and ARG1 with SEL selector when > > + the input vectors are VECTOR_CST. Return NULL_TREE otherwise. */ > > + > > +static tree > > +fold_vec_perm_cst (tree type, tree arg0, tree arg1, const vec_perm_ind= ices &sel, > > + char *reason =3D NULL, bool verbose =3D false) > > +{ > > + /* Allow cases where: > > + (1) arg0, arg1 and sel are VLS. > > + (2) arg0, arg1, and sel are VLA. > > + Punt if input vectors are VLA but sel is VLS or vice-versa. */ > > + poly_uint64 arg_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + if (!((arg_len.is_constant () && sel.length ().is_constant ()) > > + || (!arg_len.is_constant () && !sel.length ().is_constant ()))) > > + return NULL_TREE; > > With the changes above, I'm not sure we need to enforce this. Removed. > > > + unsigned sel_npatterns, sel_nelts_per_pattern; > > + > > + arg0 =3D valid_operand_for_fold_vec_perm_cst_p (arg0); > > + if (!arg0) > > + return NULL_TREE; > > + > > + arg1 =3D valid_operand_for_fold_vec_perm_cst_p (arg1); > > + if (!arg1) > > + return NULL_TREE; > > + > > + if (!valid_mask_for_fold_vec_perm_cst_p (arg0, arg1, sel, sel_npatte= rns, > > + sel_nelts_per_pattern, reason,= verbose)) > > + return NULL_TREE; > > + > > + unsigned res_npatterns > > + =3D std::max (VECTOR_CST_NPATTERNS (arg0), > > + std::max (VECTOR_CST_NPATTERNS (arg1), sel_npatterns)); > > + > > + unsigned res_nelts_per_pattern > > + =3D std::max (VECTOR_CST_NELTS_PER_PATTERN (arg0), > > + std::max (VECTOR_CST_NELTS_PER_PATTERN (arg1), > > + sel_nelts_per_pattern)); > > + > > + > > Nit: too much vertical space. Fixed, thanks. > > > + tree_vector_builder out_elts (type, res_npatterns, res_nelts_per_pat= tern); > > + unsigned res_nelts =3D res_npatterns * res_nelts_per_pattern; > > + for (unsigned i =3D 0; i < res_nelts; i++) > > + { > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + uint64_t q; > > + poly_uint64 r; > > + unsigned HOST_WIDE_INT index; > > + > > + /* Punt if sel[i] /trunc_div len cannot be determined, > > + because the input vector to be chosen will depend on > > + runtime vector length. > > + For example if len =3D=3D 4 + 4x, and sel[i] =3D=3D 4, > > + If len at runtime equals 4, we choose arg1[0]. > > + For any other value of len > 4 at runtime, we choose arg0[4]. > > + which makes the element choice dependent on runtime vector lengt= h. */ > > + if (!can_div_trunc_p (sel[i], len, &q, &r)) > > + return NULL_TREE; > > + > > + /* sel[i] % len will give the index of element in the chosen inp= ut > > + vector. For example if sel[i] =3D=3D 5 + 4x and len =3D=3D 4 + 4= x, > > + we will choose arg1[1] since (5 + 4x) % (4 + 4x) =3D=3D 1. */ > > + if (!r.is_constant (&index)) > > + return NULL_TREE; > > + > > + tree arg =3D ((q & 1) =3D=3D 0) ? arg0 : arg1; > > + tree elem =3D vector_cst_elt (arg, index); > > + out_elts.quick_push (elem); > > + } > > + > > + return out_elts.build (); > > +} > > + > > /* Attempt to fold vector permutation of ARG0 and ARG1 vectors using S= EL > > selector. Return the folded VECTOR_CST or CONSTRUCTOR if successfu= l, > > NULL_TREE otherwise. */ > > @@ -10528,43 +10750,39 @@ fold_vec_perm (tree type, tree arg0, tree arg= 1, const vec_perm_indices &sel) > > { > > unsigned int i; > > unsigned HOST_WIDE_INT nelts; > > - bool need_ctor =3D false; > > > > - if (!sel.length ().is_constant (&nelts)) > > - return NULL_TREE; > > - gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (type), nelts) > > - && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)), nelts= ) > > - && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)), nelts= )); > > + gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (type), sel.length ()) > > + && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)), > > + TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)))); > > + > > if (TREE_TYPE (TREE_TYPE (arg0)) !=3D TREE_TYPE (type) > > || TREE_TYPE (TREE_TYPE (arg1)) !=3D TREE_TYPE (type)) > > return NULL_TREE; > > > > + if (TREE_CODE (arg0) =3D=3D VECTOR_CST > > + && TREE_CODE (arg1) =3D=3D VECTOR_CST) > > + return fold_vec_perm_cst (type, arg0, arg1, sel); > > + > > + /* For fall back case, we want to ensure arg and sel have same len. = */ > > + if (!(sel.length ().is_constant (&nelts) > > + && known_eq (sel.length (), TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0= ))))) > > + return NULL_TREE; > > I think the known_eq should be an unconditional assert (after the call > to fold_vec_perm_cst but before the return NULL_TREE). Um sorry I am not sure if I understood this correctly. In the patch, I placed the assert unconditionally after checking sel is constant. Does that look OK ? > > Looks good otherwise. I'll do a separate review for the tests (but they > look pretty extensive, thanks). Thanks. The attached patch passes bootstrap+test on aarch64-linux-gnu with and without SVE enabled, and on x86_64-linux-gnu. Could you please elaborate on the following issue, because it still stands in this patch, which is in Case 2 of test_fold_vec_perm_cst::test_stepped. For example, op0, op1: npatterns =3D 1, nelts_per_pattern =3D 3 op0_len =3D op1_len =3D 4 + 4x sel: { 4 + 4x, 5 + 4x, 6 + 4x, ... } // should choose op1 In this case, a1 =3D 5 + 4x S =3D (6 + 4x) - (5 + 4x) =3D 1 Esel =3D 4 + 4x ae =3D a1 + (esel - 2) * S =3D (5 + 4x) + (4 + 4x - 2) * 1 =3D 7 + 8x IIUC, 7 + 8x will always be index for last element of op1 ? if x =3D 0, len =3D 4, 7 + 8x =3D 7 if x =3D 1, len =3D 8, 7 + 8x =3D 15, etc. So the stepped sequence will always choose elements from op1 regardless of vector length for above case ? However, ae /trunc op0_len =3D (7 + 8x) / (4 + 4x) which is not defined because 7/4 !=3D 8/4 and we return NULL_TREE, but I suppose the expected result would be: res: { op1[0], op1[1], op1[2], ... } ? I was wondering if the following approach made sense: Since indices wrap around, take index % 2*arg_len, so the remainder is in interval (0, 2 * arg_len]. If both remainders are in interval [0, arg_len) -> choose arg0 If both remainders are in interval [arg_len, 2 * arg_len) -> choose arg1 If comparison is not determined at compile time or both lie in different intervals, return NULL_TREE. So for above example, r1 =3D (5 + 4x) % (8 + 8x) =3D 5 + 4x re =3D (7 + 8x) % (8 + 8x) =3D 7 + 8x Since both lie in interval [4+4x, 8+8x) --> choose arg1 If we have say a1 =3D 4, and arg_len =3D 4 + 4x, then the comparison becomes ambiguous, and known_lt (4, 4+4x) will return 0. In that case, we return NULL_TREE. Taking Case 4 eg from test_fold_vec_perm_cst::test_stepped(): op0, op1 -> len =3D 16+16x, npatterns =3D 1, nelts_per_pattern =3D 3 sel =3D { len, 0, 2, ... } npatterns =3D 1, nelts_per_pattern =3D 3 a1 =3D 0 esel =3D (16 + 16x) / 1 =3D 16 + 16x S =3D 2 ae =3D a1 + (esel - 2) * S =3D 28 + 32x r1 =3D 0 % (32 + 32x) =3D 0 re =3D (28 + 32x) % (32 + 32x) =3D 28 + 32x However r1 is in interval [0, 16+16x) and re is in interval [16+16x, 32+32x= ), so we cross input vectors here and return NULL_TREE. Thanks, Prathamesh > > Richard > > > + > > tree *in_elts =3D XALLOCAVEC (tree, nelts * 2); > > if (!vec_cst_ctor_to_array (arg0, nelts, in_elts) > > || !vec_cst_ctor_to_array (arg1, nelts, in_elts + nelts)) > > return NULL_TREE; > > > > - tree_vector_builder out_elts (type, nelts, 1); > > + vec *v; > > + vec_alloc (v, nelts); > > for (i =3D 0; i < nelts; i++) > > { > > HOST_WIDE_INT index; > > if (!sel[i].is_constant (&index)) > > return NULL_TREE; > > - if (!CONSTANT_CLASS_P (in_elts[index])) > > - need_ctor =3D true; > > - out_elts.quick_push (unshare_expr (in_elts[index])); > > + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, in_elts[index]); > > } > > - > > - if (need_ctor) > > - { > > - vec *v; > > - vec_alloc (v, nelts); > > - for (i =3D 0; i < nelts; i++) > > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, out_elts[i]); > > - return build_constructor (type, v); > > - } > > - else > > - return out_elts.build (); > > + return build_constructor (type, v); > > } > > > > /* Try to fold a pointer difference of type TYPE two address expressio= ns of > > @@ -16891,6 +17109,388 @@ test_arithmetic_folding () > > x); > > } > > > > +namespace test_fold_vec_perm_cst { > > + > > +static tree > > +get_preferred_vectype (tree inner_type) > > +{ > > + scalar_int_mode int_mode =3D SCALAR_INT_TYPE_MODE (inner_type); > > + machine_mode vmode =3D targetm.vectorize.preferred_simd_mode (int_mo= de); > > + poly_uint64 nunits =3D GET_MODE_NUNITS (vmode); > > + return build_vector_type (inner_type, nunits); > > +} > > + > > +static tree > > +build_vec_cst_rand (tree inner_type, unsigned npatterns, > > + unsigned nelts_per_pattern, int S =3D 0) > > +{ > > + tree vectype =3D get_preferred_vectype (inner_type); > > + tree_vector_builder builder (vectype, npatterns, nelts_per_pattern); > > + > > + // Fill a0 for each pattern > > + for (unsigned i =3D 0; i < npatterns; i++) > > + builder.quick_push (build_int_cst (inner_type, rand () % 100)); > > + > > + if (nelts_per_pattern =3D=3D 1) > > + return builder.build (); > > + > > + // Fill a1 for each pattern > > + for (unsigned i =3D 0; i < npatterns; i++) > > + builder.quick_push (build_int_cst (inner_type, rand () % 100)); > > + > > + if (nelts_per_pattern =3D=3D 2) > > + return builder.build (); > > + > > + for (unsigned i =3D npatterns * 2; i < npatterns * nelts_per_pattern= ; i++) > > + { > > + tree prev_elem =3D builder[i - npatterns]; > > + int prev_elem_val =3D TREE_INT_CST_LOW (prev_elem); > > + int val =3D prev_elem_val + S; > > + builder.quick_push (build_int_cst (inner_type, val)); > > + } > > + > > + return builder.build (); > > +} > > + > > +static void > > +validate_res (unsigned npatterns, unsigned nelts_per_pattern, > > + tree res, tree *expected_res) > > +{ > > + ASSERT_TRUE (VECTOR_CST_NPATTERNS (res) =3D=3D npatterns); > > + ASSERT_TRUE (VECTOR_CST_NELTS_PER_PATTERN (res) =3D=3D nelts_per_pat= tern); > > + > > + for (unsigned i =3D 0; i < vector_cst_encoded_nelts (res); i++) > > + ASSERT_TRUE (operand_equal_p (VECTOR_CST_ELT (res, i), expected_re= s[i], 0)); > > +} > > + > > +/* Verify VLA vec_perm folding. */ > > + > > +static void > > +test_stepped () > > +{ > > + /* Case 1: sel =3D {0, 1, 2, ...} > > + npatterns =3D 1, nelts_per_pattern =3D 3 */ > > + { > > + tree arg0 =3D build_vec_cst_rand (char_type_node, 1, 3, 2); > > + tree arg1 =3D build_vec_cst_rand (char_type_node, 1, 3, 2); > > + poly_uint64 arg0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + builder.quick_push (0); > > + builder.quick_push (1); > > + builder.quick_push (2); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + tree expected_res[] =3D { vector_cst_elt (arg0, 0), vector_cst_elt= (arg0, 1), > > + vector_cst_elt (arg0, 2) }; > > + validate_res (1, 3, res, expected_res); > > + } > > + > > +#if 0 > > + /* Case 2: sel =3D {len, len + 1, len + 2, ... } > > + npatterns =3D 1, nelts_per_pattern =3D 3 > > + FIXME: This should return > > + expected res: { op1[0], op1[1], op1[2], ... } > > + however it returns NULL_TREE. */ > > + { > > + vec_perm_builder builder (arg0_len, 1, 3); > > + builder.quick_push (arg0_len); > > + builder.quick_push (arg0_len + 1); > > + builder.quick_push (arg0_len + 2); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + } > > +#endif > > + > > + /* Case 3: Leading element of arg1, stepped sequence: pattern 0 of a= rg0. > > + sel =3D {len, 0, 0, 0, 2, 0, ...} > > + npatterns =3D 2, nelts_per_pattern =3D 3. > > + Use extra pattern {0, ...} to lower number of elements per patter= n. */ > > + { > > + tree arg0 =3D build_vec_cst_rand (char_type_node, 1, 3, 2); > > + tree arg1 =3D build_vec_cst_rand (char_type_node, 1, 3, 2); > > + poly_uint64 arg0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 2, 3); > > + builder.quick_push (arg0_len); > > + int mask_elems[] =3D { 0, 0, 0, 2, 0 }; > > + for (int i =3D 0; i < 5; i++) > > + builder.quick_push (mask_elems[i]); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + gcc_assert (res); > > + } > > + > > + /* Case 4: > > + sel =3D { len, 0, 2, ... } npatterns =3D 1, nelts_per_pattern =3D= 3. > > + This should return NULL because we cross the input vectors. > > + Because, > > + arg0_len =3D 16 + 16x > > + a1 =3D 0 > > + S =3D 2 > > + esel =3D arg0_len / npatterns_sel =3D 16+16x/1 =3D 16 + 16x > > + ae =3D a1 + (esel - 2) * S > > + =3D 0 + (16 + 16x - 2) * 2 > > + =3D 28 + 32x > > + a1 / arg0_len =3D 0 /trunc (16 + 16x) =3D 0 > > + ae / arg0_len =3D (28 + 32x) /trunc (16 + 16x), which is not defi= ned, > > + since 28/16 !=3D 32/16. > > + So return NULL_TREE. */ > > + { > > + tree arg0 =3D build_vec_cst_rand (char_type_node, 1, 3, 2); > > + tree arg1 =3D build_vec_cst_rand (char_type_node, 1, 3, 2); > > + poly_uint64 arg0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + poly_uint64 ae =3D (arg0_len - 2) * 2; > > + uint64_t qe; > > + poly_uint64 re; > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + builder.quick_push (arg0_len); > > + builder.quick_push (0); > > + builder.quick_push (2); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + char reason[100] =3D "\0"; > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel,= reason, false); > > + gcc_assert (res =3D=3D NULL_TREE); > > + gcc_assert (!strcmp (reason, "crossed input vectors")); > > + } > > + > > + /* Case 5: Select elements from different patterns. > > + Should return NULL. */ > > + { > > + tree op0 =3D build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree op1 =3D build_vec_cst_rand (char_type_node, 2, 3, 2); > > + poly_uint64 op0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0)); > > + > > + vec_perm_builder builder (op0_len, 2, 3); > > + builder.quick_push (op0_len); > > + int mask_elems[] =3D { 0, 0, 0, 1, 0 }; > > + for (int i =3D 0; i < 5; i++) > > + builder.quick_push (mask_elems[i]); > > + > > + vec_perm_indices sel (builder, 2, op0_len); > > + char reason[100] =3D "\0"; > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (op0), op0, op1, sel, re= ason, false); > > + gcc_assert (res =3D=3D NULL_TREE); > > + gcc_assert (!strcmp (reason, "S is not multiple of npatterns")); > > + } > > + > > + /* Case 6: Select pattern 0 of op0 and dup of op0[0] > > + op0, op1, sel: npatterns =3D 2, nelts_per_pattern =3D 3 > > + sel =3D { 0, 0, 2, 0, 4, 0, ... }. > > + > > + For pattern {0, 2, 4, ...}: > > + a1 =3D 2 > > + len =3D 16 + 16x > > + S =3D 2 > > + esel =3D len / npatterns_sel =3D (16 + 16x) / 2 =3D (8 + 8x) > > + ae =3D a1 + (esel - 2) * S > > + =3D 2 + (8 + 8x - 2) * 2 > > + =3D 14 + 16x > > + a1 / arg0_len =3D 2 / (16 + 16x) =3D 0 > > + ae / arg0_len =3D (14 + 16x) / (16 + 16x) =3D 0 > > + So a1/arg0_len =3D ae/arg0_len =3D 0 > > + Hence we select from first vector op0 > > + S =3D 2, npatterns =3D 2. > > + Since S is multiple of npatterns(op0), we are selecting from > > + same pattern of op0. > > + > > + For pattern {0, ...}, we are choosing { op0[0] ... } > > + So res will be combination of above patterns: > > + res: { op0[0], op0[0], op0[2], op0[0], op0[4], op0[0], ... } > > + with npatterns =3D 2, nelts_per_pattern =3D 3. */ > > + { > > + tree op0 =3D build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree op1 =3D build_vec_cst_rand (char_type_node, 2, 3, 2); > > + poly_uint64 op0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0)); > > + > > + vec_perm_builder builder (op0_len, 2, 3); > > + int mask_elems[] =3D { 0, 0, 2, 0, 4, 0 }; > > + for (int i =3D 0; i < 6; i++) > > + builder.quick_push (mask_elems[i]); > > + > > + vec_perm_indices sel (builder, 2, op0_len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (op0), op0, op1, sel); > > + tree expected_res[] =3D { vector_cst_elt (op0, 0), vector_cst_elt = (op0, 0), > > + vector_cst_elt (op0, 2), vector_cst_elt (op0,= 0), > > + vector_cst_elt (op0, 4), vector_cst_elt (op0,= 0) }; > > + validate_res (2, 3, res, expected_res); > > + } > > + > > + /* Case 7: sel_npatterns > op_npatterns; > > + op0, op1: npatterns =3D 2, nelts_per_pattern =3D 3 > > + sel: { 0, 0, 1, len, 2, 0, 3, len, 4, 0, 5, len, ...}, > > + with npatterns =3D 4, nelts_per_pattern =3D 3. */ > > + { > > + tree op0 =3D build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree op1 =3D build_vec_cst_rand (char_type_node, 2, 3, 2); > > + poly_uint64 op0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0)); > > + > > + vec_perm_builder builder(op0_len, 4, 3); > > + // -1 is used as place holder for poly_int_cst > > + int mask_elems[] =3D { 0, 0, 1, -1, 2, 0, 3, -1, 4, 0, 5, -1 }; > > + for (int i =3D 0; i < 12; i++) > > + builder.quick_push ((mask_elems[i] =3D=3D -1) ? op0_len : mask_e= lems[i]); > > + > > + vec_perm_indices sel (builder, 2, op0_len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (op0), op0, op1, sel); > > + tree expected_res[] =3D { vector_cst_elt (op0, 0), vector_cst_elt = (op0, 0), > > + vector_cst_elt (op0, 1), vector_cst_elt (op1,= 0), > > + vector_cst_elt (op0, 2), vector_cst_elt (op0,= 0), > > + vector_cst_elt (op0, 3), vector_cst_elt (op1,= 0), > > + vector_cst_elt (op0, 4), vector_cst_elt (op0,= 0), > > + vector_cst_elt (op0, 5), vector_cst_elt (op1,= 0) }; > > + validate_res (4, 3, res, expected_res); > > + } > > +} > > + > > +static void > > +test_dup () > > +{ > > + /* Case 1: mask =3D {0, ...} */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 1); > > + builder.quick_push (0); > > + vec_perm_indices sel (builder, 2, len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + > > + tree expected_res[] =3D { vector_cst_elt (res, 0) }; > > + validate_res (1, 1, res, expected_res); > > + } > > + > > + /* Case 2: mask =3D {len, ...} */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 1); > > + builder.quick_push (len); > > + vec_perm_indices sel (builder, 2, len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + > > + tree expected_res[] =3D { vector_cst_elt (arg1, 0) }; > > + validate_res (1, 1, res, expected_res); > > + } > > + > > + /* Case 3: mask =3D { 0, len, ... } */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 1); > > + builder.quick_push (0); > > + builder.quick_push (len); > > + vec_perm_indices sel (builder, 2, len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + > > + tree expected_res[] =3D { vector_cst_elt (arg0, 0), vector_cst_elt= (arg1, 0) }; > > + validate_res (2, 1, res, expected_res); > > + } > > + > > + /* Case 4: mask =3D { 0, len, 1, len+1, ... } */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 2); > > + builder.quick_push (0); > > + builder.quick_push (len); > > + builder.quick_push (1); > > + builder.quick_push (len + 1); > > + vec_perm_indices sel (builder, 2, len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + > > + tree expected_res[] =3D { vector_cst_elt (arg0, 0), vector_cst_elt= (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg= 1, 1) > > + }; > > + validate_res (2, 2, res, expected_res); > > + } > > + > > + /* Case 5: mask =3D { 0, len, 1, len+1, .... } > > + npatterns =3D 4, nelts_per_pattern =3D 1 */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 4, 1); > > + builder.quick_push (0); > > + builder.quick_push (len); > > + builder.quick_push (1); > > + builder.quick_push (len + 1); > > + vec_perm_indices sel (builder, 2, len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + > > + tree expected_res[] =3D { vector_cst_elt (arg0, 0), vector_cst_elt= (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg= 1, 1) > > + }; > > + validate_res (4, 1, res, expected_res); > > + } > > + > > + /* Case 6: mask =3D {0, 4, ...} > > + npatterns =3D 1, nelts_per_pattern =3D 2. > > + This should return NULL_TREE because the index 4 may choose > > + from either arg0 or arg1 depending on vector length. */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 2); > > + builder.quick_push (0); > > + builder.quick_push (4); > > + vec_perm_indices sel (builder, 2, len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + ASSERT_TRUE (res =3D=3D NULL_TREE); > > + } > > + > > + /* Case 7: npatterns(arg0) =3D 4 > npatterns(sel) =3D 2 > > + mask =3D {0, len, 1, len + 1, ...} > > + sel_npatterns =3D 2, sel_nelts_per_pattern =3D 2. */ > > + { > > + tree arg0 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 =3D build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 arg0_len =3D TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 2, 2); > > + builder.quick_push (0); > > + builder.quick_push (arg0_len); > > + builder.quick_push (1); > > + builder.quick_push (arg0_len + 1); > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res =3D fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel)= ; > > + > > + tree expected_res[] =3D { vector_cst_elt (arg0, 0), vector_cst_elt= (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg= 1, 1) > > + }; > > + validate_res (2, 2, res, expected_res); > > + } > > +} > > + > > +static void > > +test () > > +{ > > + tree vectype =3D get_preferred_vectype (integer_type_node); > > + if (TYPE_VECTOR_SUBPARTS (vectype).is_constant ()) > > + return; > > + > > + test_dup (); > > + test_stepped (); > > +} > > +}; > > + > > /* Verify that various binary operations on vectors are folded > > correctly. */ > > > > @@ -16942,6 +17542,7 @@ fold_const_cc_tests () > > test_arithmetic_folding (); > > test_vector_folding (); > > test_vec_duplicate_folding (); > > + test_fold_vec_perm_cst::test (); > > } > > > > } // namespace selftest --0000000000002767ae06018ba112 Content-Type: text/plain; charset="US-ASCII"; name="gnu-790-v2-8.txt" Content-Disposition: attachment; filename="gnu-790-v2-8.txt" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_lkmk7ft20 ZGlmZiAtLWdpdCBhL2djYy9mb2xkLWNvbnN0LmNjIGIvZ2NjL2ZvbGQtY29uc3QuY2MKaW5kZXgg N2U1NDk0ZGZkMzkuLjcxODU3ZTE2MTg1IDEwMDY0NAotLS0gYS9nY2MvZm9sZC1jb25zdC5jYwor KysgYi9nY2MvZm9sZC1jb25zdC5jYwpAQCAtODUsNiArODUsMTAgQEAgYWxvbmcgd2l0aCBHQ0M7 IHNlZSB0aGUgZmlsZSBDT1BZSU5HMy4gIElmIG5vdCBzZWUKICNpbmNsdWRlICJ2ZWMtcGVybS1p bmRpY2VzLmgiCiAjaW5jbHVkZSAiYXNhbi5oIgogI2luY2x1ZGUgImdpbXBsZS1yYW5nZS5oIgor I2luY2x1ZGUgPGFsZ29yaXRobT4KKyNpbmNsdWRlICJ0cmVlLXByZXR0eS1wcmludC5oIgorI2lu Y2x1ZGUgImdpbXBsZS1wcmV0dHktcHJpbnQuaCIKKyNpbmNsdWRlICJwcmludC10cmVlLmgiCiAK IC8qIE5vbnplcm8gaWYgd2UgYXJlIGZvbGRpbmcgY29uc3RhbnRzIGluc2lkZSBhbiBpbml0aWFs aXplciBvciBhIEMrKwogICAgbWFuaWZlc3RseS1jb25zdGFudC1ldmFsdWF0ZWQgY29udGV4dDsg emVybyBvdGhlcndpc2UuCkBAIC0xMDQ5NCwxNSArMTA0OTgsOSBAQCBmb2xkX211bHRfemNvbmp6 IChsb2NhdGlvbl90IGxvYywgdHJlZSB0eXBlLCB0cmVlIGV4cHIpCiBzdGF0aWMgYm9vbAogdmVj X2NzdF9jdG9yX3RvX2FycmF5ICh0cmVlIGFyZywgdW5zaWduZWQgaW50IG5lbHRzLCB0cmVlICpl bHRzKQogewotICB1bnNpZ25lZCBIT1NUX1dJREVfSU5UIGksIG51bml0czsKKyAgdW5zaWduZWQg SE9TVF9XSURFX0lOVCBpOwogCi0gIGlmIChUUkVFX0NPREUgKGFyZykgPT0gVkVDVE9SX0NTVAot ICAgICAgJiYgVkVDVE9SX0NTVF9ORUxUUyAoYXJnKS5pc19jb25zdGFudCAoJm51bml0cykpCi0g ICAgewotICAgICAgZm9yIChpID0gMDsgaSA8IG51bml0czsgKytpKQotCWVsdHNbaV0gPSBWRUNU T1JfQ1NUX0VMVCAoYXJnLCBpKTsKLSAgICB9Ci0gIGVsc2UgaWYgKFRSRUVfQ09ERSAoYXJnKSA9 PSBDT05TVFJVQ1RPUikKKyAgaWYgKFRSRUVfQ09ERSAoYXJnKSA9PSBDT05TVFJVQ1RPUikKICAg ICB7CiAgICAgICBjb25zdHJ1Y3Rvcl9lbHQgKmVsdDsKIApAQCAtMTA1MjAsNiArMTA1MTgsMTky IEBAIHZlY19jc3RfY3Rvcl90b19hcnJheSAodHJlZSBhcmcsIHVuc2lnbmVkIGludCBuZWx0cywg dHJlZSAqZWx0cykKICAgcmV0dXJuIHRydWU7CiB9CiAKKy8qIEhlbHBlciByb3V0aW5lIGZvciBm b2xkX3ZlY19wZXJtX2NzdCB0byBjaGVjayBpZiBTRUwgaXMgYSBzdWl0YWJsZQorICAgbWFzayBm b3IgVkxBIHZlY19wZXJtIGZvbGRpbmcuCisgICBSRUFTT04gaWYgc3BlY2lmaWVkLCB3aWxsIGNv bnRhaW4gdGhlIHJlYXNvbiB3aHkgU0VMIGlzIG5vdCBzdWl0YWJsZS4KKyAgIFVzZWQgb25seSBm b3IgZGVidWdnaW5nIGFuZCB1bml0LXRlc3RpbmcuCisgICBWRVJCT1NFIGlmIGVuYWJsZWQgaXMg dXNlZCBmb3IgZGVidWdnaW5nIG91dHB1dC4gICovCisKK3N0YXRpYyBib29sCit2YWxpZF9tYXNr X2Zvcl9mb2xkX3ZlY19wZXJtX2NzdF9wICh0cmVlIGFyZzAsIHRyZWUgYXJnMSwKKwkJCQkgICAg Y29uc3QgdmVjX3Blcm1faW5kaWNlcyAmc2VsLAorCQkJCSAgICBjaGFyICpyZWFzb24gPSBOVUxM LAorCQkJCSAgICBBVFRSSUJVVEVfVU5VU0VEIGJvb2wgdmVyYm9zZSA9IGZhbHNlKQoreworICB1 bnNpZ25lZCBzZWxfbnBhdHRlcm5zID0gc2VsLmVuY29kaW5nICgpLm5wYXR0ZXJucyAoKTsKKyAg dW5zaWduZWQgc2VsX25lbHRzX3Blcl9wYXR0ZXJuID0gc2VsLmVuY29kaW5nICgpLm5lbHRzX3Bl cl9wYXR0ZXJuICgpOworCisgIGlmICghKHBvdzJwX2h3aSAoc2VsX25wYXR0ZXJucykKKwkmJiBw b3cycF9od2kgKFZFQ1RPUl9DU1RfTlBBVFRFUk5TIChhcmcwKSkKKwkmJiBwb3cycF9od2kgKFZF Q1RPUl9DU1RfTlBBVFRFUk5TIChhcmcxKSkpKQorICAgIHsKKyAgICAgIGlmIChyZWFzb24pCisJ c3RyY3B5IChyZWFzb24sICJucGF0dGVybnMgaXMgbm90IHBvd2VyIG9mIDIiKTsKKyAgICAgIHJl dHVybiBmYWxzZTsKKyAgICB9CisKKyAgLyogV2Ugd2FudCB0byBhdm9pZCBjYXNlcyB3aGVyZSBz ZWwubGVuZ3RoIGlzIG5vdCBhIG11bHRpcGxlIG9mIG5wYXR0ZXJucy4KKyAgICAgRm9yIGVnOiBz ZWwubGVuZ3RoID0gMiArIDJ4LCBhbmQgc2VsIG5wYXR0ZXJucyA9IDQuICAqLworICBwb2x5X3Vp bnQ2NCBlc2VsOworICBpZiAoIW11bHRpcGxlX3AgKHNlbC5sZW5ndGggKCksIHNlbF9ucGF0dGVy bnMsICZlc2VsKSkKKyAgICB7CisgICAgICBpZiAocmVhc29uKQorCXN0cmNweSAocmVhc29uLCAi c2VsLmxlbmd0aCBpcyBub3QgbXVsdGlwbGUgb2Ygc2VsX25wYXR0ZXJucyIpOworICAgICAgcmV0 dXJuIGZhbHNlOworICAgIH0KKworICBpZiAoc2VsX25lbHRzX3Blcl9wYXR0ZXJuIDwgMykKKyAg ICByZXR1cm4gdHJ1ZTsKKworICBmb3IgKHVuc2lnbmVkIHBhdHRlcm4gPSAwOyBwYXR0ZXJuIDwg c2VsX25wYXR0ZXJuczsgcGF0dGVybisrKQorICAgIHsKKyAgICAgIHBvbHlfdWludDY0IGExID0g c2VsW3BhdHRlcm4gKyBzZWxfbnBhdHRlcm5zXTsKKyAgICAgIHBvbHlfdWludDY0IGEyID0gc2Vs W3BhdHRlcm4gKyAyICogc2VsX25wYXR0ZXJuc107CisgICAgICBwb2x5X3VpbnQ2NCBzdGVwID0g YTIgLSBhMTsKKyAgICAgIGlmICghc3RlcC5pc19jb25zdGFudCAoKSkKKwl7CisJICBpZiAocmVh c29uKQorCSAgICBzdHJjcHkgKHJlYXNvbiwgInN0ZXAgaXMgbm90IGNvbnN0YW50Iik7CisJICBy ZXR1cm4gZmFsc2U7CisJfQorICAgICAgSE9TVF9XSURFX0lOVCBTID0gc3RlcC50b19jb25zdGFu dCAoKTsKKworICAgICAgLy8gRklYTUU6IFB1bnQgb24gUyA8IDAgZm9yIG5vdywgcmV2aXNpdCBs YXRlci4KKyAgICAgIGlmIChTIDwgMCkKKwlyZXR1cm4gZmFsc2U7CisgICAgICBpZiAoUyA9PSAw KQorCWNvbnRpbnVlOworCisgICAgICBpZiAoIXBvdzJwX2h3aSAoUykpCisJeworCSAgaWYgKHJl YXNvbikKKwkgICAgc3RyY3B5IChyZWFzb24sICJzdGVwIGlzIG5vdCBwb3dlciBvZiAyIik7CisJ ICByZXR1cm4gZmFsc2U7CisJfQorCisgICAgICAvKiBFbnN1cmUgdGhhdCBzdGVwcGVkIHNlcXVl bmNlIG9mIHRoZSBwYXR0ZXJuIHNlbGVjdHMgZWxlbWVudHMKKwkgb25seSBmcm9tIHRoZSBzYW1l IGlucHV0IHZlY3RvciBpZiBpdCdzIFZMQS4gICovCisgICAgICB1aW50NjRfdCBxMSwgcWU7Cisg ICAgICBwb2x5X3VpbnQ2NCByMSwgcmU7CisgICAgICBwb2x5X3VpbnQ2NCBhZSA9IGExICsgKGVz ZWwgLSAyKSAqIFM7CisgICAgICBwb2x5X3VpbnQ2NCBhcmdfbGVuID0gVFlQRV9WRUNUT1JfU1VC UEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisgICAgICBpZiAoIShjYW5fZGl2X3RydW5jX3Ag KGExLCBhcmdfbGVuLCAmcTEsICZyMSkKKwkgICAgJiYgY2FuX2Rpdl90cnVuY19wIChhZSwgYXJn X2xlbiwgJnFlLCAmcmUpCisJICAgICYmIHExID09IHFlKSkKKwl7CisJICBpZiAocmVhc29uKQor CSAgICBzdHJjcHkgKHJlYXNvbiwgImNyb3NzZWQgaW5wdXQgdmVjdG9ycyIpOworCSAgcmV0dXJu IGZhbHNlOworCX0KKworICAgICAgdW5zaWduZWQgYXJnX25wYXR0ZXJucworCT0gKChxMSAmIDAp ID09IDApID8gVkVDVE9SX0NTVF9OUEFUVEVSTlMgKGFyZzApCisJCQkgIDogVkVDVE9SX0NTVF9O UEFUVEVSTlMgKGFyZzEpOworCisgICAgICBpZiAoIW11bHRpcGxlX3AgKFMsIGFyZ19ucGF0dGVy bnMpKQorCXsKKwkgIGlmIChyZWFzb24pCisJICAgIHN0cmNweSAocmVhc29uLCAiUyBpcyBub3Qg bXVsdGlwbGUgb2YgbnBhdHRlcm5zIik7CisJICByZXR1cm4gZmFsc2U7CisJfQorICAgIH0KKwor ICByZXR1cm4gdHJ1ZTsKK30KKworLyogVHJ5IHRvIGZvbGQgcGVybXV0YXRpb24gb2YgQVJHMCBh bmQgQVJHMSB3aXRoIFNFTCBzZWxlY3RvciB3aGVuCisgICB0aGUgaW5wdXQgdmVjdG9ycyBhcmUg VkVDVE9SX0NTVC4gUmV0dXJuIE5VTExfVFJFRSBvdGhlcndpc2UuCisgICBSRUFTT04gYW5kIFZF UkJPU0UgaGF2ZSBzYW1lIHB1cnBvc2UgYXMgZGVzY3JpYmVkIGluCisgICB2YWxpZF9tYXNrX2Zv cl9mb2xkX3ZlY19wZXJtX2NzdF9wLgorCisgICAoMSkgSWYgU0VMIGlzIGEgc3VpdGFibGUgbWFz ayBhcyBkZXRlcm1pbmVkIGJ5CisgICAgICAgdmFsaWRfbWFza19mb3JfZm9sZF92ZWNfcGVybV9j c3RfcCwgdGhlbjoKKyAgICAgICByZXNfbnBhdHRlcm5zID0gbWF4IG9mIG5wYXR0ZXJucyBiZXR3 ZWVuIEFSRzAsIEFSRzEsIGFuZCBTRUwKKyAgICAgICByZXNfbmVsdHNfcGVyX3BhdHRlcm4gPSBt YXggb2YgbmVsdHNfcGVyX3BhdHRlcm4gYmV0d2VlbgorCQkJICAgICAgIEFSRzAsIEFSRzEgYW5k IFNFTC4KKyAgICgyKSBJZiBTRUwgaXMgbm90IGEgc3VpdGFibGUgbWFzaywgYW5kIEFSRzAsIEFS RzEgYXJlIFZMUywKKyAgICAgICB0aGVuOgorICAgICAgIHJlc19ucGF0dGVybnMgPSBuZWx0cyBp biBpbnB1dCB2ZWN0b3IuCisgICAgICAgcmVzX25lbHRzX3Blcl9wYXR0ZXJuID0gMS4KKyAgICAg ICBUaGlzIGV4Y2VwdGlvbiBpcyBtYWRlIHNvIHRoYXQgVkxTIEFSRzAsIEFSRzEgYW5kIFNFTCB3 b3JrIGFzIGJlZm9yZS4gICovCisKK3N0YXRpYyB0cmVlCitmb2xkX3ZlY19wZXJtX2NzdCAodHJl ZSB0eXBlLCB0cmVlIGFyZzAsIHRyZWUgYXJnMSwgY29uc3QgdmVjX3Blcm1faW5kaWNlcyAmc2Vs LAorCQkgICBjaGFyICpyZWFzb24gPSBOVUxMLCBib29sIHZlcmJvc2UgPSBmYWxzZSkKK3sKKyAg dW5zaWduZWQgcmVzX25wYXR0ZXJucywgcmVzX25lbHRzX3Blcl9wYXR0ZXJuOworICB1bnNpZ25l ZCBIT1NUX1dJREVfSU5UIGFyZ19uZWx0czsKKworICBpZiAodmFsaWRfbWFza19mb3JfZm9sZF92 ZWNfcGVybV9jc3RfcCAoYXJnMCwgYXJnMSwgc2VsLCByZWFzb24sIHZlcmJvc2UpKQorICAgIHsK KyAgICAgIHJlc19ucGF0dGVybnMKKwk9IHN0ZDo6bWF4IChWRUNUT1JfQ1NUX05QQVRURVJOUyAo YXJnMCksCisJCSAgICBzdGQ6Om1heCAoVkVDVE9SX0NTVF9OUEFUVEVSTlMgKGFyZzEpLAorCQkJ ICAgICAgc2VsLmVuY29kaW5nICgpLm5wYXR0ZXJucyAoKSkpOworCisgICAgICByZXNfbmVsdHNf cGVyX3BhdHRlcm4KKwk9IHN0ZDo6bWF4IChWRUNUT1JfQ1NUX05FTFRTX1BFUl9QQVRURVJOIChh cmcwKSwKKwkJICAgIHN0ZDo6bWF4IChWRUNUT1JfQ1NUX05FTFRTX1BFUl9QQVRURVJOIChhcmcx KSwKKwkJCSAgICAgIHNlbC5lbmNvZGluZyAoKS5uZWx0c19wZXJfcGF0dGVybiAoKSkpOworICAg IH0KKyAgZWxzZSBpZiAoVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpLmlz X2NvbnN0YW50ICgmYXJnX25lbHRzKSkKKyAgICB7CisgICAgICByZXNfbnBhdHRlcm5zID0gYXJn X25lbHRzOworICAgICAgcmVzX25lbHRzX3Blcl9wYXR0ZXJuID0gMTsKKyAgICB9CisgIGVsc2UK KyAgICByZXR1cm4gTlVMTF9UUkVFOworCisgIHRyZWVfdmVjdG9yX2J1aWxkZXIgb3V0X2VsdHMg KHR5cGUsIHJlc19ucGF0dGVybnMsIHJlc19uZWx0c19wZXJfcGF0dGVybik7CisgIHVuc2lnbmVk IHJlc19uZWx0cyA9IHJlc19ucGF0dGVybnMgKiByZXNfbmVsdHNfcGVyX3BhdHRlcm47CisgIGZv ciAodW5zaWduZWQgaSA9IDA7IGkgPCByZXNfbmVsdHM7IGkrKykKKyAgICB7CisgICAgICBwb2x5 X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7Cisg ICAgICB1aW50NjRfdCBxOworICAgICAgcG9seV91aW50NjQgcjsKKyAgICAgIHVuc2lnbmVkIEhP U1RfV0lERV9JTlQgaW5kZXg7CisKKyAgICAgIGlmIChUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJF RV9UWVBFIChhcmcwKSkuaXNfY29uc3RhbnQgKCZhcmdfbmVsdHMpCisJICAmJiBrbm93bl9nZSAo c2VsW2ldLCAyICogYXJnX25lbHRzKSkKKwl7CisJICBpZiAocmVhc29uKQorCSAgICBzdHJjcHkg KHJlYXNvbiwgIm91dCBvZiBib3VuZHMgYWNjZXNzIik7CisJICByZXR1cm4gTlVMTF9UUkVFOwor CX0KKworICAgICAgLyogUHVudCBpZiBzZWxbaV0gL3RydW5jX2RpdiBsZW4gY2Fubm90IGJlIGRl dGVybWluZWQsCisJIGJlY2F1c2UgdGhlIGlucHV0IHZlY3RvciB0byBiZSBjaG9zZW4gd2lsbCBk ZXBlbmQgb24KKwkgcnVudGltZSB2ZWN0b3IgbGVuZ3RoLgorCSBGb3IgZXhhbXBsZSBpZiBsZW4g PT0gNCArIDR4LCBhbmQgc2VsW2ldID09IDQsCisJIElmIGxlbiBhdCBydW50aW1lIGVxdWFscyA0 LCB3ZSBjaG9vc2UgYXJnMVswXS4KKwkgRm9yIGFueSBvdGhlciB2YWx1ZSBvZiBsZW4gPiA0IGF0 IHJ1bnRpbWUsIHdlIGNob29zZSBhcmcwWzRdLgorCSB3aGljaCBtYWtlcyB0aGUgZWxlbWVudCBj aG9pY2UgZGVwZW5kZW50IG9uIHJ1bnRpbWUgdmVjdG9yIGxlbmd0aC4gICovCisgICAgICBpZiAo IWNhbl9kaXZfdHJ1bmNfcCAoc2VsW2ldLCBsZW4sICZxLCAmcikpCisJeworCSAgaWYgKHJlYXNv bikKKwkgICAgc3RyY3B5IChyZWFzb24sICJjYW5ub3QgZGl2aWRlIHNlbGVjdG9yIGVsZW1lbnQg YnkgYXJnIGxlbiIpOworCSAgcmV0dXJuIE5VTExfVFJFRTsKKwl9CisKKyAgICAgIC8qIHNlbFtp XSAlIGxlbiB3aWxsIGdpdmUgdGhlIGluZGV4IG9mIGVsZW1lbnQgaW4gdGhlIGNob3NlbiBpbnB1 dAorCSB2ZWN0b3IuIEZvciBleGFtcGxlIGlmIHNlbFtpXSA9PSA1ICsgNHggYW5kIGxlbiA9PSA0 ICsgNHgsCisJIHdlIHdpbGwgY2hvb3NlIGFyZzFbMV0gc2luY2UgKDUgKyA0eCkgJSAoNCArIDR4 KSA9PSAxLiAgKi8KKyAgICAgIGlmICghci5pc19jb25zdGFudCAoJmluZGV4KSkKKwl7CisJICBp ZiAocmVhc29uKQorCSAgICBzdHJjcHkgKHJlYXNvbiwgInJlbWFpbmRlciBpcyBub3QgY29uc3Rh bnQiKTsKKwkgIHJldHVybiBOVUxMX1RSRUU7CisJfQorCisgICAgICB0cmVlIGFyZyA9ICgocSAm IDEpID09IDApID8gYXJnMCA6IGFyZzE7CisgICAgICB0cmVlIGVsZW0gPSB2ZWN0b3JfY3N0X2Vs dCAoYXJnLCBpbmRleCk7CisgICAgICBvdXRfZWx0cy5xdWlja19wdXNoIChlbGVtKTsKKyAgICB9 CisKKyAgcmV0dXJuIG91dF9lbHRzLmJ1aWxkICgpOworfQorCiAvKiBBdHRlbXB0IHRvIGZvbGQg dmVjdG9yIHBlcm11dGF0aW9uIG9mIEFSRzAgYW5kIEFSRzEgdmVjdG9ycyB1c2luZyBTRUwKICAg IHNlbGVjdG9yLiAgUmV0dXJuIHRoZSBmb2xkZWQgVkVDVE9SX0NTVCBvciBDT05TVFJVQ1RPUiBp ZiBzdWNjZXNzZnVsLAogICAgTlVMTF9UUkVFIG90aGVyd2lzZS4gICovCkBAIC0xMDUyOSw0MyAr MTA3MTMsNDAgQEAgZm9sZF92ZWNfcGVybSAodHJlZSB0eXBlLCB0cmVlIGFyZzAsIHRyZWUgYXJn MSwgY29uc3QgdmVjX3Blcm1faW5kaWNlcyAmc2VsKQogewogICB1bnNpZ25lZCBpbnQgaTsKICAg dW5zaWduZWQgSE9TVF9XSURFX0lOVCBuZWx0czsKLSAgYm9vbCBuZWVkX2N0b3IgPSBmYWxzZTsK IAotICBpZiAoIXNlbC5sZW5ndGggKCkuaXNfY29uc3RhbnQgKCZuZWx0cykpCi0gICAgcmV0dXJu IE5VTExfVFJFRTsKLSAgZ2NjX2Fzc2VydCAoa25vd25fZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRT ICh0eXBlKSwgbmVsdHMpCi0JICAgICAgJiYga25vd25fZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRT IChUUkVFX1RZUEUgKGFyZzApKSwgbmVsdHMpCi0JICAgICAgJiYga25vd25fZXEgKFRZUEVfVkVD VE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzEpKSwgbmVsdHMpKTsKKyAgZ2NjX2Fzc2VydCAo a25vd25fZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRTICh0eXBlKSwgc2VsLmxlbmd0aCAoKSkKKwkg ICAgICAmJiBrbm93bl9lcSAoVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkp LAorCQkJICAgVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMSkpKSk7CisKICAg aWYgKFRSRUVfVFlQRSAoVFJFRV9UWVBFIChhcmcwKSkgIT0gVFJFRV9UWVBFICh0eXBlKQogICAg ICAgfHwgVFJFRV9UWVBFIChUUkVFX1RZUEUgKGFyZzEpKSAhPSBUUkVFX1RZUEUgKHR5cGUpKQog ICAgIHJldHVybiBOVUxMX1RSRUU7CiAKKyAgaWYgKFRSRUVfQ09ERSAoYXJnMCkgPT0gVkVDVE9S X0NTVAorICAgICAgJiYgVFJFRV9DT0RFIChhcmcxKSA9PSBWRUNUT1JfQ1NUKQorICAgIHJldHVy biBmb2xkX3ZlY19wZXJtX2NzdCAodHlwZSwgYXJnMCwgYXJnMSwgc2VsKTsKKworICAvKiBGb3Ig ZmFsbCBiYWNrIGNhc2UsIHdlIHdhbnQgdG8gZW5zdXJlIHdlIGhhdmUgVkxTIHZlY3RvcnMKKyAg ICAgd2l0aCBlcXVhbCBsZW5ndGguICAqLworICBpZiAoIXNlbC5sZW5ndGggKCkuaXNfY29uc3Rh bnQgKCZuZWx0cykpCisgICAgcmV0dXJuIE5VTExfVFJFRTsKKworICBnY2NfYXNzZXJ0IChrbm93 bl9lcSAoc2VsLmxlbmd0aCAoKSwgVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJn MCkpKSk7CiAgIHRyZWUgKmluX2VsdHMgPSBYQUxMT0NBVkVDICh0cmVlLCBuZWx0cyAqIDIpOwog ICBpZiAoIXZlY19jc3RfY3Rvcl90b19hcnJheSAoYXJnMCwgbmVsdHMsIGluX2VsdHMpCiAgICAg ICB8fCAhdmVjX2NzdF9jdG9yX3RvX2FycmF5IChhcmcxLCBuZWx0cywgaW5fZWx0cyArIG5lbHRz KSkKICAgICByZXR1cm4gTlVMTF9UUkVFOwogCi0gIHRyZWVfdmVjdG9yX2J1aWxkZXIgb3V0X2Vs dHMgKHR5cGUsIG5lbHRzLCAxKTsKKyAgdmVjPGNvbnN0cnVjdG9yX2VsdCwgdmFfZ2M+ICp2Owor ICB2ZWNfYWxsb2MgKHYsIG5lbHRzKTsKICAgZm9yIChpID0gMDsgaSA8IG5lbHRzOyBpKyspCiAg ICAgewogICAgICAgSE9TVF9XSURFX0lOVCBpbmRleDsKICAgICAgIGlmICghc2VsW2ldLmlzX2Nv bnN0YW50ICgmaW5kZXgpKQogCXJldHVybiBOVUxMX1RSRUU7Ci0gICAgICBpZiAoIUNPTlNUQU5U X0NMQVNTX1AgKGluX2VsdHNbaW5kZXhdKSkKLQluZWVkX2N0b3IgPSB0cnVlOwotICAgICAgb3V0 X2VsdHMucXVpY2tfcHVzaCAodW5zaGFyZV9leHByIChpbl9lbHRzW2luZGV4XSkpOwotICAgIH0K LQotICBpZiAobmVlZF9jdG9yKQotICAgIHsKLSAgICAgIHZlYzxjb25zdHJ1Y3Rvcl9lbHQsIHZh X2djPiAqdjsKLSAgICAgIHZlY19hbGxvYyAodiwgbmVsdHMpOwotICAgICAgZm9yIChpID0gMDsg aSA8IG5lbHRzOyBpKyspCi0JQ09OU1RSVUNUT1JfQVBQRU5EX0VMVCAodiwgTlVMTF9UUkVFLCBv dXRfZWx0c1tpXSk7Ci0gICAgICByZXR1cm4gYnVpbGRfY29uc3RydWN0b3IgKHR5cGUsIHYpOwor ICAgICAgQ09OU1RSVUNUT1JfQVBQRU5EX0VMVCAodiwgTlVMTF9UUkVFLCBpbl9lbHRzW2luZGV4 XSk7CiAgICAgfQotICBlbHNlCi0gICAgcmV0dXJuIG91dF9lbHRzLmJ1aWxkICgpOworICByZXR1 cm4gYnVpbGRfY29uc3RydWN0b3IgKHR5cGUsIHYpOwogfQogCiAvKiBUcnkgdG8gZm9sZCBhIHBv aW50ZXIgZGlmZmVyZW5jZSBvZiB0eXBlIFRZUEUgdHdvIGFkZHJlc3MgZXhwcmVzc2lvbnMgb2YK QEAgLTE2ODkyLDYgKzE3MDczLDUyOCBAQCB0ZXN0X2FyaXRobWV0aWNfZm9sZGluZyAoKQogCQkJ CSAgIHgpOwogfQogCituYW1lc3BhY2UgdGVzdF9mb2xkX3ZlY19wZXJtX2NzdCB7CisKK3N0YXRp YyB0cmVlCitnZXRfcHJlZmVycmVkX3ZlY3R5cGUgKHRyZWUgaW5uZXJfdHlwZSkKK3sKKyAgc2Nh bGFyX2ludF9tb2RlIGludF9tb2RlID0gU0NBTEFSX0lOVF9UWVBFX01PREUgKGlubmVyX3R5cGUp OworICBtYWNoaW5lX21vZGUgdm1vZGUgPSB0YXJnZXRtLnZlY3Rvcml6ZS5wcmVmZXJyZWRfc2lt ZF9tb2RlIChpbnRfbW9kZSk7CisgIHBvbHlfdWludDY0IG51bml0cyA9IEdFVF9NT0RFX05VTklU UyAodm1vZGUpOworICByZXR1cm4gYnVpbGRfdmVjdG9yX3R5cGUgKGlubmVyX3R5cGUsIG51bml0 cyk7Cit9CisKK3N0YXRpYyB0cmVlCitidWlsZF92ZWNfY3N0X3JhbmQgKHRyZWUgaW5uZXJfdHlw ZSwgdW5zaWduZWQgbnBhdHRlcm5zLAorCQkgICAgdW5zaWduZWQgbmVsdHNfcGVyX3BhdHRlcm4s IGludCBTID0gMCwKKwkJICAgIHRyZWUgdmVjdHlwZSA9IE5VTExfVFJFRSkKK3sKKyAgaWYgKCF2 ZWN0eXBlKQorICAgIHZlY3R5cGUgPSBnZXRfcHJlZmVycmVkX3ZlY3R5cGUgKGlubmVyX3R5cGUp OworICB0cmVlX3ZlY3Rvcl9idWlsZGVyIGJ1aWxkZXIgKHZlY3R5cGUsIG5wYXR0ZXJucywgbmVs dHNfcGVyX3BhdHRlcm4pOworCisgIC8vIEZpbGwgYTAgZm9yIGVhY2ggcGF0dGVybgorICBmb3Ig KHVuc2lnbmVkIGkgPSAwOyBpIDwgbnBhdHRlcm5zOyBpKyspCisgICAgYnVpbGRlci5xdWlja19w dXNoIChidWlsZF9pbnRfY3N0IChpbm5lcl90eXBlLCByYW5kICgpICUgMTAwKSk7CisKKyAgaWYg KG5lbHRzX3Blcl9wYXR0ZXJuID09IDEpCisgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGQgKCk7CisK KyAgLy8gRmlsbCBhMSBmb3IgZWFjaCBwYXR0ZXJuCisgIGZvciAodW5zaWduZWQgaSA9IDA7IGkg PCBucGF0dGVybnM7IGkrKykKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGJ1aWxkX2ludF9jc3Qg KGlubmVyX3R5cGUsIHJhbmQgKCkgJSAxMDApKTsKKworICBpZiAobmVsdHNfcGVyX3BhdHRlcm4g PT0gMikKKyAgICByZXR1cm4gYnVpbGRlci5idWlsZCAoKTsKKworICBmb3IgKHVuc2lnbmVkIGkg PSBucGF0dGVybnMgKiAyOyBpIDwgbnBhdHRlcm5zICogbmVsdHNfcGVyX3BhdHRlcm47IGkrKykK KyAgICB7CisgICAgICB0cmVlIHByZXZfZWxlbSA9IGJ1aWxkZXJbaSAtIG5wYXR0ZXJuc107Cisg ICAgICBpbnQgcHJldl9lbGVtX3ZhbCA9IFRSRUVfSU5UX0NTVF9MT1cgKHByZXZfZWxlbSk7Cisg ICAgICBpbnQgdmFsID0gcHJldl9lbGVtX3ZhbCArIFM7CisgICAgICBidWlsZGVyLnF1aWNrX3B1 c2ggKGJ1aWxkX2ludF9jc3QgKGlubmVyX3R5cGUsIHZhbCkpOworICAgIH0KKworICByZXR1cm4g YnVpbGRlci5idWlsZCAoKTsKK30KKworc3RhdGljIHZvaWQKK3ZhbGlkYXRlX3JlcyAodW5zaWdu ZWQgbnBhdHRlcm5zLCB1bnNpZ25lZCBuZWx0c19wZXJfcGF0dGVybiwKKwkgICAgICB0cmVlIHJl cywgdHJlZSAqZXhwZWN0ZWRfcmVzKQoreworICBBU1NFUlRfVFJVRSAoVkVDVE9SX0NTVF9OUEFU VEVSTlMgKHJlcykgPT0gbnBhdHRlcm5zKTsKKyAgQVNTRVJUX1RSVUUgKFZFQ1RPUl9DU1RfTkVM VFNfUEVSX1BBVFRFUk4gKHJlcykgPT0gbmVsdHNfcGVyX3BhdHRlcm4pOworCisgIGZvciAodW5z aWduZWQgaSA9IDA7IGkgPCB2ZWN0b3JfY3N0X2VuY29kZWRfbmVsdHMgKHJlcyk7IGkrKykKKyAg ICBBU1NFUlRfVFJVRSAob3BlcmFuZF9lcXVhbF9wIChWRUNUT1JfQ1NUX0VMVCAocmVzLCBpKSwg ZXhwZWN0ZWRfcmVzW2ldLCAwKSk7Cit9CisKK3N0YXRpYyB2b2lkCit2YWxpZGF0ZV9yZXNfdmxz ICh0cmVlIHJlcywgdHJlZSAqZXhwZWN0ZWRfcmVzLCB1bnNpZ25lZCBleHBlY3RlZF9uZWx0cykK K3sKKyAgQVNTRVJUX1RSVUUgKGtub3duX2VxIChWRUNUT1JfQ1NUX05FTFRTIChyZXMpLCBleHBl Y3RlZF9uZWx0cykpOworICBmb3IgKHVuc2lnbmVkIGkgPSAwOyBpIDwgZXhwZWN0ZWRfbmVsdHM7 IGkrKykKKyAgICBBU1NFUlRfVFJVRSAob3BlcmFuZF9lcXVhbF9wIChWRUNUT1JfQ1NUX0VMVCAo cmVzLCBpKSwgZXhwZWN0ZWRfcmVzW2ldLCAwKSk7Cit9CisKKy8qIFZlcmlmeSBWTEEgdmVjX3Bl cm0gZm9sZGluZy4gICovCisKK3N0YXRpYyB2b2lkCit0ZXN0X3N0ZXBwZWQgKCkKK3sKKyAgLyog Q2FzZSAxOiBzZWwgPSB7MCwgMSwgMiwgLi4ufQorICAgICBucGF0dGVybnMgPSAxLCBuZWx0c19w ZXJfcGF0dGVybiA9IDMgICovCisgIHsKKyAgICB0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3Jh bmQgKGNoYXJfdHlwZV9ub2RlLCAxLCAzLCAyKTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNf Y3N0X3JhbmQgKGNoYXJfdHlwZV9ub2RlLCAxLCAzLCAyKTsKKyAgICBwb2x5X3VpbnQ2NCBhcmcw X2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworICAgIHZl Y19wZXJtX2J1aWxkZXIgYnVpbGRlciAoYXJnMF9sZW4sIDEsIDMpOworICAgIGJ1aWxkZXIucXVp Y2tfcHVzaCAoMCk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgxKTsKKyAgICBidWlsZGVyLnF1 aWNrX3B1c2ggKDIpOworCisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGFy ZzBfbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFy ZzApLCBhcmcwLCBhcmcxLCBzZWwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rv cl9jc3RfZWx0IChhcmcwLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDEpLAorCQkJICAgIHZl Y3Rvcl9jc3RfZWx0IChhcmcwLCAyKSB9OworICAgIHZhbGlkYXRlX3JlcyAoMSwgMywgcmVzLCBl eHBlY3RlZF9yZXMpOworICB9CisKKyNpZiAwCisgIC8qIENhc2UgMjogc2VsID0ge2xlbiwgbGVu ICsgMSwgbGVuICsgMiwgLi4uIH0KKyAgICAgbnBhdHRlcm5zID0gMSwgbmVsdHNfcGVyX3BhdHRl cm4gPSAzCisgICAgIEZJWE1FOiBUaGlzIHNob3VsZCByZXR1cm4KKyAgICAgZXhwZWN0ZWQgcmVz OiB7IG9wMVswXSwgb3AxWzFdLCBvcDFbMl0sIC4uLiB9CisgICAgIGhvd2V2ZXIgaXQgcmV0dXJu cyBOVUxMX1RSRUUuICAqLworICB7CisgICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChhcmcw X2xlbiwgMSwgMyk7CisgICAgYnVpbGRlci5xdWlja19wdXNoIChhcmcwX2xlbik7CisgICAgYnVp bGRlci5xdWlja19wdXNoIChhcmcwX2xlbiArIDEpOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAo YXJnMF9sZW4gKyAyKTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBh cmcwX2xlbik7CisgICAgdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChh cmcwKSwgYXJnMCwgYXJnMSwgc2VsKTsKKyAgfQorI2VuZGlmCisKKyAgLyogQ2FzZSAzOiBMZWFk aW5nIGVsZW1lbnQgb2YgYXJnMSwgc3RlcHBlZCBzZXF1ZW5jZTogcGF0dGVybiAwIG9mIGFyZzAu CisgICAgIHNlbCA9IHtsZW4sIDAsIDAsIDAsIDIsIDAsIC4uLn0KKyAgICAgbnBhdHRlcm5zID0g MiwgbmVsdHNfcGVyX3BhdHRlcm4gPSAzLgorICAgICBVc2UgZXh0cmEgcGF0dGVybiB7MCwgLi4u fSB0byBsb3dlciBudW1iZXIgb2YgZWxlbWVudHMgcGVyIHBhdHRlcm4uICAqLworICB7CisgICAg dHJlZSBhcmcwID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwgMSwgMywgMik7 CisgICAgdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwgMSwg MywgMik7CisgICAgcG9seV91aW50NjQgYXJnMF9sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAo VFJFRV9UWVBFIChhcmcwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGFyZzBf bGVuLCAyLCAzKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGFyZzBfbGVuKTsKKyAgICBpbnQg bWFza19lbGVtc1tdID0geyAwLCAwLCAwLCAyLCAwIH07CisgICAgZm9yIChpbnQgaSA9IDA7IGkg PCA1OyBpKyspCisgICAgICBidWlsZGVyLnF1aWNrX3B1c2ggKG1hc2tfZWxlbXNbaV0pOworCisg ICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGFyZzBfbGVuKTsKKyAgICBjaGFy IHJlYXNvblsxMDBdID0gIlwwIjsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChU UkVFX1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBzZWwsIHJlYXNvbik7CisKKyAgICB0cmVlIGV4 cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJnMSwgMCksIHZlY3Rvcl9jc3RfZWx0 IChhcmcwLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCksIHZlY3Rvcl9jc3Rf ZWx0IChhcmcwLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMiksIHZlY3Rvcl9j c3RfZWx0IChhcmcwLCAwKQorCQkJICB9OworICAgIHZhbGlkYXRlX3JlcyAoMiwgMywgcmVzLCBl eHBlY3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSA0OgorICAgICBzZWwgPSB7IGxlbiwgMCwg MiwgLi4uIH0gbnBhdHRlcm5zID0gMSwgbmVsdHNfcGVyX3BhdHRlcm4gPSAzLgorICAgICBUaGlz IHNob3VsZCByZXR1cm4gTlVMTCBiZWNhdXNlIHdlIGNyb3NzIHRoZSBpbnB1dCB2ZWN0b3JzLgor ICAgICBCZWNhdXNlLAorICAgICBhcmcwX2xlbiA9IDE2ICsgMTZ4CisgICAgIGExID0gMAorICAg ICBTID0gMgorICAgICBlc2VsID0gYXJnMF9sZW4gLyBucGF0dGVybnNfc2VsID0gMTYrMTZ4LzEg PSAxNiArIDE2eAorICAgICBhZSA9IDAgKyAoZXNlbCAtIDIpICogUworCT0gMCArICgxNiArIDE2 eCAtIDIpICogMgorCT0gMjggKyAzMngKKyAgICAgYTEgLyBhcmcwX2xlbiA9IDAgL3RydW5jICgx NiArIDE2eCkgPSAwCisgICAgIGFlIC8gYXJnMF9sZW4gPSAoMjggKyAzMngpIC90cnVuYyAoMTYg KyAxNngpLCB3aGljaCBpcyBub3QgZGVmaW5lZCwKKyAgICAgc2luY2UgMjgvMTYgIT0gMzIvMTYu CisgICAgIFNvIHJldHVybiBOVUxMX1RSRUUuICAqLworICB7CisgICAgdHJlZSBhcmcwID0gYnVp bGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwgMSwgMywgMik7CisgICAgdHJlZSBhcmcx ID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwgMSwgMywgMik7CisgICAgcG9s eV91aW50NjQgYXJnMF9sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcw KSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGFyZzBfbGVuLCAxLCAzKTsKKyAg ICBidWlsZGVyLnF1aWNrX3B1c2ggKGFyZzBfbGVuKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2gg KDApOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoMik7CisKKyAgICB2ZWNfcGVybV9pbmRpY2Vz IHNlbCAoYnVpbGRlciwgMiwgYXJnMF9sZW4pOworICAgIGNoYXIgcmVhc29uWzEwMF0gPSAiXDAi OworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFy ZzAsIGFyZzEsIHNlbCwgcmVhc29uLCBmYWxzZSk7CisgICAgZ2NjX2Fzc2VydCAocmVzID09IE5V TExfVFJFRSk7CisgICAgZ2NjX2Fzc2VydCAoIXN0cmNtcCAocmVhc29uLCAiY3Jvc3NlZCBpbnB1 dCB2ZWN0b3JzIikpOworICB9CisKKyAgLyogQ2FzZSA1OiBTZWxlY3QgZWxlbWVudHMgZnJvbSBk aWZmZXJlbnQgcGF0dGVybnMuCisgICAgIFNob3VsZCByZXR1cm4gTlVMTC4gICovCisgIHsKKyAg ICB0cmVlIG9wMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAoY2hhcl90eXBlX25vZGUsIDIsIDMsIDIp OworICAgIHRyZWUgb3AxID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwgMiwg MywgMik7CisgICAgcG9seV91aW50NjQgb3AwX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChU UkVFX1RZUEUgKG9wMCkpOworCisgICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChvcDBfbGVu LCAyLCAzKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKG9wMF9sZW4pOworICAgIGludCBtYXNr X2VsZW1zW10gPSB7IDAsIDAsIDAsIDEsIDAgfTsKKyAgICBmb3IgKGludCBpID0gMDsgaSA8IDU7 IGkrKykKKyAgICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAobWFza19lbGVtc1tpXSk7CisKKyAgICB2 ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgb3AwX2xlbik7CisgICAgY2hhciByZWFz b25bMTAwXSA9ICJcMCI7CisgICAgdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9U WVBFIChvcDApLCBvcDAsIG9wMSwgc2VsLCByZWFzb24sIGZhbHNlKTsKKyAgICBnY2NfYXNzZXJ0 IChyZXMgPT0gTlVMTF9UUkVFKTsKKyAgICBnY2NfYXNzZXJ0ICghc3RyY21wIChyZWFzb24sICJT IGlzIG5vdCBtdWx0aXBsZSBvZiBucGF0dGVybnMiKSk7CisgIH0KKworICAvKiBDYXNlIDY6IFNl bGVjdCBwYXR0ZXJuIDAgb2Ygb3AwIGFuZCBkdXAgb2Ygb3AwWzBdCisgICAgIG9wMCwgb3AxLCBz ZWw6IG5wYXR0ZXJucyA9IDIsIG5lbHRzX3Blcl9wYXR0ZXJuID0gMworICAgICBzZWwgPSB7IDAs IDAsIDIsIDAsIDQsIDAsIC4uLiB9LgorCisgICAgIEZvciBwYXR0ZXJuIHswLCAyLCA0LCAuLi59 OgorICAgICBhMSA9IDIKKyAgICAgbGVuID0gMTYgKyAxNngKKyAgICAgUyA9IDIKKyAgICAgZXNl bCA9IGxlbiAvIG5wYXR0ZXJuc19zZWwgPSAoMTYgKyAxNngpIC8gMiA9ICg4ICsgOHgpCisgICAg IGFlID0gYTEgKyAoZXNlbCAtIDIpICogUworCT0gMiArICg4ICsgOHggLSAyKSAqIDIKKwk9IDE0 ICsgMTZ4CisgICAgIGExIC8gYXJnMF9sZW4gPSAyIC8gKDE2ICsgMTZ4KSA9IDAKKyAgICAgYWUg LyBhcmcwX2xlbiA9ICgxNCArIDE2eCkgLyAoMTYgKyAxNngpID0gMAorICAgICBTbyBhMS9hcmcw X2xlbiA9IGFlL2FyZzBfbGVuID0gMAorICAgICBIZW5jZSB3ZSBzZWxlY3QgZnJvbSBmaXJzdCB2 ZWN0b3Igb3AwCisgICAgIFMgPSAyLCBucGF0dGVybnMgPSAyLgorICAgICBTaW5jZSBTIGlzIG11 bHRpcGxlIG9mIG5wYXR0ZXJucyhvcDApLCB3ZSBhcmUgc2VsZWN0aW5nIGZyb20KKyAgICAgc2Ft ZSBwYXR0ZXJuIG9mIG9wMC4KKworICAgICBGb3IgcGF0dGVybiB7MCwgLi4ufSwgd2UgYXJlIGNo b29zaW5nIHsgb3AwWzBdIC4uLiB9CisgICAgIFNvIHJlcyB3aWxsIGJlIGNvbWJpbmF0aW9uIG9m IGFib3ZlIHBhdHRlcm5zOgorICAgICByZXM6IHsgb3AwWzBdLCBvcDBbMF0sIG9wMFsyXSwgb3Aw WzBdLCBvcDBbNF0sIG9wMFswXSwgLi4uIH0KKyAgICAgd2l0aCBucGF0dGVybnMgPSAyLCBuZWx0 c19wZXJfcGF0dGVybiA9IDMuICAqLworICB7CisgICAgdHJlZSBvcDAgPSBidWlsZF92ZWNfY3N0 X3JhbmQgKGNoYXJfdHlwZV9ub2RlLCAyLCAzLCAyKTsKKyAgICB0cmVlIG9wMSA9IGJ1aWxkX3Zl Y19jc3RfcmFuZCAoY2hhcl90eXBlX25vZGUsIDIsIDMsIDIpOworICAgIHBvbHlfdWludDY0IG9w MF9sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChvcDApKTsKKworICAgIHZl Y19wZXJtX2J1aWxkZXIgYnVpbGRlciAob3AwX2xlbiwgMiwgMyk7CisgICAgaW50IG1hc2tfZWxl bXNbXSA9IHsgMCwgMCwgMiwgMCwgNCwgMCB9OworICAgIGZvciAoaW50IGkgPSAwOyBpIDwgNjsg aSsrKQorICAgICAgYnVpbGRlci5xdWlja19wdXNoIChtYXNrX2VsZW1zW2ldKTsKKworICAgIHZl Y19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBvcDBfbGVuKTsKKyAgICB0cmVlIHJlcyA9 IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKG9wMCksIG9wMCwgb3AxLCBzZWwpOworICAg IHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rvcl9jc3RfZWx0IChvcDAsIDApLCB2ZWN0b3Jf Y3N0X2VsdCAob3AwLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAob3AwLCAyKSwgdmVjdG9y X2NzdF9lbHQgKG9wMCwgMCksCisJCQkgICAgdmVjdG9yX2NzdF9lbHQgKG9wMCwgNCksIHZlY3Rv cl9jc3RfZWx0IChvcDAsIDApIH07CisgICAgdmFsaWRhdGVfcmVzICgyLCAzLCByZXMsIGV4cGVj dGVkX3Jlcyk7CisgIH0KKworICAvKiBDYXNlIDc6IHNlbF9ucGF0dGVybnMgPiBvcF9ucGF0dGVy bnM7CisgICAgIG9wMCwgb3AxOiBucGF0dGVybnMgPSAyLCBuZWx0c19wZXJfcGF0dGVybiA9IDMK KyAgICAgc2VsOiB7IDAsIDAsIDEsIGxlbiwgMiwgMCwgMywgbGVuLCA0LCAwLCA1LCBsZW4sIC4u Ln0sCisgICAgIHdpdGggbnBhdHRlcm5zID0gNCwgbmVsdHNfcGVyX3BhdHRlcm4gPSAzLiAgKi8K KyAgeworICAgIHRyZWUgb3AwID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwg MiwgMywgMik7CisgICAgdHJlZSBvcDEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGNoYXJfdHlwZV9u b2RlLCAyLCAzLCAyKTsKKyAgICBwb2x5X3VpbnQ2NCBvcDBfbGVuID0gVFlQRV9WRUNUT1JfU1VC UEFSVFMgKFRSRUVfVFlQRSAob3AwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIo b3AwX2xlbiwgNCwgMyk7CisgICAgLy8gLTEgaXMgdXNlZCBhcyBwbGFjZSBob2xkZXIgZm9yIHBv bHlfaW50X2NzdAorICAgIGludCBtYXNrX2VsZW1zW10gPSB7IDAsIDAsIDEsIC0xLCAyLCAwLCAz LCAtMSwgNCwgMCwgNSwgLTEgfTsKKyAgICBmb3IgKGludCBpID0gMDsgaSA8IDEyOyBpKyspCisg ICAgICBidWlsZGVyLnF1aWNrX3B1c2ggKChtYXNrX2VsZW1zW2ldID09IC0xKSA/IG9wMF9sZW4g OiBtYXNrX2VsZW1zW2ldKTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAy LCBvcDBfbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUg KG9wMCksIG9wMCwgb3AxLCBzZWwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rv cl9jc3RfZWx0IChvcDAsIDApLCB2ZWN0b3JfY3N0X2VsdCAob3AwLCAwKSwKKwkJCSAgICB2ZWN0 b3JfY3N0X2VsdCAob3AwLCAxKSwgdmVjdG9yX2NzdF9lbHQgKG9wMSwgMCksCisJCQkgICAgdmVj dG9yX2NzdF9lbHQgKG9wMCwgMiksIHZlY3Rvcl9jc3RfZWx0IChvcDAsIDApLAorCQkJICAgIHZl Y3Rvcl9jc3RfZWx0IChvcDAsIDMpLCB2ZWN0b3JfY3N0X2VsdCAob3AxLCAwKSwKKwkJCSAgICB2 ZWN0b3JfY3N0X2VsdCAob3AwLCA0KSwgdmVjdG9yX2NzdF9lbHQgKG9wMCwgMCksCisJCQkgICAg dmVjdG9yX2NzdF9lbHQgKG9wMCwgNSksIHZlY3Rvcl9jc3RfZWx0IChvcDEsIDApIH07CisgICAg dmFsaWRhdGVfcmVzICg0LCAzLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgIH0KK30KKworc3RhdGlj IHZvaWQKK3Rlc3RfZHVwICgpCit7CisgIC8qIENhc2UgMTogbWFzayA9IHswLCAuLi59ICovCisg IHsKKyAgICB0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2Rl LCAyLCAzLCAxKTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJf dHlwZV9ub2RlLCAyLCAzLCAxKTsKKyAgICBwb2x5X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9T VUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxk ZXIgKGxlbiwgMSwgMSk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgwKTsKKyAgICB2ZWNfcGVy bV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVj X3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBzZWwpOworCisgICAgdHJl ZSBleHBlY3RlZF9yZXNbXSA9IHsgdmVjdG9yX2NzdF9lbHQgKHJlcywgMCkgfTsKKyAgICB2YWxp ZGF0ZV9yZXMgKDEsIDEsIHJlcywgZXhwZWN0ZWRfcmVzKTsKKyAgfQorCisgIC8qIENhc2UgMjog bWFzayA9IHtsZW4sIC4uLn0gKi8KKyAgeworICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3Rf cmFuZCAoaW50ZWdlcl90eXBlX25vZGUsIDIsIDMsIDEpOworICAgIHRyZWUgYXJnMSA9IGJ1aWxk X3ZlY19jc3RfcmFuZCAoaW50ZWdlcl90eXBlX25vZGUsIDIsIDMsIDEpOworICAgIHBvbHlfdWlu dDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworICAg IHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAobGVuLCAxLCAxKTsKKyAgICBidWlsZGVyLnF1aWNr X3B1c2ggKGxlbik7CisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7 CisgICAgdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcwKSwgYXJn MCwgYXJnMSwgc2VsKTsKKworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rvcl9jc3Rf ZWx0IChhcmcxLCAwKSB9OworICAgIHZhbGlkYXRlX3JlcyAoMSwgMSwgcmVzLCBleHBlY3RlZF9y ZXMpOworICB9CisKKyAgLyogQ2FzZSAzOiBtYXNrID0geyAwLCBsZW4sIC4uLiB9ICovCisgIHsK KyAgICB0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAy LCAzLCAxKTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlw ZV9ub2RlLCAyLCAzLCAxKTsKKyAgICBwb2x5X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQ QVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIg KGxlbiwgMiwgMSk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgwKTsKKyAgICBidWlsZGVyLnF1 aWNrX3B1c2ggKGxlbik7CisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxl bik7CisgICAgdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcwKSwg YXJnMCwgYXJnMSwgc2VsKTsKKworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rvcl9j c3RfZWx0IChhcmcwLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDApIH07CisgICAgdmFsaWRh dGVfcmVzICgyLCAxLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgIH0KKworICAvKiBDYXNlIDQ6IG1h c2sgPSB7IDAsIGxlbiwgMSwgbGVuKzEsIC4uLiB9ICovCisgIHsKKyAgICB0cmVlIGFyZzAgPSBi dWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAxKTsKKyAgICB0cmVl IGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAxKTsK KyAgICBwb2x5X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChh cmcwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGxlbiwgMiwgMik7CisgICAg YnVpbGRlci5xdWlja19wdXNoICgwKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGxlbik7Cisg ICAgYnVpbGRlci5xdWlja19wdXNoICgxKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGxlbiAr IDEpOworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBsZW4pOworICAgIHRy ZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFyZzAsIGFyZzEs IHNlbCk7CisKKyAgICB0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJn MCwgMCksIHZlY3Rvcl9jc3RfZWx0IChhcmcxLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAo YXJnMCwgMSksIHZlY3Rvcl9jc3RfZWx0IChhcmcxLCAxKQorCQkJICB9OworICAgIHZhbGlkYXRl X3JlcyAoMiwgMiwgcmVzLCBleHBlY3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSA1OiBtYXNr ID0geyAwLCBsZW4sIDEsIGxlbisxLCAuLi4uIH0KKyAgICAgbnBhdHRlcm5zID0gNCwgbmVsdHNf cGVyX3BhdHRlcm4gPSAxICovCisgIHsKKyAgICB0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3Jh bmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAxKTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92 ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAxKTsKKyAgICBwb2x5X3VpbnQ2 NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKyAgICB2 ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGxlbiwgNCwgMSk7CisgICAgYnVpbGRlci5xdWlja19w dXNoICgwKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGxlbik7CisgICAgYnVpbGRlci5xdWlj a19wdXNoICgxKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGxlbiArIDEpOworICAgIHZlY19w ZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBsZW4pOworICAgIHRyZWUgcmVzID0gZm9sZF92 ZWNfcGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFyZzAsIGFyZzEsIHNlbCk7CisKKyAgICB0 cmVlIGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCksIHZlY3Rvcl9j c3RfZWx0IChhcmcxLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMSksIHZlY3Rv cl9jc3RfZWx0IChhcmcxLCAxKQorCQkJICB9OworICAgIHZhbGlkYXRlX3JlcyAoNCwgMSwgcmVz LCBleHBlY3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSA2OiBtYXNrID0gezAsIDQsIC4uLn0K KyAgICAgbnBhdHRlcm5zID0gMSwgbmVsdHNfcGVyX3BhdHRlcm4gPSAyLgorICAgICBUaGlzIHNo b3VsZCByZXR1cm4gTlVMTF9UUkVFIGJlY2F1c2UgdGhlIGluZGV4IDQgbWF5IGNob29zZQorICAg ICBmcm9tIGVpdGhlciBhcmcwIG9yIGFyZzEgZGVwZW5kaW5nIG9uIHZlY3RvciBsZW5ndGguICAq LworICB7CisgICAgdHJlZSBhcmcwID0gYnVpbGRfdmVjX2NzdF9yYW5kIChpbnRlZ2VyX3R5cGVf bm9kZSwgMiwgMywgMSk7CisgICAgdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kIChpbnRl Z2VyX3R5cGVfbm9kZSwgMiwgMywgMSk7CisgICAgcG9seV91aW50NjQgbGVuID0gVFlQRV9WRUNU T1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisgICAgdmVjX3Blcm1fYnVpbGRlciBi dWlsZGVyIChsZW4sIDEsIDIpOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoMCk7CisgICAgYnVp bGRlci5xdWlja19wdXNoICg0KTsKKyAgICB2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwg MiwgbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFy ZzApLCBhcmcwLCBhcmcxLCBzZWwpOworICAgIEFTU0VSVF9UUlVFIChyZXMgPT0gTlVMTF9UUkVF KTsKKyAgfQorCisgIC8qIENhc2UgNzogbnBhdHRlcm5zKGFyZzApID0gNCA+IG5wYXR0ZXJucyhz ZWwpID0gMgorICAgICBtYXNrID0gezAsIGxlbiwgMSwgbGVuICsgMSwgLi4ufQorICAgICBzZWxf bnBhdHRlcm5zID0gMiwgc2VsX25lbHRzX3Blcl9wYXR0ZXJuID0gMi4gICovCisgIHsKKyAgICB0 cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAx KTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2Rl LCAyLCAzLCAxKTsKKyAgICBwb2x5X3VpbnQ2NCBhcmcwX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBB UlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAo YXJnMF9sZW4sIDIsIDIpOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoMCk7CisgICAgYnVpbGRl ci5xdWlja19wdXNoIChhcmcwX2xlbik7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgxKTsKKyAg ICBidWlsZGVyLnF1aWNrX3B1c2ggKGFyZzBfbGVuICsgMSk7CisgICAgdmVjX3Blcm1faW5kaWNl cyBzZWwgKGJ1aWxkZXIsIDIsIGFyZzBfbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Bl cm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBzZWwpOworCisgICAgdHJlZSBl eHBlY3RlZF9yZXNbXSA9IHsgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDApLCB2ZWN0b3JfY3N0X2Vs dCAoYXJnMSwgMCksCisJCQkgICAgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDEpLCB2ZWN0b3JfY3N0 X2VsdCAoYXJnMSwgMSkKKwkJCSAgfTsKKyAgICB2YWxpZGF0ZV9yZXMgKDIsIDIsIHJlcywgZXhw ZWN0ZWRfcmVzKTsKKyAgfQorfQorCitzdGF0aWMgdm9pZAordGVzdF9taXhlZCAoKQoreworICAv KiBDYXNlIDE6IG9wMCwgb3AxIC0+IFZMUywgc2VsIC0+IFZMQSBhbmQgc2VsZWN0cyBmcm9tIGJv dGggaW5wdXQgdmVjdG9ycy4KKyAgICAgSW4gdGhpcyBjYXNlLCB3ZSB0cmVhdCByZXNfbnBhdHRl cm5zID0gbmVsdHMgaW4gaW5wdXQgdmVjdG9yCisgICAgIGFuZCByZXNfbmVsdHNfcGVyX3BhdHRl cm4gPSAxLCBhbmQgY3JlYXRlIGEgZHVwIHBhdHRlcm4uCisgICAgIHNlbCA9IHsgMCwgNCwgMSwg NSwgLi4uIH0KKyAgICAgcmVzID0geyBvcDBbMF0sIG9wMVswXSwgb3AwWzFdLCBvcDFbMV0sIC4u Ln0gLy8gKDQsIDEpCisgICAgIHJlc19ucGF0dGVybnMgPSA0LCByZXNfbmVsdHNfcGVyX3BhdHRl cm4gPSAxLiAgKi8KKyAgeworICAgIHRyZWUgYXJnX3ZlY3R5cGUgPSBidWlsZF92ZWN0b3JfdHlw ZSAoaW50ZWdlcl90eXBlX25vZGUsIDQpOworICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3Rf cmFuZCAoaW50ZWdlcl90eXBlX25vZGUsIDQsIDEsIDAsIGFyZ192ZWN0eXBlKTsKKyAgICB0cmVl IGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCA0LCAxLCAwLCBh cmdfdmVjdHlwZSk7CisKKyAgICB0cmVlIHJlc190eXBlID0gZ2V0X3ByZWZlcnJlZF92ZWN0eXBl IChpbnRlZ2VyX3R5cGVfbm9kZSk7CisgICAgcG9seV91aW50NjQgcmVzX2xlbiA9IFRZUEVfVkVD VE9SX1NVQlBBUlRTIChyZXNfdHlwZSk7CisgICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChy ZXNfbGVuLCA0LCAxKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDApOworICAgIGJ1aWxkZXIu cXVpY2tfcHVzaCAoNCk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgxKTsKKyAgICBidWlsZGVy LnF1aWNrX3B1c2ggKDUpOworCisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIs IHJlc19sZW4pOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKHJlc190eXBlLCBh cmcwLCBhcmcxLCBzZWwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rvcl9jc3Rf ZWx0IChhcmcwLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDApLAorCQkJICAgIHZlY3Rvcl9j c3RfZWx0IChhcmcwLCAxKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDEpCisJCQkgIH07CisgICAg dmFsaWRhdGVfcmVzICg0LCAxLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgIH0KKworICAvKiBDYXNl IDI6IFNhbWUgYXMgQ2FzZSAxLCBidXQgc2VsIGNvbnRhaW5zIGFuIG91dCBvZiBib3VuZHMgaW5k ZXguCisgICAgIHJlc3VsdCBzaG91bGQgYmUgTlVMTF9UUkVFLiAgKi8KKyAgeworICAgIHRyZWUg YXJnX3ZlY3R5cGUgPSBidWlsZF92ZWN0b3JfdHlwZSAoaW50ZWdlcl90eXBlX25vZGUsIDQpOwor ICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAoaW50ZWdlcl90eXBlX25vZGUsIDQs IDEsIDAsIGFyZ192ZWN0eXBlKTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQg KGludGVnZXJfdHlwZV9ub2RlLCA0LCAxLCAwLCBhcmdfdmVjdHlwZSk7CisKKyAgICB0cmVlIHJl c190eXBlID0gZ2V0X3ByZWZlcnJlZF92ZWN0eXBlIChpbnRlZ2VyX3R5cGVfbm9kZSk7CisgICAg cG9seV91aW50NjQgcmVzX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChyZXNfdHlwZSk7Cisg ICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChyZXNfbGVuLCA0LCAxKTsKKyAgICBidWlsZGVy LnF1aWNrX3B1c2ggKDApOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoOCk7CisgICAgYnVpbGRl ci5xdWlja19wdXNoICgxKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDUpOworCisgICAgdmVj X3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIHJlc19sZW4pOworICAgIGNoYXIgcmVhc29u WzEwMF0gPSAiXDAiOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKHJlc190eXBl LCBhcmcwLCBhcmcxLCBzZWwsIHJlYXNvbik7CisgICAgZ2NjX2Fzc2VydCAocmVzID09IE5VTExf VFJFRSk7CisgICAgZ2NjX2Fzc2VydCAoIXN0cmNtcCAocmVhc29uLCAib3V0IG9mIGJvdW5kcyBh Y2Nlc3MiKSk7CisgIH0KKworICAvKiBDYXNlIDM6IG9wMCwgb3AxIGFyZSBWTFMgYW5kIHNlbCBp cyBWTEEgYnV0IGNvbnRhaW5zIHN0ZXBwZWQgc2VxdWVuY2UKKyAgICAgYW5kIGNyb3NzZXMgaW5w dXQgdmVjdG9ycy4KKyAgICAgb3AwLCBvcDEgPSBWNFNJIHZlY3RvcnMuCisgICAgIHNlbCA9IHsg MCwgMiwgNCwgLi4uIH0KKyAgICAgcmVzOiB7IG9wMFswXSwgb3AwWzJdLCBvcDFbMF0sIG9wMVsy XSwgLi4uIH0gKDQsIDEpICAqLworICB7CisgICAgdHJlZSBhcmdfdmVjdHlwZSA9IGJ1aWxkX3Zl Y3Rvcl90eXBlIChpbnRlZ2VyX3R5cGVfbm9kZSwgNCk7CisgICAgdHJlZSBhcmcwID0gYnVpbGRf dmVjX2NzdF9yYW5kIChpbnRlZ2VyX3R5cGVfbm9kZSwgNCwgMSwgMCwgYXJnX3ZlY3R5cGUpOwor ICAgIHRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAoaW50ZWdlcl90eXBlX25vZGUsIDQs IDEsIDAsIGFyZ192ZWN0eXBlKTsKKworICAgIHRyZWUgcmVzX3R5cGUgPSBnZXRfcHJlZmVycmVk X3ZlY3R5cGUgKGludGVnZXJfdHlwZV9ub2RlKTsKKyAgICBwb2x5X3VpbnQ2NCByZXNfbGVuID0g VFlQRV9WRUNUT1JfU1VCUEFSVFMgKHJlc190eXBlKTsKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1 aWxkZXIgKHJlc19sZW4sIDEsIDMpOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoMCk7CisgICAg YnVpbGRlci5xdWlja19wdXNoICgyKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDQpOworCisg ICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIHJlc19sZW4pOworICAgIHRyZWUg cmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKHJlc190eXBlLCBhcmcwLCBhcmcxLCBzZWwpOworCisg ICAgdHJlZSBleHBlY3RlZF9yZXNbXSA9IHsgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDApLCB2ZWN0 b3JfY3N0X2VsdCAoYXJnMCwgMiksCisJCQkgICAgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDApLCB2 ZWN0b3JfY3N0X2VsdCAoYXJnMSwgMikKKwkJCSAgfTsKKyAgICB2YWxpZGF0ZV9yZXMgKDQsIDEs IHJlcywgZXhwZWN0ZWRfcmVzKTsKKyAgfQorCisgIC8qIENhc2UgNDogb3AwLCBvcDEgYXJlIFZM QSBhbmQgc2VsIGlzIFZMUy4KKyAgICAgb3AwLCBvcDE6IFZOeDE2UUkgd2l0aCBzaGFwZSAoMiwg MykKKyAgICAgc2VsID0gVjRTSSB3aXRoIHZhbHVlcyB7MCwgMiwgNCwgNn0KKyAgICAgcmVzOiBW NFNJIHdpdGggdmFsdWVzIHsgb3AwWzBdLCBvcDBbMl0sIG9wMFs0XSwgb3AwWzZdIH0uICAqLwor ICB7CisgICAgdHJlZSBhcmcwID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVfbm9kZSwg MiwgMywgMik7CisgICAgdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kIChjaGFyX3R5cGVf bm9kZSwgMiwgMywgMik7CisKKyAgICBwb2x5X3VpbnQ2NCByZXNfbGVuID0gNDsKKyAgICB0cmVl IHJlc190eXBlID0gYnVpbGRfdmVjdG9yX3R5cGUgKGNoYXJfdHlwZV9ub2RlLCByZXNfbGVuKTsK KyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKHJlc19sZW4sIDQsIDEpOworICAgIGJ1aWxk ZXIucXVpY2tfcHVzaCAoMCk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgyKTsKKyAgICBidWls ZGVyLnF1aWNrX3B1c2ggKDQpOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoNik7CisKKyAgICB2 ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgcmVzX2xlbik7CisgICAgdHJlZSByZXMg PSBmb2xkX3ZlY19wZXJtX2NzdCAocmVzX3R5cGUsIGFyZzAsIGFyZzEsIHNlbCk7CisKKyAgICB0 cmVlIGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCksIHZlY3Rvcl9j c3RfZWx0IChhcmcwLCAyKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgNCksIHZlY3Rv cl9jc3RfZWx0IChhcmcwLCA2KQorCQkJICB9OworICAgIHZhbGlkYXRlX3Jlc192bHMgKHJlcywg ZXhwZWN0ZWRfcmVzLCA0KTsKKyAgfQorCisgIC8qIENhc2UgNTogU2FtZSBhcyBjYXNlIDQsIGJ1 dCBvcDAsIG9wMSBhcmUgVk54NFNJIHdpdGggc2hhcGUgKDIsIDMpIGFuZCBzdGVwID0gMgorICAg ICBzZWwgPSBWNFNJIHdpdGggdmFsdWVzIHswLCAyLCA0LCA2fQorICAgICBJbiB0aGlzIGNhc2Ug cmVzdWx0IHNob3VsZCBiZSBOVUxMX1RSRUUgYmVjYXVzZSB3ZSBjcm9zcyBpbnB1dCB2ZWN0b3IK KyAgICAgYm91bmRhcnkgYXQgaW5kZXggNC4gICovCisgIHsKKyAgICB0cmVlIGFyZzAgPSBidWls ZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAyKTsKKyAgICB0cmVlIGFy ZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKGludGVnZXJfdHlwZV9ub2RlLCAyLCAzLCAyKTsKKwor ICAgIHBvbHlfdWludDY0IHJlc19sZW4gPSA0OworICAgIHRyZWUgcmVzX3R5cGUgPSBidWlsZF92 ZWN0b3JfdHlwZSAoY2hhcl90eXBlX25vZGUsIHJlc19sZW4pOworICAgIHZlY19wZXJtX2J1aWxk ZXIgYnVpbGRlciAocmVzX2xlbiwgNCwgMSk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgwKTsK KyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDIpOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoNCk7 CisgICAgYnVpbGRlci5xdWlja19wdXNoICg2KTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2Vs IChidWlsZGVyLCAyLCByZXNfbGVuKTsKKyAgICBjaGFyIHJlYXNvblsxMDBdID0gIlwwIjsKKyAg ICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChyZXNfdHlwZSwgYXJnMCwgYXJnMSwgc2Vs LCByZWFzb24pOworICAgIGdjY19hc3NlcnQgKHJlcyA9PSBOVUxMX1RSRUUpOworICAgIGdjY19h c3NlcnQgKCFzdHJjbXAgKHJlYXNvbiwgImNyb3NzZWQgaW5wdXQgdmVjdG9ycyIpKTsKKyAgfQor fQorCitzdGF0aWMgdm9pZAordGVzdCAoKQoreworICB0cmVlIHZlY3R5cGUgPSBnZXRfcHJlZmVy cmVkX3ZlY3R5cGUgKGludGVnZXJfdHlwZV9ub2RlKTsKKyAgaWYgKFRZUEVfVkVDVE9SX1NVQlBB UlRTICh2ZWN0eXBlKS5pc19jb25zdGFudCAoKSkKKyAgICByZXR1cm47CisKKyAgdGVzdF9kdXAg KCk7CisgIHRlc3Rfc3RlcHBlZCAoKTsKKyAgdGVzdF9taXhlZCAoKTsKK30KK307CisKIC8qIFZl cmlmeSB0aGF0IHZhcmlvdXMgYmluYXJ5IG9wZXJhdGlvbnMgb24gdmVjdG9ycyBhcmUgZm9sZGVk CiAgICBjb3JyZWN0bHkuICAqLwogCkBAIC0xNjk0Myw2ICsxNzY0Niw3IEBAIGZvbGRfY29uc3Rf Y2NfdGVzdHMgKCkKICAgdGVzdF9hcml0aG1ldGljX2ZvbGRpbmcgKCk7CiAgIHRlc3RfdmVjdG9y X2ZvbGRpbmcgKCk7CiAgIHRlc3RfdmVjX2R1cGxpY2F0ZV9mb2xkaW5nICgpOworICB0ZXN0X2Zv bGRfdmVjX3Blcm1fY3N0Ojp0ZXN0ICgpOwogfQogCiB9IC8vIG5hbWVzcGFjZSBzZWxmdGVzdAo= --0000000000002767ae06018ba112--