diff options
author | Abid Qadeer <haqadeer@amd.com> | 2025-08-29 16:56:26 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-29 16:56:26 +0100 |
commit | 4159fd819a89cb18e03a91576372ae257ee5fbc7 (patch) | |
tree | 0fc1e8d9846077f427c4575889fe4fba6eda87d5 /llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp | |
parent | 260ee975fcb43621c1979848dc02ebad7bece350 (diff) | |
download | llvm-4159fd819a89cb18e03a91576372ae257ee5fbc7.zip llvm-4159fd819a89cb18e03a91576372ae257ee5fbc7.tar.gz llvm-4159fd819a89cb18e03a91576372ae257ee5fbc7.tar.bz2 |
[OMPIRBuilder] Avoid crash in BasicBlock::splice. (#154987)
Calling `BasicBlock::splice` in `spliceBB` when both `Old` and `New` are
empty is a `nop` currently but it can cause a crash once debug records
are used instead of debug intrinsics. This PR makes the call conditional
on at least one of `Old` or `New` being non-empty.
Consider the following mlir:
```
omp.target map_entries() {
llvm.intr.dbg.declare ...
llvm.intr.dbg.declare ...
omp.teams ...
...
}
```
Current code would translate llvm.intr Ops to llvm intrinsics. Old is
the BasicBlock where they were get inserted and it will have 2 llvm
debug intrinsics by the time the implementation of `omp.teams` starts.
This implementation creates many BasicBlocks by calling `splitBB`. The
`New` is the just created BasicBlock which is empty.
In the new scheme (using debug records), there will be no instruction in
the `Old` BB after llvm.intr Ops get translated but just 2 trailing
debug records. So both `Old` and `New` are empty. When control reaches
`BasicBlock::splice`, it calls `spliceDebugInfoEmptyBlock`. This
function expects that in this case (`Src` is empty but has trailing
debug records), the `ToIt` is valid and it can call `adoptDbgRecords` on
it. This assumption is not true in this case as `New` is empty and
`ToIt` is pointing to end(). The fix is to only call
`BasicBlock::splice` when at least of `Old` or `New` is not empty.
Diffstat (limited to 'llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp')
-rw-r--r-- | llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp index b7a060b..c13570d 100644 --- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -7852,4 +7852,28 @@ TEST_F(OpenMPIRBuilderTest, splitBB) { EXPECT_TRUE(DL == AllocaBB->getTerminator()->getStableDebugLoc()); } +TEST_F(OpenMPIRBuilderTest, spliceBBWithEmptyBB) { + OpenMPIRBuilder OMPBuilder(*M); + OMPBuilder.Config.IsTargetDevice = false; + OMPBuilder.initialize(); + F->setName("func"); + IRBuilder<> Builder(BB); + + // Test calling spliceBB with an empty Block (but having trailing debug + // records). + DIBuilder DIB(*M); + DISubprogram *SP = F->getSubprogram(); + DIType *VoidPtrTy = + DIB.createQualifiedType(dwarf::DW_TAG_pointer_type, nullptr); + DILocalVariable *Var = DIB.createParameterVariable( + SP, "test", /*ArgNo*/ 1, SP->getFile(), /*LineNo=*/0, VoidPtrTy); + DIB.insertDeclare(F->getArg(0), Var, DIB.createExpression(), DL, + Builder.GetInsertPoint()); + BasicBlock *New = BasicBlock::Create(Ctx, "", F); + spliceBB(Builder.saveIP(), New, true, DL); + Instruction *Terminator = BB->getTerminator(); + EXPECT_NE(Terminator, nullptr); + EXPECT_FALSE(Terminator->getDbgRecordRange().empty()); +} + } // namespace |