1319072f4SAart Bik //===- SparseTensorDialect.cpp - Sparse tensor dialect implementation -----===// 2319072f4SAart Bik // 3319072f4SAart Bik // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4319072f4SAart Bik // See https://llvm.org/LICENSE.txt for license information. 5319072f4SAart Bik // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6319072f4SAart Bik // 7319072f4SAart Bik //===----------------------------------------------------------------------===// 8319072f4SAart Bik 9319072f4SAart Bik #include "mlir/Dialect/SparseTensor/IR/SparseTensor.h" 105517208dSAart Bik 11319072f4SAart Bik #include "mlir/IR/Builders.h" 120a292199SAart Bik #include "mlir/IR/DialectImplementation.h" 1365e7cd13SRiver Riddle #include "mlir/IR/Matchers.h" 14319072f4SAart Bik #include "mlir/IR/OpImplementation.h" 150a292199SAart Bik #include "llvm/ADT/TypeSwitch.h" 16319072f4SAart Bik 17319072f4SAart Bik using namespace mlir; 18319072f4SAart Bik using namespace mlir::sparse_tensor; 19319072f4SAart Bik 200a292199SAart Bik //===----------------------------------------------------------------------===// 2196a23911SAart Bik // TensorDialect Attribute Methods. 220a292199SAart Bik //===----------------------------------------------------------------------===// 230a292199SAart Bik 240a292199SAart Bik #define GET_ATTRDEF_CLASSES 250a292199SAart Bik #include "mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.cpp.inc" 260a292199SAart Bik 270a292199SAart Bik static bool acceptBitWidth(unsigned bitWidth) { 280a292199SAart Bik switch (bitWidth) { 290a292199SAart Bik case 0: 300a292199SAart Bik case 8: 310a292199SAart Bik case 16: 320a292199SAart Bik case 32: 330a292199SAart Bik case 64: 340a292199SAart Bik return true; 350a292199SAart Bik default: 360a292199SAart Bik return false; 370a292199SAart Bik } 380a292199SAart Bik } 390a292199SAart Bik 40f97e72aaSMehdi Amini Attribute SparseTensorEncodingAttr::parse(AsmParser &parser, Type type) { 410a292199SAart Bik if (failed(parser.parseLess())) 420a292199SAart Bik return {}; 430a292199SAart Bik // Parse the data as a dictionary. 440a292199SAart Bik DictionaryAttr dict; 450a292199SAart Bik if (failed(parser.parseAttribute(dict))) 460a292199SAart Bik return {}; 470a292199SAart Bik if (failed(parser.parseGreater())) 480a292199SAart Bik return {}; 490a292199SAart Bik // Process the data from the parsed dictionary value into struct-like data. 500a292199SAart Bik SmallVector<SparseTensorEncodingAttr::DimLevelType, 4> dlt; 510a292199SAart Bik AffineMap map = {}; 520a292199SAart Bik unsigned ptr = 0; 530a292199SAart Bik unsigned ind = 0; 540a292199SAart Bik for (const NamedAttribute &attr : dict) { 550c7890c8SRiver Riddle if (attr.getName() == "dimLevelType") { 560c7890c8SRiver Riddle auto arrayAttr = attr.getValue().dyn_cast<ArrayAttr>(); 570a292199SAart Bik if (!arrayAttr) { 580a292199SAart Bik parser.emitError(parser.getNameLoc(), 590a292199SAart Bik "expected an array for dimension level types"); 600a292199SAart Bik return {}; 610a292199SAart Bik } 62e5639b3fSMehdi Amini for (auto i : arrayAttr) { 63e5639b3fSMehdi Amini auto strAttr = i.dyn_cast<StringAttr>(); 640a292199SAart Bik if (!strAttr) { 650a292199SAart Bik parser.emitError(parser.getNameLoc(), 660a292199SAart Bik "expected a string value in dimension level types"); 670a292199SAart Bik return {}; 680a292199SAart Bik } 690a292199SAart Bik auto strVal = strAttr.getValue(); 700a292199SAart Bik if (strVal == "dense") { 710a292199SAart Bik dlt.push_back(SparseTensorEncodingAttr::DimLevelType::Dense); 720a292199SAart Bik } else if (strVal == "compressed") { 730a292199SAart Bik dlt.push_back(SparseTensorEncodingAttr::DimLevelType::Compressed); 740a292199SAart Bik } else if (strVal == "singleton") { 750a292199SAart Bik dlt.push_back(SparseTensorEncodingAttr::DimLevelType::Singleton); 760a292199SAart Bik } else { 770a292199SAart Bik parser.emitError(parser.getNameLoc(), 780a292199SAart Bik "unexpected dimension level type: ") 790a292199SAart Bik << strVal; 800a292199SAart Bik return {}; 810a292199SAart Bik } 820a292199SAart Bik } 830c7890c8SRiver Riddle } else if (attr.getName() == "dimOrdering") { 840c7890c8SRiver Riddle auto affineAttr = attr.getValue().dyn_cast<AffineMapAttr>(); 850a292199SAart Bik if (!affineAttr) { 860a292199SAart Bik parser.emitError(parser.getNameLoc(), 870a292199SAart Bik "expected an affine map for dimension ordering"); 880a292199SAart Bik return {}; 890a292199SAart Bik } 900a292199SAart Bik map = affineAttr.getValue(); 910c7890c8SRiver Riddle } else if (attr.getName() == "pointerBitWidth") { 920c7890c8SRiver Riddle auto intAttr = attr.getValue().dyn_cast<IntegerAttr>(); 930a292199SAart Bik if (!intAttr) { 940a292199SAart Bik parser.emitError(parser.getNameLoc(), 950a292199SAart Bik "expected an integral pointer bitwidth"); 960a292199SAart Bik return {}; 970a292199SAart Bik } 980a292199SAart Bik ptr = intAttr.getInt(); 990c7890c8SRiver Riddle } else if (attr.getName() == "indexBitWidth") { 1000c7890c8SRiver Riddle auto intAttr = attr.getValue().dyn_cast<IntegerAttr>(); 1010a292199SAart Bik if (!intAttr) { 1020a292199SAart Bik parser.emitError(parser.getNameLoc(), 1030a292199SAart Bik "expected an integral index bitwidth"); 1040a292199SAart Bik return {}; 1050a292199SAart Bik } 1060a292199SAart Bik ind = intAttr.getInt(); 1070a292199SAart Bik } else { 1080a292199SAart Bik parser.emitError(parser.getNameLoc(), "unexpected key: ") 1090c7890c8SRiver Riddle << attr.getName().strref(); 1100a292199SAart Bik return {}; 1110a292199SAart Bik } 1120a292199SAart Bik } 1130a292199SAart Bik // Construct struct-like storage for attribute. 114fb093c83SChris Lattner return parser.getChecked<SparseTensorEncodingAttr>(parser.getContext(), dlt, 115fb093c83SChris Lattner map, ptr, ind); 1160a292199SAart Bik } 1170a292199SAart Bik 118f97e72aaSMehdi Amini void SparseTensorEncodingAttr::print(AsmPrinter &printer) const { 1190a292199SAart Bik // Print the struct-like storage in dictionary fashion. 120f30a8a6fSMehdi Amini printer << "<{ dimLevelType = [ "; 1210a292199SAart Bik for (unsigned i = 0, e = getDimLevelType().size(); i < e; i++) { 1220a292199SAart Bik switch (getDimLevelType()[i]) { 1230a292199SAart Bik case DimLevelType::Dense: 1240a292199SAart Bik printer << "\"dense\""; 1250a292199SAart Bik break; 1260a292199SAart Bik case DimLevelType::Compressed: 1270a292199SAart Bik printer << "\"compressed\""; 1280a292199SAart Bik break; 1290a292199SAart Bik case DimLevelType::Singleton: 1300a292199SAart Bik printer << "\"singleton\""; 1310a292199SAart Bik break; 1320a292199SAart Bik } 1330a292199SAart Bik if (i != e - 1) 1340a292199SAart Bik printer << ", "; 1350a292199SAart Bik } 1360a292199SAart Bik printer << " ]"; 1370a292199SAart Bik if (getDimOrdering()) 1380a292199SAart Bik printer << ", dimOrdering = affine_map<" << getDimOrdering() << ">"; 1390a292199SAart Bik printer << ", pointerBitWidth = " << getPointerBitWidth() 1400a292199SAart Bik << ", indexBitWidth = " << getIndexBitWidth() << " }>"; 1410a292199SAart Bik } 1420a292199SAart Bik 1430a292199SAart Bik LogicalResult SparseTensorEncodingAttr::verify( 1440a292199SAart Bik function_ref<InFlightDiagnostic()> emitError, 1450a292199SAart Bik ArrayRef<DimLevelType> dimLevelType, AffineMap dimOrdering, 1460a292199SAart Bik unsigned pointerBitWidth, unsigned indexBitWidth) { 1470a292199SAart Bik if (!acceptBitWidth(pointerBitWidth)) 1480a292199SAart Bik return emitError() << "unexpected pointer bitwidth: " << pointerBitWidth; 1490a292199SAart Bik if (!acceptBitWidth(indexBitWidth)) 1500a292199SAart Bik return emitError() << "unexpected index bitwidth: " << indexBitWidth; 1510a292199SAart Bik if (dimOrdering) { 1520a292199SAart Bik if (!dimOrdering.isPermutation()) 1530a292199SAart Bik return emitError() 1540a292199SAart Bik << "expected a permutation affine map for dimension ordering"; 1550a292199SAart Bik if (dimOrdering.getNumResults() != dimLevelType.size()) 1560a292199SAart Bik return emitError() << "unexpected mismatch in ordering and dimension " 1570a292199SAart Bik "level types size"; 1580a292199SAart Bik } 1590a292199SAart Bik return success(); 1600a292199SAart Bik } 1610a292199SAart Bik 1620a292199SAart Bik LogicalResult SparseTensorEncodingAttr::verifyEncoding( 1630a292199SAart Bik ArrayRef<int64_t> shape, Type elementType, 1640a292199SAart Bik function_ref<InFlightDiagnostic()> emitError) const { 1650a292199SAart Bik // Check structural integrity. 1660a292199SAart Bik if (failed(verify(emitError, getDimLevelType(), getDimOrdering(), 1670a292199SAart Bik getPointerBitWidth(), getIndexBitWidth()))) 1680a292199SAart Bik return failure(); 1690a292199SAart Bik // Check integrity with tensor type specifics. Dimension ordering is optional, 1700a292199SAart Bik // but we always should have dimension level types for the full rank. 1710a292199SAart Bik unsigned size = shape.size(); 1724aa9b398SAart Bik if (size == 0) 1734aa9b398SAart Bik return emitError() << "expected non-scalar sparse tensor"; 1740a292199SAart Bik if (getDimOrdering() && getDimOrdering().getNumResults() != size) 1750a292199SAart Bik return emitError() << "expected an affine map of size " << size 1760a292199SAart Bik << " for dimension ordering"; 1770a292199SAart Bik if (getDimLevelType().size() != size) 1780a292199SAart Bik return emitError() << "expected an array of size " << size 1790a292199SAart Bik << " for dimension level types"; 1800a292199SAart Bik return success(); 1810a292199SAart Bik } 1820a292199SAart Bik 18396a23911SAart Bik SparseTensorEncodingAttr 18496a23911SAart Bik mlir::sparse_tensor::getSparseTensorEncoding(Type type) { 18596a23911SAart Bik if (auto ttp = type.dyn_cast<RankedTensorType>()) 18696a23911SAart Bik return ttp.getEncoding().dyn_cast_or_null<SparseTensorEncodingAttr>(); 18796a23911SAart Bik return nullptr; 18896a23911SAart Bik } 18996a23911SAart Bik 1900a292199SAart Bik //===----------------------------------------------------------------------===// 19196a23911SAart Bik // TensorDialect Operations. 19296a23911SAart Bik //===----------------------------------------------------------------------===// 19396a23911SAart Bik 19496a23911SAart Bik static LogicalResult isInBounds(Value dim, Value tensor) { 19565e7cd13SRiver Riddle IntegerAttr constantAttr; 19665e7cd13SRiver Riddle if (matchPattern(dim, m_Constant(&constantAttr))) { 19765e7cd13SRiver Riddle unsigned d = constantAttr.getInt(); 19896a23911SAart Bik if (d >= tensor.getType().cast<RankedTensorType>().getRank()) 19996a23911SAart Bik return failure(); 20096a23911SAart Bik } 20196a23911SAart Bik return success(); // in bounds, or symbolic 20296a23911SAart Bik } 20396a23911SAart Bik 20496a23911SAart Bik static LogicalResult isMatchingWidth(Value result, unsigned width) { 20596a23911SAart Bik Type etp = result.getType().cast<MemRefType>().getElementType(); 20696a23911SAart Bik if ((width == 0 && etp.isIndex()) || (width > 0 && etp.isInteger(width))) 20796a23911SAart Bik return success(); 20896a23911SAart Bik return failure(); 20996a23911SAart Bik } 21096a23911SAart Bik 211b98dc035SRiver Riddle LogicalResult NewOp::verify() { 212b98dc035SRiver Riddle if (!getSparseTensorEncoding(result().getType())) 213b98dc035SRiver Riddle return emitError("expected a sparse tensor result"); 21496a23911SAart Bik return success(); 21596a23911SAart Bik } 21696a23911SAart Bik 217b98dc035SRiver Riddle LogicalResult InitOp::verify() { 218b98dc035SRiver Riddle if (!getSparseTensorEncoding(result().getType())) 219b98dc035SRiver Riddle return emitError("expected a sparse tensor result"); 220b98dc035SRiver Riddle RankedTensorType ttp = getType().cast<RankedTensorType>(); 22135517a25SAart Bik unsigned rank = ttp.getRank(); 222b98dc035SRiver Riddle if (rank != sizes().size()) 223b98dc035SRiver Riddle return emitError("unexpected mismatch between tensor rank and sizes: ") 224b98dc035SRiver Riddle << rank << " vs. " << sizes().size(); 22535517a25SAart Bik auto shape = ttp.getShape(); 22635517a25SAart Bik for (unsigned i = 0; i < rank; i++) { 22735517a25SAart Bik if (shape[i] == ShapedType::kDynamicSize) 22835517a25SAart Bik continue; 22965e7cd13SRiver Riddle IntegerAttr constantAttr; 230b98dc035SRiver Riddle if (!matchPattern(sizes()[i], m_Constant(&constantAttr)) || 23165e7cd13SRiver Riddle constantAttr.getInt() != shape[i]) { 232b98dc035SRiver Riddle return emitError("unexpected mismatch with static dimension size ") 23335517a25SAart Bik << shape[i]; 23435517a25SAart Bik } 23565e7cd13SRiver Riddle } 23635517a25SAart Bik return success(); 23735517a25SAart Bik } 23835517a25SAart Bik 239b98dc035SRiver Riddle LogicalResult ConvertOp::verify() { 240b98dc035SRiver Riddle if (auto tp1 = source().getType().dyn_cast<RankedTensorType>()) { 241b98dc035SRiver Riddle if (auto tp2 = dest().getType().dyn_cast<RankedTensorType>()) { 2421e6ef0cfSAart Bik if (tp1.getRank() != tp2.getRank()) 243b98dc035SRiver Riddle return emitError("unexpected conversion mismatch in rank"); 244697ea09dSAart Bik auto shape1 = tp1.getShape(); 245697ea09dSAart Bik auto shape2 = tp2.getShape(); 2469d1db3d4SAart Bik // Accept size matches between the source and the destination type 2479d1db3d4SAart Bik // (e.g. 10 vs. 10, 10 vs. ?, or ? vs. ?), but reject direct mismatches or 2489d1db3d4SAart Bik // matches that would need a runtime assert (e.g. 10 vs. 20 or ? vs. 10). 249b98dc035SRiver Riddle for (unsigned d = 0, rank = tp1.getRank(); d < rank; d++) 2509d1db3d4SAart Bik if (shape1[d] != shape2[d] && shape2[d] != ShapedType::kDynamicSize) 251b98dc035SRiver Riddle return emitError("unexpected conversion mismatch in dimension ") << d; 252697ea09dSAart Bik return success(); 253697ea09dSAart Bik } 254697ea09dSAart Bik } 255b98dc035SRiver Riddle return emitError("unexpected type in convert"); 256697ea09dSAart Bik } 257697ea09dSAart Bik 258066d786cSAart Bik OpFoldResult ConvertOp::fold(ArrayRef<Attribute> operands) { 259066d786cSAart Bik if (getType() == source().getType()) 260066d786cSAart Bik return source(); 261066d786cSAart Bik return {}; 262066d786cSAart Bik } 263066d786cSAart Bik 264b98dc035SRiver Riddle LogicalResult ToPointersOp::verify() { 265b98dc035SRiver Riddle if (auto e = getSparseTensorEncoding(tensor().getType())) { 266b98dc035SRiver Riddle if (failed(isInBounds(dim(), tensor()))) 267b98dc035SRiver Riddle return emitError("requested pointers dimension out of bounds"); 268b98dc035SRiver Riddle if (failed(isMatchingWidth(result(), e.getPointerBitWidth()))) 269b98dc035SRiver Riddle return emitError("unexpected type for pointers"); 27096a23911SAart Bik return success(); 27196a23911SAart Bik } 272b98dc035SRiver Riddle return emitError("expected a sparse tensor to get pointers"); 27396a23911SAart Bik } 27496a23911SAart Bik 275b98dc035SRiver Riddle LogicalResult ToIndicesOp::verify() { 276b98dc035SRiver Riddle if (auto e = getSparseTensorEncoding(tensor().getType())) { 277b98dc035SRiver Riddle if (failed(isInBounds(dim(), tensor()))) 278b98dc035SRiver Riddle return emitError("requested indices dimension out of bounds"); 279b98dc035SRiver Riddle if (failed(isMatchingWidth(result(), e.getIndexBitWidth()))) 280b98dc035SRiver Riddle return emitError("unexpected type for indices"); 28196a23911SAart Bik return success(); 28296a23911SAart Bik } 283b98dc035SRiver Riddle return emitError("expected a sparse tensor to get indices"); 28496a23911SAart Bik } 28596a23911SAart Bik 286b98dc035SRiver Riddle LogicalResult ToValuesOp::verify() { 287b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 288b98dc035SRiver Riddle return emitError("expected a sparse tensor to get values"); 289b98dc035SRiver Riddle RankedTensorType ttp = tensor().getType().cast<RankedTensorType>(); 290b98dc035SRiver Riddle MemRefType mtp = result().getType().cast<MemRefType>(); 29196a23911SAart Bik if (ttp.getElementType() != mtp.getElementType()) 292b98dc035SRiver Riddle return emitError("unexpected mismatch in element types"); 29396a23911SAart Bik return success(); 29496a23911SAart Bik } 29596a23911SAart Bik 296f66e5769SAart Bik //===----------------------------------------------------------------------===// 297f66e5769SAart Bik // TensorDialect Management Operations. 298f66e5769SAart Bik //===----------------------------------------------------------------------===// 299f66e5769SAart Bik 300b98dc035SRiver Riddle LogicalResult LexInsertOp::verify() { 301b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 302b98dc035SRiver Riddle return emitError("expected a sparse tensor for insertion"); 303f66e5769SAart Bik return success(); 304f66e5769SAart Bik } 305f66e5769SAart Bik 306b98dc035SRiver Riddle LogicalResult ExpandOp::verify() { 307b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 308b98dc035SRiver Riddle return emitError("expected a sparse tensor for expansion"); 3094f2ec7f9SAart Bik return success(); 3104f2ec7f9SAart Bik } 3114f2ec7f9SAart Bik 312b98dc035SRiver Riddle LogicalResult CompressOp::verify() { 313b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 314b98dc035SRiver Riddle return emitError("expected a sparse tensor for compression"); 3154f2ec7f9SAart Bik return success(); 3164f2ec7f9SAart Bik } 3174f2ec7f9SAart Bik 318b98dc035SRiver Riddle LogicalResult LoadOp::verify() { 319b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 320b98dc035SRiver Riddle return emitError("expected a sparse tensor to materialize"); 321f66e5769SAart Bik return success(); 322f66e5769SAart Bik } 323f66e5769SAart Bik 324b98dc035SRiver Riddle LogicalResult ReleaseOp::verify() { 325b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 326b98dc035SRiver Riddle return emitError("expected a sparse tensor to release"); 32736b66ab9SAart Bik return success(); 328727a63e0SAart Bik } 329727a63e0SAart Bik 330b98dc035SRiver Riddle LogicalResult OutOp::verify() { 331b98dc035SRiver Riddle if (!getSparseTensorEncoding(tensor().getType())) 332b98dc035SRiver Riddle return emitError("expected a sparse tensor for output"); 333efa15f41SAart Bik return success(); 334efa15f41SAart Bik } 335efa15f41SAart Bik 33696a23911SAart Bik //===----------------------------------------------------------------------===// 337*414ed019SJim Kitchen // TensorDialect Linalg.Generic Operations. 338*414ed019SJim Kitchen //===----------------------------------------------------------------------===// 339*414ed019SJim Kitchen 340*414ed019SJim Kitchen template <class T> 341*414ed019SJim Kitchen static LogicalResult verifyNumBlockArgs(T *op, Region ®ion, 342*414ed019SJim Kitchen const char *regionName, 343*414ed019SJim Kitchen TypeRange inputTypes, Type outputType) { 344*414ed019SJim Kitchen unsigned numArgs = region.getNumArguments(); 345*414ed019SJim Kitchen unsigned expectedNum = inputTypes.size(); 346*414ed019SJim Kitchen if (numArgs != expectedNum) 347*414ed019SJim Kitchen return op->emitError() << regionName << " region must have exactly " 348*414ed019SJim Kitchen << expectedNum << " arguments"; 349*414ed019SJim Kitchen 350*414ed019SJim Kitchen for (unsigned i = 0; i < numArgs; i++) { 351*414ed019SJim Kitchen Type typ = region.getArgument(i).getType(); 352*414ed019SJim Kitchen if (typ != inputTypes[i]) 353*414ed019SJim Kitchen return op->emitError() << regionName << " region argument " << (i + 1) 354*414ed019SJim Kitchen << " type mismatch"; 355*414ed019SJim Kitchen } 356*414ed019SJim Kitchen Operation *term = region.front().getTerminator(); 357*414ed019SJim Kitchen YieldOp yield = dyn_cast<YieldOp>(term); 358*414ed019SJim Kitchen if (!yield) 359*414ed019SJim Kitchen return op->emitError() << regionName 360*414ed019SJim Kitchen << " region must end with sparse_tensor.yield"; 361*414ed019SJim Kitchen if (yield.getOperand().getType() != outputType) 362*414ed019SJim Kitchen return op->emitError() << regionName << " region yield type mismatch"; 363*414ed019SJim Kitchen 364*414ed019SJim Kitchen return success(); 365*414ed019SJim Kitchen } 366*414ed019SJim Kitchen 367*414ed019SJim Kitchen LogicalResult BinaryOp::verify() { 368*414ed019SJim Kitchen NamedAttrList attrs = (*this)->getAttrs(); 369*414ed019SJim Kitchen Type leftType = x().getType(); 370*414ed019SJim Kitchen Type rightType = y().getType(); 371*414ed019SJim Kitchen Type outputType = output().getType(); 372*414ed019SJim Kitchen Region &overlap = overlapRegion(); 373*414ed019SJim Kitchen Region &left = leftRegion(); 374*414ed019SJim Kitchen Region &right = rightRegion(); 375*414ed019SJim Kitchen 376*414ed019SJim Kitchen // Check correct number of block arguments and return type for each 377*414ed019SJim Kitchen // non-empty region. 378*414ed019SJim Kitchen LogicalResult regionResult = success(); 379*414ed019SJim Kitchen if (!overlap.empty()) { 380*414ed019SJim Kitchen regionResult = verifyNumBlockArgs( 381*414ed019SJim Kitchen this, overlap, "overlap", TypeRange{leftType, rightType}, outputType); 382*414ed019SJim Kitchen if (failed(regionResult)) 383*414ed019SJim Kitchen return regionResult; 384*414ed019SJim Kitchen } 385*414ed019SJim Kitchen if (!left.empty()) { 386*414ed019SJim Kitchen regionResult = 387*414ed019SJim Kitchen verifyNumBlockArgs(this, left, "left", TypeRange{leftType}, outputType); 388*414ed019SJim Kitchen if (failed(regionResult)) 389*414ed019SJim Kitchen return regionResult; 390*414ed019SJim Kitchen } else if (left_identity()) { 391*414ed019SJim Kitchen if (leftType != outputType) 392*414ed019SJim Kitchen return emitError("left=identity requires first argument to have the same " 393*414ed019SJim Kitchen "type as the output"); 394*414ed019SJim Kitchen } 395*414ed019SJim Kitchen if (!right.empty()) { 396*414ed019SJim Kitchen regionResult = verifyNumBlockArgs(this, right, "right", 397*414ed019SJim Kitchen TypeRange{rightType}, outputType); 398*414ed019SJim Kitchen if (failed(regionResult)) 399*414ed019SJim Kitchen return regionResult; 400*414ed019SJim Kitchen } else if (right_identity()) { 401*414ed019SJim Kitchen if (rightType != outputType) 402*414ed019SJim Kitchen return emitError("right=identity requires second argument to have the " 403*414ed019SJim Kitchen "same type as the output"); 404*414ed019SJim Kitchen } 405*414ed019SJim Kitchen 406*414ed019SJim Kitchen return success(); 407*414ed019SJim Kitchen } 408*414ed019SJim Kitchen 409*414ed019SJim Kitchen LogicalResult UnaryOp::verify() { 410*414ed019SJim Kitchen Type inputType = x().getType(); 411*414ed019SJim Kitchen Type outputType = output().getType(); 412*414ed019SJim Kitchen LogicalResult regionResult = success(); 413*414ed019SJim Kitchen 414*414ed019SJim Kitchen // Check correct number of block arguments and return type for each 415*414ed019SJim Kitchen // non-empty region. 416*414ed019SJim Kitchen Region &present = presentRegion(); 417*414ed019SJim Kitchen if (!present.empty()) { 418*414ed019SJim Kitchen regionResult = verifyNumBlockArgs(this, present, "present", 419*414ed019SJim Kitchen TypeRange{inputType}, outputType); 420*414ed019SJim Kitchen if (failed(regionResult)) 421*414ed019SJim Kitchen return regionResult; 422*414ed019SJim Kitchen } 423*414ed019SJim Kitchen Region &absent = absentRegion(); 424*414ed019SJim Kitchen if (!absent.empty()) { 425*414ed019SJim Kitchen regionResult = 426*414ed019SJim Kitchen verifyNumBlockArgs(this, absent, "absent", TypeRange{}, outputType); 427*414ed019SJim Kitchen if (failed(regionResult)) 428*414ed019SJim Kitchen return regionResult; 429*414ed019SJim Kitchen } 430*414ed019SJim Kitchen 431*414ed019SJim Kitchen return success(); 432*414ed019SJim Kitchen } 433*414ed019SJim Kitchen 434*414ed019SJim Kitchen LogicalResult YieldOp::verify() { 435*414ed019SJim Kitchen // Check for compatible parent. 436*414ed019SJim Kitchen auto *parentOp = (*this)->getParentOp(); 437*414ed019SJim Kitchen if (auto binaryOp = dyn_cast<BinaryOp>(parentOp)) 438*414ed019SJim Kitchen return success(); 439*414ed019SJim Kitchen if (auto unaryOp = dyn_cast<UnaryOp>(parentOp)) 440*414ed019SJim Kitchen return success(); 441*414ed019SJim Kitchen 442*414ed019SJim Kitchen return emitOpError("expected parent op to be sparse_tensor binary or unary"); 443*414ed019SJim Kitchen } 444*414ed019SJim Kitchen 445*414ed019SJim Kitchen //===----------------------------------------------------------------------===// 44696a23911SAart Bik // TensorDialect Methods. 4470a292199SAart Bik //===----------------------------------------------------------------------===// 4480a292199SAart Bik 449319072f4SAart Bik void SparseTensorDialect::initialize() { 4500a292199SAart Bik addAttributes< 4510a292199SAart Bik #define GET_ATTRDEF_LIST 4520a292199SAart Bik #include "mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.cpp.inc" 4530a292199SAart Bik >(); 454319072f4SAart Bik addOperations< 455319072f4SAart Bik #define GET_OP_LIST 456319072f4SAart Bik #include "mlir/Dialect/SparseTensor/IR/SparseTensorOps.cpp.inc" 457319072f4SAart Bik >(); 458319072f4SAart Bik } 459319072f4SAart Bik 460319072f4SAart Bik #define GET_OP_CLASSES 461319072f4SAart Bik #include "mlir/Dialect/SparseTensor/IR/SparseTensorOps.cpp.inc" 4625517208dSAart Bik 4635517208dSAart Bik #include "mlir/Dialect/SparseTensor/IR/SparseTensorOpsDialect.cpp.inc" 464