-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[IA] Relax the requirement of having ExtractValue users on deinterleave intrinsic #148716
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
Changes from 2 commits
40ed9ae
5106d8b
fd0de02
b4e1320
445a187
aec05c4
25a49c9
cffff30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -306,6 +306,25 @@ unsigned llvm::getDeinterleaveIntrinsicFactor(Intrinsic::ID ID) { | |
| } | ||
| } | ||
|
|
||
| unsigned VectorDeinterleaving::getFactor() const { | ||
| assert(isValid()); | ||
| if (DI) | ||
| return getDeinterleaveIntrinsicFactor(DI->getIntrinsicID()); | ||
| else | ||
|
||
| return Values.size(); | ||
| } | ||
|
|
||
| Type *VectorDeinterleaving::getDeinterleavedType() const { | ||
| assert(getFactor() > 0); | ||
| if (DI) { | ||
| return *DI->getType()->subtype_begin(); | ||
| } else { | ||
|
||
| Value *FirstActive = | ||
| *llvm::find_if(Values, [](Value *V) { return V != nullptr; }); | ||
| return FirstActive->getType(); | ||
| } | ||
| } | ||
|
|
||
| /// Given a vector and an element number, see if the scalar value is | ||
| /// already around as a register, for example if it were inserted then extracted | ||
| /// from the vector. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17476,16 +17476,15 @@ bool AArch64TargetLowering::lowerInterleavedStore(StoreInst *SI, | |
| } | ||
|
|
||
| bool AArch64TargetLowering::lowerDeinterleaveIntrinsicToLoad( | ||
| LoadInst *LI, ArrayRef<Value *> DeinterleavedValues) const { | ||
| unsigned Factor = DeinterleavedValues.size(); | ||
| LoadInst *LI, IntrinsicInst *DI) const { | ||
| VectorDeinterleaving VD(DI); | ||
| const unsigned Factor = VD.getFactor(); | ||
| if (Factor != 2 && Factor != 4) { | ||
| LLVM_DEBUG(dbgs() << "Matching ld2 and ld4 patterns failed\n"); | ||
| return false; | ||
| } | ||
|
|
||
| Value *FirstActive = *llvm::find_if(DeinterleavedValues, | ||
| [](Value *V) { return V != nullptr; }); | ||
| VectorType *VTy = cast<VectorType>(FirstActive->getType()); | ||
| VectorType *VTy = cast<VectorType>(VD.getDeinterleavedType()); | ||
|
|
||
| const DataLayout &DL = LI->getModule()->getDataLayout(); | ||
| bool UseScalable; | ||
|
|
@@ -17513,7 +17512,10 @@ bool AArch64TargetLowering::lowerDeinterleaveIntrinsicToLoad( | |
| Builder.CreateVectorSplat(LdTy->getElementCount(), Builder.getTrue()); | ||
|
|
||
| Value *BaseAddr = LI->getPointerOperand(); | ||
| Value *Result = nullptr; | ||
| if (NumLoads > 1) { | ||
| Result = PoisonValue::get(DI->getType()); | ||
|
||
|
|
||
| // Create multiple legal small ldN. | ||
| SmallVector<Value *, 4> ExtractedLdValues(Factor, PoisonValue::get(VTy)); | ||
| for (unsigned I = 0; I < NumLoads; ++I) { | ||
|
|
@@ -17533,25 +17535,19 @@ bool AArch64TargetLowering::lowerDeinterleaveIntrinsicToLoad( | |
| } | ||
| LLVM_DEBUG(dbgs() << "LdN4 res: "; LdN->dump()); | ||
| } | ||
| // Replace output of deinterleave2 intrinsic by output of ldN2/ldN4 | ||
| for (unsigned J = 0; J < Factor; ++J) { | ||
| if (DeinterleavedValues[J]) | ||
| DeinterleavedValues[J]->replaceAllUsesWith(ExtractedLdValues[J]); | ||
| } | ||
|
|
||
| // Merge the values from different factors. | ||
| for (unsigned J = 0; J < Factor; ++J) | ||
| Result = Builder.CreateInsertValue(Result, ExtractedLdValues[J], J); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this extra intertvalue shouldn't affect codegen. @hassnaaHamdi do you think AArch64 also needs some codegen tests for InterleavedAccess? |
||
| } else { | ||
| Value *Result; | ||
| if (UseScalable) | ||
| Result = Builder.CreateCall(LdNFunc, {Pred, BaseAddr}, "ldN"); | ||
| else | ||
| Result = Builder.CreateCall(LdNFunc, BaseAddr, "ldN"); | ||
| // Replace output of deinterleave2 intrinsic by output of ldN2/ldN4 | ||
| for (unsigned I = 0; I < Factor; I++) { | ||
| if (DeinterleavedValues[I]) { | ||
| Value *NewExtract = Builder.CreateExtractValue(Result, I); | ||
| DeinterleavedValues[I]->replaceAllUsesWith(NewExtract); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Replace output of deinterleave2 intrinsic by output of ldN2/ldN4 | ||
| DI->replaceAllUsesWith(Result); | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| #include "RISCVISelLowering.h" | ||
| #include "RISCVSubtarget.h" | ||
| #include "llvm/Analysis/ValueTracking.h" | ||
| #include "llvm/Analysis/VectorUtils.h" | ||
| #include "llvm/CodeGen/ValueTypes.h" | ||
| #include "llvm/IR/IRBuilder.h" | ||
| #include "llvm/IR/Instructions.h" | ||
|
|
@@ -233,17 +234,17 @@ bool RISCVTargetLowering::lowerInterleavedStore(StoreInst *SI, | |
| } | ||
|
|
||
| bool RISCVTargetLowering::lowerDeinterleaveIntrinsicToLoad( | ||
| LoadInst *LI, ArrayRef<Value *> DeinterleaveValues) const { | ||
| const unsigned Factor = DeinterleaveValues.size(); | ||
| LoadInst *LI, IntrinsicInst *DI) const { | ||
| VectorDeinterleaving VD(DI); | ||
| const unsigned Factor = VD.getFactor(); | ||
| assert(Factor && "unexpected deinterleaving factor"); | ||
|
||
| if (Factor > 8) | ||
| return false; | ||
|
|
||
| assert(LI->isSimple()); | ||
| IRBuilder<> Builder(LI); | ||
|
|
||
| Value *FirstActive = | ||
| *llvm::find_if(DeinterleaveValues, [](Value *V) { return V != nullptr; }); | ||
| VectorType *ResVTy = cast<VectorType>(FirstActive->getType()); | ||
| VectorType *ResVTy = cast<VectorType>(VD.getDeinterleavedType()); | ||
|
|
||
| const DataLayout &DL = LI->getDataLayout(); | ||
|
|
||
|
|
@@ -293,16 +294,7 @@ bool RISCVTargetLowering::lowerDeinterleaveIntrinsicToLoad( | |
| } | ||
| } | ||
|
|
||
| for (auto [Idx, DIV] : enumerate(DeinterleaveValues)) { | ||
| if (!DIV) | ||
| continue; | ||
| // We have to create a brand new ExtractValue to replace each | ||
| // of these old ExtractValue instructions. | ||
| Value *NewEV = | ||
| Builder.CreateExtractValue(Return, {static_cast<unsigned>(Idx)}); | ||
| DIV->replaceAllUsesWith(NewEV); | ||
| } | ||
|
|
||
| DI->replaceAllUsesWith(Return); | ||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -419,16 +411,14 @@ static bool isMultipleOfN(const Value *V, const DataLayout &DL, unsigned N) { | |
| /// dealing with factor of 2 (extractvalue is still required for most of other | ||
| /// factors though). | ||
| bool RISCVTargetLowering::lowerInterleavedVPLoad( | ||
| VPIntrinsic *Load, Value *Mask, | ||
| ArrayRef<Value *> DeinterleaveResults) const { | ||
| const unsigned Factor = DeinterleaveResults.size(); | ||
| VPIntrinsic *Load, Value *Mask, const VectorDeinterleaving &VD) const { | ||
| assert(Mask && "Expect a valid mask"); | ||
| assert(Load->getIntrinsicID() == Intrinsic::vp_load && | ||
| "Unexpected intrinsic"); | ||
|
|
||
| Value *FirstActive = *llvm::find_if(DeinterleaveResults, | ||
| [](Value *V) { return V != nullptr; }); | ||
| VectorType *VTy = cast<VectorType>(FirstActive->getType()); | ||
| const unsigned Factor = VD.getFactor(); | ||
| assert(Factor && "unexpected vector deinterleaving"); | ||
| VectorType *VTy = cast<VectorType>(VD.getDeinterleavedType()); | ||
|
|
||
| auto &DL = Load->getModule()->getDataLayout(); | ||
| Align Alignment = Load->getParamAlign(0).value_or( | ||
|
|
@@ -494,14 +484,18 @@ bool RISCVTargetLowering::lowerInterleavedVPLoad( | |
| } | ||
| } | ||
|
|
||
| for (auto [Idx, DIO] : enumerate(DeinterleaveResults)) { | ||
| if (!DIO) | ||
| continue; | ||
| // We have to create a brand new ExtractValue to replace each | ||
| // of these old ExtractValue instructions. | ||
| Value *NewEV = | ||
| Builder.CreateExtractValue(Return, {static_cast<unsigned>(Idx)}); | ||
| DIO->replaceAllUsesWith(NewEV); | ||
| if (VD.DI) { | ||
| VD.DI->replaceAllUsesWith(Return); | ||
| } else { | ||
| for (auto [Idx, DIO] : enumerate(VD.Values)) { | ||
| if (!DIO) | ||
| continue; | ||
| // We have to create a brand new ExtractValue to replace each | ||
| // of these old ExtractValue instructions. | ||
| Value *NewEV = | ||
| Builder.CreateExtractValue(Return, {static_cast<unsigned>(Idx)}); | ||
| DIO->replaceAllUsesWith(NewEV); | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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 tried to make this wrapper as simple as possible. I'm open to make it a union + tag or even
std::variant.