18#include "llvm/ADT/TypeSwitch.h"
25 bool requireSameBitWidth =
true,
26 bool skipBitWidthCheck =
false) {
28 if (skipBitWidthCheck)
36 using TypePair = std::pair<Type, Type>;
37 auto [operandElemTy, resultElemTy] =
40 [resultType](
auto concreteOperandTy) -> TypePair {
41 if (
auto concreteResultTy =
42 dyn_cast<
decltype(concreteOperandTy)>(resultType)) {
43 return {concreteOperandTy.getElementType(),
44 concreteResultTy.getElementType()};
48 .Default([resultType](
Type operandType) -> TypePair {
49 return {operandType, resultType};
52 if (!operandElemTy || !resultElemTy)
53 return op->
emitOpError(
"incompatible operand and result types");
55 unsigned operandTypeBitWidth = operandElemTy.getIntOrFloatBitWidth();
56 unsigned resultTypeBitWidth = resultElemTy.getIntOrFloatBitWidth();
57 bool isSameBitWidth = operandTypeBitWidth == resultTypeBitWidth;
59 if (requireSameBitWidth) {
60 if (!isSameBitWidth) {
62 "expected the same bit widths for operand type and result "
63 "type, but provided ")
64 << operandElemTy <<
" and " << resultElemTy;
71 "expected the different bit widths for operand type and result "
72 "type, but provided ")
73 << operandElemTy <<
" and " << resultElemTy;
82LogicalResult BitcastOp::verify() {
85 auto operandType = getOperand().getType();
86 auto resultType = getResult().getType();
87 if (operandType == resultType) {
88 return emitError(
"result type must be different from operand type");
91 auto operandCoopMatrixType =
92 dyn_cast<spirv::CooperativeMatrixType>(operandType);
93 auto resultCoopMatrixType =
94 dyn_cast<spirv::CooperativeMatrixType>(resultType);
95 if (operandCoopMatrixType || resultCoopMatrixType) {
96 if (!operandCoopMatrixType || !resultCoopMatrixType)
97 return emitError(
"unhandled bit cast conversion from cooperative matrix "
98 "type to non-cooperative matrix type");
100 if (operandCoopMatrixType.getRows() != resultCoopMatrixType.getRows() ||
101 operandCoopMatrixType.getColumns() != resultCoopMatrixType.getColumns())
102 return emitError(
"cooperative matrix dimensions must match");
104 if (operandCoopMatrixType.getScope() != resultCoopMatrixType.getScope())
105 return emitError(
"cooperative matrix scope must match");
107 if (operandCoopMatrixType.getUse() != resultCoopMatrixType.getUse())
108 return emitError(
"cooperative matrix use must match");
110 unsigned operandBitWidth =
111 getBitWidth(operandCoopMatrixType.getElementType());
112 unsigned resultBitWidth =
113 getBitWidth(resultCoopMatrixType.getElementType());
114 if (operandBitWidth != resultBitWidth)
115 return emitOpError(
"mismatch in result and operand type bitwidth");
120 if (isa<spirv::PointerType>(operandType) &&
121 !isa<spirv::PointerType>(resultType)) {
123 "unhandled bit cast conversion from pointer type to non-pointer type");
125 if (!isa<spirv::PointerType>(operandType) &&
126 isa<spirv::PointerType>(resultType)) {
128 "unhandled bit cast conversion from non-pointer type to pointer type");
132 if (operandBitWidth != resultBitWidth) {
133 return emitOpError(
"mismatch in result type bitwidth ")
134 << resultBitWidth <<
" and operand type bitwidth "
144LogicalResult ConvertPtrToUOp::verify() {
145 auto operandType = cast<spirv::PointerType>(getPointer().
getType());
146 auto resultType = cast<spirv::ScalarType>(getResult().
getType());
147 if (!resultType || !resultType.isSignlessInteger())
148 return emitError(
"result must be a scalar type of unsigned integer");
149 auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
152 auto addressingModel = spirvModule.getAddressingModel();
153 if ((addressingModel == spirv::AddressingModel::Logical) ||
154 (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
155 operandType.getStorageClass() !=
156 spirv::StorageClass::PhysicalStorageBuffer))
157 return emitError(
"operand must be a physical pointer");
165LogicalResult ConvertUToPtrOp::verify() {
166 auto operandType = cast<spirv::ScalarType>(getOperand().
getType());
167 auto resultType = cast<spirv::PointerType>(getResult().
getType());
168 if (!operandType || !operandType.isSignlessInteger())
169 return emitError(
"result must be a scalar type of unsigned integer");
170 auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
173 auto addressingModel = spirvModule.getAddressingModel();
174 if ((addressingModel == spirv::AddressingModel::Logical) ||
175 (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
176 resultType.getStorageClass() !=
177 spirv::StorageClass::PhysicalStorageBuffer))
178 return emitError(
"result must be a physical pointer");
186LogicalResult PtrCastToGenericOp::verify() {
187 auto operandType = cast<spirv::PointerType>(getPointer().
getType());
188 auto resultType = cast<spirv::PointerType>(getResult().
getType());
190 spirv::StorageClass operandStorage = operandType.getStorageClass();
191 if (operandStorage != spirv::StorageClass::Workgroup &&
192 operandStorage != spirv::StorageClass::CrossWorkgroup &&
193 operandStorage != spirv::StorageClass::Function)
194 return emitError(
"pointer must point to the Workgroup, CrossWorkgroup"
195 ", or Function Storage Class");
197 spirv::StorageClass resultStorage = resultType.getStorageClass();
198 if (resultStorage != spirv::StorageClass::Generic)
199 return emitError(
"result type must be of storage class Generic");
201 Type operandPointeeType = operandType.getPointeeType();
202 Type resultPointeeType = resultType.getPointeeType();
203 if (operandPointeeType != resultPointeeType)
204 return emitOpError(
"pointer operand's pointee type must have the same "
205 "as the op result type, but found ")
206 << operandPointeeType <<
" vs " << resultPointeeType;
214LogicalResult GenericCastToPtrOp::verify() {
215 auto operandType = cast<spirv::PointerType>(getPointer().
getType());
216 auto resultType = cast<spirv::PointerType>(getResult().
getType());
218 spirv::StorageClass operandStorage = operandType.getStorageClass();
219 if (operandStorage != spirv::StorageClass::Generic)
220 return emitError(
"pointer type must be of storage class Generic");
222 spirv::StorageClass resultStorage = resultType.getStorageClass();
223 if (resultStorage != spirv::StorageClass::Workgroup &&
224 resultStorage != spirv::StorageClass::CrossWorkgroup &&
225 resultStorage != spirv::StorageClass::Function)
226 return emitError(
"result must point to the Workgroup, CrossWorkgroup, "
227 "or Function Storage Class");
229 Type operandPointeeType = operandType.getPointeeType();
230 Type resultPointeeType = resultType.getPointeeType();
231 if (operandPointeeType != resultPointeeType)
232 return emitOpError(
"pointer operand's pointee type must have the same "
233 "as the op result type, but found ")
234 << operandPointeeType <<
" vs " << resultPointeeType;
242LogicalResult GenericCastToPtrExplicitOp::verify() {
243 auto operandType = cast<spirv::PointerType>(getPointer().
getType());
244 auto resultType = cast<spirv::PointerType>(getResult().
getType());
246 spirv::StorageClass operandStorage = operandType.getStorageClass();
247 if (operandStorage != spirv::StorageClass::Generic)
248 return emitError(
"pointer type must be of storage class Generic");
250 spirv::StorageClass resultStorage = resultType.getStorageClass();
251 if (resultStorage != spirv::StorageClass::Workgroup &&
252 resultStorage != spirv::StorageClass::CrossWorkgroup &&
253 resultStorage != spirv::StorageClass::Function)
254 return emitError(
"result must point to the Workgroup, CrossWorkgroup, "
255 "or Function Storage Class");
257 Type operandPointeeType = operandType.getPointeeType();
258 Type resultPointeeType = resultType.getPointeeType();
259 if (operandPointeeType != resultPointeeType)
260 return emitOpError(
"pointer operand's pointee type must have the same "
261 "as the op result type, but found ")
262 << operandPointeeType <<
" vs " << resultPointeeType;
270LogicalResult ConvertFToSOp::verify() {
279LogicalResult ConvertFToUOp::verify() {
288LogicalResult ConvertSToFOp::verify() {
297LogicalResult ConvertUToFOp::verify() {
306LogicalResult spirv::FConvertOp::verify() {
314LogicalResult spirv::SConvertOp::verify() {
322LogicalResult spirv::UConvertOp::verify() {
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Type getType() const
Return the type of this value.
static LogicalResult verifyCastOp(Operation *op, bool requireSameBitWidth=true, bool skipBitWidthCheck=false)
unsigned getBitWidth(Type type)
Returns the bit width of the type.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::TypeSwitch< T, ResultT > TypeSwitch