Merge OperationInst functionality into Instruction.

We do some limited renaming here but define an alias for OperationInst so that a follow up cl can solely perform the large scale renaming.

PiperOrigin-RevId: 221726963
This commit is contained in:
River Riddle 2018-11-15 18:31:15 -08:00 committed by jpienaar
parent 711047c0cd
commit 8b6bc09f48
13 changed files with 254 additions and 397 deletions

View File

@ -78,7 +78,7 @@ public:
//===--------------------------------------------------------------------===//
/// This is the list of operations in the block.
using OperationListType = llvm::iplist<OperationInst>;
using OperationListType = llvm::iplist<Instruction>;
OperationListType &getOperations() { return operations; }
const OperationListType &getOperations() const { return operations; }
@ -98,16 +98,16 @@ public:
const_reverse_iterator rend() const { return operations.rend(); }
bool empty() const { return operations.empty(); }
void push_back(OperationInst *inst) { operations.push_back(inst); }
void push_front(OperationInst *inst) { operations.push_front(inst); }
void push_back(Instruction *inst) { operations.push_back(inst); }
void push_front(Instruction *inst) { operations.push_front(inst); }
OperationInst &back() { return operations.back(); }
const OperationInst &back() const {
Instruction &back() { return operations.back(); }
const Instruction &back() const {
return const_cast<BasicBlock *>(this)->back();
}
OperationInst &front() { return operations.front(); }
const OperationInst &front() const {
Instruction &front() { return operations.front(); }
const Instruction &front() const {
return const_cast<BasicBlock*>(this)->front();
}
@ -117,7 +117,7 @@ public:
/// Get the terminator instruction of this block, or null if the block is
/// malformed.
OperationInst *getTerminator() const;
Instruction *getTerminator() const;
//===--------------------------------------------------------------------===//
// Predecessors and successors.
@ -189,7 +189,7 @@ public:
///
/// This function invalidates the specified iterator.
BasicBlock *splitBasicBlock(iterator splitBefore);
BasicBlock *splitBasicBlock(OperationInst *splitBeforeInst) {
BasicBlock *splitBasicBlock(Instruction *splitBeforeInst) {
return splitBasicBlock(iterator(splitBeforeInst));
}
@ -202,7 +202,7 @@ public:
void printAsOperand(raw_ostream &os, bool printType = true);
/// getSublistAccess() - Returns pointer to member of operation list
static OperationListType BasicBlock::*getSublistAccess(OperationInst*) {
static OperationListType BasicBlock::*getSublistAccess(Instruction *) {
return &BasicBlock::operations;
}

View File

@ -169,7 +169,7 @@ public:
setInsertionPoint(block, insertPoint);
}
CFGFuncBuilder(OperationInst *insertBefore)
CFGFuncBuilder(Instruction *insertBefore)
: CFGFuncBuilder(insertBefore->getBlock(),
BasicBlock::iterator(insertBefore)) {}
@ -210,7 +210,7 @@ public:
}
/// Set the insertion point to the specified operation.
void setInsertionPoint(OperationInst *inst) {
void setInsertionPoint(Instruction *inst) {
setInsertionPoint(inst->getBlock(), BasicBlock::iterator(inst));
}
@ -219,7 +219,7 @@ public:
setInsertionPoint(block, block->end());
}
void insert(OperationInst *opInst) {
void insert(Instruction *opInst) {
block->getOperations().insert(insertPoint, opInst);
}
@ -230,7 +230,7 @@ public:
BasicBlock *createBlock(BasicBlock *insertBefore = nullptr);
/// Create an operation given the fields represented as an OperationState.
OperationInst *createOperation(const OperationState &state);
Instruction *createOperation(const OperationState &state);
/// Create operation of specific op type at the current insertion point
/// without verifying to see if it is valid.
@ -253,7 +253,7 @@ public:
OpTy::build(this, &state, args...);
auto *inst = createOperation(state);
// If the OperationInst we produce is valid, return it.
// If the Instruction we produce is valid, return it.
if (!OpTy::verifyInvariants(inst)) {
auto result = inst->dyn_cast<OpTy>();
assert(result && "Builder didn't return the right type");
@ -266,7 +266,7 @@ public:
return OpPointer<OpTy>();
}
OperationInst *cloneOperation(const OperationInst &srcOpInst) {
Instruction *cloneOperation(const Instruction &srcOpInst) {
auto *op = srcOpInst.clone();
insert(op);
return op;
@ -437,8 +437,8 @@ public:
: Builder(mlFuncBuilder.getContext()), builder(mlFuncBuilder),
kind(Function::Kind::MLFunc) {}
FuncBuilder(Operation *op) : Builder(op->getContext()) {
if (isa<OperationInst>(op)) {
builder = builderUnion(cast<OperationInst>(op));
if (auto *inst = dyn_cast<Instruction>(op)) {
builder = builderUnion(inst);
kind = Function::Kind::CFGFunc;
} else {
builder = builderUnion(cast<OperationStmt>(op));
@ -473,11 +473,11 @@ public:
}
/// Set the insertion point to the specified operation. This requires that the
/// input operation is a OperationInst when building a CFG function and a
/// input operation is a Instruction when building a CFG function and a
/// OperationStmt when building a ML function.
void setInsertionPoint(Operation *op) {
if (kind == Function::Kind::CFGFunc)
builder.cfg.setInsertionPoint(cast<OperationInst>(op));
builder.cfg.setInsertionPoint(cast<Instruction>(op));
else
builder.ml.setInsertionPoint(cast<OperationStmt>(op));
}
@ -487,7 +487,7 @@ private:
union builderUnion {
builderUnion(CFGFuncBuilder cfg) : cfg(cfg) {}
builderUnion(MLFuncBuilder ml) : ml(ml) {}
builderUnion(OperationInst *op) : cfg(op) {}
builderUnion(Instruction *op) : cfg(op) {}
builderUnion(OperationStmt *op) : ml(op) {}
// Default initializer to allow deferring initialization of member.
builderUnion() {}

View File

@ -99,15 +99,15 @@ private:
/// Instruction results are CFG Values.
class InstResult : public CFGValue {
public:
InstResult(Type type, OperationInst *owner)
InstResult(Type type, Instruction *owner)
: CFGValue(CFGValueKind::InstResult, type), owner(owner) {}
static bool classof(const SSAValue *value) {
return value->getKind() == SSAValueKind::InstResult;
}
OperationInst *getOwner() { return owner; }
const OperationInst *getOwner() const { return owner; }
Instruction *getOwner() { return owner; }
const Instruction *getOwner() const { return owner; }
/// Return the number of this result.
unsigned getResultNumber() const;
@ -116,7 +116,7 @@ private:
/// The owner of this operand.
/// TODO: can encode this more efficiently to avoid the space hit of this
/// through bitpacking shenanigans.
OperationInst *const owner;
Instruction *const owner;
};
} // namespace mlir

View File

@ -32,24 +32,22 @@
namespace mlir {
class BasicBlock;
class CFGFunction;
class OperationInst;
class TerminatorInst;
} // end namespace mlir
//===----------------------------------------------------------------------===//
// ilist_traits for OperationInst
// ilist_traits for Instruction
//===----------------------------------------------------------------------===//
namespace llvm {
template <> struct ilist_traits<::mlir::OperationInst> {
using OperationInst = ::mlir::OperationInst;
using instr_iterator = simple_ilist<OperationInst>::iterator;
template <> struct ilist_traits<::mlir::Instruction> {
using Instruction = ::mlir::Instruction;
using instr_iterator = simple_ilist<Instruction>::iterator;
static void deleteNode(OperationInst *inst);
void addNodeToList(OperationInst *inst);
void removeNodeFromList(OperationInst *inst);
void transferNodesFromList(ilist_traits<OperationInst> &otherList,
static void deleteNode(Instruction *inst);
void addNodeToList(Instruction *inst);
void removeNodeFromList(Instruction *inst);
void transferNodesFromList(ilist_traits<Instruction> &otherList,
instr_iterator first, instr_iterator last);
private:
@ -63,44 +61,35 @@ namespace mlir {
/// The operand of a Terminator contains a BasicBlock.
using BasicBlockOperand = IROperandImpl<BasicBlock, Instruction>;
/// Instruction is the root of the operation and terminator instructions in the
/// hierarchy.
class Instruction : public IROperandOwner {
// The trailing objects of an instruction are layed out as follows:
// - InstResult : The results of the instruction.
// - BasicBlockOperand : Use-list of successor blocks if this is a terminator.
// - unsigned : Count of operands held for each of the successors.
//
// Note: For Terminators, we rely on the assumption that all non successor
// operands are placed at the beginning of the operands list.
class Instruction final
: public Operation,
public IROperandOwner,
public llvm::ilist_node_with_parent<Instruction, BasicBlock>,
private llvm::TrailingObjects<Instruction, InstResult, BasicBlockOperand,
unsigned> {
public:
enum class Kind {
Operation = (int)IROperandOwner::Kind::OperationInst,
};
Kind getKind() const { return (Kind)IROperandOwner::getKind(); }
/// Return the BasicBlock containing this instruction.
const BasicBlock *getBlock() const { return block; }
BasicBlock *getBlock() { return block; }
/// Return the CFGFunction containing this instruction.
CFGFunction *getFunction();
const CFGFunction *getFunction() const {
return const_cast<Instruction *>(this)->getFunction();
}
/// Destroy this instruction and its subclass data.
void destroy();
void print(raw_ostream &os) const;
void dump() const;
using IROperandOwner::getContext;
using IROperandOwner::getLoc;
//===--------------------------------------------------------------------===//
// Operands
//===--------------------------------------------------------------------===//
unsigned getNumOperands() const;
unsigned getNumOperands() const { return operands.size(); }
CFGValue *getOperand(unsigned idx) { return getInstOperand(idx).get(); }
const CFGValue *getOperand(unsigned idx) const {
return getInstOperand(idx).get();
}
void setOperand(unsigned idx, CFGValue *value) {
return getInstOperand(idx).set(value);
getInstOperand(idx).set(value);
}
// Support non-const operand iteration.
@ -132,144 +121,10 @@ public:
return {operand_begin(), operand_end()};
}
MutableArrayRef<InstOperand> getInstOperands();
ArrayRef<InstOperand> getInstOperands() const {
return const_cast<Instruction *>(this)->getInstOperands();
}
InstOperand &getInstOperand(unsigned idx) { return getInstOperands()[idx]; }
const InstOperand &getInstOperand(unsigned idx) const {
return getInstOperands()[idx];
}
/// This drops all operand uses from this instruction, which is an essential
/// step in breaking cyclic dependences between references when they are to
/// be deleted.
void dropAllReferences();
/// Emit an error about fatal conditions with this operation, reporting up to
/// any diagnostic handlers that may be listening. NOTE: This may terminate
/// the containing application, only use when the IR is in an inconsistent
/// state.
void emitError(const Twine &message) const;
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
void emitWarning(const Twine &message) const;
/// Emit a note about this operation, reporting up to any diagnostic
/// handlers that may be listening.
void emitNote(const Twine &message) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const IROperandOwner *ptr) {
return ptr->getKind() >= IROperandOwner::Kind::INST_FIRST;
}
protected:
Instruction(Kind kind, Location location)
: IROperandOwner((IROperandOwner::Kind)kind, location) {}
// Instructions are deleted through the destroy() member because this class
// does not have a virtual destructor. A vtable would bloat the size of
// every instruction by a word, is not necessary given the closed nature of
// instruction kinds.
~Instruction();
private:
BasicBlock *block = nullptr;
friend struct llvm::ilist_traits<OperationInst>;
friend class BasicBlock;
};
inline raw_ostream &operator<<(raw_ostream &os, const Instruction &inst) {
inst.print(os);
return os;
}
/// Operations are the main instruction kind in MLIR, which represent all of the
/// arithmetic and other basic computation.
//
// The trailing objects of an operation instruction are layed out as follows:
// - InstResult : The results of the instruction.
// - BasicBlockOperand : Use-list of successor blocks if this is a terminator.
// - unsigned : Count of operands held for each of the successors.
//
// Note: For Terminators, we rely on the assumption that all non successor
// operands are placed at the beginning of the operands list.
class OperationInst final
: public Operation,
public Instruction,
public llvm::ilist_node_with_parent<OperationInst, BasicBlock>,
private llvm::TrailingObjects<OperationInst, InstResult,
BasicBlockOperand, unsigned> {
public:
/// Create a new OperationInst with the specified fields.
static OperationInst *
create(Location location, OperationName name, ArrayRef<CFGValue *> operands,
ArrayRef<Type> resultTypes, ArrayRef<NamedAttribute> attributes,
ArrayRef<BasicBlock *> successors, MLIRContext *context);
using Instruction::dump;
using Instruction::emitError;
using Instruction::emitNote;
using Instruction::emitWarning;
using Instruction::getContext;
using Instruction::getLoc;
using Instruction::print;
OperationInst *clone() const;
//===--------------------------------------------------------------------===//
// Operands
//===--------------------------------------------------------------------===//
unsigned getNumOperands() const { return operands.size(); }
CFGValue *getOperand(unsigned idx) { return getInstOperand(idx).get(); }
const CFGValue *getOperand(unsigned idx) const {
return getInstOperand(idx).get();
}
void setOperand(unsigned idx, CFGValue *value) {
getInstOperand(idx).set(value);
}
// Support non-const operand iteration.
using operand_iterator = OperandIterator<OperationInst, CFGValue>;
operand_iterator operand_begin() { return operand_iterator(this, 0); }
operand_iterator operand_end() {
return operand_iterator(this, getNumOperands());
}
llvm::iterator_range<operand_iterator> getOperands() {
return {operand_begin(), operand_end()};
}
// Support const operand iteration.
using const_operand_iterator =
OperandIterator<const OperationInst, const CFGValue>;
const_operand_iterator operand_begin() const {
return const_operand_iterator(this, 0);
}
const_operand_iterator operand_end() const {
return const_operand_iterator(this, getNumOperands());
}
llvm::iterator_range<const_operand_iterator> getOperands() const {
return {operand_begin(), operand_end()};
}
MutableArrayRef<InstOperand> getInstOperands() { return operands; }
ArrayRef<InstOperand> getInstOperands() const { return operands; }
// Accessors to InstOperand. Without these methods invoking getInstOperand()
// calls Instruction::getInstOperands() resulting in execution of
// an unnecessary switch statement.
// Accessors to InstOperand.
InstOperand &getInstOperand(unsigned idx) { return getInstOperands()[idx]; }
const InstOperand &getInstOperand(unsigned idx) const {
return getInstOperands()[idx];
@ -285,7 +140,7 @@ public:
const CFGValue *getResult(unsigned idx) const { return &getInstResult(idx); }
// Support non-const result iteration.
using result_iterator = ResultIterator<OperationInst, CFGValue>;
using result_iterator = ResultIterator<Instruction, CFGValue>;
result_iterator result_begin() { return result_iterator(this, 0); }
result_iterator result_end() {
return result_iterator(this, getNumResults());
@ -296,7 +151,7 @@ public:
// Support const operand iteration.
using const_result_iterator =
ResultIterator<const OperationInst, const CFGValue>;
ResultIterator<const Instruction, const CFGValue>;
const_result_iterator result_begin() const {
return const_result_iterator(this, 0);
}
@ -332,7 +187,7 @@ public:
return {getTrailingObjects<BasicBlockOperand>(), numSuccs};
}
ArrayRef<BasicBlockOperand> getBasicBlockOperands() const {
return const_cast<OperationInst *>(this)->getBasicBlockOperands();
return const_cast<Instruction *>(this)->getBasicBlockOperands();
}
MutableArrayRef<InstOperand> getSuccessorInstOperands(unsigned index) {
@ -343,7 +198,7 @@ public:
return {operandBegin, getNumSuccessorOperands(index)};
}
ArrayRef<InstOperand> getSuccessorInstOperands(unsigned index) const {
return const_cast<OperationInst *>(this)->getSuccessorInstOperands(index);
return const_cast<Instruction *>(this)->getSuccessorInstOperands(index);
}
unsigned getNumSuccessors() const { return getBasicBlockOperands().size(); }
@ -358,7 +213,7 @@ public:
return getBasicBlockOperands()[index].get();
}
BasicBlock *getSuccessor(unsigned index) const {
return const_cast<OperationInst *>(this)->getSuccessor(index);
return const_cast<Instruction *>(this)->getSuccessor(index);
}
void setSuccessor(BasicBlock *block, unsigned index) {
assert(index < getNumSuccessors());
@ -395,26 +250,66 @@ public:
// Other
//===--------------------------------------------------------------------===//
/// Create a new Instruction with the specified fields.
static Instruction *
create(Location location, OperationName name, ArrayRef<CFGValue *> operands,
ArrayRef<Type> resultTypes, ArrayRef<NamedAttribute> attributes,
ArrayRef<BasicBlock *> successors, MLIRContext *context);
Instruction *clone() const;
/// Return the BasicBlock containing this instruction.
const BasicBlock *getBlock() const { return block; }
BasicBlock *getBlock() { return block; }
/// Return the CFGFunction containing this instruction.
CFGFunction *getFunction();
const CFGFunction *getFunction() const {
return const_cast<Instruction *>(this)->getFunction();
}
void print(raw_ostream &os) const;
void dump() const;
/// Unlink this instruction from its BasicBlock and delete it.
void erase();
/// Delete an instruction that is not linked into a block.
/// Destroy this instruction and its subclass data.
void destroy();
/// Unlink this operation instruction from its current basic block and insert
/// Unlink this instruction from its current basic block and insert
/// it right before `existingInst` which may be in the same or another block
/// of the same function.
void moveBefore(OperationInst *existingInst);
void moveBefore(Instruction *existingInst);
/// Unlink this operation instruction from its current basic block and insert
/// Unlink this instruction from its current basic block and insert
/// it right before `iterator` in the specified basic block, which must be in
/// the same function.
void moveBefore(BasicBlock *block,
llvm::iplist<OperationInst>::iterator iterator);
llvm::iplist<Instruction>::iterator iterator);
/// This drops all operand uses from this instruction, which is an essential
/// step in breaking cyclic dependences between references when they are to
/// be deleted.
void dropAllReferences();
/// Emit an error about fatal conditions with this operation, reporting up to
/// any diagnostic handlers that may be listening. NOTE: This may terminate
/// the containing application, only use when the IR is in an inconsistent
/// state.
void emitError(const Twine &message) const;
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
void emitWarning(const Twine &message) const;
/// Emit a note about this operation, reporting up to any diagnostic
/// handlers that may be listening.
void emitNote(const Twine &message) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const IROperandOwner *ptr) {
return ptr->getKind() == IROperandOwner::Kind::OperationInst;
return ptr->getKind() == IROperandOwner::Kind::Instruction;
}
static bool classof(const Operation *op) {
return op->getOperationKind() == OperationKind::Instruction;
@ -423,14 +318,21 @@ public:
private:
const unsigned numResults, numSuccs;
std::vector<InstOperand> operands;
BasicBlock *block = nullptr;
OperationInst(Location location, OperationName name, unsigned numResults,
unsigned numSuccessors, ArrayRef<NamedAttribute> attributes,
MLIRContext *context);
~OperationInst();
Instruction(Location location, OperationName name, unsigned numResults,
unsigned numSuccessors, ArrayRef<NamedAttribute> attributes,
MLIRContext *context);
// Instructions are deleted through the destroy() member because this class
// does not have a virtual destructor.
~Instruction();
friend struct llvm::ilist_traits<Instruction>;
friend class BasicBlock;
// This stuff is used by the TrailingObjects template.
friend llvm::TrailingObjects<OperationInst, InstResult, BasicBlockOperand,
friend llvm::TrailingObjects<Instruction, InstResult, BasicBlockOperand,
unsigned>;
size_t numTrailingObjects(OverloadToken<InstResult>) const {
return numResults;
@ -441,6 +343,14 @@ private:
size_t numTrailingObjects(OverloadToken<unsigned>) const { return numSuccs; }
};
inline raw_ostream &operator<<(raw_ostream &os, const Instruction &inst) {
inst.print(os);
return os;
}
// TODO(riverriddle) Remove this when all uses have been renamed.
using OperationInst = Instruction;
} // end namespace mlir
#endif // MLIR_IR_INSTRUCTIONS_H

View File

@ -35,7 +35,7 @@ class Instruction;
class Statement;
/// Operations represent all of the arithmetic and other basic computation in
/// MLIR. This class is the common implementation details behind OperationInst
/// MLIR. This class is the common implementation details behind Instruction
/// and OperationStmt.
///
class Operation {
@ -196,7 +196,7 @@ public:
}
/// The dyn_cast methods perform a dynamic cast from an Operation (like
/// OperationInst and OperationStmt) to a typed Op like DimOp. This returns
/// Instruction and OperationStmt) to a typed Op like DimOp. This returns
/// a null OpPointer on failure.
template <typename OpClass> OpPointer<OpClass> dyn_cast() {
if (isa<OpClass>()) {
@ -207,7 +207,7 @@ public:
}
/// The dyn_cast methods perform a dynamic cast from an Operation (like
/// OperationInst and OperationStmt) to a typed Op like DimOp. This returns
/// Instruction and OperationStmt) to a typed Op like DimOp. This returns
/// a null ConstOpPointer on failure.
template <typename OpClass> ConstOpPointer<OpClass> dyn_cast() const {
if (isa<OpClass>()) {
@ -218,7 +218,7 @@ public:
}
/// The cast methods perform a cast from an Operation (like
/// OperationInst and OperationStmt) to a typed Op like DimOp. This aborts
/// Instruction and OperationStmt) to a typed Op like DimOp. This aborts
/// if the parameter to the template isn't an instance of the template type
/// argument.
template <typename OpClass> OpPointer<OpClass> cast() {
@ -227,7 +227,7 @@ public:
}
/// The cast methods perform a cast from an Operation (like
/// OperationInst and OperationStmt) to a typed Op like DimOp. This aborts
/// Instruction and OperationStmt) to a typed Op like DimOp. This aborts
/// if the parameter to the template isn't an instance of the template type
/// argument.
template <typename OpClass> ConstOpPointer<OpClass> cast() const {
@ -243,7 +243,7 @@ public:
enum class OperationKind { Instruction, Statement };
// This is used to implement the dynamic casting logic, but you shouldn't
// call it directly. Use something like isa<OperationInst>(someOp) instead.
// call it directly. Use something like isa<Instruction>(someOp) instead.
OperationKind getOperationKind() const {
return nameAndIsInstruction.getInt() ? OperationKind::Instruction
: OperationKind::Statement;
@ -285,7 +285,6 @@ public:
void dump() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Instruction *inst);
static bool classof(const Statement *stmt);
static bool classof(const IROperandOwner *ptr);
@ -299,7 +298,7 @@ private:
void operator=(const Operation&) = delete;
/// This holds the name of the operation, and a bool. The bool is true if
/// this operation is an OperationInst, false if it is a OperationStmt.
/// this operation is an Instruction, false if it is a OperationStmt.
llvm::PointerIntPair<OperationName, 1, bool> nameAndIsInstruction;
/// This holds general named attributes for the operation.

View File

@ -28,7 +28,7 @@
namespace mlir {
class Function;
class OperationInst;
class Instruction;
class OperationStmt;
class Operation;
@ -67,10 +67,10 @@ public:
return const_cast<SSAValue *>(this)->getFunction();
}
/// If this value is the result of an OperationInst, return the instruction
/// If this value is the result of an Instruction, return the instruction
/// that defines it.
OperationInst *getDefiningInst();
const OperationInst *getDefiningInst() const {
Instruction *getDefiningInst();
const Instruction *getDefiningInst() const {
return const_cast<SSAValue *>(this)->getDefiningInst();
}

View File

@ -79,11 +79,10 @@ public:
OperationStmt,
ForStmt,
IfStmt,
OperationInst,
Instruction,
/// These enums define ranges used for classof implementations.
STMT_LAST = IfStmt,
INST_FIRST = OperationInst,
};
Kind getKind() const { return locationAndKind.getInt(); }

View File

@ -49,17 +49,15 @@ bool DominanceInfo::properlyDominates(const Instruction *a,
return false;
// If one is a terminator, then the other dominates it.
auto *aOp = cast<OperationInst>(a);
if (aOp->isTerminator())
if (a->isTerminator())
return false;
auto *bOp = cast<OperationInst>(b);
if (bOp->isTerminator())
if (b->isTerminator())
return true;
// Otherwise, do a linear scan to determine whether B comes after A.
auto aIter = BasicBlock::const_iterator(aOp);
auto bIter = BasicBlock::const_iterator(bOp);
auto aIter = BasicBlock::const_iterator(a);
auto bIter = BasicBlock::const_iterator(b);
auto fIter = aBlock->begin();
while (bIter != fIter) {
--bIter;

View File

@ -1168,7 +1168,6 @@ public:
void print(const BasicBlock *block);
void print(const Instruction *inst);
void print(const OperationInst *inst);
void printSuccessorAndUseList(const Operation *term, unsigned index);
@ -1277,13 +1276,6 @@ void CFGFunctionPrinter::print(const Instruction *inst) {
os << "<<null instruction>>\n";
return;
}
switch (inst->getKind()) {
case Instruction::Kind::Operation:
return print(cast<OperationInst>(inst));
}
}
void CFGFunctionPrinter::print(const OperationInst *inst) {
printOperation(inst);
}

View File

@ -41,101 +41,21 @@ unsigned InstResult::getResultNumber() const {
// Instruction
//===----------------------------------------------------------------------===//
// Instructions are deleted through the destroy() member because we don't have
// a virtual destructor.
Instruction::~Instruction() {
assert(block == nullptr && "instruction destroyed but still in a block");
}
/// Destroy this instruction or one of its subclasses.
void Instruction::destroy() {
switch (getKind()) {
case Kind::Operation:
cast<OperationInst>(this)->destroy();
break;
}
}
void OperationInst::destroy() {
this->~OperationInst();
free(this);
}
CFGFunction *Instruction::getFunction() {
auto *block = getBlock();
return block ? block->getFunction() : nullptr;
}
unsigned Instruction::getNumOperands() const {
switch (getKind()) {
case Kind::Operation:
return cast<OperationInst>(this)->getNumOperands();
}
}
MutableArrayRef<InstOperand> Instruction::getInstOperands() {
switch (getKind()) {
case Kind::Operation:
return cast<OperationInst>(this)->getInstOperands();
}
}
/// This drops all operand uses from this instruction, which is an essential
/// step in breaking cyclic dependences between references when they are to
/// be deleted.
void Instruction::dropAllReferences() {
for (auto &op : getInstOperands())
op.drop();
if (OperationInst *opInst = dyn_cast<OperationInst>(this)) {
if (opInst->isTerminator())
for (auto &dest : opInst->getBasicBlockOperands())
dest.drop();
}
}
/// Emit a note about this instruction, reporting up to any diagnostic
/// handlers that may be listening.
void Instruction::emitNote(const Twine &message) const {
getContext()->emitDiagnostic(getLoc(), message,
MLIRContext::DiagnosticKind::Note);
}
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
void Instruction::emitWarning(const Twine &message) const {
getContext()->emitDiagnostic(getLoc(), message,
MLIRContext::DiagnosticKind::Warning);
}
/// Emit an error about fatal conditions with this instruction, reporting up to
/// any diagnostic handlers that may be listening. NOTE: This may terminate
/// the containing application, only use when the IR is in an inconsistent
/// state.
void Instruction::emitError(const Twine &message) const {
getContext()->emitDiagnostic(getLoc(), message,
MLIRContext::DiagnosticKind::Error);
}
//===----------------------------------------------------------------------===//
// OperationInst
//===----------------------------------------------------------------------===//
/// Create a new OperationInst with the specified fields.
OperationInst *OperationInst::create(Location location, OperationName name,
ArrayRef<CFGValue *> operands,
ArrayRef<Type> resultTypes,
ArrayRef<NamedAttribute> attributes,
ArrayRef<BasicBlock *> successors,
MLIRContext *context) {
/// Create a new Instruction with the specified fields.
Instruction *Instruction::create(Location location, OperationName name,
ArrayRef<CFGValue *> operands,
ArrayRef<Type> resultTypes,
ArrayRef<NamedAttribute> attributes,
ArrayRef<BasicBlock *> successors,
MLIRContext *context) {
unsigned numSuccessors = successors.size();
auto byteSize = totalSizeToAlloc<InstResult, BasicBlockOperand, unsigned>(
resultTypes.size(), numSuccessors, numSuccessors);
void *rawMem = malloc(byteSize);
// Initialize the OperationInst part of the instruction.
auto inst = ::new (rawMem) OperationInst(location, name, resultTypes.size(),
numSuccessors, attributes, context);
// Initialize the Instruction part of the instruction.
auto inst = ::new (rawMem) Instruction(location, name, resultTypes.size(),
numSuccessors, attributes, context);
// Initialize the results and operands.
auto instResults = inst->getInstResults();
@ -193,7 +113,7 @@ OperationInst *OperationInst::create(Location location, OperationName name,
return inst;
}
OperationInst *OperationInst::clone() const {
Instruction *Instruction::clone() const {
SmallVector<CFGValue *, 8> operands;
SmallVector<Type, 8> resultTypes;
SmallVector<BasicBlock *, 1> successors;
@ -238,15 +158,17 @@ OperationInst *OperationInst::clone() const {
successors, getContext());
}
OperationInst::OperationInst(Location location, OperationName name,
unsigned numResults, unsigned numSuccessors,
ArrayRef<NamedAttribute> attributes,
MLIRContext *context)
Instruction::Instruction(Location location, OperationName name,
unsigned numResults, unsigned numSuccessors,
ArrayRef<NamedAttribute> attributes,
MLIRContext *context)
: Operation(/*isInstruction=*/true, name, attributes, context),
Instruction(Kind::Operation, location), numResults(numResults),
numSuccs(numSuccessors) {}
IROperandOwner(IROperandOwner::Kind::Instruction, location),
numResults(numResults), numSuccs(numSuccessors) {}
Instruction::~Instruction() {
assert(block == nullptr && "instruction destroyed but still in a block");
OperationInst::~OperationInst() {
// Explicitly run the destructors for the results and successors.
for (auto &result : getInstResults())
result.~InstResult();
@ -256,7 +178,53 @@ OperationInst::~OperationInst() {
successor.~BasicBlockOperand();
}
void OperationInst::addSuccessorOperand(unsigned index, CFGValue *value) {
/// Destroy this instruction.
void Instruction::destroy() {
this->~Instruction();
free(this);
}
CFGFunction *Instruction::getFunction() {
auto *block = getBlock();
return block ? block->getFunction() : nullptr;
}
/// This drops all operand uses from this instruction, which is an essential
/// step in breaking cyclic dependences between references when they are to
/// be deleted.
void Instruction::dropAllReferences() {
for (auto &op : getInstOperands())
op.drop();
if (isTerminator())
for (auto &dest : getBasicBlockOperands())
dest.drop();
}
/// Emit a note about this instruction, reporting up to any diagnostic
/// handlers that may be listening.
void Instruction::emitNote(const Twine &message) const {
getContext()->emitDiagnostic(getLoc(), message,
MLIRContext::DiagnosticKind::Note);
}
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
void Instruction::emitWarning(const Twine &message) const {
getContext()->emitDiagnostic(getLoc(), message,
MLIRContext::DiagnosticKind::Warning);
}
/// Emit an error about fatal conditions with this instruction, reporting up to
/// any diagnostic handlers that may be listening. NOTE: This may terminate
/// the containing application, only use when the IR is in an inconsistent
/// state.
void Instruction::emitError(const Twine &message) const {
getContext()->emitDiagnostic(getLoc(), message,
MLIRContext::DiagnosticKind::Error);
}
void Instruction::addSuccessorOperand(unsigned index, CFGValue *value) {
assert(isTerminator() && "Only terminators have successors.");
assert(index < getNumSuccessors());
assert(std::accumulate(getTrailingObjects<unsigned>() + index + 1,
@ -267,47 +235,45 @@ void OperationInst::addSuccessorOperand(unsigned index, CFGValue *value) {
++getTrailingObjects<unsigned>()[index];
}
void OperationInst::addSuccessorOperands(unsigned index,
ArrayRef<CFGValue *> values) {
void Instruction::addSuccessorOperands(unsigned index,
ArrayRef<CFGValue *> values) {
operands.reserve(operands.size() + values.size());
for (auto *value : values)
addSuccessorOperand(index, value);
}
void llvm::ilist_traits<::mlir::OperationInst>::deleteNode(
OperationInst *inst) {
void llvm::ilist_traits<::mlir::Instruction>::deleteNode(Instruction *inst) {
inst->destroy();
}
mlir::BasicBlock *
llvm::ilist_traits<::mlir::OperationInst>::getContainingBlock() {
llvm::ilist_traits<::mlir::Instruction>::getContainingBlock() {
size_t Offset(
size_t(&((BasicBlock *)nullptr->*BasicBlock::getSublistAccess(nullptr))));
iplist<OperationInst> *Anchor(static_cast<iplist<OperationInst> *>(this));
iplist<Instruction> *Anchor(static_cast<iplist<Instruction> *>(this));
return reinterpret_cast<BasicBlock *>(reinterpret_cast<char *>(Anchor) -
Offset);
}
/// This is a trait method invoked when an instruction is added to a block. We
/// keep the block pointer up to date.
void llvm::ilist_traits<::mlir::OperationInst>::addNodeToList(
OperationInst *inst) {
void llvm::ilist_traits<::mlir::Instruction>::addNodeToList(Instruction *inst) {
assert(!inst->getBlock() && "already in a basic block!");
inst->block = getContainingBlock();
}
/// This is a trait method invoked when an instruction is removed from a block.
/// We keep the block pointer up to date.
void llvm::ilist_traits<::mlir::OperationInst>::removeNodeFromList(
OperationInst *inst) {
void llvm::ilist_traits<::mlir::Instruction>::removeNodeFromList(
Instruction *inst) {
assert(inst->block && "not already in a basic block!");
inst->block = nullptr;
}
/// This is a trait method invoked when an instruction is moved from one block
/// to another. We keep the block pointer up to date.
void llvm::ilist_traits<::mlir::OperationInst>::transferNodesFromList(
ilist_traits<OperationInst> &otherList, instr_iterator first,
void llvm::ilist_traits<::mlir::Instruction>::transferNodesFromList(
ilist_traits<Instruction> &otherList, instr_iterator first,
instr_iterator last) {
// If we are transferring instructions within the same basic block, the block
// pointer doesn't need to be updated.
@ -321,7 +287,7 @@ void llvm::ilist_traits<::mlir::OperationInst>::transferNodesFromList(
}
/// Unlink this instruction from its BasicBlock and delete it.
void OperationInst::erase() {
void Instruction::erase() {
assert(getBlock() && "Instruction has no parent");
getBlock()->getOperations().erase(this);
}
@ -329,15 +295,15 @@ void OperationInst::erase() {
/// Unlink this operation instruction from its current basic block and insert
/// it right before `existingInst` which may be in the same or another block
/// in the same function.
void OperationInst::moveBefore(OperationInst *existingInst) {
void Instruction::moveBefore(Instruction *existingInst) {
assert(existingInst && "Cannot move before a null instruction");
return moveBefore(existingInst->getBlock(), existingInst->getIterator());
}
/// Unlink this operation instruction from its current basic block and insert
/// it right before `iterator` in the specified basic block.
void OperationInst::moveBefore(BasicBlock *block,
llvm::iplist<OperationInst>::iterator iterator) {
void Instruction::moveBefore(BasicBlock *block,
llvm::iplist<Instruction>::iterator iterator) {
block->getOperations().splice(iterator, getBlock()->getOperations(),
getIterator());
}

View File

@ -74,7 +74,7 @@ Operation::~Operation() {}
/// Return the context this operation is associated with.
MLIRContext *Operation::getContext() const {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getContext();
return llvm::cast<OperationStmt>(this)->getContext();
}
@ -82,35 +82,35 @@ MLIRContext *Operation::getContext() const {
/// The source location the operation was defined or derived from. Note that
/// it is possible for this pointer to be null.
Location Operation::getLoc() const {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getLoc();
return llvm::cast<OperationStmt>(this)->getLoc();
}
/// Return the function this operation is defined in.
Function *Operation::getOperationFunction() {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getFunction();
return llvm::cast<OperationStmt>(this)->findFunction();
}
/// Return the number of operands this operation has.
unsigned Operation::getNumOperands() const {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getNumOperands();
return llvm::cast<OperationStmt>(this)->getNumOperands();
}
SSAValue *Operation::getOperand(unsigned idx) {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getOperand(idx);
return llvm::cast<OperationStmt>(this)->getOperand(idx);
}
void Operation::setOperand(unsigned idx, SSAValue *value) {
if (auto *inst = llvm::dyn_cast<OperationInst>(this)) {
if (auto *inst = llvm::dyn_cast<Instruction>(this)) {
inst->setOperand(idx, llvm::cast<CFGValue>(value));
} else {
auto *stmt = llvm::cast<OperationStmt>(this);
@ -120,7 +120,7 @@ void Operation::setOperand(unsigned idx, SSAValue *value) {
/// Return the number of results this operation has.
unsigned Operation::getNumResults() const {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getNumResults();
return llvm::cast<OperationStmt>(this)->getNumResults();
@ -128,7 +128,7 @@ unsigned Operation::getNumResults() const {
/// Return the indicated result.
SSAValue *Operation::getResult(unsigned idx) {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->getResult(idx);
return llvm::cast<OperationStmt>(this)->getResult(idx);
@ -136,8 +136,8 @@ SSAValue *Operation::getResult(unsigned idx) {
unsigned Operation::getNumSuccessors() const {
assert(isTerminator() && "Only terminators have successors.");
if (llvm::isa<OperationInst>(this))
return llvm::cast<OperationInst>(this)->getNumSuccessors();
if (llvm::isa<Instruction>(this))
return llvm::cast<Instruction>(this)->getNumSuccessors();
// OperationStmt currently only has a return terminator.
assert(llvm::cast<OperationStmt>(this)->isReturn() &&
@ -147,36 +147,33 @@ unsigned Operation::getNumSuccessors() const {
unsigned Operation::getNumSuccessorOperands(unsigned index) const {
assert(isTerminator() && "Only terminators have successors.");
assert(llvm::isa<OperationInst>(this) &&
"Only instructions have successors.");
return llvm::cast<OperationInst>(this)->getNumSuccessorOperands(index);
assert(llvm::isa<Instruction>(this) && "Only instructions have successors.");
return llvm::cast<Instruction>(this)->getNumSuccessorOperands(index);
}
BasicBlock *Operation::getSuccessor(unsigned index) {
assert(isTerminator() && "Only terminators have successors.");
assert(llvm::isa<OperationInst>(this) &&
assert(llvm::isa<Instruction>(this) &&
"Only instructions have basic block successors.");
return llvm::cast<OperationInst>(this)->getSuccessor(index);
return llvm::cast<Instruction>(this)->getSuccessor(index);
}
void Operation::setSuccessor(BasicBlock *block, unsigned index) {
assert(isTerminator() && "Only terminators have successors.");
assert(llvm::isa<OperationInst>(this) &&
assert(llvm::isa<Instruction>(this) &&
"Only instructions have basic block successors.");
llvm::cast<OperationInst>(this)->setSuccessor(block, index);
llvm::cast<Instruction>(this)->setSuccessor(block, index);
}
void Operation::addSuccessorOperand(unsigned index, SSAValue *value) {
assert(isTerminator() && "Only terminators have successors.");
assert(llvm::isa<OperationInst>(this) &&
"Only instructions have successors.");
return llvm::cast<OperationInst>(this)->addSuccessorOperand(
assert(llvm::isa<Instruction>(this) && "Only instructions have successors.");
return llvm::cast<Instruction>(this)->addSuccessorOperand(
index, llvm::cast<CFGValue>(value));
}
auto Operation::getSuccessorOperands(unsigned index) const
-> llvm::iterator_range<const_operand_iterator> {
assert(isTerminator() && "Only terminators have successors.");
assert(llvm::isa<OperationInst>(this) &&
"Only instructions have successors.");
assert(llvm::isa<Instruction>(this) && "Only instructions have successors.");
unsigned succOperandIndex =
llvm::cast<OperationInst>(this)->getSuccessorOperandIndex(index);
llvm::cast<Instruction>(this)->getSuccessorOperandIndex(index);
return {const_operand_iterator(this, succOperandIndex),
const_operand_iterator(this, succOperandIndex +
getNumSuccessorOperands(index))};
@ -184,10 +181,9 @@ auto Operation::getSuccessorOperands(unsigned index) const
auto Operation::getSuccessorOperands(unsigned index)
-> llvm::iterator_range<operand_iterator> {
assert(isTerminator() && "Only terminators have successors.");
assert(llvm::isa<OperationInst>(this) &&
"Only instructions have successors.");
assert(llvm::isa<Instruction>(this) && "Only instructions have successors.");
unsigned succOperandIndex =
llvm::cast<OperationInst>(this)->getSuccessorOperandIndex(index);
llvm::cast<Instruction>(this)->getSuccessorOperandIndex(index);
return {operand_iterator(this, succOperandIndex),
operand_iterator(this,
succOperandIndex + getNumSuccessorOperands(index))};
@ -278,7 +274,7 @@ bool Operation::emitOpError(const Twine &message) const {
/// Remove this operation from its parent block and delete it.
void Operation::erase() {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->erase();
return llvm::cast<OperationStmt>(this)->erase();
}
@ -302,26 +298,23 @@ bool Operation::constantFold(ArrayRef<Attribute> operands,
}
void Operation::print(raw_ostream &os) const {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->print(os);
return llvm::cast<OperationStmt>(this)->print(os);
}
void Operation::dump() const {
if (auto *inst = llvm::dyn_cast<OperationInst>(this))
if (auto *inst = llvm::dyn_cast<Instruction>(this))
return inst->dump();
return llvm::cast<OperationStmt>(this)->dump();
}
/// Methods for support type inquiry through isa, cast, and dyn_cast.
bool Operation::classof(const Instruction *inst) {
return inst->getKind() == Instruction::Kind::Operation;
}
bool Operation::classof(const Statement *stmt) {
return stmt->getKind() == Statement::Kind::Operation;
}
bool Operation::classof(const IROperandOwner *ptr) {
return ptr->getKind() == IROperandOwner::Kind::OperationInst ||
return ptr->getKind() == IROperandOwner::Kind::Instruction ||
ptr->getKind() == IROperandOwner::Kind::OperationStmt;
}
@ -337,7 +330,7 @@ llvm::cast_convert_val<mlir::Operation, mlir::IROperandOwner *,
if (auto *ptr = dyn_cast<OperationStmt>(value))
op = ptr;
else
op = cast<OperationInst>(value);
op = cast<Instruction>(value);
return const_cast<Operation *>(op);
}
@ -540,7 +533,7 @@ bool OpTrait::impl::verifyIsTerminator(const Operation *op) {
if (!block || !isa<MLFunction>(block) || &block->back() != stmt)
return op->emitOpError("must be the last statement in the ML function");
} else {
const OperationInst *inst = cast<OperationInst>(op);
const Instruction *inst = cast<Instruction>(op);
const BasicBlock *block = inst->getBlock();
if (!block || &block->back() != inst)
return op->emitOpError(

View File

@ -23,9 +23,9 @@
using namespace mlir;
/// If this value is the result of an OperationInst, return the instruction
/// If this value is the result of an Instruction, return the instruction
/// that defines it.
OperationInst *SSAValue::getDefiningInst() {
Instruction *SSAValue::getDefiningInst() {
if (auto *result = dyn_cast<InstResult>(this))
return result->getOwner();
return nullptr;
@ -77,7 +77,7 @@ MLIRContext *IROperandOwner::getContext() const {
case Kind::IfStmt:
return cast<IfStmt>(this)->getContext();
case Kind::OperationInst:
case Kind::Instruction:
// If we have an instruction, we can efficiently get this from the function
// the instruction is in.
auto *fn = cast<Instruction>(this)->getFunction();

View File

@ -1936,10 +1936,10 @@ SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
// cannot be created through normal user input, allowing us to distinguish
// them.
auto name = OperationName("placeholder", getContext());
auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
/*operands=*/{}, type,
/*attributes=*/{},
/*successors=*/{}, getContext());
auto *inst = Instruction::create(getEncodedSourceLocation(loc), name,
/*operands=*/{}, type,
/*attributes=*/{},
/*successors=*/{}, getContext());
forwardReferencePlaceholders[inst->getResult(0)] = loc;
return inst->getResult(0);
}