diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc index aef4a4a7ea..efc31ca34d 100644 --- a/src/tint/reader/spirv/function.cc +++ b/src/tint/reader/spirv/function.cc @@ -329,6 +329,8 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) { return "faceForward"; case GLSLstd450FindILsb: return "firstTrailingBit"; + case GLSLstd450FindUMsb: + return "firstLeadingBit"; case GLSLstd450Floor: return "floor"; case GLSLstd450Fma: @@ -430,7 +432,6 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) { case GLSLstd450UnpackDouble2x32: case GLSLstd450FindSMsb: - case GLSLstd450FindUMsb: case GLSLstd450InterpolateAtCentroid: case GLSLstd450InterpolateAtSample: diff --git a/src/tint/reader/spirv/function_glsl_std_450_test.cc b/src/tint/reader/spirv/function_glsl_std_450_test.cc index 7a4fd94394..a87723e7ee 100644 --- a/src/tint/reader/spirv/function_glsl_std_450_test.cc +++ b/src/tint/reader/spirv/function_glsl_std_450_test.cc @@ -701,7 +701,8 @@ TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting, Vector) { INSTANTIATE_TEST_SUITE_P(Samples, SpvParserTest_GlslStd450_Uinting_Uinting, - ::testing::Values(GlslStd450Case{"FindILsb", "firstTrailingBit"})); + ::testing::Values(GlslStd450Case{"FindILsb", "firstTrailingBit"}, + GlslStd450Case{"FindUMsb", "firstLeadingBit"})); INSTANTIATE_TEST_SUITE_P(Samples, SpvParserTest_GlslStd450_Uinting_UintingUinting, @@ -977,6 +978,56 @@ let x_4 : vec2 = bitcast>(firstTrailingBit(v2u1));)")) << body; } +TEST_F(SpvParserTest, RectifyOperandsAndResult_FindUMsb) { + // Check signedness conversion of arguments and results. + // SPIR-V signed arg -> cast arg to unsigned + // signed result -> cast result to signed + // unsigned result -> keep it + // + // SPIR-V unsigned arg -> keep it + // signed result -> cast result to signed + // unsigned result -> keep it + const auto assembly = Preamble() + R"( + ; signed arg + ; signed result + %1 = OpExtInst %int %glsl FindUMsb %i1 + %2 = OpExtInst %v2int %glsl FindUMsb %v2i1 + + ; signed arg + ; unsigned result + %3 = OpExtInst %uint %glsl FindUMsb %i1 + %4 = OpExtInst %v2uint %glsl FindUMsb %v2i1 + + ; unsigned arg + ; signed result + %5 = OpExtInst %int %glsl FindUMsb %u1 + %6 = OpExtInst %v2int %glsl FindUMsb %v2u1 + + ; unsigned arg + ; unsigned result + %7 = OpExtInst %uint %glsl FindUMsb %u1 + %8 = OpExtInst %v2uint %glsl FindUMsb %v2u1 + OpReturn + OpFunctionEnd + )"; + auto p = parser(test::Assemble(assembly)); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); + auto fe = p->function_emitter(100); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + auto ast_body = fe.ast_body(); + const auto body = test::ToString(p->program(), ast_body); + EXPECT_THAT(body, HasSubstr(R"( +let x_1 : i32 = bitcast(firstLeadingBit(bitcast(i1))); +let x_2 : vec2 = bitcast>(firstLeadingBit(bitcast>(v2i1))); +let x_3 : u32 = firstLeadingBit(bitcast(i1)); +let x_4 : vec2 = firstLeadingBit(bitcast>(v2i1)); +let x_5 : i32 = bitcast(firstLeadingBit(u1)); +let x_6 : vec2 = bitcast>(firstLeadingBit(v2u1)); +let x_7 : u32 = firstLeadingBit(u1); +let x_8 : vec2 = firstLeadingBit(v2u1); +)")) << body; +} + struct DataPackingCase { std::string opcode; std::string wgsl_func; diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc index 42c5c7d909..c1a905693f 100644 --- a/src/tint/reader/spirv/parser_impl.cc +++ b/src/tint/reader/spirv/parser_impl.cc @@ -150,6 +150,7 @@ bool AssumesUnsignedOperands(GLSLstd450 extended_opcode) { case GLSLstd450UMin: case GLSLstd450UMax: case GLSLstd450UClamp: + case GLSLstd450FindUMsb: return true; default: break; @@ -222,8 +223,8 @@ bool AssumesResultSignednessMatchesFirstOperand(GLSLstd450 extended_opcode) { case GLSLstd450UMax: case GLSLstd450UClamp: case GLSLstd450FindILsb: + case GLSLstd450FindUMsb: // TODO(dneto): FindSMsb? - // TODO(dneto): FindUMsb? return true; default: break;