-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[IA][RISCV] Support VP loads/stores in InterleavedAccessPass #120490
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 3 commits
156661a
c869bec
3688672
32d8de5
6b7f8e9
f7242df
0e4bf69
1afd2cc
16a88d9
5cd5be4
16915c9
725dfad
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 |
|---|---|---|
|
|
@@ -630,11 +630,35 @@ getVectorDeinterleaveFactor(IntrinsicInst *II, | |
| return true; | ||
| } | ||
|
|
||
| /// Check the interleaved mask | ||
| /// | ||
| /// - if a value within the optional is non-nullptr, the value corresponds to | ||
| /// deinterleaved mask | ||
| /// - if a value within the option is nullptr, the value corresponds to all-true | ||
| /// mask | ||
| /// - return nullopt if mask cannot be deinterleaved | ||
| static Value *getMask(Value *WideMask, unsigned Factor) { | ||
| using namespace llvm::PatternMatch; | ||
| if (auto *IMI = dyn_cast<IntrinsicInst>(WideMask)) { | ||
| SmallVector<Value *, 8> Operands; | ||
| SmallVector<Instruction *, 8> DeadInsts; | ||
| if (getVectorInterleaveFactor(IMI, Operands, DeadInsts)) { | ||
| assert(!Operands.empty()); | ||
| if (Operands.size() == Factor && | ||
| std::equal(Operands.begin(), Operands.end(), Operands.begin())) | ||
topperc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return Operands.front(); | ||
| } | ||
| } | ||
| if (match(WideMask, m_AllOnes())) | ||
| return WideMask; | ||
|
||
|
|
||
| return nullptr; | ||
| } | ||
|
|
||
| bool InterleavedAccessImpl::lowerDeinterleaveIntrinsic( | ||
| IntrinsicInst *DI, SmallSetVector<Instruction *, 32> &DeadInsts) { | ||
| LoadInst *LI = dyn_cast<LoadInst>(DI->getOperand(0)); | ||
|
|
||
| if (!LI || !LI->hasOneUse() || !LI->isSimple()) | ||
| Value *LoadedVal = DI->getOperand(0); | ||
| if (!LoadedVal->hasOneUse() || !isa<LoadInst, VPIntrinsic>(LoadedVal)) | ||
| return false; | ||
|
|
||
| SmallVector<Value *, 8> DeinterleaveValues; | ||
|
|
@@ -643,43 +667,92 @@ bool InterleavedAccessImpl::lowerDeinterleaveIntrinsic( | |
| DeinterleaveDeadInsts)) | ||
| return false; | ||
|
|
||
| LLVM_DEBUG(dbgs() << "IA: Found a deinterleave intrinsic: " << *DI | ||
| << " with factor = " << DeinterleaveValues.size() << "\n"); | ||
| const unsigned Factor = DeinterleaveValues.size(); | ||
|
|
||
| // Try and match this with target specific intrinsics. | ||
| if (!TLI->lowerDeinterleaveIntrinsicToLoad(LI, DeinterleaveValues)) | ||
| return false; | ||
| if (auto *VPLoad = dyn_cast<VPIntrinsic>(LoadedVal)) { | ||
| if (VPLoad->getIntrinsicID() != Intrinsic::vp_load) | ||
| return false; | ||
| // Check mask operand. Handle both all-true and interleaved mask. | ||
| Value *WideMask = VPLoad->getOperand(1); | ||
| Value *Mask = getMask(WideMask, Factor); | ||
| if (!Mask) | ||
| return false; | ||
|
|
||
| LLVM_DEBUG(dbgs() << "IA: Found a vp.load with deinterleave intrinsic " | ||
| << *DI << " and factor = " << Factor << "\n"); | ||
|
|
||
| // Since lowerInterleaveLoad expects Shuffles and LoadInst, use special | ||
| // TLI function to emit target-specific interleaved instruction. | ||
| if (!TLI->lowerDeinterleavedIntrinsicToVPLoad(VPLoad, Mask, | ||
| DeinterleaveValues)) | ||
| return false; | ||
|
|
||
| } else { | ||
| auto *LI = cast<LoadInst>(LoadedVal); | ||
| if (!LI->isSimple()) | ||
| return false; | ||
|
|
||
| LLVM_DEBUG(dbgs() << "IA: Found a load with deinterleave intrinsic " << *DI | ||
| << " and factor = " << Factor << "\n"); | ||
|
|
||
| // Try and match this with target specific intrinsics. | ||
| if (!TLI->lowerDeinterleaveIntrinsicToLoad(LI, DeinterleaveValues)) | ||
| return false; | ||
| } | ||
|
|
||
| DeadInsts.insert(DeinterleaveDeadInsts.begin(), DeinterleaveDeadInsts.end()); | ||
| // We now have a target-specific load, so delete the old one. | ||
| DeadInsts.insert(LI); | ||
| DeadInsts.insert(cast<Instruction>(LoadedVal)); | ||
| return true; | ||
| } | ||
|
|
||
| bool InterleavedAccessImpl::lowerInterleaveIntrinsic( | ||
| IntrinsicInst *II, SmallSetVector<Instruction *, 32> &DeadInsts) { | ||
| if (!II->hasOneUse()) | ||
| return false; | ||
|
|
||
| StoreInst *SI = dyn_cast<StoreInst>(*(II->users().begin())); | ||
|
|
||
| if (!SI || !SI->isSimple()) | ||
| Value *StoredBy = II->user_back(); | ||
| if (!isa<StoreInst, VPIntrinsic>(StoredBy)) | ||
| return false; | ||
|
|
||
| SmallVector<Value *, 8> InterleaveValues; | ||
| SmallVector<Instruction *, 8> InterleaveDeadInsts; | ||
| if (!getVectorInterleaveFactor(II, InterleaveValues, InterleaveDeadInsts)) | ||
| return false; | ||
|
|
||
| LLVM_DEBUG(dbgs() << "IA: Found an interleave intrinsic: " << *II | ||
| << " with factor = " << InterleaveValues.size() << "\n"); | ||
| const unsigned Factor = InterleaveValues.size(); | ||
|
|
||
| // Try and match this with target specific intrinsics. | ||
| if (!TLI->lowerInterleaveIntrinsicToStore(SI, InterleaveValues)) | ||
| return false; | ||
| if (auto *VPStore = dyn_cast<VPIntrinsic>(StoredBy)) { | ||
| if (VPStore->getIntrinsicID() != Intrinsic::vp_store) | ||
| return false; | ||
|
|
||
| Value *WideMask = VPStore->getOperand(2); | ||
| Value *Mask = getMask(WideMask, Factor); | ||
| if (!Mask) | ||
| return false; | ||
|
|
||
| LLVM_DEBUG(dbgs() << "IA: Found a vp.store with interleave intrinsic " | ||
| << *II << " and factor = " << Factor << "\n"); | ||
|
|
||
| // Since lowerInterleavedStore expects Shuffle and StoreInst, use special | ||
| // TLI function to emit target-specific interleaved instruction. | ||
| if (!TLI->lowerInterleavedIntrinsicToVPStore(VPStore, Mask, | ||
| InterleaveValues)) | ||
| return false; | ||
| } else { | ||
| auto *SI = cast<StoreInst>(StoredBy); | ||
| if (!SI->isSimple()) | ||
| return false; | ||
|
|
||
| LLVM_DEBUG(dbgs() << "IA: Found a store with interleave intrinsic " << *II | ||
| << " and factor = " << Factor << "\n"); | ||
|
|
||
| // Try and match this with target specific intrinsics. | ||
| if (!TLI->lowerInterleaveIntrinsicToStore(SI, InterleaveValues)) | ||
| return false; | ||
| } | ||
|
|
||
| // We now have a target-specific store, so delete the old one. | ||
| DeadInsts.insert(SI); | ||
| DeadInsts.insert(cast<Instruction>(StoredBy)); | ||
| DeadInsts.insert(InterleaveDeadInsts.begin(), InterleaveDeadInsts.end()); | ||
| return true; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.