This is an archive of the discontinued LLVM Phabricator instance.

[llgo] irgen: generate switch instructions
ClosedPublic

Authored by axw on Jan 2 2015, 6:17 PM.

Details

Summary
With this patch, llgo uses ssautil.Switches
to reconstitute (and synthesise) switches,
which can then be lowered to lookup tables,
trees, etc.

We currently only handle integer const case
switches. We erase the comparison blocks (other
than the initial block), and generate a switch
instruction at the end of the block starting
the if-else-if chain. ssautil.Switches does
not remove duplicate const cases (e.g. same
operands for "||"), so we do this in llgo for
now.

Diff Detail

Event Timeline

axw updated this revision to Diff 17768.Jan 2 2015, 6:17 PM
axw retitled this revision from to [llgo] irgen: generate switch instructions.
axw updated this object.
axw edited the test plan for this revision. (Show Details)
axw added a reviewer: pcc.
axw added a subscriber: Unknown Object (MLST).
axw set the repository for this revision to rL LLVM.Jan 2 2015, 6:18 PM
pcc edited edge metadata.Jan 6 2015, 6:37 PM

I wonder if there is a way to do this without modifying the go/ssa IR. In particular, I don't feel very comfortable about any attempt to define an instruction outside the ssa package. Maybe we can build a mapping to keep track of which ssa.If instructions are to be treated as switch instructions?

I believe LLVM already has a transformation to convert chains of branch instructions into switches, at least in some cases. Have you measured a performance improvement with this change at all? (Asking just out of curiosity. I think it would be worth exploring the performance impact of extending this to support type switches, so I have no objection to this change in principle.)

axw added a comment.Jan 6 2015, 9:29 PM
In D6831#105921, @pcc wrote:

I wonder if there is a way to do this without modifying the go/ssa IR. In particular, I don't feel very comfortable about any attempt to define an instruction outside the ssa package. Maybe we can build a mapping to keep track of which ssa.If instructions are to be treated as switch instructions?

It is certainly possible to do that, and I did go down that road initially. I don't really like the kludginess of the current approach either, but the reason I did it this way was to keep it relatively self-contained. Aside from being (IMHO) a bit messy, adding a check to each "ssa.If" would mean we have a performance hit in the frontend for each If instruction, rather than just the ones that we care about. Maybe that's nothing to worry about; I haven't measured it.

I don't know if this will ever be necessary, but another option is for llgo to grow its own IR on top of go/ssa. I'd rather not go there for this, though.

I believe LLVM already has a transformation to convert chains of branch instructions into switches, at least in some cases. Have you measured a performance improvement with this change at all? (Asking just out of curiosity. I think it would be worth exploring the performance impact of extending this to support type switches, so I have no objection to this change in principle.)

Geo-mean improvement of 0.49% (0.23% - 0.75% @ 95% CI)

There seems to be a fair bit of noise in some of the tests, since I'm getting supposed improvements in BenchmarkAppendGrowString, and BenchmarkTCP6ConcurrentReadWrite. One significant improvement that looks genuine is:

BenchmarkCSSEscaper 2983.000000 2476.000000 1.204766

Standard optimisations do not appear to convert branches to switches AFAICT, but perhaps I'm doing something wrong. I did look to see if there was an existing pass, but again I couldn't see anything that looked relevant. There is a pass that goes the opposite direction, converting switches to branches, for targets that don't implement switch.

pcc accepted this revision.Jan 7 2015, 11:05 AM
pcc edited edge metadata.

adding a check to each "ssa.If" would mean we have a performance hit in the frontend for each If instruction

I very much doubt that the performance impact would be measurable. Remember that the switch analysis has to look at each if instruction anyway.

Regardless, I agree that both approaches are a little messy, and I can't see a neater way without modifying go/ssa, so LGTM.

I don't know if this will ever be necessary, but another option is for llgo to grow its own IR on top of go/ssa. I'd rather not go there for this, though.

Agreed. FWIW, the long term direction I'd like to see is attempting to extend go/ssa with what we need (in this particular case, a native switch instruction).

I did look to see if there was an existing pass, but again I couldn't see anything that looked relevant

If you grep for SimplifyCFGOpt::FoldValueComparisonIntoPredecessors you should find something.

Geo-mean improvement of 0.49% (0.23% - 0.75% @ 95% CI)

Great! I'm a little surprised that we can do better than LLVM on its own, but maybe I don't understand what the simplifycfg code is doing.

This revision is now accepted and ready to land.Jan 7 2015, 11:05 AM
axw closed this revision.Jan 7 2015, 11:50 PM