This is an archive of the discontinued LLVM Phabricator instance.

[NFC][SLP] Cleanup: Simplify traversal loop in SLPVectorizerPass::vectorizeHorReduction().
ClosedPublic

Authored by vporpo on May 1 2023, 6:51 PM.

Details

Summary

This includes a couple of changes:

  1. Moves the code that changes the root node out of the TryToReduce lambda and out of the traversal loop.
  2. Since that code moved, there isn't much left in TryToReduce so the code was inlined.
  3. The phi node variable P was also being used as a flag that turns on/off the exploration of operands as new seeds. This patch uses a new variable TryOperandsAsNewSeeds for this.
  4. Simplifies the code executed when vectorization fails.

The logic of the code should be identical to the original, but I may be missing something not caught by tests.

Diff Detail

Event Timeline

vporpo created this revision.May 1 2023, 6:51 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 1 2023, 6:51 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
vporpo requested review of this revision.May 1 2023, 6:51 PM
ABataev added inline comments.May 2 2023, 6:03 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14064–14065
  1. Make a separate NFC patch.
  2. Format, the second parameter is not aligned
14104–14106

bool TryOperandsAsNewSeeds = P && isa<BinaryOperator>(Root);

14110–14117
if (P && isa<BinaryOperator>(Root) && HorizontalReduction::getRdxKind(Root) != RecurKind::None)
  Root = tryGetSecondaryReductionRoot(P, Root);
14167

What if Inst is one of the P operands here, but not Root?

14176

I think this is not quite same as before, it should not be a Root, it may be another P operand.

vporpo updated this revision to Diff 518783.May 2 2023, 10:04 AM
vporpo marked an inline comment as done.

Addressed comments.

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14064–14065

OK I will do this in a separate patch.

14110–14117

I kept NewRoot because we need the original Root for Inst == Root later, otherwise the logic changes a bit. I also prefer to use TryOperandsAsNewSeeds instead of P as it shows intent. Same for isReductionCandidate() instead of isa<BinaryOperator>().

14167

This should work as the original code. This condition is the same as line 14028 and 14032.

14176

In the original code P was set to nullptr after visiting the root node, so this would only enter if Inst == Root.

ABataev added inline comments.May 2 2023, 10:37 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14088

auto *Op

14088–14090

return dyn_cast<Instruction>(Op0 == Phi ? Op1 : Op0);

14166–14167

Better to keep this as lambda.

14176

The original code does not compare with Root, it compares with P. What if Inst is an instruction with P operand, but not Root?

14179

Why break here?

vporpo updated this revision to Diff 518809.May 2 2023, 11:13 AM
vporpo marked 2 inline comments as done.

Brought back the lambda and addressed comments.

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14088–14090

Phi and Op are already Instruction * so I will use this instead: return Op == Phi ? dyn_cast<Instruction>(Val: Op1) : Op;

14176

P is set to null after visiting the root node (lines 14060, 14075 and 14081). So the code will enter this if only if Inst is the root node. If it is any other instruction it won't enter.

14179

This can only happen if Inst is the root node and at this point Stack is empty so it effectively breaks out of the loop, so it is better to be explicit about it.

ABataev added inline comments.May 2 2023, 12:34 PM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14086

Better:

if (!match(...))
  return nullptr;
14088–14090

You just don't need Op at all, just
return dyn_cast<Instruction>(Op0 == Phi ? Op1 : Op0);
after assert is enough.

14175–14178

This logic also better to represent as lambda

14179

Add an assert(Stack.empty()) here and check with at least Spec that it does not crash

vporpo updated this revision to Diff 518869.May 2 2023, 2:55 PM
vporpo marked 2 inline comments as done.

Created lambda TryAppendToPostponedInsts and addressed comments.

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14179

I checked with Spec 2017 and our presubmit tests and Stack is always empty.

ABataev added inline comments.May 2 2023, 3:39 PM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14179

Add the assert here

vporpo updated this revision to Diff 518896.May 2 2023, 3:58 PM

Added the assertion.

