This is an archive of the discontinued LLVM Phabricator instance.

[LoopPredication] Do not sink conditions to branches. PR61673
AbandonedPublic

Authored by mkazantsev on Mar 24 2023, 2:56 AM.

Details

Summary

This patch fixes the bug that happens when we sink a widenable condition from
outside the loop into the loop, and therefore creating more possible execution
paths than existed before.

This sinking is:

Maybe there was some intent here, but there is no test that would show why it is done
and I could not find such reason myself. So I'm just removing this code.

Diff Detail

Unit TestsFailed

Event Timeline

mkazantsev created this revision.Mar 24 2023, 2:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2023, 2:56 AM
mkazantsev requested review of this revision.Mar 24 2023, 2:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2023, 2:56 AM

@reames you seem to be the author of this code. Do you remember why it was done? I couldn't figure out the motivation from this comment or tests.

Adding more context here: This transform gets enabled by LICM hoisting widenable conditions (today it is hidden because we stopped LICM from hoisting widenable conditions: https://reviews.llvm.org/D146274). Also, while discussing with @apilipenko about the comment in Loop Predication, he pointed that the latter part of the comment referred to older implementation in loop predication before we had GuardUtils::widenBranch API.
Specifically the latter part of this comment (" inserting code before it and then modifying the operand is legal.") :

// Subtlety: We need to avoid inserting additional uses of the WC.  We know
 // that it can only have one transitive use at the moment, and thus moving
 // that use to just before the branch and inserting code before it and then
 // modifying the operand is legal.

But we could not identify why "we need to avoid inserting additional uses of the WC".

It seems there is a wider problem here. At least, according to me, there is nothing in the semantics of widenable condition that prevents us from sinking widenable condition into the loop. This means we can have subtle (and hard to debug) miscompiles such as the one caused here and in GuardWidening (explained here: https://github.com/llvm/llvm-project/issues/60234). Anything that prevents LLVM transforms from sinking widenable condition into loops?

One more point: the original cause of the downstream miscompile is still present after this fix (that makes sense because even when we sink the widenable condition into the loop, later LICM comes along and hoists it out, so the bug attempted to be fixed by this patch is masked). In short - the miscompile is seen when we have loop predication's hoisting of widenable condition, followed by loop predication's predicate loop exits transform here. Will continue investigation on that front.

This patch probably solves a bug as explained by Max here: https://github.com/llvm/llvm-project/issues/61673

mkazantsev added a comment.EditedMar 26 2023, 9:49 PM

It seems there is a wider problem here. At least, according to me, there is nothing in the semantics of widenable condition that prevents us from sinking widenable condition into the loop.

@anna here is how WC is declared:

// Supports widenable conditions for guards represented as explicit branches.
def int_experimental_widenable_condition : Intrinsic<[llvm_i1_ty], [],
                                           [IntrInaccessibleMemOnly, IntrWillReturn]>;

it has semantics of accessing innacessible memory. In particular, it can read or write it. So you cannot sink it into the loops for the same reasons as you cannot do so to volatile loads. Hoisting - possibly legal (assuming that no one else is accessing this memory), but sinking is sure not.

So by default, we should not move it at all, unless we intentionally did exceptions (and I'm currently finding and undoing them; they were not meant to exist).

anna added a comment.Apr 5 2023, 2:35 PM

Thanks for clarification Max.

This is superseded by the complete fix here: https://reviews.llvm.org/D147662

anna added inline comments.Apr 5 2023, 2:37 PM
llvm/lib/Transforms/Scalar/LoopPredication.cpp
1188

We should not widen at the branch, but rather at the widenable call. This is handled in the patch referenced above.

mkazantsev abandoned this revision.Apr 13 2023, 10:21 PM

Closing per Anna's comment.