aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2025-12-06 19:56:45 +0000
committerDimitry Andric <dim@FreeBSD.org>2025-12-06 20:08:43 +0000
commit3f709e42e3be0f28a88ca3e77663a02b52c914f4 (patch)
tree948796bf3bf7e164373caf6c31f9f128ca85fd8c /llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp
parent32a711e1c447004eb1fd015925f305ed1d8426de (diff)
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp53
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)