18 #include "llvm/ADT/TypeSwitch.h"
25 bool requireSameBitWidth =
true,
26 bool skipBitWidthCheck =
false) {
28 if (skipBitWidthCheck)
31 Type operandType = op->getOperand(0).getType();
32 Type resultType = op->getResult(0).getType();
36 using TypePair = std::pair<Type, Type>;
37 auto [operandElemTy, resultElemTy] =
41 [resultType](
auto concreteOperandTy) -> TypePair {
42 if (
auto concreteResultTy =
43 dyn_cast<decltype(concreteOperandTy)>(resultType)) {
44 return {concreteOperandTy.getElementType(),
45 concreteResultTy.getElementType()};
49 .Default([resultType](
Type operandType) -> TypePair {
50 return {operandType, resultType};
53 if (!operandElemTy || !resultElemTy)
54 return op->emitOpError(
"incompatible operand and result types");
56 unsigned operandTypeBitWidth = operandElemTy.getIntOrFloatBitWidth();
57 unsigned resultTypeBitWidth = resultElemTy.getIntOrFloatBitWidth();
58 bool isSameBitWidth = operandTypeBitWidth == resultTypeBitWidth;
60 if (requireSameBitWidth) {
61 if (!isSameBitWidth) {
62 return op->emitOpError(
63 "expected the same bit widths for operand type and result "
64 "type, but provided ")
65 << operandElemTy <<
" and " << resultElemTy;
71 return op->emitOpError(
72 "expected the different bit widths for operand type and result "
73 "type, but provided ")
74 << operandElemTy <<
" and " << resultElemTy;
86 auto operandType = getOperand().getType();
87 auto resultType = getResult().getType();
88 if (operandType == resultType) {
89 return emitError(
"result type must be different from operand type");
91 if (llvm::isa<spirv::PointerType>(operandType) &&
92 !llvm::isa<spirv::PointerType>(resultType)) {
94 "unhandled bit cast conversion from pointer type to non-pointer type");
96 if (!llvm::isa<spirv::PointerType>(operandType) &&
97 llvm::isa<spirv::PointerType>(resultType)) {
99 "unhandled bit cast conversion from non-pointer type to pointer type");
103 if (operandBitWidth != resultBitWidth) {
104 return emitOpError(
"mismatch in result type bitwidth ")
105 << resultBitWidth <<
" and operand type bitwidth "
116 auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());
117 auto resultType = llvm::cast<spirv::ScalarType>(getResult().getType());
118 if (!resultType || !resultType.isSignlessInteger())
119 return emitError(
"result must be a scalar type of unsigned integer");
120 auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
123 auto addressingModel = spirvModule.getAddressingModel();
124 if ((addressingModel == spirv::AddressingModel::Logical) ||
125 (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
126 operandType.getStorageClass() !=
127 spirv::StorageClass::PhysicalStorageBuffer))
128 return emitError(
"operand must be a physical pointer");
137 auto operandType = llvm::cast<spirv::ScalarType>(getOperand().getType());
138 auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());
139 if (!operandType || !operandType.isSignlessInteger())
140 return emitError(
"result must be a scalar type of unsigned integer");
141 auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
144 auto addressingModel = spirvModule.getAddressingModel();
145 if ((addressingModel == spirv::AddressingModel::Logical) ||
146 (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
147 resultType.getStorageClass() !=
148 spirv::StorageClass::PhysicalStorageBuffer))
149 return emitError(
"result must be a physical pointer");
158 auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());
159 auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());
161 spirv::StorageClass operandStorage = operandType.getStorageClass();
162 if (operandStorage != spirv::StorageClass::Workgroup &&
163 operandStorage != spirv::StorageClass::CrossWorkgroup &&
164 operandStorage != spirv::StorageClass::Function)
165 return emitError(
"pointer must point to the Workgroup, CrossWorkgroup"
166 ", or Function Storage Class");
168 spirv::StorageClass resultStorage = resultType.getStorageClass();
169 if (resultStorage != spirv::StorageClass::Generic)
170 return emitError(
"result type must be of storage class Generic");
172 Type operandPointeeType = operandType.getPointeeType();
173 Type resultPointeeType = resultType.getPointeeType();
174 if (operandPointeeType != resultPointeeType)
175 return emitOpError(
"pointer operand's pointee type must have the same "
176 "as the op result type, but found ")
177 << operandPointeeType <<
" vs " << resultPointeeType;
186 auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());
187 auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());
189 spirv::StorageClass operandStorage = operandType.getStorageClass();
190 if (operandStorage != spirv::StorageClass::Generic)
191 return emitError(
"pointer type must be of storage class Generic");
193 spirv::StorageClass resultStorage = resultType.getStorageClass();
194 if (resultStorage != spirv::StorageClass::Workgroup &&
195 resultStorage != spirv::StorageClass::CrossWorkgroup &&
196 resultStorage != spirv::StorageClass::Function)
197 return emitError(
"result must point to the Workgroup, CrossWorkgroup, "
198 "or Function Storage Class");
200 Type operandPointeeType = operandType.getPointeeType();
201 Type resultPointeeType = resultType.getPointeeType();
202 if (operandPointeeType != resultPointeeType)
203 return emitOpError(
"pointer operand's pointee type must have the same "
204 "as the op result type, but found ")
205 << operandPointeeType <<
" vs " << resultPointeeType;
214 auto operandType = llvm::cast<spirv::PointerType>(getPointer().getType());
215 auto resultType = llvm::cast<spirv::PointerType>(getResult().getType());
217 spirv::StorageClass operandStorage = operandType.getStorageClass();
218 if (operandStorage != spirv::StorageClass::Generic)
219 return emitError(
"pointer type must be of storage class Generic");
221 spirv::StorageClass resultStorage = resultType.getStorageClass();
222 if (resultStorage != spirv::StorageClass::Workgroup &&
223 resultStorage != spirv::StorageClass::CrossWorkgroup &&
224 resultStorage != spirv::StorageClass::Function)
225 return emitError(
"result must point to the Workgroup, CrossWorkgroup, "
226 "or Function Storage Class");
228 Type operandPointeeType = operandType.getPointeeType();
229 Type resultPointeeType = resultType.getPointeeType();
230 if (operandPointeeType != resultPointeeType)
231 return emitOpError(
"pointer operand's pointee type must have the same "
232 "as the op result type, but found ")
233 << operandPointeeType <<
" vs " << resultPointeeType;
278 auto operandType = getOperand().getType();
279 auto resultType = getResult().getType();
282 if (
auto vectorType = llvm::dyn_cast<VectorType>(operandType)) {
283 unsigned operandNumElements = vectorType.getNumElements();
284 unsigned resultNumElements =
285 llvm::cast<VectorType>(resultType).getNumElements();
286 if (operandNumElements != resultNumElements) {
288 "operand and result must have same number of elements");
299 auto operandType = getOperand().getType();
300 auto resultType = getResult().getType();
303 if (
auto vectorType = llvm::dyn_cast<VectorType>(operandType)) {
304 unsigned operandNumElements = vectorType.getNumElements();
305 unsigned resultNumElements =
306 llvm::cast<VectorType>(resultType).getNumElements();
307 if (operandNumElements != resultNumElements) {
309 "operand and result must have same number of elements");
Operation is the basic unit of execution within MLIR.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
@ Type
An inlay hint that for a type annotation.
static LogicalResult verifyCastOp(Operation *op, bool requireSameBitWidth=true, bool skipBitWidthCheck=false)
unsigned getBitWidth(Type type)
Returns the bit width of the type.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
This class represents an efficient way to signal success or failure.