This is an archive of the discontinued LLVM Phabricator instance.

[SystemZ] Implement isGuaranteedNotToBeUndefOrPoisonForTargetNode()
ClosedPublic

Authored by jonpa on Jan 31 2023, 3:28 AM.

Details

Summary

Returning true from this method for PCREL_WRAPPER and PCREL_OFFSET avoids problems when a PCREL_OFFSET node ends up with a freeze operand, which is not handled or expected by the backend.

Fixes #60107

There are probably other SystemZISD nodes that could go in here, but I am not quite sure how this is supposed to work: It seems to me that some kind of undef/poison value is recognized and at some point a freeze instruction is inserted in the IR. Then the DAGCombiner optimizes it away because there is a target node that now says that it is never undef..? This is contradictory but probably still worthwhile somehow, but I can't quite figure out how..?

Diff Detail

Event Timeline

jonpa created this revision.Jan 31 2023, 3:28 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 31 2023, 3:28 AM
jonpa requested review of this revision.Jan 31 2023, 3:28 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 31 2023, 3:28 AM
uweigand accepted this revision.Jan 31 2023, 11:43 AM

There are probably other SystemZISD nodes that could go in here, but I am not quite sure how this is supposed to work: It seems to me that some kind of undef/poison value is recognized and at some point a freeze instruction is inserted in the IR. Then the DAGCombiner optimizes it away because there is a target node that now says that it is never undef..? This is contradictory but probably still worthwhile somehow, but I can't quite figure out how..?

Here's the documentation of the FREEZE node:

// FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or
// is evaluated to UNDEF), or returns VAL otherwise. Note that each
// read of UNDEF can yield different value, but FREEZE(UNDEF) cannot.

So the way I understand that is that various code transformations are only correct if multiple evaluations of a value always yield the same result. Now, since this property does not hold for undef values, you'd have to prove the value cannot be undef in order to perform the transformation. That may be difficult or impossible in general. Therefore, you can use a FREEZE node instead, which prevents this from happening.

Now, it is on the code generator to handle FREEZE efficiently. But one obvious observation is that *if* the inner value of FREEZE *actually* can be proven to never be undef, then the FREEZE is a no-op and can just be removed. This is what common code already does, but sometimes it fails with target nodes, because it doesn't understand what those nodes do and therefore cannot perform this optimization. This target hook helps with that.

So in general, every target node where we unconditionally know it never returns undef should go in isGuaranteedNotToBeUndefOrPoisonForTargetNode, and every target node where we at least conditionally know that, in the case where none of the *arguments* to the target node are undef, the result is never undef either, should go in canCreateUndefOrPoisonForTargetNode.

These require reasoning about the properties of our various target nodes, so I think it's fine if this goes in in stages over time. But this patch at least is obviously correct, and if it fixes some failures, it should go it now.

This revision is now accepted and ready to land.Jan 31 2023, 11:43 AM
This revision was landed with ongoing or failed builds.Feb 1 2023, 4:28 AM
This revision was automatically updated to reflect the committed changes.
jonpa added a comment.Feb 1 2023, 4:30 AM

Thanks for explanation!