blob: a1cdcb3dc33e79eb4c86af7df6925aabeb65f529 [file] [log] [blame]
Chris Lattner4c95a502018-06-23 16:03:42 -07001//===- Instructions.cpp - MLIR CFGFunction Instruction Classes ------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17
18#include "mlir/IR/Instructions.h"
19#include "mlir/IR/BasicBlock.h"
20using namespace mlir;
21
Chris Lattner6119d382018-07-20 18:41:34 -070022/// Replace all uses of 'this' value with the new value, updating anything in
23/// the IR that uses 'this' to use the other value instead. When this returns
24/// there are zero uses of 'this'.
25void SSAValue::replaceAllUsesWith(SSAValue *newValue) {
26 assert(this != newValue && "cannot RAUW a value with itself");
27 while (!use_empty()) {
28 use_begin()->set(newValue);
29 }
30}
31
32/// Return the result number of this result.
33unsigned InstResult::getResultNumber() const {
34 // Results are always stored consecutively, so use pointer subtraction to
35 // figure out what number this is.
36 return this - &getOwner()->getInstResults()[0];
37}
38
Chris Lattnered65a732018-06-28 20:45:33 -070039//===----------------------------------------------------------------------===//
40// Instruction
41//===----------------------------------------------------------------------===//
42
Chris Lattner3a467cc2018-07-01 20:28:00 -070043// Instructions are deleted through the destroy() member because we don't have
44// a virtual destructor.
45Instruction::~Instruction() {
46 assert(block == nullptr && "instruction destroyed but still in a block");
47}
48
49/// Destroy this instruction or one of its subclasses.
Chris Lattner6119d382018-07-20 18:41:34 -070050void Instruction::destroy() {
51 switch (getKind()) {
Chris Lattner3a467cc2018-07-01 20:28:00 -070052 case Kind::Operation:
Chris Lattner6119d382018-07-20 18:41:34 -070053 cast<OperationInst>(this)->destroy();
Chris Lattner3a467cc2018-07-01 20:28:00 -070054 break;
55 case Kind::Branch:
Chris Lattner6119d382018-07-20 18:41:34 -070056 delete cast<BranchInst>(this);
Chris Lattner3a467cc2018-07-01 20:28:00 -070057 break;
James Molloy4f788372018-07-24 15:01:27 -070058 case Kind::CondBranch:
59 delete cast<CondBranchInst>(this);
60 break;
Chris Lattner3a467cc2018-07-01 20:28:00 -070061 case Kind::Return:
Chris Lattner40746442018-07-21 14:32:09 -070062 cast<ReturnInst>(this)->destroy();
Chris Lattner3a467cc2018-07-01 20:28:00 -070063 break;
64 }
65}
66
Chris Lattner6119d382018-07-20 18:41:34 -070067void OperationInst::destroy() {
68 this->~OperationInst();
69 free(this);
70}
71
Chris Lattnered65a732018-06-28 20:45:33 -070072CFGFunction *Instruction::getFunction() const {
Chris Lattner4c95a502018-06-23 16:03:42 -070073 return getBlock()->getFunction();
74}
75
Chris Lattner68a3fd02018-07-23 10:08:00 -070076unsigned Instruction::getNumOperands() const {
77 switch (getKind()) {
78 case Kind::Operation:
79 return cast<OperationInst>(this)->getNumOperands();
80 case Kind::Branch:
81 return cast<BranchInst>(this)->getNumOperands();
James Molloy4f788372018-07-24 15:01:27 -070082 case Kind::CondBranch:
83 return cast<CondBranchInst>(this)->getNumOperands();
Chris Lattner68a3fd02018-07-23 10:08:00 -070084 case Kind::Return:
85 return cast<ReturnInst>(this)->getNumOperands();
86 }
87}
88
89MutableArrayRef<InstOperand> Instruction::getInstOperands() {
90 switch (getKind()) {
91 case Kind::Operation:
92 return cast<OperationInst>(this)->getInstOperands();
93 case Kind::Branch:
94 return cast<BranchInst>(this)->getInstOperands();
James Molloy4f788372018-07-24 15:01:27 -070095 case Kind::CondBranch:
96 return cast<CondBranchInst>(this)->getInstOperands();
Chris Lattner68a3fd02018-07-23 10:08:00 -070097 case Kind::Return:
98 return cast<ReturnInst>(this)->getInstOperands();
99 }
100}
101
Chris Lattnera8e47672018-07-25 14:08:16 -0700102/// This drops all operand uses from this instruction, which is an essential
103/// step in breaking cyclic dependences between references when they are to
104/// be deleted.
105void Instruction::dropAllReferences() {
106 for (auto &op : getInstOperands())
107 op.drop();
108}
109
Chris Lattnered65a732018-06-28 20:45:33 -0700110//===----------------------------------------------------------------------===//
111// OperationInst
112//===----------------------------------------------------------------------===//
113
Chris Lattner3b2ef762018-07-18 15:31:25 -0700114/// Create a new OperationInst with the specific fields.
115OperationInst *OperationInst::create(Identifier name,
116 ArrayRef<CFGValue *> operands,
117 ArrayRef<Type *> resultTypes,
118 ArrayRef<NamedAttribute> attributes,
119 MLIRContext *context) {
120 auto byteSize = totalSizeToAlloc<InstOperand, InstResult>(operands.size(),
121 resultTypes.size());
Chris Lattner6119d382018-07-20 18:41:34 -0700122 void *rawMem = malloc(byteSize);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700123
124 // Initialize the OperationInst part of the instruction.
125 auto inst = ::new (rawMem) OperationInst(
126 name, operands.size(), resultTypes.size(), attributes, context);
127
128 // Initialize the operands and results.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700129 auto instOperands = inst->getInstOperands();
Chris Lattner3b2ef762018-07-18 15:31:25 -0700130 for (unsigned i = 0, e = operands.size(); i != e; ++i)
131 new (&instOperands[i]) InstOperand(inst, operands[i]);
132
Chris Lattnerf8cce872018-07-20 09:28:54 -0700133 auto instResults = inst->getInstResults();
Chris Lattner3b2ef762018-07-18 15:31:25 -0700134 for (unsigned i = 0, e = resultTypes.size(); i != e; ++i)
135 new (&instResults[i]) InstResult(resultTypes[i], inst);
136 return inst;
137}
138
139OperationInst::OperationInst(Identifier name, unsigned numOperands,
140 unsigned numResults,
141 ArrayRef<NamedAttribute> attributes,
142 MLIRContext *context)
James Molloy4f788372018-07-24 15:01:27 -0700143 : Operation(name, /*isInstruction=*/true, attributes, context),
Chris Lattner55315d52018-07-18 19:06:45 -0700144 Instruction(Kind::Operation), numOperands(numOperands),
145 numResults(numResults) {}
Chris Lattner3b2ef762018-07-18 15:31:25 -0700146
147OperationInst::~OperationInst() {
148 // Explicitly run the destructors for the operands and results.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700149 for (auto &operand : getInstOperands())
Chris Lattner3b2ef762018-07-18 15:31:25 -0700150 operand.~InstOperand();
151
Chris Lattnerf8cce872018-07-20 09:28:54 -0700152 for (auto &result : getInstResults())
Chris Lattner3b2ef762018-07-18 15:31:25 -0700153 result.~InstResult();
154}
155
Chris Lattner3a467cc2018-07-01 20:28:00 -0700156mlir::BasicBlock *
157llvm::ilist_traits<::mlir::OperationInst>::getContainingBlock() {
158 size_t Offset(
159 size_t(&((BasicBlock *)nullptr->*BasicBlock::getSublistAccess(nullptr))));
160 iplist<OperationInst> *Anchor(static_cast<iplist<OperationInst> *>(this));
161 return reinterpret_cast<BasicBlock *>(reinterpret_cast<char *>(Anchor) -
James Molloy4f788372018-07-24 15:01:27 -0700162 Offset);
Chris Lattnered65a732018-06-28 20:45:33 -0700163}
164
Chris Lattner3a467cc2018-07-01 20:28:00 -0700165/// This is a trait method invoked when an instruction is added to a block. We
166/// keep the block pointer up to date.
James Molloy4f788372018-07-24 15:01:27 -0700167void llvm::ilist_traits<::mlir::OperationInst>::addNodeToList(
168 OperationInst *inst) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700169 assert(!inst->getBlock() && "already in a basic block!");
170 inst->block = getContainingBlock();
171}
172
173/// This is a trait method invoked when an instruction is removed from a block.
174/// We keep the block pointer up to date.
James Molloy4f788372018-07-24 15:01:27 -0700175void llvm::ilist_traits<::mlir::OperationInst>::removeNodeFromList(
176 OperationInst *inst) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700177 assert(inst->block && "not already in a basic block!");
178 inst->block = nullptr;
179}
180
181/// This is a trait method invoked when an instruction is moved from one block
182/// to another. We keep the block pointer up to date.
James Molloy4f788372018-07-24 15:01:27 -0700183void llvm::ilist_traits<::mlir::OperationInst>::transferNodesFromList(
184 ilist_traits<OperationInst> &otherList, instr_iterator first,
185 instr_iterator last) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700186 // If we are transferring instructions within the same basic block, the block
187 // pointer doesn't need to be updated.
188 BasicBlock *curParent = getContainingBlock();
189 if (curParent == otherList.getContainingBlock())
190 return;
191
192 // Update the 'block' member of each instruction.
193 for (; first != last; ++first)
194 first->block = curParent;
195}
196
197/// Unlink this instruction from its BasicBlock and delete it.
198void OperationInst::eraseFromBlock() {
199 assert(getBlock() && "Instruction has no parent");
200 getBlock()->getOperations().erase(this);
201}
202
Chris Lattner6119d382018-07-20 18:41:34 -0700203/// If this value is the result of an OperationInst, return the instruction
204/// that defines it.
205OperationInst *SSAValue::getDefiningInst() {
206 if (auto *result = dyn_cast<InstResult>(this))
207 return result->getOwner();
208 return nullptr;
209}
210
Chris Lattnered65a732018-06-28 20:45:33 -0700211//===----------------------------------------------------------------------===//
212// Terminators
213//===----------------------------------------------------------------------===//
214
Chris Lattner3a467cc2018-07-01 20:28:00 -0700215/// Remove this terminator from its BasicBlock and delete it.
216void TerminatorInst::eraseFromBlock() {
217 assert(getBlock() && "Instruction has no parent");
218 getBlock()->setTerminator(nullptr);
Chris Lattner6119d382018-07-20 18:41:34 -0700219 destroy();
Chris Lattner4c95a502018-06-23 16:03:42 -0700220}
221
Chris Lattner40746442018-07-21 14:32:09 -0700222/// Create a new OperationInst with the specific fields.
223ReturnInst *ReturnInst::create(ArrayRef<CFGValue *> operands) {
224 auto byteSize = totalSizeToAlloc<InstOperand>(operands.size());
225 void *rawMem = malloc(byteSize);
Chris Lattner3a467cc2018-07-01 20:28:00 -0700226
Chris Lattner40746442018-07-21 14:32:09 -0700227 // Initialize the ReturnInst part of the instruction.
228 auto inst = ::new (rawMem) ReturnInst(operands.size());
229
230 // Initialize the operands and results.
231 auto instOperands = inst->getInstOperands();
232 for (unsigned i = 0, e = operands.size(); i != e; ++i)
233 new (&instOperands[i]) InstOperand(inst, operands[i]);
234 return inst;
235}
236
237void ReturnInst::destroy() {
238 this->~ReturnInst();
239 free(this);
240}
241
242ReturnInst::~ReturnInst() {
243 // Explicitly run the destructors for the operands.
244 for (auto &operand : getInstOperands())
245 operand.~InstOperand();
246}
Chris Lattner1604e472018-07-23 08:42:19 -0700247
248/// Add one value to the operand list.
249void BranchInst::addOperand(CFGValue *value) {
250 operands.emplace_back(InstOperand(this, value));
251}
252
253/// Add a list of values to the operand list.
254void BranchInst::addOperands(ArrayRef<CFGValue *> values) {
255 operands.reserve(operands.size() + values.size());
256 for (auto *value : values)
257 addOperand(value);
258}
James Molloy4f788372018-07-24 15:01:27 -0700259
260/// Add one value to the true operand list.
261void CondBranchInst::addTrueOperand(CFGValue *value) {
262 assert(getNumFalseOperands() == 0 &&
263 "Must insert all true operands before false operands!");
264 operands.emplace_back(InstOperand(this, value));
265 ++numTrueOperands;
266}
267
268/// Add a list of values to the true operand list.
269void CondBranchInst::addTrueOperands(ArrayRef<CFGValue *> values) {
270 operands.reserve(operands.size() + values.size());
271 for (auto *value : values)
272 addTrueOperand(value);
273}
274
275/// Add one value to the false operand list.
276void CondBranchInst::addFalseOperand(CFGValue *value) {
277 operands.emplace_back(InstOperand(this, value));
278}
279
280/// Add a list of values to the false operand list.
281void CondBranchInst::addFalseOperands(ArrayRef<CFGValue *> values) {
282 operands.reserve(operands.size() + values.size());
283 for (auto *value : values)
284 addFalseOperand(value);
285}