[spirv-writer] Add is_nan support.

This Cl adds support for generating OpIsNan.

Bug: tint:5
Change-Id: If35e46c6cb2719771abdd425ff6116b539da0be0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22622
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-06-04 17:05:49 +00:00 committed by dan sinclair
parent 0bcb50b04a
commit c31903d2ad
2 changed files with 81 additions and 13 deletions

View File

@ -1250,6 +1250,8 @@ uint32_t Builder::GenerateIntrinsic(const std::string& name,
op = spv::Op::OpAny; op = spv::Op::OpAny;
} else if (name == "all") { } else if (name == "all") {
op = spv::Op::OpAll; op = spv::Op::OpAll;
} else if (name == "is_nan") {
op = spv::Op::OpIsNan;
} }
if (op == spv::Op::OpNop) { if (op == spv::Op::OpNop) {
error_ = "unable to determine operator for: " + name; error_ = "unable to determine operator for: " + name;

View File

@ -18,6 +18,7 @@
#include "src/ast/call_expression.h" #include "src/ast/call_expression.h"
#include "src/ast/identifier_expression.h" #include "src/ast/identifier_expression.h"
#include "src/ast/type/bool_type.h" #include "src/ast/type/bool_type.h"
#include "src/ast/type/f32_type.h"
#include "src/ast/type/vector_type.h" #include "src/ast/type/vector_type.h"
#include "src/ast/variable.h" #include "src/ast/variable.h"
#include "src/context.h" #include "src/context.h"
@ -32,7 +33,19 @@ namespace {
using BuilderTest = testing::Test; using BuilderTest = testing::Test;
TEST_F(BuilderTest, Call_Any) { struct IntrinsicData {
std::string name;
std::string op;
};
inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
out << data.name;
return out;
}
using IntrinsicBoolTest = testing::TestWithParam<IntrinsicData>;
TEST_P(IntrinsicBoolTest, Call_Bool) {
auto param = GetParam();
ast::type::BoolType bool_type; ast::type::BoolType bool_type;
ast::type::VectorType vec3(&bool_type, 3); ast::type::VectorType vec3(&bool_type, 3);
@ -41,7 +54,8 @@ TEST_F(BuilderTest, Call_Any) {
ast::ExpressionList params; ast::ExpressionList params;
params.push_back(std::make_unique<ast::IdentifierExpression>("v")); params.push_back(std::make_unique<ast::IdentifierExpression>("v"));
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>("any"), ast::CallExpression expr(
std::make_unique<ast::IdentifierExpression>(param.name),
std::move(params)); std::move(params));
Context ctx; Context ctx;
@ -64,20 +78,66 @@ TEST_F(BuilderTest, Call_Any) {
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
R"(%7 = OpLoad %3 %1 R"(%7 = OpLoad %3 %1
%6 = OpAny %4 %7 %6 = )" + param.op +
" %4 %7\n");
}
INSTANTIATE_TEST_SUITE_P(BuilderTest,
IntrinsicBoolTest,
testing::Values(IntrinsicData{"any", "OpAny"},
IntrinsicData{"all", "OpAll"}));
using IntrinsicFloatTest = testing::TestWithParam<IntrinsicData>;
TEST_P(IntrinsicFloatTest, Call_Float_Scalar) {
auto param = GetParam();
ast::type::F32Type f32;
auto var =
std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &f32);
ast::ExpressionList params;
params.push_back(std::make_unique<ast::IdentifierExpression>("v"));
ast::CallExpression expr(
std::make_unique<ast::IdentifierExpression>(param.name),
std::move(params));
Context ctx;
ast::Module mod;
TypeDeterminer td(&ctx, &mod);
td.RegisterVariableForTesting(var.get());
ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
Builder b(&mod);
b.push_function(Function{});
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
EXPECT_EQ(b.GenerateCallExpression(&expr), 5u) << b.error();
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
%2 = OpTypePointer Private %3
%4 = OpConstantNull %3
%1 = OpVariable %2 Private %4
%6 = OpTypeBool
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
R"(%7 = OpLoad %3 %1
%5 = )" + param.op +
" %6 %7\n");
} }
TEST_F(BuilderTest, Call_All) { TEST_P(IntrinsicFloatTest, Call_Float_Vector) {
ast::type::BoolType bool_type; auto param = GetParam();
ast::type::VectorType vec3(&bool_type, 3);
ast::type::F32Type f32;
ast::type::VectorType vec3(&f32, 3);
auto var = auto var =
std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &vec3); std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &vec3);
ast::ExpressionList params; ast::ExpressionList params;
params.push_back(std::make_unique<ast::IdentifierExpression>("v")); params.push_back(std::make_unique<ast::IdentifierExpression>("v"));
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>("all"), ast::CallExpression expr(
std::make_unique<ast::IdentifierExpression>(param.name),
std::move(params)); std::move(params));
Context ctx; Context ctx;
@ -92,17 +152,23 @@ TEST_F(BuilderTest, Call_All) {
ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error(); ASSERT_TRUE(b.GenerateGlobalVariable(var.get())) << b.error();
EXPECT_EQ(b.GenerateCallExpression(&expr), 6u) << b.error(); EXPECT_EQ(b.GenerateCallExpression(&expr), 6u) << b.error();
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeBool EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
%3 = OpTypeVector %4 3 %3 = OpTypeVector %4 3
%2 = OpTypePointer Private %3 %2 = OpTypePointer Private %3
%5 = OpConstantNull %3 %5 = OpConstantNull %3
%1 = OpVariable %2 Private %5 %1 = OpVariable %2 Private %5
%8 = OpTypeBool
%7 = OpTypeVector %8 3
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
R"(%7 = OpLoad %3 %1 R"(%9 = OpLoad %3 %1
%6 = OpAll %4 %7 %6 = )" + param.op +
)"); " %7 %9\n");
} }
INSTANTIATE_TEST_SUITE_P(BuilderTest,
IntrinsicFloatTest,
testing::Values(IntrinsicData{"is_nan", "OpIsNan"}));
} // namespace } // namespace
} // namespace spirv } // namespace spirv
} // namespace writer } // namespace writer