[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 ();