1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <memory> 16fd4e5da5Sopenharmony_ci#include <vector> 17fd4e5da5Sopenharmony_ci 18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 19fd4e5da5Sopenharmony_ci#include "spirv-tools/libspirv.hpp" 20fd4e5da5Sopenharmony_ci#include "spirv-tools/optimizer.hpp" 21fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 22fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 23fd4e5da5Sopenharmony_ci 24fd4e5da5Sopenharmony_cinamespace spvtools { 25fd4e5da5Sopenharmony_cinamespace opt { 26fd4e5da5Sopenharmony_cinamespace { 27fd4e5da5Sopenharmony_ci 28fd4e5da5Sopenharmony_ciusing CompactIdsTest = PassTest<::testing::Test>; 29fd4e5da5Sopenharmony_ci 30fd4e5da5Sopenharmony_ciTEST_F(CompactIdsTest, PassOff) { 31fd4e5da5Sopenharmony_ci const std::string before = 32fd4e5da5Sopenharmony_ci R"(OpCapability Addresses 33fd4e5da5Sopenharmony_ciOpCapability Kernel 34fd4e5da5Sopenharmony_ciOpCapability GenericPointer 35fd4e5da5Sopenharmony_ciOpCapability Linkage 36fd4e5da5Sopenharmony_ciOpMemoryModel Physical32 OpenCL 37fd4e5da5Sopenharmony_ci%99 = OpTypeInt 32 0 38fd4e5da5Sopenharmony_ci%10 = OpTypeVector %99 2 39fd4e5da5Sopenharmony_ci%20 = OpConstant %99 2 40fd4e5da5Sopenharmony_ci%30 = OpTypeArray %99 %20 41fd4e5da5Sopenharmony_ci)"; 42fd4e5da5Sopenharmony_ci 43fd4e5da5Sopenharmony_ci const std::string after = before; 44fd4e5da5Sopenharmony_ci 45fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 46fd4e5da5Sopenharmony_ci SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); 47fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<NullPass>(before, after, false, false); 48fd4e5da5Sopenharmony_ci} 49fd4e5da5Sopenharmony_ci 50fd4e5da5Sopenharmony_ciTEST_F(CompactIdsTest, PassOn) { 51fd4e5da5Sopenharmony_ci const std::string before = 52fd4e5da5Sopenharmony_ci R"(OpCapability Addresses 53fd4e5da5Sopenharmony_ciOpCapability Kernel 54fd4e5da5Sopenharmony_ciOpCapability GenericPointer 55fd4e5da5Sopenharmony_ciOpCapability Linkage 56fd4e5da5Sopenharmony_ciOpMemoryModel Physical32 OpenCL 57fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %3 "simple_kernel" 58fd4e5da5Sopenharmony_ci%99 = OpTypeInt 32 0 59fd4e5da5Sopenharmony_ci%10 = OpTypeVector %99 2 60fd4e5da5Sopenharmony_ci%20 = OpConstant %99 2 61fd4e5da5Sopenharmony_ci%30 = OpTypeArray %99 %20 62fd4e5da5Sopenharmony_ci%40 = OpTypeVoid 63fd4e5da5Sopenharmony_ci%50 = OpTypeFunction %40 64fd4e5da5Sopenharmony_ci %3 = OpFunction %40 None %50 65fd4e5da5Sopenharmony_ci%70 = OpLabel 66fd4e5da5Sopenharmony_ciOpReturn 67fd4e5da5Sopenharmony_ciOpFunctionEnd 68fd4e5da5Sopenharmony_ci)"; 69fd4e5da5Sopenharmony_ci 70fd4e5da5Sopenharmony_ci const std::string after = 71fd4e5da5Sopenharmony_ci R"(OpCapability Addresses 72fd4e5da5Sopenharmony_ciOpCapability Kernel 73fd4e5da5Sopenharmony_ciOpCapability GenericPointer 74fd4e5da5Sopenharmony_ciOpCapability Linkage 75fd4e5da5Sopenharmony_ciOpMemoryModel Physical32 OpenCL 76fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %1 "simple_kernel" 77fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0 78fd4e5da5Sopenharmony_ci%3 = OpTypeVector %2 2 79fd4e5da5Sopenharmony_ci%4 = OpConstant %2 2 80fd4e5da5Sopenharmony_ci%5 = OpTypeArray %2 %4 81fd4e5da5Sopenharmony_ci%6 = OpTypeVoid 82fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %6 83fd4e5da5Sopenharmony_ci%1 = OpFunction %6 None %7 84fd4e5da5Sopenharmony_ci%8 = OpLabel 85fd4e5da5Sopenharmony_ciOpReturn 86fd4e5da5Sopenharmony_ciOpFunctionEnd 87fd4e5da5Sopenharmony_ci)"; 88fd4e5da5Sopenharmony_ci 89fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 90fd4e5da5Sopenharmony_ci SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); 91fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<CompactIdsPass>(before, after, false, false); 92fd4e5da5Sopenharmony_ci} 93fd4e5da5Sopenharmony_ci 94fd4e5da5Sopenharmony_ciTEST_F(CompactIdsTest, DebugScope) { 95fd4e5da5Sopenharmony_ci const std::string text = 96fd4e5da5Sopenharmony_ci R"(OpCapability Addresses 97fd4e5da5Sopenharmony_ciOpCapability Kernel 98fd4e5da5Sopenharmony_ciOpCapability GenericPointer 99fd4e5da5Sopenharmony_ciOpCapability Linkage 100fd4e5da5Sopenharmony_ci%5 = OpExtInstImport "OpenCL.DebugInfo.100" 101fd4e5da5Sopenharmony_ciOpMemoryModel Physical32 OpenCL 102fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %3 "simple_kernel" 103fd4e5da5Sopenharmony_ci%2 = OpString "test" 104fd4e5da5Sopenharmony_ci%99 = OpTypeInt 32 0 105fd4e5da5Sopenharmony_ci%10 = OpTypeVector %99 2 106fd4e5da5Sopenharmony_ci%20 = OpConstant %99 2 107fd4e5da5Sopenharmony_ci%30 = OpTypeArray %99 %20 108fd4e5da5Sopenharmony_ci%40 = OpTypeVoid 109fd4e5da5Sopenharmony_ci%50 = OpTypeFunction %40 110fd4e5da5Sopenharmony_ci%11 = OpExtInst %40 %5 DebugSource %2 111fd4e5da5Sopenharmony_ci%12 = OpExtInst %40 %5 DebugCompilationUnit 1 4 %11 HLSL 112fd4e5da5Sopenharmony_ci%13 = OpExtInst %40 %5 DebugTypeFunction FlagIsProtected|FlagIsPrivate %40 113fd4e5da5Sopenharmony_ci 114fd4e5da5Sopenharmony_ci; CHECK: [[fn:%\w+]] = OpExtInst {{%\w+}} {{%\w+}} DebugFunction 115fd4e5da5Sopenharmony_ci%14 = OpExtInst %40 %5 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %3 116fd4e5da5Sopenharmony_ci %3 = OpFunction %40 None %50 117fd4e5da5Sopenharmony_ci%70 = OpLabel 118fd4e5da5Sopenharmony_ci 119fd4e5da5Sopenharmony_ci; CHECK: DebugScope [[fn]] 120fd4e5da5Sopenharmony_ci%19 = OpExtInst %40 %5 DebugScope %14 121fd4e5da5Sopenharmony_ciOpReturn 122fd4e5da5Sopenharmony_ciOpFunctionEnd 123fd4e5da5Sopenharmony_ci)"; 124fd4e5da5Sopenharmony_ci 125fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 126fd4e5da5Sopenharmony_ci SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); 127fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CompactIdsPass>(text, true); 128fd4e5da5Sopenharmony_ci} 129fd4e5da5Sopenharmony_ci 130fd4e5da5Sopenharmony_ciTEST(CompactIds, InstructionResultIsUpdated) { 131fd4e5da5Sopenharmony_ci // For https://github.com/KhronosGroup/SPIRV-Tools/issues/827 132fd4e5da5Sopenharmony_ci // In that bug, the compact Ids pass was directly updating the result Id 133fd4e5da5Sopenharmony_ci // word for an OpFunction instruction, but not updating the cached 134fd4e5da5Sopenharmony_ci // result_id_ in that Instruction object. 135fd4e5da5Sopenharmony_ci // 136fd4e5da5Sopenharmony_ci // This test is a bit cheesy. We don't expose internal interfaces enough 137fd4e5da5Sopenharmony_ci // to see the inconsistency. So reproduce the original scenario, with 138fd4e5da5Sopenharmony_ci // compact ids followed by a pass that trips up on the inconsistency. 139fd4e5da5Sopenharmony_ci 140fd4e5da5Sopenharmony_ci const std::string input(R"(OpCapability Shader 141fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 142fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %100 "main" 143fd4e5da5Sopenharmony_ci%200 = OpTypeVoid 144fd4e5da5Sopenharmony_ci%300 = OpTypeFunction %200 145fd4e5da5Sopenharmony_ci%100 = OpFunction %200 None %300 146fd4e5da5Sopenharmony_ci%400 = OpLabel 147fd4e5da5Sopenharmony_ciOpReturn 148fd4e5da5Sopenharmony_ciOpFunctionEnd 149fd4e5da5Sopenharmony_ci)"); 150fd4e5da5Sopenharmony_ci 151fd4e5da5Sopenharmony_ci std::vector<uint32_t> binary; 152fd4e5da5Sopenharmony_ci const spv_target_env env = SPV_ENV_UNIVERSAL_1_0; 153fd4e5da5Sopenharmony_ci spvtools::SpirvTools tools(env); 154fd4e5da5Sopenharmony_ci auto assembled = tools.Assemble( 155fd4e5da5Sopenharmony_ci input, &binary, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 156fd4e5da5Sopenharmony_ci EXPECT_TRUE(assembled); 157fd4e5da5Sopenharmony_ci 158fd4e5da5Sopenharmony_ci spvtools::Optimizer optimizer(env); 159fd4e5da5Sopenharmony_ci optimizer.RegisterPass(CreateCompactIdsPass()); 160fd4e5da5Sopenharmony_ci // The exhaustive inliner will use the result_id 161fd4e5da5Sopenharmony_ci optimizer.RegisterPass(CreateInlineExhaustivePass()); 162fd4e5da5Sopenharmony_ci 163fd4e5da5Sopenharmony_ci // This should not crash! 164fd4e5da5Sopenharmony_ci optimizer.Run(binary.data(), binary.size(), &binary); 165fd4e5da5Sopenharmony_ci 166fd4e5da5Sopenharmony_ci std::string disassembly; 167fd4e5da5Sopenharmony_ci tools.Disassemble(binary, &disassembly, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER); 168fd4e5da5Sopenharmony_ci 169fd4e5da5Sopenharmony_ci const std::string expected(R"(OpCapability Shader 170fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 171fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %1 "main" 172fd4e5da5Sopenharmony_ci%2 = OpTypeVoid 173fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 174fd4e5da5Sopenharmony_ci%1 = OpFunction %2 None %3 175fd4e5da5Sopenharmony_ci%4 = OpLabel 176fd4e5da5Sopenharmony_ciOpReturn 177fd4e5da5Sopenharmony_ciOpFunctionEnd 178fd4e5da5Sopenharmony_ci)"); 179fd4e5da5Sopenharmony_ci 180fd4e5da5Sopenharmony_ci EXPECT_THAT(disassembly, ::testing::Eq(expected)); 181fd4e5da5Sopenharmony_ci} 182fd4e5da5Sopenharmony_ci 183fd4e5da5Sopenharmony_ciTEST(CompactIds, HeaderIsUpdated) { 184fd4e5da5Sopenharmony_ci const std::string input(R"(OpCapability Shader 185fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 186fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %100 "main" 187fd4e5da5Sopenharmony_ci%200 = OpTypeVoid 188fd4e5da5Sopenharmony_ci%300 = OpTypeFunction %200 189fd4e5da5Sopenharmony_ci%100 = OpFunction %200 None %300 190fd4e5da5Sopenharmony_ci%400 = OpLabel 191fd4e5da5Sopenharmony_ciOpReturn 192fd4e5da5Sopenharmony_ciOpFunctionEnd 193fd4e5da5Sopenharmony_ci)"); 194fd4e5da5Sopenharmony_ci 195fd4e5da5Sopenharmony_ci std::vector<uint32_t> binary; 196fd4e5da5Sopenharmony_ci const spv_target_env env = SPV_ENV_UNIVERSAL_1_0; 197fd4e5da5Sopenharmony_ci spvtools::SpirvTools tools(env); 198fd4e5da5Sopenharmony_ci auto assembled = tools.Assemble( 199fd4e5da5Sopenharmony_ci input, &binary, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 200fd4e5da5Sopenharmony_ci EXPECT_TRUE(assembled); 201fd4e5da5Sopenharmony_ci 202fd4e5da5Sopenharmony_ci spvtools::Optimizer optimizer(env); 203fd4e5da5Sopenharmony_ci optimizer.RegisterPass(CreateCompactIdsPass()); 204fd4e5da5Sopenharmony_ci // The exhaustive inliner will use the result_id 205fd4e5da5Sopenharmony_ci optimizer.RegisterPass(CreateInlineExhaustivePass()); 206fd4e5da5Sopenharmony_ci 207fd4e5da5Sopenharmony_ci // This should not crash! 208fd4e5da5Sopenharmony_ci optimizer.Run(binary.data(), binary.size(), &binary); 209fd4e5da5Sopenharmony_ci 210fd4e5da5Sopenharmony_ci std::string disassembly; 211fd4e5da5Sopenharmony_ci tools.Disassemble(binary, &disassembly, SPV_BINARY_TO_TEXT_OPTION_NONE); 212fd4e5da5Sopenharmony_ci 213fd4e5da5Sopenharmony_ci const std::string expected(R"(; SPIR-V 214fd4e5da5Sopenharmony_ci; Version: 1.0 215fd4e5da5Sopenharmony_ci; Generator: Khronos SPIR-V Tools Assembler; 0 216fd4e5da5Sopenharmony_ci; Bound: 5 217fd4e5da5Sopenharmony_ci; Schema: 0 218fd4e5da5Sopenharmony_ciOpCapability Shader 219fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 220fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %1 "main" 221fd4e5da5Sopenharmony_ci%2 = OpTypeVoid 222fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 223fd4e5da5Sopenharmony_ci%1 = OpFunction %2 None %3 224fd4e5da5Sopenharmony_ci%4 = OpLabel 225fd4e5da5Sopenharmony_ciOpReturn 226fd4e5da5Sopenharmony_ciOpFunctionEnd 227fd4e5da5Sopenharmony_ci)"); 228fd4e5da5Sopenharmony_ci 229fd4e5da5Sopenharmony_ci EXPECT_THAT(disassembly, ::testing::Eq(expected)); 230fd4e5da5Sopenharmony_ci} 231fd4e5da5Sopenharmony_ci 232fd4e5da5Sopenharmony_ci// Test context consistency check after invalidating 233fd4e5da5Sopenharmony_ci// CFG and others by compact IDs Pass. 234fd4e5da5Sopenharmony_ci// Uses a GLSL shader with named labels for variety 235fd4e5da5Sopenharmony_ciTEST(CompactIds, ConsistentCheck) { 236fd4e5da5Sopenharmony_ci const std::string input(R"(OpCapability Shader 237fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 238fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %in_var_A %out_var_SV_TARGET 239fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 240fd4e5da5Sopenharmony_ciOpSource HLSL 600 241fd4e5da5Sopenharmony_ciOpName %main "main" 242fd4e5da5Sopenharmony_ciOpName %in_var_A "in.var.A" 243fd4e5da5Sopenharmony_ciOpName %out_var_SV_TARGET "out.var.SV_TARGET" 244fd4e5da5Sopenharmony_ciOpDecorate %in_var_A Location 0 245fd4e5da5Sopenharmony_ciOpDecorate %out_var_SV_TARGET Location 0 246fd4e5da5Sopenharmony_ci%void = OpTypeVoid 247fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void 248fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 249fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4 250fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float 251fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float 252fd4e5da5Sopenharmony_ci%in_var_A = OpVariable %_ptr_Input_v4float Input 253fd4e5da5Sopenharmony_ci%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 254fd4e5da5Sopenharmony_ci%main = OpFunction %void None %3 255fd4e5da5Sopenharmony_ci%5 = OpLabel 256fd4e5da5Sopenharmony_ci%12 = OpLoad %v4float %in_var_A 257fd4e5da5Sopenharmony_ci%23 = OpVectorShuffle %v4float %12 %12 0 0 0 1 258fd4e5da5Sopenharmony_ciOpStore %out_var_SV_TARGET %23 259fd4e5da5Sopenharmony_ciOpReturn 260fd4e5da5Sopenharmony_ciOpFunctionEnd 261fd4e5da5Sopenharmony_ci)"); 262fd4e5da5Sopenharmony_ci 263fd4e5da5Sopenharmony_ci spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); 264fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 265fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input, 266fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 267fd4e5da5Sopenharmony_ci ASSERT_NE(context, nullptr); 268fd4e5da5Sopenharmony_ci 269fd4e5da5Sopenharmony_ci CompactIdsPass compact_id_pass; 270fd4e5da5Sopenharmony_ci context->BuildInvalidAnalyses(compact_id_pass.GetPreservedAnalyses()); 271fd4e5da5Sopenharmony_ci const auto status = compact_id_pass.Run(context.get()); 272fd4e5da5Sopenharmony_ci ASSERT_NE(status, Pass::Status::Failure); 273fd4e5da5Sopenharmony_ci EXPECT_TRUE(context->IsConsistent()); 274fd4e5da5Sopenharmony_ci 275fd4e5da5Sopenharmony_ci // Test output just in case 276fd4e5da5Sopenharmony_ci std::vector<uint32_t> binary; 277fd4e5da5Sopenharmony_ci context->module()->ToBinary(&binary, false); 278fd4e5da5Sopenharmony_ci std::string disassembly; 279fd4e5da5Sopenharmony_ci tools.Disassemble(binary, &disassembly, 280fd4e5da5Sopenharmony_ci SpirvTools::kDefaultDisassembleOption); 281fd4e5da5Sopenharmony_ci 282fd4e5da5Sopenharmony_ci const std::string expected(R"(OpCapability Shader 283fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 284fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %in_var_A %out_var_SV_TARGET 285fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 286fd4e5da5Sopenharmony_ciOpSource HLSL 600 287fd4e5da5Sopenharmony_ciOpName %main "main" 288fd4e5da5Sopenharmony_ciOpName %in_var_A "in.var.A" 289fd4e5da5Sopenharmony_ciOpName %out_var_SV_TARGET "out.var.SV_TARGET" 290fd4e5da5Sopenharmony_ciOpDecorate %in_var_A Location 0 291fd4e5da5Sopenharmony_ciOpDecorate %out_var_SV_TARGET Location 0 292fd4e5da5Sopenharmony_ci%void = OpTypeVoid 293fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void 294fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 295fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4 296fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float 297fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float 298fd4e5da5Sopenharmony_ci%in_var_A = OpVariable %_ptr_Input_v4float Input 299fd4e5da5Sopenharmony_ci%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 300fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5 301fd4e5da5Sopenharmony_ci%10 = OpLabel 302fd4e5da5Sopenharmony_ci%11 = OpLoad %v4float %in_var_A 303fd4e5da5Sopenharmony_ci%12 = OpVectorShuffle %v4float %11 %11 0 0 0 1 304fd4e5da5Sopenharmony_ciOpStore %out_var_SV_TARGET %12 305fd4e5da5Sopenharmony_ciOpReturn 306fd4e5da5Sopenharmony_ciOpFunctionEnd 307fd4e5da5Sopenharmony_ci)"); 308fd4e5da5Sopenharmony_ci 309fd4e5da5Sopenharmony_ci EXPECT_THAT(disassembly, ::testing::Eq(expected)); 310fd4e5da5Sopenharmony_ci} 311fd4e5da5Sopenharmony_ci 312fd4e5da5Sopenharmony_ciTEST(CompactIds, ResetIdBound) { 313fd4e5da5Sopenharmony_ci const std::string input(R"(OpCapability Shader 314fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 315fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %1 "main" 316fd4e5da5Sopenharmony_ciOpExecutionMode %1 OriginUpperLeft 317fd4e5da5Sopenharmony_ci%void = OpTypeVoid 318fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void 319fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %3 320fd4e5da5Sopenharmony_ci%4 = OpLabel 321fd4e5da5Sopenharmony_ciOpReturn 322fd4e5da5Sopenharmony_ciOpFunctionEnd 323fd4e5da5Sopenharmony_ci)"); 324fd4e5da5Sopenharmony_ci 325fd4e5da5Sopenharmony_ci spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); 326fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 327fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, input, 328fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 329fd4e5da5Sopenharmony_ci ASSERT_NE(context, nullptr); 330fd4e5da5Sopenharmony_ci 331fd4e5da5Sopenharmony_ci CompactIdsPass compact_id_pass; 332fd4e5da5Sopenharmony_ci context->module()->SetIdBound(20000); 333fd4e5da5Sopenharmony_ci const auto status = compact_id_pass.Run(context.get()); 334fd4e5da5Sopenharmony_ci EXPECT_EQ(status, Pass::Status::SuccessWithChange); 335fd4e5da5Sopenharmony_ci EXPECT_EQ(context->module()->id_bound(), 5); 336fd4e5da5Sopenharmony_ci 337fd4e5da5Sopenharmony_ci // Test output just in case 338fd4e5da5Sopenharmony_ci std::vector<uint32_t> binary; 339fd4e5da5Sopenharmony_ci context->module()->ToBinary(&binary, false); 340fd4e5da5Sopenharmony_ci std::string disassembly; 341fd4e5da5Sopenharmony_ci tools.Disassemble(binary, &disassembly, 342fd4e5da5Sopenharmony_ci SpirvTools::kDefaultDisassembleOption); 343fd4e5da5Sopenharmony_ci 344fd4e5da5Sopenharmony_ci EXPECT_THAT(disassembly, ::testing::Eq(input)); 345fd4e5da5Sopenharmony_ci} 346fd4e5da5Sopenharmony_ci 347fd4e5da5Sopenharmony_ci} // namespace 348fd4e5da5Sopenharmony_ci} // namespace opt 349fd4e5da5Sopenharmony_ci} // namespace spvtools 350