This is an archive of the discontinued LLVM Phabricator instance.

Fix three bugs in loop unswitching related to trivial unswitching and the threshold parameter
ClosedPublic

Authored by broune on Jun 10 2015, 5:14 PM.

Details

Summary

This change fixes three bugs in loop unswitching. This change causes an 81% speed-up on a benchmark that is based on EigenConvolutionKernel2D from Eigen3, where the lack of loop unswitching blocks hoisting of loads out of a nested loop (see bug 23816 for how loop unswitching and load hoisting are related).

Change 1: Unswitching on trivial conditions should always happen regardless of the computed unswitching cost, as really the cost is zero. While there is code to make that happen, the logic that checks the unswitching cost against a threshold was moved to an earlier point (revision 147935) than the point where trivial unswitching is detected, so trivial unswitching is currently blocked by the cost threshold. This change fixes that.

Change 2: Before revision 147935 (from 2012-01-11), the threshold parameter was a per-loop threshold. So an unswitching happened only if the cost of the unswitching was less than the threshold. In an indirect way (and I believe unintentionally), the logic for this since then has been that the threshold is an over-all budget across all loops for all loop unswitching done by a given LoopUnswitch loop pass object. So if an unswitching with cost 100 happens in one function, that in effect reduces the threshold from 100 to 0 for the loops even in another function. This persists for the lifetime of that loop pass object. This makes no difference for most small examples but it is important for large examples. This revision fixes that.

Change 3: The cost is currently calculated as std::min(NumInstructions, 5 * NumBlocks). So a loop with 2 blocks and a million instructions will have an unswitching cost of 10. I changed this to just NumInstructions, as it were before revision 147935, though I'm open to e.g. instead replacing std::min with std::max.

I've tried to make the change minimally invasive while staying with what I think was the original intent of the code.

Diff Detail

Event Timeline

broune updated this revision to Diff 27480.Jun 10 2015, 5:14 PM
broune retitled this revision from to Fix two bugs in loop unswitching related to trivial unswitching and the threshold parameter.
broune updated this object.
broune edited the test plan for this revision. (Show Details)
broune added reviewers: hfinkel, eli.friedman, meheff.
broune added subscribers: dyatkovskiy, Unknown Object (MLST).
broune retitled this revision from Fix two bugs in loop unswitching related to trivial unswitching and the threshold parameter to Fix three bugs in loop unswitching related to trivial unswitching and the threshold parameter.Jun 10 2015, 10:00 PM
broune updated this object.
broune edited the test plan for this revision. (Show Details)
broune updated this revision to Diff 27485.Jun 10 2015, 10:02 PM

Change unswitching cost calculation from std::min(NumInstructions, 5 * NumBlocks) to NumInstructions.

meheff edited edge metadata.Jun 12 2015, 11:42 AM

Thanks for fixing this. This certainly seems saner than what is there now. Some clarifying comments about MaxSize might be good. Superficially it looks like some global budget because it is a pass level value and gets decremented per loop, but in reality all the budget gets returned when the pass is done with a loop and all of it's clones.

broune updated this revision to Diff 27625.Jun 12 2015, 7:55 PM
broune edited edge metadata.

Add comment on MaxSize.

Friendly ping.

broune added a subscriber: eliben.Jun 16 2015, 11:25 AM

LGTM. Thanks!

Friendly ping.

hfinkel accepted this revision.Jun 22 2015, 5:35 PM
hfinkel edited edge metadata.

LGTM too.

This revision is now accepted and ready to land.Jun 22 2015, 5:35 PM