[spirv-reader][ir] Correctly handle GLSL 450 UMin
The SPIR-V `UMin` method allows unsigned arguments and return types.
This is not permitted in WGSL. The SPIR-V spec states that the argument
is treated as a signed value, so bitcast the argument/result as needed.
Bug: 42250952
Change-Id: I52fe1f869b15ca8a89c68b57be03928cc80fd7f3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/222755
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/tint/lang/spirv/builtin_fn.cc b/src/tint/lang/spirv/builtin_fn.cc
index 78d0254..84521f1 100644
--- a/src/tint/lang/spirv/builtin_fn.cc
+++ b/src/tint/lang/spirv/builtin_fn.cc
@@ -124,6 +124,8 @@
return "sclamp";
case BuiltinFn::kUmax:
return "umax";
+ case BuiltinFn::kUmin:
+ return "umin";
case BuiltinFn::kSdot:
return "sdot";
case BuiltinFn::kUdot:
@@ -185,6 +187,7 @@
case BuiltinFn::kSmin:
case BuiltinFn::kSclamp:
case BuiltinFn::kUmax:
+ case BuiltinFn::kUmin:
break;
}
return core::ir::Instruction::Accesses{};
diff --git a/src/tint/lang/spirv/builtin_fn.cc.tmpl b/src/tint/lang/spirv/builtin_fn.cc.tmpl
index c20bf32..35967f4 100644
--- a/src/tint/lang/spirv/builtin_fn.cc.tmpl
+++ b/src/tint/lang/spirv/builtin_fn.cc.tmpl
@@ -80,6 +80,7 @@
case BuiltinFn::kSmin:
case BuiltinFn::kSclamp:
case BuiltinFn::kUmax:
+ case BuiltinFn::kUmin:
break;
}
return core::ir::Instruction::Accesses{};
diff --git a/src/tint/lang/spirv/builtin_fn.h b/src/tint/lang/spirv/builtin_fn.h
index c34ecac..50b4cc4 100644
--- a/src/tint/lang/spirv/builtin_fn.h
+++ b/src/tint/lang/spirv/builtin_fn.h
@@ -89,6 +89,7 @@
kSmin,
kSclamp,
kUmax,
+ kUmin,
kSdot,
kUdot,
kNone,
diff --git a/src/tint/lang/spirv/intrinsic/data.cc b/src/tint/lang/spirv/intrinsic/data.cc
index ff0dd41..4ed1781 100644
--- a/src/tint/lang/spirv/intrinsic/data.cc
+++ b/src/tint/lang/spirv/intrinsic/data.cc
@@ -5682,12 +5682,19 @@
},
{
/* [41] */
+ /* fn umin<R : iu32>[T : iu32, U : iu32](T, U) -> R */
+ /* fn umin<R : iu32>[T : iu32, U : iu32, N : num](vec<N, T>, vec<N, U>) -> vec<N, R> */
+ /* num overloads */ 2,
+ /* overloads */ OverloadIndex(156),
+ },
+ {
+ /* [42] */
/* fn sdot(u32, u32, u32) -> i32 */
/* num overloads */ 1,
/* overloads */ OverloadIndex(171),
},
{
- /* [42] */
+ /* [43] */
/* fn udot(u32, u32, u32) -> u32 */
/* num overloads */ 1,
/* overloads */ OverloadIndex(172),
diff --git a/src/tint/lang/spirv/reader/import_glsl_std450_test.cc b/src/tint/lang/spirv/reader/import_glsl_std450_test.cc
index 0d67a1e..0188299 100644
--- a/src/tint/lang/spirv/reader/import_glsl_std450_test.cc
+++ b/src/tint/lang/spirv/reader/import_glsl_std450_test.cc
@@ -646,23 +646,6 @@
)");
}
-TEST_F(SpirvReaderTest, DISABLED_RectifyOperandsAndResult_UMin) {
- EXPECT_IR(Preamble() + R"(
- %1 = OpExtInst %int %glsl UMin %int_30 %int_35
- %2 = OpExtInst %v2int %glsl UMin %v2int_30_40 %v2int_40_30
- OpReturn
- OpFunctionEnd
- )",
- R"(
-%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
- $B1: {
- let x_1 = bitcast<i32>(min(bitcast<u32>(i1), bitcast<u32>(i2)));
- let x_2 = bitcast<vec2i>(min(bitcast<vec2u>(v2i1), bitcast<vec2u>(v2i2)));
- }
-}
-)");
-}
-
TEST_F(SpirvReaderTest, DISABLED_RectifyOperandsAndResult_UClamp) {
EXPECT_IR(Preamble() + R"(
%1 = OpExtInst %int %glsl UClamp %int_30 %uint_15 %int_40
diff --git a/src/tint/lang/spirv/reader/lower/builtins.cc b/src/tint/lang/spirv/reader/lower/builtins.cc
index 3cd419e..63d290f 100644
--- a/src/tint/lang/spirv/reader/lower/builtins.cc
+++ b/src/tint/lang/spirv/reader/lower/builtins.cc
@@ -85,6 +85,9 @@
case spirv::BuiltinFn::kUmax:
UMax(builtin);
break;
+ case spirv::BuiltinFn::kUmin:
+ UMin(builtin);
+ break;
default:
TINT_UNREACHABLE() << "unknown spirv builtin: " << builtin->Func();
}
@@ -170,6 +173,9 @@
void UMax(spirv::ir::BuiltinCall* call) {
WrapUnsignedSpirvMethods(call, core::BuiltinFn::kMax);
}
+ void UMin(spirv::ir::BuiltinCall* call) {
+ WrapUnsignedSpirvMethods(call, core::BuiltinFn::kMin);
+ }
void Normalize(spirv::ir::BuiltinCall* call) {
auto* arg = call->Args()[0];
diff --git a/src/tint/lang/spirv/reader/lower/builtins_test.cc b/src/tint/lang/spirv/reader/lower/builtins_test.cc
index 6e87fd1..e2c4efb 100644
--- a/src/tint/lang/spirv/reader/lower/builtins_test.cc
+++ b/src/tint/lang/spirv/reader/lower/builtins_test.cc
@@ -1551,7 +1551,8 @@
INSTANTIATE_TEST_SUITE_P(SpirvReader,
SpirvParser_BuiltinsTest_TwoParamUnsigned,
- ::testing::Values(SpirvReaderParams{spirv::BuiltinFn::kUmax, "max"}));
+ ::testing::Values(SpirvReaderParams{spirv::BuiltinFn::kUmax, "max"},
+ SpirvReaderParams{spirv::BuiltinFn::kUmin, "min"}));
TEST_F(SpirvParser_BuiltinsTest, SClamp_UnsignedToUnsigned) {
auto* ep = b.ComputeFunction("foo");
diff --git a/src/tint/lang/spirv/reader/parser/import_glsl_std450_test.cc b/src/tint/lang/spirv/reader/parser/import_glsl_std450_test.cc
index 32010c6..2a17571 100644
--- a/src/tint/lang/spirv/reader/parser/import_glsl_std450_test.cc
+++ b/src/tint/lang/spirv/reader/parser/import_glsl_std450_test.cc
@@ -374,7 +374,8 @@
GlslStd450TwoParamTest,
::testing::Values(GlslStd450TwoParams{"SMax", "smax"},
GlslStd450TwoParams{"SMin", "smin"},
- GlslStd450TwoParams{"UMax", "umax"}));
+ GlslStd450TwoParams{"UMax", "umax"},
+ GlslStd450TwoParams{"UMin", "umin"}));
TEST_F(SpirvParserTest, GlslStd450_SClamp_UnsignedToUnsigned) {
EXPECT_IR(Preamble() + R"(
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 9258df4..a2c13ea 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -695,7 +695,6 @@
case GLSLstd450NClamp:
case GLSLstd450FClamp: // FClamp is less prescriptive about NaN operands
return core::BuiltinFn::kClamp;
- case GLSLstd450UMin:
case GLSLstd450NMin:
case GLSLstd450FMin: // FMin is less prescriptive about NaN operands
return core::BuiltinFn::kMin;
@@ -771,6 +770,8 @@
return spirv::BuiltinFn::kSclamp;
case GLSLstd450UMax:
return spirv::BuiltinFn::kUmax;
+ case GLSLstd450UMin:
+ return spirv::BuiltinFn::kUmin;
default:
break;
}
@@ -781,7 +782,8 @@
const core::type::Type* result_ty) {
if (ext_opcode == GLSLstd450SSign || ext_opcode == GLSLstd450SAbs ||
ext_opcode == GLSLstd450SMax || ext_opcode == GLSLstd450SMin ||
- ext_opcode == GLSLstd450SClamp || ext_opcode == GLSLstd450UMax) {
+ ext_opcode == GLSLstd450SClamp || ext_opcode == GLSLstd450UMax ||
+ ext_opcode == GLSLstd450UMin) {
return {result_ty->DeepestElement()};
}
return {};
diff --git a/src/tint/lang/spirv/spirv.def b/src/tint/lang/spirv/spirv.def
index 1202a8f..5f6f0fc 100644
--- a/src/tint/lang/spirv/spirv.def
+++ b/src/tint/lang/spirv/spirv.def
@@ -340,6 +340,8 @@
implicit(T: iu32, U: iu32) fn umax<R: iu32>(T, U) -> R
implicit(T: iu32, U: iu32, N: num) fn umax<R: iu32>(vec<N, T>, vec<N, U>) -> vec<N, R>
+implicit(T: iu32, U: iu32) fn umin<R: iu32>(T, U) -> R
+implicit(T: iu32, U: iu32, N: num) fn umin<R: iu32>(vec<N, T>, vec<N, U>) -> vec<N, R>
////////////////////////////////////////////////////////////////////////////////
// SPV_KHR_integer_dot_product instructions
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index e768da5..b2ddaad 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -1390,6 +1390,9 @@
case spirv::BuiltinFn::kUmax:
ext_inst(GLSLstd450UMax);
break;
+ case spirv::BuiltinFn::kUmin:
+ ext_inst(GLSLstd450UMin);
+ break;
case spirv::BuiltinFn::kNormalize:
ext_inst(GLSLstd450Normalize);
break;