[llvm] [AMDGPU] Fix LDS access via flat pointer argument in amdgpu-sw-lower-lds (PR #209842)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 30 08:17:53 PDT 2026


================
@@ -287,6 +303,99 @@ void AMDGPUSwLowerLDS::getNonKernelsWithLDSArguments(const CallGraph &CG) {
   }
 }
 
+// True if flat pointer V is derived from an LDS-carrying argument in LDSArgs,
+// looking through GEP/bitcast/phi/select; Visited breaks phi cycles. When
+// AcceptLocalCast is set, a flat<-local addrspacecast also counts as an origin.
+// Detection (getNonKernelsWithLDSFlatArguments) sets it, since that cast is how
+// LDS first enters a flat pointer; the rewrite
+// (getFlatPtrForRoundTripLDSAccess) leaves it clear so only argument origins
+// qualify.
+static bool flatPtrDerivesFromLDS(Value *V,
+                                  const SmallPtrSetImpl<Argument *> &LDSArgs,
+                                  SmallPtrSetImpl<Value *> &Visited,
+                                  bool AcceptLocalCast) {
+  if (!V->getType()->isPointerTy() || !Visited.insert(V).second)
+    return false;
+  if (auto *A = dyn_cast<Argument>(V))
+    return LDSArgs.contains(A);
+  auto *Op = dyn_cast<Operator>(V);
+  if (!Op)
+    return false;
+  switch (Op->getOpcode()) {
+  case Instruction::AddrSpaceCast: {
+    if (!AcceptLocalCast)
+      return false;
+    Value *Src = Op->getOperand(0);
+    if (Src->getType()->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
+      return true;
+    return flatPtrDerivesFromLDS(Src, LDSArgs, Visited, AcceptLocalCast);
+  }
+  case Instruction::GetElementPtr:
+  case Instruction::BitCast:
+    return flatPtrDerivesFromLDS(Op->getOperand(0), LDSArgs, Visited,
+                                 AcceptLocalCast);
+  case Instruction::PHI:
+    for (Value *In : cast<PHINode>(Op)->incoming_values())
+      if (flatPtrDerivesFromLDS(In, LDSArgs, Visited, AcceptLocalCast))
+        return true;
+    return false;
+  case Instruction::Select: {
+    auto *SI = cast<SelectInst>(Op);
+    return flatPtrDerivesFromLDS(SI->getTrueValue(), LDSArgs, Visited,
+                                 AcceptLocalCast) ||
+           flatPtrDerivesFromLDS(SI->getFalseValue(), LDSArgs, Visited,
+                                 AcceptLocalCast);
+  }
+  default:
+    return false;
+  }
+}
+
+void AMDGPUSwLowerLDS::getNonKernelsWithLDSFlatArguments() {
+  // A kernel or non-kernel may pass lowered LDS storage to a non-kernel as a
+  // flat pointer instead of addrspace(3). Record, per callee, which flat
+  // parameters carry LDS. Must run before lowering rewrites the call-site
+  // casts.
+  auto &FlatArgMap = FuncLDSAccessInfo.NonKernelsWithLDSFlatArg;
+  bool Changed = true;
+  while (Changed) {
+    Changed = false;
+    for (Function &F : M) {
+      if (F.isDeclaration())
+        continue;
+      SmallPtrSet<Argument *, 4> CallerLDSArgs;
+      if (auto It = FlatArgMap.find(&F); It != FlatArgMap.end())
+        CallerLDSArgs = It->second;
+      for (BasicBlock &BB : F) {
+        for (Instruction &I : BB) {
+          auto *CB = dyn_cast<CallBase>(&I);
+          if (!CB)
+            continue;
+          Function *Callee = CB->getCalledFunction();
+          if (!Callee || Callee->isDeclaration() || AMDGPU::isKernel(*Callee))
+            continue;
+          unsigned NumArgs =
+              std::min(CB->arg_size(), (unsigned)Callee->arg_size());
----------------
skc7 wrote:

Thanks for feedback. Updated in latest patch.

https://github.com/llvm/llvm-project/pull/209842


More information about the llvm-commits mailing list