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

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
E.g. in simplify-rtx.c we have:
    case SIGN_EXTRACT:
    case ZERO_EXTRACT:
      if (CONST_INT_P (op0)
          && CONST_INT_P (op1)
          && CONST_INT_P (op2)
          && is_a <scalar_int_mode> (mode, &int_mode)
          && INTVAL (op1) + INTVAL (op2) <= GET_MODE_PRECISION (int_mode)
          && HWI_COMPUTABLE_MODE_P (int_mode))
        {
          /* Extracting a bit-field from a constant */
          unsigned HOST_WIDE_INT val = UINTVAL (op0);
          HOST_WIDE_INT op1val = INTVAL (op1);
          HOST_WIDE_INT op2val = INTVAL (op2);
          if (!BITS_BIG_ENDIAN)
            val >>= op2val;
          else if (is_a <scalar_int_mode> (op0_mode, &int_op0_mode))
            val >>= GET_MODE_PRECISION (int_op0_mode) - op2val - op1val;
          else
            /* Not enough information to calculate the bit position.  */
            break;

          if (HOST_BITS_PER_WIDE_INT != op1val)
            {
              /* First zero-extend.  */
              val &= (HOST_WIDE_INT_1U << op1val) - 1;
              /* If desired, propagate sign bit.  */
              if (code == SIGN_EXTRACT
                  && (val & (HOST_WIDE_INT_1U << (op1val - 1)))
                     != 0)
                val |= ~ ((HOST_WIDE_INT_1U << op1val) - 1);
            }

          return gen_int_mode (val, int_mode);
        }
where for ZERO_EXTRACT we actually return CONST0_RTX (int_mode) if op1val == 0,
but can invoke UB before that in the big endian shift.  For SIGN_EXTRACT we
invoke UB in any case, HOST_WIDE_INT_1U << (-1).

Note, the bzhi patterns aren't the only ones that rely on ZERO_EXTRACT being
defined for size 0, e.g. bextr does as well.

Reply via email to