vporpo marked an inline comment as done.May 2 2023, 3:59 PM
ABataev added inline comments.May 3 2023, 4:29 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14109–14113

Can you turn into lambda too:

auto SelectRoot = [&]() {
  if (TryOperandsAsNewSeeds && isReductionCandidate(Root) &&
      HorizontalReduction::getRdxKind(Root) != RecurKind::None)
    return tryGetSecondaryReductionRoot(P, Root);
  return Root;
}
...
Stack.emplace(SelectRoot(), 0);
14111

TryOperandsAsNewSeeds && isReductionCandidate(Root) && to avoid extra call when TryOperandsAsNewSeeds is false.

14143–14144

auto TryAppendToPostponedInsts = [&]

vporpo updated this revision to Diff 519144.May 3 2023, 10:07 AM
vporpo marked 3 inline comments as done.

Addressed comments.

ABataev added inline comments.May 3 2023, 10:20 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

Replace the message with something meaningful, like 'Empty Stack is expected.'

vporpo added inline comments.May 3 2023, 10:39 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

I think we should also mention why we are checking that Stack is empty, so that we know how to fix this if it triggers the assertion. How about: "Empty Stack expected. Change break to continue?"

ABataev added inline comments.May 3 2023, 10:41 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

The change continue to break is actual only for this patch, not for the codebase. So just Empty stack expected, the original root is reached or something like this should be enough

vporpo added inline comments.May 3 2023, 10:51 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

I don't understand what you mean. We are adding the assertion specifically for checking that changing continue to break was correct, and you are arguing that we should not mention this in the assertion message, and instead write some generic message that provides no information about why this assertion exists.
How will a message like "Empty stack expected, the original root is reached" is supposed to help a third person fix the code if the assertion triggers?

vporpo added inline comments.May 3 2023, 10:55 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

Anyway I don't feel to strongly about this I will change it to what you are proposing.

ABataev added inline comments.May 3 2023, 10:57 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

The assert is not about the change itself. It should not inform about changes you made but about the precondition expected here. asserts are for precondition/postcondition messages, not change history.

So a message like "expecting loop to exit" would

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

Yes the precondition is that the loop will exit right after this point, which explains why we are using break. Shouldn't we mention this in the message? I just don't like assertion messages that repeat the obvious like mentioning "Expected empty stack" when the assertion is assert(Stack.empty()).

ABataev added inline comments.May 3 2023, 11:16 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

You don't need to describe git history in the message, better describe better why Stack is expected to be empty (the original root is reached should help with this). Also, check https://llvm.org/docs/CodingStandards.html#assert-liberally and message examples.

vporpo updated this revision to Diff 519177.May 3 2023, 11:17 AM

Updated assertion message. How about this?

Updated assertion message. How about this?

The break below already means it, better to describe why Stack is expected to be empty here.

vporpo added inline comments.May 3 2023, 11:35 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

The break below already means it, better to describe why Stack is expected to be empty here.

I don't understand why you don't like the message "Expected empty stack, loop should exit".
The precondition is that the loop should exit at this point. The fact that there is a break is exactly what is being checked by the assertion.

ABataev accepted this revision.May 3 2023, 11:46 AM
ABataev added inline comments.
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

It is obvious already, that the loop should exit.

This revision is now accepted and ready to land.May 3 2023, 11:46 AM
vporpo added inline comments.May 3 2023, 11:52 AM
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
14177

How is it obvious? This is exactly what the assertion is checking: if the assertion triggers it means that the loop should not exit and that break is wrong.

Anyway, I think we have already spent too much time on this and it is not that important. I will change it to "Expected stack is epxected" as you originally proposed, even though I think such messages are not very useful.

vporpo updated this revision to Diff 519196.May 3 2023, 11:56 AM

Changed assertion message to "Expected empty stack".

ABataev accepted this revision.May 3 2023, 12:25 PM

Still LG

This revision was landed with ongoing or failed builds.May 3 2023, 12:49 PM
This revision was automatically updated to reflect the committed changes.