[llvm] [OpenMP] Fix debug locations in GPU reductions (PR #228622)
Amadeu Moya via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 5 12:46:24 PDT 2026
Amadeu Moya =?utf-8?q?Sardà ?= <moyasarda1 at llnl.gov>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/228622 at github.com>
https://github.com/amad00r updated https://github.com/llvm/llvm-project/pull/228622
>From c77fca3e06f1b46578123e0d486a9ac095132288 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Amadeu=20Moya=20Sard=C3=A0?= <moyasarda1 at llnl.gov>
Date: Fri, 2 Oct 2026 16:33:25 -0700
Subject: [PATCH 1/2] [OpenMP] Fix debug locations in GPU reductions
GPU reduction codegen temporarily switches the IRBuilder to AllocaIP to
create reduction storage. In Clang, AllocaIP points before the
unlocated allocapt marker, which clears the current debug location.
Restoring the insertion point does not restore the debug location, so
the following inlinable runtime calls lack !dbg.
Use InsertPointGuard for temporary alloca insertion regions, preserving
both the caller insertion point and debug location.
Remove redundant saveIP/restoreIP pairs around helper emitters that
already use InsertPointGuard internally to preserve the builder state.
Add an OpenMPIRBuilder unit test that models Clang's allocapt insertion
point and verifies the expected runtime call has a valid debug
location.
---
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 60 +++++++++----------
.../Frontend/OpenMPIRBuilderTest.cpp | 60 +++++++++++++++++++
2 files changed, 89 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 2c60bf3d67a9cde..0a70b6337f1f427 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -4809,6 +4809,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
if (!updateToLocation(Loc))
return InsertPointTy();
Builder.restoreIP(CodeGenIP);
+ Builder.SetCurrentDebugLocation(Loc.DL);
checkReductionInfos(ReductionInfos, /*IsGPU*/ true);
LLVMContext &Ctx = M.getContext();
@@ -4839,14 +4840,12 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
AttrBldr.removeAttribute(Attribute::OptimizeNone);
FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
- CodeGenIP = Builder.saveIP();
Expected<Function *> ReductionResult = createReductionFunction(
Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
ReductionGenCBKind, FuncAttrs);
if (!ReductionResult)
return ReductionResult.takeError();
Function *ReductionFunc = *ReductionResult;
- Builder.restoreIP(CodeGenIP);
// Set the grid value in the config needed for lowering later on
if (GridValue.has_value())
@@ -4867,13 +4866,14 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
Type *FuncPtrTy =
Builder.getPtrTy(M.getDataLayout().getProgramAddressSpace());
Type *RedArrayTy = ArrayType::get(PtrTy, Size);
- CodeGenIP = Builder.saveIP();
- Builder.restoreIP(AllocaIP);
- Value *ReductionListAlloca =
- Builder.CreateAlloca(RedArrayTy, nullptr, ".omp.reduction.red_list");
- Value *ReductionList = Builder.CreatePointerBitCastOrAddrSpaceCast(
- ReductionListAlloca, PtrTy, ReductionListAlloca->getName() + ".ascast");
- Builder.restoreIP(CodeGenIP);
+ Value *ReductionList = [&] {
+ IRBuilder<>::InsertPointGuard IPG(Builder);
+ Builder.restoreIP(AllocaIP);
+ Value *ReductionListAlloca =
+ Builder.CreateAlloca(RedArrayTy, nullptr, ".omp.reduction.red_list");
+ return Builder.CreatePointerBitCastOrAddrSpaceCast(
+ ReductionListAlloca, PtrTy, ReductionListAlloca->getName() + ".ascast");
+ }();
Type *IndexTy = Builder.getIndexTy(
M.getDataLayout(), M.getDataLayout().getDefaultGlobalsAddressSpace());
for (auto En : enumerate(ReductionInfos)) {
@@ -4891,7 +4891,6 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
Builder.CreateStore(CastElem, ElemPtr);
}
- CodeGenIP = Builder.saveIP();
Expected<Function *> SarFunc = emitShuffleAndReduceFunction(
ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
@@ -4903,7 +4902,6 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
if (!CopyResult)
return CopyResult.takeError();
Function *WcFunc = *CopyResult;
- Builder.restoreIP(CodeGenIP);
Value *RL = Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
@@ -4960,7 +4958,6 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
Res = createRuntimeFunctionCall(IsMainThreadFn, {});
} else {
- CodeGenIP = Builder.saveIP();
StructType *ReductionsBufferTy = StructType::create(
Ctx, ReductionTypeArgs, "struct._globalized_locals_ty");
@@ -4979,8 +4976,6 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
if (!GtLRFunc)
return GtLRFunc.takeError();
- Builder.restoreIP(CodeGenIP);
-
// The runtime's cross-team final aggregate uses the storage pointed at by
// its reduce-list argument as per-thread scratch. When the surrounding
// kernel is already in SPMD execution mode, clang emitted each reduction
@@ -5001,23 +4996,26 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
Value *RuntimeRL = RL;
if (!IsSPMD) {
- CodeGenIP = Builder.saveIP();
- Builder.restoreIP(AllocaIP);
- // Allocate thread-local buffer for the reduction variables.
- Value *PerThreadScratchAlloca = Builder.CreateAlloca(
- ReductionsBufferTy, /*ArraySize=*/nullptr, ".omp.reduction.scratch");
- Value *PerThreadScratch = Builder.CreatePointerBitCastOrAddrSpaceCast(
- PerThreadScratchAlloca, PtrTy,
- PerThreadScratchAlloca->getName() + ".ascast");
- // Allocate thread-local buffer for the pointers to the reduction
- // variables.
- Value *PerThreadRedListAlloca =
- Builder.CreateAlloca(RedArrayTy, /*ArraySize=*/nullptr,
- ".omp.reduction.per_thread_red_list");
- RuntimeRL = Builder.CreatePointerBitCastOrAddrSpaceCast(
- PerThreadRedListAlloca, PtrTy,
- PerThreadRedListAlloca->getName() + ".ascast");
- Builder.restoreIP(CodeGenIP);
+ Value *PerThreadScratch = [&] {
+ IRBuilder<>::InsertPointGuard IPG(Builder);
+ Builder.restoreIP(AllocaIP);
+ // Allocate thread-local buffer for the reduction variables.
+ Value *PerThreadScratchAlloca =
+ Builder.CreateAlloca(ReductionsBufferTy, /*ArraySize=*/nullptr,
+ ".omp.reduction.scratch");
+ Value *PerThreadScratch = Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PerThreadScratchAlloca, PtrTy,
+ PerThreadScratchAlloca->getName() + ".ascast");
+ // Allocate thread-local buffer for the pointers to the reduction
+ // variables.
+ Value *PerThreadRedListAlloca =
+ Builder.CreateAlloca(RedArrayTy, /*ArraySize=*/nullptr,
+ ".omp.reduction.per_thread_red_list");
+ RuntimeRL = Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PerThreadRedListAlloca, PtrTy,
+ PerThreadRedListAlloca->getName() + ".ascast");
+ return PerThreadScratch;
+ }();
// Iterate over the reduction variables and copy the team-local value to
// the thread-local buffer.
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index 2010533b7e6db4d..e75754ffd05ea84 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -5457,6 +5457,66 @@ TEST_F(OpenMPIRBuilderTest, CreateReductions) {
EXPECT_TRUE(findGEPZeroOne(ReductionFn->getArg(1), FirstRHS, SecondRHS));
}
+TEST_F(OpenMPIRBuilderTest, GPUTeamsReductionRuntimeCallHasDebugLoc) {
+ using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
+ OpenMPIRBuilder OMPBuilder(*M);
+ OMPBuilder.Config.IsTargetDevice = true;
+ OMPBuilder.Config.setIsGPU(true);
+ OMPBuilder.initialize();
+
+ IRBuilder<> Builder(BB);
+ Instruction *AllocaInsertPt =
+ new BitCastInst(PoisonValue::get(Builder.getInt32Ty()),
+ Builder.getInt32Ty(), "allocapt", BB);
+ Builder.SetInsertPoint(BB);
+ Builder.SetCurrentDebugLocation(DL);
+ InsertPointTy AllocaIP(AllocaInsertPt->getIterator());
+ Value *Original;
+ Value *Private;
+ {
+ IRBuilder<>::InsertPointGuard Guard(Builder);
+ Builder.restoreIP(AllocaIP);
+ Original = Builder.CreateAlloca(Builder.getFloatTy(), nullptr, "original");
+ Private = Builder.CreateAlloca(Builder.getFloatTy(), nullptr, "private");
+ }
+
+ auto ReductionGen = [](InsertPointTy IP, unsigned, Value **LHSPtr,
+ Value **RHSPtr, Function *) {
+ IRBuilder<> Builder(IP.getNodeParent(), IP);
+ *LHSPtr = Builder.CreateAlloca(Builder.getFloatTy());
+ *RHSPtr = Builder.CreateAlloca(Builder.getFloatTy());
+ Builder.CreateLoad(Builder.getFloatTy(), *LHSPtr);
+ Builder.CreateLoad(Builder.getFloatTy(), *RHSPtr);
+ return Builder.saveIP();
+ };
+ OpenMPIRBuilder::ReductionInfo ReductionInfos[] = {
+ {Builder.getFloatTy(), Original, Private,
+ /*EvaluationKind=*/OpenMPIRBuilder::EvalKind::Scalar,
+ /*ReductionGen=*/nullptr, ReductionGen,
+ /*AtomicReductionGen=*/nullptr, /*DataPtrPtrGen=*/nullptr}};
+ bool IsByRef[] = {false};
+
+ OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
+ ASSERT_EXPECTED_INIT(
+ InsertPointTy, AfterIP,
+ OMPBuilder.createReductionsGPU(
+ Loc, AllocaIP, Builder.saveIP(), ReductionInfos, IsByRef,
+ /*IsNoWait=*/false, /*IsTeamsReduction=*/true, /*IsSPMD=*/true,
+ OpenMPIRBuilder::ReductionGenCBKind::Clang, omp::NVPTXGridValues));
+ Builder.restoreIP(AfterIP);
+ Builder.CreateRetVoid();
+
+ SmallVector<CallInst *> Calls;
+ findCalls(F, RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait,
+ OMPBuilder, Calls);
+ ASSERT_EQ(Calls.size(), 1u);
+ ASSERT_TRUE(Calls.front()->getDebugLoc());
+ EXPECT_EQ(Calls.front()->getDebugLoc()->getScope()->getSubprogram(),
+ F->getSubprogram());
+
+ EXPECT_FALSE(verifyModule(*M));
+}
+
static void createScan(llvm::Value *scanVar, llvm::Type *scanType,
OpenMPIRBuilder &OMPBuilder, IRBuilder<> &Builder,
OpenMPIRBuilder::LocationDescription Loc,
>From 86925d581db8f1ab305dfd662950d422e0c9df18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Amadeu=20Moya=20Sard=C3=A0?= <moyasarda1 at llnl.gov>
Date: Mon, 5 Oct 2026 11:42:47 -0700
Subject: [PATCH 2/2] Test __kmpc_nvptx_parallel_reduce_nowait_v2 and style fix
---
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 16 ++++++----
.../Frontend/OpenMPIRBuilderTest.cpp | 32 +++++++++++++------
2 files changed, 32 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 0a70b6337f1f427..4a25e3da23625c7 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -4866,14 +4866,15 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
Type *FuncPtrTy =
Builder.getPtrTy(M.getDataLayout().getProgramAddressSpace());
Type *RedArrayTy = ArrayType::get(PtrTy, Size);
- Value *ReductionList = [&] {
+ Value *ReductionList;
+ {
IRBuilder<>::InsertPointGuard IPG(Builder);
Builder.restoreIP(AllocaIP);
Value *ReductionListAlloca =
Builder.CreateAlloca(RedArrayTy, nullptr, ".omp.reduction.red_list");
- return Builder.CreatePointerBitCastOrAddrSpaceCast(
+ ReductionList = Builder.CreatePointerBitCastOrAddrSpaceCast(
ReductionListAlloca, PtrTy, ReductionListAlloca->getName() + ".ascast");
- }();
+ }
Type *IndexTy = Builder.getIndexTy(
M.getDataLayout(), M.getDataLayout().getDefaultGlobalsAddressSpace());
for (auto En : enumerate(ReductionInfos)) {
@@ -4996,14 +4997,16 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
Value *RuntimeRL = RL;
if (!IsSPMD) {
- Value *PerThreadScratch = [&] {
+ Value *PerThreadScratch;
+
+ {
IRBuilder<>::InsertPointGuard IPG(Builder);
Builder.restoreIP(AllocaIP);
// Allocate thread-local buffer for the reduction variables.
Value *PerThreadScratchAlloca =
Builder.CreateAlloca(ReductionsBufferTy, /*ArraySize=*/nullptr,
".omp.reduction.scratch");
- Value *PerThreadScratch = Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PerThreadScratch = Builder.CreatePointerBitCastOrAddrSpaceCast(
PerThreadScratchAlloca, PtrTy,
PerThreadScratchAlloca->getName() + ".ascast");
// Allocate thread-local buffer for the pointers to the reduction
@@ -5014,8 +5017,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createReductionsGPU(
RuntimeRL = Builder.CreatePointerBitCastOrAddrSpaceCast(
PerThreadRedListAlloca, PtrTy,
PerThreadRedListAlloca->getName() + ".ascast");
- return PerThreadScratch;
- }();
+ };
// Iterate over the reduction variables and copy the team-local value to
// the thread-local buffer.
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index e75754ffd05ea84..2f9cd8d498f4530 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -5496,23 +5496,37 @@ TEST_F(OpenMPIRBuilderTest, GPUTeamsReductionRuntimeCallHasDebugLoc) {
/*AtomicReductionGen=*/nullptr, /*DataPtrPtrGen=*/nullptr}};
bool IsByRef[] = {false};
- OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
ASSERT_EXPECTED_INIT(
InsertPointTy, AfterIP,
OMPBuilder.createReductionsGPU(
- Loc, AllocaIP, Builder.saveIP(), ReductionInfos, IsByRef,
+ {Builder.saveIP(), DL}, AllocaIP, Builder.saveIP(), ReductionInfos,
+ IsByRef,
/*IsNoWait=*/false, /*IsTeamsReduction=*/true, /*IsSPMD=*/true,
OpenMPIRBuilder::ReductionGenCBKind::Clang, omp::NVPTXGridValues));
Builder.restoreIP(AfterIP);
+
+ ASSERT_EXPECTED_INIT(
+ InsertPointTy, AfterParallelReductionIP,
+ OMPBuilder.createReductionsGPU(
+ {Builder.saveIP(), DL}, AllocaIP, Builder.saveIP(), ReductionInfos,
+ IsByRef,
+ /*IsNoWait=*/false, /*IsTeamsReduction=*/false, /*IsSPMD=*/true,
+ OpenMPIRBuilder::ReductionGenCBKind::Clang, omp::NVPTXGridValues));
+ Builder.restoreIP(AfterParallelReductionIP);
+
Builder.CreateRetVoid();
- SmallVector<CallInst *> Calls;
- findCalls(F, RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait,
- OMPBuilder, Calls);
- ASSERT_EQ(Calls.size(), 1u);
- ASSERT_TRUE(Calls.front()->getDebugLoc());
- EXPECT_EQ(Calls.front()->getDebugLoc()->getScope()->getSubprogram(),
- F->getSubprogram());
+ CallInst *Calls[] = {
+ findSingleCall(F, RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait,
+ OMPBuilder),
+ findSingleCall(
+ F, RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2,
+ OMPBuilder)};
+ for (CallInst *Call : Calls) {
+ ASSERT_TRUE(Call->getDebugLoc());
+ EXPECT_EQ(Call->getDebugLoc()->getScope()->getSubprogram(),
+ F->getSubprogram());
+ }
EXPECT_FALSE(verifyModule(*M));
}
More information about the llvm-commits
mailing list