-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SLP] NFC. Use InstructionsState::valid if users just want to know whether VL has same opcode. #120217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SLP] NFC. Use InstructionsState::valid if users just want to know whether VL has same opcode. #120217
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-vectorizers Author: Han-Kuan Chen (HanKuanChen) ChangesFull diff: https://github.com/llvm/llvm-project/pull/120217.diff 1 Files Affected:
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index d967813075bb9f..8a6958c3541bd7 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -868,8 +868,8 @@ static bool areCompatibleCmpOps(Value *BaseOp0, Value *BaseOp1, Value *Op0,
(!isa<Instruction>(BaseOp0) && !isa<Instruction>(Op0) &&
!isa<Instruction>(BaseOp1) && !isa<Instruction>(Op1)) ||
BaseOp0 == Op0 || BaseOp1 == Op1 ||
- getSameOpcode({BaseOp0, Op0}, TLI).getOpcode() ||
- getSameOpcode({BaseOp1, Op1}, TLI).getOpcode();
+ getSameOpcode({BaseOp0, Op0}, TLI).getMainOp() ||
+ getSameOpcode({BaseOp1, Op1}, TLI).getMainOp();
}
/// \returns true if a compare instruction \p CI has similar "look" and
@@ -2380,7 +2380,7 @@ class BoUpSLP {
// Use Boyer-Moore majority voting for finding the majority opcode and
// the number of times it occurs.
if (auto *I = dyn_cast<Instruction>(OpData.V)) {
- if (!OpcodeI || !getSameOpcode({OpcodeI, I}, TLI).getOpcode() ||
+ if (!OpcodeI || !getSameOpcode({OpcodeI, I}, TLI).getMainOp() ||
I->getParent() != Parent) {
if (NumOpsWithSameOpcodeParent == 0) {
NumOpsWithSameOpcodeParent = 1;
@@ -2500,7 +2500,7 @@ class BoUpSLP {
// next lane does not build same opcode sequence.
(Lns == 2 &&
!getSameOpcode({Op, getValue((OpI + 1) % OpE, Ln)}, TLI)
- .getOpcode() &&
+ .getMainOp() &&
isa<Constant>(Data.V)))) ||
// 3. The operand in the current lane is loop invariant (can be
// hoisted out) and another operand is also a loop invariant
@@ -2509,7 +2509,7 @@ class BoUpSLP {
// FIXME: need to teach the cost model about this case for better
// estimation.
(IsInvariant && !isa<Constant>(Data.V) &&
- !getSameOpcode({Op, Data.V}, TLI).getOpcode() &&
+ !getSameOpcode({Op, Data.V}, TLI).getMainOp() &&
L->isLoopInvariant(Data.V))) {
FoundCandidate = true;
Data.IsUsed = Data.V == Op;
@@ -2539,7 +2539,7 @@ class BoUpSLP {
return true;
Value *OpILn = getValue(OpI, Ln);
return (L && L->isLoopInvariant(OpILn)) ||
- (getSameOpcode({Op, OpILn}, TLI).getOpcode() &&
+ (getSameOpcode({Op, OpILn}, TLI).getMainOp() &&
allSameBlock({Op, OpILn}));
}))
return true;
@@ -4766,7 +4766,7 @@ static bool arePointersCompatible(Value *Ptr1, Value *Ptr2,
!CompareOpcodes ||
(GEP1 && GEP2 &&
getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)
- .getOpcode()));
+ .getMainOp()));
}
/// Calculates minimal alignment as a common alignment.
@@ -13223,7 +13223,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
Value *In1 = PHI1->getIncomingValue(I);
if (isConstant(In) && isConstant(In1))
continue;
- if (!getSameOpcode({In, In1}, *TLI).getOpcode())
+ if (!getSameOpcode({In, In1}, *TLI).getMainOp())
return false;
if (cast<Instruction>(In)->getParent() !=
cast<Instruction>(In1)->getParent())
@@ -13251,7 +13251,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
if (It != UsedValuesEntry.end())
UsedInSameVTE = It->second == UsedValuesEntry.find(V)->second;
return V != V1 && MightBeIgnored(V1) && !UsedInSameVTE &&
- getSameOpcode({V, V1}, *TLI).getOpcode() &&
+ getSameOpcode({V, V1}, *TLI).getMainOp() &&
cast<Instruction>(V)->getParent() ==
cast<Instruction>(V1)->getParent() &&
(!isa<PHINode>(V1) || AreCompatiblePHIs(V, V1));
@@ -21346,8 +21346,7 @@ bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) {
return false;
if (I1->getParent() != I2->getParent())
return false;
- InstructionsState S = getSameOpcode({I1, I2}, *TLI);
- if (S.getOpcode())
+ if (getSameOpcode({I1, I2}, *TLI).getMainOp())
continue;
return false;
}
@@ -21701,8 +21700,7 @@ bool SLPVectorizerPass::vectorizeStoreChains(BoUpSLP &R) {
"Different nodes should have different DFS numbers");
if (NodeI1 != NodeI2)
return NodeI1->getDFSNumIn() < NodeI2->getDFSNumIn();
- InstructionsState S = getSameOpcode({I1, I2}, *TLI);
- if (S.getOpcode())
+ if (getSameOpcode({I1, I2}, *TLI).getMainOp())
return false;
return I1->getOpcode() < I2->getOpcode();
}
@@ -21728,8 +21726,7 @@ bool SLPVectorizerPass::vectorizeStoreChains(BoUpSLP &R) {
if (auto *I2 = dyn_cast<Instruction>(V2->getValueOperand())) {
if (I1->getParent() != I2->getParent())
return false;
- InstructionsState S = getSameOpcode({I1, I2}, *TLI);
- return S.getOpcode() > 0;
+ return getSameOpcode({I1, I2}, *TLI).getMainOp() != nullptr;
}
if (isa<Constant>(V1->getValueOperand()) &&
isa<Constant>(V2->getValueOperand()))
|
Retitle the patch |
if (S.getOpcode() == Instruction::ExtractElement && | ||
isa<ScalableVectorType>( | ||
cast<ExtractElementInst>(S.getMainOp())->getVectorOperandType())) { | ||
if (auto *EE = dyn_cast_if_present<ExtractElementInst>(S.getMainOp()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto *EE = dyn_cast_if_present<ExtractElementInst>(S.getMainOp()); | |
if (auto *EE = dyn_cast<ExtractElementInst>(S.getMainOp()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot. S may not be valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then you cannot use getMainOp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The origin code check MainOp opcode (
S.getOpcode() == Instruction::ExtractElement
) and usecast
later. I think usedyn_cast_if_present
is better.
if (S.getOpcode() == Instruction::ExtractElement &&
isa<ScalableVectorType>(
cast<ExtractElementInst>(S.getMainOp())->getVectorOperandType())) {
- There is a case which uses
isa_and_present
. Follow the same idea, I usedyn_cast_if_present
here.
bool AreAllSameInsts = AreAllSameBlock || AreScatterAllGEPSameBlock;
if (!AreAllSameInsts || (!S && allConstant(VL)) || isSplat(VL) ||
(isa_and_present<InsertElementInst, ExtractValueInst, ExtractElementInst>(
S.getMainOp()) &&
!all_of(VL, isVectorLikeInstWithConstOps)) ||
NotProfitableForVectorization(VL)) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I.e. the original code check if S is valid, has the opcode ExtractElement and then checks the vector type. getMainOp will crash, if S is invalid. If S is valid, getMainOp cannot return nullptr. dyn_cast_if_present should not be used here, just a dyn_cast should be enough. getMainOp just cannot return nullptr.
- It should be fixed, need to replace by
S and isa<....>(S.getMainOp())
. It worked before, currently it will crash, if S is invalid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently some code use isa some code use getOpcode. I think we should either
- use isa, dyn_cast, isa_and_present and dyn_cast_if_present for getMainOp
- use getOpcode and check whether the opcode is what we want
to make the code consistency.
However, isa (and others) can check isa_and_present<InsertElementInst, ExtractValueInst, ExtractElementInst>
with less code. Use getOpcode
will write a lot of code in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't work, it will crash the compiler, _and_present
are not required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can work. See c9ccb55.
isa_and_present<>
= S.valid() && isa<>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should not work. getMainOp()
and getAltOp()
should crash if requested from invalid state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. See 1c16e5c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getMainOp and getAltOp should assert if the state is invalid
Cannot. |
It must be fixed. TreeEntry shall check if the state is valid and only after using getMainOp and getAltOp. Otherwise, use nullptr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG
I'm seeing this when doing check-llvm:
This happens when compiling |
This may be solved by #122443. |
Not sure what command you need, check-llvm is a part of the testing I've invoked with
|
Looks like this has been crashing for a couple of hours. Can we revert this to unblock people or land a fix ASAP? |
It is fixed by #122443. |
I see, but the fix hasn't landed yet, and it is not clear when it will land. If it takes longer, the change should be reverted Also, if the change fixes a crash, I don't think it is really NFC :) |
Really appreciate your advice. I will test more and resubmit it. It is reverted already. |
Add assert for InstructionsState::getOpcode.
Use InstructionsState::getOpcode only when necessary.