[Mlir-commits] [mlir] 339c87a - [mlir][spirv] Add group ops

Ivan Butygin llvmlistbot at llvm.org
Tue Nov 29 06:05:08 PST 2022


Author: Ivan Butygin
Date: 2022-11-29T15:03:31+01:00
New Revision: 339c87a8a086347bd8b5aae8b5bc43fc1c155cc1

URL: https://github.com/llvm/llvm-project/commit/339c87a8a086347bd8b5aae8b5bc43fc1c155cc1
DIFF: https://github.com/llvm/llvm-project/commit/339c87a8a086347bd8b5aae8b5bc43fc1c155cc1.diff

LOG: [mlir][spirv] Add group ops

Also, gen_spirv_dialect script was broken was broken due to SPV->SPIRV renamings.

Differential Revision: https://reviews.llvm.org/D138756

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGroupOps.td
    mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
    mlir/test/Dialect/SPIRV/IR/group-ops.mlir
    mlir/test/Target/SPIRV/group-ops.mlir
    mlir/utils/spirv/gen_spirv_dialect.py

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
index 536cc136d0c48..e4d4ee56da065 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
@@ -4327,6 +4327,14 @@ def SPIRV_OC_OpReturn                     : I32EnumAttrCase<"OpReturn", 253>;
 def SPIRV_OC_OpReturnValue                : I32EnumAttrCase<"OpReturnValue", 254>;
 def SPIRV_OC_OpUnreachable                : I32EnumAttrCase<"OpUnreachable", 255>;
 def SPIRV_OC_OpGroupBroadcast             : I32EnumAttrCase<"OpGroupBroadcast", 263>;
+def SPIRV_OC_OpGroupIAdd                  : I32EnumAttrCase<"OpGroupIAdd", 264>;
+def SPIRV_OC_OpGroupFAdd                  : I32EnumAttrCase<"OpGroupFAdd", 265>;
+def SPIRV_OC_OpGroupFMin                  : I32EnumAttrCase<"OpGroupFMin", 266>;
+def SPIRV_OC_OpGroupUMin                  : I32EnumAttrCase<"OpGroupUMin", 267>;
+def SPIRV_OC_OpGroupSMin                  : I32EnumAttrCase<"OpGroupSMin", 268>;
+def SPIRV_OC_OpGroupFMax                  : I32EnumAttrCase<"OpGroupFMax", 269>;
+def SPIRV_OC_OpGroupUMax                  : I32EnumAttrCase<"OpGroupUMax", 270>;
+def SPIRV_OC_OpGroupSMax                  : I32EnumAttrCase<"OpGroupSMax", 271>;
 def SPIRV_OC_OpNoLine                     : I32EnumAttrCase<"OpNoLine", 317>;
 def SPIRV_OC_OpModuleProcessed            : I32EnumAttrCase<"OpModuleProcessed", 330>;
 def SPIRV_OC_OpGroupNonUniformElect       : I32EnumAttrCase<"OpGroupNonUniformElect", 333>;
@@ -4356,6 +4364,8 @@ def SPIRV_OC_OpSubgroupBlockReadINTEL     : I32EnumAttrCase<"OpSubgroupBlockRead
 def SPIRV_OC_OpSubgroupBlockWriteINTEL    : I32EnumAttrCase<"OpSubgroupBlockWriteINTEL", 5576>;
 def SPIRV_OC_OpAssumeTrueKHR              : I32EnumAttrCase<"OpAssumeTrueKHR", 5630>;
 def SPIRV_OC_OpAtomicFAddEXT              : I32EnumAttrCase<"OpAtomicFAddEXT", 6035>;
+def SPIRV_OC_OpGroupIMulKHR               : I32EnumAttrCase<"OpGroupIMulKHR", 6401>;
+def SPIRV_OC_OpGroupFMulKHR               : I32EnumAttrCase<"OpGroupFMulKHR", 6402>;
 
 def SPIRV_OC_OpTypeJointMatrixINTEL       : I32EnumAttrCase<"OpTypeJointMatrixINTEL", 6119>;
 def SPIRV_OC_OpJointMatrixLoadINTEL       : I32EnumAttrCase<"OpJointMatrixLoadINTEL", 6120>;
