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

Pablo Reble via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 20:12:04 PDT 2026


================
@@ -777,17 +919,78 @@ void AMDGPUSwLowerLDS::translateLDSMemoryOperationsToGlobalMemory(
       MI->eraseFromParent();
     } else if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(Inst)) {
       Value *AIOperand = ASC->getPointerOperand();
-      Value *Replacement =
-          getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, AIOperand);
+      Value *Replacement = TranslatePtr(AIOperand);
+      if (!Replacement)
+        continue;
       Value *NewAI = IRB.CreateAddrSpaceCast(Replacement, ASC->getType());
       // Note: No need to add the instruction to AsanInfo instructions to be
       // instrumented list. FLAT_ADDRESS ptr would have been already
       // instrumented by asan pass prior to this pass.
       ASC->replaceAllUsesWith(NewAI);
       ASC->eraseFromParent();
+      MaybeDeadPtrs.push_back(AIOperand);
     } else
       report_fatal_error("Unimplemented LDS lowering instruction");
   }
+
+  // Drop the now-dead flat->local casts and local GEPs.
+  RecursivelyDeleteTriviallyDeadInstructionsPermissive(MaybeDeadPtrs);
+}
+
+Value *AMDGPUSwLowerLDS::getFlatPtrForRoundTripLDSAccess(Function *Func,
+                                                         Value *LDSPtr) {
+  // If LDSPtr is lowered storage reached via a flat argument, i.e.
+  // addrspacecast(flat->local) optionally followed by local GEPs, return the
+  // equivalent flat pointer into the global backing buffer. Otherwise nullptr,
+  // so the caller falls back to the base/offset-table translation.
+  auto It = FuncLDSAccessInfo.NonKernelsWithLDSFlatArg.find(Func);
+  if (It == FuncLDSAccessInfo.NonKernelsWithLDSFlatArg.end())
+    return nullptr;
+  const SmallPtrSet<Argument *, 4> &LDSArgs = It->second;
+
+  // Peel off local GEPs sitting between the cast and the access.
+  SmallVector<GEPOperator *, 4> GEPs;
+  Value *Cur = LDSPtr;
+  while (auto *GEP = dyn_cast<GEPOperator>(Cur)) {
+    if (GEP->getPointerAddressSpace() != AMDGPUAS::LOCAL_ADDRESS)
+      return nullptr;
+    GEPs.push_back(GEP);
+    Cur = GEP->getPointerOperand();
+  }
+
+  auto *ASC = dyn_cast<Operator>(Cur);
+  if (!ASC || ASC->getOpcode() != Instruction::AddrSpaceCast)
+    return nullptr;
+  Value *FlatSrc = ASC->getOperand(0);
+  if (FlatSrc->getType()->getPointerAddressSpace() != AMDGPUAS::FLAT_ADDRESS)
+    return nullptr;
----------------
reble wrote:

```suggestion
  auto *ASC = dyn_cast<AddrSpaceCastOperator>(Cur);
  if (!ASC || ASC->getSrcAddressSpace() != AMDGPUAS::FLAT_ADDRESS ||
      ASC->getDestAddressSpace() != AMDGPUAS::LOCAL_ADDRESS)
    return nullptr;
  Value *FlatSrc = ASC->getPointerOperand();
```
Using `AddrSpaceCastOperator` instead of manual handling for consistency?

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


More information about the llvm-commits mailing list