[spirv-reader] Add OpNot
Bug: tint:3
Change-Id: I4fe2f7ba0e8597ac5bed1e4817e3ccc38dc06a82
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/19885
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index d69a144..d882907 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -51,7 +51,7 @@
*ast_unary_op = ast::UnaryOp::kNegation;
return true;
case SpvOpLogicalNot:
- // TODO(dneto): SpvOpNot
+ case SpvOpNot:
*ast_unary_op = ast::UnaryOp::kNot;
return true;
default:
diff --git a/src/reader/spirv/function_arithmetic_test.cc b/src/reader/spirv/function_arithmetic_test.cc
index b4aa51e..ad5fb6d 100644
--- a/src/reader/spirv/function_arithmetic_test.cc
+++ b/src/reader/spirv/function_arithmetic_test.cc
@@ -299,6 +299,39 @@
<< ToString(fe.ast_body());
}
+TEST_F(SpvUnaryArithTest, SNegate_UnsignedVec_SignedVec) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpSNegate %v2uint %v2int_30_40
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __vec_2__u32
+ {
+ As<__vec_2__u32>{
+ UnaryOp{
+ negation
+ TypeConstructor{
+ __vec_2__i32
+ ScalarConstructor{30}
+ ScalarConstructor{40}
+ }
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
TEST_F(SpvUnaryArithTest, SNegate_UnsignedVec_UnsignedVec) {
const auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
@@ -1080,6 +1113,251 @@
"__vec_2__i32", AstFor("v2int_40_30"), "xor",
AstFor("v2uint_20_10")}));
+TEST_F(SpvUnaryArithTest, Not_Int_Int) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %int %int_30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __i32
+ {
+ UnaryOp{
+ not
+ ScalarConstructor{30}
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryArithTest, Not_Int_Uint) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %int %uint_10
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __i32
+ {
+ As<__i32>{
+ UnaryOp{
+ not
+ ScalarConstructor{10}
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryArithTest, Not_Uint_Int) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %uint %int_30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __u32
+ {
+ As<__u32>{
+ UnaryOp{
+ not
+ ScalarConstructor{30}
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryArithTest, Not_Uint_Uint) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %uint %uint_10
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __u32
+ {
+ UnaryOp{
+ not
+ ScalarConstructor{10}
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryArithTest, Not_SignedVec_SignedVec) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %v2int %v2int_30_40
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __vec_2__i32
+ {
+ UnaryOp{
+ not
+ TypeConstructor{
+ __vec_2__i32
+ ScalarConstructor{30}
+ ScalarConstructor{40}
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryArithTest, Not_SignedVec_UnsignedVec) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %v2int %v2uint_10_20
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __vec_2__i32
+ {
+ As<__vec_2__i32>{
+ UnaryOp{
+ not
+ TypeConstructor{
+ __vec_2__u32
+ ScalarConstructor{10}
+ ScalarConstructor{20}
+ }
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryArithTest, Not_UnsignedVec_SignedVec) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %v2uint %v2int_30_40
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __vec_2__u32
+ {
+ As<__vec_2__u32>{
+ UnaryOp{
+ not
+ TypeConstructor{
+ __vec_2__i32
+ ScalarConstructor{30}
+ ScalarConstructor{40}
+ }
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+TEST_F(SpvUnaryArithTest, Not_UnsignedVec_UnsignedVec) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpNot %v2uint %v2uint_10_20
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __vec_2__u32
+ {
+ UnaryOp{
+ not
+ TypeConstructor{
+ __vec_2__u32
+ ScalarConstructor{10}
+ ScalarConstructor{20}
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+// TODO(dneto): OpBitFieldInsert
+// TODO(dneto): OpBitFieldSExtract
+// TODO(dneto): OpBitFieldUExtract
+// TODO(dneto): OpBitReverse
+// TODO(dneto): OpBitCount
+
// TODO(dneto): OpSRem. Missing from WGSL
// https://github.com/gpuweb/gpuweb/issues/702
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index ba7957b..e057bf8 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -949,7 +949,7 @@
ast::type::Type* first_operand_type) {
const bool binary_match_first_operand =
AssumesResultSignednessMatchesBinaryFirstOperand(op);
- const bool unary_match_operand = (op == SpvOpSNegate);
+ const bool unary_match_operand = (op == SpvOpSNegate) || (op == SpvOpNot);
if (binary_match_first_operand || unary_match_operand) {
return first_operand_type;
}