@@ -4365,58 +4375,69 @@ def SPIRV_OC_OpTypejointMatrixWorkItemLengthINTEL : I32EnumAttrCase<"OpJointMatr
 
 def SPIRV_OpcodeAttr :
     SPIRV_I32EnumAttr<"Opcode", "valid SPIR-V instructions", "opcode", [
-      SPIRV_OC_OpNop, SPIRV_OC_OpUndef, SPIRV_OC_OpSourceContinued, SPIRV_OC_OpSource,
-      SPIRV_OC_OpSourceExtension, SPIRV_OC_OpName, SPIRV_OC_OpMemberName, SPIRV_OC_OpString,
-      SPIRV_OC_OpLine, SPIRV_OC_OpExtension, SPIRV_OC_OpExtInstImport, SPIRV_OC_OpExtInst,
+      SPIRV_OC_OpNop, SPIRV_OC_OpUndef, SPIRV_OC_OpSourceContinued,
+      SPIRV_OC_OpSource, SPIRV_OC_OpSourceExtension, SPIRV_OC_OpName,
+      SPIRV_OC_OpMemberName, SPIRV_OC_OpString, SPIRV_OC_OpLine,
+      SPIRV_OC_OpExtension, SPIRV_OC_OpExtInstImport, SPIRV_OC_OpExtInst,
       SPIRV_OC_OpMemoryModel, SPIRV_OC_OpEntryPoint, SPIRV_OC_OpExecutionMode,
-      SPIRV_OC_OpCapability, SPIRV_OC_OpTypeVoid, SPIRV_OC_OpTypeBool, SPIRV_OC_OpTypeInt,
-      SPIRV_OC_OpTypeFloat, SPIRV_OC_OpTypeVector, SPIRV_OC_OpTypeMatrix,
-      SPIRV_OC_OpTypeImage, SPIRV_OC_OpTypeSampledImage, SPIRV_OC_OpTypeArray,
-      SPIRV_OC_OpTypeRuntimeArray, SPIRV_OC_OpTypeStruct, SPIRV_OC_OpTypePointer,
-      SPIRV_OC_OpTypeFunction, SPIRV_OC_OpTypeForwardPointer, SPIRV_OC_OpConstantTrue,
-      SPIRV_OC_OpConstantFalse, SPIRV_OC_OpConstant, SPIRV_OC_OpConstantComposite,
-      SPIRV_OC_OpConstantNull, SPIRV_OC_OpSpecConstantTrue, SPIRV_OC_OpSpecConstantFalse,
-      SPIRV_OC_OpSpecConstant, SPIRV_OC_OpSpecConstantComposite, SPIRV_OC_OpSpecConstantOp,
-      SPIRV_OC_OpFunction, SPIRV_OC_OpFunctionParameter, SPIRV_OC_OpFunctionEnd,
-      SPIRV_OC_OpFunctionCall, SPIRV_OC_OpVariable, SPIRV_OC_OpLoad, SPIRV_OC_OpStore,
-      SPIRV_OC_OpCopyMemory, SPIRV_OC_OpAccessChain, SPIRV_OC_OpPtrAccessChain,
-      SPIRV_OC_OpInBoundsPtrAccessChain, SPIRV_OC_OpDecorate, SPIRV_OC_OpMemberDecorate,
-      SPIRV_OC_OpVectorExtractDynamic, SPIRV_OC_OpVectorInsertDynamic,
-      SPIRV_OC_OpVectorShuffle, SPIRV_OC_OpCompositeConstruct, SPIRV_OC_OpCompositeExtract,
+      SPIRV_OC_OpCapability, SPIRV_OC_OpTypeVoid, SPIRV_OC_OpTypeBool,
+      SPIRV_OC_OpTypeInt, SPIRV_OC_OpTypeFloat, SPIRV_OC_OpTypeVector,
+      SPIRV_OC_OpTypeMatrix, SPIRV_OC_OpTypeImage, SPIRV_OC_OpTypeSampledImage,
+      SPIRV_OC_OpTypeArray, SPIRV_OC_OpTypeRuntimeArray, SPIRV_OC_OpTypeStruct,
+      SPIRV_OC_OpTypePointer, SPIRV_OC_OpTypeFunction, SPIRV_OC_OpTypeForwardPointer,
+      SPIRV_OC_OpConstantTrue, SPIRV_OC_OpConstantFalse, SPIRV_OC_OpConstant,
+      SPIRV_OC_OpConstantComposite, SPIRV_OC_OpConstantNull,
+      SPIRV_OC_OpSpecConstantTrue, SPIRV_OC_OpSpecConstantFalse,
+      SPIRV_OC_OpSpecConstant, SPIRV_OC_OpSpecConstantComposite,
+      SPIRV_OC_OpSpecConstantOp, SPIRV_OC_OpFunction, SPIRV_OC_OpFunctionParameter,
+      SPIRV_OC_OpFunctionEnd, SPIRV_OC_OpFunctionCall, SPIRV_OC_OpVariable,
+      SPIRV_OC_OpLoad, SPIRV_OC_OpStore, SPIRV_OC_OpCopyMemory,
+      SPIRV_OC_OpAccessChain, SPIRV_OC_OpPtrAccessChain,
+      SPIRV_OC_OpInBoundsPtrAccessChain, SPIRV_OC_OpDecorate,
+      SPIRV_OC_OpMemberDecorate, SPIRV_OC_OpVectorExtractDynamic,
+      SPIRV_OC_OpVectorInsertDynamic, SPIRV_OC_OpVectorShuffle,
+      SPIRV_OC_OpCompositeConstruct, SPIRV_OC_OpCompositeExtract,
       SPIRV_OC_OpCompositeInsert, SPIRV_OC_OpTranspose, SPIRV_OC_OpImageDrefGather,
       SPIRV_OC_OpImage, SPIRV_OC_OpImageQuerySize, SPIRV_OC_OpConvertFToU,
       SPIRV_OC_OpConvertFToS, SPIRV_OC_OpConvertSToF, SPIRV_OC_OpConvertUToF,
-      SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert, SPIRV_OC_OpFConvert, SPIRV_OC_OpPtrCastToGeneric,
-      SPIRV_OC_OpGenericCastToPtr, SPIRV_OC_OpGenericCastToPtrExplicit, SPIRV_OC_OpBitcast,
-      SPIRV_OC_OpSNegate, SPIRV_OC_OpFNegate, SPIRV_OC_OpIAdd, SPIRV_OC_OpFAdd,
-      SPIRV_OC_OpISub, SPIRV_OC_OpFSub, SPIRV_OC_OpIMul, SPIRV_OC_OpFMul, SPIRV_OC_OpUDiv,
-      SPIRV_OC_OpSDiv, SPIRV_OC_OpFDiv, SPIRV_OC_OpUMod, SPIRV_OC_OpSRem, SPIRV_OC_OpSMod,
-      SPIRV_OC_OpFRem, SPIRV_OC_OpFMod, SPIRV_OC_OpVectorTimesScalar,
-      SPIRV_OC_OpMatrixTimesScalar, SPIRV_OC_OpMatrixTimesMatrix, SPIRV_OC_OpIAddCarry,
-      SPIRV_OC_OpISubBorrow, SPIRV_OC_OpUMulExtended, SPIRV_OC_OpSMulExtended, SPIRV_OC_OpIsNan,
-      SPIRV_OC_OpIsInf, SPIRV_OC_OpOrdered, SPIRV_OC_OpUnordered, SPIRV_OC_OpLogicalEqual,
-      SPIRV_OC_OpLogicalNotEqual, SPIRV_OC_OpLogicalOr, SPIRV_OC_OpLogicalAnd, SPIRV_OC_OpLogicalNot,
-      SPIRV_OC_OpSelect, SPIRV_OC_OpIEqual, SPIRV_OC_OpINotEqual, SPIRV_OC_OpUGreaterThan,
-      SPIRV_OC_OpSGreaterThan, SPIRV_OC_OpUGreaterThanEqual, SPIRV_OC_OpSGreaterThanEqual,
-      SPIRV_OC_OpULessThan, SPIRV_OC_OpSLessThan, SPIRV_OC_OpULessThanEqual,
-      SPIRV_OC_OpSLessThanEqual, SPIRV_OC_OpFOrdEqual, SPIRV_OC_OpFUnordEqual,
-      SPIRV_OC_OpFOrdNotEqual, SPIRV_OC_OpFUnordNotEqual, SPIRV_OC_OpFOrdLessThan,
-      SPIRV_OC_OpFUnordLessThan, SPIRV_OC_OpFOrdGreaterThan, SPIRV_OC_OpFUnordGreaterThan,
-      SPIRV_OC_OpFOrdLessThanEqual, SPIRV_OC_OpFUnordLessThanEqual,
-      SPIRV_OC_OpFOrdGreaterThanEqual, SPIRV_OC_OpFUnordGreaterThanEqual,
-      SPIRV_OC_OpShiftRightLogical, SPIRV_OC_OpShiftRightArithmetic,
-      SPIRV_OC_OpShiftLeftLogical, SPIRV_OC_OpBitwiseOr, SPIRV_OC_OpBitwiseXor,
-      SPIRV_OC_OpBitwiseAnd, SPIRV_OC_OpNot, SPIRV_OC_OpBitFieldInsert,
-      SPIRV_OC_OpBitFieldSExtract, SPIRV_OC_OpBitFieldUExtract, SPIRV_OC_OpBitReverse,
-      SPIRV_OC_OpBitCount, SPIRV_OC_OpControlBarrier, SPIRV_OC_OpMemoryBarrier,
-      SPIRV_OC_OpAtomicExchange, SPIRV_OC_OpAtomicCompareExchange,
-      SPIRV_OC_OpAtomicCompareExchangeWeak, SPIRV_OC_OpAtomicIIncrement,
-      SPIRV_OC_OpAtomicIDecrement, SPIRV_OC_OpAtomicIAdd, SPIRV_OC_OpAtomicISub,
-      SPIRV_OC_OpAtomicSMin, SPIRV_OC_OpAtomicUMin, SPIRV_OC_OpAtomicSMax,
-      SPIRV_OC_OpAtomicUMax, SPIRV_OC_OpAtomicAnd, SPIRV_OC_OpAtomicOr, SPIRV_OC_OpAtomicXor,
-      SPIRV_OC_OpPhi, SPIRV_OC_OpLoopMerge, SPIRV_OC_OpSelectionMerge, SPIRV_OC_OpLabel,
-      SPIRV_OC_OpBranch, SPIRV_OC_OpBranchConditional, SPIRV_OC_OpReturn,
-      SPIRV_OC_OpReturnValue, SPIRV_OC_OpUnreachable, SPIRV_OC_OpGroupBroadcast,
+      SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert, SPIRV_OC_OpFConvert,
+      SPIRV_OC_OpPtrCastToGeneric, SPIRV_OC_OpGenericCastToPtr,
+      SPIRV_OC_OpGenericCastToPtrExplicit, SPIRV_OC_OpBitcast, SPIRV_OC_OpSNegate,
+      SPIRV_OC_OpFNegate, SPIRV_OC_OpIAdd, SPIRV_OC_OpFAdd, SPIRV_OC_OpISub,
+      SPIRV_OC_OpFSub, SPIRV_OC_OpIMul, SPIRV_OC_OpFMul, SPIRV_OC_OpUDiv,
+      SPIRV_OC_OpSDiv, SPIRV_OC_OpFDiv, SPIRV_OC_OpUMod, SPIRV_OC_OpSRem,
+      SPIRV_OC_OpSMod, SPIRV_OC_OpFRem, SPIRV_OC_OpFMod,
+      SPIRV_OC_OpVectorTimesScalar, SPIRV_OC_OpMatrixTimesScalar,
+      SPIRV_OC_OpMatrixTimesMatrix, SPIRV_OC_OpIAddCarry, SPIRV_OC_OpISubBorrow,
+      SPIRV_OC_OpUMulExtended, SPIRV_OC_OpSMulExtended, SPIRV_OC_OpIsNan,
+      SPIRV_OC_OpIsInf, SPIRV_OC_OpOrdered, SPIRV_OC_OpUnordered,
+      SPIRV_OC_OpLogicalEqual, SPIRV_OC_OpLogicalNotEqual, SPIRV_OC_OpLogicalOr,
+      SPIRV_OC_OpLogicalAnd, SPIRV_OC_OpLogicalNot, SPIRV_OC_OpSelect,
+      SPIRV_OC_OpIEqual, SPIRV_OC_OpINotEqual, SPIRV_OC_OpUGreaterThan,
+      SPIRV_OC_OpSGreaterThan, SPIRV_OC_OpUGreaterThanEqual,
+      SPIRV_OC_OpSGreaterThanEqual, SPIRV_OC_OpULessThan, SPIRV_OC_OpSLessThan,
+      SPIRV_OC_OpULessThanEqual, SPIRV_OC_OpSLessThanEqual, SPIRV_OC_OpFOrdEqual,
+      SPIRV_OC_OpFUnordEqual, SPIRV_OC_OpFOrdNotEqual, SPIRV_OC_OpFUnordNotEqual,
+      SPIRV_OC_OpFOrdLessThan, SPIRV_OC_OpFUnordLessThan, SPIRV_OC_OpFOrdGreaterThan,
+      SPIRV_OC_OpFUnordGreaterThan, SPIRV_OC_OpFOrdLessThanEqual,
+      SPIRV_OC_OpFUnordLessThanEqual, SPIRV_OC_OpFOrdGreaterThanEqual,
+      SPIRV_OC_OpFUnordGreaterThanEqual, SPIRV_OC_OpShiftRightLogical,
+      SPIRV_OC_OpShiftRightArithmetic, SPIRV_OC_OpShiftLeftLogical,
+      SPIRV_OC_OpBitwiseOr, SPIRV_OC_OpBitwiseXor, SPIRV_OC_OpBitwiseAnd,
+      SPIRV_OC_OpNot, SPIRV_OC_OpBitFieldInsert, SPIRV_OC_OpBitFieldSExtract,
+      SPIRV_OC_OpBitFieldUExtract, SPIRV_OC_OpBitReverse, SPIRV_OC_OpBitCount,
+      SPIRV_OC_OpControlBarrier, SPIRV_OC_OpMemoryBarrier, SPIRV_OC_OpAtomicExchange,
+      SPIRV_OC_OpAtomicCompareExchange, SPIRV_OC_OpAtomicCompareExchangeWeak,
+      SPIRV_OC_OpAtomicIIncrement, SPIRV_OC_OpAtomicIDecrement,
+      SPIRV_OC_OpAtomicIAdd, SPIRV_OC_OpAtomicISub, SPIRV_OC_OpAtomicSMin,
+      SPIRV_OC_OpAtomicUMin, SPIRV_OC_OpAtomicSMax, SPIRV_OC_OpAtomicUMax,
+      SPIRV_OC_OpAtomicAnd, SPIRV_OC_OpAtomicOr, SPIRV_OC_OpAtomicXor,
+      SPIRV_OC_OpPhi, SPIRV_OC_OpLoopMerge, SPIRV_OC_OpSelectionMerge,
+      SPIRV_OC_OpLabel, SPIRV_OC_OpBranch, SPIRV_OC_OpBranchConditional,
+      SPIRV_OC_OpReturn, SPIRV_OC_OpReturnValue, SPIRV_OC_OpUnreachable,
+      SPIRV_OC_OpGroupBroadcast, SPIRV_OC_OpGroupIAdd, SPIRV_OC_OpGroupFAdd,
+      SPIRV_OC_OpGroupFMin, SPIRV_OC_OpGroupUMin, SPIRV_OC_OpGroupSMin,
+      SPIRV_OC_OpGroupFMax, SPIRV_OC_OpGroupUMax, SPIRV_OC_OpGroupSMax,
       SPIRV_OC_OpNoLine, SPIRV_OC_OpModuleProcessed, SPIRV_OC_OpGroupNonUniformElect,
       SPIRV_OC_OpGroupNonUniformBroadcast, SPIRV_OC_OpGroupNonUniformBallot,
       SPIRV_OC_OpGroupNonUniformShuffle, SPIRV_OC_OpGroupNonUniformShuffleXor,
@@ -4430,7 +4451,8 @@ def SPIRV_OpcodeAttr :
       SPIRV_OC_OpCooperativeMatrixLoadNV, SPIRV_OC_OpCooperativeMatrixStoreNV,
       SPIRV_OC_OpCooperativeMatrixMulAddNV, SPIRV_OC_OpCooperativeMatrixLengthNV,
       SPIRV_OC_OpSubgroupBlockReadINTEL, SPIRV_OC_OpSubgroupBlockWriteINTEL,
-      SPIRV_OC_OpAssumeTrueKHR, SPIRV_OC_OpAtomicFAddEXT,
+      SPIRV_OC_OpAssumeTrueKHR, SPIRV_OC_OpAtomicFAddEXT, SPIRV_OC_OpGroupIMulKHR,
+      SPIRV_OC_OpGroupFMulKHR,
 
       SPIRV_OC_OpTypeJointMatrixINTEL, SPIRV_OC_OpJointMatrixLoadINTEL,
       SPIRV_OC_OpJointMatrixStoreINTEL, SPIRV_OC_OpJointMatrixMadINTEL,

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGroupOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGroupOps.td
index 8c43107a0dc94..0d2f416947c51 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGroupOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGroupOps.td
@@ -17,6 +17,69 @@
 
 // -----
 
+def SPIRV_GroupFMulKHROp : SPIRV_KhrVendorOp<"GroupFMul", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    A floating-point multiplication group operation specified for all values of
+    'X' specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    'Execution' reach this point of execution.
+
+    Behavior is undefined unless all invocations within 'Execution' execute the
+    same dynamic instance of this instruction.
+
+    'Result Type' must be a scalar or vector of floating-point type.
+
+    'Execution' is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for 'Operation' is 1.
+
+    The type of 'X' must be the same as 'Result Type'.
+
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.KHR.GroupFMul` scope operation ssa-use
+                            `:` float-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.KHR.GroupFMul <Workgroup> <Reduce> %value : f32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_GroupUniformArithmeticKHR]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
 def SPIRV_GroupBroadcastOp : SPIRV_Op<"GroupBroadcast",
                               [Pure,
                                AllTypesMatch<["value", "result"]>]> {
@@ -93,56 +156,564 @@ def SPIRV_GroupBroadcastOp : SPIRV_Op<"GroupBroadcast",
 
 // -----
 
-def SPIRV_KHRSubgroupBallotOp : SPIRV_KhrVendorOp<"SubgroupBallot", []> {
-  let summary = "See extension SPV_KHR_shader_ballot";
+def SPIRV_GroupFAddOp : SPIRV_Op<"GroupFAdd", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    A floating-point add group operation specified for all values of X
+    specified by invocations in the group.
+  }];
 
   let description = [{
-    Computes a bitfield value combining the Predicate value from all invocations
-    in the current Subgroup that execute the same dynamic instance of this
-    instruction. The bit is set to one if the corresponding invocation is active
-    and the predicate is evaluated to true; otherwise, it is set to zero.
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
 
-    Predicate must be a Boolean type.
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
 
-    Result Type must be a 4 component vector of 32 bit integer types.
+    Result Type  must be a scalar or vector of floating-point type.
 
-    Result is a set of bitfields where the first invocation is represented in bit
-    0 of the first vector component and the last (up to SubgroupSize) is the
-    higher bit number of the last bitmask needed to represent all bits of the
-    subgroup invocations.
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is 0.
+
+     The type of X must be the same as Result Type.
 
     <!-- End of AutoGen section -->
 
     ```
-    subgroup-ballot-op ::= ssa-id `=` `spirv.KHR.SubgroupBallot`
-                                ssa-use `:` `vector` `<` 4 `x` `i32` `>`
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupFAdd` scope operation ssa-use
+                            `:` float-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupFAdd <Workgroup> <Reduce> %value : f32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupFMaxOp : SPIRV_Op<"GroupFMax", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    A floating-point maximum group operation specified for all values of X
+    specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of floating-point type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is -INF.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
     ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupFMax` scope operation ssa-use
+                            `:` float-type
+    ```mlir
 
     #### Example:
 
+    ```
+    %0 = spirv.GroupFMax <Workgroup> <Reduce> %value : f32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupFMinOp : SPIRV_Op<"GroupFMin", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    A floating-point minimum group operation specified for all values of X
+    specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of floating-point type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is +INF.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupFMin` scope operation ssa-use
+                            `:` float-type
     ```mlir
-    %0 = spirv.KHR.SubgroupBallot %predicate : vector<4xi32>
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupFMin <Workgroup> <Reduce> %value : f32
     ```
   }];
 
   let availability = [
     MinVersion<SPIRV_V_1_0>,
     MaxVersion<SPIRV_V_1_6>,
-    Extension<[SPV_KHR_shader_ballot]>,
-    Capability<[SPIRV_C_SubgroupBallotKHR]>
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
   ];
 
   let arguments = (ins
-    SPIRV_Bool:$predicate
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$x
   );
 
   let results = (outs
-    SPIRV_Int32Vec4:$result
+    SPIRV_ScalarOrVectorOf<SPIRV_Float>:$result
   );
 
-  let hasVerifier = 0;
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
 
-  let assemblyFormat = "$predicate attr-dict `:` type($result)";
+// -----
+
+def SPIRV_GroupIAddOp : SPIRV_Op<"GroupIAdd", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    An integer add group operation specified for all values of X specified
+    by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of integer type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is 0.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupIAdd` scope operation ssa-use
+                            `:` integer-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupIAdd <Workgroup> <Reduce> %value : i32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupIMulKHROp : SPIRV_KhrVendorOp<"GroupIMul", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    An integer multiplication group operation specified for all values of 'X'
+    specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    'Execution' reach this point of execution.
+
+    Behavior is undefined unless all invocations within 'Execution' execute the
+    same dynamic instance of this instruction.
+
+    'Result Type' must be a scalar or vector of integer type.
+
+    'Execution' is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for 'Operation' is 1.
+
+    The type of 'X' must be the same as 'Result Type'.
+
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.KHR.GroupIMul` scope operation ssa-use
+                            `:` integer-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.KHR.GroupIMul <Workgroup> <Reduce> %value : i32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_GroupUniformArithmeticKHR]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupSMaxOp : SPIRV_Op<"GroupSMax", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    A signed integer maximum group operation specified for all values of X
+    specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of integer type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is INT_MIN when X is 32 bits wide and
+    LONG_MIN when X is 64 bits wide.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupSMax` scope operation ssa-use
+                            `:` integer-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupSMax <Workgroup> <Reduce> %value : i32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupSMinOp : SPIRV_Op<"GroupSMin", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    A signed integer minimum group operation specified for all values of X
+    specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of integer type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is INT_MAX when X is 32 bits wide and
+    LONG_MAX when X is 64 bits wide.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupSMin` scope operation ssa-use
+                            `:` integer-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupSMin <Workgroup> <Reduce> %value : i32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupUMaxOp : SPIRV_Op<"GroupUMax", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    An unsigned integer maximum group operation specified for all values of
+    X specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of integer type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is 0.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupUMax` scope operation ssa-use
+                            `:` integer-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupUMax <Workgroup> <Reduce> %value : i32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
+}
+
+// -----
+
+def SPIRV_GroupUMinOp : SPIRV_Op<"GroupUMin", [Pure,
+                               AllTypesMatch<["x", "result"]>]> {
+  let summary = [{
+    An unsigned integer minimum group operation specified for all values of
+    X specified by invocations in the group.
+  }];
+
+  let description = [{
+    Behavior is undefined if not all invocations of this module within
+    Execution reach this point of execution.
+
+    Behavior is undefined unless all invocations within Execution execute
+    the same dynamic instance of this instruction.
+
+    Result Type  must be a scalar or vector of integer type.
+
+    Execution is a Scope. It must be either Workgroup or Subgroup.
+
+    The identity I for Operation is UINT_MAX when X is 32 bits wide and
+    ULONG_MAX when X is 64 bits wide.
+
+     The type of X must be the same as Result Type.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    scope ::= `"Workgroup"` | `"Subgroup"`
+    operation ::= `"Reduce"` | `"InclusiveScan"` | `"ExclusiveScan"`
+    op ::= ssa-id `=` `spirv.GroupUMin` scope operation ssa-use
+                            `:` integer-type
+    ```mlir
+
+    #### Example:
+
+    ```
+    %0 = spirv.GroupUMin <Workgroup> <Reduce> %value : i32
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[SPIRV_C_Groups]>
+  ];
+
+  let arguments = (ins
+    SPIRV_ScopeAttr:$execution_scope,
+    SPIRV_GroupOperationAttr:$group_operation,
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$x
+  );
+
+  let results = (outs
+    SPIRV_ScalarOrVectorOf<SPIRV_Integer>:$result
+  );
+
+  let assemblyFormat = [{
+    $execution_scope $group_operation operands attr-dict `:` type($x)
+  }];
 }
 
 // -----
@@ -247,4 +818,58 @@ def SPIRV_INTELSubgroupBlockWriteOp : SPIRV_IntelVendorOp<"SubgroupBlockWrite",
 
 // -----
 
+def SPIRV_KHRSubgroupBallotOp : SPIRV_KhrVendorOp<"SubgroupBallot", []> {
+  let summary = "See extension SPV_KHR_shader_ballot";
+
+  let description = [{
+    Computes a bitfield value combining the Predicate value from all invocations
+    in the current Subgroup that execute the same dynamic instance of this
+    instruction. The bit is set to one if the corresponding invocation is active
+    and the predicate is evaluated to true; otherwise, it is set to zero.
+
+    Predicate must be a Boolean type.
+
+    Result Type must be a 4 component vector of 32 bit integer types.
+
+    Result is a set of bitfields where the first invocation is represented in bit
+    0 of the first vector component and the last (up to SubgroupSize) is the
+    higher bit number of the last bitmask needed to represent all bits of the
+    subgroup invocations.
+
+    <!-- End of AutoGen section -->
+
+    ```
+    subgroup-ballot-op ::= ssa-id `=` `spirv.KHR.SubgroupBallot`
+                                ssa-use `:` `vector` `<` 4 `x` `i32` `>`
+    ```
+
+    #### Example:
+
+    ```mlir
+    %0 = spirv.KHR.SubgroupBallot %predicate : vector<4xi32>
+    ```
+  }];
+
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[SPV_KHR_shader_ballot]>,
+    Capability<[SPIRV_C_SubgroupBallotKHR]>
+  ];
+
+  let arguments = (ins
+    SPIRV_Bool:$predicate
+  );
+
+  let results = (outs
+    SPIRV_Int32Vec4:$result
+  );
+
+  let hasVerifier = 0;
+
+  let assemblyFormat = "$predicate attr-dict `:` type($result)";
+}
+
+// -----
+
 #endif // MLIR_DIALECT_SPIRV_IR_GROUP_OPS

