This is an archive of the discontinued LLVM Phabricator instance.

[LICM] Reassociate & hoist add expressions
ClosedPublic

Authored by mkazantsev on Apr 25 2023, 12:56 AM.

Details

Summary

This patch allows LICM to reassociate and hoist following expressions:

loop:
  %sum = add nsw %iv, %C1
  %cmp = icmp <signed pred> %sum, C2

where C1 and C2 are loop invariants. The reassociated version looks like

preheader:
  %inv_sum = C2 - C1
...
loop:
  %cmp = icmp <signed pred> %iv, %inv_sum

In order to prove legality, we need both initial addition and the newly created subtraction
to happen without overflow.

Diff Detail

Event Timeline

mkazantsev created this revision.Apr 25 2023, 12:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 25 2023, 12:56 AM
mkazantsev requested review of this revision.Apr 25 2023, 12:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 25 2023, 12:56 AM
skatkov added inline comments.Apr 25 2023, 3:37 AM
llvm/lib/Transforms/Scalar/LICM.cpp
2627

Any comments?
Why LHS invariant is not interested to you? Covered in other place? Assert instead of if?

Is hasOneUse a cost model? We want to remove original add?

2638

Comment?

2646

Some words about, why it is legal if both add and sub are nsw?

mkazantsev added inline comments.Apr 25 2023, 3:44 AM
llvm/lib/Transforms/Scalar/LICM.cpp
2627

Yes, we want to remove the original add.

mkazantsev marked 3 inline comments as done.

Added even more comments.

anna added inline comments.Apr 25 2023, 9:29 AM
llvm/lib/Transforms/Scalar/LICM.cpp
2639

Nit: LHS itself is an invariant.

2653

Don't we need to check for isa<SCEVCouldNotCompute>(RHSS) here and below for InvariantOp before getting NegativeSCEV?

Proof: https://alive2.llvm.org/ce/z/imgdNt

Somewhat skeptical about introducing SCEV use in LICM. As you are actually reasoning about loop invariants here, do we need SCEV? Would using computeOverflowForSignedSub() from ValueTracking work, possibly even provide better results?

llvm/lib/Transforms/Scalar/LICM.cpp
2654–2657

This seems more obvious and matches the generated sub?

skatkov added inline comments.Apr 25 2023, 7:33 PM
llvm/lib/Transforms/Scalar/LICM.cpp
2651

Will SCEV more powerful to check that LHS is NSW then just check of flag on instruction?

mkazantsev added inline comments.Apr 25 2023, 10:07 PM
llvm/lib/Transforms/Scalar/LICM.cpp
2654–2657

Yes, and it provides worse results on the tests that are here.

mkazantsev added inline comments.Apr 25 2023, 10:08 PM
llvm/lib/Transforms/Scalar/LICM.cpp
2653

No, value's SCEV is never SCEVCouldNotCompute. You can only get SCEVCouldNotCompute when computing some loop exit count, for example.

mkazantsev added inline comments.Apr 25 2023, 10:11 PM
llvm/lib/Transforms/Scalar/LICM.cpp
2651

In theory, yes.

mkazantsev planned changes to this revision.Apr 25 2023, 10:28 PM

Proof: https://alive2.llvm.org/ce/z/imgdNt

Somewhat skeptical about introducing SCEV use in LICM. As you are actually reasoning about loop invariants here, do we need SCEV? Would using computeOverflowForSignedSub() from ValueTracking work, possibly even provide better results?

Let me check if it achieves the same result.

Reworked w/o SCEV, using ValueTracking's API as Nikita has proposed.

llvm/lib/Transforms/Scalar/LICM.cpp
2639

I must have been crazy when I wrote this. It's not just a bunch of typos, but it's also "variant" instead of "invariant" :)

2651

Added one more overflow check, leaving nsw as shortcut.

2654–2657

No longer actual after API change.

nikic added inline comments.Apr 26 2023, 12:08 AM
llvm/lib/Transforms/Scalar/LICM.cpp
2561

If it is

2574–2575

InstCombine will do exactly this inference already, so I think we should only be checking the nsw flag here.

mkazantsev marked 2 inline comments as done.

Typo fixed, check reduced to nsw check.

nikic added inline comments.Apr 28 2023, 5:28 AM
llvm/test/Transforms/LICM/hoist-add-sub.ll
394

TODO incorrectly dropped here. But I think maybe the test isn't right and %x is supposed to use range !1 not !0? Same for the pair of tests above.

444

Drop TODO.

mkazantsev planned changes to this revision.May 1 2023, 8:56 PM

Err, indeed I messed up with test TODOs.

llvm/test/Transforms/LICM/hoist-add-sub.ll
394

No, range !0 is good enough here. The original add doesn't overflow because of nsw, and the new sub doesn't overflow because it's a subtraction of two non-negatives.

This comment was removed by mkazantsev.
mkazantsev updated this revision to Diff 518632.EditedMay 1 2023, 10:09 PM

Fixed bug (typo) that caused messup with checks in tests. Bug was

if (ProvedNoOverflowAfterReassociate)
  return false;

instead of

if (!ProvedNoOverflowAfterReassociate)
  return false;

Friday evening refactoring is evil.

Some NFC reafactoring due to request to untwine sub and add logic.

mkazantsev marked 2 inline comments as done.May 2 2023, 1:37 AM
mkazantsev updated this revision to Diff 518652.May 2 2023, 1:55 AM

NFC. Used m_NSWAdd.

mkazantsev planned changes to this revision.May 2 2023, 2:39 AM

I'm planning to roll back to SCEV version. Value Tracking doesn't infer things from dominating conditions.

mkazantsev requested review of this revision.May 2 2023, 4:59 AM

Ok, getting SCEV here brings potential correctness issues... Let's keep Value tracking.

D149648 shows that SCEV is more powerful than value tracking (the latter cannot figure out the range from dominating checks).

LGTM, @nikic, any remaining concerns?

This revision was not accepted when it landed; it landed in state Needs Review.May 21 2023, 11:22 PM
This revision was automatically updated to reflect the committed changes.