[MLIR] Merge terminator and uses into BasicBlock operations list handling.

PiperOrigin-RevId: 221700132
diff --git a/include/mlir/IR/BasicBlock.h b/include/mlir/IR/BasicBlock.h
index e05dc59..73d0b7f 100644
--- a/include/mlir/IR/BasicBlock.h
+++ b/include/mlir/IR/BasicBlock.h
@@ -115,10 +115,9 @@
   // Terminator management
   //===--------------------------------------------------------------------===//
 
-  /// Change the terminator of this block to the specified instruction.
-  void setTerminator(OperationInst *inst);
-
-  OperationInst *getTerminator() const { return terminator; }
+  /// Get the terminator instruction of this block, or null if the block is
+  /// malformed.
+  OperationInst *getTerminator() const;
 
   //===--------------------------------------------------------------------===//
   // Predecessors and successors.
@@ -216,9 +215,6 @@
   /// This is the list of arguments to the block.
   std::vector<BBArgument *> arguments;
 
-  /// This is the owning reference to the terminator of the block.
-  OperationInst *terminator = nullptr;
-
   BasicBlock(const BasicBlock&) = delete;
   void operator=(const BasicBlock&) = delete;
 
diff --git a/lib/Analysis/Verifier.cpp b/lib/Analysis/Verifier.cpp
index 5486350..3662692 100644
--- a/lib/Analysis/Verifier.cpp
+++ b/lib/Analysis/Verifier.cpp
@@ -62,20 +62,10 @@
     return true;
   }
 