diff  --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
index 606562292ebcf..9a509796e5c19 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -4770,6 +4770,39 @@ LogicalResult spirv::VectorTimesScalarOp::verify() {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// Group ops
+//===----------------------------------------------------------------------===//
+
+template <typename Op>
+static LogicalResult verifyGroupOp(Op op) {
+  spirv::Scope scope = op.getExecutionScope();
+  if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
+    return op.emitOpError("execution scope must be 'Workgroup' or 'Subgroup'");
+
+  return success();
+}
+
+LogicalResult spirv::GroupIAddOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupFAddOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupFMinOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupUMinOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupSMinOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupFMaxOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupUMaxOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupSMaxOp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupIMulKHROp::verify() { return verifyGroupOp(*this); }
+
+LogicalResult spirv::GroupFMulKHROp::verify() { return verifyGroupOp(*this); }
+
 // TableGen'erated operation interfaces for querying versions, extensions, and
 // capabilities.
 #include "mlir/Dialect/SPIRV/IR/SPIRVAvailability.cpp.inc"

diff  --git a/mlir/test/Dialect/SPIRV/IR/group-ops.mlir b/mlir/test/Dialect/SPIRV/IR/group-ops.mlir
index 061d3f0d798b4..741081a37d8a0 100644
--- a/mlir/test/Dialect/SPIRV/IR/group-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/group-ops.mlir
@@ -112,3 +112,87 @@ func.func @subgroup_block_write_intel_vector(%ptr : !spirv.ptr<i32, StorageBuffe
   spirv.INTEL.SubgroupBlockWrite "StorageBuffer" %ptr, %value : vector<3xi32>
   return
 }
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// Group ops
+//===----------------------------------------------------------------------===//
+
+func.func @group_iadd(%value: i32) -> i32 {
+  // CHECK: spirv.GroupIAdd <Workgroup> <Reduce> %{{.*}} : i32
+  %0 = spirv.GroupIAdd <Workgroup> <Reduce> %value : i32
+  return %0: i32
+}
+
+// -----
+
+func.func @group_fadd(%value: f32) -> f32 {
+  // CHECK: spirv.GroupFAdd <Workgroup> <Reduce> %{{.*}} : f32
+  %0 = spirv.GroupFAdd <Workgroup> <Reduce> %value : f32
+  return %0: f32
+}
+
+// -----
+
+func.func @group_fmin(%value: f32) -> f32 {
+  // CHECK: spirv.GroupFMin <Workgroup> <Reduce> %{{.*}} : f32
+  %0 = spirv.GroupFMin <Workgroup> <Reduce> %value : f32
+  return %0: f32
+}
+
+// -----
+
+func.func @group_umin(%value: i32) -> i32 {
+  // CHECK: spirv.GroupUMin <Workgroup> <Reduce> %{{.*}} : i32
+  %0 = spirv.GroupUMin <Workgroup> <Reduce> %value : i32
+  return %0: i32
+}
+
+// -----
+
+func.func @group_smin(%value: i32) -> i32 {
+  // CHECK: spirv.GroupSMin <Workgroup> <Reduce> %{{.*}} : i32
+  %0 = spirv.GroupSMin <Workgroup> <Reduce> %value : i32
+  return %0: i32
+}
+
+// -----
+
+func.func @group_fmax(%value: f32) -> f32 {
+  // CHECK: spirv.GroupFMax <Workgroup> <Reduce> %{{.*}} : f32
+  %0 = spirv.GroupFMax <Workgroup> <Reduce> %value : f32
+  return %0: f32
+}
+
+// -----
+
+func.func @group_umax(%value: i32) -> i32 {
+  // CHECK: spirv.GroupUMax <Workgroup> <Reduce> %{{.*}} : i32
+  %0 = spirv.GroupUMax <Workgroup> <Reduce> %value : i32
+  return %0: i32
+}
+
+// -----
+
+func.func @group_smax(%value: i32) -> i32 {
+  // CHECK: spirv.GroupSMax <Workgroup> <Reduce> %{{.*}} : i32
+  %0 = spirv.GroupSMax <Workgroup> <Reduce> %value : i32
+  return %0: i32
+}
+
+// -----
+
+func.func @group_imul(%value: i32) -> i32 {
+  // CHECK: spirv.KHR.GroupIMul <Workgroup> <Reduce> %{{.*}} : i32
+  %0 = spirv.KHR.GroupIMul <Workgroup> <Reduce> %value : i32
+  return %0: i32
+}
+
+// -----
+
+func.func @group_fmul(%value: f32) -> f32 {
+  // CHECK: spirv.KHR.GroupFMul <Workgroup> <Reduce> %{{.*}} : f32
+  %0 = spirv.KHR.GroupFMul <Workgroup> <Reduce> %value : f32
+  return %0: f32
+}

diff  --git a/mlir/test/Target/SPIRV/group-ops.mlir b/mlir/test/Target/SPIRV/group-ops.mlir
index 5a17e89463f78..dc07f8c8ef61f 100644
--- a/mlir/test/Target/SPIRV/group-ops.mlir
+++ b/mlir/test/Target/SPIRV/group-ops.mlir
@@ -43,4 +43,65 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
     spirv.INTEL.SubgroupBlockWrite "StorageBuffer" %ptr, %value : vector<3xi32>
     spirv.Return
   }
