[spirv-writer] Adding binary equals generation
This CL adds generation for a == operator.
Bug: tint:5
Change-Id: Ib27836a42153f3732927234cfa9aed342d0f9ac1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/19402
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 21e8f42..a3e634d 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -547,38 +547,50 @@
}
uint32_t Builder::GenerateBinaryExpression(ast::BinaryExpression* expr) {
+ auto lhs_id = GenerateExpressionAndLoad(expr->lhs());
+ if (lhs_id == 0) {
+ return 0;
+ }
+ auto rhs_id = GenerateExpressionAndLoad(expr->rhs());
+ if (rhs_id == 0) {
+ return 0;
+ }
+
+ auto result = result_op();
+ auto result_id = result.to_i();
+
+ auto lhs_type = expr->lhs()->result_type();
+
+ auto expr_type = expr->result_type();
+ auto type_id = GenerateTypeIfNeeded(expr_type);
+ if (type_id == 0) {
+ return 0;
+ }
+
+ spv::Op op = spv::Op::OpNop;
if (expr->IsAdd()) {
- auto lhs_id = GenerateExpressionAndLoad(expr->lhs());
- if (lhs_id == 0) {
- return 0;
- }
- auto rhs_id = GenerateExpressionAndLoad(expr->rhs());
- if (rhs_id == 0) {
- return 0;
- }
-
- auto result = result_op();
- auto result_id = result.to_i();
-
- auto expr_type = expr->result_type();
- auto type_id = GenerateTypeIfNeeded(expr_type);
- if (type_id == 0) {
- return 0;
- }
-
// This handles int and float and the vectors of those types. Other types
// should have been rejected by validation.
- spv::Op op = spv::Op::OpIAdd;
+ op = spv::Op::OpIAdd;
if (expr_type->IsF32() ||
(expr_type->IsVector() && expr_type->AsVector()->type()->IsF32())) {
op = spv::Op::OpFAdd;
}
- push_function_inst(op, {Operand::Int(type_id), result, Operand::Int(lhs_id),
- Operand::Int(rhs_id)});
-
- return result_id;
+ } else if (expr->IsEqual()) {
+ // This handles int and float and the vectors of those types. Other types
+ // should have been rejected by validation.
+ op = spv::Op::OpIEqual;
+ if (lhs_type->IsF32() ||
+ (lhs_type->IsVector() && lhs_type->AsVector()->type()->IsF32())) {
+ op = spv::Op::OpFOrdEqual;
+ }
+ } else {
+ return 0;
}
- return 0;
+
+ push_function_inst(op, {Operand::Int(type_id), result, Operand::Int(lhs_id),
+ Operand::Int(rhs_id)});
+ return result_id;
}
bool Builder::GenerateReturnStatement(ast::ReturnStatement* stmt) {
diff --git a/src/writer/spirv/builder_binary_expression_test.cc b/src/writer/spirv/builder_binary_expression_test.cc
index 5827ef2..6b0848f 100644
--- a/src/writer/spirv/builder_binary_expression_test.cc
+++ b/src/writer/spirv/builder_binary_expression_test.cc
@@ -200,6 +200,168 @@
testing::Values(BinaryData{ast::BinaryOp::kAdd,
"OpFAdd"}));
+using BinaryCompareIntegerTest = testing::TestWithParam<BinaryData>;
+TEST_P(BinaryCompareIntegerTest, Scalar) {
+ auto param = GetParam();
+
+ ast::type::I32Type i32;
+
+ auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 3));
+ auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 4));
+
+ ast::BinaryExpression expr(param.op, std::move(lhs), std::move(rhs));
+
+ Context ctx;
+ TypeDeterminer td(&ctx);
+ ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
+
+ Builder b;
+ b.push_function(Function{});
+
+ ASSERT_EQ(b.GenerateBinaryExpression(&expr), 4) << b.error();
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeInt 32 1
+%2 = OpConstant %1 3
+%3 = OpConstant %1 4
+%5 = OpTypeBool
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ "%4 = " + param.name + " %5 %2 %3\n");
+}
+
+TEST_P(BinaryCompareIntegerTest, Vector) {
+ auto param = GetParam();
+
+ ast::type::I32Type i32;
+ ast::type::VectorType vec3(&i32, 3);
+
+ ast::ExpressionList vals;
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+ auto lhs =
+ std::make_unique<ast::TypeConstructorExpression>(&vec3, std::move(vals));
+
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::IntLiteral>(&i32, 1)));
+ auto rhs =
+ std::make_unique<ast::TypeConstructorExpression>(&vec3, std::move(vals));
+
+ Context ctx;
+ TypeDeterminer td(&ctx);
+
+ ast::BinaryExpression expr(param.op, std::move(lhs), std::move(rhs));
+
+ ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
+
+ Builder b;
+ b.push_function(Function{});
+
+ ASSERT_EQ(b.GenerateBinaryExpression(&expr), 5) << b.error();
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstantComposite %1 %3 %3 %3
+%7 = OpTypeBool
+%6 = OpTypeVector %7 3
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ "%5 = " + param.name + " %6 %4 %4\n");
+}
+INSTANTIATE_TEST_SUITE_P(BuilderTest,
+ BinaryCompareIntegerTest,
+ testing::Values(BinaryData{ast::BinaryOp::kEqual,
+ "OpIEqual"}));
+
+using BinaryCompareFloatTest = testing::TestWithParam<BinaryData>;
+TEST_P(BinaryCompareFloatTest, Scalar) {
+ auto param = GetParam();
+
+ ast::type::F32Type f32;
+
+ auto lhs = std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 3.2f));
+ auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 4.5f));
+
+ ast::BinaryExpression expr(param.op, std::move(lhs), std::move(rhs));
+
+ Context ctx;
+ TypeDeterminer td(&ctx);
+ ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
+
+ Builder b;
+ b.push_function(Function{});
+
+ ASSERT_EQ(b.GenerateBinaryExpression(&expr), 4) << b.error();
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
+%2 = OpConstant %1 3.20000005
+%3 = OpConstant %1 4.5
+%5 = OpTypeBool
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ "%4 = " + param.name + " %5 %2 %3\n");
+}
+
+TEST_P(BinaryCompareFloatTest, Vector) {
+ auto param = GetParam();
+
+ ast::type::F32Type f32;
+ ast::type::VectorType vec3(&f32, 3);
+
+ ast::ExpressionList vals;
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ auto lhs =
+ std::make_unique<ast::TypeConstructorExpression>(&vec3, std::move(vals));
+
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
+ std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+ auto rhs =
+ std::make_unique<ast::TypeConstructorExpression>(&vec3, std::move(vals));
+
+ Context ctx;
+ TypeDeterminer td(&ctx);
+
+ ast::BinaryExpression expr(param.op, std::move(lhs), std::move(rhs));
+
+ ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
+
+ Builder b;
+ b.push_function(Function{});
+
+ ASSERT_EQ(b.GenerateBinaryExpression(&expr), 5) << b.error();
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
+%1 = OpTypeVector %2 3
+%3 = OpConstant %2 1
+%4 = OpConstantComposite %1 %3 %3 %3
+%7 = OpTypeBool
+%6 = OpTypeVector %7 3
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ "%5 = " + param.name + " %6 %4 %4\n");
+}
+INSTANTIATE_TEST_SUITE_P(BuilderTest,
+ BinaryCompareFloatTest,
+ testing::Values(BinaryData{ast::BinaryOp::kEqual,
+ "OpFOrdEqual"}));
+
} // namespace
} // namespace spirv
} // namespace writer