spirv-reader: support OpBitCount, OpBitReverse
Bug: tint:3 Change-Id: I81580136621ab51a9852e1d692ddad2457b9aab9 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35340 Auto-Submit: David Neto <dneto@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: David Neto <dneto@google.com>
This commit is contained in:
parent
d8591088fb
commit
ccc67252ff
|
@ -465,6 +465,10 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) {
|
||||||
// given instruction, or ast::Intrinsic::kNone
|
// given instruction, or ast::Intrinsic::kNone
|
||||||
ast::Intrinsic GetIntrinsic(SpvOp opcode) {
|
ast::Intrinsic GetIntrinsic(SpvOp opcode) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
case SpvOpBitCount:
|
||||||
|
return ast::Intrinsic::kCountOneBits;
|
||||||
|
case SpvOpBitReverse:
|
||||||
|
return ast::Intrinsic::kReverseBits;
|
||||||
case SpvOpDot:
|
case SpvOpDot:
|
||||||
return ast::Intrinsic::kDot;
|
return ast::Intrinsic::kDot;
|
||||||
case SpvOpOuterProduct:
|
case SpvOpOuterProduct:
|
||||||
|
@ -3726,8 +3730,13 @@ TypedExpression FunctionEmitter::MakeIntrinsicCall(
|
||||||
ident->set_intrinsic(intrinsic);
|
ident->set_intrinsic(intrinsic);
|
||||||
|
|
||||||
ast::ExpressionList params;
|
ast::ExpressionList params;
|
||||||
|
ast::type::Type* first_operand_type = nullptr;
|
||||||
for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
|
for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
|
||||||
params.emplace_back(MakeOperand(inst, iarg).expr);
|
TypedExpression operand = MakeOperand(inst, iarg);
|
||||||
|
if (first_operand_type == nullptr) {
|
||||||
|
first_operand_type = operand.type;
|
||||||
|
}
|
||||||
|
params.emplace_back(operand.expr);
|
||||||
}
|
}
|
||||||
auto* call_expr = create<ast::CallExpression>(ident, std::move(params));
|
auto* call_expr = create<ast::CallExpression>(ident, std::move(params));
|
||||||
auto* result_type = parser_impl_.ConvertType(inst.type_id());
|
auto* result_type = parser_impl_.ConvertType(inst.type_id());
|
||||||
|
@ -3736,7 +3745,8 @@ TypedExpression FunctionEmitter::MakeIntrinsicCall(
|
||||||
<< inst.PrettyPrint();
|
<< inst.PrettyPrint();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return {result_type, call_expr};
|
TypedExpression call{result_type, call_expr};
|
||||||
|
return parser_impl_.RectifyForcedResultType(call, inst, first_operand_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedExpression FunctionEmitter::MakeSimpleSelect(
|
TypedExpression FunctionEmitter::MakeSimpleSelect(
|
||||||
|
|
|
@ -627,11 +627,499 @@ TEST_F(SpvUnaryBitTest, Not_UnsignedVec_UnsignedVec) {
|
||||||
<< ToString(fe.ast_body());
|
<< ToString(fe.ast_body());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string BitTestPreamble() {
|
||||||
|
return R"(
|
||||||
|
OpCapability Shader
|
||||||
|
%glsl = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint GLCompute %100 "main"
|
||||||
|
OpExecutionMode %100 LocalSize 1 1 1
|
||||||
|
|
||||||
|
OpName %u1 "u1"
|
||||||
|
OpName %i1 "i1"
|
||||||
|
OpName %v2u1 "v2u1"
|
||||||
|
OpName %v2i1 "v2i1"
|
||||||
|
|
||||||
|
)" + CommonTypes() +
|
||||||
|
R"(
|
||||||
|
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%u1 = OpCopyObject %uint %uint_10
|
||||||
|
%i1 = OpCopyObject %int %int_30
|
||||||
|
%v2u1 = OpCopyObject %v2uint %v2uint_10_20
|
||||||
|
%v2i1 = OpCopyObject %v2int %v2int_30_40
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_Uint_Uint) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %uint %u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__u32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_Uint_Int) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %uint %i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__u32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__u32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_Int_Uint) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %int %u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__i32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__i32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_Int_Int) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %int %i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__i32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_UintVector_UintVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %v2uint %v2u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_UintVector_IntVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %v2uint %v2i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__vec_2__u32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_IntVector_UintVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %v2int %v2u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__i32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__vec_2__i32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitCount_IntVector_IntVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitCount %v2int %v2i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__i32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{countOneBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_Uint_Uint) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %uint %u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__u32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_Uint_Int) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %uint %i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__u32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__u32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_Int_Uint) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %int %u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__i32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__i32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_Int_Int) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %int %i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__i32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_UintVector_UintVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %v2uint %v2u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_UintVector_IntVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %v2uint %v2i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__vec_2__u32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_IntVector_UintVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %v2int %v2u1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__i32
|
||||||
|
{
|
||||||
|
Bitcast[not set]<__vec_2__i32>{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2u1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvUnaryBitTest, BitReverse_IntVector_IntVector) {
|
||||||
|
const auto assembly = BitTestPreamble() + R"(
|
||||||
|
%1 = OpBitReverse %v2int %v2i1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(fe.ast_body());
|
||||||
|
EXPECT_THAT(body, HasSubstr(R"(
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__vec_2__i32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reverseBits}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2i1}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< body;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(dneto): OpBitFieldInsert
|
// TODO(dneto): OpBitFieldInsert
|
||||||
// TODO(dneto): OpBitFieldSExtract
|
// TODO(dneto): OpBitFieldSExtract
|
||||||
// TODO(dneto): OpBitFieldUExtract
|
// TODO(dneto): OpBitFieldUExtract
|
||||||
// TODO(dneto): OpBitReverse
|
|
||||||
// TODO(dneto): OpBitCount
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
|
|
|
@ -209,10 +209,14 @@ bool AssumesUnsignedOperands(GLSLstd450 extended_opcode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the operation is binary, and the WGSL operation requires
|
// Returns true if the corresponding WGSL operation requires
|
||||||
// the signedness of the result to match the signedness of the first operand.
|
// the signedness of the result to match the signedness of the first operand.
|
||||||
bool AssumesResultSignednessMatchesBinaryFirstOperand(SpvOp opcode) {
|
bool AssumesResultSignednessMatchesFirstOperand(SpvOp opcode) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
case SpvOpNot:
|
||||||
|
case SpvOpSNegate:
|
||||||
|
case SpvOpBitCount:
|
||||||
|
case SpvOpBitReverse:
|
||||||
case SpvOpSDiv:
|
case SpvOpSDiv:
|
||||||
case SpvOpSMod:
|
case SpvOpSMod:
|
||||||
case SpvOpSRem:
|
case SpvOpSRem:
|
||||||
|
@ -1501,14 +1505,7 @@ ast::type::Type* ParserImpl::ForcedResultType(
|
||||||
const spvtools::opt::Instruction& inst,
|
const spvtools::opt::Instruction& inst,
|
||||||
ast::type::Type* first_operand_type) {
|
ast::type::Type* first_operand_type) {
|
||||||
const auto opcode = inst.opcode();
|
const auto opcode = inst.opcode();
|
||||||
if ((opcode == SpvOpSNegate) || (opcode == SpvOpNot)) {
|
if (AssumesResultSignednessMatchesFirstOperand(opcode)) {
|
||||||
// The unary operation cases that force the result type to match the
|
|
||||||
// first operand type.
|
|
||||||
return first_operand_type;
|
|
||||||
}
|
|
||||||
if (AssumesResultSignednessMatchesBinaryFirstOperand(opcode)) {
|
|
||||||
// The binary operation cases that force the result type to match
|
|
||||||
// the first operand type.
|
|
||||||
return first_operand_type;
|
return first_operand_type;
|
||||||
}
|
}
|
||||||
if (IsGlslExtendedInstruction(inst)) {
|
if (IsGlslExtendedInstruction(inst)) {
|
||||||
|
|
Loading…
Reference in New Issue