[Sorry for any weird MUA issues, don't have access to my usual set-up.]

> when looking at a riscv ICE in vect-live-6.c I noticed that we
> assume that the variable part (coeffs[1] * x1) of the to-be-extracted
> bit number in extract_bit_field_1 is a multiple of BITS_PER_UNIT.
>
> This means that bits_to_bytes_round_down and num_trailing_bits
> cannot handle e.g. extracting from a "VNx4BI"-mode vector which has
> 4-bit precision on riscv.

But in the VLA case, doesn't it instead have precision 4+4X?
The problem then is that we can't tell at compile time which
byte that corresponds to.  So...

> This patch adds a special case for that situation and sets bytenum to
> zero as well as bitnum to its proper value.  It works for the riscv
> case because in all other situations we can align to a byte boundary.
> If x1 were 3 for some reason, however, the above assertion would still
> fail.  I don't think this can happen for riscv as we only ever double
> the number of chunks for larger vector sizes but not sure about the
> general case.
>
> If there's another, correct way to work around feel free to suggest.
>
> Bootstrap/testsuite on aarch64 and x86 is running but I would be
> surprised if there were any changes as riscv is the only target that
> uses modes with precision < 8.
>
> Regards
>  Robin
>
> gcc/ChangeLog:
>
>       * expmed.cc (extract_bit_field_1): Handle bitnum with variable
>       part less than BITS_PER_UNIT.
> ---
>  gcc/expmed.cc | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/expmed.cc b/gcc/expmed.cc
> index e22e43c8505..1b0119f9cfc 100644
> --- a/gcc/expmed.cc
> +++ b/gcc/expmed.cc
> @@ -1858,8 +1858,22 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, 
> poly_uint64 bitnum,
>       but is useful for things like vector booleans.  */
>    if (MEM_P (op0) && !bitnum.is_constant ())
>      {
> -      bytenum = bits_to_bytes_round_down (bitnum);
> -      bitnum = num_trailing_bits (bitnum);
> +      /* bits_to_bytes_round_down tries to align to a byte (BITS_PER_UNIT)
> +      boundary and asserts that bitnum.coeffs[1] % BITS_PER_UNIT == 0.
> +      For modes with precision < BITS_PER_UNIT this fails but we can
> +      still extract from the first byte.  */
> +      poly_uint16 prec = GET_MODE_PRECISION (outermode);
> +      if (prec.coeffs[1] < BITS_PER_UNIT && bitnum.coeffs[1] < BITS_PER_UNIT)
> +     {
> +       bytenum = 0;
> +       bitnum = bitnum.coeffs[0] & (BITS_PER_UNIT - 1);

...this doesn't look right.  We can't drop bitnum.coeffs[1] when it's
nonzero, because it says that for some runtime vector sizes, the bit
position might be higher than bitnum.coeffs[0].

Also, it's not possible to access coeffs[1] unconditionally in
target-independent code.

Thanks,
Richard

> +     }
> +      else
> +     {
> +       bytenum = bits_to_bytes_round_down (bitnum);
> +       bitnum = num_trailing_bits (bitnum);
> +     }
> +
>        poly_uint64 bytesize = bits_to_bytes_round_up (bitnum + bitsize);
>        op0 = adjust_bitfield_address_size (op0, BLKmode, bytenum, bytesize);
>        op0_mode = opt_scalar_int_mode ();

Reply via email to