From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by sourceware.org (Postfix) with ESMTPS id 4E41B3858404 for ; Tue, 15 Aug 2023 11:30:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4E41B3858404 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-x42d.google.com with SMTP id ffacd0b85a97d-318015ade49so4744090f8f.0 for ; Tue, 15 Aug 2023 04:30:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1692099024; x=1692703824; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=MMmHB8Enl11LlvTOMBSIHGQNj+dVq9jXowPNRHFyE5I=; b=w52tNF02T3CbcdtqDh/9S1Xgc6xpgBuNWntqztpz3su62CIFGcGvXwmMwX0Qi3Pyp/ 4qsMbImN0gHlJilFSoUcGnDWn+UrDHFwrdYavHltPYWV9thqkoXxYT9ovwot+vVUddNQ ZfSUb+s+ij/QukQ2LsPtlKQES1BpLXV3PTaNPezqpuRSGtpREDbjBO0QNe3+fJkboQxv eKXERKkYUkkGpvBOSM+ve2lN2c3fuq+28xFLtM7gIv0Afe0z7nfJyNsQeArrvZQ2+LpV G/HyfH+IfFL2itzI0MG29Lk51xdy3bnSpZhh/haGesMyNOFS+GeFym8rOpdLC6dTJ2RE bJlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1692099024; x=1692703824; 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=MMmHB8Enl11LlvTOMBSIHGQNj+dVq9jXowPNRHFyE5I=; b=SntHkm1K5uPOXAvBMg3e51ZpOg+zI2UtzMmREvOdhpOGJTxnFAQZxN66cSDeH9jVrT FCs6zhXKwG5KkdPK+MNqlUp9TXrUCg5NWTky2T/KymRHxyroMAT76g2y9cZ+6U6my9PZ b0aiDspQPIyF0nVrT3fcd8aBCV0VOvLgb13yXbcHZwaCBN0T3lJaD7oP8WhohlllRQZ+ WzM8YmrnEYbrwufyMNus9rFcnhe4Wieh+lbUoKDiJ1AIa5KzKDSOfiKRJ8MocL4U9+gc qTSBhpxpiAaE2AE0eFEULJ97nJzvFZOaRwL3ikDxYjBXDD0ew0YmUKGehQ/i74j9L1UY +asg== X-Gm-Message-State: AOJu0YyB1DmpIJMAmpuqvkgfTtyCORPWPLyGPlXiERzfwsWI7+boTWbE 6N6sV0MR2TFw/LOGB59/ubsbwDuwC2aKMqwvfsvWFyBj8NXM1GD/Y8E= X-Google-Smtp-Source: AGHT+IEsOzd+eQV19Wmk4X1SzsyuVhb6sRXgPtuB2IRmn5Y6E4abdYX1fdHm0qTIDuUlDqlva8yp+ivw3f0CBebqT4g= X-Received: by 2002:adf:f150:0:b0:314:15a8:7879 with SMTP id y16-20020adff150000000b0031415a87879mr8834775wro.34.1692099023588; Tue, 15 Aug 2023 04:30:23 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Prathamesh Kulkarni Date: Tue, 15 Aug 2023 16:59:49 +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="0000000000003a81f90602f481f0" X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,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: --0000000000003a81f90602f481f0 Content-Type: text/plain; charset="UTF-8" On Mon, 14 Aug 2023 at 18:23, Richard Sandiford wrote: > > Prathamesh Kulkarni writes: > > On Thu, 10 Aug 2023 at 21:27, Richard Sandiford > > wrote: > >> > >> Prathamesh Kulkarni writes: > >> >> static bool > >> >> is_simple_vla_size (poly_uint64 size) > >> >> { > >> >> if (size.is_constant ()) > >> >> return false; > >> >> for (int i = 1; i < ARRAY_SIZE (size.coeffs); ++i) > >> >> if (size[i] != (i <= 1 ? size[0] : 0)) > >> > Just wondering is this should be (i == 1 ? size[0] : 0) since i is > >> > initialized to 1 ? > >> > >> Both work. I prefer <= 1 because it doesn't depend on the micro > >> optimisation to start at coefficient 1. In a theoretical 3-indeterminate > >> poly_int, we want the first 2 coefficients to be nonzero and the rest to > >> be zero. > >> > >> > IIUC, is_simple_vla_size should return true for polynomials of first > >> > degree and having same coeff like 4 + 4x ? > >> > >> FWIW, poly_int only supports first-degree polynomials at the moment. > >> coeffs>2 means there is more than one indeterminate, rather than a > >> higher power. > > Oh OK, thanks for the clarification. > >> > >> >> return false; > >> >> return true; > >> >> } > >> >> > >> >> > >> >> FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT) > >> >> { > >> >> auto nunits = GET_MODE_NUNITS (mode); > >> >> if (!is_simple_vla_size (nunits)) > >> >> continue; > >> >> if (nunits[0] ...) > >> >> test_... (mode); > >> >> ... > >> >> > >> >> } > >> >> > >> >> test_vnx4si_v4si and test_v4si_vnx4si look good. But with the > >> >> loop structure above, I think we can apply the test_vnx4si and > >> >> test_vnx16qi to more cases. So the classification isn't the > >> >> exact number of elements, but instead a limit. > >> >> > >> >> I think the nunits[0] conditions for test_vnx4si are as follows > >> >> (inspection only, so could be wrong): > >> >> > >> >> > +/* Test cases where result and input vectors are VNx4SI */ > >> >> > + > >> >> > +static void > >> >> > +test_vnx4si (machine_mode vmode) > >> >> > +{ > >> >> > + /* Case 1: mask = {0, ...} */ > >> >> > + { > >> >> > + tree arg0 = build_vec_cst_rand (vmode, 2, 3, 1); > >> >> > + tree arg1 = build_vec_cst_rand (vmode, 2, 3, 1); > >> >> > + poly_uint64 len = 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 = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > >> >> > + > >> >> > + tree expected_res[] = { vector_cst_elt (res, 0) }; > >> > This should be { vector_cst_elt (arg0, 0) }; will fix in next patch. > >> >> > + validate_res (1, 1, res, expected_res); > >> >> > + } > >> >> > >> >> nunits[0] >= 2 (could be all nunits if the inputs had nelts_per_pattern==1, > >> >> which I think would be better) > >> > IIUC, the vectors that can be used for a particular test should have > >> > nunits[0] >= res_npatterns, > >> > where res_npatterns is as computed in fold_vec_perm_cst without the > >> > canonicalization ? > >> > For above test -- res_npatterns = max(2, max (2, 1)) == 2, so we > >> > require nunits[0] >= 2 ? > >> > Which implies we can use above test for vectors with length 2 + 2x, 4 + 4x, etc. > >> > >> Right, that's what I meant. With the inputs as they stand it has to be > >> nunits[0] >= 2. We need that form the inputs correctly. But if the > >> inputs instead had nelts_per_pattern == 1, the test would work for all > >> nunits. > > In the attached patch, I have reordered the tests based on min or max limit. > > For tests where sel_npatterns < 3 (ie dup sequence), I have kept input > > npatterns = 1, > > so we can test more vector modes, and also input npatterns matter only > > for stepped sequence in sel > > (Since for a dup pattern we don't enforce the constraint of selecting > > elements from same input pattern). > > Does it look OK ? > > > > For the following tests with input vectors having shape (1, 3) > > sel = {0, 1, 2, ...} // (1, 3) > > res = { arg0[0], arg0[1], arg0[2], ... } // (1, 3) > > > > and sel = {len, len + 1, len + 2, ... } // (1, 3) > > res = { arg1[0], arg1[1], arg1[2], ... } // (1, 3) > > > > Altho res_npatterns = 1, I suppose these will need to be tested with > > vectors with length >= 4 + 4x, > > since index 2 can be ambiguous for length 2 + 2x ? > > (In the patch, these are cases 2 and 3 in test_nunits_min_4) > > Ah, yeah, fair point. I guess that means: > > + /* Case 3: mask = {len, 0, 1, ...} // (1, 3) > + Test that stepped sequence of the pattern selects from arg0. > + res = { arg1[0], arg0[0], arg0[1], ... } // (1, 3) */ > + { > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > + > + vec_perm_builder builder (len, 1, 3); > + poly_uint64 mask_elems[] = { len, 0, 1 }; > + builder_push_elems (builder, mask_elems); > + > + vec_perm_indices sel (builder, 2, len); > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > + > + tree expected_res[] = { ARG1(0), ARG0(0), ARG0(1) }; > + validate_res (1, 3, res, expected_res); > + } > > needs to be min_2 after all. Ah indeed. Fixed, thanks. > > Also: > > > +/* Helper routine to push multiple elements into BUILDER. */ > > + > > +static void > > +builder_push_elems (vec_perm_builder& builder, poly_uint64 *elems) > > +{ > > + for (unsigned i = 0; i < builder.encoded_nelts (); i++) > > + builder.quick_push (elems[i]); > > +} > > I think it'd be safer to make this: > > template > builder_push_elems (vec_perm_builder& builder, poly_uint64 (&elems)[N]) > { > for (unsigned i = 0; i < N; i++) > builder.quick_push (elems[i]); > } > > so that we only push elements that are in the array. Done, thanks. > > OK for trunk with those changes, thanks. Unfortunately, the patch regressed following tests on ppc64le and armhf respectively: gcc.target/powerpc/vec-perm-ctor.c scan-tree-dump-not optimized "VIEW_CONVERT_EXPR" gcc.dg/tree-ssa/forwprop-20.c scan-tree-dump-not forwprop1 "VEC_PERM_EXPR" This happens because of the change to vect_cst_ctor_array which removes handling of VECTOR_CST, and thus we return NULL_TREE for cases where VEC_PERM_EXPR has vector_cst, ctor input operands. For eg we fail to fold VEC_PERM_EXPR for the following test taken from forwprop-20.c: void f (double d, vecf* r) { vecf x = { -d, 5 }; vecf y = { 1, 4 }; veci m = { 2, 0 }; *r = __builtin_shuffle (x, y, m); // { 1, -d } } because vect_cst_ctor_to_array will now return NULL_TREE for vector_cst {1, 4}. The attached patch thus reverts the changes to vect_cst_ctor_to_array, which makes the tests pass again. I have put the patch for another round of bootstrap+test on the above targets (aarch64, aarch64-sve, x86_64, armhf, ppc64le). OK to commit if it passes ? Thanks, Prathamesh > > Richard > > > + > > +#define ARG0(index) vector_cst_elt (arg0, index) > > +#define ARG1(index) vector_cst_elt (arg1, index) > > + > > +/* Test cases where result is VNx4SI and input vectors are V4SI. */ > > + > > +static void > > +test_vnx4si_v4si (machine_mode vnx4si_mode, machine_mode v4si_mode) > > +{ > > + for (int i = 0; i < 10; i++) > > + { > > + /* Case 1: > > + sel = { 0, 4, 1, 5, ... } > > + res = { arg[0], arg1[0], arg0[1], arg1[1], ...} // (4, 1) */ > > + { > > + tree arg0 = build_vec_cst_rand (v4si_mode, 4, 1, 0); > > + tree arg1 = build_vec_cst_rand (v4si_mode, 4, 1, 0); > > + > > + tree inner_type > > + = lang_hooks.types.type_for_mode (GET_MODE_INNER (vnx4si_mode), 1); > > + tree res_type = build_vector_type_for_mode (inner_type, vnx4si_mode); > > + > > + poly_uint64 res_len = TYPE_VECTOR_SUBPARTS (res_type); > > + vec_perm_builder builder (res_len, 4, 1); > > + poly_uint64 mask_elems[] = { 0, 4, 1, 5 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG1(0), ARG0(1), ARG1(1) }; > > + validate_res (4, 1, res, expected_res); > > + } > > + > > + /* Case 2: Same as case 1, but contains an out of bounds access which > > + should wrap around. > > + sel = {0, 8, 4, 12, ...} (4, 1) > > + res = { arg0[0], arg0[0], arg1[0], arg1[0], ... } (4, 1). */ > > + { > > + tree arg0 = build_vec_cst_rand (v4si_mode, 4, 1, 0); > > + tree arg1 = build_vec_cst_rand (v4si_mode, 4, 1, 0); > > + > > + tree inner_type > > + = lang_hooks.types.type_for_mode (GET_MODE_INNER (vnx4si_mode), 1); > > + tree res_type = build_vector_type_for_mode (inner_type, vnx4si_mode); > > + > > + poly_uint64 res_len = TYPE_VECTOR_SUBPARTS (res_type); > > + vec_perm_builder builder (res_len, 4, 1); > > + poly_uint64 mask_elems[] = { 0, 8, 4, 12 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG0(0), ARG1(0), ARG1(0) }; > > + validate_res (4, 1, res, expected_res); > > + } > > + } > > +} > > + > > +/* Test cases where result is V4SI and input vectors are VNx4SI. */ > > + > > +static void > > +test_v4si_vnx4si (machine_mode v4si_mode, machine_mode vnx4si_mode) > > +{ > > + for (int i = 0; i < 10; i++) > > + { > > + /* Case 1: > > + sel = { 0, 1, 2, 3} > > + res = { arg0[0], arg0[1], arg0[2], arg0[3] }. */ > > + { > > + tree arg0 = build_vec_cst_rand (vnx4si_mode, 4, 1); > > + tree arg1 = build_vec_cst_rand (vnx4si_mode, 4, 1); > > + > > + tree inner_type > > + = lang_hooks.types.type_for_mode (GET_MODE_INNER (v4si_mode), 1); > > + tree res_type = build_vector_type_for_mode (inner_type, v4si_mode); > > + > > + poly_uint64 res_len = TYPE_VECTOR_SUBPARTS (res_type); > > + vec_perm_builder builder (res_len, 4, 1); > > + poly_uint64 mask_elems[] = {0, 1, 2, 3}; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG0(1), ARG0(2), ARG0(3) }; > > + validate_res_vls (res, expected_res, 4); > > + } > > + > > + /* Case 2: Same as Case 1, but crossing input vector. > > + sel = {0, 2, 4, 6} > > + In this case,the index 4 is ambiguous since len = 4 + 4x. > > + Since we cannot determine, which vector to choose from during > > + compile time, should return NULL_TREE. */ > > + { > > + tree arg0 = build_vec_cst_rand (vnx4si_mode, 4, 1); > > + tree arg1 = build_vec_cst_rand (vnx4si_mode, 4, 1); > > + > > + tree inner_type > > + = lang_hooks.types.type_for_mode (GET_MODE_INNER (v4si_mode), 1); > > + tree res_type = build_vector_type_for_mode (inner_type, v4si_mode); > > + > > + poly_uint64 res_len = TYPE_VECTOR_SUBPARTS (res_type); > > + vec_perm_builder builder (res_len, 4, 1); > > + poly_uint64 mask_elems[] = {0, 2, 4, 6}; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel, &reason); > > + > > + ASSERT_TRUE (res == NULL_TREE); > > + ASSERT_TRUE (!strcmp (reason, "cannot divide selector element by arg len")); > > + } > > + } > > +} > > + > > +/* Test all input vectors. */ > > + > > +static void > > +test_all_nunits (machine_mode vmode) > > +{ > > + /* Test with 10 different inputs. */ > > + for (int i = 0; i < 10; i++) > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + /* Case 1: mask = {0, ...} // (1, 1) > > + res = { arg0[0], ... } // (1, 1) */ > > + { > > + vec_perm_builder builder (len, 1, 1); > > + builder.quick_push (0); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + tree expected_res[] = { ARG0(0) }; > > + validate_res (1, 1, res, expected_res); > > + } > > + > > + /* Case 2: mask = {len, ...} // (1, 1) > > + res = { arg1[0], ... } // (1, 1) */ > > + { > > + vec_perm_builder builder (len, 1, 1); > > + builder.quick_push (len); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG1(0) }; > > + validate_res (1, 1, res, expected_res); > > + } > > + > > + /* Case 3: mask = {len, 0, 1, ...} // (1, 3) > > + Test that stepped sequence of the pattern selects from arg0. > > + res = { arg1[0], arg0[0], arg0[1], ... } // (1, 3) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 3); > > + poly_uint64 mask_elems[] = { len, 0, 1 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG1(0), ARG0(0), ARG0(1) }; > > + validate_res (1, 3, res, expected_res); > > + } > > + } > > +} > > + > > +/* Test all vectors which contain at-least 2 elements. */ > > + > > +static void > > +test_nunits_min_2 (machine_mode vmode) > > +{ > > + for (int i = 0; i < 10; i++) > > + { > > + /* Case 1: mask = { 0, len, ... } // (2, 1) > > + res = { arg0[0], arg1[0], ... } // (2, 1) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 1); > > + poly_uint64 mask_elems[] = { 0, len }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG1(0) }; > > + validate_res (2, 1, res, expected_res); > > + } > > + > > + /* Case 2: mask = { 0, len, 1, len+1, ... } // (2, 2) > > + res = { arg0[0], arg1[0], arg0[1], arg1[1], ... } // (2, 2) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 2); > > + poly_uint64 mask_elems[] = { 0, len, 1, len + 1 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG1(0), ARG0(1), ARG1(1) }; > > + validate_res (2, 2, res, expected_res); > > + } > > + > > + /* Case 4: mask = {0, 0, 1, ...} // (1, 3) > > + Test that the stepped sequence of the pattern selects from > > + same input pattern. Since input vectors have npatterns = 2, > > + and step (a2 - a1) = 1, step is not a multiple of npatterns > > + in input vector. So return NULL_TREE. */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 3); > > + poly_uint64 mask_elems[] = { 0, 0, 1 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel, > > + &reason); > > + ASSERT_TRUE (res == NULL_TREE); > > + ASSERT_TRUE (!strcmp (reason, "step is not multiple of npatterns")); > > + } > > + } > > +} > > + > > +/* Test all vectors which contain at-least 4 elements. */ > > + > > +static void > > +test_nunits_min_4 (machine_mode vmode) > > +{ > > + for (int i = 0; i < 10; i++) > > + { > > + /* Case 1: mask = { 0, len, 1, len+1, ... } // (4, 1) > > + res: { arg0[0], arg1[0], arg0[1], arg1[1], ... } // (4, 1) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 4, 1); > > + poly_uint64 mask_elems[] = { 0, len, 1, len + 1 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG1(0), ARG0(1), ARG1(1) }; > > + validate_res (4, 1, res, expected_res); > > + } > > + > > + /* Case 2: sel = {0, 1, 2, ...} // (1, 3) > > + res: { arg0[0], arg0[1], arg0[2], ... } // (1, 3) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 2); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + poly_uint64 mask_elems[] = {0, 1, 2}; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + tree expected_res[] = { ARG0(0), ARG0(1), ARG0(2) }; > > + validate_res (1, 3, res, expected_res); > > + } > > + > > + /* Case 3: sel = {len, len+1, len+2, ...} // (1, 3) > > + res: { arg1[0], arg1[1], arg1[2], ... } // (1, 3) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 2); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 3); > > + poly_uint64 mask_elems[] = {len, len + 1, len + 2}; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + tree expected_res[] = { ARG1(0), ARG1(1), ARG1(2) }; > > + validate_res (1, 3, res, expected_res); > > + } > > + > > + /* Case 4: > > + sel = { len, 0, 2, ... } // (1, 3) > > + This should return NULL because we cross the input vectors. > > + Because, > > + Let's assume len = C + Cx > > + a1 = 0 > > + S = 2 > > + esel = arg0_len / sel_npatterns = C + Cx > > + ae = 0 + (esel - 2) * S > > + = 0 + (C + Cx - 2) * 2 > > + = 2(C-2) + 2Cx > > + > > + For C >= 4: > > + Let q1 = a1 / arg0_len = 0 / (C + Cx) = 0 > > + Let qe = ae / arg0_len = (2(C-2) + 2Cx) / (C + Cx) = 1 > > + Since q1 != qe, we cross input vectors. > > + So return NULL_TREE. */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 2); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + poly_uint64 mask_elems[] = { arg0_len, 0, 2 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel, &reason); > > + ASSERT_TRUE (res == NULL_TREE); > > + ASSERT_TRUE (!strcmp (reason, "crossed input vectors")); > > + } > > + > > + /* Case 5: npatterns(arg0) = 4 > npatterns(sel) = 2 > > + mask = { 0, len, 1, len + 1, ...} // (2, 2) > > + res = { arg0[0], arg1[0], arg0[1], arg1[1], ... } // (2, 2) > > + > > + Note that fold_vec_perm_cst will set > > + res_npatterns = max(4, max(4, 2)) = 4 > > + However after canonicalizing, we will end up with shape (2, 2). */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 4, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 4, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 2); > > + poly_uint64 mask_elems[] = { 0, len, 1, len + 1 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + tree expected_res[] = { ARG0(0), ARG1(0), ARG0(1), ARG1(1) }; > > + validate_res (2, 2, res, expected_res); > > + } > > + > > + /* Case 6: Test combination in sel, where one pattern is dup and other > > + is stepped sequence. > > + sel = { 0, 0, 0, 1, 0, 2, ... } // (2, 3) > > + res = { arg0[0], arg0[0], arg0[0], > > + arg0[1], arg0[0], arg0[2], ... } // (2, 3) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 3); > > + poly_uint64 mask_elems[] = { 0, 0, 0, 1, 0, 2 }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG0(0), ARG0(0), > > + ARG0(1), ARG0(0), ARG0(2) }; > > + validate_res (2, 3, res, expected_res); > > + } > > + } > > +} > > + > > +/* Test all vectors which contain at-least 8 elements. */ > > + > > +static void > > +test_nunits_min_8 (machine_mode vmode) > > +{ > > + for (int i = 0; i < 10; i++) > > + { > > + /* Case 1: sel_npatterns (4) > input npatterns (2) > > + sel: { 0, 0, 1, len, 2, 0, 3, len, 4, 0, 5, len, ...} // (4, 3) > > + res: { arg0[0], arg0[0], arg0[0], arg1[0], > > + arg0[2], arg0[0], arg0[3], arg1[0], > > + arg0[4], arg0[0], arg0[5], arg1[0], ... } // (4, 3) */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 2, 3, 2); > > + tree arg1 = build_vec_cst_rand (vmode, 2, 3, 2); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder(len, 4, 3); > > + poly_uint64 mask_elems[] = { 0, 0, 1, len, 2, 0, 3, len, > > + 4, 0, 5, len }; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { ARG0(0), ARG0(0), ARG0(1), ARG1(0), > > + ARG0(2), ARG0(0), ARG0(3), ARG1(0), > > + ARG0(4), ARG0(0), ARG0(5), ARG1(0) }; > > + validate_res (4, 3, res, expected_res); > > + } > > + } > > +} > > + > > +/* Test vectors for which nunits[0] <= 4. */ > > + > > +static void > > +test_nunits_max_4 (machine_mode vmode) > > +{ > > + /* Case 1: mask = {0, 4, ...} // (1, 2) > > + This should return NULL_TREE because the index 4 may choose > > + from either arg0 or arg1 depending on vector length. */ > > + { > > + tree arg0 = build_vec_cst_rand (vmode, 1, 3, 1); > > + tree arg1 = build_vec_cst_rand (vmode, 1, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 2); > > + poly_uint64 mask_elems[] = {0, 4}; > > + builder_push_elems (builder, mask_elems); > > + > > + vec_perm_indices sel (builder, 2, len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel, &reason); > > + ASSERT_TRUE (res == NULL_TREE); > > + ASSERT_TRUE (reason != NULL); > > + ASSERT_TRUE (!strcmp (reason, "cannot divide selector element by arg len")); > > + } > > +} > > + > > +#undef ARG0 > > +#undef ARG1 > > + > > +/* Return true if SIZE is of the form C + Cx and C is power of 2. */ > > + > > +static bool > > +is_simple_vla_size (poly_uint64 size) > > +{ > > + if (size.is_constant () > > + || !pow2p_hwi (size.coeffs[0])) > > + return false; > > + for (unsigned i = 1; i < ARRAY_SIZE (size.coeffs); ++i) > > + if (size.coeffs[i] != (i <= 1 ? size.coeffs[0] : 0)) > > + return false; > > + return true; > > +} > > + > > +/* Execute fold_vec_perm_cst unit tests. */ > > + > > +static void > > +test () > > +{ > > + machine_mode vnx4si_mode = E_VOIDmode; > > + machine_mode v4si_mode = E_VOIDmode; > > + > > + machine_mode vmode; > > + FOR_EACH_MODE_IN_CLASS (vmode, MODE_VECTOR_INT) > > + { > > + /* Obtain modes corresponding to VNx4SI and V4SI, > > + to call mixed mode tests below. > > + FIXME: Is there a better way to do this ? */ > > + if (GET_MODE_INNER (vmode) == SImode) > > + { > > + poly_uint64 nunits = GET_MODE_NUNITS (vmode); > > + if (is_simple_vla_size (nunits) > > + && nunits.coeffs[0] == 4) > > + vnx4si_mode = vmode; > > + else if (known_eq (nunits, poly_uint64 (4))) > > + v4si_mode = vmode; > > + } > > + > > + if (!is_simple_vla_size (GET_MODE_NUNITS (vmode)) > > + || !targetm.vector_mode_supported_p (vmode)) > > + continue; > > + > > + poly_uint64 nunits = GET_MODE_NUNITS (vmode); > > + test_all_nunits (vmode); > > + if (nunits.coeffs[0] >= 2) > > + test_nunits_min_2 (vmode); > > + if (nunits.coeffs[0] >= 4) > > + test_nunits_min_4 (vmode); > > + if (nunits.coeffs[0] >= 8) > > + test_nunits_min_8 (vmode); > > + > > + if (nunits.coeffs[0] <= 4) > > + test_nunits_max_4 (vmode); > > + } > > + > > + if (vnx4si_mode != E_VOIDmode && v4si_mode != E_VOIDmode > > + && targetm.vector_mode_supported_p (vnx4si_mode) > > + && targetm.vector_mode_supported_p (v4si_mode)) > > + { > > + test_vnx4si_v4si (vnx4si_mode, v4si_mode); > > + test_v4si_vnx4si (v4si_mode, vnx4si_mode); > > + } > > +} > > +}; // end of test_fold_vec_perm_cst namespace > > + > > /* Verify that various binary operations on vectors are folded > > correctly. */ > > > > @@ -16943,6 +17693,7 @@ fold_const_cc_tests () > > test_arithmetic_folding (); > > test_vector_folding (); > > test_vec_duplicate_folding (); > > + test_fold_vec_perm_cst::test (); > > } > > > > } // namespace selftest --0000000000003a81f90602f481f0 Content-Type: text/plain; charset="US-ASCII"; name="gnu-790-v2-16.txt" Content-Disposition: attachment; filename="gnu-790-v2-16.txt" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_llc7sycm0 RXh0ZW5kIGZvbGRfdmVjX3Blcm0gdG8gaGFuZGxlIFZMQSB2ZWN0b3JfY3N0LgoKZ2NjL0NoYW5n ZUxvZzoKCSogZm9sZC1jb25zdC5jYyAoSU5DTFVERV9BTEdPUklUSE0pOiBBZGQgSW5jbHVkZS4K CSh2YWxpZF9tYXNrX2Zvcl9mb2xkX3ZlY19wZXJtX2NzdF9wKTogTmV3IGZ1bmN0aW9uLgoJKGZv bGRfdmVjX3Blcm1fY3N0KTogTGlrZXdpc2UuCgkoZm9sZF92ZWNfcGVybSk6IEFkanVzdCBhc3Nl cnQgYW5kIGNhbGwgZm9sZF92ZWNfcGVybV9jc3QuCgkodGVzdF9mb2xkX3ZlY19wZXJtX2NzdCk6 IE5ldyBuYW1lc3BhY2UuCgkodGVzdF9mb2xkX3ZlY19wZXJtX2NzdDo6YnVpbGRfdmVjX2NzdF9y YW5kKTogTmV3IGZ1bmN0aW9uLgoJKHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnZhbGlkYXRlX3Jl cyk6IExpa2V3aXNlLgoJKHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnZhbGlkYXRlX3Jlc192bHMp OiBMaWtld2lzZS4KCSh0ZXN0X2ZvbGRfdmVjX3Blcm1fY3N0OjpidWlsZGVyX3B1c2hfZWxlbXMp OiBMaWtld2lzZS4KCSh0ZXN0X2ZvbGRfdmVjX3Blcm1fY3N0Ojp0ZXN0X3ZueDRzaV92NHNpKTog TGlrZXdpc2UuCgkodGVzdF9mb2xkX3ZlY19wZXJtX2NzdDo6dGVzdF92NHNpX3ZueDRzaSk6IExp a2V3aXNlLgoJKHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnRlc3RfYWxsX251bml0cyk6IExpa2V3 aXNlLgoJKHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnRlc3RfbnVuaXRzX21pbl8yKTogTGlrZXdp c2UuCgkodGVzdF9mb2xkX3ZlY19wZXJtX2NzdDo6dGVzdF9udW5pdHNfbWluXzQpOiBMaWtld2lz ZS4KCSh0ZXN0X2ZvbGRfdmVjX3Blcm1fY3N0Ojp0ZXN0X251bml0c19taW5fOCk6IExpa2V3aXNl LgoJKHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnRlc3RfbnVuaXRzX21heF80KTogTGlrZXdpc2Uu CgkodGVzdF9mb2xkX3ZlY19wZXJtX2NzdDo6aXNfc2ltcGxlX3ZsYV9zaXplKTogTGlrZXdpc2Uu CgkodGVzdF9mb2xkX3ZlY19wZXJtX2NzdDo6dGVzdCk6IExpa2V3aXNlLgoJKGZvbGRfY29uc3Rf Y2NfdGVzdHMpOiBDYWxsIHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnRlc3QuCgpDby1hdXRob3Jl ZC1ieTogUmljaGFyZCBTYW5kaWZvcmQgPHJpY2hhcmQuc2FuZGlmb3JkQGFybS5jb20+CgpkaWZm IC0tZ2l0IGEvZ2NjL2ZvbGQtY29uc3QuY2MgYi9nY2MvZm9sZC1jb25zdC5jYwppbmRleCA3ZTU0 OTRkZmQzOS4uYzZmYjA4MzAyN2QgMTAwNjQ0Ci0tLSBhL2djYy9mb2xkLWNvbnN0LmNjCisrKyBi L2djYy9mb2xkLWNvbnN0LmNjCkBAIC00MCw2ICs0MCw3IEBAIGFsb25nIHdpdGggR0NDOyBzZWUg dGhlIGZpbGUgQ09QWUlORzMuICBJZiBub3Qgc2VlCiAgICBnaW1wbGUgY29kZSwgd2UgbmVlZCB0 byBoYW5kbGUgR0lNUExFIHR1cGxlcyBhcyB3ZWxsIGFzIHRoZWlyCiAgICBjb3JyZXNwb25kaW5n IHRyZWUgZXF1aXZhbGVudHMuICAqLwogCisjZGVmaW5lIElOQ0xVREVfQUxHT1JJVEhNCiAjaW5j bHVkZSAiY29uZmlnLmgiCiAjaW5jbHVkZSAic3lzdGVtLmgiCiAjaW5jbHVkZSAiY29yZXR5cGVz LmgiCkBAIC0xMDUyMCw2ICsxMDUyMSwxODEgQEAgdmVjX2NzdF9jdG9yX3RvX2FycmF5ICh0cmVl IGFyZywgdW5zaWduZWQgaW50IG5lbHRzLCB0cmVlICplbHRzKQogICByZXR1cm4gdHJ1ZTsKIH0K IAorLyogSGVscGVyIHJvdXRpbmUgZm9yIGZvbGRfdmVjX3Blcm1fY3N0IHRvIGNoZWNrIGlmIFNF TCBpcyBhIHN1aXRhYmxlCisgICBtYXNrIGZvciBWTEEgdmVjX3Blcm0gZm9sZGluZy4KKyAgIFJF QVNPTiBpZiBzcGVjaWZpZWQsIHdpbGwgY29udGFpbiB0aGUgcmVhc29uIHdoeSBTRUwgaXMgbm90 IHN1aXRhYmxlLgorICAgVXNlZCBvbmx5IGZvciBkZWJ1Z2dpbmcgYW5kIHVuaXQtdGVzdGluZy4g ICovCisKK3N0YXRpYyBib29sCit2YWxpZF9tYXNrX2Zvcl9mb2xkX3ZlY19wZXJtX2NzdF9wICh0 cmVlIGFyZzAsIHRyZWUgYXJnMSwKKwkJCQkgICAgY29uc3QgdmVjX3Blcm1faW5kaWNlcyAmc2Vs LAorCQkJCSAgICBjb25zdCBjaGFyICoqcmVhc29uID0gTlVMTCkKK3sKKyAgdW5zaWduZWQgc2Vs X25wYXR0ZXJucyA9IHNlbC5lbmNvZGluZyAoKS5ucGF0dGVybnMgKCk7CisgIHVuc2lnbmVkIHNl bF9uZWx0c19wZXJfcGF0dGVybiA9IHNlbC5lbmNvZGluZyAoKS5uZWx0c19wZXJfcGF0dGVybiAo KTsKKworICBpZiAoIShwb3cycF9od2kgKHNlbF9ucGF0dGVybnMpCisJJiYgcG93MnBfaHdpIChW RUNUT1JfQ1NUX05QQVRURVJOUyAoYXJnMCkpCisJJiYgcG93MnBfaHdpIChWRUNUT1JfQ1NUX05Q QVRURVJOUyAoYXJnMSkpKSkKKyAgICB7CisgICAgICBpZiAocmVhc29uKQorCSpyZWFzb24gPSAi bnBhdHRlcm5zIGlzIG5vdCBwb3dlciBvZiAyIjsKKyAgICAgIHJldHVybiBmYWxzZTsKKyAgICB9 CisKKyAgLyogV2Ugd2FudCB0byBhdm9pZCBjYXNlcyB3aGVyZSBzZWwubGVuZ3RoIGlzIG5vdCBh IG11bHRpcGxlIG9mIG5wYXR0ZXJucy4KKyAgICAgRm9yIGVnOiBzZWwubGVuZ3RoID0gMiArIDJ4 LCBhbmQgc2VsIG5wYXR0ZXJucyA9IDQuICAqLworICBwb2x5X3VpbnQ2NCBlc2VsOworICBpZiAo IW11bHRpcGxlX3AgKHNlbC5sZW5ndGggKCksIHNlbF9ucGF0dGVybnMsICZlc2VsKSkKKyAgICB7 CisgICAgICBpZiAocmVhc29uKQorCSpyZWFzb24gPSAic2VsLmxlbmd0aCBpcyBub3QgbXVsdGlw bGUgb2Ygc2VsX25wYXR0ZXJucyI7CisgICAgICByZXR1cm4gZmFsc2U7CisgICAgfQorCisgIGlm IChzZWxfbmVsdHNfcGVyX3BhdHRlcm4gPCAzKQorICAgIHJldHVybiB0cnVlOworCisgIGZvciAo dW5zaWduZWQgcGF0dGVybiA9IDA7IHBhdHRlcm4gPCBzZWxfbnBhdHRlcm5zOyBwYXR0ZXJuKysp CisgICAgeworICAgICAgcG9seV91aW50NjQgYTEgPSBzZWxbcGF0dGVybiArIHNlbF9ucGF0dGVy bnNdOworICAgICAgcG9seV91aW50NjQgYTIgPSBzZWxbcGF0dGVybiArIDIgKiBzZWxfbnBhdHRl cm5zXTsKKyAgICAgIEhPU1RfV0lERV9JTlQgc3RlcDsKKyAgICAgIGlmICghcG9seV9pbnQ2NCAo YTIgLSBhMSkuaXNfY29uc3RhbnQgKCZzdGVwKSkKKwl7CisJICBpZiAocmVhc29uKQorCSAgICAq cmVhc29uID0gInN0ZXAgaXMgbm90IGNvbnN0YW50IjsKKwkgIHJldHVybiBmYWxzZTsKKwl9Cisg ICAgICAvLyBGSVhNRTogUHVudCBvbiBzdGVwIDwgMCBmb3Igbm93LCByZXZpc2l0IGxhdGVyLgor ICAgICAgaWYgKHN0ZXAgPCAwKQorCXJldHVybiBmYWxzZTsKKyAgICAgIGlmIChzdGVwID09IDAp CisJY29udGludWU7CisKKyAgICAgIGlmICghcG93MnBfaHdpIChzdGVwKSkKKwl7CisJICBpZiAo cmVhc29uKQorCSAgICAqcmVhc29uID0gInN0ZXAgaXMgbm90IHBvd2VyIG9mIDIiOworCSAgcmV0 dXJuIGZhbHNlOworCX0KKworICAgICAgLyogRW5zdXJlIHRoYXQgc3RlcHBlZCBzZXF1ZW5jZSBv ZiB0aGUgcGF0dGVybiBzZWxlY3RzIGVsZW1lbnRzCisJIG9ubHkgZnJvbSB0aGUgc2FtZSBpbnB1 dCB2ZWN0b3IuICAqLworICAgICAgdWludDY0X3QgcTEsIHFlOworICAgICAgcG9seV91aW50NjQg cjEsIHJlOworICAgICAgcG9seV91aW50NjQgYWUgPSBhMSArIChlc2VsIC0gMikgKiBzdGVwOwor ICAgICAgcG9seV91aW50NjQgYXJnX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZ UEUgKGFyZzApKTsKKworICAgICAgaWYgKCEoY2FuX2Rpdl90cnVuY19wIChhMSwgYXJnX2xlbiwg JnExLCAmcjEpCisJICAgICYmIGNhbl9kaXZfdHJ1bmNfcCAoYWUsIGFyZ19sZW4sICZxZSwgJnJl KQorCSAgICAmJiBxMSA9PSBxZSkpCisJeworCSAgaWYgKHJlYXNvbikKKwkgICAgKnJlYXNvbiA9 ICJjcm9zc2VkIGlucHV0IHZlY3RvcnMiOworCSAgcmV0dXJuIGZhbHNlOworCX0KKworICAgICAg LyogRW5zdXJlIHRoYXQgdGhlIHN0ZXBwZWQgc2VxdWVuY2UgYWx3YXlzIHNlbGVjdHMgZnJvbSB0 aGUgc2FtZQorCSBpbnB1dCBwYXR0ZXJuLiAgKi8KKyAgICAgIHVuc2lnbmVkIGFyZ19ucGF0dGVy bnMKKwk9ICgocTEgJiAwKSA9PSAwKSA/IFZFQ1RPUl9DU1RfTlBBVFRFUk5TIChhcmcwKQorCQkJ ICA6IFZFQ1RPUl9DU1RfTlBBVFRFUk5TIChhcmcxKTsKKworICAgICAgaWYgKCFtdWx0aXBsZV9w IChzdGVwLCBhcmdfbnBhdHRlcm5zKSkKKwl7CisJICBpZiAocmVhc29uKQorCSAgICAqcmVhc29u ID0gInN0ZXAgaXMgbm90IG11bHRpcGxlIG9mIG5wYXR0ZXJucyI7CisJICByZXR1cm4gZmFsc2U7 CisJfQorICAgIH0KKworICByZXR1cm4gdHJ1ZTsKK30KKworLyogVHJ5IHRvIGZvbGQgcGVybXV0 YXRpb24gb2YgQVJHMCBhbmQgQVJHMSB3aXRoIFNFTCBzZWxlY3RvciB3aGVuCisgICB0aGUgaW5w dXQgdmVjdG9ycyBhcmUgVkVDVE9SX0NTVC4gUmV0dXJuIE5VTExfVFJFRSBvdGhlcndpc2UuCisg ICBSRUFTT04gaGFzIHNhbWUgcHVycG9zZSBhcyBkZXNjcmliZWQgaW4KKyAgIHZhbGlkX21hc2tf Zm9yX2ZvbGRfdmVjX3Blcm1fY3N0X3AuICAqLworCitzdGF0aWMgdHJlZQorZm9sZF92ZWNfcGVy bV9jc3QgKHRyZWUgdHlwZSwgdHJlZSBhcmcwLCB0cmVlIGFyZzEsIGNvbnN0IHZlY19wZXJtX2lu ZGljZXMgJnNlbCwKKwkJICAgY29uc3QgY2hhciAqKnJlYXNvbiA9IE5VTEwpCit7CisgIHVuc2ln bmVkIHJlc19ucGF0dGVybnMsIHJlc19uZWx0c19wZXJfcGF0dGVybjsKKyAgdW5zaWduZWQgSE9T VF9XSURFX0lOVCByZXNfbmVsdHM7CisKKyAgLyogKDEpIElmIFNFTCBpcyBhIHN1aXRhYmxlIG1h c2sgYXMgZGV0ZXJtaW5lZCBieQorICAgICB2YWxpZF9tYXNrX2Zvcl9mb2xkX3ZlY19wZXJtX2Nz dF9wLCB0aGVuOgorICAgICByZXNfbnBhdHRlcm5zID0gbWF4IG9mIG5wYXR0ZXJucyBiZXR3ZWVu IEFSRzAsIEFSRzEsIGFuZCBTRUwKKyAgICAgcmVzX25lbHRzX3Blcl9wYXR0ZXJuID0gbWF4IG9m IG5lbHRzX3Blcl9wYXR0ZXJuIGJldHdlZW4KKwkJCSAgICAgQVJHMCwgQVJHMSBhbmQgU0VMLgor ICAgICAoMikgSWYgU0VMIGlzIG5vdCBhIHN1aXRhYmxlIG1hc2ssIGFuZCBUWVBFIGlzIFZMUyB0 aGVuOgorICAgICByZXNfbnBhdHRlcm5zID0gbmVsdHMgaW4gcmVzdWx0IHZlY3Rvci4KKyAgICAg cmVzX25lbHRzX3Blcl9wYXR0ZXJuID0gMS4KKyAgICAgVGhpcyBleGNlcHRpb24gaXMgbWFkZSBz byB0aGF0IFZMUyBBUkcwLCBBUkcxIGFuZCBTRUwgd29yayBhcyBiZWZvcmUuICAqLworICBpZiAo dmFsaWRfbWFza19mb3JfZm9sZF92ZWNfcGVybV9jc3RfcCAoYXJnMCwgYXJnMSwgc2VsLCByZWFz b24pKQorICAgIHsKKyAgICAgIHJlc19ucGF0dGVybnMKKwk9IHN0ZDo6bWF4IChWRUNUT1JfQ1NU X05QQVRURVJOUyAoYXJnMCksCisJCSAgICBzdGQ6Om1heCAoVkVDVE9SX0NTVF9OUEFUVEVSTlMg KGFyZzEpLAorCQkJICAgICAgc2VsLmVuY29kaW5nICgpLm5wYXR0ZXJucyAoKSkpOworCisgICAg ICByZXNfbmVsdHNfcGVyX3BhdHRlcm4KKwk9IHN0ZDo6bWF4IChWRUNUT1JfQ1NUX05FTFRTX1BF Ul9QQVRURVJOIChhcmcwKSwKKwkJICAgIHN0ZDo6bWF4IChWRUNUT1JfQ1NUX05FTFRTX1BFUl9Q QVRURVJOIChhcmcxKSwKKwkJCSAgICAgIHNlbC5lbmNvZGluZyAoKS5uZWx0c19wZXJfcGF0dGVy biAoKSkpOworCisgICAgICByZXNfbmVsdHMgPSByZXNfbnBhdHRlcm5zICogcmVzX25lbHRzX3Bl cl9wYXR0ZXJuOworICAgIH0KKyAgZWxzZSBpZiAoVFlQRV9WRUNUT1JfU1VCUEFSVFMgKHR5cGUp LmlzX2NvbnN0YW50ICgmcmVzX25lbHRzKSkKKyAgICB7CisgICAgICByZXNfbnBhdHRlcm5zID0g cmVzX25lbHRzOworICAgICAgcmVzX25lbHRzX3Blcl9wYXR0ZXJuID0gMTsKKyAgICB9CisgIGVs c2UKKyAgICByZXR1cm4gTlVMTF9UUkVFOworCisgIHRyZWVfdmVjdG9yX2J1aWxkZXIgb3V0X2Vs dHMgKHR5cGUsIHJlc19ucGF0dGVybnMsIHJlc19uZWx0c19wZXJfcGF0dGVybik7CisgIGZvciAo dW5zaWduZWQgaSA9IDA7IGkgPCByZXNfbmVsdHM7IGkrKykKKyAgICB7CisgICAgICBwb2x5X3Vp bnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisgICAg ICB1aW50NjRfdCBxOworICAgICAgcG9seV91aW50NjQgcjsKKyAgICAgIHVuc2lnbmVkIEhPU1Rf V0lERV9JTlQgaW5kZXg7CisKKyAgICAgIC8qIFB1bnQgaWYgc2VsW2ldIC90cnVuY19kaXYgbGVu IGNhbm5vdCBiZSBkZXRlcm1pbmVkLAorCSBiZWNhdXNlIHRoZSBpbnB1dCB2ZWN0b3IgdG8gYmUg Y2hvc2VuIHdpbGwgZGVwZW5kIG9uCisJIHJ1bnRpbWUgdmVjdG9yIGxlbmd0aC4KKwkgRm9yIGV4 YW1wbGUgaWYgbGVuID09IDQgKyA0eCwgYW5kIHNlbFtpXSA9PSA0LAorCSBJZiBsZW4gYXQgcnVu dGltZSBlcXVhbHMgNCwgd2UgY2hvb3NlIGFyZzFbMF0uCisJIEZvciBhbnkgb3RoZXIgdmFsdWUg b2YgbGVuID4gNCBhdCBydW50aW1lLCB3ZSBjaG9vc2UgYXJnMFs0XS4KKwkgd2hpY2ggbWFrZXMg dGhlIGVsZW1lbnQgY2hvaWNlIGRlcGVuZGVudCBvbiBydW50aW1lIHZlY3RvciBsZW5ndGguICAq LworICAgICAgaWYgKCFjYW5fZGl2X3RydW5jX3AgKHNlbFtpXSwgbGVuLCAmcSwgJnIpKQorCXsK KwkgIGlmIChyZWFzb24pCisJICAgICpyZWFzb24gPSAiY2Fubm90IGRpdmlkZSBzZWxlY3RvciBl bGVtZW50IGJ5IGFyZyBsZW4iOworCSAgcmV0dXJuIE5VTExfVFJFRTsKKwl9CisKKyAgICAgIC8q IHNlbFtpXSAlIGxlbiB3aWxsIGdpdmUgdGhlIGluZGV4IG9mIGVsZW1lbnQgaW4gdGhlIGNob3Nl biBpbnB1dAorCSB2ZWN0b3IuIEZvciBleGFtcGxlIGlmIHNlbFtpXSA9PSA1ICsgNHggYW5kIGxl biA9PSA0ICsgNHgsCisJIHdlIHdpbGwgY2hvb3NlIGFyZzFbMV0gc2luY2UgKDUgKyA0eCkgJSAo NCArIDR4KSA9PSAxLiAgKi8KKyAgICAgIGlmICghci5pc19jb25zdGFudCAoJmluZGV4KSkKKwl7 CisJICBpZiAocmVhc29uKQorCSAgICAqcmVhc29uID0gInJlbWFpbmRlciBpcyBub3QgY29uc3Rh bnQiOworCSAgcmV0dXJuIE5VTExfVFJFRTsKKwl9CisKKyAgICAgIHRyZWUgYXJnID0gKChxICYg MSkgPT0gMCkgPyBhcmcwIDogYXJnMTsKKyAgICAgIHRyZWUgZWxlbSA9IHZlY3Rvcl9jc3RfZWx0 IChhcmcsIGluZGV4KTsKKyAgICAgIG91dF9lbHRzLnF1aWNrX3B1c2ggKGVsZW0pOworICAgIH0K KworICByZXR1cm4gb3V0X2VsdHMuYnVpbGQgKCk7Cit9CisKIC8qIEF0dGVtcHQgdG8gZm9sZCB2 ZWN0b3IgcGVybXV0YXRpb24gb2YgQVJHMCBhbmQgQVJHMSB2ZWN0b3JzIHVzaW5nIFNFTAogICAg c2VsZWN0b3IuICBSZXR1cm4gdGhlIGZvbGRlZCBWRUNUT1JfQ1NUIG9yIENPTlNUUlVDVE9SIGlm IHN1Y2Nlc3NmdWwsCiAgICBOVUxMX1RSRUUgb3RoZXJ3aXNlLiAgKi8KQEAgLTEwNTI5LDQzICsx MDcwNSw0MSBAQCBmb2xkX3ZlY19wZXJtICh0cmVlIHR5cGUsIHRyZWUgYXJnMCwgdHJlZSBhcmcx LCBjb25zdCB2ZWNfcGVybV9pbmRpY2VzICZzZWwpCiB7CiAgIHVuc2lnbmVkIGludCBpOwogICB1 bnNpZ25lZCBIT1NUX1dJREVfSU5UIG5lbHRzOwotICBib29sIG5lZWRfY3RvciA9IGZhbHNlOwog Ci0gIGlmICghc2VsLmxlbmd0aCAoKS5pc19jb25zdGFudCAoJm5lbHRzKSkKLSAgICByZXR1cm4g TlVMTF9UUkVFOwotICBnY2NfYXNzZXJ0IChrbm93bl9lcSAoVFlQRV9WRUNUT1JfU1VCUEFSVFMg KHR5cGUpLCBuZWx0cykKLQkgICAgICAmJiBrbm93bl9lcSAoVFlQRV9WRUNUT1JfU1VCUEFSVFMg KFRSRUVfVFlQRSAoYXJnMCkpLCBuZWx0cykKLQkgICAgICAmJiBrbm93bl9lcSAoVFlQRV9WRUNU T1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMSkpLCBuZWx0cykpOworICBnY2NfYXNzZXJ0IChr bm93bl9lcSAoVFlQRV9WRUNUT1JfU1VCUEFSVFMgKHR5cGUpLCBzZWwubGVuZ3RoICgpKQorCSAg ICAgICYmIGtub3duX2VxIChUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSks CisJCQkgICBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcxKSkpKTsKKwogICBp ZiAoVFJFRV9UWVBFIChUUkVFX1RZUEUgKGFyZzApKSAhPSBUUkVFX1RZUEUgKHR5cGUpCiAgICAg ICB8fCBUUkVFX1RZUEUgKFRSRUVfVFlQRSAoYXJnMSkpICE9IFRSRUVfVFlQRSAodHlwZSkpCiAg ICAgcmV0dXJuIE5VTExfVFJFRTsKIAorICBpZiAoVFJFRV9DT0RFIChhcmcwKSA9PSBWRUNUT1Jf Q1NUCisgICAgICAmJiBUUkVFX0NPREUgKGFyZzEpID09IFZFQ1RPUl9DU1QpCisgICAgcmV0dXJu IGZvbGRfdmVjX3Blcm1fY3N0ICh0eXBlLCBhcmcwLCBhcmcxLCBzZWwpOworCisgIC8qIEZvciBm YWxsIGJhY2sgY2FzZSwgd2Ugd2FudCB0byBlbnN1cmUgd2UgaGF2ZSBWTFMgdmVjdG9ycworICAg ICB3aXRoIGVxdWFsIGxlbmd0aC4gICovCisgIGlmICghc2VsLmxlbmd0aCAoKS5pc19jb25zdGFu dCAoJm5lbHRzKSkKKyAgICByZXR1cm4gTlVMTF9UUkVFOworCisgIGdjY19hc3NlcnQgKGtub3du X2VxIChzZWwubGVuZ3RoICgpLAorCQkJVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAo YXJnMCkpKSk7CiAgIHRyZWUgKmluX2VsdHMgPSBYQUxMT0NBVkVDICh0cmVlLCBuZWx0cyAqIDIp OwogICBpZiAoIXZlY19jc3RfY3Rvcl90b19hcnJheSAoYXJnMCwgbmVsdHMsIGluX2VsdHMpCiAg ICAgICB8fCAhdmVjX2NzdF9jdG9yX3RvX2FycmF5IChhcmcxLCBuZWx0cywgaW5fZWx0cyArIG5l bHRzKSkKICAgICByZXR1cm4gTlVMTF9UUkVFOwogCi0gIHRyZWVfdmVjdG9yX2J1aWxkZXIgb3V0 X2VsdHMgKHR5cGUsIG5lbHRzLCAxKTsKKyAgdmVjPGNvbnN0cnVjdG9yX2VsdCwgdmFfZ2M+ICp2 OworICB2ZWNfYWxsb2MgKHYsIG5lbHRzKTsKICAgZm9yIChpID0gMDsgaSA8IG5lbHRzOyBpKysp CiAgICAgewogICAgICAgSE9TVF9XSURFX0lOVCBpbmRleDsKICAgICAgIGlmICghc2VsW2ldLmlz X2NvbnN0YW50ICgmaW5kZXgpKQogCXJldHVybiBOVUxMX1RSRUU7Ci0gICAgICBpZiAoIUNPTlNU QU5UX0NMQVNTX1AgKGluX2VsdHNbaW5kZXhdKSkKLQluZWVkX2N0b3IgPSB0cnVlOwotICAgICAg b3V0X2VsdHMucXVpY2tfcHVzaCAodW5zaGFyZV9leHByIChpbl9lbHRzW2luZGV4XSkpOwotICAg IH0KLQotICBpZiAobmVlZF9jdG9yKQotICAgIHsKLSAgICAgIHZlYzxjb25zdHJ1Y3Rvcl9lbHQs IHZhX2djPiAqdjsKLSAgICAgIHZlY19hbGxvYyAodiwgbmVsdHMpOwotICAgICAgZm9yIChpID0g MDsgaSA8IG5lbHRzOyBpKyspCi0JQ09OU1RSVUNUT1JfQVBQRU5EX0VMVCAodiwgTlVMTF9UUkVF LCBvdXRfZWx0c1tpXSk7Ci0gICAgICByZXR1cm4gYnVpbGRfY29uc3RydWN0b3IgKHR5cGUsIHYp OworICAgICAgQ09OU1RSVUNUT1JfQVBQRU5EX0VMVCAodiwgTlVMTF9UUkVFLCBpbl9lbHRzW2lu ZGV4XSk7CiAgICAgfQotICBlbHNlCi0gICAgcmV0dXJuIG91dF9lbHRzLmJ1aWxkICgpOworICBy ZXR1cm4gYnVpbGRfY29uc3RydWN0b3IgKHR5cGUsIHYpOwogfQogCiAvKiBUcnkgdG8gZm9sZCBh IHBvaW50ZXIgZGlmZmVyZW5jZSBvZiB0eXBlIFRZUEUgdHdvIGFkZHJlc3MgZXhwcmVzc2lvbnMg b2YKQEAgLTE2ODkyLDYgKzE3MDY2LDU4OCBAQCB0ZXN0X2FyaXRobWV0aWNfZm9sZGluZyAoKQog CQkJCSAgIHgpOwogfQogCituYW1lc3BhY2UgdGVzdF9mb2xkX3ZlY19wZXJtX2NzdCB7CisKKy8q IEJ1aWxkIGEgVkVDVE9SX0NTVCBjb3JyZXNwb25kaW5nIHRvIFZNT0RFLCBhbmQgaGFzCisgICBl bmNvZGluZyBnaXZlbiBieSBOUEFUVEVSTlMsIE5FTFRTX1BFUl9QQVRURVJOIGFuZCBTVEVQLgor ICAgRmlsbCBpdCB3aXRoIHJhbmRvbWl6ZWQgZWxlbWVudHMsIHVzaW5nIHJhbmQoKSAlIFRIUkVT SE9MRC4gICovCisKK3N0YXRpYyB0cmVlCitidWlsZF92ZWNfY3N0X3JhbmQgKG1hY2hpbmVfbW9k ZSB2bW9kZSwgdW5zaWduZWQgbnBhdHRlcm5zLAorCQkgICAgdW5zaWduZWQgbmVsdHNfcGVyX3Bh dHRlcm4sCisJCSAgICBpbnQgc3RlcCA9IDAsIGludCB0aHJlc2hvbGQgPSAxMDApCit7CisgIHRy ZWUgaW5uZXJfdHlwZSA9IGxhbmdfaG9va3MudHlwZXMudHlwZV9mb3JfbW9kZSAoR0VUX01PREVf SU5ORVIgKHZtb2RlKSwgMSk7CisgIHRyZWUgdmVjdHlwZSA9IGJ1aWxkX3ZlY3Rvcl90eXBlX2Zv cl9tb2RlIChpbm5lcl90eXBlLCB2bW9kZSk7CisgIHRyZWVfdmVjdG9yX2J1aWxkZXIgYnVpbGRl ciAodmVjdHlwZSwgbnBhdHRlcm5zLCBuZWx0c19wZXJfcGF0dGVybik7CisKKyAgLy8gRmlsbCBh MCBmb3IgZWFjaCBwYXR0ZXJuCisgIGZvciAodW5zaWduZWQgaSA9IDA7IGkgPCBucGF0dGVybnM7 IGkrKykKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGJ1aWxkX2ludF9jc3QgKGlubmVyX3R5cGUs IHJhbmQgKCkgJSB0aHJlc2hvbGQpKTsKKworICBpZiAobmVsdHNfcGVyX3BhdHRlcm4gPT0gMSkK KyAgICByZXR1cm4gYnVpbGRlci5idWlsZCAoKTsKKworICAvLyBGaWxsIGExIGZvciBlYWNoIHBh dHRlcm4KKyAgZm9yICh1bnNpZ25lZCBpID0gMDsgaSA8IG5wYXR0ZXJuczsgaSsrKQorICAgIGJ1 aWxkZXIucXVpY2tfcHVzaCAoYnVpbGRfaW50X2NzdCAoaW5uZXJfdHlwZSwgcmFuZCAoKSAlIHRo cmVzaG9sZCkpOworCisgIGlmIChuZWx0c19wZXJfcGF0dGVybiA9PSAyKQorICAgIHJldHVybiBi dWlsZGVyLmJ1aWxkICgpOworCisgIGZvciAodW5zaWduZWQgaSA9IG5wYXR0ZXJucyAqIDI7IGkg PCBucGF0dGVybnMgKiBuZWx0c19wZXJfcGF0dGVybjsgaSsrKQorICAgIHsKKyAgICAgIHRyZWUg cHJldl9lbGVtID0gYnVpbGRlcltpIC0gbnBhdHRlcm5zXTsKKyAgICAgIGludCBwcmV2X2VsZW1f dmFsID0gVFJFRV9JTlRfQ1NUX0xPVyAocHJldl9lbGVtKTsKKyAgICAgIGludCB2YWwgPSBwcmV2 X2VsZW1fdmFsICsgc3RlcDsKKyAgICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoYnVpbGRfaW50X2Nz dCAoaW5uZXJfdHlwZSwgdmFsKSk7CisgICAgfQorCisgIHJldHVybiBidWlsZGVyLmJ1aWxkICgp OworfQorCisvKiBWYWxpZGF0ZSByZXN1bHQgb2YgVkVDX1BFUk1fRVhQUiBmb2xkaW5nIGZvciB0 aGUgdW5pdC10ZXN0cyBiZWxvdywKKyAgIHdoZW4gcmVzdWx0IGlzIFZMQS4gICovCisKK3N0YXRp YyB2b2lkCit2YWxpZGF0ZV9yZXMgKHVuc2lnbmVkIG5wYXR0ZXJucywgdW5zaWduZWQgbmVsdHNf cGVyX3BhdHRlcm4sCisJICAgICAgdHJlZSByZXMsIHRyZWUgKmV4cGVjdGVkX3JlcykKK3sKKyAg LyogQWN0dWFsIG5wYXR0ZXJucyBhbmQgZW5jb2RlZF9lbHRzIGluIHJlcyBtYXkgYmUgbGVzcyB0 aGFuIGV4cGVjdGVkIGR1ZQorICAgICB0byBjYW5vbmljYWxpemF0aW9uLiAgKi8KKyAgQVNTRVJU X1RSVUUgKHJlcyAhPSBOVUxMX1RSRUUpOworICBBU1NFUlRfVFJVRSAoVkVDVE9SX0NTVF9OUEFU VEVSTlMgKHJlcykgPD0gbnBhdHRlcm5zKTsKKyAgQVNTRVJUX1RSVUUgKHZlY3Rvcl9jc3RfZW5j b2RlZF9uZWx0cyAocmVzKSA8PSBucGF0dGVybnMgKiBuZWx0c19wZXJfcGF0dGVybik7CisKKyAg Zm9yICh1bnNpZ25lZCBpID0gMDsgaSA8IG5wYXR0ZXJucyAqIG5lbHRzX3Blcl9wYXR0ZXJuOyBp KyspCisgICAgQVNTRVJUX1RSVUUgKG9wZXJhbmRfZXF1YWxfcCAoVkVDVE9SX0NTVF9FTFQgKHJl cywgaSksIGV4cGVjdGVkX3Jlc1tpXSwgMCkpOworfQorCisvKiBWYWxpZGF0ZSByZXN1bHQgb2Yg VkVDX1BFUk1fRVhQUiBmb2xkaW5nIGZvciB0aGUgdW5pdC10ZXN0cyBiZWxvdywKKyAgIHdoZW4g dGhlIHJlc3VsdCBpcyBWTFMuICAqLworCitzdGF0aWMgdm9pZAordmFsaWRhdGVfcmVzX3ZscyAo dHJlZSByZXMsIHRyZWUgKmV4cGVjdGVkX3JlcywgdW5zaWduZWQgZXhwZWN0ZWRfbmVsdHMpCit7 CisgIEFTU0VSVF9UUlVFIChrbm93bl9lcSAoVkVDVE9SX0NTVF9ORUxUUyAocmVzKSwgZXhwZWN0 ZWRfbmVsdHMpKTsKKyAgZm9yICh1bnNpZ25lZCBpID0gMDsgaSA8IGV4cGVjdGVkX25lbHRzOyBp KyspCisgICAgQVNTRVJUX1RSVUUgKG9wZXJhbmRfZXF1YWxfcCAoVkVDVE9SX0NTVF9FTFQgKHJl cywgaSksIGV4cGVjdGVkX3Jlc1tpXSwgMCkpOworfQorCisvKiBIZWxwZXIgcm91dGluZSB0byBw dXNoIG11bHRpcGxlIGVsZW1lbnRzIGludG8gQlVJTERFUi4gICovCit0ZW1wbGF0ZTx1bnNpZ25l ZCBOPgorc3RhdGljIHZvaWQgYnVpbGRlcl9wdXNoX2VsZW1zICh2ZWNfcGVybV9idWlsZGVyJiBi dWlsZGVyLAorCQkJCXBvbHlfdWludDY0ICgmZWxlbXMpW05dKQoreworICBmb3IgKHVuc2lnbmVk IGkgPSAwOyBpIDwgTjsgaSsrKQorICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoZWxlbXNbaV0pOwor fQorCisjZGVmaW5lIEFSRzAoaW5kZXgpIHZlY3Rvcl9jc3RfZWx0IChhcmcwLCBpbmRleCkKKyNk ZWZpbmUgQVJHMShpbmRleCkgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIGluZGV4KQorCisvKiBUZXN0 IGNhc2VzIHdoZXJlIHJlc3VsdCBpcyBWTng0U0kgYW5kIGlucHV0IHZlY3RvcnMgYXJlIFY0U0ku ICAqLworCitzdGF0aWMgdm9pZAordGVzdF92bng0c2lfdjRzaSAobWFjaGluZV9tb2RlIHZueDRz aV9tb2RlLCBtYWNoaW5lX21vZGUgdjRzaV9tb2RlKQoreworICBmb3IgKGludCBpID0gMDsgaSA8 IDEwOyBpKyspCisgICAgeworICAgICAgLyogQ2FzZSAxOgorCSBzZWwgPSB7IDAsIDQsIDEsIDUs IC4uLiB9CisJIHJlcyA9IHsgYXJnWzBdLCBhcmcxWzBdLCBhcmcwWzFdLCBhcmcxWzFdLCAuLi59 IC8vICg0LCAxKSAgKi8KKyAgICAgIHsKKwl0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQg KHY0c2lfbW9kZSwgNCwgMSwgMCk7CisJdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2 NHNpX21vZGUsIDQsIDEsIDApOworCisJdHJlZSBpbm5lcl90eXBlCisJICA9IGxhbmdfaG9va3Mu dHlwZXMudHlwZV9mb3JfbW9kZSAoR0VUX01PREVfSU5ORVIgKHZueDRzaV9tb2RlKSwgMSk7CisJ dHJlZSByZXNfdHlwZSA9IGJ1aWxkX3ZlY3Rvcl90eXBlX2Zvcl9tb2RlIChpbm5lcl90eXBlLCB2 bng0c2lfbW9kZSk7CisKKwlwb2x5X3VpbnQ2NCByZXNfbGVuID0gVFlQRV9WRUNUT1JfU1VCUEFS VFMgKHJlc190eXBlKTsKKwl2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKHJlc19sZW4sIDQsIDEp OworCXBvbHlfdWludDY0IG1hc2tfZWxlbXNbXSA9IHsgMCwgNCwgMSwgNSB9OworCWJ1aWxkZXJf cHVzaF9lbGVtcyAoYnVpbGRlciwgbWFza19lbGVtcyk7CisKKwl2ZWNfcGVybV9pbmRpY2VzIHNl bCAoYnVpbGRlciwgMiwgcmVzX2xlbik7CisJdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAo cmVzX3R5cGUsIGFyZzAsIGFyZzEsIHNlbCk7CisKKwl0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyBB UkcwKDApLCBBUkcxKDApLCBBUkcwKDEpLCBBUkcxKDEpIH07CisJdmFsaWRhdGVfcmVzICg0LCAx LCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgICAgICB9CisKKyAgICAgIC8qIENhc2UgMjogU2FtZSBh cyBjYXNlIDEsIGJ1dCBjb250YWlucyBhbiBvdXQgb2YgYm91bmRzIGFjY2VzcyB3aGljaAorCSBz aG91bGQgd3JhcCBhcm91bmQuCisJIHNlbCA9IHswLCA4LCA0LCAxMiwgLi4ufSAoNCwgMSkKKwkg cmVzID0geyBhcmcwWzBdLCBhcmcwWzBdLCBhcmcxWzBdLCBhcmcxWzBdLCAuLi4gfSAoNCwgMSku ICAqLworICAgICAgeworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodjRzaV9tb2Rl LCA0LCAxLCAwKTsKKwl0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHY0c2lfbW9kZSwg NCwgMSwgMCk7CisKKwl0cmVlIGlubmVyX3R5cGUKKwkgID0gbGFuZ19ob29rcy50eXBlcy50eXBl X2Zvcl9tb2RlIChHRVRfTU9ERV9JTk5FUiAodm54NHNpX21vZGUpLCAxKTsKKwl0cmVlIHJlc190 eXBlID0gYnVpbGRfdmVjdG9yX3R5cGVfZm9yX21vZGUgKGlubmVyX3R5cGUsIHZueDRzaV9tb2Rl KTsKKworCXBvbHlfdWludDY0IHJlc19sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAocmVzX3R5 cGUpOworCXZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAocmVzX2xlbiwgNCwgMSk7CisJcG9seV91 aW50NjQgbWFza19lbGVtc1tdID0geyAwLCA4LCA0LCAxMiB9OworCWJ1aWxkZXJfcHVzaF9lbGVt cyAoYnVpbGRlciwgbWFza19lbGVtcyk7CisKKwl2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRl ciwgMiwgcmVzX2xlbik7CisJdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAocmVzX3R5cGUs IGFyZzAsIGFyZzEsIHNlbCk7CisKKwl0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyBBUkcwKDApLCBB UkcwKDApLCBBUkcxKDApLCBBUkcxKDApIH07CisJdmFsaWRhdGVfcmVzICg0LCAxLCByZXMsIGV4 cGVjdGVkX3Jlcyk7CisgICAgICB9CisgICAgfQorfQorCisvKiBUZXN0IGNhc2VzIHdoZXJlIHJl c3VsdCBpcyBWNFNJIGFuZCBpbnB1dCB2ZWN0b3JzIGFyZSBWTng0U0kuICAqLworCitzdGF0aWMg dm9pZAordGVzdF92NHNpX3ZueDRzaSAobWFjaGluZV9tb2RlIHY0c2lfbW9kZSwgbWFjaGluZV9t b2RlIHZueDRzaV9tb2RlKQoreworICBmb3IgKGludCBpID0gMDsgaSA8IDEwOyBpKyspCisgICAg eworICAgICAgLyogQ2FzZSAxOgorCSBzZWwgPSB7IDAsIDEsIDIsIDN9CisJIHJlcyA9IHsgYXJn MFswXSwgYXJnMFsxXSwgYXJnMFsyXSwgYXJnMFszXSB9LiAgKi8KKyAgICAgIHsKKwl0cmVlIGFy ZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZueDRzaV9tb2RlLCA0LCAxKTsKKwl0cmVlIGFyZzEg PSBidWlsZF92ZWNfY3N0X3JhbmQgKHZueDRzaV9tb2RlLCA0LCAxKTsKKworCXRyZWUgaW5uZXJf dHlwZQorCSAgPSBsYW5nX2hvb2tzLnR5cGVzLnR5cGVfZm9yX21vZGUgKEdFVF9NT0RFX0lOTkVS ICh2NHNpX21vZGUpLCAxKTsKKwl0cmVlIHJlc190eXBlID0gYnVpbGRfdmVjdG9yX3R5cGVfZm9y X21vZGUgKGlubmVyX3R5cGUsIHY0c2lfbW9kZSk7CisKKwlwb2x5X3VpbnQ2NCByZXNfbGVuID0g VFlQRV9WRUNUT1JfU1VCUEFSVFMgKHJlc190eXBlKTsKKwl2ZWNfcGVybV9idWlsZGVyIGJ1aWxk ZXIgKHJlc19sZW4sIDQsIDEpOworCXBvbHlfdWludDY0IG1hc2tfZWxlbXNbXSA9IHswLCAxLCAy LCAzfTsKKwlidWlsZGVyX3B1c2hfZWxlbXMgKGJ1aWxkZXIsIG1hc2tfZWxlbXMpOworCisJdmVj X3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIHJlc19sZW4pOworCXRyZWUgcmVzID0gZm9s ZF92ZWNfcGVybV9jc3QgKHJlc190eXBlLCBhcmcwLCBhcmcxLCBzZWwpOworCisJdHJlZSBleHBl Y3RlZF9yZXNbXSA9IHsgQVJHMCgwKSwgQVJHMCgxKSwgQVJHMCgyKSwgQVJHMCgzKSB9OworCXZh bGlkYXRlX3Jlc192bHMgKHJlcywgZXhwZWN0ZWRfcmVzLCA0KTsKKyAgICAgIH0KKworICAgICAg LyogQ2FzZSAyOiBTYW1lIGFzIENhc2UgMSwgYnV0IGNyb3NzaW5nIGlucHV0IHZlY3Rvci4KKwkg c2VsID0gezAsIDIsIDQsIDZ9CisJIEluIHRoaXMgY2FzZSx0aGUgaW5kZXggNCBpcyBhbWJpZ3Vv dXMgc2luY2UgbGVuID0gNCArIDR4LgorCSBTaW5jZSB3ZSBjYW5ub3QgZGV0ZXJtaW5lLCB3aGlj aCB2ZWN0b3IgdG8gY2hvb3NlIGZyb20gZHVyaW5nCisJIGNvbXBpbGUgdGltZSwgc2hvdWxkIHJl dHVybiBOVUxMX1RSRUUuICAqLworICAgICAgeworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3Rf cmFuZCAodm54NHNpX21vZGUsIDQsIDEpOworCXRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFu ZCAodm54NHNpX21vZGUsIDQsIDEpOworCisJdHJlZSBpbm5lcl90eXBlCisJICA9IGxhbmdfaG9v a3MudHlwZXMudHlwZV9mb3JfbW9kZSAoR0VUX01PREVfSU5ORVIgKHY0c2lfbW9kZSksIDEpOwor CXRyZWUgcmVzX3R5cGUgPSBidWlsZF92ZWN0b3JfdHlwZV9mb3JfbW9kZSAoaW5uZXJfdHlwZSwg djRzaV9tb2RlKTsKKworCXBvbHlfdWludDY0IHJlc19sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJU UyAocmVzX3R5cGUpOworCXZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAocmVzX2xlbiwgNCwgMSk7 CisJcG9seV91aW50NjQgbWFza19lbGVtc1tdID0gezAsIDIsIDQsIDZ9OworCWJ1aWxkZXJfcHVz aF9lbGVtcyAoYnVpbGRlciwgbWFza19lbGVtcyk7CisKKwl2ZWNfcGVybV9pbmRpY2VzIHNlbCAo YnVpbGRlciwgMiwgcmVzX2xlbik7CisJY29uc3QgY2hhciAqcmVhc29uOworCXRyZWUgcmVzID0g Zm9sZF92ZWNfcGVybV9jc3QgKHJlc190eXBlLCBhcmcwLCBhcmcxLCBzZWwsICZyZWFzb24pOwor CisJQVNTRVJUX1RSVUUgKHJlcyA9PSBOVUxMX1RSRUUpOworCUFTU0VSVF9UUlVFICghc3RyY21w IChyZWFzb24sICJjYW5ub3QgZGl2aWRlIHNlbGVjdG9yIGVsZW1lbnQgYnkgYXJnIGxlbiIpKTsK KyAgICAgIH0KKyAgICB9Cit9CisKKy8qIFRlc3QgYWxsIGlucHV0IHZlY3RvcnMuICAqLworCitz dGF0aWMgdm9pZAordGVzdF9hbGxfbnVuaXRzIChtYWNoaW5lX21vZGUgdm1vZGUpCit7CisgIC8q IFRlc3Qgd2l0aCAxMCBkaWZmZXJlbnQgaW5wdXRzLiAgKi8KKyAgZm9yIChpbnQgaSA9IDA7IGkg PCAxMDsgaSsrKQorICAgIHsKKyAgICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAo dm1vZGUsIDEsIDMsIDEpOworICAgICAgdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2 bW9kZSwgMSwgMywgMSk7CisgICAgICBwb2x5X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQ QVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKyAgICAgIC8qIENhc2UgMTogbWFzayA9IHswLCAu Li59IC8vICgxLCAxKQorCSByZXMgPSB7IGFyZzBbMF0sIC4uLiB9IC8vICgxLCAxKSAgKi8KKyAg ICAgIHsKKwl2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGxlbiwgMSwgMSk7CisJYnVpbGRlci5x dWlja19wdXNoICgwKTsKKwl2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgbGVuKTsK Kwl0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBhcmcwLCBh cmcxLCBzZWwpOworCXRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IEFSRzAoMCkgfTsKKwl2YWxpZGF0 ZV9yZXMgKDEsIDEsIHJlcywgZXhwZWN0ZWRfcmVzKTsKKyAgICAgIH0KKworICAgICAgLyogQ2Fz ZSAyOiBtYXNrID0ge2xlbiwgLi4ufSAvLyAoMSwgMSkKKwkgcmVzID0geyBhcmcxWzBdLCAuLi4g fSAvLyAoMSwgMSkgICovCisgICAgICB7CisJdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChsZW4s IDEsIDEpOworCWJ1aWxkZXIucXVpY2tfcHVzaCAobGVuKTsKKwl2ZWNfcGVybV9pbmRpY2VzIHNl bCAoYnVpbGRlciwgMiwgbGVuKTsKKwl0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVF X1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBzZWwpOworCisJdHJlZSBleHBlY3RlZF9yZXNbXSA9 IHsgQVJHMSgwKSB9OworCXZhbGlkYXRlX3JlcyAoMSwgMSwgcmVzLCBleHBlY3RlZF9yZXMpOwor ICAgICAgfQorICAgIH0KK30KKworLyogVGVzdCBhbGwgdmVjdG9ycyB3aGljaCBjb250YWluIGF0 LWxlYXN0IDIgZWxlbWVudHMuICAqLworCitzdGF0aWMgdm9pZAordGVzdF9udW5pdHNfbWluXzIg KG1hY2hpbmVfbW9kZSB2bW9kZSkKK3sKKyAgZm9yIChpbnQgaSA9IDA7IGkgPCAxMDsgaSsrKQor ICAgIHsKKyAgICAgIC8qIENhc2UgMTogbWFzayA9IHsgMCwgbGVuLCAuLi4gfSAgLy8gKDIsIDEp CisJIHJlcyA9IHsgYXJnMFswXSwgYXJnMVswXSwgLi4uIH0gLy8gKDIsIDEpICAqLworICAgICAg eworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDEpOworCXRy ZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDEpOworCXBvbHlfdWlu dDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworCXZl Y19wZXJtX2J1aWxkZXIgYnVpbGRlciAobGVuLCAyLCAxKTsKKwlwb2x5X3VpbnQ2NCBtYXNrX2Vs ZW1zW10gPSB7IDAsIGxlbiB9OworCWJ1aWxkZXJfcHVzaF9lbGVtcyAoYnVpbGRlciwgbWFza19l bGVtcyk7CisKKwl2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgbGVuKTsKKwl0cmVl IHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBz ZWwpOworCisJdHJlZSBleHBlY3RlZF9yZXNbXSA9IHsgQVJHMCgwKSwgQVJHMSgwKSB9OworCXZh bGlkYXRlX3JlcyAoMiwgMSwgcmVzLCBleHBlY3RlZF9yZXMpOworICAgICAgfQorCisgICAgICAv KiBDYXNlIDI6IG1hc2sgPSB7IDAsIGxlbiwgMSwgbGVuKzEsIC4uLiB9IC8vICgyLCAyKQorCSBy ZXMgPSB7IGFyZzBbMF0sIGFyZzFbMF0sIGFyZzBbMV0sIGFyZzFbMV0sIC4uLiB9IC8vICgyLCAy KSAgKi8KKyAgICAgIHsKKwl0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAx LCAzLCAxKTsKKwl0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAxLCAzLCAx KTsKKwlwb2x5X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChh cmcwKSk7CisKKwl2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGxlbiwgMiwgMik7CisJcG9seV91 aW50NjQgbWFza19lbGVtc1tdID0geyAwLCBsZW4sIDEsIGxlbiArIDEgfTsKKwlidWlsZGVyX3B1 c2hfZWxlbXMgKGJ1aWxkZXIsIG1hc2tfZWxlbXMpOworCisJdmVjX3Blcm1faW5kaWNlcyBzZWwg KGJ1aWxkZXIsIDIsIGxlbik7CisJdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9U WVBFIChhcmcwKSwgYXJnMCwgYXJnMSwgc2VsKTsKKworCXRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7 IEFSRzAoMCksIEFSRzEoMCksIEFSRzAoMSksIEFSRzEoMSkgfTsKKwl2YWxpZGF0ZV9yZXMgKDIs IDIsIHJlcywgZXhwZWN0ZWRfcmVzKTsKKyAgICAgIH0KKworICAgICAgLyogQ2FzZSA0OiBtYXNr ID0gezAsIDAsIDEsIC4uLn0gLy8gKDEsIDMpCisJIFRlc3QgdGhhdCB0aGUgc3RlcHBlZCBzZXF1 ZW5jZSBvZiB0aGUgcGF0dGVybiBzZWxlY3RzIGZyb20KKwkgc2FtZSBpbnB1dCBwYXR0ZXJuLiBT aW5jZSBpbnB1dCB2ZWN0b3JzIGhhdmUgbnBhdHRlcm5zID0gMiwKKwkgYW5kIHN0ZXAgKGEyIC0g YTEpID0gMSwgc3RlcCBpcyBub3QgYSBtdWx0aXBsZSBvZiBucGF0dGVybnMKKwkgaW4gaW5wdXQg dmVjdG9yLiBTbyByZXR1cm4gTlVMTF9UUkVFLiAgKi8KKyAgICAgIHsKKwl0cmVlIGFyZzAgPSBi dWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAyLCAzLCAxKTsKKwl0cmVlIGFyZzEgPSBidWlsZF92 ZWNfY3N0X3JhbmQgKHZtb2RlLCAyLCAzLCAxKTsKKwlwb2x5X3VpbnQ2NCBsZW4gPSBUWVBFX1ZF Q1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKwl2ZWNfcGVybV9idWlsZGVyIGJ1 aWxkZXIgKGxlbiwgMSwgMyk7CisJcG9seV91aW50NjQgbWFza19lbGVtc1tdID0geyAwLCAwLCAx IH07CisJYnVpbGRlcl9wdXNoX2VsZW1zIChidWlsZGVyLCBtYXNrX2VsZW1zKTsKKworCXZlY19w ZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBsZW4pOworCWNvbnN0IGNoYXIgKnJlYXNvbjsK Kwl0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBhcmcwLCBh cmcxLCBzZWwsCisJCQkJICAgICAgJnJlYXNvbik7CisJQVNTRVJUX1RSVUUgKHJlcyA9PSBOVUxM X1RSRUUpOworCUFTU0VSVF9UUlVFICghc3RyY21wIChyZWFzb24sICJzdGVwIGlzIG5vdCBtdWx0 aXBsZSBvZiBucGF0dGVybnMiKSk7CisgICAgICB9CisKKyAgICAgIC8qIENhc2UgNTogbWFzayA9 IHtsZW4sIDAsIDEsIC4uLn0gLy8gKDEsIDMpCisJIFRlc3QgdGhhdCBzdGVwcGVkIHNlcXVlbmNl IG9mIHRoZSBwYXR0ZXJuIHNlbGVjdHMgZnJvbSBhcmcwLgorCSByZXMgPSB7IGFyZzFbMF0sIGFy ZzBbMF0sIGFyZzBbMV0sIC4uLiB9IC8vICgxLCAzKSAgKi8KKyAgICAgIHsKKwl0cmVlIGFyZzAg PSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAxLCAzLCAxKTsKKwl0cmVlIGFyZzEgPSBidWls ZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAxLCAzLCAxKTsKKwlwb2x5X3VpbnQ2NCBsZW4gPSBUWVBF X1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKwl2ZWNfcGVybV9idWlsZGVy IGJ1aWxkZXIgKGxlbiwgMSwgMyk7CisJcG9seV91aW50NjQgbWFza19lbGVtc1tdID0geyBsZW4s IDAsIDEgfTsKKwlidWlsZGVyX3B1c2hfZWxlbXMgKGJ1aWxkZXIsIG1hc2tfZWxlbXMpOworCisJ dmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7CisJdHJlZSByZXMgPSBmb2xk X3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcwKSwgYXJnMCwgYXJnMSwgc2VsKTsKKworCXRy ZWUgZXhwZWN0ZWRfcmVzW10gPSB7IEFSRzEoMCksIEFSRzAoMCksIEFSRzAoMSkgfTsKKwl2YWxp ZGF0ZV9yZXMgKDEsIDMsIHJlcywgZXhwZWN0ZWRfcmVzKTsKKyAgICAgIH0KKyAgICB9Cit9CisK Ky8qIFRlc3QgYWxsIHZlY3RvcnMgd2hpY2ggY29udGFpbiBhdC1sZWFzdCA0IGVsZW1lbnRzLiAg Ki8KKworc3RhdGljIHZvaWQKK3Rlc3RfbnVuaXRzX21pbl80IChtYWNoaW5lX21vZGUgdm1vZGUp Cit7CisgIGZvciAoaW50IGkgPSAwOyBpIDwgMTA7IGkrKykKKyAgICB7CisgICAgICAvKiBDYXNl IDE6IG1hc2sgPSB7IDAsIGxlbiwgMSwgbGVuKzEsIC4uLiB9IC8vICg0LCAxKQorCSByZXM6IHsg YXJnMFswXSwgYXJnMVswXSwgYXJnMFsxXSwgYXJnMVsxXSwgLi4uIH0gLy8gKDQsIDEpICAqLwor ICAgICAgeworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDEp OworCXRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDEpOworCXBv bHlfdWludDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsK KworCXZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAobGVuLCA0LCAxKTsKKwlwb2x5X3VpbnQ2NCBt YXNrX2VsZW1zW10gPSB7IDAsIGxlbiwgMSwgbGVuICsgMSB9OworCWJ1aWxkZXJfcHVzaF9lbGVt cyAoYnVpbGRlciwgbWFza19lbGVtcyk7CisKKwl2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRl ciwgMiwgbGVuKTsKKwl0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFy ZzApLCBhcmcwLCBhcmcxLCBzZWwpOworCisJdHJlZSBleHBlY3RlZF9yZXNbXSA9IHsgQVJHMCgw KSwgQVJHMSgwKSwgQVJHMCgxKSwgQVJHMSgxKSB9OworCXZhbGlkYXRlX3JlcyAoNCwgMSwgcmVz LCBleHBlY3RlZF9yZXMpOworICAgICAgfQorCisgICAgICAvKiBDYXNlIDI6IHNlbCA9IHswLCAx LCAyLCAuLi59ICAvLyAoMSwgMykKKwkgcmVzOiB7IGFyZzBbMF0sIGFyZzBbMV0sIGFyZzBbMl0s IC4uLiB9IC8vICgxLCAzKSAqLworICAgICAgeworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3Rf cmFuZCAodm1vZGUsIDEsIDMsIDIpOworCXRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAo dm1vZGUsIDEsIDMsIDIpOworCXBvbHlfdWludDY0IGFyZzBfbGVuID0gVFlQRV9WRUNUT1JfU1VC UEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisJdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChh cmcwX2xlbiwgMSwgMyk7CisJcG9seV91aW50NjQgbWFza19lbGVtc1tdID0gezAsIDEsIDJ9Owor CWJ1aWxkZXJfcHVzaF9lbGVtcyAoYnVpbGRlciwgbWFza19lbGVtcyk7CisKKwl2ZWNfcGVybV9p bmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgYXJnMF9sZW4pOworCXRyZWUgcmVzID0gZm9sZF92ZWNf cGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFyZzAsIGFyZzEsIHNlbCk7CisJdHJlZSBleHBl Y3RlZF9yZXNbXSA9IHsgQVJHMCgwKSwgQVJHMCgxKSwgQVJHMCgyKSB9OworCXZhbGlkYXRlX3Jl cyAoMSwgMywgcmVzLCBleHBlY3RlZF9yZXMpOworICAgICAgfQorCisgICAgICAvKiBDYXNlIDM6 IHNlbCA9IHtsZW4sIGxlbisxLCBsZW4rMiwgLi4ufSAvLyAoMSwgMykKKwkgcmVzOiB7IGFyZzFb MF0sIGFyZzFbMV0sIGFyZzFbMl0sIC4uLiB9IC8vICgxLCAzKSAqLworICAgICAgeworCXRyZWUg YXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDIpOworCXRyZWUgYXJnMSA9 IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDIpOworCXBvbHlfdWludDY0IGxlbiA9 IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworCXZlY19wZXJtX2J1 aWxkZXIgYnVpbGRlciAobGVuLCAxLCAzKTsKKwlwb2x5X3VpbnQ2NCBtYXNrX2VsZW1zW10gPSB7 bGVuLCBsZW4gKyAxLCBsZW4gKyAyfTsKKwlidWlsZGVyX3B1c2hfZWxlbXMgKGJ1aWxkZXIsIG1h c2tfZWxlbXMpOworCisJdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7CisJ dHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcwKSwgYXJnMCwgYXJn MSwgc2VsKTsKKwl0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyBBUkcxKDApLCBBUkcxKDEpLCBBUkcx KDIpIH07CisJdmFsaWRhdGVfcmVzICgxLCAzLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgICAgICB9 CisKKyAgICAgIC8qIENhc2UgNDoKKwlzZWwgPSB7IGxlbiwgMCwgMiwgLi4uIH0gLy8gKDEsIDMp CisJVGhpcyBzaG91bGQgcmV0dXJuIE5VTEwgYmVjYXVzZSB3ZSBjcm9zcyB0aGUgaW5wdXQgdmVj dG9ycy4KKwlCZWNhdXNlLAorCUxldCdzIGFzc3VtZSBsZW4gPSBDICsgQ3gKKwlhMSA9IDAKKwlT ID0gMgorCWVzZWwgPSBhcmcwX2xlbiAvIHNlbF9ucGF0dGVybnMgPSBDICsgQ3gKKwlhZSA9IDAg KyAoZXNlbCAtIDIpICogUworCSAgID0gMCArIChDICsgQ3ggLSAyKSAqIDIKKwkgICA9IDIoQy0y KSArIDJDeAorCisJRm9yIEMgPj0gNDoKKwlMZXQgcTEgPSBhMSAvIGFyZzBfbGVuID0gMCAvIChD ICsgQ3gpID0gMAorCUxldCBxZSA9IGFlIC8gYXJnMF9sZW4gPSAoMihDLTIpICsgMkN4KSAvIChD ICsgQ3gpID0gMQorCVNpbmNlIHExICE9IHFlLCB3ZSBjcm9zcyBpbnB1dCB2ZWN0b3JzLgorCVNv IHJldHVybiBOVUxMX1RSRUUuICAqLworICAgICAgeworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19j c3RfcmFuZCAodm1vZGUsIDEsIDMsIDIpOworCXRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFu ZCAodm1vZGUsIDEsIDMsIDIpOworCXBvbHlfdWludDY0IGFyZzBfbGVuID0gVFlQRV9WRUNUT1Jf U1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisJdmVjX3Blcm1fYnVpbGRlciBidWlsZGVy IChhcmcwX2xlbiwgMSwgMyk7CisJcG9seV91aW50NjQgbWFza19lbGVtc1tdID0geyBhcmcwX2xl biwgMCwgMiB9OworCWJ1aWxkZXJfcHVzaF9lbGVtcyAoYnVpbGRlciwgbWFza19lbGVtcyk7CisK Kwl2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgYXJnMF9sZW4pOworCWNvbnN0IGNo YXIgKnJlYXNvbjsKKwl0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFy ZzApLCBhcmcwLCBhcmcxLCBzZWwsICZyZWFzb24pOworCUFTU0VSVF9UUlVFIChyZXMgPT0gTlVM TF9UUkVFKTsKKwlBU1NFUlRfVFJVRSAoIXN0cmNtcCAocmVhc29uLCAiY3Jvc3NlZCBpbnB1dCB2 ZWN0b3JzIikpOworICAgICAgfQorCisgICAgICAvKiBDYXNlIDU6IG5wYXR0ZXJucyhhcmcwKSA9 IDQgPiBucGF0dGVybnMoc2VsKSA9IDIKKwkgbWFzayA9IHsgMCwgbGVuLCAxLCBsZW4gKyAxLCAu Li59IC8vICgyLCAyKQorCSByZXMgPSB7IGFyZzBbMF0sIGFyZzFbMF0sIGFyZzBbMV0sIGFyZzFb MV0sIC4uLiB9IC8vICgyLCAyKQorCisJIE5vdGUgdGhhdCBmb2xkX3ZlY19wZXJtX2NzdCB3aWxs IHNldAorCSByZXNfbnBhdHRlcm5zID0gbWF4KDQsIG1heCg0LCAyKSkgPSA0CisJIEhvd2V2ZXIg YWZ0ZXIgY2Fub25pY2FsaXppbmcsIHdlIHdpbGwgZW5kIHVwIHdpdGggc2hhcGUgKDIsIDIpLiAg Ki8KKyAgICAgIHsKKwl0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCA0LCAx KTsKKwl0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCA0LCAxKTsKKwlwb2x5 X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisK Kwl2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGxlbiwgMiwgMik7CisJcG9seV91aW50NjQgbWFz a19lbGVtc1tdID0geyAwLCBsZW4sIDEsIGxlbiArIDEgfTsKKwlidWlsZGVyX3B1c2hfZWxlbXMg KGJ1aWxkZXIsIG1hc2tfZWxlbXMpOworCisJdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIs IDIsIGxlbik7CisJdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcw KSwgYXJnMCwgYXJnMSwgc2VsKTsKKwl0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyBBUkcwKDApLCBB UkcxKDApLCBBUkcwKDEpLCBBUkcxKDEpIH07CisJdmFsaWRhdGVfcmVzICgyLCAyLCByZXMsIGV4 cGVjdGVkX3Jlcyk7CisgICAgICB9CisKKyAgICAgIC8qIENhc2UgNjogVGVzdCBjb21iaW5hdGlv biBpbiBzZWwsIHdoZXJlIG9uZSBwYXR0ZXJuIGlzIGR1cCBhbmQgb3RoZXIKKwkgaXMgc3RlcHBl ZCBzZXF1ZW5jZS4KKwkgc2VsID0geyAwLCAwLCAwLCAxLCAwLCAyLCAuLi4gfSAvLyAoMiwgMykK KwkgcmVzID0geyBhcmcwWzBdLCBhcmcwWzBdLCBhcmcwWzBdLAorCQkgYXJnMFsxXSwgYXJnMFsw XSwgYXJnMFsyXSwgLi4uIH0gLy8gKDIsIDMpICAqLworICAgICAgeworCXRyZWUgYXJnMCA9IGJ1 aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDEpOworCXRyZWUgYXJnMSA9IGJ1aWxkX3Zl Y19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDEpOworCXBvbHlfdWludDY0IGxlbiA9IFRZUEVfVkVD VE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworCXZlY19wZXJtX2J1aWxkZXIgYnVp bGRlciAobGVuLCAyLCAzKTsKKwlwb2x5X3VpbnQ2NCBtYXNrX2VsZW1zW10gPSB7IDAsIDAsIDAs IDEsIDAsIDIgfTsKKwlidWlsZGVyX3B1c2hfZWxlbXMgKGJ1aWxkZXIsIG1hc2tfZWxlbXMpOwor CisJdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7CisJdHJlZSByZXMgPSBm b2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcwKSwgYXJnMCwgYXJnMSwgc2VsKTsKKwor CXRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IEFSRzAoMCksIEFSRzAoMCksIEFSRzAoMCksCisJCQkJ QVJHMCgxKSwgQVJHMCgwKSwgQVJHMCgyKSB9OworCXZhbGlkYXRlX3JlcyAoMiwgMywgcmVzLCBl eHBlY3RlZF9yZXMpOworICAgICAgfQorICAgIH0KK30KKworLyogVGVzdCBhbGwgdmVjdG9ycyB3 aGljaCBjb250YWluIGF0LWxlYXN0IDggZWxlbWVudHMuICAqLworCitzdGF0aWMgdm9pZAordGVz dF9udW5pdHNfbWluXzggKG1hY2hpbmVfbW9kZSB2bW9kZSkKK3sKKyAgZm9yIChpbnQgaSA9IDA7 IGkgPCAxMDsgaSsrKQorICAgIHsKKyAgICAgIC8qIENhc2UgMTogc2VsX25wYXR0ZXJucyAoNCkg PiBpbnB1dCBucGF0dGVybnMgKDIpCisJIHNlbDogeyAwLCAwLCAxLCBsZW4sIDIsIDAsIDMsIGxl biwgNCwgMCwgNSwgbGVuLCAuLi59IC8vICg0LCAzKQorCSByZXM6IHsgYXJnMFswXSwgYXJnMFsw XSwgYXJnMFswXSwgYXJnMVswXSwKKwkJYXJnMFsyXSwgYXJnMFswXSwgYXJnMFszXSwgYXJnMVsw XSwKKwkJYXJnMFs0XSwgYXJnMFswXSwgYXJnMFs1XSwgYXJnMVswXSwgLi4uIH0gLy8gKDQsIDMp ICAqLworICAgICAgeworCXRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIs IDMsIDIpOworCXRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDIp OworCXBvbHlfdWludDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFy ZzApKTsKKworCXZlY19wZXJtX2J1aWxkZXIgYnVpbGRlcihsZW4sIDQsIDMpOworCXBvbHlfdWlu dDY0IG1hc2tfZWxlbXNbXSA9IHsgMCwgMCwgMSwgbGVuLCAyLCAwLCAzLCBsZW4sCisJCQkJICAg ICA0LCAwLCA1LCBsZW4gfTsKKwlidWlsZGVyX3B1c2hfZWxlbXMgKGJ1aWxkZXIsIG1hc2tfZWxl bXMpOworCisJdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7CisJdHJlZSBy ZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcwKSwgYXJnMCwgYXJnMSwgc2Vs KTsKKworCXRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IEFSRzAoMCksIEFSRzAoMCksIEFSRzAoMSks IEFSRzEoMCksCisJCQkJQVJHMCgyKSwgQVJHMCgwKSwgQVJHMCgzKSwgQVJHMSgwKSwKKwkJCQlB UkcwKDQpLCBBUkcwKDApLCBBUkcwKDUpLCBBUkcxKDApIH07CisJdmFsaWRhdGVfcmVzICg0LCAz LCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgICAgICB9CisgICAgfQorfQorCisvKiBUZXN0IHZlY3Rv cnMgZm9yIHdoaWNoIG51bml0c1swXSA8PSA0LiAgKi8KKworc3RhdGljIHZvaWQKK3Rlc3RfbnVu aXRzX21heF80IChtYWNoaW5lX21vZGUgdm1vZGUpCit7CisgIC8qIENhc2UgMTogbWFzayA9IHsw LCA0LCAuLi59IC8vICgxLCAyKQorICAgICBUaGlzIHNob3VsZCByZXR1cm4gTlVMTF9UUkVFIGJl Y2F1c2UgdGhlIGluZGV4IDQgbWF5IGNob29zZQorICAgICBmcm9tIGVpdGhlciBhcmcwIG9yIGFy ZzEgZGVwZW5kaW5nIG9uIHZlY3RvciBsZW5ndGguICAqLworICB7CisgICAgdHJlZSBhcmcwID0g YnVpbGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMSwgMywgMSk7CisgICAgdHJlZSBhcmcxID0gYnVp bGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMSwgMywgMSk7CisgICAgcG9seV91aW50NjQgbGVuID0g VFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisgICAgdmVjX3Blcm1f YnVpbGRlciBidWlsZGVyIChsZW4sIDEsIDIpOworICAgIHBvbHlfdWludDY0IG1hc2tfZWxlbXNb XSA9IHswLCA0fTsKKyAgICBidWlsZGVyX3B1c2hfZWxlbXMgKGJ1aWxkZXIsIG1hc2tfZWxlbXMp OworCisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7CisgICAgY29u c3QgY2hhciAqcmVhc29uOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKFRSRUVf VFlQRSAoYXJnMCksIGFyZzAsIGFyZzEsIHNlbCwgJnJlYXNvbik7CisgICAgQVNTRVJUX1RSVUUg KHJlcyA9PSBOVUxMX1RSRUUpOworICAgIEFTU0VSVF9UUlVFIChyZWFzb24gIT0gTlVMTCk7Cisg ICAgQVNTRVJUX1RSVUUgKCFzdHJjbXAgKHJlYXNvbiwgImNhbm5vdCBkaXZpZGUgc2VsZWN0b3Ig ZWxlbWVudCBieSBhcmcgbGVuIikpOworICB9Cit9CisKKyN1bmRlZiBBUkcwCisjdW5kZWYgQVJH MQorCisvKiBSZXR1cm4gdHJ1ZSBpZiBTSVpFIGlzIG9mIHRoZSBmb3JtIEMgKyBDeCBhbmQgQyBp cyBwb3dlciBvZiAyLiAgKi8KKworc3RhdGljIGJvb2wKK2lzX3NpbXBsZV92bGFfc2l6ZSAocG9s eV91aW50NjQgc2l6ZSkKK3sKKyAgaWYgKHNpemUuaXNfY29uc3RhbnQgKCkKKyAgICAgIHx8ICFw b3cycF9od2kgKHNpemUuY29lZmZzWzBdKSkKKyAgICByZXR1cm4gZmFsc2U7CisgIGZvciAodW5z aWduZWQgaSA9IDE7IGkgPCBBUlJBWV9TSVpFIChzaXplLmNvZWZmcyk7ICsraSkKKyAgICBpZiAo c2l6ZS5jb2VmZnNbaV0gIT0gKGkgPD0gMSA/IHNpemUuY29lZmZzWzBdIDogMCkpCisgICAgICBy ZXR1cm4gZmFsc2U7CisgIHJldHVybiB0cnVlOworfQorCisvKiBFeGVjdXRlIGZvbGRfdmVjX3Bl cm1fY3N0IHVuaXQgdGVzdHMuICAqLworCitzdGF0aWMgdm9pZAordGVzdCAoKQoreworICBtYWNo aW5lX21vZGUgdm54NHNpX21vZGUgPSBFX1ZPSURtb2RlOworICBtYWNoaW5lX21vZGUgdjRzaV9t b2RlID0gRV9WT0lEbW9kZTsKKworICBtYWNoaW5lX21vZGUgdm1vZGU7CisgIEZPUl9FQUNIX01P REVfSU5fQ0xBU1MgKHZtb2RlLCBNT0RFX1ZFQ1RPUl9JTlQpCisgICAgeworICAgICAgLyogT2J0 YWluIG1vZGVzIGNvcnJlc3BvbmRpbmcgdG8gVk54NFNJIGFuZCBWNFNJLAorCSB0byBjYWxsIG1p eGVkIG1vZGUgdGVzdHMgYmVsb3cuCisJIEZJWE1FOiBJcyB0aGVyZSBhIGJldHRlciB3YXkgdG8g ZG8gdGhpcyA/ICAqLworICAgICAgaWYgKEdFVF9NT0RFX0lOTkVSICh2bW9kZSkgPT0gU0ltb2Rl KQorCXsKKwkgIHBvbHlfdWludDY0IG51bml0cyA9IEdFVF9NT0RFX05VTklUUyAodm1vZGUpOwor CSAgaWYgKGlzX3NpbXBsZV92bGFfc2l6ZSAobnVuaXRzKQorCSAgICAgICYmIG51bml0cy5jb2Vm ZnNbMF0gPT0gNCkKKwkgICAgdm54NHNpX21vZGUgPSB2bW9kZTsKKwkgIGVsc2UgaWYgKGtub3du X2VxIChudW5pdHMsIHBvbHlfdWludDY0ICg0KSkpCisJICAgIHY0c2lfbW9kZSA9IHZtb2RlOwor CX0KKworICAgICAgaWYgKCFpc19zaW1wbGVfdmxhX3NpemUgKEdFVF9NT0RFX05VTklUUyAodm1v ZGUpKQorCSAgfHwgIXRhcmdldG0udmVjdG9yX21vZGVfc3VwcG9ydGVkX3AgKHZtb2RlKSkKKwlj b250aW51ZTsKKworICAgICAgcG9seV91aW50NjQgbnVuaXRzID0gR0VUX01PREVfTlVOSVRTICh2 bW9kZSk7CisgICAgICB0ZXN0X2FsbF9udW5pdHMgKHZtb2RlKTsKKyAgICAgIGlmIChudW5pdHMu Y29lZmZzWzBdID49IDIpCisJdGVzdF9udW5pdHNfbWluXzIgKHZtb2RlKTsKKyAgICAgIGlmIChu dW5pdHMuY29lZmZzWzBdID49IDQpCisJdGVzdF9udW5pdHNfbWluXzQgKHZtb2RlKTsKKyAgICAg IGlmIChudW5pdHMuY29lZmZzWzBdID49IDgpCisJdGVzdF9udW5pdHNfbWluXzggKHZtb2RlKTsK KworICAgICAgaWYgKG51bml0cy5jb2VmZnNbMF0gPD0gNCkKKwl0ZXN0X251bml0c19tYXhfNCAo dm1vZGUpOworICAgIH0KKworICBpZiAodm54NHNpX21vZGUgIT0gRV9WT0lEbW9kZSAmJiB2NHNp X21vZGUgIT0gRV9WT0lEbW9kZQorICAgICAgJiYgdGFyZ2V0bS52ZWN0b3JfbW9kZV9zdXBwb3J0 ZWRfcCAodm54NHNpX21vZGUpCisgICAgICAmJiB0YXJnZXRtLnZlY3Rvcl9tb2RlX3N1cHBvcnRl ZF9wICh2NHNpX21vZGUpKQorICAgIHsKKyAgICAgIHRlc3Rfdm54NHNpX3Y0c2kgKHZueDRzaV9t b2RlLCB2NHNpX21vZGUpOworICAgICAgdGVzdF92NHNpX3ZueDRzaSAodjRzaV9tb2RlLCB2bng0 c2lfbW9kZSk7CisgICAgfQorfQorfSAvLyBlbmQgb2YgdGVzdF9mb2xkX3ZlY19wZXJtX2NzdCBu YW1lc3BhY2UKKwogLyogVmVyaWZ5IHRoYXQgdmFyaW91cyBiaW5hcnkgb3BlcmF0aW9ucyBvbiB2 ZWN0b3JzIGFyZSBmb2xkZWQKICAgIGNvcnJlY3RseS4gICovCiAKQEAgLTE2OTQzLDYgKzE3Njk5 LDcgQEAgZm9sZF9jb25zdF9jY190ZXN0cyAoKQogICB0ZXN0X2FyaXRobWV0aWNfZm9sZGluZyAo KTsKICAgdGVzdF92ZWN0b3JfZm9sZGluZyAoKTsKICAgdGVzdF92ZWNfZHVwbGljYXRlX2ZvbGRp bmcgKCk7CisgIHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnRlc3QgKCk7CiB9CiAKIH0gLy8gbmFt ZXNwYWNlIHNlbGZ0ZXN0Cg== --0000000000003a81f90602f481f0--