[Bug target/93505] [8/9/10 Regression] wrong code or ICE with __builtin_bswap64() and rotation at -Og

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Jan 30 10:44:00 GMT 2020


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

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Still bisecting it, but I'd say the bug is in expand_binop:
  /* If we were trying to rotate, and that didn't work, try rotating
     the other direction before falling back to shifts and bitwise-or.  */
  if (((binoptab == rotl_optab
        && (icode = optab_handler (rotr_optab, mode)) != CODE_FOR_nothing)
       || (binoptab == rotr_optab
           && (icode = optab_handler (rotl_optab, mode)) != CODE_FOR_nothing))
      && is_int_mode (mode, &int_mode))
    {
      optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
      rtx newop1;
      unsigned int bits = GET_MODE_PRECISION (int_mode);

      if (CONST_INT_P (op1))
        newop1 = gen_int_shift_amount (int_mode, bits - INTVAL (op1));
      else if (targetm.shift_truncation_mask (int_mode) == bits - 1)
        newop1 = negate_rtx (GET_MODE (op1), op1);
      else
        newop1 = expand_binop (GET_MODE (op1), sub_optab,
                               gen_int_mode (bits, GET_MODE (op1)), op1,
                               NULL_RTX, unsignedp, OPTAB_DIRECT);

      temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1,
                                    target, unsignedp, methods, last);
      if (temp)
        return temp;
    }

The above is wrong if op1 is or might be 0 and targetm.shift_truncation_mask
(int_mode) != bits - 1,
because for original valid rotate by 0 it will create invalid rotate in the
other direction by bits
which is out of bounds rotation count.
So, I'd say we should either mask the result of subtraction with bits - 1, or
perhaps better
do a negate + and, i.e. -op1 & (bits - 1).


More information about the Gcc-bugs mailing list