> -----Original Message----- > From: Richard Sandiford <richard.sandif...@arm.com> > Sent: Friday, September 20, 2024 2:10 PM > To: Tamar Christina <tamar.christ...@arm.com> > Cc: gcc-patches@gcc.gnu.org; nd <n...@arm.com> > Subject: Re: [PATCH 3/4][rtl]: simplify boolean vector EQ and NE comparisons > > Tamar Christina <tamar.christ...@arm.com> writes: > >> For variable-sized vectors, I suppose the question is whether the > >> first unequal element is found in the minimum vector length, or whether > >> it only occurs for larger lengths. In the former case we can fold at > >> compile time, but in the latter case we can't. > >> > >> So we probably do want the loop for variable-length vectors, up to > >> constant_lower_bound (CONST_VECTOR_NUNITS (...)). > >> > > > > Doesn't operand_equal already do this? it looks like the VLA handling > > In same_vector_encodings_p rejects vectors that are not the same size, > > which is good enough for this no? since I'm after strict equality. > > But what I meant is that for VLA vectors, compile-time equality is > a tristate value: yes, no, or maybe. > > E.g.: > > { 0, 0, 0, 0, 0, 0, 0, 0, ... } > > is not equal to > > { 0, 0, 1, 1, 1, 1, 1, 1, ... } > > if the runtime VL gives more than 2 elements, but they are equal if > the runtime VL gives 2 elements. In this case, we can't fold EQ to > false at compile time if the minimum length is 2 elements, but we can > if the minimum length is 4 elements. > > Similarly: > > { 0, 0, 1, 1, 1, 1, 1, 1, ... } > > is only conditionally not equal to: > > { 0, 0, 1, 1, 2, 2, 3, 3, ... } > > It isn't the case that every encoded value has to be present in every > runtime vector. E.g. the series { 0, 1, 2, ... } exists for VNx2DI > (for INDEX Z0.D, #0, #1), even though there is never a "2" element for > the minimum vector length.
Ah ok... so if I understand correctly, VLA series aren't capped by the VL (e.g. representable values) In RTL but represent the base + step only. So the series for a VNx2DI and a VNx4SI are the same but what the usable bits are is determined by the mode/VL? That's really not how I thought they were represented but get why you want a loop now... Tamar. > > Thanks, > Richard > > > > > > > Bootstrapped Regtested on aarch64-none-linux-gnu, arm-none-linux-gnueabihf, > > x86_64-pc-linux-gnu -m32, -m64 and no issues. > > > > Ok for master? > > > > Thanks, > > Tamar > > > > gcc/ChangeLog: > > > > * simplify-rtx.cc (simplify_context::simplify_unary_operation): Try > > simplifying operand. > > (simplify_const_relational_operation): Simplify vector EQ and NE. > > (test_vector_int_const_compare): New. > > (test_vector_ops): Use it. > > > > > > -- inline copy of patch -- > > > > diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc > > index > a20a61c5dddbc80b23a9489d925a2c31b2163458..8ba5864efb33ffa5d1ced99f > 6a7d0c73e12560d5 100644 > > --- a/gcc/simplify-rtx.cc > > +++ b/gcc/simplify-rtx.cc > > @@ -6354,6 +6354,19 @@ simplify_const_relational_operation (enum rtx_code > code, > > return 0; > > } > > > > + /* Check if the operands are a vector EQ or NE comparison. */ > > + if (VECTOR_MODE_P (mode) > > + && INTEGRAL_MODE_P (mode) > > + && GET_CODE (op0) == CONST_VECTOR > > + && GET_CODE (op1) == CONST_VECTOR > > + && (code == EQ || code == NE)) > > + { > > + if (rtx_equal_p (op0, op1)) > > + return code == EQ ? const_true_rtx : const0_rtx; > > + else > > + return code == NE ? const_true_rtx : const0_rtx; > > + } > > + > > /* We can't simplify MODE_CC values since we don't know what the > > actual comparison is. */ > > if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) > > @@ -8797,6 +8810,34 @@ test_vector_subregs (machine_mode inner_mode) > > test_vector_subregs_stepped (inner_mode); > > } > > > > +/* Verify vector constant comparisons for EQ and NE. */ > > + > > +static void > > +test_vector_int_const_compare (machine_mode mode) > > +{ > > + rtx zeros = CONST0_RTX (mode); > > + rtx minusone = CONSTM1_RTX (mode); > > + rtx series_0_1 = gen_const_vec_series (mode, const0_rtx, const1_rtx); > > + ASSERT_RTX_EQ (const0_rtx, > > + simplify_const_relational_operation (EQ, mode, zeros, > > + CONST1_RTX (mode))); > > + ASSERT_RTX_EQ (const_true_rtx, > > + simplify_const_relational_operation (EQ, mode, zeros, > > + CONST0_RTX (mode))); > > + ASSERT_RTX_EQ (const_true_rtx, > > + simplify_const_relational_operation (EQ, mode, minusone, > > + CONSTM1_RTX (mode))); > > + ASSERT_RTX_EQ (const_true_rtx, > > + simplify_const_relational_operation (NE, mode, zeros, > > + CONST1_RTX (mode))); > > + ASSERT_RTX_EQ (const_true_rtx, > > + simplify_const_relational_operation (NE, mode, zeros, > > + series_0_1)); > > + ASSERT_RTX_EQ (const0_rtx, > > + simplify_const_relational_operation (EQ, mode, zeros, > > + series_0_1)); > > +} > > + > > /* Verify some simplifications involving vectors. */ > > > > static void > > @@ -8814,6 +8855,7 @@ test_vector_ops () > > { > > test_vector_ops_series (mode, scalar_reg); > > test_vector_subregs (mode); > > + test_vector_int_const_compare (mode); > > } > > test_vec_merge (mode); > > }