This is an archive of the discontinued LLVM Phabricator instance.

[SimplifyCFG] avoid illegal phi with both poison and undef
ClosedPublic

Authored by spatel on Feb 25 2021, 1:25 PM.

Details

Summary

In the example based on:
https://llvm.org/PR49218
...we are crashing because poison is a subclass of undef, so we merge blocks and create:

PHI node has multiple entries for the same basic block with different incoming values!
  %k3 = phi i64 [ poison, %entry ], [ %k3, %g ], [ undef, %entry ]

I think we could soften the poison to undef, but it seems unlikely that this would matter in any real code.

Diff Detail

Event Timeline

spatel created this revision.Feb 25 2021, 1:25 PM
spatel requested review of this revision.Feb 25 2021, 1:25 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 25 2021, 1:25 PM
lebedev.ri added inline comments.Feb 25 2021, 11:36 PM
llvm/test/Transforms/SimplifyCFG/poison-merge.ll
14–17

It looks like we didn't merge them after all?

What about updating redirectValuesFromPredecessorsToPhi to lower conflicting poison to undef?
We can maintain two sets of incoming BBs, say BBundef and BBpoison that have poison incoming values and undef incoming values.
At the end of redirectValuesFromPredecessorsToPhi, if BBundef and BBpoison overlaps, there are operands that need to be updated.
It will keep the transformation enabled.

spatel edited the summary of this revision. (Show Details)Feb 26 2021, 4:57 AM
spatel marked an inline comment as done.
spatel added inline comments.
llvm/test/Transforms/SimplifyCFG/poison-merge.ll
14–17

That's correct - let me add some tests of the other value combos to make it clearer what this patch does.

I'm fine with having this as a quickfix, but i think we shouldn't pessimize such case in general, but actually properly handle it.

spatel updated this revision to Diff 326659.Feb 26 2021, 5:08 AM
spatel marked an inline comment as done.

Patch updated:
No code change, but added negative (for this patch) tests to show that the transform still fires in the expected (existing) combinations.

What about updating redirectValuesFromPredecessorsToPhi to lower conflicting poison to undef?
We can maintain two sets of incoming BBs, say BBundef and BBpoison that have poison incoming values and undef incoming values.
At the end of redirectValuesFromPredecessorsToPhi, if BBundef and BBpoison overlaps, there are operands that need to be updated.
It will keep the transformation enabled.

Yes, we can do better on this, but I suspect it's rare to encounter both poison and undef (and gets more rare as we eliminate more and more undef from IR?).

What about updating redirectValuesFromPredecessorsToPhi to lower conflicting poison to undef?
We can maintain two sets of incoming BBs, say BBundef and BBpoison that have poison incoming values and undef incoming values.
At the end of redirectValuesFromPredecessorsToPhi, if BBundef and BBpoison overlaps, there are operands that need to be updated.
It will keep the transformation enabled.

Yes, we can do better on this, but I suspect it's rare to encounter both poison and undef (and gets more rare as we eliminate more and more undef from IR?).

I think it won't be very rare ATM because there are quite a few places that create poison constants.

Maybe we can create a new function that 'sanitizes' operands in PHI: it checks whether a PHI has multiple incoming edges with different undef/poison constants, and if there's any, replace such poison constants with undefs.

p = phi [ undef, BB ], [ poison, BB ]
  -> PHINode::sanitize (or something like this, I guess this isn't the best name)
p = phi [ undef,  BB ], [ undef, BB ]

If a new bug that's similar to this issue is reported, we can simply add a call to this function and it will fix the bug.

spatel updated this revision to Diff 326802.Feb 26 2021, 2:30 PM

Patch updated:
We have a dedicated function for replacing undef incoming values, so I enhanced that to account for poison mismatches.
This gives us the expected, optimized result in all of the test examples.

aqjune accepted this revision.Feb 26 2021, 6:44 PM

LGTM
The fix is conservative, but I think it is okay. I believe this will be helpful in addressing (imaginary) hidden crashes by making undef/poison operands homogeneous.

This revision is now accepted and ready to land.Feb 26 2021, 6:44 PM
lebedev.ri accepted this revision.Feb 26 2021, 11:14 PM

Looks ok to me, thanks.

This revision was landed with ongoing or failed builds.Feb 27 2021, 6:58 AM
This revision was automatically updated to reflect the committed changes.