[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.");
}