23template <
typename OpTy>
28 OpTy::getExecutionScopeAttrName(groupOp->
getName()))
30 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
32 "execution scope must be 'Workgroup' or 'Subgroup'");
34 GroupOperation operation =
37 OpTy::getGroupOperationAttrName(groupOp->
getName()))
39 if (operation == GroupOperation::ClusteredReduce &&
41 return groupOp->
emitOpError(
"cluster size operand must be provided for "
42 "'ClusteredReduce' group operation");
45 int32_t clusterSize = 0;
50 "cluster size operand must come from a constant op");
52 if (!llvm::isPowerOf2_32(clusterSize))
54 "cluster size operand must be a power of two");
63LogicalResult GroupBroadcastOp::verify() {
64 spirv::Scope scope = getExecutionScope();
65 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
66 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
68 if (
auto localIdTy = llvm::dyn_cast<VectorType>(getLocalid().
getType()))
69 if (localIdTy.getNumElements() != 2 && localIdTy.getNumElements() != 3)
70 return emitOpError(
"localid is a vector and can be with only "
71 " 2 or 3 components, actual number is ")
72 << localIdTy.getNumElements();
81LogicalResult GroupNonUniformBallotOp::verify() {
82 spirv::Scope scope = getExecutionScope();
83 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
84 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
93LogicalResult GroupNonUniformBallotFindLSBOp::verify() {
94 spirv::Scope scope = getExecutionScope();
95 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
96 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
105LogicalResult GroupNonUniformBallotFindMSBOp::verify() {
106 spirv::Scope scope = getExecutionScope();
107 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
108 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
117LogicalResult GroupNonUniformBroadcastOp::verify() {
118 spirv::Scope scope = getExecutionScope();
119 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
120 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
125 if (
auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>())
128 if (targetEnv.getVersion() < spirv::Version::V_1_5) {
129 auto *idOp = getId().getDefiningOp();
130 if (!idOp || !isa<spirv::ConstantOp,
131 spirv::ReferenceOfOp>(idOp))
132 return emitOpError(
"id must be the result of a constant op");
142template <
typename OpTy>
144 spirv::Scope scope = op.getExecutionScope();
145 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
146 return op.emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
148 if (op.getOperands().back().getType().isSignedInteger())
149 return op.emitOpError(
"second operand must be a singless/unsigned integer");
154LogicalResult GroupNonUniformShuffleOp::verify() {
157LogicalResult GroupNonUniformShuffleDownOp::verify() {
160LogicalResult GroupNonUniformShuffleUpOp::verify() {
163LogicalResult GroupNonUniformShuffleXorOp::verify() {
171LogicalResult GroupNonUniformElectOp::verify() {
172 spirv::Scope scope = getExecutionScope();
173 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
174 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
183LogicalResult GroupNonUniformFAddOp::verify() {
191LogicalResult GroupNonUniformFMaxOp::verify() {
199LogicalResult GroupNonUniformFMinOp::verify() {
207LogicalResult GroupNonUniformFMulOp::verify() {
215LogicalResult GroupNonUniformIAddOp::verify() {
223LogicalResult GroupNonUniformIMulOp::verify() {
231LogicalResult GroupNonUniformSMaxOp::verify() {
239LogicalResult GroupNonUniformSMinOp::verify() {
247LogicalResult GroupNonUniformUMaxOp::verify() {
255LogicalResult GroupNonUniformUMinOp::verify() {
263LogicalResult GroupNonUniformBitwiseAndOp::verify() {
271LogicalResult GroupNonUniformBitwiseOrOp::verify() {
279LogicalResult GroupNonUniformBitwiseXorOp::verify() {
287LogicalResult GroupNonUniformLogicalAndOp::verify() {
295LogicalResult GroupNonUniformLogicalOrOp::verify() {
303LogicalResult GroupNonUniformLogicalXorOp::verify() {
311LogicalResult GroupNonUniformRotateKHROp::verify() {
312 spirv::Scope scope = getExecutionScope();
313 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
314 return emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
316 if (Value clusterSizeVal = getClusterSize()) {
317 mlir::Operation *defOp = clusterSizeVal.getDefiningOp();
318 int32_t clusterSize = 0;
321 return emitOpError(
"cluster size operand must come from a constant op");
323 if (!llvm::isPowerOf2_32(clusterSize))
324 return emitOpError(
"cluster size operand must be a power of two");
334template <
typename Op>
336 spirv::Scope scope = op.getExecutionScope();
337 if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
338 return op.
emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
343LogicalResult GroupIAddOp::verify() {
return verifyGroupOp(*
this); }
345LogicalResult GroupFAddOp::verify() {
return verifyGroupOp(*
this); }
347LogicalResult GroupFMinOp::verify() {
return verifyGroupOp(*
this); }
349LogicalResult GroupUMinOp::verify() {
return verifyGroupOp(*
this); }
351LogicalResult GroupSMinOp::verify() {
return verifyGroupOp(*
this); }
353LogicalResult GroupFMaxOp::verify() {
return verifyGroupOp(*
this); }
355LogicalResult GroupUMaxOp::verify() {
return verifyGroupOp(*
this); }
357LogicalResult GroupSMaxOp::verify() {
return verifyGroupOp(*
this); }
359LogicalResult GroupIMulKHROp::verify() {
return verifyGroupOp(*
this); }
361LogicalResult GroupFMulKHROp::verify() {
return verifyGroupOp(*
this); }
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.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
AttrClass getAttrOfType(StringAttr name)
unsigned getNumOperands()
OperationName getName()
The name of an operation is the key identifier for it.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static LogicalResult verifyGroupNonUniformArithmeticOp(Operation *groupOp)
TargetEnvAttr lookupTargetEnvOrDefault(Operation *op)
Queries the target environment recursively from enclosing symbol table ops containing the given op or...
static LogicalResult verifyGroupNonUniformShuffleOp(OpTy op)
static LogicalResult verifyGroupOp(Op op)
LogicalResult extractValueFromConstOp(Operation *op, int32_t &value)
TargetEnvAttr getDefaultTargetEnv(MLIRContext *context)
Returns the default target environment: SPIR-V 1.0 with Shader capability and no extra extensions.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.