Remove outerProduct.
The community decided to remove outerProduct from WGSL. This Cl removes
the pieces from Tint.
Change-Id: Ib1735867e4a7ca852a72549fc8c9bd86e8de22b0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37600
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/docs/translations.md b/docs/translations.md
index d6ff55e..5688952 100644
--- a/docs/translations.md
+++ b/docs/translations.md
@@ -88,7 +88,6 @@
| mix | GLSLstd450FMix | mix | mix |
| modf | GLSLstd450Modf | | |
| normalize | GLSLstd450Normalize | normalize | normalize |
-| outerProduct | SpvOpOuterProduct | | |
| pow | GLSLstd450Pow | pow | pow |
| reflect | GLSLstd450Reflect | reflect | reflect |
| reverseBits | SpvOpBitReverse | reverse_bits | reversebits |
diff --git a/src/ast/intrinsic.cc b/src/ast/intrinsic.cc
index c4ce9c1..73f3ab3 100644
--- a/src/ast/intrinsic.cc
+++ b/src/ast/intrinsic.cc
@@ -162,9 +162,6 @@
case Intrinsic::kNormalize:
out << "normalize";
break;
- case Intrinsic::kOuterProduct:
- out << "outerProduct";
- break;
case Intrinsic::kPow:
out << "pow";
break;
diff --git a/src/ast/intrinsic.h b/src/ast/intrinsic.h
index 568c9ee..9de55b1 100644
--- a/src/ast/intrinsic.h
+++ b/src/ast/intrinsic.h
@@ -70,7 +70,6 @@
kMix,
kModf,
kNormalize,
- kOuterProduct,
kPow,
kReflect,
kReverseBits,
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index fcfcc33..93e7cd8 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -472,8 +472,6 @@
return ast::Intrinsic::kReverseBits;
case SpvOpDot:
return ast::Intrinsic::kDot;
- case SpvOpOuterProduct:
- return ast::Intrinsic::kOuterProduct;
default:
break;
}
diff --git a/src/reader/spirv/function_arithmetic_test.cc b/src/reader/spirv/function_arithmetic_test.cc
index b474a27..044fca5 100644
--- a/src/reader/spirv/function_arithmetic_test.cc
+++ b/src/reader/spirv/function_arithmetic_test.cc
@@ -1099,38 +1099,6 @@
<< ToString(p->get_module(), fe.ast_body());
}
-TEST_F(SpvBinaryArithTestBasic, OuterProduct) {
- const auto assembly = CommonTypes() + R"(
- %100 = OpFunction %void None %voidfn
- %entry = OpLabel
- %1 = OpCopyObject %v2float %v2float_50_60
- %2 = OpCopyObject %v2float %v2float_60_50
- %3 = OpOuterProduct %m2v2float %1 %2
- OpReturn
- OpFunctionEnd
-)";
- auto p = parser(test::Assemble(assembly));
- ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
- FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
- EXPECT_TRUE(fe.EmitBody()) << p->error();
- EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
- HasSubstr(R"(VariableConst{
- x_3
- none
- __mat_2_2__f32
- {
- Call[not set]{
- Identifier[not set]{outerProduct}
- (
- Identifier[not set]{x_1}
- Identifier[not set]{x_2}
- )
- }
- }
- })"))
- << ToString(p->get_module(), fe.ast_body());
-}
-
// TODO(dneto): OpSRem. Missing from WGSL
// https://github.com/gpuweb/gpuweb/issues/702
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index eaa95bf..b8aab37 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -721,28 +721,6 @@
expr->func()->set_result_type(mod_->create<ast::type::F32>());
return true;
}
- if (ident->intrinsic() == ast::Intrinsic::kOuterProduct) {
- if (expr->params().size() != 2) {
- set_error(expr->source(), "incorrect number of parameters for " +
- mod_->SymbolToName(ident->symbol()));
- return false;
- }
-
- auto* param0_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
- auto* param1_type = expr->params()[1]->result_type()->UnwrapPtrIfNeeded();
- if (!param0_type->Is<ast::type::Vector>() ||
- !param1_type->Is<ast::type::Vector>()) {
- set_error(expr->source(), "invalid parameter type for " +
- mod_->SymbolToName(ident->symbol()));
- return false;
- }
-
- expr->func()->set_result_type(mod_->create<ast::type::Matrix>(
- mod_->create<ast::type::F32>(),
- param0_type->As<ast::type::Vector>()->size(),
- param1_type->As<ast::type::Vector>()->size()));
- return true;
- }
if (ident->intrinsic() == ast::Intrinsic::kSelect) {
if (expr->params().size() != 3) {
set_error(expr->source(), "incorrect number of parameters for " +
@@ -1017,8 +995,6 @@
ident->set_intrinsic(ast::Intrinsic::kModf);
} else if (name == "normalize") {
ident->set_intrinsic(ast::Intrinsic::kNormalize);
- } else if (name == "outerProduct") {
- ident->set_intrinsic(ast::Intrinsic::kOuterProduct);
} else if (name == "pow") {
ident->set_intrinsic(ast::Intrinsic::kPow);
} else if (name == "reflect") {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index 46545c4..87f6ed0 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -1617,55 +1617,6 @@
"incorrect number of parameters for select expected 3 got 4");
}
-TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct) {
- auto* var1 = Var( // source
- "v3", ast::StorageClass::kNone, ty.vec3<f32>());
- auto* var2 = Var( // source
- "v2", ast::StorageClass::kNone, ty.vec2<f32>());
- mod->AddGlobalVariable(var1);
- mod->AddGlobalVariable(var2);
-
- auto* expr = Call("outerProduct", "v3", "v2");
-
- // Register the variable
- EXPECT_TRUE(td()->Determine());
- EXPECT_TRUE(td()->DetermineResultType(expr));
-
- ASSERT_NE(expr->result_type(), nullptr);
- ASSERT_TRUE(expr->result_type()->Is<ast::type::Matrix>());
-
- auto* mat = expr->result_type()->As<ast::type::Matrix>();
- EXPECT_TRUE(mat->type()->Is<ast::type::F32>());
- EXPECT_EQ(mat->rows(), 3u);
- EXPECT_EQ(mat->columns(), 2u);
-}
-
-TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct_TooFewParams) {
- auto* var2 = Var( // source
- "v2", ast::StorageClass::kNone, ty.vec2<f32>());
- mod->AddGlobalVariable(var2);
-
- auto* expr = Call("outerProduct", "v2");
-
- // Register the variable
- EXPECT_TRUE(td()->Determine());
- EXPECT_FALSE(td()->DetermineResultType(expr));
- EXPECT_EQ(td()->error(), "incorrect number of parameters for outerProduct");
-}
-
-TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct_TooManyParams) {
- auto* var2 = Var( // source
- "v2", ast::StorageClass::kNone, ty.vec2<f32>());
- mod->AddGlobalVariable(var2);
-
- auto* expr = Call("outerProduct", "v2", "v2", "v2");
-
- // Register the variable
- EXPECT_TRUE(td()->Determine());
- EXPECT_FALSE(td()->DetermineResultType(expr));
- EXPECT_EQ(td()->error(), "incorrect number of parameters for outerProduct");
-}
-
using UnaryOpExpressionTest = TypeDeterminerTestWithParam<ast::UnaryOp>;
TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
auto op = GetParam();
@@ -1798,7 +1749,6 @@
IntrinsicData{"mix", ast::Intrinsic::kMix},
IntrinsicData{"modf", ast::Intrinsic::kModf},
IntrinsicData{"normalize", ast::Intrinsic::kNormalize},
- IntrinsicData{"outerProduct", ast::Intrinsic::kOuterProduct},
IntrinsicData{"pow", ast::Intrinsic::kPow},
IntrinsicData{"reflect", ast::Intrinsic::kReflect},
IntrinsicData{"reverseBits", ast::Intrinsic::kReverseBits},
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index d95769f..4c6067b 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -595,59 +595,6 @@
} else if (ident->intrinsic() == ast::Intrinsic::kIsNormal) {
error_ = "is_normal not supported in HLSL backend yet";
return false;
- } else if (ident->intrinsic() == ast::Intrinsic::kOuterProduct) {
- error_ = "outer_product not supported yet";
- return false;
- // TODO(dsinclair): This gets tricky. We need to generate two variables to
- // hold the outer_product expressions, but we maybe inside an expression
- // ourselves. So, this will need to, possibly, output the variables
- // _before_ the expression which contains the outer product.
- //
- // This then has the follow on, what if we have `(false &&
- // outer_product())` in that case, we shouldn't evaluate the expressions
- // at all because of short circuting.
- //
- // So .... this turns out to be hard ...
-
- // // We create variables to hold the two parameters in case they're
- // // function calls with side effects.
- // auto* param0 = param[0].get();
- // auto* name0 = generate_name("outer_product_expr_0");
-
- // auto* param1 = param[1].get();
- // auto* name1 = generate_name("outer_product_expr_1");
-
- // make_indent(out);
- // if (!EmitType(out, expr->result_type(), "")) {
- // return false;
- // }
- // out << "(";
-
- // auto param1_type = params[1]->result_type()->UnwrapPtrIfNeeded();
- // if (!param1_type->Is<ast::type::Vector>()) {
- // error_ = "invalid param type in outer_product got: " +
- // param1_type->type_name();
- // return false;
- // }
-
- // for (uint32_t i = 0; i <
- // param1_type->As<ast::type::Vector>()->size(); ++i) {
- // if (i > 0) {
- // out << ", ";
- // }
-
- // if (!EmitExpression(pre, out, params[0].get())) {
- // return false;
- // }
- // out << " * ";
-
- // if (!EmitExpression(pre, out, params[1].get())) {
- // return false;
- // }
- // out << "[" << i << "]";
- // }
-
- // out << ")";
} else {
auto name = generate_intrinsic_name(ident->intrinsic());
if (name.empty()) {
diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc
index 1841ef6..2658f74 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc
@@ -70,26 +70,6 @@
FAIL();
}
-TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_OuterProduct) {
- auto* a = Var("a", ast::StorageClass::kNone, ty.vec2<f32>());
- auto* b = Var("b", ast::StorageClass::kNone, ty.vec3<f32>());
-
- auto* call = Call("outer_product", "a", "b");
-
- td.RegisterVariableForTesting(a);
- td.RegisterVariableForTesting(b);
-
- mod->AddGlobalVariable(a);
- mod->AddGlobalVariable(b);
-
- ASSERT_TRUE(td.Determine()) << td.error();
- ASSERT_TRUE(td.DetermineResultType(call)) << td.error();
-
- gen.increment_indent();
- ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error();
- EXPECT_EQ(result(), " float3x2(a * b[0], a * b[1], a * b[2])");
-}
-
TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Bad_Name) {
EXPECT_EQ(gen.generate_intrinsic_name(ast::Intrinsic::kNone), "");
}
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 5343a11..a9509a8 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -487,89 +487,34 @@
}
if (ident->IsIntrinsic()) {
- const auto& params = expr->params();
- if (ident->intrinsic() == ast::Intrinsic::kOuterProduct) {
- error_ = "outer_product not supported yet";
- return false;
- // TODO(dsinclair): This gets tricky. We need to generate two variables to
- // hold the outer_product expressions, but we maybe inside an expression
- // ourselves. So, this will need to, possibly, output the variables
- // _before_ the expression which contains the outer product.
- //
- // This then has the follow on, what if we have `(false &&
- // outer_product())` in that case, we shouldn't evaluate the expressions
- // at all because of short circuting.
- //
- // So .... this turns out to be hard ...
-
- // // We create variables to hold the two parameters in case they're
- // // function calls with side effects.
- // auto* param0 = param[0].get();
- // auto* name0 = generate_name("outer_product_expr_0");
-
- // auto* param1 = param[1].get();
- // auto* name1 = generate_name("outer_product_expr_1");
-
- // make_indent();
- // if (!EmitType(expr->result_type(), "")) {
- // return false;
- // }
- // out_ << "(";
-
- // auto param1_type = params[1]->result_type()->UnwrapPtrIfNeeded();
- // if (!param1_type->Is<ast::type::Vector>()) {
- // error_ = "invalid param type in outer_product got: " +
- // param1_type->type_name();
- // return false;
- // }
-
- // for (uint32_t i = 0; i <
- // param1_type->As<ast::type::Vector>()->size(); ++i) {
- // if (i > 0) {
- // out_ << ", ";
- // }
-
- // if (!EmitExpression(params[0].get())) {
- // return false;
- // }
- // out_ << " * ";
-
- // if (!EmitExpression(params[1].get())) {
- // return false;
- // }
- // out_ << "[" << i << "]";
- // }
-
- // out_ << ")";
- } else {
- auto name = generate_intrinsic_name(ident->intrinsic());
+ auto name = generate_intrinsic_name(ident->intrinsic());
+ if (name.empty()) {
+ if (ast::intrinsic::IsTextureIntrinsic(ident->intrinsic())) {
+ return EmitTextureCall(expr);
+ }
+ name = generate_builtin_name(ident);
if (name.empty()) {
- if (ast::intrinsic::IsTextureIntrinsic(ident->intrinsic())) {
- return EmitTextureCall(expr);
- }
- name = generate_builtin_name(ident);
- if (name.empty()) {
- return false;
- }
+ return false;
}
-
- make_indent();
- out_ << name << "(";
-
- bool first = true;
- for (auto* param : params) {
- if (!first) {
- out_ << ", ";
- }
- first = false;
-
- if (!EmitExpression(param)) {
- return false;
- }
- }
-
- out_ << ")";
}
+
+ make_indent();
+ out_ << name << "(";
+
+ bool first = true;
+ const auto& params = expr->params();
+ for (auto* param : params) {
+ if (!first) {
+ out_ << ", ";
+ }
+ first = false;
+
+ if (!EmitExpression(param)) {
+ return false;
+ }
+ }
+
+ out_ << ")";
return true;
}
diff --git a/src/writer/msl/generator_impl_intrinsic_test.cc b/src/writer/msl/generator_impl_intrinsic_test.cc
index af661cb..b1f0e92 100644
--- a/src/writer/msl/generator_impl_intrinsic_test.cc
+++ b/src/writer/msl/generator_impl_intrinsic_test.cc
@@ -65,25 +65,6 @@
IntrinsicData{ast::Intrinsic::kReverseBits, "reverse_bits"},
IntrinsicData{ast::Intrinsic::kSelect, "select"}));
-TEST_F(MslGeneratorImplTest, DISABLED_Intrinsic_OuterProduct) {
- auto* a = Var("a", ast::StorageClass::kNone, ty.vec2<f32>());
- auto* b = Var("b", ast::StorageClass::kNone, ty.vec3<f32>());
-
- auto* call = Call("outer_product", "a", "b");
- td.RegisterVariableForTesting(a);
- td.RegisterVariableForTesting(b);
-
- mod->AddGlobalVariable(a);
- mod->AddGlobalVariable(b);
-
- ASSERT_TRUE(td.Determine()) << td.error();
- ASSERT_TRUE(td.DetermineResultType(call)) << td.error();
-
- gen.increment_indent();
- ASSERT_TRUE(gen.EmitExpression(call)) << gen.error();
- EXPECT_EQ(gen.result(), " float3x2(a * b[0], a * b[1], a * b[2])");
-}
-
TEST_F(MslGeneratorImplTest, Intrinsic_Bad_Name) {
EXPECT_EQ(gen.generate_intrinsic_name(ast::Intrinsic::kNone), "");
}
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 1bdd166..598a0db 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -1940,8 +1940,6 @@
op = spv::Op::OpIsInf;
} else if (intrinsic == ast::Intrinsic::kIsNan) {
op = spv::Op::OpIsNan;
- } else if (intrinsic == ast::Intrinsic::kOuterProduct) {
- op = spv::Op::OpOuterProduct;
} else if (intrinsic == ast::Intrinsic::kReverseBits) {
op = spv::Op::OpBitReverse;
} else if (intrinsic == ast::Intrinsic::kSelect) {
diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc
index c2dde98..654317b 100644
--- a/src/writer/spirv/builder_intrinsic_test.cc
+++ b/src/writer/spirv/builder_intrinsic_test.cc
@@ -349,38 +349,6 @@
IntrinsicData{"fwidthFine", "OpFwidthFine"},
IntrinsicData{"fwidthCoarse", "OpFwidthCoarse"}));
-TEST_F(IntrinsicBuilderTest, Call_OuterProduct) {
- auto* v2 = Var("v2", ast::StorageClass::kPrivate, ty.vec2<f32>());
- auto* v3 = Var("v3", ast::StorageClass::kPrivate, ty.vec3<f32>());
-
- auto* expr = Call("outerProduct", "v2", "v3");
-
- ASSERT_TRUE(td.DetermineResultType(expr)) << td.error();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateGlobalVariable(v2)) << b.error();
- ASSERT_TRUE(b.GenerateGlobalVariable(v3)) << b.error();
-
- EXPECT_EQ(b.GenerateCallExpression(expr), 10u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 2
-%2 = OpTypePointer Private %3
-%5 = OpConstantNull %3
-%1 = OpVariable %2 Private %5
-%8 = OpTypeVector %4 3
-%7 = OpTypePointer Private %8
-%9 = OpConstantNull %8
-%6 = OpVariable %7 Private %9
-%11 = OpTypeMatrix %3 3
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%12 = OpLoad %3 %1
-%13 = OpLoad %8 %6
-%10 = OpOuterProduct %11 %12 %13
-)");
-}
-
TEST_F(IntrinsicBuilderTest, Call_Select) {
auto* v3 = Var("v3", ast::StorageClass::kPrivate, ty.vec3<f32>());
auto* bool_v3 = Var("bool_v3", ast::StorageClass::kPrivate, ty.vec3<bool>());