[clang] [llvm] [mlir] [IR] Require well-formed IR for BasicBlock::getTerminator (PR #189416)

Alexis Engelke via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 08:51:16 PDT 2026


https://github.com/aengelke created https://github.com/llvm/llvm-project/pull/189416

BasicBlock::getTerminator() is frequently called on valid IR, yet the
function has to check that the last instruction is in fact a terminator,
even in release builds. This check can only be optimized away when the
instruction is dereferenced.

Therefore, introduce the functions hasTerminator() and
getTerminatorOrNull() as replacement and require (assert) that
getTerminator() always returns a valid terminator. As a side effect,
this forces explicit expression of intent at call sites when unfinished
basic blocks should be supported.


>From 9248202dcbb5ed61f4c8a7da9ade3827784897fa Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Mon, 30 Mar 2026 15:50:32 +0000
Subject: [PATCH] [spr] initial version

Created using spr 1.3.8-wip
---
 clang/lib/CodeGen/CGCleanup.cpp               |  3 +-
 clang/lib/CodeGen/CGException.cpp             |  2 +-
 clang/lib/CodeGen/CGStmt.cpp                  |  4 +-
 clang/lib/CodeGen/CodeGenFunction.cpp         |  2 +-
 clang/lib/CodeGen/CodeGenFunction.h           |  2 +-
 llvm/include/llvm/IR/BasicBlock.h             | 20 +++++++--
 llvm/lib/Analysis/ValueTracking.cpp           |  2 +-
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 41 +++++++++----------
 llvm/lib/FuzzMutate/RandomIRBuilder.cpp       |  6 +--
 llvm/lib/IR/BasicBlock.cpp                    |  4 +-
 llvm/lib/IR/DIBuilder.cpp                     |  2 +-
 llvm/lib/Transforms/Scalar/LICM.cpp           |  6 +--
 .../Transforms/Scalar/SimpleLoopUnswitch.cpp  |  2 +-
 llvm/lib/Transforms/Scalar/StructurizeCFG.cpp |  2 +-
 .../lib/Transforms/Utils/AMDGPUEmitPrintf.cpp |  2 +-
 llvm/lib/Transforms/Utils/Local.cpp           |  8 ++--
 llvm/unittests/IR/CFGBuilder.cpp              |  2 +-
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      |  2 +-
 18 files changed, 61 insertions(+), 51 deletions(-)

diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 3d242bec73126..9adc928c11585 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -367,7 +367,6 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
   // If it's a branch, turn it into a switch whose default
   // destination is its original target.
   llvm::Instruction *Term = Block->getTerminator();
-  assert(Term && "can't transition block without terminator");
 
   if (llvm::UncondBrInst *Br = dyn_cast<llvm::UncondBrInst>(Term)) {
     auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(),
@@ -697,7 +696,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
   // rest of IR gen doesn't need to worry about this; it only happens
   // during the execution of PopCleanupBlocks().
   bool HasPrebranchedFallthrough =
-    (FallthroughSource && FallthroughSource->getTerminator());
+      (FallthroughSource && FallthroughSource->hasTerminator());
 
   // If this is a normal cleanup, then having a prebranched
   // fallthrough implies that the fallthrough source unconditionally
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 7559727721496..9d1fe3654573c 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1325,7 +1325,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
     // we follow the false destination for each of the cond branches to reach
     // the rethrow block.
     llvm::BasicBlock *RethrowBlock = WasmCatchStartBlock;
-    while (llvm::Instruction *TI = RethrowBlock->getTerminator())
+    while (llvm::Instruction *TI = RethrowBlock->getTerminatorOrNull())
       RethrowBlock = cast<llvm::CondBrInst>(TI)->getSuccessor(1);
     assert(RethrowBlock != WasmCatchStartBlock && RethrowBlock->empty());
     Builder.SetInsertPoint(RethrowBlock);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index a923002bec9b6..a75d3dc64c6b4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -663,7 +663,7 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
   // terminator, don't emit it.
   llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
 
-  if (!CurBB || CurBB->getTerminator()) {
+  if (!CurBB || CurBB->hasTerminator()) {
     // If there is no insert point or the previous block is already
     // terminated, don't touch it.
   } else {
@@ -859,7 +859,7 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
   cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
 
   EmitBranch(IndGotoBB);
-  if (CurBB && CurBB->getTerminator())
+  if (CurBB && CurBB->hasTerminator())
     addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr);
 }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a64cec801a173..77c6866bbefa6 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -309,7 +309,7 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
   llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
 
   if (CurBB) {
-    assert(!CurBB->getTerminator() && "Unexpected terminated block.");
+    assert(!CurBB->hasTerminator() && "Unexpected terminated block.");
 
     // We have a valid insert point, reuse it if it is empty or there are no
     // explicit jumps to the return block.
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 0ff93d2ce7363..50ba46c04c81b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2012,7 +2012,7 @@ class CodeGenFunction : public CodeGenTypeCache {
                                 llvm::BasicBlock &FiniBB, llvm::Function *Fn,
                                 ArrayRef<llvm::Value *> Args) {
       llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
-      if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
+      if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminatorOrNull())
         CodeGenIPBBTI->eraseFromParent();
 
       CGF.Builder.SetInsertPoint(CodeGenIPBB);
diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
index 6ac5c0b381e6d..1f08dcc6114c2 100644
--- a/llvm/include/llvm/IR/BasicBlock.h
+++ b/llvm/include/llvm/IR/BasicBlock.h
@@ -228,11 +228,14 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
   /// Requires the basic block to have a parent module.
   LLVM_ABI const DataLayout &getDataLayout() const;
 
-  /// Returns the terminator instruction if the block is well formed or
-  /// null if the block is not well formed.
+  /// Returns whether the block has a terminator.
+  bool hasTerminator() const LLVM_READONLY {
+    return !InstList.empty() && InstList.back().isTerminator();
+  }
+
+  /// Returns the terminator instruction; assumes that the block is well-formed.
   const Instruction *getTerminator() const LLVM_READONLY {
-    if (InstList.empty() || !InstList.back().isTerminator())
-      return nullptr;
+    assert(hasTerminator() && "cannot get terminator of non-well-formed block");
     return &InstList.back();
   }
   Instruction *getTerminator() {
@@ -240,6 +243,15 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
         static_cast<const BasicBlock *>(this)->getTerminator());
   }
 
+  /// Returns the terminator instruction if the block is well formed or
+  /// null if the block is not well formed.
+  const Instruction *getTerminatorOrNull() const LLVM_READONLY {
+    return hasTerminator() ? getTerminator() : nullptr;
+  }
+  Instruction *getTerminatorOrNull() {
+    return hasTerminator() ? getTerminator() : nullptr;
+  }
+
   /// Returns the call instruction calling \@llvm.experimental.deoptimize
   /// prior to the terminating return instruction of this basic block, if such
   /// a call is present.  Otherwise, returns null.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 3528cc963e434..daef68790f252 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7895,7 +7895,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(
   // if what we are checking for includes undef and the value is not an integer.
   if (!includesUndef(Kind) || V->getType()->isIntegerTy())
     while (Dominator) {
-      auto *TI = Dominator->getBlock()->getTerminator();
+      auto *TI = Dominator->getBlock()->getTerminatorOrNull();
 
       Value *Cond = nullptr;
       if (auto BI = dyn_cast_or_null<CondBrInst>(TI)) {
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 2bd054501506a..ae8f261ff98b2 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -301,7 +301,7 @@ computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks,
 /// * \p Source is a degenerate block (no terminator because the BB is
 ///             the current head of the IR construction).
 static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL) {
-  if (Instruction *Term = Source->getTerminator()) {
+  if (Instruction *Term = Source->getTerminatorOrNull()) {
     auto *Br = cast<UncondBrInst>(Term);
     BasicBlock *Succ = Br->getSuccessor();
     Succ->removePredecessor(Source, /*KeepOneInputPHIs=*/true);
@@ -884,9 +884,8 @@ void OpenMPIRBuilder::finalize(Function *Fn) {
 
         if (I.isTerminator()) {
           // Absorb any debug value that terminator may have
-          if (OI.EntryBB->getTerminator())
-            OI.EntryBB->getTerminator()->adoptDbgRecords(
-                &ArtificialEntry, I.getIterator(), false);
+          if (Instruction *TI = OI.EntryBB->getTerminatorOrNull())
+            TI->adoptDbgRecords(&ArtificialEntry, I.getIterator(), false);
           continue;
         }
 
@@ -4928,7 +4927,7 @@ Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
     return AfterIP.takeError();
   Builder.restoreIP(*AfterIP);
   BasicBlock *InputBB = Builder.GetInsertBlock();
-  if (InputBB->getTerminator())
+  if (InputBB->hasTerminator())
     Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
   AfterIP = createBarrier(Builder.saveIP(), llvm::omp::OMPD_barrier);
   if (!AfterIP)
@@ -4963,8 +4962,8 @@ Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
   // called for variables which have destructors/finalizers.
   auto FiniCB = [&](InsertPointTy CodeGenIP) { return llvm::Error::success(); };
 
-  if (ScanRedInfo->OMPScanFinish->getTerminator())
-    Builder.SetInsertPoint(ScanRedInfo->OMPScanFinish->getTerminator());
+  if (Instruction *TI = ScanRedInfo->OMPScanFinish->getTerminatorOrNull())
+    Builder.SetInsertPoint(TI);
   else
     Builder.SetInsertPoint(ScanRedInfo->OMPScanFinish);
 
@@ -4976,7 +4975,7 @@ Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
     return AfterIP.takeError();
   Builder.restoreIP(*AfterIP);
   BasicBlock *InputBB = Builder.GetInsertBlock();
-  if (InputBB->getTerminator())
+  if (InputBB->hasTerminator())
     Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
   AfterIP = createBarrier(Builder.saveIP(), llvm::omp::OMPD_barrier);
   if (!AfterIP)
@@ -5605,7 +5604,7 @@ OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
   // FIXME: Don't run analyses on incomplete/invalid IR.
   SmallVector<Instruction *> UIs;
   for (BasicBlock &BB : *F)
-    if (!BB.getTerminator())
+    if (!BB.hasTerminator())
       UIs.push_back(new UnreachableInst(F->getContext(), &BB));
   FunctionAnalysisManager FAM;
   FAM.registerPass([]() { return DominatorTreeAnalysis(); });
@@ -6902,7 +6901,7 @@ void OpenMPIRBuilder::applySimd(CanonicalLoopInfo *CanonicalLoop,
   // FIXME: Don't run analyses on incomplete/invalid IR.
   SmallVector<Instruction *> UIs;
   for (BasicBlock &BB : *F)
-    if (!BB.getTerminator())
+    if (!BB.hasTerminator())
       UIs.push_back(new UnreachableInst(F->getContext(), &BB));
 
   // TODO: We should not rely on pass manager. Currently we use pass manager
@@ -7041,7 +7040,7 @@ static int32_t computeHeuristicUnrollFactor(CanonicalLoopInfo *CLI) {
   // FIXME: Don't run analyses on incomplete/invalid IR.
   SmallVector<Instruction *> UIs;
   for (BasicBlock &BB : *F)
-    if (!BB.getTerminator())
+    if (!BB.hasTerminator())
       UIs.push_back(new UnreachableInst(F->getContext(), &BB));
 
   FunctionAnalysisManager FAM;
@@ -7451,7 +7450,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::EmitOMPInlinedRegion(
   // Create inlined region's entry and body blocks, in preparation
   // for conditional creation
   BasicBlock *EntryBB = Builder.GetInsertBlock();
-  Instruction *SplitPos = EntryBB->getTerminator();
+  Instruction *SplitPos = EntryBB->getTerminatorOrNull();
   if (!isa_and_nonnull<UncondBrInst, CondBrInst>(SplitPos))
     SplitPos = new UnreachableInst(Builder.getContext(), EntryBB);
   BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end");
@@ -7581,7 +7580,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createCopyinClauseBlocks(
 
   // If entry block is terminated, split to preserve the branch to following
   // basic block (i.e. OMP.Entry.Next), otherwise, leave everything as is.
-  if (isa_and_nonnull<CondBrInst>(OMP_Entry->getTerminator())) {
+  if (isa_and_nonnull<CondBrInst>(OMP_Entry->getTerminatorOrNull())) {
     CopyEnd = OMP_Entry->splitBasicBlock(OMP_Entry->getTerminator(),
                                          "copyin.not.master.end");
     OMP_Entry->getTerminator()->eraseFromParent();
@@ -10170,7 +10169,7 @@ Error OpenMPIRBuilder::emitOffloadingArrays(
 void OpenMPIRBuilder::emitBranch(BasicBlock *Target) {
   BasicBlock *CurBB = Builder.GetInsertBlock();
 
-  if (!CurBB || CurBB->getTerminator()) {
+  if (!CurBB || CurBB->hasTerminator()) {
     // If there is no insert point or the previous block is already
     // terminated, don't touch it.
   } else {
@@ -10525,7 +10524,7 @@ Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
         OldVal->getAlign(), true /* UseLibcall */, AllocaIP, X);
     auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
     BasicBlock *CurBB = Builder.GetInsertBlock();
-    Instruction *CurBBTI = CurBB->getTerminator();
+    Instruction *CurBBTI = CurBB->getTerminatorOrNull();
     CurBBTI = CurBBTI ? CurBBTI : Builder.CreateUnreachable();
     BasicBlock *ExitBB =
         CurBB->splitBasicBlock(CurBBTI, X->getName() + ".atomic.exit");
@@ -10574,7 +10573,7 @@ Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
     // |     \---/
     // ExitBB
     BasicBlock *CurBB = Builder.GetInsertBlock();
-    Instruction *CurBBTI = CurBB->getTerminator();
+    Instruction *CurBBTI = CurBB->getTerminatorOrNull();
     CurBBTI = CurBBTI ? CurBBTI : Builder.CreateUnreachable();
     BasicBlock *ExitBB =
         CurBB->splitBasicBlock(CurBBTI, X->getName() + ".atomic.exit");
@@ -10733,7 +10732,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
           //
           // where ContBB only contains the store of old value to 'v'.
           BasicBlock *CurBB = Builder.GetInsertBlock();
-          Instruction *CurBBTI = CurBB->getTerminator();
+          Instruction *CurBBTI = CurBB->getTerminatorOrNull();
           CurBBTI = CurBBTI ? CurBBTI : Builder.CreateUnreachable();
           BasicBlock *ExitBB = CurBB->splitBasicBlock(
               CurBBTI, X.Var->getName() + ".atomic.exit");
@@ -11609,7 +11608,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createIteratorLoop(
 
   InsertPointTy SplitIP = Builder.saveIP();
   if (SplitIP.getPoint() == CurBB->end())
-    if (Instruction *Terminator = CurBB->getTerminator())
+    if (Instruction *Terminator = CurBB->getTerminatorOrNull())
       SplitIP = InsertPointTy(CurBB, Terminator->getIterator());
 
   BasicBlock *ContBB =
@@ -11625,7 +11624,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createIteratorLoop(
   redirectTo(CurBB, CLI->getPreheader(), Builder.getCurrentDebugLocation());
 
   // Remove the unconditional branch inserted by createLoopSkeleton in the body
-  if (Instruction *T = CLI->getBody()->getTerminator())
+  if (Instruction *T = CLI->getBody()->getTerminatorOrNull())
     T->eraseFromParent();
 
   InsertPointTy BodyIP = CLI->getBodyIP();
@@ -11633,7 +11632,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createIteratorLoop(
     return Err;
 
   // Body must either fallthrough to the latch or branch directly to it.
-  if (Instruction *BodyTerminator = CLI->getBody()->getTerminator()) {
+  if (Instruction *BodyTerminator = CLI->getBody()->getTerminatorOrNull()) {
     auto *BodyBr = dyn_cast<UncondBrInst>(BodyTerminator);
     if (!BodyBr || BodyBr->getSuccessor() != CLI->getLatch()) {
       return make_error<StringError>(
@@ -11649,7 +11648,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createIteratorLoop(
 
   // Link After -> ContBB
   Builder.SetInsertPoint(CLI->getAfter(), CLI->getAfter()->begin());
-  if (!CLI->getAfter()->getTerminator())
+  if (!CLI->getAfter()->hasTerminator())
     Builder.CreateBr(ContBB);
 
   return InsertPointTy{ContBB, ContBB->begin()};
diff --git a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
index 4d1d6d6cc0a79..bcfe58c72d09b 100644
--- a/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
+++ b/llvm/lib/FuzzMutate/RandomIRBuilder.cpp
@@ -25,7 +25,7 @@ static DominatorTree getDomTree(Function &F) {
   // Dominator tree construction requires that all blocks have terminators.
   SmallVector<Instruction *> AddedInsts;
   for (BasicBlock &BB : F)
-    if (!BB.getTerminator())
+    if (!BB.hasTerminator())
       AddedInsts.push_back(new UnreachableInst(F.getContext(), &BB));
   DominatorTree DT(F);
   for (Instruction *I : AddedInsts)
@@ -219,7 +219,7 @@ Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
       Module *M = BB.getParent()->getParent();
       auto [GV, DidCreate] = findOrCreateGlobalVariable(M, Srcs, Pred);
       Type *Ty = GV->getValueType();
-      InsertPosition IP = BB.getTerminator()
+      InsertPosition IP = BB.hasTerminator()
                               ? InsertPosition(BB.getFirstInsertionPt())
                               : InsertPosition(&BB);
       // Build a legal load and track new instructions in case a rollback is
@@ -292,7 +292,7 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
     Type *Ty = newSrc->getType();
     Function *F = BB.getParent();
     AllocaInst *Alloca = createStackMemory(F, Ty, newSrc);
-    if (BB.getTerminator()) {
+    if (BB.hasTerminator()) {
       newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L",
                             BB.getTerminator()->getIterator());
     } else {
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index 0305b8e258109..da97b26f7cec5 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -614,7 +614,7 @@ void BasicBlock::replacePhiUsesWith(BasicBlock *Old, BasicBlock *New) {
 
 void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *Old,
                                               BasicBlock *New) {
-  Instruction *TI = getTerminator();
+  Instruction *TI = getTerminatorOrNull();
   if (!TI)
     // Cope with being called on a BasicBlock that doesn't have a terminator
     // yet. Clang's CodeGenFunction::EmitReturnBlock() likes to do this.
@@ -676,7 +676,7 @@ void BasicBlock::flushTerminatorDbgRecords() {
   // DbgRecords in front of the terminator.
 
   // If there's no terminator, there's nothing to do.
-  Instruction *Term = getTerminator();
+  Instruction *Term = getTerminatorOrNull();
   if (!Term)
     return;
 
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 54e80806245e0..9cb5b63d885d4 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -1126,7 +1126,7 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
                                     BasicBlock *InsertAtEnd) {
   // If this block already has a terminator then insert this intrinsic before
   // the terminator. Otherwise, put it at the end of the block.
-  Instruction *InsertBefore = InsertAtEnd->getTerminator();
+  Instruction *InsertBefore = InsertAtEnd->getTerminatorOrNull();
   return insertDeclare(Storage, VarInfo, Expr, DL,
                        InsertBefore ? InsertBefore->getIterator()
                                     : InsertAtEnd->end());
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 859bc4cf83898..3b9669179c08a 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -823,7 +823,7 @@ class ControlFlowHoister {
     BasicBlock *HoistCommonSucc = CreateHoistedBlock(CommonSucc);
 
     // Link up these blocks with branches.
-    if (!HoistCommonSucc->getTerminator()) {
+    if (!HoistCommonSucc->hasTerminator()) {
       // The new common successor we've generated will branch to whatever that
       // hoist target branched to.
       BasicBlock *TargetSucc = HoistTarget->getSingleSuccessor();
@@ -831,11 +831,11 @@ class ControlFlowHoister {
       HoistCommonSucc->moveBefore(TargetSucc);
       UncondBrInst::Create(TargetSucc, HoistCommonSucc);
     }
-    if (!HoistTrueDest->getTerminator()) {
+    if (!HoistTrueDest->hasTerminator()) {
       HoistTrueDest->moveBefore(HoistCommonSucc);
       UncondBrInst::Create(HoistCommonSucc, HoistTrueDest);
     }
-    if (!HoistFalseDest->getTerminator()) {
+    if (!HoistFalseDest->hasTerminator()) {
       HoistFalseDest->moveBefore(HoistCommonSucc);
       UncondBrInst::Create(HoistCommonSucc, HoistFalseDest);
     }
diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
index 40a3a23814700..a7aa0e956b91d 100644
--- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
@@ -709,7 +709,7 @@ static bool unswitchTrivialBranch(Loop &L, CondBrInst &BI, DominatorTree &DT,
              " condition!");
     buildPartialUnswitchConditionalBranch(
         *OldPH, Invariants, ExitDirection, *UnswitchedBB, *NewPH,
-        FreezeLoopUnswitchCond, OldPH->getTerminator(), nullptr, DT, BI);
+        FreezeLoopUnswitchCond, OldPH->getTerminatorOrNull(), nullptr, DT, BI);
   }
 
   // Update the dominator tree with the added edge.
diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
index 136cb965f94c5..04ece92b74375 100644
--- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
+++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
@@ -1024,7 +1024,7 @@ void StructurizeCFG::simplifyAffectedPhis() {
 
 /// Remove phi values from all successors and then remove the terminator.
 DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
-  Instruction *Term = BB->getTerminator();
+  Instruction *Term = BB->getTerminatorOrNull();
   if (!Term)
     return DebugLoc();
 
diff --git a/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp b/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp
index 04a2cda3cf44a..22a503e61a288 100644
--- a/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp
+++ b/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp
@@ -100,7 +100,7 @@ static Value *getStrlenWithNull(IRBuilder<> &Builder, Value *Str) {
   //  Strictly speaking, the zero does not matter since
   // __ockl_printf_append_string_n ignores the length if the pointer is null.
   BasicBlock *Join = nullptr;
-  if (Prev->getTerminator()) {
+  if (Prev->hasTerminator()) {
     Join = Prev->splitBasicBlock(Builder.GetInsertPoint(),
                                  "strlen.join");
     Prev->getTerminator()->eraseFromParent();
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 84c0989a7fe07..75af57ffa2057 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1277,10 +1277,10 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
   // |       v
   // |    for.body <---- (md2)
   // |_______|  |______|
-  if (Instruction *TI = BB->getTerminator())
+  if (Instruction *TI = BB->getTerminatorOrNull())
     if (TI->hasNonDebugLocLoopMetadata())
       for (BasicBlock *Pred : predecessors(BB))
-        if (Instruction *PredTI = Pred->getTerminator())
+        if (Instruction *PredTI = Pred->getTerminatorOrNull())
           if (PredTI->hasNonDebugLocLoopMetadata())
             return false;
 
@@ -1348,7 +1348,7 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
   // If the unconditional branch we replaced contains non-debug llvm.loop
   // metadata, we add the metadata to the branch instructions in the
   // predecessors.
-  if (Instruction *TI = BB->getTerminator())
+  if (Instruction *TI = BB->getTerminatorOrNull())
     if (TI->hasNonDebugLocLoopMetadata()) {
       MDNode *LoopMD = TI->getMetadata(LLVMContext::MD_loop);
       for (BasicBlock *Pred : predecessors(BB))
@@ -1363,7 +1363,7 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
       Succ->takeName(BB);
 
     // Clear the successor list of BB to match updates applying to DTU later.
-    if (BB->getTerminator())
+    if (BB->hasTerminator())
       BB->back().eraseFromParent();
 
     new UnreachableInst(BB->getContext(), BB);
diff --git a/llvm/unittests/IR/CFGBuilder.cpp b/llvm/unittests/IR/CFGBuilder.cpp
index 7dc1e5162a81e..896e354686963 100644
--- a/llvm/unittests/IR/CFGBuilder.cpp
+++ b/llvm/unittests/IR/CFGBuilder.cpp
@@ -43,7 +43,7 @@ static void ConnectBlocks(BasicBlock *From, BasicBlock *To) {
 
   if (isa<UnreachableInst>(From->getTerminator()))
     From->getTerminator()->eraseFromParent();
-  if (!From->getTerminator()) {
+  if (!From->hasTerminator()) {
     IRBuilder<> IRB(From);
     IRB.CreateSwitch(ConstantInt::get(IntTy, 0), To);
     return;
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 42fdadaba0da1..a665ee76770fb 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -1220,7 +1220,7 @@ setInsertPointForPossiblyEmptyBlock(llvm::IRBuilderBase &builder,
   if (block == nullptr)
     block = builder.GetInsertBlock();
 
-  if (block->empty() || block->getTerminator() == nullptr)
+  if (!block->hasTerminator())
     builder.SetInsertPoint(block);
   else
     builder.SetInsertPoint(block->getTerminator());



More information about the llvm-commits mailing list