blob: 104ff2efe5dc93cf039c6bbd3811fcda8cb51ddf [file] [log] [blame]
Chris Lattnerff0d5902018-07-05 09:12:11 -07001//===- StandardOps.cpp - Standard MLIR Operations -------------------------===//
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/StandardOps.h"
MLIR Team3fa00ab2018-07-24 10:13:31 -070019#include "mlir/IR/AffineMap.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070020#include "mlir/IR/Builders.h"
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070021#include "mlir/IR/OpImplementation.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070022#include "mlir/IR/OperationSet.h"
Chris Lattner9361fb32018-07-24 08:34:58 -070023#include "mlir/IR/SSAValue.h"
24#include "mlir/IR/Types.h"
Chris Lattnerff0d5902018-07-05 09:12:11 -070025#include "llvm/Support/raw_ostream.h"
26using namespace mlir;
27
MLIR Team39a3a602018-07-24 17:43:56 -070028// TODO: Have verify functions return std::string to enable more descriptive
29// error messages.
Chris Lattner85ee1512018-07-25 11:15:20 -070030OpAsmParserResult AddFOp::parse(OpAsmParser *parser) {
31 SmallVector<OpAsmParser::OperandType, 2> ops;
32 Type *type;
33 SSAValue *lhs, *rhs;
34 if (parser->parseOperandList(ops, 2) || parser->parseColonType(type) ||
35 parser->resolveOperand(ops[0], type, lhs) ||
36 parser->resolveOperand(ops[1], type, rhs))
37 return {};
38
39 return OpAsmParserResult({lhs, rhs}, type);
40}
41
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070042void AddFOp::print(OpAsmPrinter *p) const {
43 *p << "addf " << *getOperand(0) << ", " << *getOperand(1) << " : "
44 << *getType();
Chris Lattnerff0d5902018-07-05 09:12:11 -070045}
46
Chris Lattner21e67f62018-07-06 10:46:19 -070047// Return an error message on failure.
48const char *AddFOp::verify() const {
49 // TODO: Check that the types of the LHS and RHS match.
50 // TODO: This should be a refinement of TwoOperands.
51 // TODO: There should also be a OneResultWhoseTypeMatchesFirstOperand.
52 return nullptr;
53}
54
Chris Lattner9361fb32018-07-24 08:34:58 -070055/// The constant op requires an attribute, and furthermore requires that it
56/// matches the return type.
57const char *ConstantOp::verify() const {
58 auto *value = getValue();
59 if (!value)
60 return "requires a 'value' attribute";
61
62 auto *type = this->getType();
Chris Lattner1ec70572018-07-24 10:41:30 -070063 if (isa<IntegerType>(type) || type->isAffineInt()) {
Chris Lattner9361fb32018-07-24 08:34:58 -070064 if (!isa<IntegerAttr>(value))
65 return "requires 'value' to be an integer for an integer result type";
66 return nullptr;
67 }
68
69 if (isa<FunctionType>(type)) {
70 // TODO: Verify a function attr.
71 }
72
73 return "requires a result type that aligns with the 'value' attribute";
74}
75
Chris Lattner3da86ad2018-07-26 09:58:23 -070076/// ConstantIntOp only matches values whose result type is an IntegerType or
77/// AffineInt.
Chris Lattner9361fb32018-07-24 08:34:58 -070078bool ConstantIntOp::isClassFor(const Operation *op) {
79 return ConstantOp::isClassFor(op) &&
Chris Lattner3da86ad2018-07-26 09:58:23 -070080 (isa<IntegerType>(op->getResult(0)->getType()) ||
81 op->getResult(0)->getType()->isAffineInt());
Chris Lattner9361fb32018-07-24 08:34:58 -070082}
83
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -070084void DimOp::print(OpAsmPrinter *p) const {
85 *p << "dim " << *getOperand() << ", " << getIndex() << " : "
86 << *getOperand()->getType();
Chris Lattnerff0d5902018-07-05 09:12:11 -070087}
88
Chris Lattner85ee1512018-07-25 11:15:20 -070089OpAsmParserResult DimOp::parse(OpAsmParser *parser) {
90 OpAsmParser::OperandType operandInfo;
91 IntegerAttr *indexAttr;
92 Type *type;
93 SSAValue *operand;
94 if (parser->parseOperand(operandInfo) || parser->parseComma() ||
95 parser->parseAttribute(indexAttr) || parser->parseColonType(type) ||
96 parser->resolveOperand(operandInfo, type, operand))
97 return {};
98
99 auto &builder = parser->getBuilder();
100 return OpAsmParserResult(
101 operand, builder.getAffineIntType(),
102 NamedAttribute(builder.getIdentifier("index"), indexAttr));
103}
104
Chris Lattner21e67f62018-07-06 10:46:19 -0700105const char *DimOp::verify() const {
Chris Lattner21e67f62018-07-06 10:46:19 -0700106 // Check that we have an integer index operand.
107 auto indexAttr = getAttrOfType<IntegerAttr>("index");
108 if (!indexAttr)
Chris Lattner9361fb32018-07-24 08:34:58 -0700109 return "requires an integer attribute named 'index'";
110 uint64_t index = (uint64_t)indexAttr->getValue();
Chris Lattner21e67f62018-07-06 10:46:19 -0700111
Chris Lattner9361fb32018-07-24 08:34:58 -0700112 auto *type = getOperand()->getType();
113 if (auto *tensorType = dyn_cast<RankedTensorType>(type)) {
114 if (index >= tensorType->getRank())
115 return "index is out of range";
116 } else if (auto *memrefType = dyn_cast<MemRefType>(type)) {
117 if (index >= memrefType->getRank())
118 return "index is out of range";
119
120 } else if (isa<UnrankedTensorType>(type)) {
121 // ok, assumed to be in-range.
122 } else {
123 return "requires an operand with tensor or memref type";
124 }
Chris Lattner21e67f62018-07-06 10:46:19 -0700125
126 return nullptr;
127}
128
Chris Lattner85ee1512018-07-25 11:15:20 -0700129void LoadOp::print(OpAsmPrinter *p) const {
130 *p << "load " << *getMemRef() << '[';
131 p->printOperands(getIndices());
132 *p << "] : " << *getMemRef()->getType();
133}
134
135OpAsmParserResult LoadOp::parse(OpAsmParser *parser) {
136 OpAsmParser::OperandType memrefInfo;
137 SmallVector<OpAsmParser::OperandType, 4> indexInfo;
138 MemRefType *type;
139 SmallVector<SSAValue *, 4> operands;
140
141 auto affineIntTy = parser->getBuilder().getAffineIntType();
142 if (parser->parseOperand(memrefInfo) ||
143 parser->parseOperandList(indexInfo, -1,
144 OpAsmParser::Delimeter::SquareDelimeter) ||
145 parser->parseColonType(type) ||
146 parser->resolveOperands(memrefInfo, type, operands) ||
147 parser->resolveOperands(indexInfo, affineIntTy, operands))
148 return {};
149
150 return OpAsmParserResult(operands, type->getElementType());
151}
152
153const char *LoadOp::verify() const {
154 // TODO: Check load
155 return nullptr;
156}
157
Chris Lattnerdd0c2ca2018-07-24 16:07:22 -0700158void AffineApplyOp::print(OpAsmPrinter *p) const {
159 // TODO: Print operands etc.
160 *p << "affine_apply map: " << *getAffineMap();
MLIR Team3fa00ab2018-07-24 10:13:31 -0700161}
162
163const char *AffineApplyOp::verify() const {
MLIR Team3fa00ab2018-07-24 10:13:31 -0700164 // Check that affine map attribute was specified
165 auto affineMapAttr = getAttrOfType<AffineMapAttr>("map");
166 if (!affineMapAttr)
167 return "requires an affine map.";
168
MLIR Team39a3a602018-07-24 17:43:56 -0700169 // Check input and output dimensions match.
170 auto *map = affineMapAttr->getValue();
171
172 // Verify that operand count matches affine map dimension and symbol count.
173 if (getNumOperands() != map->getNumDims() + map->getNumSymbols())
174 return "operand count and affine map dimension and symbol count must match";
175
176 // Verify that result count matches affine map result count.
177 if (getNumResults() != map->getNumResults())
178 return "result count and affine map result count must match";
179
MLIR Team3fa00ab2018-07-24 10:13:31 -0700180 return nullptr;
181}
182
Chris Lattnerff0d5902018-07-05 09:12:11 -0700183/// Install the standard operations in the specified operation set.
184void mlir::registerStandardOperations(OperationSet &opSet) {
Chris Lattner85ee1512018-07-25 11:15:20 -0700185 opSet.addOperations<AddFOp, ConstantOp, DimOp, LoadOp, AffineApplyOp>(
186 /*prefix=*/"");
Chris Lattnerff0d5902018-07-05 09:12:11 -0700187}