Eric Botcazou <ebotca...@adacore.com> writes: >> FWIW I agree this is the right approach, although I can't approve it. >> The assert above is guarding code that deals with a very general case, >> including some unusual combinations, so I don't think it would be a >> good idea to try to remove it entirely. > > Yes, but the patch is a bit of kludge since it short-circuits the meat of the > function: > > /* This should always pass, otherwise we don't know how to verify > the constraint. These conditions may be relaxed but > subreg_regno_offset would need to be redesigned. */ > gcc_assert ((GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)) == 0); > gcc_assert ((nregs_xmode % nregs_ymode) == 0); > > So what would it take to do things properly here, i.e. relax the conditions > and adjust downstream?
What do you think we should relax it to though? Obviously there's a balance here between relaxing things enough and not relaxing them too far (so that the EImode AArch64 thing I mentioned is still a noisy failure, for example). ISTM the patch deals with the only significant case that is obviously safe for modes that are not a power of 2 in size. If you're saying that the condition itself is OK, but that the code should be further down in the function, then I don't think that would gain much. We already have early-outs for the simple cases, such as: /* Paradoxical subregs are otherwise valid. */ if (!rknown && offset == 0 && GET_MODE_PRECISION (ymode) > GET_MODE_PRECISION (xmode)) { info->representable_p = true; /* If this is a big endian paradoxical subreg, which uses more actual hard registers than the original register, we must return a negative offset so that we find the proper highpart of the register. */ if (GET_MODE_SIZE (ymode) > UNITS_PER_WORD ? REG_WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN) info->offset = nregs_xmode - nregs_ymode; else info->offset = 0; info->nregs = nregs_ymode; return; } [...] /* Lowpart subregs are otherwise valid. */ if (!rknown && offset == subreg_lowpart_offset (ymode, xmode)) { info->representable_p = true; rknown = true; if (offset == 0 || nregs_xmode == nregs_ymode) { info->offset = 0; info->nregs = nregs_ymode; return; } } which also come before the assert. Thanks, Richard