This is an archive of the discontinued LLVM Phabricator instance.

[IPSCCP] Switch away from Instruction::isSafeToRemove()
ClosedPublic

Authored by kpn on Jan 27 2022, 9:11 AM.

Details

Summary

In D115737 I found that I needed to teach Instruction::isSafeToRemove() about strictfp/constrained intrinsics. It was pointed out that this is probably the wrong function to use isInstructionTriviallyDead(). It doesn't make sense to have a "second, worse implementation".

I also believe that the Instruction class is the wrong place for this functionality. The information about whether or not an instruction can be removed is in the transform passes and should stay there.

Diff Detail

Event Timeline

kpn created this revision.Jan 27 2022, 9:11 AM
kpn requested review of this revision.Jan 27 2022, 9:11 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 27 2022, 9:11 AM
kpn retitled this revision from [U to [IPSCCP] Switch away from Instruction::isSafeToRemove().Jan 27 2022, 9:17 AM
kpn edited the summary of this revision. (Show Details)
nikic added inline comments.Jan 27 2022, 9:56 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
96

I'd drop the TLI pass through here. SCCP should primarily be removing instructions it has simplified itself, and that shouldn't need TLI.

103

I don't understand why we need this remaining code -- why is wouldInstructionBeTriviallyDead not sufficient?

kpn added inline comments.Jan 28 2022, 9:08 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
96

I didn't realize it wasn't required. Dropping it is certainly much easier.

103

From more study, it looks like you are correct and this bit isn't needed. Which implies that this whole function isn't needed and we can just call wouldInstructionBeTriviallyDead() directly.

kpn updated this revision to Diff 404924.Feb 1 2022, 7:16 AM

No, actually wouldInstructionBeTriviallyDead() rejects some instructions that the previous isSafeToRemove() function allowed. By trusting a true returned by wouldInstructionBeTriviallyDead(), but using the old logic if it returned false, we can make this change NFC. To that end I have also removed the constrained FP logic and I plan on adding it back in probably D115737.

kpn updated this revision to Diff 417028.Mar 21 2022, 10:52 AM
kpn retitled this revision from [IPSCCP] Switch away from Instruction::isSafeToRemove() to [NFC][IPSCCP] Switch away from Instruction::isSafeToRemove().

Rebase. Ping.

Herald added a project: Restricted Project. · View Herald TranscriptMar 21 2022, 10:52 AM
Herald added a subscriber: StephenFan. · View Herald Transcript
sepavloff added inline comments.Mar 22 2022, 4:53 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
98

This check is almost the same as used by Instruction::isSafeToRemove, but the latter also checks for isEHPad. Why this check is omitted here? Would it be more consistent just to call isSafeToRemove?

kpn added a comment.Apr 19 2022, 11:28 AM

I realized that going through isInstructionTriviallyDead() means it will handle constrained intrinsics differently than it does now. So this isn't strictly speaking an NFC change.

llvm/lib/Transforms/Scalar/SCCP.cpp
98

I believe you are correct and this check should not have been omitted.

I'm trying to eliminate isSafeToRemove() since the Instruction class is the wrong place to do this check, and like the summary says, I don't want another implementation of isInstructionTriviallyDead().

kpn updated this revision to Diff 423689.Apr 19 2022, 11:28 AM
kpn retitled this revision from [NFC][IPSCCP] Switch away from Instruction::isSafeToRemove() to [IPSCCP] Switch away from Instruction::isSafeToRemove().

Update for review comments.

fhahn added inline comments.Apr 21 2022, 3:38 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
98

Why is this extra code needed?

It looks like wouldInstructionBeTriviallyDead doesn't consider atomic loads from globals as trivially dead, which is causing an issue with IPSCCP as it requires such loads to be removed.

According to https://llvm.org/docs/Atomics.html#atomics-and-ir-optimization, atomic loads from globals can be constant folded, so I *think* wouldInstructionBeTriviallyDead should consider them as trivially dead.

sepavloff added inline comments.Apr 21 2022, 6:19 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
94

I would say that SCCP in the function name is excessive, because we are already in SCCP.

98

I wonder if you can just make

return I->isSafeToRemove();

instead of copying the body of isSafeToRemove()?

kpn added inline comments.Apr 21 2022, 9:37 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
94

OK, easily changed.

98

@sepavloff I think we have a few options:

  1. Keep I->isSafeToRemove(), but put wrappers around it. This leaves a land mine for future developers to add more uses of it that are incompatible with the constrained intrinsics.
  2. Keep I->isSafeToRemove(), but teach it about the constrained intrinsics. This makes it a copy of wouldInstructionBeTriviallyDead(), except worse. And it creates confusion in the future because a developer may not know which of the two functions is needed.
  3. Push the body of I->isSafeToRemove() up into the _two_ callers of the function and then eliminate it. No future confusion, no opportunity to break the constrained intrinsics by using the wrong function.

Since there are only two callers it seems to me it's best to take #3 above.

@fhahn, are you referring to the body of Instruction::isSafeToRemove() that has been lifted up into this function here? We were using I->isSafeToRemove() before so this movement into this new wrapper keeps the behavior pretty much the same. IPSCCP's handling of atomic loads shouldn't be affected since a rejection by wouldInstructionBeTriviallyDead() falls through into the same code as before. Can we build on this to improve wouldInstructionBeTriviallyDead() later?

fhahn added inline comments.Apr 22 2022, 12:46 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
98

@fhahn, are you referring to the body of Instruction::isSafeToRemove() that has been lifted up into this function here? We were using I->isSafeToRemove() before so this movement into this new wrapper keeps the behavior pretty much the same. IPSCCP's handling of atomic loads shouldn't be affected since a rejection by wouldInstructionBeTriviallyDead() falls through into the same code as before. Can we build on this to improve wouldInstructionBeTriviallyDead() later?

Yes I meant the inlined code here. Without comment, it is very hard for the reader to understand why it is there and why wouldInstructionBeTriviallyDead is not sufficient. I think it is fine to have some extra checks here before moving them to wouldInstructionBeTriviallyDead, but it should be as minimal as possible, with an explantation and a TODO.

nikic added inline comments.
llvm/lib/Transforms/Scalar/SCCP.cpp
98

I've put up https://reviews.llvm.org/D124241 to add the additional check to wouldInstructionBeTriviallyDead(). Unfortunately, this doesn't fully address the problem, because IPSCCP can also remove loads from non-constant globals if it determines that they are actually constant. We would either have to retain a special case here, or we'd have to mark the globals as constant before attempting to remove uses.

kpn updated this revision to Diff 425278.Apr 26 2022, 12:07 PM

Update for review comments.

kpn added inline comments.May 25 2022, 11:03 AM
llvm/lib/Transforms/Scalar/SCCP.cpp
98

Having a special case here seems like a lower risk change. It can always be improved later. It would be nice to get strictfp improvements to IPSCCP unblocked.

nikic added inline comments.May 25 2022, 12:16 PM
llvm/lib/Transforms/Scalar/SCCP.cpp
98

Having the special case here is fine, but please limit it to isa<LoadInst>(I) and add a comment for why it is necessary (atomic loads from globals that are effectively constant, in a way that IPSCCP knows but wouldInstructionBeTriviallyDead does not). The current comment is unclear on why the additional checks are needed (and most of them are not needed).

kpn updated this revision to Diff 433155.May 31 2022, 11:38 AM

Update for review comments: eliminate unneeded checks.

nikic added a comment.Jun 1 2022, 1:05 AM

This generally looks good to me, but I wonder whether it can be tested? I.e. does this allow eliminating (some) constrained FP intrinsics during SCCP and we can test that? Or does that require additional changes?

llvm/lib/Transforms/Scalar/SCCP.cpp
101

We can't really teach wouldInstructionBeTriviallyDead() about this because it requires SCCP-specific knowledge -- I think a more actionable TODO would be along these lines:

TODO: Mark globals as being constant earlier, sowouldInstructionBeTriviallyDead() knows that atomic loads are safe to remove.

kpn updated this revision to Diff 433443.Jun 1 2022, 10:08 AM

Update comment as requested.

No, the change can't be tested yet. That'll come with D115737 once this gets pushed and I get back to updating that ticket.

nikic accepted this revision.Jun 3 2022, 7:14 AM

LGTM

This revision is now accepted and ready to land.Jun 3 2022, 7:14 AM
This revision was landed with ongoing or failed builds.Jun 6 2022, 6:24 AM
This revision was automatically updated to reflect the committed changes.