On Mon, Nov 18, 2019 at 02:39:12PM +0100, Martin Liška wrote:
> On 11/18/19 11:06 AM, Jakub Jelinek wrote:
> > On Mon, Nov 18, 2019 at 10:17:56AM +0100, Martin Liška wrote:
> > > On 11/14/19 1:15 PM, Richard Biener wrote:
> > > > Hmm.  I was thinking of moving the pass instead of adding another one.
> > > > What's the reason to run switch-conversion during early optimization 
> > > > again?
> > > 
> > > I'm adding CC, as he's the author of cswitch pass and he probably knows
> > > more about the pass placement. But I bet early conversion to array access
> > > rapidly simplifies CFG and other passes can benefit from that.
> > 
> > Yes, I think the early placement is to take it into account in inlining
> > decisions, on the other side it causes various issues, I think we have
> > several PRs open where the early cswitch just makes a good decision based on
> > what it knows at that point, but later on we find better VRP ranges for the
> > switch condition and it is too late to undo it and handle it differently.
> 
> I bet we must have multiple similar problems where one transformation makes
> a transformation that other pass is not happy about.

This is something that happens quite often.  Typical example is where
we commit to doing a an constant array load and later the range is narrowed
and it would be better done either as a bitmask test, or say the constant
array load with sometimes much shorter needed arrays.

> I don't like the suggested approach much. There can be optimization in between
> that can leverage the conversion to a constant array.

For what exactly?

> > Another thing is perform the optimizations we do in reassoc (but aren't
> 
> What kind of optimizations do you mean?

I believe the cswitch expansion can handle well the case where certain
range can be expressed as ((unsigned) x - const1) <= const2) conditional,
but reassoc has also optimize_range_tests_xor, optimize_range_tests_diff,
both of which can be applied multiple times.  To quote the comments
explaining what it does:
/* Optimize X == CST1 || X == CST2
   if popcount (CST1 ^ CST2) == 1 into
   (X & ~(CST1 ^ CST2)) == (CST1 & ~(CST1 ^ CST2)).
   Similarly for ranges.  E.g.
   X != 2 && X != 3 && X != 10 && X != 11
   will be transformed by the previous optimization into
   !((X - 2U) <= 1U || (X - 10U) <= 1U)
   and this loop can transform that into
   !(((X & ~8) - 2U) <= 1U).  */
and
/* Optimize X == CST1 || X == CST2
   if popcount (CST2 - CST1) == 1 into
   ((X - CST1) & ~(CST2 - CST1)) == 0.
   Similarly for ranges.  E.g.
   X == 43 || X == 76 || X == 44 || X == 78 || X == 77 || X == 46
   || X == 75 || X == 45
   will be transformed by the previous optimization into
   (X - 43U) <= 3U || (X - 75U) <= 3U
   and this loop can transform that into
   ((X - 43U) & ~(75U - 43U)) <= 3U.  */
Now, I believe with the if to gswitch optimization these will only rarely
kick in, because the IL will have switches that reassoc doesn't handle,
instead of series of ifs.  So, I believe cswitch needs to handle these cases
too and consider it in the decision whether to use const array loads or
bittest or if tree.

        Jakub

Reply via email to