diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2025-12-06 19:56:45 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2025-12-06 20:08:43 +0000 |
| commit | 3f709e42e3be0f28a88ca3e77663a02b52c914f4 (patch) | |
| tree | 948796bf3bf7e164373caf6c31f9f128ca85fd8c /llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp | |
| parent | 32a711e1c447004eb1fd015925f305ed1d8426de (diff) | |
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp')
| -rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp index 55497c837ee2..d443f4ea7d5c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp @@ -186,6 +186,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetOperations.h" #include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -195,7 +196,6 @@ #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/ReplaceConstant.h" -#include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -532,8 +532,7 @@ public: auto InsertAt = F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca(); IRBuilder<> Builder(&*InsertAt); - It->second = - Builder.CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {}, {}); + It->second = Builder.CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {}); } return It->second; @@ -573,7 +572,7 @@ public: if (OrderedKernels.size() > UINT32_MAX) { // 32 bit keeps it in one SGPR. > 2**32 kernels won't fit on the GPU - report_fatal_error("Unimplemented LDS lowering for > 2**32 kernels"); + reportFatalUsageError("unimplemented LDS lowering for > 2**32 kernels"); } for (size_t i = 0; i < OrderedKernels.size(); i++) { @@ -633,7 +632,8 @@ public: if (K.second.size() == 1) { KernelAccessVariables.insert(GV); } else { - report_fatal_error( + // FIXME: This should use DiagnosticInfo + reportFatalUsageError( "cannot lower LDS '" + GV->getName() + "' to kernel access as it is reachable from multiple kernels"); } @@ -782,7 +782,7 @@ public: // backend) difficult to use. This does mean that llvm test cases need // to name the kernels. if (!Func.hasName()) { - report_fatal_error("Anonymous kernels cannot use LDS variables"); + reportFatalUsageError("anonymous kernels cannot use LDS variables"); } std::string VarName = @@ -878,7 +878,7 @@ public: if (KernelsThatIndirectlyAllocateDynamicLDS.contains(func)) { assert(isKernelLDS(func)); if (!func->hasName()) { - report_fatal_error("Anonymous kernels cannot use LDS variables"); + reportFatalUsageError("anonymous kernels cannot use LDS variables"); } GlobalVariable *N = @@ -1016,7 +1016,7 @@ public: auto NewGV = uniquifyGVPerKernel(M, GV, F); Changed |= (NewGV != GV); int BarId = (NumAbsolutes + 1); - if (Kernel2BarId.find(F) != Kernel2BarId.end()) { + if (Kernel2BarId.contains(F)) { BarId = (Kernel2BarId[F] + 1); } Kernel2BarId[F] = BarId; @@ -1442,6 +1442,8 @@ private: if (!MaxDepth || (A == 1 && !AliasScope)) return; + ScopedNoAliasAAResult ScopedNoAlias; + for (User *U : Ptr->users()) { if (auto *I = dyn_cast<Instruction>(U)) { if (AliasScope && I->mayReadOrWriteMemory()) { @@ -1451,7 +1453,34 @@ private: I->setMetadata(LLVMContext::MD_alias_scope, AS); MDNode *NA = I->getMetadata(LLVMContext::MD_noalias); - NA = (NA ? MDNode::intersect(NA, NoAlias) : NoAlias); + + // Scoped aliases can originate from two different domains. + // First domain would be from LDS domain (created by this pass). + // All entries (LDS vars) into LDS struct will have same domain. + + // Second domain could be existing scoped aliases that are the + // results of noalias params and subsequent optimizations that + // may alter thesse sets. + + // We need to be careful how we create new alias sets, and + // have right scopes and domains for loads/stores of these new + // LDS variables. We intersect NoAlias set if alias sets belong + // to the same domain. This is the case if we have memcpy using + // LDS variables. Both src and dst of memcpy would belong to + // LDS struct, they donot alias. + // On the other hand, if one of the domains is LDS and other is + // existing domain prior to LDS, we need to have a union of all + // these aliases set to preserve existing aliasing information. + + SmallPtrSet<const MDNode *, 16> ExistingDomains, LDSDomains; + ScopedNoAlias.collectScopedDomains(NA, ExistingDomains); + ScopedNoAlias.collectScopedDomains(NoAlias, LDSDomains); + auto Intersection = set_intersection(ExistingDomains, LDSDomains); + if (Intersection.empty()) { + NA = NA ? MDNode::concatenate(NA, NoAlias) : NoAlias; + } else { + NA = NA ? MDNode::intersect(NA, NoAlias) : NoAlias; + } I->setMetadata(LLVMContext::MD_noalias, NA); } } @@ -1503,10 +1532,8 @@ public: const AMDGPUTargetMachine *TM; static char ID; - AMDGPULowerModuleLDSLegacy(const AMDGPUTargetMachine *TM_ = nullptr) - : ModulePass(ID), TM(TM_) { - initializeAMDGPULowerModuleLDSLegacyPass(*PassRegistry::getPassRegistry()); - } + AMDGPULowerModuleLDSLegacy(const AMDGPUTargetMachine *TM = nullptr) + : ModulePass(ID), TM(TM) {} void getAnalysisUsage(AnalysisUsage &AU) const override { if (!TM) |
