This is an archive of the discontinued LLVM Phabricator instance.

Deduplication of cyclic PHI nodes
Needs ReviewPublic

Authored by mark-sed on Jun 15 2023, 4:58 AM.

Details

Summary

The EliminateDuplicatePHINodes function used in simplifycfg pass does not handle cyclic phis. This patch adds detection for such phis and can be constrained using the deduplicate-phi-max-depth option.

Diff Detail

Event Timeline

mark-sed created this revision.Jun 15 2023, 4:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 15 2023, 4:58 AM
mark-sed requested review of this revision.Jun 15 2023, 4:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 15 2023, 4:58 AM
mark-sed updated this revision to Diff 532170.Jun 16 2023, 8:37 AM

Fixed formatting errors to match clang-format.

nikic added a comment.Jun 16 2023, 9:09 AM

This now only contains the reformat, not the actual patch.

mark-sed updated this revision to Diff 532194.Jun 16 2023, 9:22 AM

Squashed 2 commits into one to have a correct diff.

nikic added a comment.Jun 16 2023, 1:53 PM

I like the idea here, but the implementation approach is somewhat iffy. This is only going to work in the "naive" implementation -- I don't think the hash-based implementation can be extended to support this. So it won't work if there are many phis. The implementation approach is also quite inefficient: We're performing pairwise, recursive comparisons of all phis.

It should be possible to do this more generally and efficiently (something based on equivalence classes with optimistic assumption), but that would require processing all phis in the function together, not just those in a single block.

A substantial limitation here is that this only works on pure phi graphs, and for example won't be able to deduplicate typical induction variables where there is something like an add %phi, 1 in between. But at that point we're getting into phi-aware GVN, which is ... tricky.

I'm generally open to having this simple approach, as long as it can be made essentially free in terms of compile-time impact.

llvm/lib/Transforms/Utils/Local.cpp
1263–1265

Can do something like this can drop the MatchingPhis.count() calls below.

1277

Just dyn_cast.

1376

This won't work, and violates the DenseMap contract, because it will report two phis as equal that have a different hash.

llvm/unittests/Transforms/Utils/LocalTest.cpp
186

Use a lit test please, in some pass that uses these utilities.

@nikic

The implementation approach is also quite inefficient: We're performing pairwise, recursive comparisons of all phis.

Recursion is of course not ideal, but the comparison has an upper limit. Would you suggest trying to make this into an iterative approach?

llvm/lib/Transforms/Utils/Local.cpp
1376

That is a great point. I will look into a different approach.

llvm/unittests/Transforms/Utils/LocalTest.cpp
186

I wanted to use a lit test, but this function is called only in the -simplifycfg pass, but that pass does way too many optimizations. Using a unit test I can easily test that exactly this feature works and also it allows me to create a smaller test, where I don't have to worry about simplifycfg removing some parts.

mark-sed updated this revision to Diff 534079.Jun 23 2023, 2:49 PM

Fix for hash to not break the DenseSet contract and small optimizations

mark-sed marked 2 inline comments as done.Jul 12 2023, 1:33 AM

Ping @nikic

anna added a comment.Sep 20 2023, 8:34 AM

Looks like the missing concern from Nikita is about the compile time impact. Marek is checking this using the compile time tracker.

llvm/lib/Transforms/Utils/Local.cpp
1342

Pls add a comment on why a custom hash is used.