This is an archive of the discontinued LLVM Phabricator instance.

Revert a change in propagateMassToSuccessors that summed redundant edges n^2 times
ClosedPublic

Authored by AndrewScheidecker on Dec 6 2017, 5:03 AM.

Details

Reviewers
dexonsmith
Summary

This reverts part of r300656, which caused a regression in propagateMassToSuccessors by counting edges n^2 times, where n is the number of edges from the source basic block to the same successor basic block. The result was both incorrect and very slow to compute for large values of n (e.g. switches with multiple cases that go to the same basic block).

Diff Detail

Repository
rL LLVM

Event Timeline

Include full context in diff, as suggested on IRC

dexonsmith requested changes to this revision.Dec 6 2017, 11:30 AM
dexonsmith added inline comments.
include/llvm/Analysis/BlockFrequencyInfoImpl.h
1326

If you run clang-format-diff on this I think the loop logic will be clearer. For reference, see the Script for patch reformatting section of:
https://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting

(It will indent SuccE, clarifying that it's a continuation of the statement on the previous line. I suspect it'll line it up with SuccI.)

1330

A comment explaining why we're passing in an iterator here might help to prevent a regression.

But I wonder if you even need this change: can't getEdgeProbability() call BlockT::getIterator on the reference? I believe both BasicBlock and MachineBasicBlock have that function. In that case, you should leave this function as is and clean up getEdgeProbability().

This revision now requires changes to proceed.Dec 6 2017, 11:30 AM
AndrewScheidecker edited edge metadata.

Ran the patch through clang-format

I ran the patch through clang-format. But looking at the code again, I see that calling the getEdgeProbability overload with a successor index or iterator instead of the destination basic block actually does something different from the original code: passing a successor index/iterator gets the probability for a single edge, while passing a basic block sums the probability for all edges between the two blocks.

However, and I have to admit that I'm in over my head here, what the original code was doing doesn't seem correct. For each edge from A to B, it was summing the probability of all edges from A to B, then adding the sum to the mass for B. If there are N edges from A to B, and they have probabilities that sum to M, then this will distribute N*M mass to B instead of M. In my contrived case, N=196928.

I still think this change is good, but I didn't mean for it to change the results. What are your thoughts?

I ran the patch through clang-format. But looking at the code again, I see that calling the getEdgeProbability overload with a successor index or iterator instead of the destination basic block actually does something different from the original code: passing a successor index/iterator gets the probability for a single edge, while passing a basic block sums the probability for all edges between the two blocks.

However, and I have to admit that I'm in over my head here, what the original code was doing doesn't seem correct. For each edge from A to B, it was summing the probability of all edges from A to B, then adding the sum to the mass for B. If there are N edges from A to B, and they have probabilities that sum to M, then this will distribute N*M mass to B instead of M. In my contrived case, N=196928.

I still think this change is good, but I didn't mean for it to change the results. What are your thoughts?

You're right, the current logic is wrong. Looking at the history, it looks like it was broken by r300656, which was reviewed in https://reviews.llvm.org/D32118. You're effectively doing a partial-revert of that commit -- please be clear about that in the commit message.

Also, please add a test for this. See the current tests in test/Analysis/BlockFrequencyInfo/ for examples.

As a side note, it's somewhat subtle for the edge-iterator and block-reference versions of getEdgeProbability to give different answers. I think the latter should change names, perhaps to getEdgeProbabilitySum. But that should be in a follow-up patch.

AndrewScheidecker retitled this revision from Fix accidentally quadratic time in BlockFrequencyInfoImpl::propagateMassToSuccessors to Revert a change in propagateMassToSuccessors that summed redundant edges n^2 times.
AndrewScheidecker edited the summary of this revision. (Show Details)

Added a test that produces different results with and without this fix

dexonsmith accepted this revision.Dec 7 2017, 6:38 PM

LGTM, after you try to shrink the testcase. Thanks for tracking this down!

include/llvm/Analysis/BlockFrequencyInfoImpl.h
1318–1324

The old code had SI and SE, which are the typical initialisms. But if you prefer spelling out SuccI that's fine with me.

test/Analysis/BlockFrequencyInfo/redundant_edges.ll
16–25

Do you really need a 8-way switch to see a difference here, or would a 4-way suffice? a 3-way?

This revision is now accepted and ready to land.Dec 7 2017, 6:38 PM

Simplified test, and changed iterator variable names to SI/SE.

I don't have commit access; can somebody please commit this?

dexonsmith closed this revision.Dec 8 2017, 2:52 PM

Committed in r320208.