This is an archive of the discontinued LLVM Phabricator instance.

[BDCE][DemandedBits] Detect dead uses of undead instructions
ClosedPublic

Authored by nikic on Dec 11 2018, 9:21 AM.

Details

Summary

This (mostly) fixes https://bugs.llvm.org/show_bug.cgi?id=39771.

BDCE currently detects instructions that don't have any demanded bits and replaces their uses with zero. However, if an instruction has multiple uses, then some of the uses may be dead (have no demanded bits) even though the instruction itself is still live. This patch extends DemandedBits/BDCE to detect such uses and replace them with zero. While this will not immediately render any instructions dead, it may lead to simplifications (in the motivating case, by converting a rotate into a simple shift), break dependencies, etc.

The implementation tries to strike a balance between analysis power and complexity/memory usage. Originally I wanted to track demanded bits on a per-use level, but ultimately we're only really interested in whether a use is entirely dead or not. I'm using an extra set to track which uses are dead. However, as initially all uses are dead, I'm not storing uses those user is also dead. This case is checked separately instead.

The test case has a couple of cases that are simplified yet. In particular, we're only looking at uses of instructions right now. I think it would make sense to also extend this to arguments. Furthermore DemandedBits doesn't yet know some of the tricks that InstCombine does for the demanded bits or bitwise or/and/xor in combination with known bits information.

Diff Detail

Repository
rL LLVM

Event Timeline

nikic created this revision.Dec 11 2018, 9:21 AM
hfinkel added inline comments.Dec 18 2018, 4:03 PM
lib/Analysis/DemandedBits.cpp
440 ↗(On Diff #177726)

Please remove this assert. For consistency with the other interfaces, we should just have the function return false in this case.

455 ↗(On Diff #177726)

We know that this will never return AliveBits.end()? A comment or assert should explain this.

lib/Transforms/Scalar/BDCE.cpp
113 ↗(On Diff #177726)

TODO: (add colon)

130 ↗(On Diff #177726)

With this new logic, where do we now remove instructions for which all uses have been trivialized?

nikic updated this revision to Diff 178864.Dec 19 2018, 5:11 AM

Remove assert, check that instr is in AliveBits.

nikic marked 5 inline comments as done.Dec 19 2018, 5:18 AM
nikic added inline comments.
lib/Analysis/DemandedBits.cpp
455 ↗(On Diff #177726)

I think that due to the way the API is used by BDCE (checking isInstructionDead first) this case can't be hit, but from the perspective of just this API it could happen. I've added a check.

lib/Transforms/Scalar/BDCE.cpp
130 ↗(On Diff #177726)

BDCE currently (also before this change) does not remove instructions without demanded bits, it only replaces their uses with zero and lets somebody else handle the cleanup (some BDCE tests run instcombine afterwards). Only instructions not reached during analysis are removed entirely (the isInstructionDead check).

I think BDCE *should* be dropping them, but it's probably best to do this as a separate change, as it will require changes to otherwise unrelated BDCE tests.

hfinkel accepted this revision.Dec 19 2018, 8:11 AM
hfinkel added inline comments.
lib/Transforms/Scalar/BDCE.cpp
130 ↗(On Diff #177726)

I think BDCE *should* be dropping them, but it's probably best to do this as a separate change, as it will require changes to otherwise unrelated BDCE tests.

I agree (the old logic looks like it won't do this, and that seems to be a mistake). If you could do this as follow-up, that would be great.

LGTM.

This revision is now accepted and ready to land.Dec 19 2018, 8:11 AM
This revision was automatically updated to reflect the committed changes.
nikic marked an inline comment as done.
nikic reopened this revision.Dec 19 2018, 2:40 PM

I've reverted this, because it causes enc-3des.execution_time from test-suite to fail (e.g. http://lab.llvm.org:8011/builders/clang-cmake-x86_64-sde-avx512-linux/builds/16746).

This revision is now accepted and ready to land.Dec 19 2018, 2:40 PM
nikic updated this revision to Diff 179760.Dec 31 2018, 7:00 AM

Fix removal of dead uses. The previous version had a check whether the previous demanded bits are empty and only dropped the use from the DeadUses set in that case. The motivation for this was that the use could only be part of DeadUses if the demanded bits are empty, so we can save a redundant hash lookup. Of course, this is not actually true, because the previous demanded bits are for the instruction across all users, which is a superset of the demanded bits for a single use. (That being kind of the whole point of this change, I'm really not sure what I was thinking there...)

So now I'm just always doing the erase() call when a use has non-empty demanded bits. I've also added a testcase that was miscompiled with the previous version. I believe that this is also what caused the failure in enc-3des from the test-suite.

Fix removal of dead uses. The previous version had a check whether the previous demanded bits are empty and only dropped the use from the DeadUses set in that case. The motivation for this was that the use could only be part of DeadUses if the demanded bits are empty, so we can save a redundant hash lookup. Of course, this is not actually true, because the previous demanded bits are for the instruction across all users, which is a superset of the demanded bits for a single use. (That being kind of the whole point of this change, I'm really not sure what I was thinking there...)

So now I'm just always doing the erase() call when a use has non-empty demanded bits. I've also added a testcase that was miscompiled with the previous version. I believe that this is also what caused the failure in enc-3des from the test-suite.

LGTM

This revision was automatically updated to reflect the committed changes.