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

--- Comment #18 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Guess best would be to go through the ranges from first to last, check for the
pattern we are interested in (ranges[i].exp being SSA_NAME with BIT_AND_EXPR
def with constant where ranges[i].low == ranges[i].high is an integer, so is
the second operand of BIT_AND_EXPR, verify also the condition we've discussed
above ((CST1&~N) == 0) and whether ranges[i].in_p matches the kind of operation
(opcode and for opcode ERROR_MARK dig out the || vs. &&), push e.g. indexes of
those ranges into a vector, then have a gcc_sort_r callback that will put the
indexes for the same BIT_AND_EXPR first operand next to each other and then
just go through them, construct a new comparison for all the adjacent entries
for the same base var and nullify the rest.
Testcase showing why it is needed:
void bar (void);

int
f1 (int a)
{
  return (a & 8) == 8 && (a & 2) == 2 && (a & 4) == 4;
}

int
f2 (int a)
{
  int x = (a & 8) == 8;
  int y = (a & 2) == 2;
  int z = (a & 4) == 4;
  return x && y && z;
}

int
f3 (int a)
{
  return (a & (8 | 2 | 4)) == (8 | 2 | 4);
}

void
f4 (int a)
{
  int x = (a & 8) == 8;
  int y = (a & 2) == 2;
  int z = (a & 4) == 4;
  int u = (a & 16) == 16;
  int v = (a & 64) == 64;
  int w = (a & 256) == 256;
  if (x && y && z && u && v && w)
    bar ();
}

int
f5 (int a)
{
  return (a & 8) != 8 || (a & 2) != 2 || (a & 4) != 4;
}

int
f6 (int a)
{
  int x = (a & 8) != 8;
  int y = (a & 2) != 2;
  int z = (a & 4) != 4;
  return x || y || z;
}

int
f7 (int a)
{
  return (a & (8 | 2 | 4)) != (8 | 2 | 4);
}

void
f8 (int a)
{
  int x = (a & 8) != 8;
  int y = (a & 2) != 2;
  int z = (a & 4) != 4;
  int u = (a & 16) != 16;
  int v = (a & 64) != 64;
  int w = (a & 256) != 256;
  if (x || y || z || u || v || w)
    bar ();
}

Reply via email to