Skip to content

Commit 4159fd8

Browse files
authored
[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.
1 parent 260ee97 commit 4159fd8

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,19 @@ void llvm::spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New,
307307

308308
// Move instructions to new block.
309309
BasicBlock *Old = IP.getBlock();
310-
New->splice(New->begin(), Old, IP.getPoint(), Old->end());
310+
// If the `Old` block is empty then there are no instructions to move. But in
311+
// the new debug scheme, it could have trailing debug records which will be
312+
// moved to `New` in `spliceDebugInfoEmptyBlock`. We dont want that for 2
313+
// reasons:
314+
// 1. If `New` is also empty, `BasicBlock::splice` crashes.
315+
// 2. Even if `New` is not empty, the rationale to move those records to `New`
316+
// (in `spliceDebugInfoEmptyBlock`) does not apply here. That function
317+
// assumes that `Old` is optimized out and is going away. This is not the case
318+
// here. The `Old` block is still being used e.g. a branch instruction is
319+
// added to it later in this function.
320+
// So we call `BasicBlock::splice` only when `Old` is not empty.
321+
if (!Old->empty())
322+
New->splice(New->begin(), Old, IP.getPoint(), Old->end());
311323

312324
if (CreateBranch) {
313325
auto *NewBr = BranchInst::Create(New, Old);

llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7852,4 +7852,28 @@ TEST_F(OpenMPIRBuilderTest, splitBB) {
78527852
EXPECT_TRUE(DL == AllocaBB->getTerminator()->getStableDebugLoc());
78537853
}
78547854

7855+
TEST_F(OpenMPIRBuilderTest, spliceBBWithEmptyBB) {
7856+
OpenMPIRBuilder OMPBuilder(*M);
7857+
OMPBuilder.Config.IsTargetDevice = false;
7858+
OMPBuilder.initialize();
7859+
F->setName("func");
7860+
IRBuilder<> Builder(BB);
7861+
7862+
// Test calling spliceBB with an empty Block (but having trailing debug
7863+
// records).
7864+
DIBuilder DIB(*M);
7865+
DISubprogram *SP = F->getSubprogram();
7866+
DIType *VoidPtrTy =
7867+
DIB.createQualifiedType(dwarf::DW_TAG_pointer_type, nullptr);
7868+
DILocalVariable *Var = DIB.createParameterVariable(
7869+
SP, "test", /*ArgNo*/ 1, SP->getFile(), /*LineNo=*/0, VoidPtrTy);
7870+
DIB.insertDeclare(F->getArg(0), Var, DIB.createExpression(), DL,
7871+
Builder.GetInsertPoint());
7872+
BasicBlock *New = BasicBlock::Create(Ctx, "", F);
7873+
spliceBB(Builder.saveIP(), New, true, DL);
7874+
Instruction *Terminator = BB->getTerminator();
7875+
EXPECT_NE(Terminator, nullptr);
7876+
EXPECT_FALSE(Terminator->getDbgRecordRange().empty());
7877+
}
7878+
78557879
} // namespace

0 commit comments

Comments
 (0)