| // Copyright (c) 2016 Google Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include "test/opt/assembly_builder.h" |
| #include "test/opt/pass_fixture.h" |
| #include "test/opt/pass_utils.h" |
| |
| namespace spvtools { |
| namespace opt { |
| namespace { |
| |
| using FoldSpecConstantOpAndCompositePassBasicTest = PassTest<::testing::Test>; |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Empty) { |
| SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>( |
| "", "", /* skip_nop = */ true); |
| } |
| |
| // A test of the basic functionality of FoldSpecConstantOpAndCompositePass. |
| // A spec constant defined with an integer addition operation should be folded |
| // to a normal constant with fixed value. |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Basic) { |
| AssemblyBuilder builder; |
| builder.AppendTypesConstantsGlobals({ |
| // clang-format off |
| "%int = OpTypeInt 32 1", |
| "%frozen_spec_const_int = OpConstant %int 1", |
| "%const_int = OpConstant %int 2", |
| // Folding target: |
| "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int", |
| // clang-format on |
| }); |
| |
| std::vector<const char*> expected = { |
| // clang-format off |
| "OpCapability Shader", |
| "OpCapability Float64", |
| "%1 = OpExtInstImport \"GLSL.std.450\"", |
| "OpMemoryModel Logical GLSL450", |
| "OpEntryPoint Vertex %main \"main\"", |
| "OpName %void \"void\"", |
| "OpName %main_func_type \"main_func_type\"", |
| "OpName %main \"main\"", |
| "OpName %main_func_entry_block \"main_func_entry_block\"", |
| "OpName %int \"int\"", |
| "OpName %frozen_spec_const_int \"frozen_spec_const_int\"", |
| "OpName %const_int \"const_int\"", |
| "OpName %spec_add \"spec_add\"", |
| "%void = OpTypeVoid", |
| "%main_func_type = OpTypeFunction %void", |
| "%int = OpTypeInt 32 1", |
| "%frozen_spec_const_int = OpConstant %int 1", |
| "%const_int = OpConstant %int 2", |
| // The SpecConstantOp IAdd instruction should be replace by OpConstant |
| // instruction: |
| "%spec_add = OpConstant %int 3", |
| "%main = OpFunction %void None %main_func_type", |
| "%main_func_entry_block = OpLabel", |
| "OpReturn", |
| "OpFunctionEnd", |
| // clang-format on |
| }; |
| SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>( |
| builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true); |
| } |
| |
| // A test of skipping folding an instruction when the instruction result type |
| // has decorations. |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| SkipWhenTypeHasDecorations) { |
| AssemblyBuilder builder; |
| builder |
| .AppendAnnotations({ |
| // clang-format off |
| "OpDecorate %int RelaxedPrecision", |
| // clang-format on |
| }) |
| .AppendTypesConstantsGlobals({ |
| // clang-format off |
| "%int = OpTypeInt 32 1", |
| "%frozen_spec_const_int = OpConstant %int 1", |
| "%const_int = OpConstant %int 2", |
| // The following spec constant should not be folded as the result type |
| // has relaxed precision decoration. |
| "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int", |
| // clang-format on |
| }); |
| |
| SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>( |
| builder.GetCode(), builder.GetCode(), /* skip_nop = */ true); |
| } |
| |
| // Test where OpSpecConstantOp depends on another OpSpecConstantOp with |
| // CompositeExtract |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedCompositeExtract) { |
| AssemblyBuilder builder; |
| builder.AppendTypesConstantsGlobals({ |
| // clang-format off |
| "%uint = OpTypeInt 32 0", |
| "%v3uint = OpTypeVector %uint 3", |
| "%uint_2 = OpConstant %uint 2", |
| "%uint_3 = OpConstant %uint 3", |
| // Folding target: |
| "%composite_0 = OpSpecConstantComposite %v3uint %uint_2 %uint_3 %uint_2", |
| "%op_0 = OpSpecConstantOp %uint CompositeExtract %composite_0 0", |
| "%op_1 = OpSpecConstantOp %uint CompositeExtract %composite_0 1", |
| "%op_2 = OpSpecConstantOp %uint IMul %op_0 %op_1", |
| "%composite_1 = OpSpecConstantComposite %v3uint %op_0 %op_1 %op_2", |
| "%op_3 = OpSpecConstantOp %uint CompositeExtract %composite_1 0", |
| "%op_4 = OpSpecConstantOp %uint IMul %op_2 %op_3", |
| // clang-format on |
| }); |
| |
| std::vector<const char*> expected = { |
| // clang-format off |
| "OpCapability Shader", |
| "OpCapability Float64", |
| "%1 = OpExtInstImport \"GLSL.std.450\"", |
| "OpMemoryModel Logical GLSL450", |
| "OpEntryPoint Vertex %main \"main\"", |
| "OpName %void \"void\"", |
| "OpName %main_func_type \"main_func_type\"", |
| "OpName %main \"main\"", |
| "OpName %main_func_entry_block \"main_func_entry_block\"", |
| "OpName %uint \"uint\"", |
| "OpName %v3uint \"v3uint\"", |
| "OpName %uint_2 \"uint_2\"", |
| "OpName %uint_3 \"uint_3\"", |
| "OpName %composite_0 \"composite_0\"", |
| "OpName %op_0 \"op_0\"", |
| "OpName %op_1 \"op_1\"", |
| "OpName %op_2 \"op_2\"", |
| "OpName %composite_1 \"composite_1\"", |
| "OpName %op_3 \"op_3\"", |
| "OpName %op_4 \"op_4\"", |
| "%void = OpTypeVoid", |
| "%main_func_type = OpTypeFunction %void", |
| "%uint = OpTypeInt 32 0", |
| "%v3uint = OpTypeVector %uint 3", |
| "%uint_2 = OpConstant %uint 2", |
| "%uint_3 = OpConstant %uint 3", |
| "%composite_0 = OpConstantComposite %v3uint %uint_2 %uint_3 %uint_2", |
| "%op_0 = OpConstant %uint 2", |
| "%op_1 = OpConstant %uint 3", |
| "%op_2 = OpConstant %uint 6", |
| "%composite_1 = OpConstantComposite %v3uint %op_0 %op_1 %op_2", |
| "%op_3 = OpConstant %uint 2", |
| "%op_4 = OpConstant %uint 12", |
| "%main = OpFunction %void None %main_func_type", |
| "%main_func_entry_block = OpLabel", |
| "OpReturn", |
| "OpFunctionEnd", |
| // clang-format on |
| }; |
| SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>( |
| builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true); |
| } |
| |
| // Test where OpSpecConstantOp depends on another OpSpecConstantOp with |
| // VectorShuffle |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedVectorShuffle) { |
| AssemblyBuilder builder; |
| builder.AppendTypesConstantsGlobals({ |
| // clang-format off |
| "%uint = OpTypeInt 32 0", |
| "%v3uint = OpTypeVector %uint 3", |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_2 = OpConstant %uint 2", |
| "%uint_3 = OpConstant %uint 3", |
| "%uint_4 = OpConstant %uint 4", |
| "%uint_5 = OpConstant %uint 5", |
| "%uint_6 = OpConstant %uint 6", |
| // Folding target: |
| "%composite_0 = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_3", |
| "%composite_1 = OpSpecConstantComposite %v3uint %uint_4 %uint_5 %uint_6", |
| "%vecshuffle = OpSpecConstantOp %v3uint VectorShuffle %composite_0 %composite_1 0 5 3", |
| "%op = OpSpecConstantOp %uint CompositeExtract %vecshuffle 1", |
| // clang-format on |
| }); |
| |
| std::vector<const char*> expected = { |
| // clang-format off |
| "OpCapability Shader", |
| "OpCapability Float64", |
| "%1 = OpExtInstImport \"GLSL.std.450\"", |
| "OpMemoryModel Logical GLSL450", |
| "OpEntryPoint Vertex %main \"main\"", |
| "OpName %void \"void\"", |
| "OpName %main_func_type \"main_func_type\"", |
| "OpName %main \"main\"", |
| "OpName %main_func_entry_block \"main_func_entry_block\"", |
| "OpName %uint \"uint\"", |
| "OpName %v3uint \"v3uint\"", |
| "OpName %uint_1 \"uint_1\"", |
| "OpName %uint_2 \"uint_2\"", |
| "OpName %uint_3 \"uint_3\"", |
| "OpName %uint_4 \"uint_4\"", |
| "OpName %uint_5 \"uint_5\"", |
| "OpName %uint_6 \"uint_6\"", |
| "OpName %composite_0 \"composite_0\"", |
| "OpName %composite_1 \"composite_1\"", |
| "OpName %vecshuffle \"vecshuffle\"", |
| "OpName %op \"op\"", |
| "%void = OpTypeVoid", |
| "%main_func_type = OpTypeFunction %void", |
| "%uint = OpTypeInt 32 0", |
| "%v3uint = OpTypeVector %uint 3", |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_2 = OpConstant %uint 2", |
| "%uint_3 = OpConstant %uint 3", |
| "%uint_4 = OpConstant %uint 4", |
| "%uint_5 = OpConstant %uint 5", |
| "%uint_6 = OpConstant %uint 6", |
| "%composite_0 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3", |
| "%composite_1 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6", |
| "%vecshuffle = OpConstantComposite %v3uint %uint_1 %uint_6 %uint_4", |
| "%op = OpConstant %uint 6", |
| "%main = OpFunction %void None %main_func_type", |
| "%main_func_entry_block = OpLabel", |
| "OpReturn", |
| "OpFunctionEnd", |
| // clang-format on |
| }; |
| SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>( |
| builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true); |
| } |
| |
| // Test CompositeExtract with matrix |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeExtractMaxtrix) { |
| AssemblyBuilder builder; |
| builder.AppendTypesConstantsGlobals({ |
| // clang-format off |
| "%uint = OpTypeInt 32 0", |
| "%v3uint = OpTypeVector %uint 3", |
| "%mat3x3 = OpTypeMatrix %v3uint 3", |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_2 = OpConstant %uint 2", |
| "%uint_3 = OpConstant %uint 3", |
| // Folding target: |
| "%a = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_1", |
| "%b = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_3", |
| "%c = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_1", |
| "%op = OpSpecConstantComposite %mat3x3 %a %b %c", |
| "%x = OpSpecConstantOp %uint CompositeExtract %op 2 1", |
| "%y = OpSpecConstantOp %uint CompositeExtract %op 1 2", |
| // clang-format on |
| }); |
| |
| std::vector<const char*> expected = { |
| // clang-format off |
| "OpCapability Shader", |
| "OpCapability Float64", |
| "%1 = OpExtInstImport \"GLSL.std.450\"", |
| "OpMemoryModel Logical GLSL450", |
| "OpEntryPoint Vertex %main \"main\"", |
| "OpName %void \"void\"", |
| "OpName %main_func_type \"main_func_type\"", |
| "OpName %main \"main\"", |
| "OpName %main_func_entry_block \"main_func_entry_block\"", |
| "OpName %uint \"uint\"", |
| "OpName %v3uint \"v3uint\"", |
| "OpName %mat3x3 \"mat3x3\"", |
| "OpName %uint_1 \"uint_1\"", |
| "OpName %uint_2 \"uint_2\"", |
| "OpName %uint_3 \"uint_3\"", |
| "OpName %a \"a\"", |
| "OpName %b \"b\"", |
| "OpName %c \"c\"", |
| "OpName %op \"op\"", |
| "OpName %x \"x\"", |
| "OpName %y \"y\"", |
| "%void = OpTypeVoid", |
| "%main_func_type = OpTypeFunction %void", |
| "%uint = OpTypeInt 32 0", |
| "%v3uint = OpTypeVector %uint 3", |
| "%mat3x3 = OpTypeMatrix %v3uint 3", |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_2 = OpConstant %uint 2", |
| "%uint_3 = OpConstant %uint 3", |
| "%a = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1", |
| "%b = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_3", |
| "%c = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_1", |
| "%op = OpConstantComposite %mat3x3 %a %b %c", |
| "%x = OpConstant %uint 2", |
| "%y = OpConstant %uint 3", |
| "%main = OpFunction %void None %main_func_type", |
| "%main_func_entry_block = OpLabel", |
| "OpReturn", |
| "OpFunctionEnd", |
| // clang-format on |
| }; |
| SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>( |
| builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVector) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %uint = OpTypeInt 32 0 |
| %v3uint = OpTypeVector %uint 3 |
| %uint_2 = OpConstant %uint 2 |
| %uint_3 = OpConstant %uint 3 |
| %8 = OpConstantNull %uint |
| %9 = OpSpecConstantComposite %v3uint %uint_2 %uint_2 %uint_2 |
| ; CHECK: %15 = OpConstantComposite %v3uint %uint_3 %uint_2 %uint_2 |
| ; CHECK: %uint_3_0 = OpConstant %uint 3 |
| ; CHECK: %17 = OpConstantComposite %v3uint %8 %uint_2 %uint_2 |
| ; CHECK: %18 = OpConstantNull %uint |
| %10 = OpSpecConstantOp %v3uint CompositeInsert %uint_3 %9 0 |
| %11 = OpSpecConstantOp %uint CompositeExtract %10 0 |
| %12 = OpSpecConstantOp %v3uint CompositeInsert %8 %9 0 |
| %13 = OpSpecConstantOp %uint CompositeExtract %12 0 |
| %1 = OpFunction %void None %3 |
| %14 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| CompositeInsertVectorIntoMatrix) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v2float = OpTypeVector %float 2 |
| %mat2v2float = OpTypeMatrix %v2float 2 |
| %float_0 = OpConstant %float 0 |
| %float_1 = OpConstant %float 1 |
| %float_2 = OpConstant %float 2 |
| %v2float_01 = OpConstantComposite %v2float %float_0 %float_1 |
| %v2float_12 = OpConstantComposite %v2float %float_1 %float_2 |
| |
| ; CHECK: %10 = OpConstantComposite %v2float %float_0 %float_1 |
| ; CHECK: %11 = OpConstantComposite %v2float %float_1 %float_2 |
| ; CHECK: %12 = OpConstantComposite %mat2v2float %11 %11 |
| %mat2v2float_1212 = OpConstantComposite %mat2v2float %v2float_12 %v2float_12 |
| |
| ; CHECK: %15 = OpConstantComposite %mat2v2float %10 %11 |
| %spec_0 = OpSpecConstantOp %mat2v2float CompositeInsert %v2float_01 %mat2v2float_1212 0 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrix) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %mat3v3float = OpTypeMatrix %v3float 3 |
| %float_1 = OpConstant %float 1 |
| %float_2 = OpConstant %float 2 |
| %9 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1 |
| %10 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1 |
| %11 = OpSpecConstantComposite %v3float %float_1 %float_2 %float_1 |
| %12 = OpSpecConstantComposite %mat3v3float %9 %10 %11 |
| ; CHECK: %float_2_0 = OpConstant %float 2 |
| ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_2 |
| ; CHECK: %19 = OpConstantComposite %mat3v3float %9 %18 %11 |
| ; CHECK: %float_2_1 = OpConstant %float 2 |
| %13 = OpSpecConstantOp %float CompositeExtract %12 2 1 |
| %14 = OpSpecConstantOp %mat3v3float CompositeInsert %13 %12 1 2 |
| %15 = OpSpecConstantOp %float CompositeExtract %14 1 2 |
| %1 = OpFunction %void None %3 |
| %16 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertFloatNull) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %float_1 = OpConstant %float 1 |
| |
| ; CHECK: %7 = OpConstantNull %float |
| ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %7 |
| ; CHECK: %12 = OpConstantComposite %v3float %7 %7 %float_1 |
| %null = OpConstantNull %float |
| %spec_0 = OpConstantComposite %v3float %null %null %null |
| %spec_1 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_0 2 |
| |
| ; CHECK: %float_1_0 = OpConstant %float 1 |
| %spec_2 = OpSpecConstantOp %float CompositeExtract %spec_1 2 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| CompositeInsertFloatSetNull) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %float_1 = OpConstant %float 1 |
| |
| ; CHECK: %7 = OpConstantNull %float |
| ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %float_1 |
| ; CHECK: %12 = OpConstantComposite %v3float %7 %7 %7 |
| %null = OpConstantNull %float |
| %spec_0 = OpConstantComposite %v3float %null %null %float_1 |
| %spec_1 = OpSpecConstantOp %v3float CompositeInsert %null %spec_0 2 |
| |
| ; CHECK: %13 = OpConstantNull %float |
| %spec_2 = OpSpecConstantOp %float CompositeExtract %spec_1 2 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorNull) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %float_1 = OpConstant %float 1 |
| %null = OpConstantNull %v3float |
| |
| ; CHECK: %11 = OpConstantNull %float |
| ; CHECK: %12 = OpConstantComposite %v3float %11 %11 %float_1 |
| %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_1 %null 2 |
| |
| |
| ; CHECK: %float_1_0 = OpConstant %float 1 |
| %spec_1 = OpSpecConstantOp %float CompositeExtract %spec_0 2 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| CompositeInsertNullVectorIntoMatrix) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v2float = OpTypeVector %float 2 |
| %mat2v2float = OpTypeMatrix %v2float 2 |
| %null = OpConstantNull %mat2v2float |
| %float_1 = OpConstant %float 1 |
| %float_2 = OpConstant %float 2 |
| %v2float_12 = OpConstantComposite %v2float %float_1 %float_2 |
| |
| ; CHECK: %13 = OpConstantNull %v2float |
| ; CHECK: %14 = OpConstantComposite %mat2v2float %10 %13 |
| %spec_0 = OpSpecConstantOp %mat2v2float CompositeInsert %v2float_12 %null 0 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| CompositeInsertVectorKeepNull) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %float_0 = OpConstant %float 0 |
| %null_float = OpConstantNull %float |
| %null_vec = OpConstantNull %v3float |
| |
| ; CHECK: %15 = OpConstantComposite %v3float %7 %7 %float_0 |
| %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_0 %null_vec 2 |
| |
| ; CHECK: %float_0_0 = OpConstant %float 0 |
| %spec_1 = OpSpecConstantOp %float CompositeExtract %spec_0 2 |
| |
| ; CHECK: %17 = OpConstantComposite %v3float %7 %7 %7 |
| %spec_2 = OpSpecConstantOp %v3float CompositeInsert %null_float %null_vec 2 |
| |
| ; CHECK: %18 = OpConstantNull %float |
| %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 2 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| %add = OpFAdd %float %spec_3 %spec_3 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| CompositeInsertVectorChainNull) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %float_1 = OpConstant %float 1 |
| %null = OpConstantNull %v3float |
| |
| ; CHECK: %15 = OpConstantNull %float |
| ; CHECK: %16 = OpConstantComposite %v3float %15 %15 %float_1 |
| ; CHECK: %17 = OpConstantComposite %v3float %15 %float_1 %float_1 |
| ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_1 |
| %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_1 %null 2 |
| %spec_1 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_0 1 |
| %spec_2 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_1 0 |
| |
| ; CHECK: %float_1_0 = OpConstant %float 1 |
| ; CHECK: %float_1_1 = OpConstant %float 1 |
| ; CHECK: %float_1_2 = OpConstant %float 1 |
| %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 0 |
| %spec_4 = OpSpecConstantOp %float CompositeExtract %spec_2 1 |
| %spec_5 = OpSpecConstantOp %float CompositeExtract %spec_2 2 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, |
| CompositeInsertVectorChainReset) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %float_1 = OpConstant %float 1 |
| %null = OpConstantNull %float |
| ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %float_1 |
| %spec_0 = OpConstantComposite %v3float %null %null %float_1 |
| |
| ; set to null |
| ; CHECK: %13 = OpConstantComposite %v3float %7 %7 %7 |
| %spec_1 = OpSpecConstantOp %v3float CompositeInsert %null %spec_0 2 |
| |
| ; set to back to original value |
| ; CHECK: %14 = OpConstantComposite %v3float %7 %7 %float_1 |
| %spec_2 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_1 2 |
| |
| ; CHECK: %float_1_0 = OpConstant %float 1 |
| %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 2 |
| %1 = OpFunction %void None %3 |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrixNull) { |
| const std::string test = |
| R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %float = OpTypeFloat 32 |
| %int = OpTypeInt 32 0 |
| %v2float = OpTypeVector %float 2 |
| %mat2v2float = OpTypeMatrix %v2float 2 |
| %null = OpConstantNull %mat2v2float |
| %float_1 = OpConstant %float 1 |
| ; CHECK: %13 = OpConstantNull %v2float |
| ; CHECK: %14 = OpConstantNull %float |
| ; CHECK: %15 = OpConstantComposite %v2float %float_1 %14 |
| ; CHECK: %16 = OpConstantComposite %mat2v2float %13 %15 |
| %spec = OpSpecConstantOp %mat2v2float CompositeInsert %float_1 %null 1 0 |
| ; extra type def to make sure new type def are not just thrown at end |
| %v2int = OpTypeVector %int 2 |
| %main = OpFunction %void None %func |
| %label = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false); |
| } |
| |
| // All types and some common constants that are potentially required in |
| // FoldSpecConstantOpAndCompositeTest. |
| std::vector<std::string> CommonTypesAndConstants() { |
| return std::vector<std::string>{ |
| // clang-format off |
| // scalar types |
| "%bool = OpTypeBool", |
| "%ushort = OpTypeInt 16 0", |
| "%short = OpTypeInt 16 1", |
| "%uint = OpTypeInt 32 0", |
| "%int = OpTypeInt 32 1", |
| "%ulong = OpTypeInt 64 0", |
| "%long = OpTypeInt 64 1", |
| "%float = OpTypeFloat 32", |
| "%double = OpTypeFloat 64", |
| // vector types |
| "%v2bool = OpTypeVector %bool 2", |
| "%v2uint = OpTypeVector %uint 2", |
| "%v2int = OpTypeVector %int 2", |
| "%v3int = OpTypeVector %int 3", |
| "%v4int = OpTypeVector %int 4", |
| "%v2long = OpTypeVector %long 2", |
| "%v2ulong = OpTypeVector %ulong 2", |
| "%v2float = OpTypeVector %float 2", |
| "%v2double = OpTypeVector %double 2", |
| // variable pointer types |
| "%_pf_bool = OpTypePointer Function %bool", |
| "%_pf_uint = OpTypePointer Function %uint", |
| "%_pf_int = OpTypePointer Function %int", |
| "%_pf_float = OpTypePointer Function %float", |
| "%_pf_double = OpTypePointer Function %double", |
| "%_pf_v2int = OpTypePointer Function %v2int", |
| "%_pf_v2float = OpTypePointer Function %v2float", |
| "%_pf_v2double = OpTypePointer Function %v2double", |
| // struct types |
| "%inner_struct = OpTypeStruct %bool %int %float", |
| "%outer_struct = OpTypeStruct %inner_struct %int", |
| "%flat_struct = OpTypeStruct %bool %int %float", |
| |
| // common constants |
| // scalar constants: |
| "%bool_true = OpConstantTrue %bool", |
| "%bool_false = OpConstantFalse %bool", |
| "%bool_null = OpConstantNull %bool", |
| "%signed_zero = OpConstant %int 0", |
| "%unsigned_zero = OpConstant %uint 0", |
| "%long_zero = OpConstant %long 0", |
| "%ulong_zero = OpConstant %ulong 0", |
| "%signed_one = OpConstant %int 1", |
| "%unsigned_one = OpConstant %uint 1", |
| "%signed_two = OpConstant %int 2", |
| "%unsigned_two = OpConstant %uint 2", |
| "%signed_three = OpConstant %int 3", |
| "%unsigned_three = OpConstant %uint 3", |
| "%signed_null = OpConstantNull %int", |
| "%unsigned_null = OpConstantNull %uint", |
| "%signed_minus_one = OpConstant %int -1", |
| // vector constants: |
| "%bool_true_vec = OpConstantComposite %v2bool %bool_true %bool_true", |
| "%bool_false_vec = OpConstantComposite %v2bool %bool_false %bool_false", |
| "%bool_null_vec = OpConstantNull %v2bool", |
| "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", |
| "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", |
| "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one", |
| "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%signed_two_vec = OpConstantComposite %v2int %signed_two %signed_two", |
| "%unsigned_two_vec = OpConstantComposite %v2uint %unsigned_two %unsigned_two", |
| "%signed_three_vec = OpConstantComposite %v2int %signed_three %signed_three", |
| "%unsigned_three_vec = OpConstantComposite %v2uint %unsigned_three %unsigned_three", |
| "%signed_null_vec = OpConstantNull %v2int", |
| "%unsigned_null_vec = OpConstantNull %v2uint", |
| "%signed_minus_one_vec = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", |
| "%v4int_0_1_2_3 = OpConstantComposite %v4int %signed_zero %signed_one %signed_two %signed_three", |
| // clang-format on |
| }; |
| } |
| |
| // A helper function to strip OpName instructions from the given string of |
| // disassembly code. Returns the string with all OpName instruction stripped. |
| std::string StripOpNameInstructions(const std::string& str) { |
| std::stringstream ss(str); |
| std::ostringstream oss; |
| std::string inst_str; |
| while (std::getline(ss, inst_str, '\n')) { |
| if (inst_str.find("OpName %") == std::string::npos) { |
| oss << inst_str << '\n'; |
| } |
| } |
| return oss.str(); |
| } |
| |
| struct FoldSpecConstantOpAndCompositePassTestCase { |
| // Original constants with unfolded spec constants. |
| std::vector<std::string> original; |
| // Expected constant after folding. |
| std::vector<std::string> expected; |
| }; |
| |
| using FoldSpecConstantOpAndCompositePassTest = PassTest< |
| ::testing::TestWithParam<FoldSpecConstantOpAndCompositePassTestCase>>; |
| |
| TEST_P(FoldSpecConstantOpAndCompositePassTest, ParamTestCase) { |
| AssemblyBuilder test_code_builder, expected_code_builder; |
| const auto& tc = GetParam(); |
| test_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants()); |
| test_code_builder.AppendTypesConstantsGlobals(tc.original); |
| expected_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants()); |
| expected_code_builder.AppendTypesConstantsGlobals(tc.expected); |
| const std::string original = test_code_builder.GetCode(); |
| const std::string expected = expected_code_builder.GetCode(); |
| |
| // Run the optimization and get the result code in disassembly. |
| std::string optimized; |
| auto status = Pass::Status::SuccessWithoutChange; |
| std::tie(optimized, status) = |
| SinglePassRunAndDisassemble<FoldSpecConstantOpAndCompositePass>( |
| original, /* skip_nop = */ true, /* do_validation = */ false); |
| |
| // Check the optimized code, but ignore the OpName instructions. |
| EXPECT_NE(Pass::Status::Failure, status); |
| EXPECT_EQ( |
| StripOpNameInstructions(expected) == StripOpNameInstructions(original), |
| status == Pass::Status::SuccessWithoutChange); |
| EXPECT_EQ(StripOpNameInstructions(expected), |
| StripOpNameInstructions(optimized)); |
| } |
| |
| // Tests that OpSpecConstantComposite opcodes are replace with |
| // OpConstantComposite correctly. |
| INSTANTIATE_TEST_SUITE_P( |
| Composite, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // normal vector |
| { |
| // original |
| { |
| "%spec_v2bool = OpSpecConstantComposite %v2bool %bool_true %bool_false", |
| "%spec_v2uint = OpSpecConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%spec_v2int_a = OpSpecConstantComposite %v2int %signed_one %signed_two", |
| // Spec constants whose value can not be fully resolved should |
| // not be processed. |
| "%spec_int = OpSpecConstant %int 99", |
| "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int", |
| }, |
| // expected |
| { |
| "%spec_v2bool = OpConstantComposite %v2bool %bool_true %bool_false", |
| "%spec_v2uint = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%spec_v2int_a = OpConstantComposite %v2int %signed_one %signed_two", |
| "%spec_int = OpSpecConstant %int 99", |
| "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int", |
| }, |
| }, |
| // vector with null constants |
| { |
| // original |
| { |
| "%null_bool = OpConstantNull %bool", |
| "%null_int = OpConstantNull %int", |
| "%spec_v2bool = OpSpecConstantComposite %v2bool %null_bool %null_bool", |
| "%spec_v3int = OpSpecConstantComposite %v3int %null_int %null_int %null_int", |
| "%spec_v4int = OpSpecConstantComposite %v4int %null_int %null_int %null_int %null_int", |
| }, |
| // expected |
| { |
| "%null_bool = OpConstantNull %bool", |
| "%null_int = OpConstantNull %int", |
| "%spec_v2bool = OpConstantComposite %v2bool %null_bool %null_bool", |
| "%spec_v3int = OpConstantComposite %v3int %null_int %null_int %null_int", |
| "%spec_v4int = OpConstantComposite %v4int %null_int %null_int %null_int %null_int", |
| }, |
| }, |
| // flat struct |
| { |
| // original |
| { |
| "%float_1 = OpConstant %float 1", |
| "%flat_1 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1", |
| // following struct should not be folded as the value of |
| // %spec_float is not determined. |
| "%spec_float = OpSpecConstant %float 1", |
| "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float", |
| }, |
| // expected |
| { |
| "%float_1 = OpConstant %float 1", |
| "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", |
| "%spec_float = OpSpecConstant %float 1", |
| "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float", |
| } |
| }, |
| // nested struct |
| { |
| // original |
| { |
| "%float_1 = OpConstant %float 1", |
| "%inner_1 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %float_1", |
| "%outer_1 = OpSpecConstantComposite %outer_struct %inner_1 %signed_one", |
| // following structs should not be folded as the value of |
| // %spec_float is not determined. |
| "%spec_float = OpSpecConstant %float 1", |
| "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", |
| "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one", |
| }, |
| // expected |
| { |
| "%float_1 = OpConstant %float 1", |
| "%inner_1 = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", |
| "%outer_1 = OpConstantComposite %outer_struct %inner_1 %signed_one", |
| "%spec_float = OpSpecConstant %float 1", |
| "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", |
| "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one", |
| } |
| }, |
| // composite constants touched by OpUndef should be skipped |
| { |
| // original |
| { |
| "%undef = OpUndef %float", |
| "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", |
| "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one", |
| }, |
| // expected |
| { |
| "%undef = OpUndef %float", |
| "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", |
| "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one", |
| }, |
| }, |
| // Fold an QuantizetoF16 instruction |
| { |
| // original |
| { |
| "%float_1 = OpConstant %float 1", |
| "%quant_float = OpSpecConstantOp %float QuantizeToF16 %float_1", |
| }, |
| // expected |
| { |
| "%float_1 = OpConstant %float 1", |
| "%quant_float = OpConstant %float 1", |
| }, |
| } |
| // clang-format on |
| }))); |
| |
| // Tests for operations that resulting in different types. |
| INSTANTIATE_TEST_SUITE_P( |
| Cast, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // int -> bool scalar |
| { |
| // original |
| { |
| "%spec_bool_t = OpSpecConstantOp %bool INotEqual %signed_three %signed_zero", |
| "%spec_bool_f = OpSpecConstantOp %bool INotEqual %signed_zero %signed_zero", |
| "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %signed_null %signed_zero", |
| }, |
| // expected |
| { |
| "%spec_bool_t = OpConstantTrue %bool", |
| "%spec_bool_f = OpConstantFalse %bool", |
| "%spec_bool_from_null = OpConstantFalse %bool", |
| }, |
| }, |
| |
| // uint -> bool scalar |
| { |
| // original |
| { |
| "%spec_bool_t = OpSpecConstantOp %bool INotEqual %unsigned_three %unsigned_zero", |
| "%spec_bool_f = OpSpecConstantOp %bool INotEqual %unsigned_zero %unsigned_zero", |
| "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %unsigned_null %unsigned_zero", |
| }, |
| // expected |
| { |
| "%spec_bool_t = OpConstantTrue %bool", |
| "%spec_bool_f = OpConstantFalse %bool", |
| "%spec_bool_from_null = OpConstantFalse %bool", |
| }, |
| }, |
| |
| // bool -> int scalar |
| { |
| // original |
| { |
| "%spec_int_one = OpSpecConstantOp %int Select %bool_true %signed_one %signed_zero", |
| "%spec_int_zero = OpSpecConstantOp %int Select %bool_false %signed_one %signed_zero", |
| "%spec_int_from_null = OpSpecConstantOp %int Select %bool_null %signed_one %signed_zero", |
| }, |
| // expected |
| { |
| "%spec_int_one = OpConstant %int 1", |
| "%spec_int_zero = OpConstant %int 0", |
| "%spec_int_from_null = OpConstant %int 0", |
| }, |
| }, |
| |
| // uint -> int scalar |
| { |
| // original |
| { |
| "%spec_int_one = OpSpecConstantOp %int IAdd %unsigned_one %signed_zero", |
| "%spec_int_zero = OpSpecConstantOp %int IAdd %unsigned_zero %signed_zero", |
| "%spec_int_from_null = OpSpecConstantOp %int IAdd %unsigned_null %unsigned_zero", |
| }, |
| // expected |
| { |
| "%spec_int_one = OpConstant %int 1", |
| "%spec_int_zero = OpConstant %int 0", |
| "%spec_int_from_null = OpConstant %int 0", |
| }, |
| }, |
| |
| // bool -> uint scalar |
| { |
| // original |
| { |
| "%spec_uint_one = OpSpecConstantOp %uint Select %bool_true %unsigned_one %unsigned_zero", |
| "%spec_uint_zero = OpSpecConstantOp %uint Select %bool_false %unsigned_one %unsigned_zero", |
| "%spec_uint_from_null = OpSpecConstantOp %uint Select %bool_null %unsigned_one %unsigned_zero", |
| }, |
| // expected |
| { |
| "%spec_uint_one = OpConstant %uint 1", |
| "%spec_uint_zero = OpConstant %uint 0", |
| "%spec_uint_from_null = OpConstant %uint 0", |
| }, |
| }, |
| |
| // int -> uint scalar |
| { |
| // original |
| { |
| "%spec_uint_one = OpSpecConstantOp %uint IAdd %signed_one %unsigned_zero", |
| "%spec_uint_zero = OpSpecConstantOp %uint IAdd %signed_zero %unsigned_zero", |
| "%spec_uint_from_null = OpSpecConstantOp %uint IAdd %signed_null %unsigned_zero", |
| }, |
| // expected |
| { |
| "%spec_uint_one = OpConstant %uint 1", |
| "%spec_uint_zero = OpConstant %uint 0", |
| "%spec_uint_from_null = OpConstant %uint 0", |
| }, |
| }, |
| |
| // int -> bool vector |
| { |
| // original |
| { |
| "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %signed_three_vec %signed_zero_vec", |
| "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %signed_zero_vec %signed_zero_vec", |
| "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %signed_null_vec %signed_zero_vec", |
| }, |
| // expected |
| { |
| "%true = OpConstantTrue %bool", |
| "%true_0 = OpConstantTrue %bool", |
| "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true", |
| "%false = OpConstantFalse %bool", |
| "%false_0 = OpConstantFalse %bool", |
| "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false", |
| "%false_1 = OpConstantFalse %bool", |
| "%false_2 = OpConstantFalse %bool", |
| "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false", |
| }, |
| }, |
| |
| // uint -> bool vector |
| { |
| // original |
| { |
| "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_three_vec %unsigned_zero_vec", |
| "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_zero_vec %unsigned_zero_vec", |
| "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %unsigned_null_vec %unsigned_zero_vec", |
| }, |
| // expected |
| { |
| "%true = OpConstantTrue %bool", |
| "%true_0 = OpConstantTrue %bool", |
| "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true", |
| "%false = OpConstantFalse %bool", |
| "%false_0 = OpConstantFalse %bool", |
| "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false", |
| "%false_1 = OpConstantFalse %bool", |
| "%false_2 = OpConstantFalse %bool", |
| "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false", |
| }, |
| }, |
| |
| // bool -> int vector |
| { |
| // original |
| { |
| "%spec_int_one_vec = OpSpecConstantOp %v2int Select %bool_true_vec %signed_one_vec %signed_zero_vec", |
| "%spec_int_zero_vec = OpSpecConstantOp %v2int Select %bool_false_vec %signed_one_vec %signed_zero_vec", |
| "%spec_int_from_null = OpSpecConstantOp %v2int Select %bool_null_vec %signed_one_vec %signed_zero_vec", |
| }, |
| // expected |
| { |
| "%int_1 = OpConstant %int 1", |
| "%int_1_0 = OpConstant %int 1", |
| "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one", |
| "%int_0 = OpConstant %int 0", |
| "%int_0_0 = OpConstant %int 0", |
| "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", |
| "%int_0_1 = OpConstant %int 0", |
| "%int_0_2 = OpConstant %int 0", |
| "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero", |
| }, |
| }, |
| |
| // uint -> int vector |
| { |
| // original |
| { |
| "%spec_int_one_vec = OpSpecConstantOp %v2int IAdd %unsigned_one_vec %signed_zero_vec", |
| "%spec_int_zero_vec = OpSpecConstantOp %v2int IAdd %unsigned_zero_vec %signed_zero_vec", |
| "%spec_int_from_null = OpSpecConstantOp %v2int IAdd %unsigned_null_vec %signed_zero_vec", |
| }, |
| // expected |
| { |
| "%int_1 = OpConstant %int 1", |
| "%int_1_0 = OpConstant %int 1", |
| "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one", |
| "%int_0 = OpConstant %int 0", |
| "%int_0_0 = OpConstant %int 0", |
| "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", |
| "%int_0_1 = OpConstant %int 0", |
| "%int_0_2 = OpConstant %int 0", |
| "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero", |
| }, |
| }, |
| |
| // bool -> uint vector |
| { |
| // original |
| { |
| "%spec_uint_one_vec = OpSpecConstantOp %v2uint Select %bool_true_vec %unsigned_one_vec %unsigned_zero_vec", |
| "%spec_uint_zero_vec = OpSpecConstantOp %v2uint Select %bool_false_vec %unsigned_one_vec %unsigned_zero_vec", |
| "%spec_uint_from_null = OpSpecConstantOp %v2uint Select %bool_null_vec %unsigned_one_vec %unsigned_zero_vec", |
| }, |
| // expected |
| { |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_1_0 = OpConstant %uint 1", |
| "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%uint_0 = OpConstant %uint 0", |
| "%uint_0_0 = OpConstant %uint 0", |
| "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", |
| "%uint_0_1 = OpConstant %uint 0", |
| "%uint_0_2 = OpConstant %uint 0", |
| "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", |
| }, |
| }, |
| |
| // int -> uint vector |
| { |
| // original |
| { |
| "%spec_uint_one_vec = OpSpecConstantOp %v2uint IAdd %signed_one_vec %unsigned_zero_vec", |
| "%spec_uint_zero_vec = OpSpecConstantOp %v2uint IAdd %signed_zero_vec %unsigned_zero_vec", |
| "%spec_uint_from_null = OpSpecConstantOp %v2uint IAdd %signed_null_vec %unsigned_zero_vec", |
| }, |
| // expected |
| { |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_1_0 = OpConstant %uint 1", |
| "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%uint_0 = OpConstant %uint 0", |
| "%uint_0_0 = OpConstant %uint 0", |
| "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", |
| "%uint_0_1 = OpConstant %uint 0", |
| "%uint_0_2 = OpConstant %uint 0", |
| "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", |
| }, |
| }, |
| |
| // UConvert scalar |
| { |
| // original |
| { |
| "%spec_uint_zero = OpSpecConstantOp %uint UConvert %bool_false", |
| "%spec_uint_one = OpSpecConstantOp %uint UConvert %bool_true", |
| "%spec_ulong_zero = OpSpecConstantOp %ulong UConvert %unsigned_zero", |
| "%spec_ulong_one = OpSpecConstantOp %ulong UConvert %unsigned_one", |
| "%spec_short_zero = OpSpecConstantOp %ushort UConvert %unsigned_zero", |
| "%spec_short_one = OpSpecConstantOp %ushort UConvert %unsigned_one", |
| "%uint_max = OpConstant %uint 4294967295", |
| "%spec_ushort_max = OpSpecConstantOp %ushort UConvert %uint_max", |
| "%uint_0xDDDDDDDD = OpConstant %uint 3722304989", |
| "%spec_ushort_0xDDDD = OpSpecConstantOp %ushort UConvert %uint_0xDDDDDDDD", |
| }, |
| // expected |
| { |
| "%spec_uint_zero = OpConstant %uint 0", |
| "%spec_uint_one = OpConstant %uint 1", |
| "%spec_ulong_zero = OpConstant %ulong 0", |
| "%spec_ulong_one = OpConstant %ulong 1", |
| "%spec_short_zero = OpConstant %ushort 0", |
| "%spec_short_one = OpConstant %ushort 1", |
| "%uint_max = OpConstant %uint 4294967295", |
| "%spec_ushort_max = OpConstant %ushort 65535", |
| "%uint_0xDDDDDDDD = OpConstant %uint 3722304989", |
| "%spec_ushort_0xDDDD = OpConstant %ushort 56797", |
| }, |
| }, |
| |
| // SConvert scalar |
| { |
| // original |
| { |
| "%spec_long_zero = OpSpecConstantOp %long SConvert %signed_zero", |
| "%spec_long_one = OpSpecConstantOp %long SConvert %signed_one", |
| "%spec_long_minus_one = OpSpecConstantOp %long SConvert %signed_minus_one", |
| "%spec_short_minus_one_trunc = OpSpecConstantOp %short SConvert %signed_minus_one", |
| "%int_2_to_17_minus_one = OpConstant %int 131071", |
| "%spec_short_minus_one_trunc2 = OpSpecConstantOp %short SConvert %int_2_to_17_minus_one", |
| }, |
| // expected |
| { |
| "%spec_long_zero = OpConstant %long 0", |
| "%spec_long_one = OpConstant %long 1", |
| "%spec_long_minus_one = OpConstant %long -1", |
| "%spec_short_minus_one_trunc = OpConstant %short -1", |
| "%int_2_to_17_minus_one = OpConstant %int 131071", |
| "%spec_short_minus_one_trunc2 = OpConstant %short -1", |
| }, |
| }, |
| |
| // UConvert vector |
| { |
| // original |
| { |
| "%spec_v2uint_zero = OpSpecConstantOp %v2uint UConvert %bool_false_vec", |
| "%spec_v2uint_one = OpSpecConstantOp %v2uint UConvert %bool_true_vec", |
| "%spec_v2ulong_zero = OpSpecConstantOp %v2ulong UConvert %unsigned_zero_vec", |
| "%spec_v2ulong_one = OpSpecConstantOp %v2ulong UConvert %unsigned_one_vec", |
| }, |
| // expected |
| { |
| "%uint_0 = OpConstant %uint 0", |
| "%uint_0_0 = OpConstant %uint 0", |
| "%spec_v2uint_zero = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_1_0 = OpConstant %uint 1", |
| "%spec_v2uint_one = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%ulong_0 = OpConstant %ulong 0", |
| "%ulong_0_0 = OpConstant %ulong 0", |
| "%spec_v2ulong_zero = OpConstantComposite %v2ulong %ulong_zero %ulong_zero", |
| "%ulong_1 = OpConstant %ulong 1", |
| "%ulong_1_0 = OpConstant %ulong 1", |
| "%spec_v2ulong_one = OpConstantComposite %v2ulong %ulong_1 %ulong_1", |
| }, |
| }, |
| |
| // SConvert vector |
| { |
| // original |
| { |
| "%spec_v2long_zero = OpSpecConstantOp %v2long SConvert %signed_zero_vec", |
| "%spec_v2long_one = OpSpecConstantOp %v2long SConvert %signed_one_vec", |
| "%spec_v2long_minus_one = OpSpecConstantOp %v2long SConvert %signed_minus_one_vec", |
| }, |
| // expected |
| { |
| "%long_0 = OpConstant %long 0", |
| "%long_0_0 = OpConstant %long 0", |
| "%spec_v2long_zero = OpConstantComposite %v2long %long_zero %long_zero", |
| "%long_1 = OpConstant %long 1", |
| "%long_1_0 = OpConstant %long 1", |
| "%spec_v2long_one = OpConstantComposite %v2long %long_1 %long_1", |
| "%long_n1 = OpConstant %long -1", |
| "%long_n1_0 = OpConstant %long -1", |
| "%spec_v2long_minus_one = OpConstantComposite %v2long %long_n1 %long_n1", |
| }, |
| }, |
| // clang-format on |
| }))); |
| |
| // Tests about boolean scalar logical operations and comparison operations with |
| // scalar int/uint type. |
| INSTANTIATE_TEST_SUITE_P( |
| Logical, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // scalar integer comparison |
| { |
| // original |
| { |
| "%int_minus_1 = OpConstant %int -1", |
| |
| "%slt_0_1 = OpSpecConstantOp %bool SLessThan %signed_zero %signed_one", |
| "%sgt_0_1 = OpSpecConstantOp %bool SGreaterThan %signed_zero %signed_one", |
| "%sle_2_2 = OpSpecConstantOp %bool SLessThanEqual %signed_two %signed_two", |
| "%sge_2_1 = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_one", |
| "%sge_2_null = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_null", |
| "%sge_minus_1_null = OpSpecConstantOp %bool SGreaterThanEqual %int_minus_1 %signed_null", |
| |
| "%ult_0_1 = OpSpecConstantOp %bool ULessThan %unsigned_zero %unsigned_one", |
| "%ugt_0_1 = OpSpecConstantOp %bool UGreaterThan %unsigned_zero %unsigned_one", |
| "%ule_2_3 = OpSpecConstantOp %bool ULessThanEqual %unsigned_two %unsigned_three", |
| "%uge_1_1 = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_one %unsigned_one", |
| "%uge_2_null = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_two %unsigned_null", |
| "%uge_minus_1_null = OpSpecConstantOp %bool UGreaterThanEqual %int_minus_1 %unsigned_null", |
| }, |
| // expected |
| { |
| "%int_minus_1 = OpConstant %int -1", |
| |
| "%slt_0_1 = OpConstantTrue %bool", |
| "%sgt_0_1 = OpConstantFalse %bool", |
| "%sle_2_2 = OpConstantTrue %bool", |
| "%sge_2_1 = OpConstantTrue %bool", |
| "%sge_2_null = OpConstantTrue %bool", |
| "%sge_minus_1_null = OpConstantFalse %bool", |
| |
| "%ult_0_1 = OpConstantTrue %bool", |
| "%ugt_0_1 = OpConstantFalse %bool", |
| "%ule_2_3 = OpConstantTrue %bool", |
| "%uge_1_1 = OpConstantTrue %bool", |
| "%uge_2_null = OpConstantTrue %bool", |
| "%uge_minus_1_null = OpConstantTrue %bool", |
| }, |
| }, |
| // Logical and, or, xor. |
| { |
| // original |
| { |
| "%logical_or = OpSpecConstantOp %bool LogicalOr %bool_true %bool_false", |
| "%logical_and = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_false", |
| "%logical_not = OpSpecConstantOp %bool LogicalNot %bool_true", |
| "%logical_eq = OpSpecConstantOp %bool LogicalEqual %bool_true %bool_true", |
| "%logical_neq = OpSpecConstantOp %bool LogicalNotEqual %bool_true %bool_true", |
| "%logical_and_null = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_null", |
| }, |
| // expected |
| { |
| "%logical_or = OpConstantTrue %bool", |
| "%logical_and = OpConstantFalse %bool", |
| "%logical_not = OpConstantFalse %bool", |
| "%logical_eq = OpConstantTrue %bool", |
| "%logical_neq = OpConstantFalse %bool", |
| "%logical_and_null = OpConstantFalse %bool", |
| }, |
| }, |
| // clang-format on |
| }))); |
| |
| // Tests about arithmetic operations for scalar int and uint types. |
| INSTANTIATE_TEST_SUITE_P( |
| ScalarArithmetic, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // scalar integer negate |
| { |
| // original |
| { |
| "%int_minus_1 = OpSpecConstantOp %int SNegate %signed_one", |
| "%int_minus_2 = OpSpecConstantOp %int SNegate %signed_two", |
| "%int_neg_null = OpSpecConstantOp %int SNegate %signed_null", |
| "%int_max = OpConstant %int 2147483647", |
| "%int_neg_max = OpSpecConstantOp %int SNegate %int_max", |
| }, |
| // expected |
| { |
| "%int_minus_1 = OpConstant %int -1", |
| "%int_minus_2 = OpConstant %int -2", |
| "%int_neg_null = OpConstant %int 0", |
| "%int_max = OpConstant %int 2147483647", |
| "%int_neg_max = OpConstant %int -2147483647", |
| }, |
| }, |
| // scalar integer not |
| { |
| // original |
| { |
| "%uint_4294967294 = OpSpecConstantOp %uint Not %unsigned_one", |
| "%uint_4294967293 = OpSpecConstantOp %uint Not %unsigned_two", |
| "%uint_neg_null = OpSpecConstantOp %uint Not %unsigned_null", |
| }, |
| // expected |
| { |
| "%uint_4294967294 = OpConstant %uint 4294967294", |
| "%uint_4294967293 = OpConstant %uint 4294967293", |
| "%uint_neg_null = OpConstant %uint 4294967295", |
| }, |
| }, |
| // scalar integer add, sub, mul, div |
| { |
| // original |
| { |
| "%signed_max = OpConstant %int 2147483647", |
| "%signed_min = OpConstant %int -2147483648", |
| |
| "%spec_int_iadd = OpSpecConstantOp %int IAdd %signed_three %signed_two", |
| "%spec_int_isub = OpSpecConstantOp %int ISub %signed_one %spec_int_iadd", |
| "%spec_int_sdiv = OpSpecConstantOp %int SDiv %spec_int_isub %signed_two", |
| "%spec_int_imul = OpSpecConstantOp %int IMul %spec_int_sdiv %signed_three", |
| "%spec_int_iadd_null = OpSpecConstantOp %int IAdd %spec_int_imul %signed_null", |
| "%spec_int_imul_null = OpSpecConstantOp %int IMul %spec_int_iadd_null %signed_null", |
| "%spec_int_iadd_overflow = OpSpecConstantOp %int IAdd %signed_max %signed_three", |
| "%spec_int_isub_overflow = OpSpecConstantOp %int ISub %signed_min %signed_three", |
| |
| "%spec_uint_iadd = OpSpecConstantOp %uint IAdd %unsigned_three %unsigned_two", |
| "%spec_uint_isub = OpSpecConstantOp %uint ISub %unsigned_one %spec_uint_iadd", |
| "%spec_uint_udiv = OpSpecConstantOp %uint UDiv %spec_uint_isub %unsigned_three", |
| "%spec_uint_imul = OpSpecConstantOp %uint IMul %spec_uint_udiv %unsigned_two", |
| "%spec_uint_isub_null = OpSpecConstantOp %uint ISub %spec_uint_imul %signed_null", |
| }, |
| // expected |
| { |
| "%signed_max = OpConstant %int 2147483647", |
| "%signed_min = OpConstant %int -2147483648", |
| |
| "%spec_int_iadd = OpConstant %int 5", |
| "%spec_int_isub = OpConstant %int -4", |
| "%spec_int_sdiv = OpConstant %int -2", |
| "%spec_int_imul = OpConstant %int -6", |
| "%spec_int_iadd_null = OpConstant %int -6", |
| "%spec_int_imul_null = OpConstant %int 0", |
| "%spec_int_iadd_overflow = OpConstant %int -2147483646", |
| "%spec_int_isub_overflow = OpConstant %int 2147483645", |
| |
| "%spec_uint_iadd = OpConstant %uint 5", |
| "%spec_uint_isub = OpConstant %uint 4294967292", |
| "%spec_uint_udiv = OpConstant %uint 1431655764", |
| "%spec_uint_imul = OpConstant %uint 2863311528", |
| "%spec_uint_isub_null = OpConstant %uint 2863311528", |
| }, |
| }, |
| // scalar integer rem, mod |
| { |
| // original |
| { |
| // common constants |
| "%int_7 = OpConstant %int 7", |
| "%uint_7 = OpConstant %uint 7", |
| "%int_minus_7 = OpConstant %int -7", |
| "%int_minus_3 = OpConstant %int -3", |
| |
| // srem |
| "%7_srem_3 = OpSpecConstantOp %int SRem %int_7 %signed_three", |
| "%minus_7_srem_3 = OpSpecConstantOp %int SRem %int_minus_7 %signed_three", |
| "%7_srem_minus_3 = OpSpecConstantOp %int SRem %int_7 %int_minus_3", |
| "%minus_7_srem_minus_3 = OpSpecConstantOp %int SRem %int_minus_7 %int_minus_3", |
| // smod |
| "%7_smod_3 = OpSpecConstantOp %int SMod %int_7 %signed_three", |
| "%minus_7_smod_3 = OpSpecConstantOp %int SMod %int_minus_7 %signed_three", |
| "%7_smod_minus_3 = OpSpecConstantOp %int SMod %int_7 %int_minus_3", |
| "%minus_7_smod_minus_3 = OpSpecConstantOp %int SMod %int_minus_7 %int_minus_3", |
| // umod |
| "%7_umod_3 = OpSpecConstantOp %uint UMod %uint_7 %unsigned_three", |
| // null constant |
| "%null_srem_3 = OpSpecConstantOp %int SRem %signed_null %signed_three", |
| "%null_smod_3 = OpSpecConstantOp %int SMod %signed_null %signed_three", |
| "%null_umod_3 = OpSpecConstantOp %uint UMod %unsigned_null %unsigned_three", |
| }, |
| // expected |
| { |
| // common constants |
| "%int_7 = OpConstant %int 7", |
| "%uint_7 = OpConstant %uint 7", |
| "%int_minus_7 = OpConstant %int -7", |
| "%int_minus_3 = OpConstant %int -3", |
| |
| // srem |
| "%7_srem_3 = OpConstant %int 1", |
| "%minus_7_srem_3 = OpConstant %int -1", |
| "%7_srem_minus_3 = OpConstant %int 1", |
| "%minus_7_srem_minus_3 = OpConstant %int -1", |
| // smod |
| "%7_smod_3 = OpConstant %int 1", |
| "%minus_7_smod_3 = OpConstant %int 2", |
| "%7_smod_minus_3 = OpConstant %int -2", |
| "%minus_7_smod_minus_3 = OpConstant %int -1", |
| // umod |
| "%7_umod_3 = OpConstant %uint 1", |
| // null constant |
| "%null_srem_3 = OpConstant %int 0", |
| "%null_smod_3 = OpConstant %int 0", |
| "%null_umod_3 = OpConstant %uint 0", |
| }, |
| }, |
| // scalar integer bitwise and shift |
| { |
| // original |
| { |
| // bitwise |
| "%xor_1_3 = OpSpecConstantOp %int BitwiseXor %signed_one %signed_three", |
| "%and_1_2 = OpSpecConstantOp %int BitwiseAnd %signed_one %xor_1_3", |
| "%or_1_2 = OpSpecConstantOp %int BitwiseOr %signed_one %xor_1_3", |
| "%xor_3_null = OpSpecConstantOp %int BitwiseXor %or_1_2 %signed_null", |
| |
| // shift |
| "%unsigned_31 = OpConstant %uint 31", |
| "%unsigned_left_shift_max = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_one %unsigned_31", |
| "%unsigned_right_shift_logical = OpSpecConstantOp %uint ShiftRightLogical %unsigned_left_shift_max %unsigned_31", |
| "%signed_right_shift_arithmetic = OpSpecConstantOp %int ShiftRightArithmetic %unsigned_left_shift_max %unsigned_31", |
| "%left_shift_null_31 = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_null %unsigned_31", |
| "%right_shift_31_null = OpSpecConstantOp %uint ShiftRightLogical %unsigned_31 %unsigned_null", |
| }, |
| // expected |
| { |
| "%xor_1_3 = OpConstant %int 2", |
| "%and_1_2 = OpConstant %int 0", |
| "%or_1_2 = OpConstant %int 3", |
| "%xor_3_null = OpConstant %int 3", |
| |
| "%unsigned_31 = OpConstant %uint 31", |
| "%unsigned_left_shift_max = OpConstant %uint 2147483648", |
| "%unsigned_right_shift_logical = OpConstant %uint 1", |
| "%signed_right_shift_arithmetic = OpConstant %int -1", |
| "%left_shift_null_31 = OpConstant %uint 0", |
| "%right_shift_31_null = OpConstant %uint 31", |
| }, |
| }, |
| // Skip folding if any operands have undetermined value. |
| { |
| // original |
| { |
| "%spec_int = OpSpecConstant %int 1", |
| "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int", |
| }, |
| // expected |
| { |
| "%spec_int = OpSpecConstant %int 1", |
| "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int", |
| }, |
| }, |
| // clang-format on |
| }))); |
| |
| // Tests about arithmetic operations for vector int and uint types. |
| INSTANTIATE_TEST_SUITE_P( |
| VectorArithmetic, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // vector integer negate |
| { |
| // original |
| { |
| "%v2int_minus_1 = OpSpecConstantOp %v2int SNegate %signed_one_vec", |
| "%v2int_minus_2 = OpSpecConstantOp %v2int SNegate %signed_two_vec", |
| "%v2int_neg_null = OpSpecConstantOp %v2int SNegate %signed_null_vec", |
| }, |
| // expected |
| { |
| "%int_n1 = OpConstant %int -1", |
| "%int_n1_0 = OpConstant %int -1", |
| "%v2int_minus_1 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", |
| "%int_n2 = OpConstant %int -2", |
| "%int_n2_0 = OpConstant %int -2", |
| "%v2int_minus_2 = OpConstantComposite %v2int %int_n2 %int_n2", |
| "%int_0 = OpConstant %int 0", |
| "%int_0_0 = OpConstant %int 0", |
| "%v2int_neg_null = OpConstantComposite %v2int %signed_zero %signed_zero", |
| }, |
| }, |
| // vector integer (including null vetors) add, sub, div, mul |
| { |
| // original |
| { |
| "%spec_v2int_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %signed_two_vec", |
| "%spec_v2int_isub = OpSpecConstantOp %v2int ISub %signed_one_vec %spec_v2int_iadd", |
| "%spec_v2int_sdiv = OpSpecConstantOp %v2int SDiv %spec_v2int_isub %signed_two_vec", |
| "%spec_v2int_imul = OpSpecConstantOp %v2int IMul %spec_v2int_sdiv %signed_three_vec", |
| "%spec_v2int_iadd_null = OpSpecConstantOp %v2int IAdd %spec_v2int_imul %signed_null_vec", |
| |
| "%spec_v2uint_iadd = OpSpecConstantOp %v2uint IAdd %unsigned_three_vec %unsigned_two_vec", |
| "%spec_v2uint_isub = OpSpecConstantOp %v2uint ISub %unsigned_one_vec %spec_v2uint_iadd", |
| "%spec_v2uint_udiv = OpSpecConstantOp %v2uint UDiv %spec_v2uint_isub %unsigned_three_vec", |
| "%spec_v2uint_imul = OpSpecConstantOp %v2uint IMul %spec_v2uint_udiv %unsigned_two_vec", |
| "%spec_v2uint_isub_null = OpSpecConstantOp %v2uint ISub %spec_v2uint_imul %signed_null_vec", |
| }, |
| // expected |
| { |
| "%int_5 = OpConstant %int 5", |
| "%int_5_0 = OpConstant %int 5", |
| "%spec_v2int_iadd = OpConstantComposite %v2int %int_5 %int_5", |
| "%int_n4 = OpConstant %int -4", |
| "%int_n4_0 = OpConstant %int -4", |
| "%spec_v2int_isub = OpConstantComposite %v2int %int_n4 %int_n4", |
| "%int_n2 = OpConstant %int -2", |
| "%int_n2_0 = OpConstant %int -2", |
| "%spec_v2int_sdiv = OpConstantComposite %v2int %int_n2 %int_n2", |
| "%int_n6 = OpConstant %int -6", |
| "%int_n6_0 = OpConstant %int -6", |
| "%spec_v2int_imul = OpConstantComposite %v2int %int_n6 %int_n6", |
| "%int_n6_1 = OpConstant %int -6", |
| "%int_n6_2 = OpConstant %int -6", |
| "%spec_v2int_iadd_null = OpConstantComposite %v2int %int_n6 %int_n6", |
| |
| "%uint_5 = OpConstant %uint 5", |
| "%uint_5_0 = OpConstant %uint 5", |
| "%spec_v2uint_iadd = OpConstantComposite %v2uint %uint_5 %uint_5", |
| "%uint_4294967292 = OpConstant %uint 4294967292", |
| "%uint_4294967292_0 = OpConstant %uint 4294967292", |
| "%spec_v2uint_isub = OpConstantComposite %v2uint %uint_4294967292 %uint_4294967292", |
| "%uint_1431655764 = OpConstant %uint 1431655764", |
| "%uint_1431655764_0 = OpConstant %uint 1431655764", |
| "%spec_v2uint_udiv = OpConstantComposite %v2uint %uint_1431655764 %uint_1431655764", |
| "%uint_2863311528 = OpConstant %uint 2863311528", |
| "%uint_2863311528_0 = OpConstant %uint 2863311528", |
| "%spec_v2uint_imul = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528", |
| "%uint_2863311528_1 = OpConstant %uint 2863311528", |
| "%uint_2863311528_2 = OpConstant %uint 2863311528", |
| "%spec_v2uint_isub_null = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528", |
| }, |
| }, |
| // vector integer rem, mod |
| { |
| // original |
| { |
| // common constants |
| "%int_7 = OpConstant %int 7", |
| "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7", |
| "%uint_7 = OpConstant %uint 7", |
| "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7", |
| "%int_minus_7 = OpConstant %int -7", |
| "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7", |
| "%int_minus_3 = OpConstant %int -3", |
| "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3", |
| |
| // srem |
| "%7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_7 %signed_three_vec", |
| "%minus_7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %signed_three_vec", |
| "%7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_7 %v2int_minus_3", |
| "%minus_7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %v2int_minus_3", |
| // smod |
| "%7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_7 %signed_three_vec", |
| "%minus_7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %signed_three_vec", |
| "%7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_7 %v2int_minus_3", |
| "%minus_7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %v2int_minus_3", |
| // umod |
| "%7_umod_3 = OpSpecConstantOp %v2uint UMod %v2uint_7 %unsigned_three_vec", |
| }, |
| // expected |
| { |
| // common constants |
| "%int_7 = OpConstant %int 7", |
| "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7", |
| "%uint_7 = OpConstant %uint 7", |
| "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7", |
| "%int_minus_7 = OpConstant %int -7", |
| "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7", |
| "%int_minus_3 = OpConstant %int -3", |
| "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3", |
| |
| // srem |
| "%int_1 = OpConstant %int 1", |
| "%int_1_0 = OpConstant %int 1", |
| "%7_srem_3 = OpConstantComposite %v2int %signed_one %signed_one", |
| "%int_n1 = OpConstant %int -1", |
| "%int_n1_0 = OpConstant %int -1", |
| "%minus_7_srem_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", |
| "%int_1_1 = OpConstant %int 1", |
| "%int_1_2 = OpConstant %int 1", |
| "%7_srem_minus_3 = OpConstantComposite %v2int %signed_one %signed_one", |
| "%int_n1_1 = OpConstant %int -1", |
| "%int_n1_2 = OpConstant %int -1", |
| "%minus_7_srem_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", |
| // smod |
| "%int_1_3 = OpConstant %int 1", |
| "%int_1_4 = OpConstant %int 1", |
| "%7_smod_3 = OpConstantComposite %v2int %signed_one %signed_one", |
| "%int_2 = OpConstant %int 2", |
| "%int_2_0 = OpConstant %int 2", |
| "%minus_7_smod_3 = OpConstantComposite %v2int %signed_two %signed_two", |
| "%int_n2 = OpConstant %int -2", |
| "%int_n2_0 = OpConstant %int -2", |
| "%7_smod_minus_3 = OpConstantComposite %v2int %int_n2 %int_n2", |
| "%int_n1_3 = OpConstant %int -1", |
| "%int_n1_4 = OpConstant %int -1", |
| "%minus_7_smod_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", |
| // umod |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_1_0 = OpConstant %uint 1", |
| "%7_umod_3 = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| }, |
| }, |
| // vector integer bitwise, shift |
| { |
| // original |
| { |
| "%xor_1_3 = OpSpecConstantOp %v2int BitwiseXor %signed_one_vec %signed_three_vec", |
| "%and_1_2 = OpSpecConstantOp %v2int BitwiseAnd %signed_one_vec %xor_1_3", |
| "%or_1_2 = OpSpecConstantOp %v2int BitwiseOr %signed_one_vec %xor_1_3", |
| |
| "%unsigned_31 = OpConstant %uint 31", |
| "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31", |
| "%unsigned_left_shift_max = OpSpecConstantOp %v2uint ShiftLeftLogical %unsigned_one_vec %v2unsigned_31", |
| "%unsigned_right_shift_logical = OpSpecConstantOp %v2uint ShiftRightLogical %unsigned_left_shift_max %v2unsigned_31", |
| "%signed_right_shift_arithmetic = OpSpecConstantOp %v2int ShiftRightArithmetic %unsigned_left_shift_max %v2unsigned_31", |
| }, |
| // expected |
| { |
| "%int_2 = OpConstant %int 2", |
| "%int_2_0 = OpConstant %int 2", |
| "%xor_1_3 = OpConstantComposite %v2int %signed_two %signed_two", |
| "%int_0 = OpConstant %int 0", |
| "%int_0_0 = OpConstant %int 0", |
| "%and_1_2 = OpConstantComposite %v2int %signed_zero %signed_zero", |
| "%int_3 = OpConstant %int 3", |
| "%int_3_0 = OpConstant %int 3", |
| "%or_1_2 = OpConstantComposite %v2int %signed_three %signed_three", |
| |
| "%unsigned_31 = OpConstant %uint 31", |
| "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31", |
| "%uint_2147483648 = OpConstant %uint 2147483648", |
| "%uint_2147483648_0 = OpConstant %uint 2147483648", |
| "%unsigned_left_shift_max = OpConstantComposite %v2uint %uint_2147483648 %uint_2147483648", |
| "%uint_1 = OpConstant %uint 1", |
| "%uint_1_0 = OpConstant %uint 1", |
| "%unsigned_right_shift_logical = OpConstantComposite %v2uint %unsigned_one %unsigned_one", |
| "%int_n1 = OpConstant %int -1", |
| "%int_n1_0 = OpConstant %int -1", |
| "%signed_right_shift_arithmetic = OpConstantComposite %v2int %signed_minus_one %signed_minus_one", |
| }, |
| }, |
| // Skip folding if any vector operands or components of the operands |
| // have undetermined value. |
| { |
| // original |
| { |
| "%spec_int = OpSpecConstant %int 1", |
| "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int", |
| "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec", |
| }, |
| // expected |
| { |
| "%spec_int = OpSpecConstant %int 1", |
| "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int", |
| "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec", |
| }, |
| }, |
| // Skip folding if any vector operands are defined by OpUndef |
| { |
| // original |
| { |
| "%undef = OpUndef %int", |
| "%vec = OpConstantComposite %v2int %undef %signed_one", |
| "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec", |
| }, |
| // expected |
| { |
| "%undef = OpUndef %int", |
| "%vec = OpConstantComposite %v2int %undef %signed_one", |
| "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec", |
| }, |
| }, |
| // clang-format on |
| }))); |
| |
| // Tests for SpecConstantOp CompositeExtract instruction |
| INSTANTIATE_TEST_SUITE_P( |
| CompositeExtract, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // normal vector |
| { |
| // original |
| { |
| "%r = OpSpecConstantOp %int CompositeExtract %signed_three_vec 0", |
| "%x = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 0", |
| "%y = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 1", |
| "%z = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 2", |
| "%w = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 3", |
| }, |
| // expected |
| { |
| "%r = OpConstant %int 3", |
| "%x = OpConstant %int 0", |
| "%y = OpConstant %int 1", |
| "%z = OpConstant %int 2", |
| "%w = OpConstant %int 3", |
| }, |
| }, |
| // null vector |
| { |
| // original |
| { |
| "%x = OpSpecConstantOp %int CompositeExtract %signed_null_vec 0", |
| "%y = OpSpecConstantOp %int CompositeExtract %signed_null_vec 1", |
| "%null_v4int = OpConstantNull %v4int", |
| "%z = OpSpecConstantOp %int CompositeExtract %signed_null_vec 2", |
| }, |
| // expected |
| { |
| "%x = OpConstantNull %int", |
| "%y = OpConstantNull %int", |
| "%null_v4int = OpConstantNull %v4int", |
| "%z = OpConstantNull %int", |
| } |
| }, |
| // normal flat struct |
| { |
| // original |
| { |
| "%float_1 = OpConstant %float 1", |
| "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", |
| "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat_1 0", |
| "%extract_int = OpSpecConstantOp %int CompositeExtract %flat_1 1", |
| "%extract_float_1 = OpSpecConstantOp %float CompositeExtract %flat_1 2", |
| // foldable composite constants built with OpSpecConstantComposite |
| // should also be processed. |
| "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1", |
| "%extract_float_2 = OpSpecConstantOp %float CompositeExtract %flat_2 2", |
| }, |
| // expected |
| { |
| "%float_1 = OpConstant %float 1", |
| "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", |
| "%extract_bool = OpConstantTrue %bool", |
| "%extract_int = OpConstantNull %int", |
| "%extract_float_1 = OpConstant %float 1", |
| "%flat_2 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1", |
| "%extract_float_2 = OpConstant %float 1", |
| }, |
| }, |
| // null flat struct |
| { |
| // original |
| { |
| "%flat = OpConstantNull %flat_struct", |
| "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat 0", |
| "%extract_int = OpSpecConstantOp %int CompositeExtract %flat 1", |
| "%extract_float = OpSpecConstantOp %float CompositeExtract %flat 2", |
| }, |
| // expected |
| { |
| "%flat = OpConstantNull %flat_struct", |
| "%extract_bool = OpConstantNull %bool", |
| "%extract_int = OpConstantNull %int", |
| "%extract_float = OpConstantNull %float", |
| }, |
| }, |
| // normal nested struct |
| { |
| // original |
| { |
| "%float_1 = OpConstant %float 1", |
| "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", |
| "%outer = OpConstantComposite %outer_struct %inner %signed_one", |
| "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0", |
| "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1", |
| "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2", |
| }, |
| // expected |
| { |
| "%float_1 = OpConstant %float 1", |
| "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", |
| "%outer = OpConstantComposite %outer_struct %inner %signed_one", |
| "%extract_inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1", |
| "%extract_int = OpConstant %int 1", |
| "%extract_inner_float = OpConstant %float 1", |
| }, |
| }, |
| // null nested struct |
| { |
| // original |
| { |
| "%outer = OpConstantNull %outer_struct", |
| "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0", |
| "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1", |
| "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2", |
| }, |
| // expected |
| { |
| "%outer = OpConstantNull %outer_struct", |
| "%extract_inner = OpConstantNull %inner_struct", |
| "%extract_int = OpConstantNull %int", |
| "%extract_inner_float = OpConstantNull %float", |
| }, |
| }, |
| // skip folding if the any composite constant's value are not fully |
| // determined, even though the extracting target might have |
| // determined value. |
| { |
| // original |
| { |
| "%float_1 = OpConstant %float 1", |
| "%spec_float = OpSpecConstant %float 1", |
| "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", |
| "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one", |
| "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1", |
| "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1", |
| "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1", |
| "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1", |
| }, |
| // expected |
| { |
| "%float_1 = OpConstant %float 1", |
| "%spec_float = OpSpecConstant %float 1", |
| "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float", |
| "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one", |
| "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1", |
| "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1", |
| "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1", |
| "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1", |
| }, |
| }, |
| // skip if the composite constant depends on the result of OpUndef, |
| // even though the composite extract target element does not depends |
| // on the OpUndef. |
| { |
| // original |
| { |
| "%undef = OpUndef %float", |
| "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", |
| "%outer = OpConstantComposite %outer_struct %inner %signed_one", |
| "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1", |
| "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1", |
| }, |
| // expected |
| { |
| "%undef = OpUndef %float", |
| "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef", |
| "%outer = OpConstantComposite %outer_struct %inner %signed_one", |
| "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1", |
| "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1", |
| }, |
| }, |
| // TODO(qining): Add tests for Array and other composite type constants. |
| // clang-format on |
| }))); |
| |
| // Tests the swizzle operations for spec const vectors. |
| INSTANTIATE_TEST_SUITE_P( |
| VectorShuffle, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // normal vector |
| { |
| // original |
| { |
| "%xy = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 1", |
| "%yz = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 2", |
| "%zw = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 3", |
| "%wx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 3 0", |
| "%xx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 0", |
| "%yyy = OpSpecConstantOp %v3int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 1 1", |
| "%wwww = OpSpecConstantOp %v4int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 2 2 2", |
| }, |
| // expected |
| { |
| "%xy = OpConstantComposite %v2int %signed_zero %signed_one", |
| "%yz = OpConstantComposite %v2int %signed_one %signed_two", |
| "%zw = OpConstantComposite %v2int %signed_two %signed_three", |
| "%wx = OpConstantComposite %v2int %signed_three %signed_zero", |
| "%xx = OpConstantComposite %v2int %signed_zero %signed_zero", |
| "%yyy = OpConstantComposite %v3int %signed_one %signed_one %signed_one", |
| "%wwww = OpConstantComposite %v4int %signed_two %signed_two %signed_two %signed_two", |
| }, |
| }, |
| // null vector |
| { |
| // original |
| { |
| "%a = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 0 1", |
| "%b = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 2 3", |
| "%c = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %signed_null_vec 3 4", |
| "%d = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %signed_null_vec 1 2", |
| }, |
| // expected |
| { |
| "%a = OpConstantComposite %v2int %signed_null %signed_null", |
| "%b = OpConstantComposite %v2int %signed_zero %signed_one", |
| "%c = OpConstantComposite %v2int %signed_three %signed_null", |
| "%d = OpConstantComposite %v2int %signed_null %signed_null", |
| } |
| }, |
| // skip if any of the components of the vector operands do not have |
| // determined value, even though the result vector might not be |
| // built with those undermined values. |
| { |
| // original |
| { |
| "%spec_int = OpSpecConstant %int 1", |
| "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int", |
| "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1", |
| "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4", |
| }, |
| // expected |
| { |
| "%spec_int = OpSpecConstant %int 1", |
| "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int", |
| "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1", |
| "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4", |
| }, |
| }, |
| // Skip if any components of the two vector operands depend on |
| // the result of OpUndef. Even though the selected components do |
| // not depend on the OpUndef result. |
| { |
| // original |
| { |
| "%undef = OpUndef %int", |
| "%vec_1 = OpConstantComposite %v2int %undef %signed_one", |
| "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3", |
| "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3", |
| "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3", |
| }, |
| // expected |
| { |
| "%undef = OpUndef %int", |
| "%vec_1 = OpConstantComposite %v2int %undef %signed_one", |
| "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3", |
| "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3", |
| "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3", |
| }, |
| }, |
| // clang-format on |
| }))); |
| |
| // Test with long use-def chain. |
| INSTANTIATE_TEST_SUITE_P( |
| LongDefUseChain, FoldSpecConstantOpAndCompositePassTest, |
| ::testing::ValuesIn(std::vector< |
| FoldSpecConstantOpAndCompositePassTestCase>({ |
| // clang-format off |
| // Long Def-Use chain with binary operations. |
| { |
| // original |
| { |
| "%array_size = OpConstant %int 4", |
| "%type_arr_int_4 = OpTypeArray %int %array_size", |
| "%spec_int_0 = OpConstant %int 100", |
| "%spec_int_1 = OpConstant %int 1", |
| "%spec_int_2 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_1", |
| "%spec_int_3 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_2", |
| "%spec_int_4 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_3", |
| "%spec_int_5 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_4", |
| "%spec_int_6 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_5", |
| "%spec_int_7 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_6", |
| "%spec_int_8 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_7", |
| "%spec_int_9 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_8", |
| "%spec_int_10 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_9", |
| "%spec_int_11 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_10", |
| "%spec_int_12 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_11", |
| "%spec_int_13 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_12", |
| "%spec_int_14 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_13", |
| "%spec_int_15 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_14", |
| "%spec_int_16 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_15", |
| "%spec_int_17 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_16", |
| "%spec_int_18 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_17", |
| "%spec_int_19 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_18", |
| "%spec_int_20 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_19", |
| "%used_vec_a = OpSpecConstantComposite %v2int %spec_int_18 %spec_int_19", |
| "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a", |
| "%spec_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0", |
| "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21", |
| // Spec constants whose values can not be fully resolved should |
| // not be processed. |
| "%spec_int_22 = OpSpecConstant %int 123", |
| "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one", |
| }, |
| // expected |
| { |
| "%array_size = OpConstant %int 4", |
| "%type_arr_int_4 = OpTypeArray %int %array_size", |
| "%spec_int_0 = OpConstant %int 100", |
| "%spec_int_1 = OpConstant %int 1", |
| "%spec_int_2 = OpConstant %int 101", |
| "%spec_int_3 = OpConstant %int -1", |
| "%spec_int_4 = OpConstant %int 99", |
| "%spec_int_5 = OpConstant %int 1", |
| "%spec_int_6 = OpConstant %int 101", |
| "%spec_int_7 = OpConstant %int -1", |
| "%spec_int_8 = OpConstant %int 99", |
| "%spec_int_9 = OpConstant %int 1", |
| "%spec_int_10 = OpConstant %int 101", |
| "%spec_int_11 = OpConstant %int -1", |
| "%spec_int_12 = OpConstant %int 99", |
| "%spec_int_13 = OpConstant %int 1", |
| "%spec_int_14 = OpConstant %int 101", |
| "%spec_int_15 = OpConstant %int -1", |
| "%spec_int_16 = OpConstant %int 101", |
| "%spec_int_17 = OpConstant %int 201", |
| "%spec_int_18 = OpConstant %int -101", |
| "%spec_int_19 = OpConstant %int -1", |
| "%spec_int_20 = OpConstant %int 101", |
| "%used_vec_a = OpConstantComposite %v2int %spec_int_18 %spec_int_19", |
| "%int_10201 = OpConstant %int 10201", |
| "%int_1 = OpConstant %int 1", |
| "%used_vec_b = OpConstantComposite %v2int %int_10201 %signed_one", |
| "%spec_int_21 = OpConstant %int 10201", |
| "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21", |
| "%spec_int_22 = OpSpecConstant %int 123", |
| "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one", |
| }, |
| }, |
| // Long Def-Use chain with swizzle |
| }))); |
| |
| } // namespace |
| } // namespace opt |
| } // namespace spvtools |