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

View File

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

View File

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

View File

@ -32,24 +32,22 @@
namespace mlir { namespace mlir {
class BasicBlock; class BasicBlock;
class CFGFunction; class CFGFunction;
class OperationInst;
class TerminatorInst;
} // end namespace mlir } // end namespace mlir
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ilist_traits for OperationInst // ilist_traits for Instruction
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace llvm { namespace llvm {
template <> struct ilist_traits<::mlir::OperationInst> { template <> struct ilist_traits<::mlir::Instruction> {
using OperationInst = ::mlir::OperationInst; using Instruction = ::mlir::Instruction;
using instr_iterator = simple_ilist<OperationInst>::iterator; using instr_iterator = simple_ilist<Instruction>::iterator;
static void deleteNode(OperationInst *inst); static void deleteNode(Instruction *inst);
void addNodeToList(OperationInst *inst); void addNodeToList(Instruction *inst);
void removeNodeFromList(OperationInst *inst); void removeNodeFromList(Instruction *inst);
void transferNodesFromList(ilist_traits<OperationInst> &otherList, void transferNodesFromList(ilist_traits<Instruction> &otherList,
instr_iterator first, instr_iterator last); instr_iterator first, instr_iterator last);
private: private:
@ -63,44 +61,35 @@ namespace mlir {
/// The operand of a Terminator contains a BasicBlock. /// The operand of a Terminator contains a BasicBlock.
using BasicBlockOperand = IROperandImpl<BasicBlock, Instruction>; using BasicBlockOperand = IROperandImpl<BasicBlock, Instruction>;
/// Instruction is the root of the operation and terminator instructions in the // The trailing objects of an instruction are layed out as follows:
/// hierarchy. // - InstResult : The results of the instruction.
class Instruction : public IROperandOwner { // - 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: public:
enum class Kind { using IROperandOwner::getContext;
Operation = (int)IROperandOwner::Kind::OperationInst, using IROperandOwner::getLoc;
};
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;
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Operands // Operands
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
unsigned getNumOperands() const; unsigned getNumOperands() const { return operands.size(); }
CFGValue *getOperand(unsigned idx) { return getInstOperand(idx).get(); } CFGValue *getOperand(unsigned idx) { return getInstOperand(idx).get(); }
const CFGValue *getOperand(unsigned idx) const { const CFGValue *getOperand(unsigned idx) const {
return getInstOperand(idx).get(); return getInstOperand(idx).get();
} }
void setOperand(unsigned idx, CFGValue *value) { void setOperand(unsigned idx, CFGValue *value) {
return getInstOperand(idx).set(value); getInstOperand(idx).set(value);
} }
// Support non-const operand iteration. // Support non-const operand iteration.
@ -132,144 +121,10 @@ public:
return {operand_begin(), operand_end()}; 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; } MutableArrayRef<InstOperand> getInstOperands() { return operands; }
ArrayRef<InstOperand> getInstOperands() const { return operands; } ArrayRef<InstOperand> getInstOperands() const { return operands; }
// Accessors to InstOperand. Without these methods invoking getInstOperand() // Accessors to InstOperand.
// calls Instruction::getInstOperands() resulting in execution of
// an unnecessary switch statement.
InstOperand &getInstOperand(unsigned idx) { return getInstOperands()[idx]; } InstOperand &getInstOperand(unsigned idx) { return getInstOperands()[idx]; }
const InstOperand &getInstOperand(unsigned idx) const { const InstOperand &getInstOperand(unsigned idx) const {
return getInstOperands()[idx]; return getInstOperands()[idx];
@ -285,7 +140,7 @@ public:
const CFGValue *getResult(unsigned idx) const { return &getInstResult(idx); } const CFGValue *getResult(unsigned idx) const { return &getInstResult(idx); }
// Support non-const result iteration. // 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_begin() { return result_iterator(this, 0); }
result_iterator result_end() { result_iterator result_end() {
return result_iterator(this, getNumResults()); return result_iterator(this, getNumResults());
@ -296,7 +151,7 @@ public:
// Support const operand iteration. // Support const operand iteration.
using const_result_iterator = using const_result_iterator =
ResultIterator<const OperationInst, const CFGValue>; ResultIterator<const Instruction, const CFGValue>;
const_result_iterator result_begin() const { const_result_iterator result_begin() const {
return const_result_iterator(this, 0); return const_result_iterator(this, 0);
} }
@ -332,7 +187,7 @@ public:
return {getTrailingObjects<BasicBlockOperand>(), numSuccs}; return {getTrailingObjects<BasicBlockOperand>(), numSuccs};
} }
ArrayRef<BasicBlockOperand> getBasicBlockOperands() const { ArrayRef<BasicBlockOperand> getBasicBlockOperands() const {
return const_cast<OperationInst *>(this)->getBasicBlockOperands(); return const_cast<Instruction *>(this)->getBasicBlockOperands();
} }
MutableArrayRef<InstOperand> getSuccessorInstOperands(unsigned index) { MutableArrayRef<InstOperand> getSuccessorInstOperands(unsigned index) {
@ -343,7 +198,7 @@ public:
return {operandBegin, getNumSuccessorOperands(index)}; return {operandBegin, getNumSuccessorOperands(index)};
} }
ArrayRef<InstOperand> getSuccessorInstOperands(unsigned index) const { 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(); } unsigned getNumSuccessors() const { return getBasicBlockOperands().size(); }
@ -358,7 +213,7 @@ public:
return getBasicBlockOperands()[index].get(); return getBasicBlockOperands()[index].get();
} }
BasicBlock *getSuccessor(unsigned index) const { 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) { void setSuccessor(BasicBlock *block, unsigned index) {
assert(index < getNumSuccessors()); assert(index < getNumSuccessors());
@ -395,26 +250,66 @@ public:
// Other // 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. /// Unlink this instruction from its BasicBlock and delete it.
void erase(); void erase();
/// Delete an instruction that is not linked into a block. /// Destroy this instruction and its subclass data.
void destroy(); 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 /// it right before `existingInst` which may be in the same or another block
/// of the same function. /// 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 /// it right before `iterator` in the specified basic block, which must be in
/// the same function. /// the same function.
void moveBefore(BasicBlock *block, 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. /// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const IROperandOwner *ptr) { static bool classof(const IROperandOwner *ptr) {
return ptr->getKind() == IROperandOwner::Kind::OperationInst; return ptr->getKind() == IROperandOwner::Kind::Instruction;
} }
static bool classof(const Operation *op) { static bool classof(const Operation *op) {
return op->getOperationKind() == OperationKind::Instruction; return op->getOperationKind() == OperationKind::Instruction;
@ -423,14 +318,21 @@ public:
private: private:
const unsigned numResults, numSuccs; const unsigned numResults, numSuccs;
std::vector<InstOperand> operands; std::vector<InstOperand> operands;
BasicBlock *block = nullptr;
OperationInst(Location location, OperationName name, unsigned numResults, Instruction(Location location, OperationName name, unsigned numResults,
unsigned numSuccessors, ArrayRef<NamedAttribute> attributes, unsigned numSuccessors, ArrayRef<NamedAttribute> attributes,
MLIRContext *context); MLIRContext *context);
~OperationInst();
// 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. // This stuff is used by the TrailingObjects template.
friend llvm::TrailingObjects<OperationInst, InstResult, BasicBlockOperand, friend llvm::TrailingObjects<Instruction, InstResult, BasicBlockOperand,
unsigned>; unsigned>;
size_t numTrailingObjects(OverloadToken<InstResult>) const { size_t numTrailingObjects(OverloadToken<InstResult>) const {
return numResults; return numResults;
@ -441,6 +343,14 @@ private:
size_t numTrailingObjects(OverloadToken<unsigned>) const { return numSuccs; } 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 } // end namespace mlir
#endif // MLIR_IR_INSTRUCTIONS_H #endif // MLIR_IR_INSTRUCTIONS_H

View File

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

View File

@ -28,7 +28,7 @@
namespace mlir { namespace mlir {
class Function; class Function;
class OperationInst; class Instruction;
class OperationStmt; class OperationStmt;
class Operation; class Operation;
@ -67,10 +67,10 @@ public:
return const_cast<SSAValue *>(this)->getFunction(); 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. /// that defines it.
OperationInst *getDefiningInst(); Instruction *getDefiningInst();
const OperationInst *getDefiningInst() const { const Instruction *getDefiningInst() const {
return const_cast<SSAValue *>(this)->getDefiningInst(); return const_cast<SSAValue *>(this)->getDefiningInst();
} }

View File

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

View File

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

View File

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

View File

@ -41,101 +41,21 @@ unsigned InstResult::getResultNumber() const {
// Instruction // Instruction
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Instructions are deleted through the destroy() member because we don't have /// Create a new Instruction with the specified fields.
// a virtual destructor. Instruction *Instruction::create(Location location, OperationName name,
Instruction::~Instruction() { ArrayRef<CFGValue *> operands,
assert(block == nullptr && "instruction destroyed but still in a block"); ArrayRef<Type> resultTypes,
} ArrayRef<NamedAttribute> attributes,
ArrayRef<BasicBlock *> successors,
/// Destroy this instruction or one of its subclasses. MLIRContext *context) {
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) {
unsigned numSuccessors = successors.size(); unsigned numSuccessors = successors.size();
auto byteSize = totalSizeToAlloc<InstResult, BasicBlockOperand, unsigned>( auto byteSize = totalSizeToAlloc<InstResult, BasicBlockOperand, unsigned>(
resultTypes.size(), numSuccessors, numSuccessors); resultTypes.size(), numSuccessors, numSuccessors);
void *rawMem = malloc(byteSize); void *rawMem = malloc(byteSize);
// Initialize the OperationInst part of the instruction. // Initialize the Instruction part of the instruction.
auto inst = ::new (rawMem) OperationInst(location, name, resultTypes.size(), auto inst = ::new (rawMem) Instruction(location, name, resultTypes.size(),
numSuccessors, attributes, context); numSuccessors, attributes, context);
// Initialize the results and operands. // Initialize the results and operands.
auto instResults = inst->getInstResults(); auto instResults = inst->getInstResults();
@ -193,7 +113,7 @@ OperationInst *OperationInst::create(Location location, OperationName name,
return inst; return inst;
} }
OperationInst *OperationInst::clone() const { Instruction *Instruction::clone() const {
SmallVector<CFGValue *, 8> operands; SmallVector<CFGValue *, 8> operands;
SmallVector<Type, 8> resultTypes; SmallVector<Type, 8> resultTypes;
SmallVector<BasicBlock *, 1> successors; SmallVector<BasicBlock *, 1> successors;
@ -238,15 +158,17 @@ OperationInst *OperationInst::clone() const {
successors, getContext()); successors, getContext());
} }
OperationInst::OperationInst(Location location, OperationName name, Instruction::Instruction(Location location, OperationName name,
unsigned numResults, unsigned numSuccessors, unsigned numResults, unsigned numSuccessors,
ArrayRef<NamedAttribute> attributes, ArrayRef<NamedAttribute> attributes,
MLIRContext *context) MLIRContext *context)
: Operation(/*isInstruction=*/true, name, attributes, context), : Operation(/*isInstruction=*/true, name, attributes, context),
Instruction(Kind::Operation, location), numResults(numResults), IROperandOwner(IROperandOwner::Kind::Instruction, location),
numSuccs(numSuccessors) {} 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. // Explicitly run the destructors for the results and successors.
for (auto &result : getInstResults()) for (auto &result : getInstResults())
result.~InstResult(); result.~InstResult();
@ -256,7 +178,53 @@ OperationInst::~OperationInst() {
successor.~BasicBlockOperand(); 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(isTerminator() && "Only terminators have successors.");
assert(index < getNumSuccessors()); assert(index < getNumSuccessors());
assert(std::accumulate(getTrailingObjects<unsigned>() + index + 1, assert(std::accumulate(getTrailingObjects<unsigned>() + index + 1,
@ -267,47 +235,45 @@ void OperationInst::addSuccessorOperand(unsigned index, CFGValue *value) {
++getTrailingObjects<unsigned>()[index]; ++getTrailingObjects<unsigned>()[index];
} }
void OperationInst::addSuccessorOperands(unsigned index, void Instruction::addSuccessorOperands(unsigned index,
ArrayRef<CFGValue *> values) { ArrayRef<CFGValue *> values) {
operands.reserve(operands.size() + values.size()); operands.reserve(operands.size() + values.size());
for (auto *value : values) for (auto *value : values)
addSuccessorOperand(index, value); addSuccessorOperand(index, value);
} }
void llvm::ilist_traits<::mlir::OperationInst>::deleteNode( void llvm::ilist_traits<::mlir::Instruction>::deleteNode(Instruction *inst) {
OperationInst *inst) {
inst->destroy(); inst->destroy();
} }
mlir::BasicBlock * mlir::BasicBlock *
llvm::ilist_traits<::mlir::OperationInst>::getContainingBlock() { llvm::ilist_traits<::mlir::Instruction>::getContainingBlock() {
size_t Offset( size_t Offset(
size_t(&((BasicBlock *)nullptr->*BasicBlock::getSublistAccess(nullptr)))); 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) - return reinterpret_cast<BasicBlock *>(reinterpret_cast<char *>(Anchor) -
Offset); Offset);
} }
/// This is a trait method invoked when an instruction is added to a block. We /// This is a trait method invoked when an instruction is added to a block. We
/// keep the block pointer up to date. /// keep the block pointer up to date.
void llvm::ilist_traits<::mlir::OperationInst>::addNodeToList( void llvm::ilist_traits<::mlir::Instruction>::addNodeToList(Instruction *inst) {
OperationInst *inst) {
assert(!inst->getBlock() && "already in a basic block!"); assert(!inst->getBlock() && "already in a basic block!");
inst->block = getContainingBlock(); inst->block = getContainingBlock();
} }
/// This is a trait method invoked when an instruction is removed from a block. /// This is a trait method invoked when an instruction is removed from a block.
/// We keep the block pointer up to date. /// We keep the block pointer up to date.
void llvm::ilist_traits<::mlir::OperationInst>::removeNodeFromList( void llvm::ilist_traits<::mlir::Instruction>::removeNodeFromList(
OperationInst *inst) { Instruction *inst) {
assert(inst->block && "not already in a basic block!"); assert(inst->block && "not already in a basic block!");
inst->block = nullptr; inst->block = nullptr;
} }
/// This is a trait method invoked when an instruction is moved from one block /// This is a trait method invoked when an instruction is moved from one block
/// to another. We keep the block pointer up to date. /// to another. We keep the block pointer up to date.
void llvm::ilist_traits<::mlir::OperationInst>::transferNodesFromList( void llvm::ilist_traits<::mlir::Instruction>::transferNodesFromList(
ilist_traits<OperationInst> &otherList, instr_iterator first, ilist_traits<Instruction> &otherList, instr_iterator first,
instr_iterator last) { instr_iterator last) {
// If we are transferring instructions within the same basic block, the block // If we are transferring instructions within the same basic block, the block
// pointer doesn't need to be updated. // 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. /// Unlink this instruction from its BasicBlock and delete it.
void OperationInst::erase() { void Instruction::erase() {
assert(getBlock() && "Instruction has no parent"); assert(getBlock() && "Instruction has no parent");
getBlock()->getOperations().erase(this); getBlock()->getOperations().erase(this);
} }
@ -329,15 +295,15 @@ void OperationInst::erase() {
/// Unlink this operation instruction from its current basic block and insert /// Unlink this operation instruction from its current basic block and insert
/// it right before `existingInst` which may be in the same or another block /// it right before `existingInst` which may be in the same or another block
/// in the same function. /// in the same function.
void OperationInst::moveBefore(OperationInst *existingInst) { void Instruction::moveBefore(Instruction *existingInst) {
assert(existingInst && "Cannot move before a null instruction"); assert(existingInst && "Cannot move before a null instruction");
return moveBefore(existingInst->getBlock(), existingInst->getIterator()); return moveBefore(existingInst->getBlock(), existingInst->getIterator());
} }
/// Unlink this operation instruction from its current basic block and insert /// Unlink this operation instruction from its current basic block and insert
/// it right before `iterator` in the specified basic block. /// it right before `iterator` in the specified basic block.
void OperationInst::moveBefore(BasicBlock *block, void Instruction::moveBefore(BasicBlock *block,
llvm::iplist<OperationInst>::iterator iterator) { llvm::iplist<Instruction>::iterator iterator) {
block->getOperations().splice(iterator, getBlock()->getOperations(), block->getOperations().splice(iterator, getBlock()->getOperations(),
getIterator()); getIterator());
} }

View File

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

View File

@ -23,9 +23,9 @@
using namespace mlir; 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. /// that defines it.
OperationInst *SSAValue::getDefiningInst() { Instruction *SSAValue::getDefiningInst() {
if (auto *result = dyn_cast<InstResult>(this)) if (auto *result = dyn_cast<InstResult>(this))
return result->getOwner(); return result->getOwner();
return nullptr; return nullptr;
@ -77,7 +77,7 @@ MLIRContext *IROperandOwner::getContext() const {
case Kind::IfStmt: case Kind::IfStmt:
return cast<IfStmt>(this)->getContext(); return cast<IfStmt>(this)->getContext();
case Kind::OperationInst: case Kind::Instruction:
// If we have an instruction, we can efficiently get this from the function // If we have an instruction, we can efficiently get this from the function
// the instruction is in. // the instruction is in.
auto *fn = cast<Instruction>(this)->getFunction(); 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 // cannot be created through normal user input, allowing us to distinguish
// them. // them.
auto name = OperationName("placeholder", getContext()); auto name = OperationName("placeholder", getContext());
auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name, auto *inst = Instruction::create(getEncodedSourceLocation(loc), name,
/*operands=*/{}, type, /*operands=*/{}, type,
/*attributes=*/{}, /*attributes=*/{},
/*successors=*/{}, getContext()); /*successors=*/{}, getContext());
forwardReferencePlaceholders[inst->getResult(0)] = loc; forwardReferencePlaceholders[inst->getResult(0)] = loc;
return inst->getResult(0); return inst->getResult(0);
} }