+  // CHECK-LABEL: @group_iadd
+  spirv.func @group_iadd(%value: i32) -> i32 "None" {
+    // CHECK: spirv.GroupIAdd <Workgroup> <Reduce> %{{.*}} : i32
+    %0 = spirv.GroupIAdd <Workgroup> <Reduce> %value : i32
+    spirv.ReturnValue %0: i32
+  }
+  // CHECK-LABEL: @group_fadd
+  spirv.func @group_fadd(%value: f32) -> f32 "None" {
+    // CHECK: spirv.GroupFAdd <Workgroup> <Reduce> %{{.*}} : f32
+    %0 = spirv.GroupFAdd <Workgroup> <Reduce> %value : f32
+    spirv.ReturnValue %0: f32
+  }
+  // CHECK-LABEL: @group_fmin
+  spirv.func @group_fmin(%value: f32) -> f32 "None" {
+    // CHECK: spirv.GroupFMin <Workgroup> <Reduce> %{{.*}} : f32
+    %0 = spirv.GroupFMin <Workgroup> <Reduce> %value : f32
+    spirv.ReturnValue %0: f32
+  }
+  // CHECK-LABEL: @group_umin
+  spirv.func @group_umin(%value: i32) -> i32 "None" {
+    // CHECK: spirv.GroupUMin <Workgroup> <Reduce> %{{.*}} : i32
+    %0 = spirv.GroupUMin <Workgroup> <Reduce> %value : i32
+    spirv.ReturnValue %0: i32
+  }
+  // CHECK-LABEL: @group_smin
+  spirv.func @group_smin(%value: i32) -> i32 "None" {
+    // CHECK: spirv.GroupSMin <Workgroup> <Reduce> %{{.*}} : i32
+    %0 = spirv.GroupSMin <Workgroup> <Reduce> %value : i32
+    spirv.ReturnValue %0: i32
+  }
+  // CHECK-LABEL: @group_fmax
+  spirv.func @group_fmax(%value: f32) -> f32 "None" {
+    // CHECK: spirv.GroupFMax <Workgroup> <Reduce> %{{.*}} : f32
+    %0 = spirv.GroupFMax <Workgroup> <Reduce> %value : f32
+    spirv.ReturnValue %0: f32
+  }
+  // CHECK-LABEL: @group_umax
+  spirv.func @group_umax(%value: i32) -> i32 "None" {
+    // CHECK: spirv.GroupUMax <Workgroup> <Reduce> %{{.*}} : i32
+    %0 = spirv.GroupUMax <Workgroup> <Reduce> %value : i32
+    spirv.ReturnValue %0: i32
+  }
+  // CHECK-LABEL: @group_smax
+  spirv.func @group_smax(%value: i32) -> i32 "None" {
+    // CHECK: spirv.GroupSMax <Workgroup> <Reduce> %{{.*}} : i32
+    %0 = spirv.GroupSMax <Workgroup> <Reduce> %value : i32
+    spirv.ReturnValue %0: i32
+  }
+  // CHECK-LABEL: @group_imul
+  spirv.func @group_imul(%value: i32) -> i32 "None" {
+    // CHECK: spirv.KHR.GroupIMul <Workgroup> <Reduce> %{{.*}} : i32
+    %0 = spirv.KHR.GroupIMul <Workgroup> <Reduce> %value : i32
+    spirv.ReturnValue %0: i32
+  }
+  // CHECK-LABEL: @group_fmul
+  spirv.func @group_fmul(%value: f32) -> f32 "None" {
+    // CHECK: spirv.KHR.GroupFMul <Workgroup> <Reduce> %{{.*}} : f32
+    %0 = spirv.KHR.GroupFMul <Workgroup> <Reduce> %value : f32
+    spirv.ReturnValue %0: f32
+  }
+
 }

diff  --git a/mlir/utils/spirv/gen_spirv_dialect.py b/mlir/utils/spirv/gen_spirv_dialect.py
index ce9e8c66c63c6..94ab267ae3116 100755
--- a/mlir/utils/spirv/gen_spirv_dialect.py
+++ b/mlir/utils/spirv/gen_spirv_dialect.py
@@ -568,7 +568,8 @@ def update_td_opcodes(path, instructions, filter_list):
   assert len(content) == 3
 
   # Extend opcode list with existing list
-  existing_opcodes = [k[11:] for k in re.findall('def SPIRV_OC_\w+', content[1])]
+  prefix = 'def SPIRV_OC_'
+  existing_opcodes = [k[len(prefix):] for k in re.findall(prefix + '\w+', content[1])]
   filter_list.extend(existing_opcodes)
   filter_list = list(set(filter_list))
 


        


More information about the Mlir-commits mailing list