This is an archive of the discontinued LLVM Phabricator instance.

[SimplifyCFG] try harder to forward switch condition to phi (PR34471)
ClosedPublic

Authored by spatel on Oct 17 2017, 10:07 AM.

Details

Summary

The missed canonicalization/optimization in the motivating test from PR34471 leads to very different codegen:

int switcher(int x) {
    switch(x) {
    case 17: return 17;
    case 19: return 19;
    case 42: return 42;
    default: break;
    }
    return 0;
  }

int comparator(int x) {
  if (x == 17) return 17;
  if (x == 19) return 19;
  if (x == 42) return 42;
  return 0;
}

For the first example, we use a bit-test optimization to avoid a series of compare-and-branch:
https://godbolt.org/g/BivDsw

Diff Detail

Event Timeline

spatel created this revision.Oct 17 2017, 10:07 AM
hans accepted this revision.Oct 17 2017, 4:16 PM

lgtm

This revision is now accepted and ready to land.Oct 17 2017, 4:16 PM
davide added a subscriber: davide.Oct 17 2017, 4:26 PM

What's the interaction between this code and constant propagation?

What's the interaction between this code and constant propagation?

This transform makes it less likely to combine constants I guess. Do you have an example in mind where that makes things worse?

This revision was automatically updated to reflect the committed changes.

Hey Sanjay,
GVN/NewGVN/et al will undo this transform, and propagate constants. In fact, i expect pretty much any pass that can, will.

This definitely belongs in the late simplification category at best.

More than that, i'm concerned this is the wrong fix.

Why is the right answer to undo the transform (which will cause fights between passes) in simplifycfg instead of improving the codegen to recognize the issue?

It seems the same code you are using to detect and undo the transforrm in simplification could be used to codegen it better.

yes, that was my concern too. I think pretty much every forward data flow analysis that propagates facts can make this xform useless. If anything, it's too fragile.

(sorry I didnt reply before but it was devmtg week)

Hey Sanjay,
GVN/NewGVN/et al will undo this transform, and propagate constants. In fact, i expect pretty much any pass that can, will.

This definitely belongs in the late simplification category at best.

More than that, i'm concerned this is the wrong fix.

Why is the right answer to undo the transform (which will cause fights between passes) in simplifycfg instead of improving the codegen to recognize the issue?

It seems the same code you are using to detect and undo the transforrm in simplification could be used to codegen it better.

I didn't realize other passes were undoing this transform. I thought I was just improving the existing canonical form favored by SimplifyCFG. Ie, the existing code in ForwardSwitchConditionToPHI() is already fighting with the other passes, correct?

So I'm certainly open to suggestions on how to proceed. Should I revert this change or delay everything in ForwardSwitchConditionToPHI() to -latesimplifycfg (note: I proposed a refinement of that in D38631)? And then follow that with moving everything to codegen (I haven't actually looked at switches in codegen yet, so that's definitely a follow-up step if I'm doing it).

So, in the original test and code it's hard to tell, but yes, if it's trying to undo the propagation of constants into phi nodes, it's already going to be fighting, because everything else is trying to do that transform specifically :)

It's probably worth taking a look at codegen and seeing how hard it is.
So i'd say "delay it all to latesimplifycfg for now, see how hard codegen is".
I'm hopeful it's not that tricky to fix codegen. But if it is, yeah let's see how far we want to go here, i don't think you should be on the hook for cleaning all of this up if it's hard.

(One could also argue about the value of constant propagation in this case. It's mostly useful for range analysis, jump threading, transformation into select, etc. I'm indifferent if we want to canonicalize late to some other form if we can show it's better)

So, in the original test and code it's hard to tell, but yes, if it's trying to undo the propagation of constants into phi nodes, it's already going to be fighting, because everything else is trying to do that transform specifically :)

It's probably worth taking a look at codegen and seeing how hard it is.
So i'd say "delay it all to latesimplifycfg for now, see how hard codegen is".
I'm hopeful it's not that tricky to fix codegen. But if it is, yeah let's see how far we want to go here, i don't think you should be on the hook for cleaning all of this up if it's hard.

(One could also argue about the value of constant propagation in this case. It's mostly useful for range analysis, jump threading, transformation into select, etc. I'm indifferent if we want to canonicalize late to some other form if we can show it's better)

Yeah, I can see the existing -simplifycfg code fights -gvn on this. Let me add another simplifycfg option bit to delay the whole thing. Then, I'll look at the codegen side. Thanks everyone for pointing out the problems!

Delay switch condition forwarding to -latesimplifycfg:
rL316298