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

            Bug ID: 86401
           Summary: The "For constants M and N, if M == (1LL << cst) - 1
                    && (N & M) == M,..." opts are only in fold-const.c and
                    in RTL
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

unsigned long long foo (unsigned long long __x, unsigned int __s)
{
  int _Nd = 64;
  unsigned int _sN = __s % _Nd;
  return (__x << _sN) | (__x >> ((_Nd - _sN) % _Nd));
}

is not optimized into a simple rotate, while:
unsigned long long foo (unsigned long long __x, unsigned int __s)
{
  constexpr int _Nd = 64;
  unsigned int _sN = __s % _Nd;
  return (__x << _sN) | (__x >> ((_Nd - _sN) % _Nd));
}
is.  This is because the:
    For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
    ((A & N) + B) & M -> (A + B) & M
    Similarly if (N & M) == 0,
    ((A | N) + B) & M -> (A + B) & M
    and for - instead of + (or unary - instead of +)
    and/or ^ instead of |.
    If B is constant and (B & M) == 0, fold into A & M.
optimizations are done in fold-const.c only.

Further testcase:
unsigned f1 (unsigned x) { unsigned m = 64; return (m + x) & (m - 1); }
unsigned f2 (unsigned x) { return (64 + x) & 63; }
unsigned f3 (unsigned x) { unsigned m = 64; return (x + m) & (m - 1); }
unsigned f4 (unsigned x) { return (x + 64) & 63; }
unsigned f5 (unsigned x) { unsigned m = 64; return (m - x) & (m - 1); }
unsigned f6 (unsigned x) { return (64 - x) & 63; }
unsigned f7 (unsigned x) { unsigned m = 64; return (x - m) & (m - 1); }
unsigned f8 (unsigned x) { return (x - 64) & 63; }
unsigned f9 (unsigned x, unsigned y) { unsigned m = 64, n = 256 | (m - 1);
return ((x & n) + y) & (m - 1); }
unsigned f10 (unsigned x, unsigned y) { return ((x & 319) + y) & 63; }
unsigned f11 (unsigned x, unsigned y) { unsigned m = 64, n = -128; return ((x |
n) + y) & (m - 1); }
unsigned f12 (unsigned x, unsigned y) { return ((x | -128) + y) & 63; }
unsigned f13 (unsigned x, unsigned y) { unsigned m = 64, n = -384; return ((x ^
n) + y) & (m - 1); }
unsigned f14 (unsigned x, unsigned y) { return ((x ^ -384) + y) & 63; }
unsigned f15 (unsigned x, unsigned y) { unsigned m = 64, n = 256 | (m - 1);
return (y + (x & n)) & (m - 1); }
unsigned f16 (unsigned x, unsigned y) { return (y + (x & 319)) & 63; }
unsigned f17 (unsigned x, unsigned y) { unsigned m = 64, n = -128; return (y +
(x | n)) & (m - 1); }
unsigned f18 (unsigned x, unsigned y) { return (y + (x | -128)) & 63; }
unsigned f19 (unsigned x, unsigned y) { unsigned m = 64, n = -384; return (y +
(x ^ n)) & (m - 1); }
unsigned f20 (unsigned x, unsigned y) { return (y + (x ^ -384)) & 63; }
unsigned f21 (unsigned x, unsigned y) { unsigned m = 64, n = 256 | (m - 1);
return ((x & n) - y) & (m - 1); }
unsigned f22 (unsigned x, unsigned y) { return ((x & 319) - y) & 63; }
unsigned f23 (unsigned x, unsigned y) { unsigned m = 64, n = -128; return ((x |
n) - y) & (m - 1); }
unsigned f24 (unsigned x, unsigned y) { return ((x | -128) - y) & 63; }
unsigned f25 (unsigned x, unsigned y) { unsigned m = 64, n = -384; return ((x ^
n) - y) & (m - 1); }
unsigned f26 (unsigned x, unsigned y) { return ((x ^ -384) - y) & 63; }
unsigned f27 (unsigned x, unsigned y) { unsigned m = 64, n = 256 | (m - 1);
return (y - (x & n)) & (m - 1); }
unsigned f28 (unsigned x, unsigned y) { return (y - (x & 319)) & 63; }
unsigned f29 (unsigned x, unsigned y) { unsigned m = 64, n = -128; return (y -
(x | n)) & (m - 1); }
unsigned f30 (unsigned x, unsigned y) { return (y - (x | -128)) & 63; }
unsigned f31 (unsigned x, unsigned y) { unsigned m = 64, n = -384; return (y -
(x ^ n)) & (m - 1); }
unsigned f32 (unsigned x, unsigned y) { return (y - (x ^ -384)) & 63; }
unsigned f33 (unsigned x) { unsigned m = 64, n = 256 | (m - 1); return (-(x &
n)) & (m - 1); }
unsigned f34 (unsigned x) { return (-(x & 319)) & 63; }
unsigned f35 (unsigned x) { unsigned m = 64, n = -128; return (-(x | n)) & (m -
1); }
unsigned f36 (unsigned x) { return (-(x | -128)) & 63; }
unsigned f37 (unsigned x) { unsigned m = 64, n = -384; return (-(x ^ n)) & (m -
1); }
unsigned f38 (unsigned x) { return (-(x ^ -384)) & 63; }

Reply via email to