1// Copyright (c) 2019 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <string> 16 17#include "test/opt/assembly_builder.h" 18#include "test/opt/pass_fixture.h" 19#include "test/opt/pass_utils.h" 20 21namespace spvtools { 22namespace opt { 23namespace { 24 25using CodeSinkTest = PassTest<::testing::Test>; 26 27TEST_F(CodeSinkTest, MoveToNextBlock) { 28 const std::string text = R"( 29;CHECK: OpFunction 30;CHECK: OpLabel 31;CHECK: OpLabel 32;CHECK: [[ac:%\w+]] = OpAccessChain 33;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]] 34;CHECK: OpCopyObject %uint [[ld]] 35 OpCapability Shader 36 OpMemoryModel Logical GLSL450 37 OpEntryPoint GLCompute %1 "main" 38 %void = OpTypeVoid 39 %uint = OpTypeInt 32 0 40 %uint_0 = OpConstant %uint 0 41 %uint_4 = OpConstant %uint 4 42%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 43%_ptr_Uniform_uint = OpTypePointer Uniform %uint 44%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 45 %9 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 46 %10 = OpTypeFunction %void 47 %1 = OpFunction %void None %10 48 %11 = OpLabel 49 %12 = OpAccessChain %_ptr_Uniform_uint %9 %uint_0 50 %13 = OpLoad %uint %12 51 OpBranch %14 52 %14 = OpLabel 53 %15 = OpCopyObject %uint %13 54 OpReturn 55 OpFunctionEnd 56)"; 57 58 SinglePassRunAndMatch<CodeSinkingPass>(text, true); 59} 60 61TEST_F(CodeSinkTest, MovePastSelection) { 62 const std::string text = R"( 63;CHECK: OpFunction 64;CHECK: OpLabel 65;CHECK: OpSelectionMerge [[merge_bb:%\w+]] 66;CHECK: [[merge_bb]] = OpLabel 67;CHECK: [[ac:%\w+]] = OpAccessChain 68;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]] 69;CHECK: OpCopyObject %uint [[ld]] 70 OpCapability Shader 71 OpMemoryModel Logical GLSL450 72 OpEntryPoint GLCompute %1 "main" 73 %void = OpTypeVoid 74 %bool = OpTypeBool 75 %true = OpConstantTrue %bool 76 %uint = OpTypeInt 32 0 77 %uint_0 = OpConstant %uint 0 78 %uint_4 = OpConstant %uint 4 79%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 80%_ptr_Uniform_uint = OpTypePointer Uniform %uint 81%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 82 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 83 %12 = OpTypeFunction %void 84 %1 = OpFunction %void None %12 85 %13 = OpLabel 86 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 87 %15 = OpLoad %uint %14 88 OpSelectionMerge %16 None 89 OpBranchConditional %true %17 %16 90 %17 = OpLabel 91 OpBranch %16 92 %16 = OpLabel 93 %18 = OpCopyObject %uint %15 94 OpReturn 95 OpFunctionEnd 96)"; 97 98 SinglePassRunAndMatch<CodeSinkingPass>(text, true); 99} 100 101TEST_F(CodeSinkTest, MoveIntoSelection) { 102 const std::string text = R"( 103;CHECK: OpFunction 104;CHECK: OpLabel 105;CHECK: OpSelectionMerge [[merge_bb:%\w+]] 106;CHECK-NEXT: OpBranchConditional %true [[bb:%\w+]] [[merge_bb]] 107;CHECK: [[bb]] = OpLabel 108;CHECK-NEXT: [[ac:%\w+]] = OpAccessChain 109;CHECK-NEXT: [[ld:%\w+]] = OpLoad %uint [[ac]] 110;CHECK-NEXT: OpCopyObject %uint [[ld]] 111 OpCapability Shader 112 OpMemoryModel Logical GLSL450 113 OpEntryPoint GLCompute %1 "main" 114 %void = OpTypeVoid 115 %bool = OpTypeBool 116 %true = OpConstantTrue %bool 117 %uint = OpTypeInt 32 0 118 %uint_0 = OpConstant %uint 0 119 %uint_4 = OpConstant %uint 4 120%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 121%_ptr_Uniform_uint = OpTypePointer Uniform %uint 122%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 123 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 124 %12 = OpTypeFunction %void 125 %1 = OpFunction %void None %12 126 %13 = OpLabel 127 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 128 %15 = OpLoad %uint %14 129 OpSelectionMerge %16 None 130 OpBranchConditional %true %17 %16 131 %17 = OpLabel 132 %18 = OpCopyObject %uint %15 133 OpBranch %16 134 %16 = OpLabel 135 OpReturn 136 OpFunctionEnd 137)"; 138 139 SinglePassRunAndMatch<CodeSinkingPass>(text, true); 140} 141 142TEST_F(CodeSinkTest, LeaveBeforeSelection) { 143 const std::string text = R"( 144 OpCapability Shader 145 OpMemoryModel Logical GLSL450 146 OpEntryPoint GLCompute %1 "main" 147 %void = OpTypeVoid 148 %bool = OpTypeBool 149 %true = OpConstantTrue %bool 150 %uint = OpTypeInt 32 0 151 %uint_0 = OpConstant %uint 0 152 %uint_4 = OpConstant %uint 4 153%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 154%_ptr_Uniform_uint = OpTypePointer Uniform %uint 155%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 156 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 157 %12 = OpTypeFunction %void 158 %1 = OpFunction %void None %12 159 %13 = OpLabel 160 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 161 %15 = OpLoad %uint %14 162 OpSelectionMerge %16 None 163 OpBranchConditional %true %17 %20 164 %20 = OpLabel 165 OpBranch %16 166 %17 = OpLabel 167 %18 = OpCopyObject %uint %15 168 OpBranch %16 169 %16 = OpLabel 170 %19 = OpCopyObject %uint %15 171 OpReturn 172 OpFunctionEnd 173)"; 174 175 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 176 text, /* skip_nop = */ true, /* do_validation = */ true); 177 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 178} 179 180TEST_F(CodeSinkTest, LeaveAloneUseInSameBlock) { 181 const std::string text = R"( 182 OpCapability Shader 183 OpMemoryModel Logical GLSL450 184 OpEntryPoint GLCompute %1 "main" 185 %void = OpTypeVoid 186 %bool = OpTypeBool 187 %true = OpConstantTrue %bool 188 %uint = OpTypeInt 32 0 189 %uint_0 = OpConstant %uint 0 190 %uint_4 = OpConstant %uint 4 191%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 192%_ptr_Uniform_uint = OpTypePointer Uniform %uint 193%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 194 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 195 %12 = OpTypeFunction %void 196 %1 = OpFunction %void None %12 197 %13 = OpLabel 198 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 199 %15 = OpLoad %uint %14 200 %cond = OpIEqual %bool %15 %uint_0 201 OpSelectionMerge %16 None 202 OpBranchConditional %cond %17 %16 203 %17 = OpLabel 204 OpBranch %16 205 %16 = OpLabel 206 %19 = OpCopyObject %uint %15 207 OpReturn 208 OpFunctionEnd 209)"; 210 211 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 212 text, /* skip_nop = */ true, /* do_validation = */ true); 213 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 214} 215 216TEST_F(CodeSinkTest, DontMoveIntoLoop) { 217 const std::string text = R"( 218 OpCapability Shader 219 OpMemoryModel Logical GLSL450 220 OpEntryPoint GLCompute %1 "main" 221 %void = OpTypeVoid 222 %bool = OpTypeBool 223 %true = OpConstantTrue %bool 224 %uint = OpTypeInt 32 0 225 %uint_0 = OpConstant %uint 0 226 %uint_4 = OpConstant %uint 4 227%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 228%_ptr_Uniform_uint = OpTypePointer Uniform %uint 229%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 230 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 231 %12 = OpTypeFunction %void 232 %1 = OpFunction %void None %12 233 %13 = OpLabel 234 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 235 %15 = OpLoad %uint %14 236 OpBranch %17 237 %17 = OpLabel 238 OpLoopMerge %merge %cont None 239 OpBranch %cont 240 %cont = OpLabel 241 %cond = OpIEqual %bool %15 %uint_0 242 OpBranchConditional %cond %merge %17 243 %merge = OpLabel 244 OpReturn 245 OpFunctionEnd 246)"; 247 248 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 249 text, /* skip_nop = */ true, /* do_validation = */ true); 250 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 251} 252 253TEST_F(CodeSinkTest, DontMoveIntoLoop2) { 254 const std::string text = R"( 255 OpCapability Shader 256 OpMemoryModel Logical GLSL450 257 OpEntryPoint GLCompute %1 "main" 258 %void = OpTypeVoid 259 %bool = OpTypeBool 260 %true = OpConstantTrue %bool 261 %uint = OpTypeInt 32 0 262 %uint_0 = OpConstant %uint 0 263 %uint_4 = OpConstant %uint 4 264%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 265%_ptr_Uniform_uint = OpTypePointer Uniform %uint 266%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 267 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 268 %12 = OpTypeFunction %void 269 %1 = OpFunction %void None %12 270 %13 = OpLabel 271 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 272 %15 = OpLoad %uint %14 273 OpSelectionMerge %16 None 274 OpBranchConditional %true %17 %16 275 %17 = OpLabel 276 OpLoopMerge %merge %cont None 277 OpBranch %cont 278 %cont = OpLabel 279 %cond = OpIEqual %bool %15 %uint_0 280 OpBranchConditional %cond %merge %17 281 %merge = OpLabel 282 OpBranch %16 283 %16 = OpLabel 284 OpReturn 285 OpFunctionEnd 286)"; 287 288 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 289 text, /* skip_nop = */ true, /* do_validation = */ true); 290 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 291} 292 293TEST_F(CodeSinkTest, DontMoveSelectionUsedInBothSides) { 294 const std::string text = R"( 295 OpCapability Shader 296 OpMemoryModel Logical GLSL450 297 OpEntryPoint GLCompute %1 "main" 298 %void = OpTypeVoid 299 %bool = OpTypeBool 300 %true = OpConstantTrue %bool 301 %uint = OpTypeInt 32 0 302 %uint_0 = OpConstant %uint 0 303 %uint_4 = OpConstant %uint 4 304%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 305%_ptr_Uniform_uint = OpTypePointer Uniform %uint 306%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 307 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 308 %12 = OpTypeFunction %void 309 %1 = OpFunction %void None %12 310 %13 = OpLabel 311 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 312 %15 = OpLoad %uint %14 313 OpSelectionMerge %16 None 314 OpBranchConditional %true %17 %20 315 %20 = OpLabel 316 %19 = OpCopyObject %uint %15 317 OpBranch %16 318 %17 = OpLabel 319 %18 = OpCopyObject %uint %15 320 OpBranch %16 321 %16 = OpLabel 322 OpReturn 323 OpFunctionEnd 324)"; 325 326 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 327 text, /* skip_nop = */ true, /* do_validation = */ true); 328 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 329} 330 331TEST_F(CodeSinkTest, DontMoveBecauseOfStore) { 332 const std::string text = R"( 333 OpCapability Shader 334 OpMemoryModel Logical GLSL450 335 OpEntryPoint GLCompute %1 "main" 336 %void = OpTypeVoid 337 %bool = OpTypeBool 338 %true = OpConstantTrue %bool 339 %uint = OpTypeInt 32 0 340 %uint_0 = OpConstant %uint 0 341 %uint_4 = OpConstant %uint 4 342%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 343%_ptr_Uniform_uint = OpTypePointer Uniform %uint 344%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 345 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 346 %12 = OpTypeFunction %void 347 %1 = OpFunction %void None %12 348 %13 = OpLabel 349 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 350 %15 = OpLoad %uint %14 351 OpStore %14 %15 352 OpSelectionMerge %16 None 353 OpBranchConditional %true %17 %20 354 %20 = OpLabel 355 OpBranch %16 356 %17 = OpLabel 357 %18 = OpCopyObject %uint %15 358 OpBranch %16 359 %16 = OpLabel 360 OpReturn 361 OpFunctionEnd 362)"; 363 364 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 365 text, /* skip_nop = */ true, /* do_validation = */ true); 366 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 367} 368 369TEST_F(CodeSinkTest, MoveReadOnlyLoadWithSync) { 370 const std::string text = R"( 371 OpCapability Shader 372 OpMemoryModel Logical GLSL450 373 OpEntryPoint GLCompute %1 "main" 374 %void = OpTypeVoid 375 %bool = OpTypeBool 376 %true = OpConstantTrue %bool 377 %uint = OpTypeInt 32 0 378 %uint_0 = OpConstant %uint 0 379 %uint_4 = OpConstant %uint 4 380%mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire 381%_arr_uint_uint_4 = OpTypeArray %uint %uint_4 382%_ptr_Uniform_uint = OpTypePointer Uniform %uint 383%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 384 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 385 %12 = OpTypeFunction %void 386 %1 = OpFunction %void None %12 387 %13 = OpLabel 388 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 389 %15 = OpLoad %uint %14 390 OpMemoryBarrier %uint_4 %mem_semantics 391 OpSelectionMerge %16 None 392 OpBranchConditional %true %17 %20 393 %20 = OpLabel 394 OpBranch %16 395 %17 = OpLabel 396 %18 = OpCopyObject %uint %15 397 OpBranch %16 398 %16 = OpLabel 399 OpReturn 400 OpFunctionEnd 401)"; 402 403 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 404 text, /* skip_nop = */ true, /* do_validation = */ true); 405 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); 406} 407 408TEST_F(CodeSinkTest, DontMoveBecauseOfSync) { 409 const std::string text = R"( 410 OpCapability Shader 411 OpMemoryModel Logical GLSL450 412 OpEntryPoint GLCompute %1 "main" 413 OpDecorate %_arr_uint_uint_4 BufferBlock 414 OpMemberDecorate %_arr_uint_uint_4 0 Offset 0 415 %void = OpTypeVoid 416 %bool = OpTypeBool 417 %true = OpConstantTrue %bool 418 %uint = OpTypeInt 32 0 419 %uint_0 = OpConstant %uint 0 420 %uint_4 = OpConstant %uint 4 421%mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire 422%_arr_uint_uint_4 = OpTypeStruct %uint 423%_ptr_Uniform_uint = OpTypePointer Uniform %uint 424%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 425 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 426 %12 = OpTypeFunction %void 427 %1 = OpFunction %void None %12 428 %13 = OpLabel 429 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 430 %15 = OpLoad %uint %14 431 OpMemoryBarrier %uint_4 %mem_semantics 432 OpSelectionMerge %16 None 433 OpBranchConditional %true %17 %20 434 %20 = OpLabel 435 OpBranch %16 436 %17 = OpLabel 437 %18 = OpCopyObject %uint %15 438 OpBranch %16 439 %16 = OpLabel 440 OpReturn 441 OpFunctionEnd 442)"; 443 444 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 445 text, /* skip_nop = */ true, /* do_validation = */ true); 446 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 447} 448 449TEST_F(CodeSinkTest, DontMoveBecauseOfAtomicWithSync) { 450 const std::string text = R"( 451 OpCapability Shader 452 OpMemoryModel Logical GLSL450 453 OpEntryPoint GLCompute %1 "main" 454 OpDecorate %_arr_uint_uint_4 BufferBlock 455 OpMemberDecorate %_arr_uint_uint_4 0 Offset 0 456 %void = OpTypeVoid 457 %bool = OpTypeBool 458 %true = OpConstantTrue %bool 459 %uint = OpTypeInt 32 0 460 %uint_0 = OpConstant %uint 0 461 %uint_4 = OpConstant %uint 4 462%mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire 463%_arr_uint_uint_4 = OpTypeStruct %uint 464%_ptr_Uniform_uint = OpTypePointer Uniform %uint 465%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 466 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 467 %12 = OpTypeFunction %void 468 %1 = OpFunction %void None %12 469 %13 = OpLabel 470 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 471 %15 = OpLoad %uint %14 472 %al = OpAtomicLoad %uint %14 %uint_4 %mem_semantics 473 OpSelectionMerge %16 None 474 OpBranchConditional %true %17 %20 475 %20 = OpLabel 476 OpBranch %16 477 %17 = OpLabel 478 %18 = OpCopyObject %uint %15 479 OpBranch %16 480 %16 = OpLabel 481 OpReturn 482 OpFunctionEnd 483)"; 484 485 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 486 text, /* skip_nop = */ true, /* do_validation = */ true); 487 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 488} 489 490TEST_F(CodeSinkTest, MoveWithAtomicWithoutSync) { 491 const std::string text = R"( 492 OpCapability Shader 493 OpMemoryModel Logical GLSL450 494 OpEntryPoint GLCompute %1 "main" 495 OpDecorate %_arr_uint_uint_4 BufferBlock 496 OpMemberDecorate %_arr_uint_uint_4 0 Offset 0 497 %void = OpTypeVoid 498 %bool = OpTypeBool 499 %true = OpConstantTrue %bool 500 %uint = OpTypeInt 32 0 501 %uint_0 = OpConstant %uint 0 502 %uint_4 = OpConstant %uint 4 503%_arr_uint_uint_4 = OpTypeStruct %uint 504%_ptr_Uniform_uint = OpTypePointer Uniform %uint 505%_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4 506 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform 507 %12 = OpTypeFunction %void 508 %1 = OpFunction %void None %12 509 %13 = OpLabel 510 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0 511 %15 = OpLoad %uint %14 512 %al = OpAtomicLoad %uint %14 %uint_4 %uint_0 513 OpSelectionMerge %16 None 514 OpBranchConditional %true %17 %20 515 %20 = OpLabel 516 OpBranch %16 517 %17 = OpLabel 518 %18 = OpCopyObject %uint %15 519 OpBranch %16 520 %16 = OpLabel 521 OpReturn 522 OpFunctionEnd 523)"; 524 525 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 526 text, /* skip_nop = */ true, /* do_validation = */ true); 527 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result)); 528} 529 530TEST_F(CodeSinkTest, DecorationOnLoad) { 531 const std::string text = R"( 532 OpCapability Shader 533 OpMemoryModel Logical GLSL450 534 OpEntryPoint GLCompute %1 "main" %2 535 OpDecorate %3 RelaxedPrecision 536 %void = OpTypeVoid 537 %5 = OpTypeFunction %void 538 %float = OpTypeFloat 32 539%_ptr_Input_float = OpTypePointer Input %float 540 %2 = OpVariable %_ptr_Input_float Input 541 %1 = OpFunction %void None %5 542 %8 = OpLabel 543 %3 = OpLoad %float %2 544 OpReturn 545 OpFunctionEnd 546)"; 547 548 // We just want to make sure the code does not crash. 549 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>( 550 text, /* skip_nop = */ true, /* do_validation = */ true); 551 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 552} 553 554} // namespace 555} // namespace opt 556} // namespace spvtools 557