blob: 8f64066350e4a43d4f9a5f4f66b4c8df385898aa [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"
Chris Lattner95865062018-08-01 10:18:59 -070019#include "mlir/IR/CFGFunction.h"
Chris Lattner4c95a502018-06-23 16:03:42 -070020using 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'.
Chris Lattner1e9fd7f2018-07-26 08:56:26 -070025void IRObjectWithUseList::replaceAllUsesWith(IRObjectWithUseList *newValue) {
Chris Lattner6119d382018-07-20 18:41:34 -070026 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 Lattner95865062018-08-01 10:18:59 -070072/// Return the context this operation is associated with.
73MLIRContext *Instruction::getContext() const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -070074 auto *fn = getFunction();
75 return fn ? fn->getContext() : nullptr;
Chris Lattner95865062018-08-01 10:18:59 -070076}
77
Chris Lattnered65a732018-06-28 20:45:33 -070078CFGFunction *Instruction::getFunction() const {
Tatiana Shpeismanc335d182018-08-03 11:12:34 -070079 auto *block = getBlock();
80 return block ? block->getFunction() : nullptr;
Chris Lattner4c95a502018-06-23 16:03:42 -070081}
82
Chris Lattner68a3fd02018-07-23 10:08:00 -070083unsigned Instruction::getNumOperands() const {
84 switch (getKind()) {
85 case Kind::Operation:
86 return cast<OperationInst>(this)->getNumOperands();
87 case Kind::Branch:
88 return cast<BranchInst>(this)->getNumOperands();
James Molloy4f788372018-07-24 15:01:27 -070089 case Kind::CondBranch:
90 return cast<CondBranchInst>(this)->getNumOperands();
Chris Lattner68a3fd02018-07-23 10:08:00 -070091 case Kind::Return:
92 return cast<ReturnInst>(this)->getNumOperands();
93 }
94}
95
96MutableArrayRef<InstOperand> Instruction::getInstOperands() {
97 switch (getKind()) {
98 case Kind::Operation:
99 return cast<OperationInst>(this)->getInstOperands();
100 case Kind::Branch:
101 return cast<BranchInst>(this)->getInstOperands();
James Molloy4f788372018-07-24 15:01:27 -0700102 case Kind::CondBranch:
103 return cast<CondBranchInst>(this)->getInstOperands();
Chris Lattner68a3fd02018-07-23 10:08:00 -0700104 case Kind::Return:
105 return cast<ReturnInst>(this)->getInstOperands();
106 }
107}
108
Chris Lattnera8e47672018-07-25 14:08:16 -0700109/// This drops all operand uses from this instruction, which is an essential
110/// step in breaking cyclic dependences between references when they are to
111/// be deleted.
112void Instruction::dropAllReferences() {
113 for (auto &op : getInstOperands())
114 op.drop();
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700115
116 if (auto *term = dyn_cast<TerminatorInst>(this))
Chris Lattner548cd7f2018-07-26 11:30:28 -0700117 for (auto &dest : term->getBasicBlockOperands())
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700118 dest.drop();
Chris Lattnera8e47672018-07-25 14:08:16 -0700119}
120
Chris Lattnered65a732018-06-28 20:45:33 -0700121//===----------------------------------------------------------------------===//
122// OperationInst
123//===----------------------------------------------------------------------===//
124
Chris Lattner3b2ef762018-07-18 15:31:25 -0700125/// Create a new OperationInst with the specific fields.
126OperationInst *OperationInst::create(Identifier name,
127 ArrayRef<CFGValue *> operands,
128 ArrayRef<Type *> resultTypes,
129 ArrayRef<NamedAttribute> attributes,
130 MLIRContext *context) {
131 auto byteSize = totalSizeToAlloc<InstOperand, InstResult>(operands.size(),
132 resultTypes.size());
Chris Lattner6119d382018-07-20 18:41:34 -0700133 void *rawMem = malloc(byteSize);
Chris Lattner3b2ef762018-07-18 15:31:25 -0700134
135 // Initialize the OperationInst part of the instruction.
136 auto inst = ::new (rawMem) OperationInst(
137 name, operands.size(), resultTypes.size(), attributes, context);
138
139 // Initialize the operands and results.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700140 auto instOperands = inst->getInstOperands();
Chris Lattner3b2ef762018-07-18 15:31:25 -0700141 for (unsigned i = 0, e = operands.size(); i != e; ++i)
142 new (&instOperands[i]) InstOperand(inst, operands[i]);
143
Chris Lattnerf8cce872018-07-20 09:28:54 -0700144 auto instResults = inst->getInstResults();
Chris Lattner3b2ef762018-07-18 15:31:25 -0700145 for (unsigned i = 0, e = resultTypes.size(); i != e; ++i)
146 new (&instResults[i]) InstResult(resultTypes[i], inst);
147 return inst;
148}
149
Uday Bondhugula15984952018-08-01 22:36:12 -0700150OperationInst *OperationInst::clone() const {
151 SmallVector<CFGValue *, 8> operands;
152 SmallVector<Type *, 8> resultTypes;
153
154 // TODO(clattner): switch to iterator logic.
155 // Put together the operands and results.
156 for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
157 operands.push_back(getInstOperand(i).get());
158
159 for (unsigned i = 0, e = getNumResults(); i != e; ++i)
160 resultTypes.push_back(getInstResult(i).getType());
161
162 return create(getName(), operands, resultTypes, getAttrs(), getContext());
163}
164
Chris Lattner3b2ef762018-07-18 15:31:25 -0700165OperationInst::OperationInst(Identifier name, unsigned numOperands,
166 unsigned numResults,
167 ArrayRef<NamedAttribute> attributes,
168 MLIRContext *context)
James Molloy4f788372018-07-24 15:01:27 -0700169 : Operation(name, /*isInstruction=*/true, attributes, context),
Chris Lattner55315d52018-07-18 19:06:45 -0700170 Instruction(Kind::Operation), numOperands(numOperands),
171 numResults(numResults) {}
Chris Lattner3b2ef762018-07-18 15:31:25 -0700172
173OperationInst::~OperationInst() {
174 // Explicitly run the destructors for the operands and results.
Chris Lattnerf8cce872018-07-20 09:28:54 -0700175 for (auto &operand : getInstOperands())
Chris Lattner3b2ef762018-07-18 15:31:25 -0700176 operand.~InstOperand();
177
Chris Lattnerf8cce872018-07-20 09:28:54 -0700178 for (auto &result : getInstResults())
Chris Lattner3b2ef762018-07-18 15:31:25 -0700179 result.~InstResult();
180}
181
Chris Lattner3a467cc2018-07-01 20:28:00 -0700182mlir::BasicBlock *
183llvm::ilist_traits<::mlir::OperationInst>::getContainingBlock() {
184 size_t Offset(
185 size_t(&((BasicBlock *)nullptr->*BasicBlock::getSublistAccess(nullptr))));
186 iplist<OperationInst> *Anchor(static_cast<iplist<OperationInst> *>(this));
187 return reinterpret_cast<BasicBlock *>(reinterpret_cast<char *>(Anchor) -
James Molloy4f788372018-07-24 15:01:27 -0700188 Offset);
Chris Lattnered65a732018-06-28 20:45:33 -0700189}
190
Chris Lattner3a467cc2018-07-01 20:28:00 -0700191/// This is a trait method invoked when an instruction is added to a block. We
192/// keep the block pointer up to date.
James Molloy4f788372018-07-24 15:01:27 -0700193void llvm::ilist_traits<::mlir::OperationInst>::addNodeToList(
194 OperationInst *inst) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700195 assert(!inst->getBlock() && "already in a basic block!");
196 inst->block = getContainingBlock();
197}
198
199/// This is a trait method invoked when an instruction is removed from a block.
200/// We keep the block pointer up to date.
James Molloy4f788372018-07-24 15:01:27 -0700201void llvm::ilist_traits<::mlir::OperationInst>::removeNodeFromList(
202 OperationInst *inst) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700203 assert(inst->block && "not already in a basic block!");
204 inst->block = nullptr;
205}
206
207/// This is a trait method invoked when an instruction is moved from one block
208/// to another. We keep the block pointer up to date.
James Molloy4f788372018-07-24 15:01:27 -0700209void llvm::ilist_traits<::mlir::OperationInst>::transferNodesFromList(
210 ilist_traits<OperationInst> &otherList, instr_iterator first,
211 instr_iterator last) {
Chris Lattner3a467cc2018-07-01 20:28:00 -0700212 // If we are transferring instructions within the same basic block, the block
213 // pointer doesn't need to be updated.
214 BasicBlock *curParent = getContainingBlock();
215 if (curParent == otherList.getContainingBlock())
216 return;
217
218 // Update the 'block' member of each instruction.
219 for (; first != last; ++first)
220 first->block = curParent;
221}
222
223/// Unlink this instruction from its BasicBlock and delete it.
224void OperationInst::eraseFromBlock() {
225 assert(getBlock() && "Instruction has no parent");
226 getBlock()->getOperations().erase(this);
227}
228
Chris Lattnered65a732018-06-28 20:45:33 -0700229//===----------------------------------------------------------------------===//
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700230// TerminatorInst
Chris Lattnered65a732018-06-28 20:45:33 -0700231//===----------------------------------------------------------------------===//
232
Chris Lattner3a467cc2018-07-01 20:28:00 -0700233/// Remove this terminator from its BasicBlock and delete it.
234void TerminatorInst::eraseFromBlock() {
235 assert(getBlock() && "Instruction has no parent");
236 getBlock()->setTerminator(nullptr);
Chris Lattner6119d382018-07-20 18:41:34 -0700237 destroy();
Chris Lattner4c95a502018-06-23 16:03:42 -0700238}
239
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700240/// Return the list of destination entries that this terminator branches to.
Chris Lattner548cd7f2018-07-26 11:30:28 -0700241MutableArrayRef<BasicBlockOperand> TerminatorInst::getBasicBlockOperands() {
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700242 switch (getKind()) {
243 case Kind::Operation:
MLIR Team6f8692f2018-07-26 09:23:10 -0700244 llvm_unreachable("not a terminator");
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700245 case Kind::Branch:
Chris Lattner548cd7f2018-07-26 11:30:28 -0700246 return cast<BranchInst>(this)->getBasicBlockOperands();
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700247 case Kind::CondBranch:
Chris Lattner548cd7f2018-07-26 11:30:28 -0700248 return cast<CondBranchInst>(this)->getBasicBlockOperands();
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700249 case Kind::Return:
250 // Return has no basic block successors.
251 return {};
252 }
253}
254
255//===----------------------------------------------------------------------===//
256// ReturnInst
257//===----------------------------------------------------------------------===//
258
Chris Lattner40746442018-07-21 14:32:09 -0700259/// Create a new OperationInst with the specific fields.
260ReturnInst *ReturnInst::create(ArrayRef<CFGValue *> operands) {
261 auto byteSize = totalSizeToAlloc<InstOperand>(operands.size());
262 void *rawMem = malloc(byteSize);
Chris Lattner3a467cc2018-07-01 20:28:00 -0700263
Chris Lattner40746442018-07-21 14:32:09 -0700264 // Initialize the ReturnInst part of the instruction.
265 auto inst = ::new (rawMem) ReturnInst(operands.size());
266
267 // Initialize the operands and results.
268 auto instOperands = inst->getInstOperands();
269 for (unsigned i = 0, e = operands.size(); i != e; ++i)
270 new (&instOperands[i]) InstOperand(inst, operands[i]);
271 return inst;
272}
273
274void ReturnInst::destroy() {
275 this->~ReturnInst();
276 free(this);
277}
278
279ReturnInst::~ReturnInst() {
280 // Explicitly run the destructors for the operands.
281 for (auto &operand : getInstOperands())
282 operand.~InstOperand();
283}
Chris Lattner1604e472018-07-23 08:42:19 -0700284
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700285//===----------------------------------------------------------------------===//
286// BranchInst
287//===----------------------------------------------------------------------===//
288
289BranchInst::BranchInst(BasicBlock *dest)
290 : TerminatorInst(Kind::Branch), dest(this, dest) {}
291
292void BranchInst::setDest(BasicBlock *block) { dest.set(block); }
293
Chris Lattner1604e472018-07-23 08:42:19 -0700294/// Add one value to the operand list.
295void BranchInst::addOperand(CFGValue *value) {
296 operands.emplace_back(InstOperand(this, value));
297}
298
299/// Add a list of values to the operand list.
300void BranchInst::addOperands(ArrayRef<CFGValue *> values) {
301 operands.reserve(operands.size() + values.size());
302 for (auto *value : values)
303 addOperand(value);
304}
James Molloy4f788372018-07-24 15:01:27 -0700305
Chris Lattner1e9fd7f2018-07-26 08:56:26 -0700306//===----------------------------------------------------------------------===//
307// CondBranchInst
308//===----------------------------------------------------------------------===//
309
310CondBranchInst::CondBranchInst(CFGValue *condition, BasicBlock *trueDest,
311 BasicBlock *falseDest)
312 : TerminatorInst(Kind::CondBranch),
313 condition(condition), dests{{this}, {this}}, numTrueOperands(0) {
314 dests[falseIndex].set(falseDest);
315 dests[trueIndex].set(trueDest);
316}
317
James Molloy4f788372018-07-24 15:01:27 -0700318/// Add one value to the true operand list.
319void CondBranchInst::addTrueOperand(CFGValue *value) {
320 assert(getNumFalseOperands() == 0 &&
321 "Must insert all true operands before false operands!");
322 operands.emplace_back(InstOperand(this, value));
323 ++numTrueOperands;
324}
325
326/// Add a list of values to the true operand list.
327void CondBranchInst::addTrueOperands(ArrayRef<CFGValue *> values) {
328 operands.reserve(operands.size() + values.size());
329 for (auto *value : values)
330 addTrueOperand(value);
331}
332
333/// Add one value to the false operand list.
334void CondBranchInst::addFalseOperand(CFGValue *value) {
335 operands.emplace_back(InstOperand(this, value));
336}
337
338/// Add a list of values to the false operand list.
339void CondBranchInst::addFalseOperands(ArrayRef<CFGValue *> values) {
340 operands.reserve(operands.size() + values.size());
341 for (auto *value : values)
342 addFalseOperand(value);
343}