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

--- Comment #20 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
Created attachment 43233
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43233&action=edit
WIP that fixes PR, but causes other regressions

I am attaching a proof of concept hack that fixes this PR by moving the
optimize_bit_field_compare functionality from the front-end to the gimple
reassoc pass (picked at random, we could do it anywhere else).

It recognizes the following pattern:

     _1 = some.bit_field;
     if (_1 == 99)

...and converts it to a BIT_FIELD_REF + comparison.

Although it works for the PR, it creates various regressions, because it seems
fold_truth_andor can create optimized bit field comparisons as well, which
would be challenging to deconstruct later in gimple.

For example.  Imagine this:

enum output_type
{
  type_pde,
  type_relocatable,
  type_pie,
  type_dll,
};

struct bfd_link_info
{
  enum output_type type : 2;
};

void test_pic (struct bfd_link_info *info)
{
  if ((((info)->type == type_dll) || ((info)->type == type_pie)))
    blah();
}

Thanks to fold_truth_andor (fold_range_test specifically), if we were to delay
optimize_bit_field_compare(), we would generate the following coming out of the
front-end:

  if (info->type + 2 <= 1)
    blah();

That is, not only have we merged the set of bit field comparisons, we have also
introduced an unsigned overflow to make the comparison simpler.

So now our gimple optimize bit field compare function would also have to deal
with this:

  _1 = info_7(D)->type;
  _2 = _1 + 2;
  if (_2 <= 1)

and perhaps convert it to:

   _5 = BIT_FIELD_REF <*info, 8, 0>
   _6 = (_5 + 2) & 3
   if (_6 <= 1)

My worry is that we can handle optimizations of the following quite easily
(attached patch):

     _1 = some.bit_field;
     if (_1 == 99)

but with things like the following, it starts getting harder and harder:

  _1 = info_7(D)->type;
  _2 = _1 + 2;
  if (_2 <= 1)

And I'm pretty sure fold_truth_andor() has a lot more tricks up its sleeve,
that we'll have to mop up in gimple.  All in all, I doubt we can sensibly move
optimize_bit_field_compare() to the middle end, without having to bend over
backwards to reconstruct things or port some of fold_truth_andor() to the
middle end as well.  I doubt this is stage4 material.

I can certainly teach my WIP to handle the _2 = _1 + 2 case above without
porting fold_truth_andor*() to the middle end, but I'm afraid this is just one
of the many scenarios we'll have to deal with.  I could be wrong, and could
certainly take a stab at it.

Oh, and I'm completely ignoring the reassocation suggestions Jakub makes in
comment 19.  That would make even more work for stage4 :).

Thoughts?

Reply via email to