This is an archive of the discontinued LLVM Phabricator instance.

[IndVarSimplify] Reduce nondeterministic behaviour in visitIVCast.
ClosedPublic

Authored by sdesmalen on Oct 26 2021, 1:33 PM.

Details

Summary

rGf39978b84f1d3a1da6c32db48f64c8daae64b3ad led to and/or exposed
an issue with IndVarSimplification for a loop where a i32 phi node is
no longer replaced by a widened (i64) phi node, because the SCEVs of a
sign-extend no longer folded the same way. I'm unsure how to properly
explain this because it's all rather complicated, but in short: SCEVs
don't fold as nicely as they used to and this caused a difference.

While investigating this, I found that IndVarSimplify can actually
optimise the case in the way we want to if it chooses the widened IV to
be 'signed' (the i32 IV is both sign and zero-extended). Oddly enough,
there is some level of indeterminism in the way the algorithm works,
it just picks the sign of the 'first' zext/sext user, where the order of
the users-iterator is not guaranteed to be the same on each invocation
of the pass (e.g. shown by first running loop-rotate, which puts the
users in a different order).

While I think the fix is valid in the sense that consistently picking
_any_ order is better than having an nondeterministic order, I can
use a bit of advice from people more familiar in this area of the
code-base.

For example, I'm not sure if this fix is hiding another issue where the
IndVarSimplify pass could actually draw the same conclusions (i.e. that
it only needs an i64 phi node) if it does a bit more work, regardless
of whether it chooses the induction variable to be signed or unsigned.

I'm also not sure if choosing signed is better than unsigned, or whether
that just happens to be beneficial only in this individual case.

Any feedback would be much appreciated!

Diff Detail

Event Timeline

sdesmalen created this revision.Oct 26 2021, 1:33 PM
sdesmalen requested review of this revision.Oct 26 2021, 1:33 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 26 2021, 1:33 PM

If I understand your proposal correctly, you propose to replace scheme "take signedness from 1st user which is non-deterministically selected" with scheme "if at least one user of widest type is signed cast, widen as signed; otherwize widen as unsigned"?

In general, it makes sense to me and it also seems to solve the non-determinism you are describing. The only concern I have is, you use signed widening as default (and unsigned is possible under stricter conditions). On the other hand, IV tries hard to turn all icmp's to unsigned predicate form, preferring unsigned as default. This creates some discord between different parts of it.

Is it possible to use unsigned widening as break-even? In terms of your patch it would be replacing

WI.IsSigned |= IsSigned;

with

WI.IsSigned &= IsSigned;
llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
561

Do you mean if (!WI.IsSigned && IsSigned) ? I guess it's an equivalent check. And it is also equivalent to unconditional

WI.IsSigned |= IsSigned;

Hi @mkazantsev, thanks for having a look at this patch!

If I understand your proposal correctly, you propose to replace scheme "take signedness from 1st user which is non-deterministically selected" with scheme "if at least one user of widest type is signed cast, widen as signed; otherwize widen as unsigned"?

Yes, that's right, I figured that consistently choosing one over the other at least removes the non-determinism.

In general, it makes sense to me and it also seems to solve the non-determinism you are describing. The only concern I have is, you use signed widening as default (and unsigned is possible under stricter conditions). On the other hand, IV tries hard to turn all icmp's to unsigned predicate form, preferring unsigned as default. This creates some discord between different parts of it.

I guess it's possible to favour unsigned as the default, but the specific example in the test doesn't optimise as well when choosing unsigned, because we end up with 2 induction variables in the loop instead of 1. For one critical loop that I investigated, this led to multiple redundant sign-extends.
This code is not very familiar to me though, so if you can give me some hints on how to make IndVarSimplify handle the unsigned case, I'd be happy to look into that!

This is strange. From what I'm seeing, your IV starts from 1 and is just trivially positive, so there should not be any troubles with using zext. Could you please post a separate review with the unsigned version & its generated checks for this test?

sdesmalen updated this revision to Diff 385968.Nov 9 2021, 1:53 PM

Removed control flow in favor of WI.IsSigned |= IsSigned;

sdesmalen marked an inline comment as done.Nov 9 2021, 1:53 PM

This is strange. From what I'm seeing, your IV starts from 1 and is just trivially positive, so there should not be any troubles with using zext. Could you please post a separate review with the unsigned version & its generated checks for this test?

I've posted the unsigned version in D113516.

Surely this causes some test diff in the existing test corpus? It looks like the review is incomplete. (Or I'm simply very surprised.)

Under the assumption the diff is incomplete, I'd suggest a slightly more complicate heuristic. Pick signed or unsigned based on which we see more of. Simply keep two counters, pick the larger, and tie break when equal towards sign.

If there actually no other diffs, you can ignore previous. I just find that slightly hard to believe. :)

Surely this causes some test diff in the existing test corpus? It looks like the review is incomplete. (Or I'm simply very surprised.)

The patch is actually complete, it's indeed very surprising that no other tests fail (I've built for all targets and ran make check-all).
Consistently choosing signed (this patch) causes no other tests to fail. Consistently choosing unsigned causes only one other test to fail (D113516).

reames accepted this revision.Nov 14 2021, 2:24 PM

LGTM. We can revisit more complicate heuristics when we have evidence it matters.

This revision is now accepted and ready to land.Nov 14 2021, 2:24 PM