https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98681

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, for the mask, the question is if we should or shouldn't handle e.g.
unsigned
foo (unsigned int x)
{
  return (x << 13) & (-1U << 13);
}
or
unsigned
bar (unsigned int x)
{
  return (x << 0) & -1U;
}
I think the instruction in theory can handle those corner-cases, 
as lsb is [0, 31] and width [1, 32-lsb], but the optimizers (both GIMPLE and
simplify-rtx during combine) will optimize that away (the useless masking in
both cases and useless shift in the second case).
So the case where mask is negative is only theoretical whether it should or
shouldn't match, that
exact_log2 ((INTVAL (mask) >> INTVAL (shft_amnt)) + 1)
for negative INTVAL (mask) will result in -1 + 1 for the masks with bits
starting with shft_amnt set and smaller clear and exact_log2 (0) is -1, thus it
fail, while if UINTVAL it could succeed.  E.g. that hypothetical -1U << 13 mask
is in CONST_INT_P -1 << 13 so in UINTVAL (0xffffffffffffe000 >> 13) + 1 is a
power of two.  But e.g. for shift count 0, -1 mask would be (0xffffffffffffffff
>> 0) + 1,
so 0 and fail anyway.

On the other side, I'm not sure if the define_insn will work correctly when
mask is negative - consider again the (x << 13) & (-1U << 13).
The instruction uses %P3 which uses
    case 'P':
      if (!CONST_INT_P (x))
        {
          output_operand_lossage ("invalid operand for '%%%c'", code);
          return;
        }

      asm_fprintf (f, "%u", popcount_hwi (INTVAL (x)));
but the constant is not -1U << 13, but -1 << 13 and so %P3 will not print
ubfiz   w1, w0, 13, 19
that should be printed, but
ubfiz   w1, w0, 13, 51
on which gas will fail again:
pr98681.s: Assembler messages:
pr98681.s:11: Error: immediate value out of range 1 to 32 at operand 4 --
`ubfiz w1,w0,13,51'
So, I think it is better to keep INTVAL (mask) as is.

Reply via email to