From 20d70fccac046f3aab645c2dd96e4fcfa3d04179 Mon Sep 17 00:00:00 2001 From: Igor Wodiany Date: Fri, 13 Jun 2025 10:36:25 +0100 Subject: [PATCH 1/4] [mlir][spirv] Add definition for GL Length --- .../mlir/Dialect/SPIRV/IR/SPIRVGLOps.td | 40 +++++++++++ mlir/test/Dialect/SPIRV/IR/gl-ops.mlir | 66 +++++++++++++++++++ mlir/test/Target/SPIRV/gl-ops.mlir | 4 ++ 3 files changed, 110 insertions(+) diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td index 2ec61758ba8ef..8c4da9b2dce18 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td @@ -1160,6 +1160,46 @@ def SPIRV_GLFMixOp : // ----- +def SPIRV_GLLengthOp : SPIRV_GLOp<"Length", 66, [ + Pure, + TypesMatchWith<"result type must match operand element type", + "operand", "result", + "::mlir::getElementTypeOrSelf($_self)"> + ]> { + let summary = "Return the length of a vector x"; + + let description = [{ + Result is the length of vector x, i.e., sqrt(x[0]**2 + x[1]**2 + ...). + + The operand x must be a scalar or vector whose component type is floating-point. + + Result Type must be a scalar of the same type as the component type of x. + + #### Example: + + ```mlir + %2 = spirv.GL.Length %0 : vector<3xf32> -> f32 + %3 = spirv.GL.Length %1 : f32 -> f32 + ``` + }]; + + let arguments = (ins + SPIRV_ScalarOrVectorOf:$operand + ); + + let results = (outs + SPIRV_Float:$result + ); + + let assemblyFormat = [{ + $operand attr-dict `:` type($operand) `->` type($result) + }]; + + let hasVerifier = 0; +} + +// ----- + def SPIRV_GLDistanceOp : SPIRV_GLOp<"Distance", 67, [ Pure, AllTypesMatch<["p0", "p1"]>, diff --git a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir index 2b75767feaf92..f49be21fcf783 100644 --- a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir +++ b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir @@ -983,3 +983,69 @@ func.func @unpack_half_2x16_scalar_out(%arg0 : i32) -> () { %0 = spirv.GL.UnpackHalf2x16 %arg0 : i32 -> f32 return } + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.GL.Length +//===----------------------------------------------------------------------===// + +func.func @length(%arg0 : f32) -> () { + // CHECK: spirv.GL.Length {{%.*}} : f32 -> f32 + %0 = spirv.GL.Length %arg0 : f32 -> f32 + return +} + +func.func @lengthvec(%arg0 : vector<3xf32>) -> () { + // CHECK: spirv.GL.Length {{%.*}} : vector<3xf32> -> f32 + %0 = spirv.GL.Length %arg0 : vector<3xf32> -> f32 + return +} + +// ----- + +func.func @length_i32_in(%arg0 : i32) -> () { + // expected-error @+1 {{op operand #0 must be 16/32/64-bit float or vector of 16/32/64-bit float values of length 2/3/4/8/16, but got 'i32'}} + %0 = spirv.GL.Length %arg0 : i32 -> f32 + return +} + +// ----- + +func.func @length_f16_in(%arg0 : f16) -> () { + // expected-error @+1 {{op failed to verify that result type must match operand element type}} + %0 = spirv.GL.Length %arg0 : f16 -> f32 + return +} + +// ----- + +func.func @length_i32vec_in(%arg0 : vector<3xi32>) -> () { + // expected-error @+1 {{op operand #0 must be 16/32/64-bit float or vector of 16/32/64-bit float values of length 2/3/4/8/16, but got 'vector<3xi32>'}} + %0 = spirv.GL.Length %arg0 : vector<3xi32> -> f32 + return +} + +// ----- + +func.func @length_f16vec_in(%arg0 : vector<3xf16>) -> () { + // expected-error @+1 {{op failed to verify that result type must match operand element type}} + %0 = spirv.GL.Length %arg0 : vector<3xf16> -> f32 + return +} + +// ----- + +func.func @length_i32_out(%arg0 : vector<3xf32>) -> () { + // expected-error @+1 {{op result #0 must be 16/32/64-bit float, but got 'i32'}} + %0 = spirv.GL.Length %arg0 : vector<3xf32> -> i32 + return +} + +// ----- + +func.func @length_vec_out(%arg0 : vector<3xf32>) -> () { + // expected-error @+1 {{op result #0 must be 16/32/64-bit float, but got 'vector<3xf32>'}} + %0 = spirv.GL.Length %arg0 : vector<3xf32> -> vector<3xf32> + return +} diff --git a/mlir/test/Target/SPIRV/gl-ops.mlir b/mlir/test/Target/SPIRV/gl-ops.mlir index eacf36bfba9ce..832f7ea2fe314 100644 --- a/mlir/test/Target/SPIRV/gl-ops.mlir +++ b/mlir/test/Target/SPIRV/gl-ops.mlir @@ -128,6 +128,10 @@ spirv.module Logical GLSL450 requires #spirv.vce { %8 = spirv.GL.FindSMsb %arg3 : vector<3xi32> // CHECK: {{%.*}} = spirv.GL.FindUMsb {{%.*}} : vector<3xi32> %9 = spirv.GL.FindUMsb %arg3 : vector<3xi32> + // CHECK: {{%.*}} = spirv.GL.Length {{%.*}} : f32 -> f32 + %10 = spirv.GL.Length %arg0 : f32 -> f32 + // CHECK: {{%.*}} = spirv.GL.Length {{%.*}} : vector<3xf32> -> f32 + %11 = spirv.GL.Length %arg1 : vector<3xf32> -> f32 spirv.Return } From 7a08d1f8780c02b27f82c460cff577626ecaca27 Mon Sep 17 00:00:00 2001 From: Igor Wodiany Date: Mon, 16 Jun 2025 10:09:53 +0100 Subject: [PATCH 2/4] Add canonicalization --- .../mlir/Dialect/SPIRV/IR/SPIRVGLOps.td | 1 + .../SPIRV/IR/SPIRVCanonicalization.cpp | 9 ++++++++ .../Dialect/SPIRV/IR/SPIRVCanonicalization.td | 8 +++++++ .../SPIRV/Transforms/canonicalize.mlir | 21 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td index 8c4da9b2dce18..4e5188a11f0ac 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td @@ -1196,6 +1196,7 @@ def SPIRV_GLLengthOp : SPIRV_GLOp<"Length", 66, [ }]; let hasVerifier = 0; + let hasCanonicalizer = 1; } // ----- diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp index 03af61c81ae6c..1363ee4a41cb9 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp @@ -1403,3 +1403,12 @@ void spirv::SelectionOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { results.add(context); } + +//===----------------------------------------------------------------------===// +// spirv.GL.Length +//===----------------------------------------------------------------------===// + +void spirv::GLLengthOp::getCanonicalizationPatterns(RewritePatternSet &results, + MLIRContext *context) { + results.add(context); +} diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td index e8d2274d29aa0..39fbab8f37a2e 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.td @@ -75,3 +75,11 @@ def ConvertComparisonIntoClamp2_#CmpClampPair[0] : Pat< )), (CmpClampPair[1] $input, $min, $max)>; } + +//===----------------------------------------------------------------------===// +// spirv.GL.Length -> spirv.GL.FAbs +//===----------------------------------------------------------------------===// + +def ConvertGLLengthToGLFAbs : Pat< + (SPIRV_GLLengthOp SPIRV_Float:$operand), + (SPIRV_GLFAbsOp $operand)>; diff --git a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir index 722c27586aa61..78f3a5fb5997e 100644 --- a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir +++ b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir @@ -2490,3 +2490,24 @@ func.func @cannot_canonicalize_selection_op_4(%cond: i1) -> () { } spirv.Return } + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.GL.Length +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @convert_length_into_fabs_scalar +func.func @convert_length_in_fabs_scalar(%arg0 : f32) -> f32 { + + %0 = spirv.GL.Length %arg0 : f32 -> f32 + //%11 = spirv.GL.Length %arg1 : vector<3xf32> -> f32 + spirv.ReturnValue %0 : f32 +} + +// CHECK-LABEL: @dont_convert_length_into_fabs_vec +func.func @dont_convert_length_in_fabs_vec(%arg0 : vector<3xf32>) -> f32 { + + %0 = spirv.GL.Length %arg0 : vector<3xf32> -> f32 + spirv.ReturnValue %0 : f32 +} From eaf00eef4bc95707a9b29f577dfc4e9b925e002e Mon Sep 17 00:00:00 2001 From: Igor Wodiany Date: Mon, 16 Jun 2025 16:07:41 +0100 Subject: [PATCH 3/4] Add CHECKs --- mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir index 78f3a5fb5997e..50e06e85a59a1 100644 --- a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir +++ b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir @@ -2498,16 +2498,17 @@ func.func @cannot_canonicalize_selection_op_4(%cond: i1) -> () { //===----------------------------------------------------------------------===// // CHECK-LABEL: @convert_length_into_fabs_scalar -func.func @convert_length_in_fabs_scalar(%arg0 : f32) -> f32 { - +func.func @convert_length_into_fabs_scalar(%arg0 : f32) -> f32 { + //CHECK: spirv.GL.FAbs {{%.*}} : f32 + //CHECK-NOT: spirv.GL.Length %0 = spirv.GL.Length %arg0 : f32 -> f32 - //%11 = spirv.GL.Length %arg1 : vector<3xf32> -> f32 spirv.ReturnValue %0 : f32 } // CHECK-LABEL: @dont_convert_length_into_fabs_vec -func.func @dont_convert_length_in_fabs_vec(%arg0 : vector<3xf32>) -> f32 { - +func.func @dont_convert_length_into_fabs_vec(%arg0 : vector<3xf32>) -> f32 { + //CHECK: spirv.GL.Length {{%.*}} : vector<3xf32> -> f32 + //CHECK-NOT: spirv.GL.FAbs %0 = spirv.GL.Length %arg0 : vector<3xf32> -> f32 spirv.ReturnValue %0 : f32 } From a4d05e0982c2ff9109c312e69efa57d55ddcc87d Mon Sep 17 00:00:00 2001 From: Igor Wodiany Date: Mon, 16 Jun 2025 16:40:51 +0100 Subject: [PATCH 4/4] Move into GL canonicalizer --- .../mlir/Dialect/SPIRV/IR/SPIRVGLOps.td | 1 - .../SPIRV/IR/SPIRVCanonicalization.cpp | 9 -------- .../SPIRV/IR/SPIRVGLCanonicalization.cpp | 4 ++-- .../SPIRV/Transforms/canonicalize.mlir | 22 ------------------- .../SPIRV/Transforms/gl-canonicalize.mlir | 22 +++++++++++++++++++ 5 files changed, 24 insertions(+), 34 deletions(-) diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td index 4e5188a11f0ac..8c4da9b2dce18 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td @@ -1196,7 +1196,6 @@ def SPIRV_GLLengthOp : SPIRV_GLOp<"Length", 66, [ }]; let hasVerifier = 0; - let hasCanonicalizer = 1; } // ----- diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp index 1363ee4a41cb9..03af61c81ae6c 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp @@ -1403,12 +1403,3 @@ void spirv::SelectionOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { results.add(context); } - -//===----------------------------------------------------------------------===// -// spirv.GL.Length -//===----------------------------------------------------------------------===// - -void spirv::GLLengthOp::getCanonicalizationPatterns(RewritePatternSet &results, - MLIRContext *context) { - results.add(context); -} diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVGLCanonicalization.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVGLCanonicalization.cpp index 3ad8057a58dc9..46acb8c156fc6 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVGLCanonicalization.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVGLCanonicalization.cpp @@ -34,8 +34,8 @@ void populateSPIRVGLCanonicalizationPatterns(RewritePatternSet &results) { ConvertComparisonIntoClamp2_SPIRV_SLessThanOp, ConvertComparisonIntoClamp2_SPIRV_SLessThanEqualOp, ConvertComparisonIntoClamp2_SPIRV_ULessThanOp, - ConvertComparisonIntoClamp2_SPIRV_ULessThanEqualOp>( - results.getContext()); + ConvertComparisonIntoClamp2_SPIRV_ULessThanEqualOp, + ConvertGLLengthToGLFAbs>(results.getContext()); } } // namespace spirv } // namespace mlir diff --git a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir index 50e06e85a59a1..722c27586aa61 100644 --- a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir +++ b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir @@ -2490,25 +2490,3 @@ func.func @cannot_canonicalize_selection_op_4(%cond: i1) -> () { } spirv.Return } - -// ----- - -//===----------------------------------------------------------------------===// -// spirv.GL.Length -//===----------------------------------------------------------------------===// - -// CHECK-LABEL: @convert_length_into_fabs_scalar -func.func @convert_length_into_fabs_scalar(%arg0 : f32) -> f32 { - //CHECK: spirv.GL.FAbs {{%.*}} : f32 - //CHECK-NOT: spirv.GL.Length - %0 = spirv.GL.Length %arg0 : f32 -> f32 - spirv.ReturnValue %0 : f32 -} - -// CHECK-LABEL: @dont_convert_length_into_fabs_vec -func.func @dont_convert_length_into_fabs_vec(%arg0 : vector<3xf32>) -> f32 { - //CHECK: spirv.GL.Length {{%.*}} : vector<3xf32> -> f32 - //CHECK-NOT: spirv.GL.FAbs - %0 = spirv.GL.Length %arg0 : vector<3xf32> -> f32 - spirv.ReturnValue %0 : f32 -} diff --git a/mlir/test/Dialect/SPIRV/Transforms/gl-canonicalize.mlir b/mlir/test/Dialect/SPIRV/Transforms/gl-canonicalize.mlir index c1447b38f0a48..33b877667512e 100644 --- a/mlir/test/Dialect/SPIRV/Transforms/gl-canonicalize.mlir +++ b/mlir/test/Dialect/SPIRV/Transforms/gl-canonicalize.mlir @@ -177,3 +177,25 @@ func.func @clamp_ulessthanequal(%input: i32, %min: i32, %max: i32) -> i32 { // CHECK-NEXT: spirv.ReturnValue [[RES]] spirv.ReturnValue %2 : i32 } + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.GL.Length +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @convert_length_into_fabs_scalar +func.func @convert_length_into_fabs_scalar(%arg0 : f32) -> f32 { + //CHECK: spirv.GL.FAbs {{%.*}} : f32 + //CHECK-NOT: spirv.GL.Length + %0 = spirv.GL.Length %arg0 : f32 -> f32 + spirv.ReturnValue %0 : f32 +} + +// CHECK-LABEL: @dont_convert_length_into_fabs_vec +func.func @dont_convert_length_into_fabs_vec(%arg0 : vector<3xf32>) -> f32 { + //CHECK: spirv.GL.Length {{%.*}} : vector<3xf32> -> f32 + //CHECK-NOT: spirv.GL.FAbs + %0 = spirv.GL.Length %arg0 : vector<3xf32> -> f32 + spirv.ReturnValue %0 : f32 +}