-  bool failure(const Twine &message, const Instruction &inst) {
-    inst.emitError(message);
-    return true;
-  }
-
   bool failure(const Twine &message, const BasicBlock &bb) {
     // Take the location information for the first instruction in the block.
     if (!bb.empty())
-      return failure(message, static_cast<const Instruction &>(bb.front()));
-
-    // If the code is properly formed, there will be a terminator.  Use its
-    // location.
-    if (auto *termInst = bb.getTerminator())
-      return (termInst->emitError(message), true);
+      return failure(message, bb.front());
 
     // Worst case, fall back to using the function's location.
     return failure(message, fn);
@@ -230,12 +220,6 @@
   if (!block.getTerminator())
     return failure("basic block with no terminator", block);
 
-  // TODO(riverriddle) Remove this when terminators are inside of the block
-  // operation list.
-  auto &term = *block.getTerminator();
-  if (verifyOperation(term) || verifyInstOperands(term))
-    return true;
-
   for (auto *arg : block.getArguments()) {
     if (arg->getOwner() != &block)
       return failure("basic block argument not owned by block", block);
diff --git a/lib/IR/AsmPrinter.cpp b/lib/IR/AsmPrinter.cpp
index 2040f81..9caedc5 100644
--- a/lib/IR/AsmPrinter.cpp
+++ b/lib/IR/AsmPrinter.cpp
@@ -1265,10 +1265,6 @@
     print(&inst);
     os << '\n';
   }
-
-  os << "  ";
-  print(block->getTerminator());
-  os << '\n';
 }
 
 void CFGFunctionPrinter::print(const Instruction *inst) {
diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp
index 0187a30..96d456b 100644
--- a/lib/IR/BasicBlock.cpp
+++ b/lib/IR/BasicBlock.cpp
@@ -24,8 +24,6 @@
 BasicBlock::BasicBlock() {}
 
 BasicBlock::~BasicBlock() {
-  if (terminator)
-    terminator->erase();
   for (BBArgument *arg : arguments)
     delete arg;
   arguments.clear();
@@ -56,16 +54,14 @@
 // Terminator management
 //===----------------------------------------------------------------------===//
 
-void BasicBlock::setTerminator(OperationInst *inst) {
-  assert((!inst || !inst->block) && "terminator already inserted into a block");
-  // If we already had a terminator, abandon it.
-  if (terminator)
-    terminator->block = nullptr;
+OperationInst *BasicBlock::getTerminator() const {
+  if (empty())
+    return nullptr;
 
-  // Reset our terminator to the new instruction.
-  terminator = inst;
-  if (inst)
-    inst->block = this;
+  // Check if the last instruction is a terminator.
+  auto &backInst = operations.back();
+  return backInst.isTerminator() ? const_cast<OperationInst *>(&backInst)
+                                 : nullptr;
 }
 
 /// Return true if this block has no predecessors.
@@ -158,21 +154,16 @@
   // one in the containing function.
   auto newBB = new BasicBlock();
   getFunction()->getBlocks().insert(++CFGFunction::iterator(this), newBB);
-
-  // Create an unconditional branch to the new block, and move our terminator
-  // to the new block.
   auto branchLoc =
       splitBefore == end() ? getTerminator()->getLoc() : splitBefore->getLoc();
-  // TODO(riverriddle) Remove this when terminators are a part of the operations
-  // list.
-  auto oldTerm = getTerminator();
-  setTerminator(nullptr);
-  newBB->setTerminator(oldTerm);
-  CFGFuncBuilder(this).create<BranchOp>(branchLoc, newBB);
 
   // Move all of the operations from the split point to the end of the function
   // into the new block.
   newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore,
                                 end());
+
+  // Create an unconditional branch to the new block, and move our terminator
+  // to the new block.
+  CFGFuncBuilder(this).create<BranchOp>(branchLoc, newBB);
   return newBB;
 }
diff --git a/lib/IR/Builders.cpp b/lib/IR/Builders.cpp
index 771756c..fe8371e 100644
--- a/lib/IR/Builders.cpp
+++ b/lib/IR/Builders.cpp
@@ -19,7 +19,6 @@
 #include "mlir/IR/AffineExpr.h"
 #include "mlir/IR/AffineMap.h"
 #include "mlir/IR/Attributes.h"
-#include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/IntegerSet.h"
 #include "mlir/IR/Location.h"
 #include "mlir/IR/Module.h"
@@ -278,15 +277,7 @@
   auto *op =
       OperationInst::create(state.location, state.name, operands, state.types,
                             state.attributes, state.successors, context);
-  // TODO(riverriddle) Remove this when the terminators are in basic block
-  // operation lists.
-  if (op->isTerminator()) {
-    // FIXME(b/118738403)
-    assert(!block->getTerminator() && "cannot insert the second terminator");
-    block->setTerminator(op);
-  } else {
-    block->getOperations().insert(insertPoint, op);
-  }
+  block->getOperations().insert(insertPoint, op);
   return op;
 }
 
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index 672df82..e7b3046 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -174,12 +174,9 @@
 CFGFunction::~CFGFunction() {
   // Instructions may have cyclic references, which need to be dropped before we
   // can start deleting them.
-  for (auto &bb : *this) {
+  for (auto &bb : *this)
     for (auto &inst : bb)
       inst.dropAllReferences();
-    if (bb.getTerminator())
-      bb.getTerminator()->dropAllReferences();
-  }
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 148a5ad..e20c827 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -323,14 +323,7 @@
 /// Unlink this instruction from its BasicBlock and delete it.
 void OperationInst::erase() {
   assert(getBlock() && "Instruction has no parent");
-  // TODO(riverriddle) Remove this when terminators are a part of the operations
-  // list.
-  if (isTerminator()) {
-    getBlock()->setTerminator(nullptr);
-    destroy();
-  } else {
-    getBlock()->getOperations().erase(this);
-  }
+  getBlock()->getOperations().erase(this);
 }
 
 /// Unlink this operation instruction from its current basic block and insert
@@ -338,12 +331,6 @@
 /// in the same function.
 void OperationInst::moveBefore(OperationInst *existingInst) {
   assert(existingInst && "Cannot move before a null instruction");
-  // TODO(riverriddle) Remove this when terminators are a part of the operations
-  // list.
-  if (existingInst->isTerminator()) {
-    return moveBefore(existingInst->getBlock(),
-                      existingInst->getBlock()->end());
-  }
   return moveBefore(existingInst->getBlock(), existingInst->getIterator());
 }
 
diff --git a/lib/IR/Operation.cpp b/lib/IR/Operation.cpp
index a5bd7df..cc64b15 100644
--- a/lib/IR/Operation.cpp
+++ b/lib/IR/Operation.cpp
@@ -542,10 +542,7 @@
   } else {
     const OperationInst *inst = cast<OperationInst>(op);
     const BasicBlock *block = inst->getBlock();
-    // TODO(riverriddle) Check the instruction at the back of the block when
-    // terminators are in the operations list.
-    // if (!block || &block->back() != inst)
-    if (!block || block->getTerminator() != inst)
+    if (!block || &block->back() != inst)
       return op->emitOpError(
           "must be the last instruction in the parent basic block.");
   }