1// Copyright (c) 2017-2022 Valve Corporation 2// Copyright (c) 2017-2022 LunarG Inc. 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15 16#include <memory> 17#include <string> 18#include <vector> 19 20#include "test/opt/pass_fixture.h" 21#include "test/opt/pass_utils.h" 22 23namespace spvtools { 24namespace opt { 25namespace { 26 27using InlineTest = PassTest<::testing::Test>; 28 29TEST_F(InlineTest, Simple) { 30 // #version 140 31 // 32 // in vec4 BaseColor; 33 // 34 // float foo(vec4 bar) 35 // { 36 // return bar.x + bar.y; 37 // } 38 // 39 // void main() 40 // { 41 // vec4 color = vec4(foo(BaseColor)); 42 // gl_FragColor = color; 43 // } 44 const std::vector<const char*> predefs = { 45 // clang-format off 46 "OpCapability Shader", 47 "%1 = OpExtInstImport \"GLSL.std.450\"", 48 "OpMemoryModel Logical GLSL450", 49 "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", 50 "OpExecutionMode %main OriginUpperLeft", 51 "OpSource GLSL 140", 52 "OpName %main \"main\"", 53 "OpName %foo_vf4_ \"foo(vf4;\"", 54 "OpName %bar \"bar\"", 55 "OpName %color \"color\"", 56 "OpName %BaseColor \"BaseColor\"", 57 "OpName %param \"param\"", 58 "OpName %gl_FragColor \"gl_FragColor\"", 59 "%void = OpTypeVoid", 60 "%10 = OpTypeFunction %void", 61 "%float = OpTypeFloat 32", 62 "%v4float = OpTypeVector %float 4", 63"%_ptr_Function_v4float = OpTypePointer Function %v4float", 64 "%14 = OpTypeFunction %float %_ptr_Function_v4float", 65 "%uint = OpTypeInt 32 0", 66 "%uint_0 = OpConstant %uint 0", 67"%_ptr_Function_float = OpTypePointer Function %float", 68 "%uint_1 = OpConstant %uint 1", 69"%_ptr_Input_v4float = OpTypePointer Input %v4float", 70 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 71"%_ptr_Output_v4float = OpTypePointer Output %v4float", 72"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", 73 // clang-format on 74 }; 75 76 const std::vector<const char*> nonEntryFuncs = { 77 // clang-format off 78 "%foo_vf4_ = OpFunction %float None %14", 79 "%bar = OpFunctionParameter %_ptr_Function_v4float", 80 "%26 = OpLabel", 81 "%27 = OpAccessChain %_ptr_Function_float %bar %uint_0", 82 "%28 = OpLoad %float %27", 83 "%29 = OpAccessChain %_ptr_Function_float %bar %uint_1", 84 "%30 = OpLoad %float %29", 85 "%31 = OpFAdd %float %28 %30", 86 "OpReturnValue %31", 87 "OpFunctionEnd", 88 // clang-format on 89 }; 90 91 const std::vector<const char*> before = { 92 // clang-format off 93 "%main = OpFunction %void None %10", 94 "%21 = OpLabel", 95 "%color = OpVariable %_ptr_Function_v4float Function", 96 "%param = OpVariable %_ptr_Function_v4float Function", 97 "%22 = OpLoad %v4float %BaseColor", 98 "OpStore %param %22", 99 "%23 = OpFunctionCall %float %foo_vf4_ %param", 100 "%24 = OpCompositeConstruct %v4float %23 %23 %23 %23", 101 "OpStore %color %24", 102 "%25 = OpLoad %v4float %color", 103 "OpStore %gl_FragColor %25", 104 "OpReturn", 105 "OpFunctionEnd", 106 // clang-format on 107 }; 108 109 const std::vector<const char*> after = { 110 // clang-format off 111 "%main = OpFunction %void None %10", 112 "%21 = OpLabel", 113 "%32 = OpVariable %_ptr_Function_float Function", 114 "%color = OpVariable %_ptr_Function_v4float Function", 115 "%param = OpVariable %_ptr_Function_v4float Function", 116 "%22 = OpLoad %v4float %BaseColor", 117 "OpStore %param %22", 118 "%34 = OpAccessChain %_ptr_Function_float %param %uint_0", 119 "%35 = OpLoad %float %34", 120 "%36 = OpAccessChain %_ptr_Function_float %param %uint_1", 121 "%37 = OpLoad %float %36", 122 "%38 = OpFAdd %float %35 %37", 123 "OpStore %32 %38", 124 "%23 = OpLoad %float %32", 125 "%24 = OpCompositeConstruct %v4float %23 %23 %23 %23", 126 "OpStore %color %24", 127 "%25 = OpLoad %v4float %color", 128 "OpStore %gl_FragColor %25", 129 "OpReturn", 130 "OpFunctionEnd", 131 // clang-format on 132 }; 133 SinglePassRunAndCheck<InlineExhaustivePass>( 134 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 135 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 136 /* skip_nop = */ false, /* do_validate = */ true); 137} 138 139TEST_F(InlineTest, Nested) { 140 // #version 140 141 // 142 // in vec4 BaseColor; 143 // 144 // float foo2(float f, float f2) 145 // { 146 // return f * f2; 147 // } 148 // 149 // float foo(vec4 bar) 150 // { 151 // return foo2(bar.x + bar.y, bar.z); 152 // } 153 // 154 // void main() 155 // { 156 // vec4 color = vec4(foo(BaseColor)); 157 // gl_FragColor = color; 158 // } 159 const std::vector<const char*> predefs = { 160 // clang-format off 161 "OpCapability Shader", 162 "%1 = OpExtInstImport \"GLSL.std.450\"", 163 "OpMemoryModel Logical GLSL450", 164 "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", 165 "OpExecutionMode %main OriginUpperLeft", 166 "OpSource GLSL 140", 167 "OpName %main \"main\"", 168 "OpName %foo2_f1_f1_ \"foo2(f1;f1;\"", 169 "OpName %f \"f\"", 170 "OpName %f2 \"f2\"", 171 "OpName %foo_vf4_ \"foo(vf4;\"", 172 "OpName %bar \"bar\"", 173 "OpName %param \"param\"", 174 "OpName %param_0 \"param\"", 175 "OpName %color \"color\"", 176 "OpName %BaseColor \"BaseColor\"", 177 "OpName %param_1 \"param\"", 178 "OpName %gl_FragColor \"gl_FragColor\"", 179 "%void = OpTypeVoid", 180 "%15 = OpTypeFunction %void", 181 "%float = OpTypeFloat 32", 182"%_ptr_Function_float = OpTypePointer Function %float", 183 "%18 = OpTypeFunction %float %_ptr_Function_float %_ptr_Function_float", 184 "%v4float = OpTypeVector %float 4", 185"%_ptr_Function_v4float = OpTypePointer Function %v4float", 186 "%21 = OpTypeFunction %float %_ptr_Function_v4float", 187 "%uint = OpTypeInt 32 0", 188 "%uint_0 = OpConstant %uint 0", 189 "%uint_1 = OpConstant %uint 1", 190 "%uint_2 = OpConstant %uint 2", 191"%_ptr_Input_v4float = OpTypePointer Input %v4float", 192 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 193"%_ptr_Output_v4float = OpTypePointer Output %v4float", 194"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", 195 // clang-format on 196 }; 197 198 const std::vector<const char*> nonEntryFuncs = { 199 // clang-format off 200"%foo2_f1_f1_ = OpFunction %float None %18", 201 "%f = OpFunctionParameter %_ptr_Function_float", 202 "%f2 = OpFunctionParameter %_ptr_Function_float", 203 "%33 = OpLabel", 204 "%34 = OpLoad %float %f", 205 "%35 = OpLoad %float %f2", 206 "%36 = OpFMul %float %34 %35", 207 "OpReturnValue %36", 208 "OpFunctionEnd", 209 "%foo_vf4_ = OpFunction %float None %21", 210 "%bar = OpFunctionParameter %_ptr_Function_v4float", 211 "%37 = OpLabel", 212 "%param = OpVariable %_ptr_Function_float Function", 213 "%param_0 = OpVariable %_ptr_Function_float Function", 214 "%38 = OpAccessChain %_ptr_Function_float %bar %uint_0", 215 "%39 = OpLoad %float %38", 216 "%40 = OpAccessChain %_ptr_Function_float %bar %uint_1", 217 "%41 = OpLoad %float %40", 218 "%42 = OpFAdd %float %39 %41", 219 "OpStore %param %42", 220 "%43 = OpAccessChain %_ptr_Function_float %bar %uint_2", 221 "%44 = OpLoad %float %43", 222 "OpStore %param_0 %44", 223 "%45 = OpFunctionCall %float %foo2_f1_f1_ %param %param_0", 224 "OpReturnValue %45", 225 "OpFunctionEnd", 226 // clang-format on 227 }; 228 229 const std::vector<const char*> before = { 230 // clang-format off 231 "%main = OpFunction %void None %15", 232 "%28 = OpLabel", 233 "%color = OpVariable %_ptr_Function_v4float Function", 234 "%param_1 = OpVariable %_ptr_Function_v4float Function", 235 "%29 = OpLoad %v4float %BaseColor", 236 "OpStore %param_1 %29", 237 "%30 = OpFunctionCall %float %foo_vf4_ %param_1", 238 "%31 = OpCompositeConstruct %v4float %30 %30 %30 %30", 239 "OpStore %color %31", 240 "%32 = OpLoad %v4float %color", 241 "OpStore %gl_FragColor %32", 242 "OpReturn", 243 "OpFunctionEnd", 244 // clang-format on 245 }; 246 247 const std::vector<const char*> after = { 248 // clang-format off 249 "%main = OpFunction %void None %15", 250 "%28 = OpLabel", 251 "%58 = OpVariable %_ptr_Function_float Function", 252 "%46 = OpVariable %_ptr_Function_float Function", 253 "%47 = OpVariable %_ptr_Function_float Function", 254 "%48 = OpVariable %_ptr_Function_float Function", 255 "%color = OpVariable %_ptr_Function_v4float Function", 256 "%param_1 = OpVariable %_ptr_Function_v4float Function", 257 "%29 = OpLoad %v4float %BaseColor", 258 "OpStore %param_1 %29", 259 "%50 = OpAccessChain %_ptr_Function_float %param_1 %uint_0", 260 "%51 = OpLoad %float %50", 261 "%52 = OpAccessChain %_ptr_Function_float %param_1 %uint_1", 262 "%53 = OpLoad %float %52", 263 "%54 = OpFAdd %float %51 %53", 264 "OpStore %46 %54", 265 "%55 = OpAccessChain %_ptr_Function_float %param_1 %uint_2", 266 "%56 = OpLoad %float %55", 267 "OpStore %47 %56", 268 "%60 = OpLoad %float %46", 269 "%61 = OpLoad %float %47", 270 "%62 = OpFMul %float %60 %61", 271 "OpStore %58 %62", 272 "%57 = OpLoad %float %58", 273 "OpStore %48 %57", 274 "%30 = OpLoad %float %48", 275 "%31 = OpCompositeConstruct %v4float %30 %30 %30 %30", 276 "OpStore %color %31", 277 "%32 = OpLoad %v4float %color", 278 "OpStore %gl_FragColor %32", 279 "OpReturn", 280 "OpFunctionEnd", 281 // clang-format on 282 }; 283 SinglePassRunAndCheck<InlineExhaustivePass>( 284 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 285 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 286 /* skip_nop = */ false, /* do_validate = */ true); 287} 288 289TEST_F(InlineTest, InOutParameter) { 290 // #version 400 291 // 292 // in vec4 Basecolor; 293 // 294 // void foo(inout vec4 bar) 295 // { 296 // bar.z = bar.x + bar.y; 297 // } 298 // 299 // void main() 300 // { 301 // vec4 b = Basecolor; 302 // foo(b); 303 // vec4 color = vec4(b.z); 304 // gl_FragColor = color; 305 // } 306 const std::vector<const char*> predefs = { 307 // clang-format off 308 "OpCapability Shader", 309 "%1 = OpExtInstImport \"GLSL.std.450\"", 310 "OpMemoryModel Logical GLSL450", 311 "OpEntryPoint Fragment %main \"main\" %Basecolor %gl_FragColor", 312 "OpExecutionMode %main OriginUpperLeft", 313 "OpSource GLSL 400", 314 "OpName %main \"main\"", 315 "OpName %foo_vf4_ \"foo(vf4;\"", 316 "OpName %bar \"bar\"", 317 "OpName %b \"b\"", 318 "OpName %Basecolor \"Basecolor\"", 319 "OpName %param \"param\"", 320 "OpName %color \"color\"", 321 "OpName %gl_FragColor \"gl_FragColor\"", 322 "%void = OpTypeVoid", 323 "%11 = OpTypeFunction %void", 324 "%float = OpTypeFloat 32", 325 "%v4float = OpTypeVector %float 4", 326"%_ptr_Function_v4float = OpTypePointer Function %v4float", 327 "%15 = OpTypeFunction %void %_ptr_Function_v4float", 328 "%uint = OpTypeInt 32 0", 329 "%uint_0 = OpConstant %uint 0", 330"%_ptr_Function_float = OpTypePointer Function %float", 331 "%uint_1 = OpConstant %uint 1", 332 "%uint_2 = OpConstant %uint 2", 333"%_ptr_Input_v4float = OpTypePointer Input %v4float", 334 "%Basecolor = OpVariable %_ptr_Input_v4float Input", 335"%_ptr_Output_v4float = OpTypePointer Output %v4float", 336"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", 337 // clang-format on 338 }; 339 340 const std::vector<const char*> nonEntryFuncs = { 341 // clang-format off 342 "%foo_vf4_ = OpFunction %void None %15", 343 "%bar = OpFunctionParameter %_ptr_Function_v4float", 344 "%32 = OpLabel", 345 "%33 = OpAccessChain %_ptr_Function_float %bar %uint_0", 346 "%34 = OpLoad %float %33", 347 "%35 = OpAccessChain %_ptr_Function_float %bar %uint_1", 348 "%36 = OpLoad %float %35", 349 "%37 = OpFAdd %float %34 %36", 350 "%38 = OpAccessChain %_ptr_Function_float %bar %uint_2", 351 "OpStore %38 %37", 352 "OpReturn", 353 "OpFunctionEnd", 354 // clang-format on 355 }; 356 357 const std::vector<const char*> before = { 358 // clang-format off 359 "%main = OpFunction %void None %11", 360 "%23 = OpLabel", 361 "%b = OpVariable %_ptr_Function_v4float Function", 362 "%param = OpVariable %_ptr_Function_v4float Function", 363 "%color = OpVariable %_ptr_Function_v4float Function", 364 "%24 = OpLoad %v4float %Basecolor", 365 "OpStore %b %24", 366 "%25 = OpLoad %v4float %b", 367 "OpStore %param %25", 368 "%26 = OpFunctionCall %void %foo_vf4_ %param", 369 "%27 = OpLoad %v4float %param", 370 "OpStore %b %27", 371 "%28 = OpAccessChain %_ptr_Function_float %b %uint_2", 372 "%29 = OpLoad %float %28", 373 "%30 = OpCompositeConstruct %v4float %29 %29 %29 %29", 374 "OpStore %color %30", 375 "%31 = OpLoad %v4float %color", 376 "OpStore %gl_FragColor %31", 377 "OpReturn", 378 "OpFunctionEnd", 379 // clang-format on 380 }; 381 382 const std::vector<const char*> after = { 383 // clang-format off 384 "%main = OpFunction %void None %11", 385 "%23 = OpLabel", 386 "%b = OpVariable %_ptr_Function_v4float Function", 387 "%param = OpVariable %_ptr_Function_v4float Function", 388 "%color = OpVariable %_ptr_Function_v4float Function", 389 "%24 = OpLoad %v4float %Basecolor", 390 "OpStore %b %24", 391 "%25 = OpLoad %v4float %b", 392 "OpStore %param %25", 393 "%40 = OpAccessChain %_ptr_Function_float %param %uint_0", 394 "%41 = OpLoad %float %40", 395 "%42 = OpAccessChain %_ptr_Function_float %param %uint_1", 396 "%43 = OpLoad %float %42", 397 "%44 = OpFAdd %float %41 %43", 398 "%45 = OpAccessChain %_ptr_Function_float %param %uint_2", 399 "OpStore %45 %44", 400 "%27 = OpLoad %v4float %param", 401 "OpStore %b %27", 402 "%28 = OpAccessChain %_ptr_Function_float %b %uint_2", 403 "%29 = OpLoad %float %28", 404 "%30 = OpCompositeConstruct %v4float %29 %29 %29 %29", 405 "OpStore %color %30", 406 "%31 = OpLoad %v4float %color", 407 "OpStore %gl_FragColor %31", 408 "OpReturn", 409 "OpFunctionEnd", 410 // clang-format on 411 }; 412 SinglePassRunAndCheck<InlineExhaustivePass>( 413 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 414 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 415 /* skip_nop = */ false, /* do_validate = */ true); 416} 417 418TEST_F(InlineTest, BranchInCallee) { 419 // #version 140 420 // 421 // in vec4 BaseColor; 422 // 423 // float foo(vec4 bar) 424 // { 425 // float r = bar.x; 426 // if (r < 0.0) 427 // r = -r; 428 // return r; 429 // } 430 // 431 // void main() 432 // { 433 // vec4 color = vec4(foo(BaseColor)); 434 // 435 // gl_FragColor = color; 436 // } 437 const std::vector<const char*> predefs = { 438 // clang-format off 439 "OpCapability Shader", 440 "%1 = OpExtInstImport \"GLSL.std.450\"", 441 "OpMemoryModel Logical GLSL450", 442 "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", 443 "OpExecutionMode %main OriginUpperLeft", 444 "OpSource GLSL 140", 445 "OpName %main \"main\"", 446 "OpName %foo_vf4_ \"foo(vf4;\"", 447 "OpName %bar \"bar\"", 448 "OpName %r \"r\"", 449 "OpName %color \"color\"", 450 "OpName %BaseColor \"BaseColor\"", 451 "OpName %param \"param\"", 452 "OpName %gl_FragColor \"gl_FragColor\"", 453 "%void = OpTypeVoid", 454 "%11 = OpTypeFunction %void", 455 "%float = OpTypeFloat 32", 456 "%v4float = OpTypeVector %float 4", 457"%_ptr_Function_v4float = OpTypePointer Function %v4float", 458 "%15 = OpTypeFunction %float %_ptr_Function_v4float", 459"%_ptr_Function_float = OpTypePointer Function %float", 460 "%uint = OpTypeInt 32 0", 461 "%uint_0 = OpConstant %uint 0", 462 "%float_0 = OpConstant %float 0", 463 "%bool = OpTypeBool", 464"%_ptr_Input_v4float = OpTypePointer Input %v4float", 465 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 466"%_ptr_Output_v4float = OpTypePointer Output %v4float", 467"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", 468 // clang-format on 469 }; 470 471 const std::vector<const char*> nonEntryFuncs = { 472 // clang-format off 473 "%foo_vf4_ = OpFunction %float None %15", 474 "%bar = OpFunctionParameter %_ptr_Function_v4float", 475 "%28 = OpLabel", 476 "%r = OpVariable %_ptr_Function_float Function", 477 "%29 = OpAccessChain %_ptr_Function_float %bar %uint_0", 478 "%30 = OpLoad %float %29", 479 "OpStore %r %30", 480 "%31 = OpLoad %float %r", 481 "%32 = OpFOrdLessThan %bool %31 %float_0", 482 "OpSelectionMerge %33 None", 483 "OpBranchConditional %32 %34 %33", 484 "%34 = OpLabel", 485 "%35 = OpLoad %float %r", 486 "%36 = OpFNegate %float %35", 487 "OpStore %r %36", 488 "OpBranch %33", 489 "%33 = OpLabel", 490 "%37 = OpLoad %float %r", 491 "OpReturnValue %37", 492 "OpFunctionEnd", 493 // clang-format on 494 }; 495 496 const std::vector<const char*> before = { 497 // clang-format off 498 "%main = OpFunction %void None %11", 499 "%23 = OpLabel", 500 "%color = OpVariable %_ptr_Function_v4float Function", 501 "%param = OpVariable %_ptr_Function_v4float Function", 502 "%24 = OpLoad %v4float %BaseColor", 503 "OpStore %param %24", 504 "%25 = OpFunctionCall %float %foo_vf4_ %param", 505 "%26 = OpCompositeConstruct %v4float %25 %25 %25 %25", 506 "OpStore %color %26", 507 "%27 = OpLoad %v4float %color", 508 "OpStore %gl_FragColor %27", 509 "OpReturn", 510 "OpFunctionEnd", 511 // clang-format on 512 }; 513 514 const std::vector<const char*> after = { 515 // clang-format off 516 "%main = OpFunction %void None %11", 517 "%23 = OpLabel", 518 "%38 = OpVariable %_ptr_Function_float Function", 519 "%39 = OpVariable %_ptr_Function_float Function", 520 "%color = OpVariable %_ptr_Function_v4float Function", 521 "%param = OpVariable %_ptr_Function_v4float Function", 522 "%24 = OpLoad %v4float %BaseColor", 523 "OpStore %param %24", 524 "%41 = OpAccessChain %_ptr_Function_float %param %uint_0", 525 "%42 = OpLoad %float %41", 526 "OpStore %38 %42", 527 "%43 = OpLoad %float %38", 528 "%44 = OpFOrdLessThan %bool %43 %float_0", 529 "OpSelectionMerge %48 None", 530 "OpBranchConditional %44 %45 %48", 531 "%45 = OpLabel", 532 "%46 = OpLoad %float %38", 533 "%47 = OpFNegate %float %46", 534 "OpStore %38 %47", 535 "OpBranch %48", 536 "%48 = OpLabel", 537 "%49 = OpLoad %float %38", 538 "OpStore %39 %49", 539 "%25 = OpLoad %float %39", 540 "%26 = OpCompositeConstruct %v4float %25 %25 %25 %25", 541 "OpStore %color %26", 542 "%27 = OpLoad %v4float %color", 543 "OpStore %gl_FragColor %27", 544 "OpReturn", 545 "OpFunctionEnd", 546 // clang-format on 547 }; 548 SinglePassRunAndCheck<InlineExhaustivePass>( 549 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 550 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 551 /* skip_nop = */ false, /* do_validate = */ true); 552} 553 554TEST_F(InlineTest, PhiAfterCall) { 555 // #version 140 556 // 557 // in vec4 BaseColor; 558 // 559 // float foo(float bar) 560 // { 561 // float r = bar; 562 // if (r < 0.0) 563 // r = -r; 564 // return r; 565 // } 566 // 567 // void main() 568 // { 569 // vec4 color = BaseColor; 570 // if (foo(color.x) > 2.0 && foo(color.y) > 2.0) 571 // color = vec4(0.0); 572 // gl_FragColor = color; 573 // } 574 const std::vector<const char*> predefs = { 575 // clang-format off 576 "OpCapability Shader", 577 "%1 = OpExtInstImport \"GLSL.std.450\"", 578 "OpMemoryModel Logical GLSL450", 579 "OpEntryPoint Fragment %main \"main\" %BaseColor %gl_FragColor", 580 "OpExecutionMode %main OriginUpperLeft", 581 "OpSource GLSL 140", 582 "OpName %main \"main\"", 583 "OpName %foo_f1_ \"foo(f1;\"", 584 "OpName %bar \"bar\"", 585 "OpName %r \"r\"", 586 "OpName %color \"color\"", 587 "OpName %BaseColor \"BaseColor\"", 588 "OpName %param \"param\"", 589 "OpName %param_0 \"param\"", 590 "OpName %gl_FragColor \"gl_FragColor\"", 591 "%void = OpTypeVoid", 592 "%12 = OpTypeFunction %void", 593 "%float = OpTypeFloat 32", 594"%_ptr_Function_float = OpTypePointer Function %float", 595 "%15 = OpTypeFunction %float %_ptr_Function_float", 596 "%float_0 = OpConstant %float 0", 597 "%bool = OpTypeBool", 598 "%v4float = OpTypeVector %float 4", 599"%_ptr_Function_v4float = OpTypePointer Function %v4float", 600"%_ptr_Input_v4float = OpTypePointer Input %v4float", 601 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 602 "%uint = OpTypeInt 32 0", 603 "%uint_0 = OpConstant %uint 0", 604 "%float_2 = OpConstant %float 2", 605 "%uint_1 = OpConstant %uint 1", 606 "%25 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0", 607"%_ptr_Output_v4float = OpTypePointer Output %v4float", 608"%gl_FragColor = OpVariable %_ptr_Output_v4float Output", 609 // clang-format on 610 }; 611 612 const std::vector<const char*> nonEntryFuncs = { 613 // clang-format off 614 "%foo_f1_ = OpFunction %float None %15", 615 "%bar = OpFunctionParameter %_ptr_Function_float", 616 "%43 = OpLabel", 617 "%r = OpVariable %_ptr_Function_float Function", 618 "%44 = OpLoad %float %bar", 619 "OpStore %r %44", 620 "%45 = OpLoad %float %r", 621 "%46 = OpFOrdLessThan %bool %45 %float_0", 622 "OpSelectionMerge %47 None", 623 "OpBranchConditional %46 %48 %47", 624 "%48 = OpLabel", 625 "%49 = OpLoad %float %r", 626 "%50 = OpFNegate %float %49", 627 "OpStore %r %50", 628 "OpBranch %47", 629 "%47 = OpLabel", 630 "%51 = OpLoad %float %r", 631 "OpReturnValue %51", 632 "OpFunctionEnd", 633 // clang-format on 634 }; 635 636 const std::vector<const char*> before = { 637 // clang-format off 638 "%main = OpFunction %void None %12", 639 "%27 = OpLabel", 640 "%color = OpVariable %_ptr_Function_v4float Function", 641 "%param = OpVariable %_ptr_Function_float Function", 642 "%param_0 = OpVariable %_ptr_Function_float Function", 643 "%28 = OpLoad %v4float %BaseColor", 644 "OpStore %color %28", 645 "%29 = OpAccessChain %_ptr_Function_float %color %uint_0", 646 "%30 = OpLoad %float %29", 647 "OpStore %param %30", 648 "%31 = OpFunctionCall %float %foo_f1_ %param", 649 "%32 = OpFOrdGreaterThan %bool %31 %float_2", 650 "OpSelectionMerge %33 None", 651 "OpBranchConditional %32 %34 %33", 652 "%34 = OpLabel", 653 "%35 = OpAccessChain %_ptr_Function_float %color %uint_1", 654 "%36 = OpLoad %float %35", 655 "OpStore %param_0 %36", 656 "%37 = OpFunctionCall %float %foo_f1_ %param_0", 657 "%38 = OpFOrdGreaterThan %bool %37 %float_2", 658 "OpBranch %33", 659 "%33 = OpLabel", 660 "%39 = OpPhi %bool %32 %27 %38 %34", 661 "OpSelectionMerge %40 None", 662 "OpBranchConditional %39 %41 %40", 663 "%41 = OpLabel", 664 "OpStore %color %25", 665 "OpBranch %40", 666 "%40 = OpLabel", 667 "%42 = OpLoad %v4float %color", 668 "OpStore %gl_FragColor %42", 669 "OpReturn", 670 "OpFunctionEnd", 671 // clang-format on 672 }; 673 674 const std::vector<const char*> after = { 675 // clang-format off 676 "%main = OpFunction %void None %12", 677 "%27 = OpLabel", 678 "%63 = OpVariable %_ptr_Function_float Function", 679 "%64 = OpVariable %_ptr_Function_float Function", 680 "%52 = OpVariable %_ptr_Function_float Function", 681 "%53 = OpVariable %_ptr_Function_float Function", 682 "%color = OpVariable %_ptr_Function_v4float Function", 683 "%param = OpVariable %_ptr_Function_float Function", 684 "%param_0 = OpVariable %_ptr_Function_float Function", 685 "%28 = OpLoad %v4float %BaseColor", 686 "OpStore %color %28", 687 "%29 = OpAccessChain %_ptr_Function_float %color %uint_0", 688 "%30 = OpLoad %float %29", 689 "OpStore %param %30", 690 "%55 = OpLoad %float %param", 691 "OpStore %52 %55", 692 "%56 = OpLoad %float %52", 693 "%57 = OpFOrdLessThan %bool %56 %float_0", 694 "OpSelectionMerge %61 None", 695 "OpBranchConditional %57 %58 %61", 696 "%58 = OpLabel", 697 "%59 = OpLoad %float %52", 698 "%60 = OpFNegate %float %59", 699 "OpStore %52 %60", 700 "OpBranch %61", 701 "%61 = OpLabel", 702 "%62 = OpLoad %float %52", 703 "OpStore %53 %62", 704 "%31 = OpLoad %float %53", 705 "%32 = OpFOrdGreaterThan %bool %31 %float_2", 706 "OpSelectionMerge %33 None", 707 "OpBranchConditional %32 %34 %33", 708 "%34 = OpLabel", 709 "%35 = OpAccessChain %_ptr_Function_float %color %uint_1", 710 "%36 = OpLoad %float %35", 711 "OpStore %param_0 %36", 712 "%66 = OpLoad %float %param_0", 713 "OpStore %63 %66", 714 "%67 = OpLoad %float %63", 715 "%68 = OpFOrdLessThan %bool %67 %float_0", 716 "OpSelectionMerge %72 None", 717 "OpBranchConditional %68 %69 %72", 718 "%69 = OpLabel", 719 "%70 = OpLoad %float %63", 720 "%71 = OpFNegate %float %70", 721 "OpStore %63 %71", 722 "OpBranch %72", 723 "%72 = OpLabel", 724 "%73 = OpLoad %float %63", 725 "OpStore %64 %73", 726 "%37 = OpLoad %float %64", 727 "%38 = OpFOrdGreaterThan %bool %37 %float_2", 728 "OpBranch %33", 729 "%33 = OpLabel", 730 "%39 = OpPhi %bool %32 %61 %38 %72", 731 "OpSelectionMerge %40 None", 732 "OpBranchConditional %39 %41 %40", 733 "%41 = OpLabel", 734 "OpStore %color %25", 735 "OpBranch %40", 736 "%40 = OpLabel", 737 "%42 = OpLoad %v4float %color", 738 "OpStore %gl_FragColor %42", 739 "OpReturn", 740 "OpFunctionEnd", 741 // clang-format on 742 }; 743 SinglePassRunAndCheck<InlineExhaustivePass>( 744 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 745 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 746 /* skip_nop = */ false, /* do_validate = */ true); 747} 748 749TEST_F(InlineTest, OpSampledImageOutOfBlock) { 750 // #version 450 751 // 752 // uniform texture2D t2D; 753 // uniform sampler samp; 754 // out vec4 FragColor; 755 // in vec4 BaseColor; 756 // 757 // float foo(vec4 bar) 758 // { 759 // float r = bar.x; 760 // if (r < 0.0) 761 // r = -r; 762 // return r; 763 // } 764 // 765 // void main() 766 // { 767 // vec4 color1 = texture(sampler2D(t2D, samp), vec2(1.0)); 768 // vec4 color2 = vec4(foo(BaseColor)); 769 // vec4 color3 = texture(sampler2D(t2D, samp), vec2(0.5)); 770 // FragColor = (color1 + color2 + color3)/3; 771 // } 772 // 773 // Note: the before SPIR-V will need to be edited to create a use of 774 // the OpSampledImage across the function call. 775 const std::vector<const char*> predefs = { 776 // clang-format off 777 "OpCapability Shader", 778 "%1 = OpExtInstImport \"GLSL.std.450\"", 779 "OpMemoryModel Logical GLSL450", 780 "OpEntryPoint Fragment %main \"main\" %BaseColor %FragColor", 781 "OpExecutionMode %main OriginUpperLeft", 782 "OpSource GLSL 450", 783 "OpName %main \"main\"", 784 "OpName %foo_vf4_ \"foo(vf4;\"", 785 "OpName %bar \"bar\"", 786 "OpName %r \"r\"", 787 "OpName %color1 \"color1\"", 788 "OpName %t2D \"t2D\"", 789 "OpName %samp \"samp\"", 790 "OpName %color2 \"color2\"", 791 "OpName %BaseColor \"BaseColor\"", 792 "OpName %param \"param\"", 793 "OpName %color3 \"color3\"", 794 "OpName %FragColor \"FragColor\"", 795 "OpDecorate %t2D DescriptorSet 0", 796 "OpDecorate %samp DescriptorSet 0", 797 "%void = OpTypeVoid", 798 "%15 = OpTypeFunction %void", 799 "%float = OpTypeFloat 32", 800 "%v4float = OpTypeVector %float 4", 801"%_ptr_Function_v4float = OpTypePointer Function %v4float", 802 "%19 = OpTypeFunction %float %_ptr_Function_v4float", 803"%_ptr_Function_float = OpTypePointer Function %float", 804 "%uint = OpTypeInt 32 0", 805 "%uint_0 = OpConstant %uint 0", 806 "%float_0 = OpConstant %float 0", 807 "%bool = OpTypeBool", 808 "%25 = OpTypeImage %float 2D 0 0 0 1 Unknown", 809"%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25", 810 "%t2D = OpVariable %_ptr_UniformConstant_25 UniformConstant", 811 "%27 = OpTypeSampler", 812"%_ptr_UniformConstant_27 = OpTypePointer UniformConstant %27", 813 "%samp = OpVariable %_ptr_UniformConstant_27 UniformConstant", 814 "%29 = OpTypeSampledImage %25", 815 "%v2float = OpTypeVector %float 2", 816 "%float_1 = OpConstant %float 1", 817 "%32 = OpConstantComposite %v2float %float_1 %float_1", 818"%_ptr_Input_v4float = OpTypePointer Input %v4float", 819 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 820 "%float_0_5 = OpConstant %float 0.5", 821 "%35 = OpConstantComposite %v2float %float_0_5 %float_0_5", 822"%_ptr_Output_v4float = OpTypePointer Output %v4float", 823 "%FragColor = OpVariable %_ptr_Output_v4float Output", 824 "%float_3 = OpConstant %float 3", 825 // clang-format on 826 }; 827 828 const std::vector<const char*> nonEntryFuncs = { 829 // clang-format off 830 "%foo_vf4_ = OpFunction %float None %19", 831 "%bar = OpFunctionParameter %_ptr_Function_v4float", 832 "%56 = OpLabel", 833 "%r = OpVariable %_ptr_Function_float Function", 834 "%57 = OpAccessChain %_ptr_Function_float %bar %uint_0", 835 "%58 = OpLoad %float %57", 836 "OpStore %r %58", 837 "%59 = OpLoad %float %r", 838 "%60 = OpFOrdLessThan %bool %59 %float_0", 839 "OpSelectionMerge %61 None", 840 "OpBranchConditional %60 %62 %61", 841 "%62 = OpLabel", 842 "%63 = OpLoad %float %r", 843 "%64 = OpFNegate %float %63", 844 "OpStore %r %64", 845 "OpBranch %61", 846 "%61 = OpLabel", 847 "%65 = OpLoad %float %r", 848 "OpReturnValue %65", 849 "OpFunctionEnd", 850 // clang-format on 851 }; 852 853 const std::vector<const char*> before = { 854 // clang-format off 855 "%main = OpFunction %void None %15", 856 "%38 = OpLabel", 857 "%color1 = OpVariable %_ptr_Function_v4float Function", 858 "%color2 = OpVariable %_ptr_Function_v4float Function", 859 "%param = OpVariable %_ptr_Function_v4float Function", 860 "%color3 = OpVariable %_ptr_Function_v4float Function", 861 "%39 = OpLoad %25 %t2D", 862 "%40 = OpLoad %27 %samp", 863 "%41 = OpSampledImage %29 %39 %40", 864 "%42 = OpImageSampleImplicitLod %v4float %41 %32", 865 "OpStore %color1 %42", 866 "%43 = OpLoad %v4float %BaseColor", 867 "OpStore %param %43", 868 "%44 = OpFunctionCall %float %foo_vf4_ %param", 869 "%45 = OpCompositeConstruct %v4float %44 %44 %44 %44", 870 "OpStore %color2 %45", 871 "%46 = OpLoad %25 %t2D", 872 "%47 = OpLoad %27 %samp", 873 "%48 = OpImageSampleImplicitLod %v4float %41 %35", 874 "OpStore %color3 %48", 875 "%49 = OpLoad %v4float %color1", 876 "%50 = OpLoad %v4float %color2", 877 "%51 = OpFAdd %v4float %49 %50", 878 "%52 = OpLoad %v4float %color3", 879 "%53 = OpFAdd %v4float %51 %52", 880 "%54 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", 881 "%55 = OpFDiv %v4float %53 %54", 882 "OpStore %FragColor %55", 883 "OpReturn", 884 "OpFunctionEnd", 885 // clang-format on 886 }; 887 888 const std::vector<const char*> after = { 889 // clang-format off 890 "%main = OpFunction %void None %15", 891 "%38 = OpLabel", 892 "%66 = OpVariable %_ptr_Function_float Function", 893 "%67 = OpVariable %_ptr_Function_float Function", 894 "%color1 = OpVariable %_ptr_Function_v4float Function", 895 "%color2 = OpVariable %_ptr_Function_v4float Function", 896 "%param = OpVariable %_ptr_Function_v4float Function", 897 "%color3 = OpVariable %_ptr_Function_v4float Function", 898 "%39 = OpLoad %25 %t2D", 899 "%40 = OpLoad %27 %samp", 900 "%41 = OpSampledImage %29 %39 %40", 901 "%42 = OpImageSampleImplicitLod %v4float %41 %32", 902 "OpStore %color1 %42", 903 "%43 = OpLoad %v4float %BaseColor", 904 "OpStore %param %43", 905 "%69 = OpAccessChain %_ptr_Function_float %param %uint_0", 906 "%70 = OpLoad %float %69", 907 "OpStore %66 %70", 908 "%71 = OpLoad %float %66", 909 "%72 = OpFOrdLessThan %bool %71 %float_0", 910 "OpSelectionMerge %76 None", 911 "OpBranchConditional %72 %73 %76", 912 "%73 = OpLabel", 913 "%74 = OpLoad %float %66", 914 "%75 = OpFNegate %float %74", 915 "OpStore %66 %75", 916 "OpBranch %76", 917 "%76 = OpLabel", 918 "%77 = OpLoad %float %66", 919 "OpStore %67 %77", 920 "%44 = OpLoad %float %67", 921 "%45 = OpCompositeConstruct %v4float %44 %44 %44 %44", 922 "OpStore %color2 %45", 923 "%46 = OpLoad %25 %t2D", 924 "%47 = OpLoad %27 %samp", 925 "%78 = OpSampledImage %29 %39 %40", 926 "%48 = OpImageSampleImplicitLod %v4float %78 %35", 927 "OpStore %color3 %48", 928 "%49 = OpLoad %v4float %color1", 929 "%50 = OpLoad %v4float %color2", 930 "%51 = OpFAdd %v4float %49 %50", 931 "%52 = OpLoad %v4float %color3", 932 "%53 = OpFAdd %v4float %51 %52", 933 "%54 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", 934 "%55 = OpFDiv %v4float %53 %54", 935 "OpStore %FragColor %55", 936 "OpReturn", 937 "OpFunctionEnd", 938 // clang-format on 939 }; 940 SinglePassRunAndCheck<InlineExhaustivePass>( 941 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 942 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 943 /* skip_nop = */ false, /* do_validate = */ true); 944} 945 946TEST_F(InlineTest, OpImageOutOfBlock) { 947 // #version 450 948 // 949 // uniform texture2D t2D; 950 // uniform sampler samp; 951 // uniform sampler samp2; 952 // 953 // out vec4 FragColor; 954 // 955 // in vec4 BaseColor; 956 // 957 // float foo(vec4 bar) 958 // { 959 // float r = bar.x; 960 // if (r < 0.0) 961 // r = -r; 962 // return r; 963 // } 964 // 965 // void main() 966 // { 967 // vec4 color1 = texture(sampler2D(t2D, samp), vec2(1.0)); 968 // vec4 color2 = vec4(foo(BaseColor)); 969 // vec4 color3 = texture(sampler2D(t2D, samp2), vec2(0.5)); 970 // FragColor = (color1 + color2 + color3)/3; 971 // } 972 // Note: the before SPIR-V will need to be edited to create an OpImage 973 // from the first OpSampledImage, place it before the call and use it 974 // in the second OpSampledImage following the call. 975 const std::vector<const char*> predefs = { 976 // clang-format off 977 "OpCapability Shader", 978 "%1 = OpExtInstImport \"GLSL.std.450\"", 979 "OpMemoryModel Logical GLSL450", 980 "OpEntryPoint Fragment %main \"main\" %BaseColor %FragColor", 981 "OpExecutionMode %main OriginUpperLeft", 982 "OpSource GLSL 450", 983 "OpName %main \"main\"", 984 "OpName %foo_vf4_ \"foo(vf4;\"", 985 "OpName %bar \"bar\"", 986 "OpName %r \"r\"", 987 "OpName %color1 \"color1\"", 988 "OpName %t2D \"t2D\"", 989 "OpName %samp \"samp\"", 990 "OpName %color2 \"color2\"", 991 "OpName %BaseColor \"BaseColor\"", 992 "OpName %param \"param\"", 993 "OpName %color3 \"color3\"", 994 "OpName %samp2 \"samp2\"", 995 "OpName %FragColor \"FragColor\"", 996 "OpDecorate %t2D DescriptorSet 0", 997 "OpDecorate %samp DescriptorSet 0", 998 "OpDecorate %samp2 DescriptorSet 0", 999 "%void = OpTypeVoid", 1000 "%16 = OpTypeFunction %void", 1001 "%float = OpTypeFloat 32", 1002 "%v4float = OpTypeVector %float 4", 1003"%_ptr_Function_v4float = OpTypePointer Function %v4float", 1004 "%20 = OpTypeFunction %float %_ptr_Function_v4float", 1005"%_ptr_Function_float = OpTypePointer Function %float", 1006 "%uint = OpTypeInt 32 0", 1007 "%uint_0 = OpConstant %uint 0", 1008 "%float_0 = OpConstant %float 0", 1009 "%bool = OpTypeBool", 1010 "%26 = OpTypeImage %float 2D 0 0 0 1 Unknown", 1011"%_ptr_UniformConstant_26 = OpTypePointer UniformConstant %26", 1012 "%t2D = OpVariable %_ptr_UniformConstant_26 UniformConstant", 1013 "%28 = OpTypeSampler", 1014"%_ptr_UniformConstant_28 = OpTypePointer UniformConstant %28", 1015 "%samp = OpVariable %_ptr_UniformConstant_28 UniformConstant", 1016 "%30 = OpTypeSampledImage %26", 1017 "%v2float = OpTypeVector %float 2", 1018 "%float_1 = OpConstant %float 1", 1019 "%33 = OpConstantComposite %v2float %float_1 %float_1", 1020"%_ptr_Input_v4float = OpTypePointer Input %v4float", 1021 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 1022 "%samp2 = OpVariable %_ptr_UniformConstant_28 UniformConstant", 1023 "%float_0_5 = OpConstant %float 0.5", 1024 "%36 = OpConstantComposite %v2float %float_0_5 %float_0_5", 1025"%_ptr_Output_v4float = OpTypePointer Output %v4float", 1026 "%FragColor = OpVariable %_ptr_Output_v4float Output", 1027 "%float_3 = OpConstant %float 3", 1028 // clang-format on 1029 }; 1030 1031 const std::vector<const char*> nonEntryFuncs = { 1032 // clang-format off 1033 "%foo_vf4_ = OpFunction %float None %20", 1034 "%bar = OpFunctionParameter %_ptr_Function_v4float", 1035 "%58 = OpLabel", 1036 "%r = OpVariable %_ptr_Function_float Function", 1037 "%59 = OpAccessChain %_ptr_Function_float %bar %uint_0", 1038 "%60 = OpLoad %float %59", 1039 "OpStore %r %60", 1040 "%61 = OpLoad %float %r", 1041 "%62 = OpFOrdLessThan %bool %61 %float_0", 1042 "OpSelectionMerge %63 None", 1043 "OpBranchConditional %62 %64 %63", 1044 "%64 = OpLabel", 1045 "%65 = OpLoad %float %r", 1046 "%66 = OpFNegate %float %65", 1047 "OpStore %r %66", 1048 "OpBranch %63", 1049 "%63 = OpLabel", 1050 "%67 = OpLoad %float %r", 1051 "OpReturnValue %67", 1052 "OpFunctionEnd", 1053 // clang-format on 1054 }; 1055 1056 const std::vector<const char*> before = { 1057 // clang-format off 1058 "%main = OpFunction %void None %16", 1059 "%39 = OpLabel", 1060 "%color1 = OpVariable %_ptr_Function_v4float Function", 1061 "%color2 = OpVariable %_ptr_Function_v4float Function", 1062 "%param = OpVariable %_ptr_Function_v4float Function", 1063 "%color3 = OpVariable %_ptr_Function_v4float Function", 1064 "%40 = OpLoad %26 %t2D", 1065 "%41 = OpLoad %28 %samp", 1066 "%42 = OpSampledImage %30 %40 %41", 1067 "%43 = OpImageSampleImplicitLod %v4float %42 %33", 1068 "%44 = OpImage %26 %42", 1069 "%45 = OpLoad %28 %samp2", 1070 "OpStore %color1 %43", 1071 "%46 = OpLoad %v4float %BaseColor", 1072 "OpStore %param %46", 1073 "%47 = OpFunctionCall %float %foo_vf4_ %param", 1074 "%48 = OpCompositeConstruct %v4float %47 %47 %47 %47", 1075 "OpStore %color2 %48", 1076 "%49 = OpSampledImage %30 %44 %45", 1077 "%50 = OpImageSampleImplicitLod %v4float %49 %36", 1078 "OpStore %color3 %50", 1079 "%51 = OpLoad %v4float %color1", 1080 "%52 = OpLoad %v4float %color2", 1081 "%53 = OpFAdd %v4float %51 %52", 1082 "%54 = OpLoad %v4float %color3", 1083 "%55 = OpFAdd %v4float %53 %54", 1084 "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", 1085 "%57 = OpFDiv %v4float %55 %56", 1086 "OpStore %FragColor %57", 1087 "OpReturn", 1088 "OpFunctionEnd", 1089 // clang-format on 1090 }; 1091 1092 const std::vector<const char*> after = { 1093 // clang-format off 1094 "%main = OpFunction %void None %16", 1095 "%39 = OpLabel", 1096 "%68 = OpVariable %_ptr_Function_float Function", 1097 "%69 = OpVariable %_ptr_Function_float Function", 1098 "%color1 = OpVariable %_ptr_Function_v4float Function", 1099 "%color2 = OpVariable %_ptr_Function_v4float Function", 1100 "%param = OpVariable %_ptr_Function_v4float Function", 1101 "%color3 = OpVariable %_ptr_Function_v4float Function", 1102 "%40 = OpLoad %26 %t2D", 1103 "%41 = OpLoad %28 %samp", 1104 "%42 = OpSampledImage %30 %40 %41", 1105 "%43 = OpImageSampleImplicitLod %v4float %42 %33", 1106 "%44 = OpImage %26 %42", 1107 "%45 = OpLoad %28 %samp2", 1108 "OpStore %color1 %43", 1109 "%46 = OpLoad %v4float %BaseColor", 1110 "OpStore %param %46", 1111 "%71 = OpAccessChain %_ptr_Function_float %param %uint_0", 1112 "%72 = OpLoad %float %71", 1113 "OpStore %68 %72", 1114 "%73 = OpLoad %float %68", 1115 "%74 = OpFOrdLessThan %bool %73 %float_0", 1116 "OpSelectionMerge %78 None", 1117 "OpBranchConditional %74 %75 %78", 1118 "%75 = OpLabel", 1119 "%76 = OpLoad %float %68", 1120 "%77 = OpFNegate %float %76", 1121 "OpStore %68 %77", 1122 "OpBranch %78", 1123 "%78 = OpLabel", 1124 "%79 = OpLoad %float %68", 1125 "OpStore %69 %79", 1126 "%47 = OpLoad %float %69", 1127 "%48 = OpCompositeConstruct %v4float %47 %47 %47 %47", 1128 "OpStore %color2 %48", 1129 "%80 = OpSampledImage %30 %40 %41", 1130 "%81 = OpImage %26 %80", 1131 "%49 = OpSampledImage %30 %81 %45", 1132 "%50 = OpImageSampleImplicitLod %v4float %49 %36", 1133 "OpStore %color3 %50", 1134 "%51 = OpLoad %v4float %color1", 1135 "%52 = OpLoad %v4float %color2", 1136 "%53 = OpFAdd %v4float %51 %52", 1137 "%54 = OpLoad %v4float %color3", 1138 "%55 = OpFAdd %v4float %53 %54", 1139 "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", 1140 "%57 = OpFDiv %v4float %55 %56", 1141 "OpStore %FragColor %57", 1142 "OpReturn", 1143 "OpFunctionEnd", 1144 // clang-format on 1145 }; 1146 SinglePassRunAndCheck<InlineExhaustivePass>( 1147 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 1148 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 1149 /* skip_nop = */ false, /* do_validate = */ true); 1150} 1151 1152TEST_F(InlineTest, OpImageAndOpSampledImageOutOfBlock) { 1153 // #version 450 1154 // 1155 // uniform texture2D t2D; 1156 // uniform sampler samp; 1157 // uniform sampler samp2; 1158 // 1159 // out vec4 FragColor; 1160 // 1161 // in vec4 BaseColor; 1162 // 1163 // float foo(vec4 bar) 1164 // { 1165 // float r = bar.x; 1166 // if (r < 0.0) 1167 // r = -r; 1168 // return r; 1169 // } 1170 // 1171 // void main() 1172 // { 1173 // vec4 color1 = texture(sampler2D(t2D, samp), vec2(1.0)); 1174 // vec4 color2 = vec4(foo(BaseColor)); 1175 // vec4 color3 = texture(sampler2D(t2D, samp2), vec2(0.5)); 1176 // FragColor = (color1 + color2 + color3)/3; 1177 // } 1178 // Note: the before SPIR-V will need to be edited to create an OpImage 1179 // and subsequent OpSampledImage that is used across the function call. 1180 const std::vector<const char*> predefs = { 1181 // clang-format off 1182 "OpCapability Shader", 1183 "%1 = OpExtInstImport \"GLSL.std.450\"", 1184 "OpMemoryModel Logical GLSL450", 1185 "OpEntryPoint Fragment %main \"main\" %BaseColor %FragColor", 1186 "OpExecutionMode %main OriginUpperLeft", 1187 "OpSource GLSL 450", 1188 "OpName %main \"main\"", 1189 "OpName %foo_vf4_ \"foo(vf4;\"", 1190 "OpName %bar \"bar\"", 1191 "OpName %r \"r\"", 1192 "OpName %color1 \"color1\"", 1193 "OpName %t2D \"t2D\"", 1194 "OpName %samp \"samp\"", 1195 "OpName %color2 \"color2\"", 1196 "OpName %BaseColor \"BaseColor\"", 1197 "OpName %param \"param\"", 1198 "OpName %color3 \"color3\"", 1199 "OpName %samp2 \"samp2\"", 1200 "OpName %FragColor \"FragColor\"", 1201 "OpDecorate %t2D DescriptorSet 0", 1202 "OpDecorate %samp DescriptorSet 0", 1203 "OpDecorate %samp2 DescriptorSet 0", 1204 "%void = OpTypeVoid", 1205 "%16 = OpTypeFunction %void", 1206 "%float = OpTypeFloat 32", 1207 "%v4float = OpTypeVector %float 4", 1208"%_ptr_Function_v4float = OpTypePointer Function %v4float", 1209 "%20 = OpTypeFunction %float %_ptr_Function_v4float", 1210"%_ptr_Function_float = OpTypePointer Function %float", 1211 "%uint = OpTypeInt 32 0", 1212 "%uint_0 = OpConstant %uint 0", 1213 "%float_0 = OpConstant %float 0", 1214 "%bool = OpTypeBool", 1215 "%26 = OpTypeImage %float 2D 0 0 0 1 Unknown", 1216"%_ptr_UniformConstant_26 = OpTypePointer UniformConstant %26", 1217 "%t2D = OpVariable %_ptr_UniformConstant_26 UniformConstant", 1218 "%28 = OpTypeSampler", 1219"%_ptr_UniformConstant_28 = OpTypePointer UniformConstant %28", 1220 "%samp = OpVariable %_ptr_UniformConstant_28 UniformConstant", 1221 "%30 = OpTypeSampledImage %26", 1222 "%v2float = OpTypeVector %float 2", 1223 "%float_1 = OpConstant %float 1", 1224 "%33 = OpConstantComposite %v2float %float_1 %float_1", 1225"%_ptr_Input_v4float = OpTypePointer Input %v4float", 1226 "%BaseColor = OpVariable %_ptr_Input_v4float Input", 1227 "%samp2 = OpVariable %_ptr_UniformConstant_28 UniformConstant", 1228 "%float_0_5 = OpConstant %float 0.5", 1229 "%36 = OpConstantComposite %v2float %float_0_5 %float_0_5", 1230"%_ptr_Output_v4float = OpTypePointer Output %v4float", 1231 "%FragColor = OpVariable %_ptr_Output_v4float Output", 1232 "%float_3 = OpConstant %float 3", 1233 // clang-format on 1234 }; 1235 1236 const std::vector<const char*> nonEntryFuncs = { 1237 // clang-format off 1238 "%foo_vf4_ = OpFunction %float None %20", 1239 "%bar = OpFunctionParameter %_ptr_Function_v4float", 1240 "%58 = OpLabel", 1241 "%r = OpVariable %_ptr_Function_float Function", 1242 "%59 = OpAccessChain %_ptr_Function_float %bar %uint_0", 1243 "%60 = OpLoad %float %59", 1244 "OpStore %r %60", 1245 "%61 = OpLoad %float %r", 1246 "%62 = OpFOrdLessThan %bool %61 %float_0", 1247 "OpSelectionMerge %63 None", 1248 "OpBranchConditional %62 %64 %63", 1249 "%64 = OpLabel", 1250 "%65 = OpLoad %float %r", 1251 "%66 = OpFNegate %float %65", 1252 "OpStore %r %66", 1253 "OpBranch %63", 1254 "%63 = OpLabel", 1255 "%67 = OpLoad %float %r", 1256 "OpReturnValue %67", 1257 "OpFunctionEnd", 1258 // clang-format on 1259 }; 1260 1261 const std::vector<const char*> before = { 1262 // clang-format off 1263 "%main = OpFunction %void None %16", 1264 "%39 = OpLabel", 1265 "%color1 = OpVariable %_ptr_Function_v4float Function", 1266 "%color2 = OpVariable %_ptr_Function_v4float Function", 1267 "%param = OpVariable %_ptr_Function_v4float Function", 1268 "%color3 = OpVariable %_ptr_Function_v4float Function", 1269 "%40 = OpLoad %26 %t2D", 1270 "%41 = OpLoad %28 %samp", 1271 "%42 = OpSampledImage %30 %40 %41", 1272 "%43 = OpImageSampleImplicitLod %v4float %42 %33", 1273 "%44 = OpImage %26 %42", 1274 "%45 = OpLoad %28 %samp2", 1275 "%46 = OpSampledImage %30 %44 %45", 1276 "OpStore %color1 %43", 1277 "%47 = OpLoad %v4float %BaseColor", 1278 "OpStore %param %47", 1279 "%48 = OpFunctionCall %float %foo_vf4_ %param", 1280 "%49 = OpCompositeConstruct %v4float %48 %48 %48 %48", 1281 "OpStore %color2 %49", 1282 "%50 = OpImageSampleImplicitLod %v4float %46 %36", 1283 "OpStore %color3 %50", 1284 "%51 = OpLoad %v4float %color1", 1285 "%52 = OpLoad %v4float %color2", 1286 "%53 = OpFAdd %v4float %51 %52", 1287 "%54 = OpLoad %v4float %color3", 1288 "%55 = OpFAdd %v4float %53 %54", 1289 "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", 1290 "%57 = OpFDiv %v4float %55 %56", 1291 "OpStore %FragColor %57", 1292 "OpReturn", 1293 "OpFunctionEnd", 1294 // clang-format on 1295 }; 1296 1297 const std::vector<const char*> after = { 1298 // clang-format off 1299 "%main = OpFunction %void None %16", 1300 "%39 = OpLabel", 1301 "%68 = OpVariable %_ptr_Function_float Function", 1302 "%69 = OpVariable %_ptr_Function_float Function", 1303 "%color1 = OpVariable %_ptr_Function_v4float Function", 1304 "%color2 = OpVariable %_ptr_Function_v4float Function", 1305 "%param = OpVariable %_ptr_Function_v4float Function", 1306 "%color3 = OpVariable %_ptr_Function_v4float Function", 1307 "%40 = OpLoad %26 %t2D", 1308 "%41 = OpLoad %28 %samp", 1309 "%42 = OpSampledImage %30 %40 %41", 1310 "%43 = OpImageSampleImplicitLod %v4float %42 %33", 1311 "%44 = OpImage %26 %42", 1312 "%45 = OpLoad %28 %samp2", 1313 "%46 = OpSampledImage %30 %44 %45", 1314 "OpStore %color1 %43", 1315 "%47 = OpLoad %v4float %BaseColor", 1316 "OpStore %param %47", 1317 "%71 = OpAccessChain %_ptr_Function_float %param %uint_0", 1318 "%72 = OpLoad %float %71", 1319 "OpStore %68 %72", 1320 "%73 = OpLoad %float %68", 1321 "%74 = OpFOrdLessThan %bool %73 %float_0", 1322 "OpSelectionMerge %78 None", 1323 "OpBranchConditional %74 %75 %78", 1324 "%75 = OpLabel", 1325 "%76 = OpLoad %float %68", 1326 "%77 = OpFNegate %float %76", 1327 "OpStore %68 %77", 1328 "OpBranch %78", 1329 "%78 = OpLabel", 1330 "%79 = OpLoad %float %68", 1331 "OpStore %69 %79", 1332 "%48 = OpLoad %float %69", 1333 "%49 = OpCompositeConstruct %v4float %48 %48 %48 %48", 1334 "OpStore %color2 %49", 1335 "%80 = OpSampledImage %30 %40 %41", 1336 "%81 = OpImage %26 %80", 1337 "%82 = OpSampledImage %30 %81 %45", 1338 "%50 = OpImageSampleImplicitLod %v4float %82 %36", 1339 "OpStore %color3 %50", 1340 "%51 = OpLoad %v4float %color1", 1341 "%52 = OpLoad %v4float %color2", 1342 "%53 = OpFAdd %v4float %51 %52", 1343 "%54 = OpLoad %v4float %color3", 1344 "%55 = OpFAdd %v4float %53 %54", 1345 "%56 = OpCompositeConstruct %v4float %float_3 %float_3 %float_3 %float_3", 1346 "%57 = OpFDiv %v4float %55 %56", 1347 "OpStore %FragColor %57", 1348 "OpReturn", 1349 "OpFunctionEnd", 1350 // clang-format on 1351 }; 1352 SinglePassRunAndCheck<InlineExhaustivePass>( 1353 JoinAllInsts(Concat(Concat(predefs, before), nonEntryFuncs)), 1354 JoinAllInsts(Concat(Concat(predefs, after), nonEntryFuncs)), 1355 /* skip_nop = */ false, /* do_validate = */ true); 1356} 1357 1358TEST_F(InlineTest, EarlyReturnInLoopIsNotInlined) { 1359 // #version 140 1360 // 1361 // in vec4 BaseColor; 1362 // 1363 // float foo(vec4 bar) 1364 // { 1365 // while (true) { 1366 // if (bar.x < 0.0) 1367 // return 0.0; 1368 // return bar.x; 1369 // } 1370 // } 1371 // 1372 // void main() 1373 // { 1374 // vec4 color = vec4(foo(BaseColor)); 1375 // gl_FragColor = color; 1376 // } 1377 1378 const std::string assembly = 1379 R"(OpCapability Shader 1380%1 = OpExtInstImport "GLSL.std.450" 1381OpMemoryModel Logical GLSL450 1382OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 1383OpExecutionMode %main OriginUpperLeft 1384OpSource GLSL 140 1385OpName %main "main" 1386OpName %foo_vf4_ "foo(vf4;" 1387OpName %bar "bar" 1388OpName %color "color" 1389OpName %BaseColor "BaseColor" 1390OpName %param "param" 1391OpName %gl_FragColor "gl_FragColor" 1392%void = OpTypeVoid 1393%10 = OpTypeFunction %void 1394%float = OpTypeFloat 32 1395%v4float = OpTypeVector %float 4 1396%_ptr_Function_v4float = OpTypePointer Function %v4float 1397%14 = OpTypeFunction %float %_ptr_Function_v4float 1398%bool = OpTypeBool 1399%true = OpConstantTrue %bool 1400%uint = OpTypeInt 32 0 1401%uint_0 = OpConstant %uint 0 1402%_ptr_Function_float = OpTypePointer Function %float 1403%float_0 = OpConstant %float 0 1404%_ptr_Input_v4float = OpTypePointer Input %v4float 1405%BaseColor = OpVariable %_ptr_Input_v4float Input 1406%_ptr_Output_v4float = OpTypePointer Output %v4float 1407%gl_FragColor = OpVariable %_ptr_Output_v4float Output 1408%main = OpFunction %void None %10 1409%23 = OpLabel 1410%color = OpVariable %_ptr_Function_v4float Function 1411%param = OpVariable %_ptr_Function_v4float Function 1412%24 = OpLoad %v4float %BaseColor 1413OpStore %param %24 1414%25 = OpFunctionCall %float %foo_vf4_ %param 1415%26 = OpCompositeConstruct %v4float %25 %25 %25 %25 1416OpStore %color %26 1417%27 = OpLoad %v4float %color 1418OpStore %gl_FragColor %27 1419OpReturn 1420OpFunctionEnd 1421%foo_vf4_ = OpFunction %float None %14 1422%bar = OpFunctionParameter %_ptr_Function_v4float 1423%28 = OpLabel 1424OpBranch %29 1425%29 = OpLabel 1426OpLoopMerge %30 %31 None 1427OpBranch %32 1428%32 = OpLabel 1429OpBranchConditional %true %33 %30 1430%33 = OpLabel 1431%34 = OpAccessChain %_ptr_Function_float %bar %uint_0 1432%35 = OpLoad %float %34 1433%36 = OpFOrdLessThan %bool %35 %float_0 1434OpSelectionMerge %37 None 1435OpBranchConditional %36 %38 %37 1436%38 = OpLabel 1437OpReturnValue %float_0 1438%37 = OpLabel 1439%39 = OpAccessChain %_ptr_Function_float %bar %uint_0 1440%40 = OpLoad %float %39 1441OpReturnValue %40 1442%31 = OpLabel 1443OpBranch %29 1444%30 = OpLabel 1445%41 = OpUndef %float 1446OpReturnValue %41 1447OpFunctionEnd 1448)"; 1449 1450 SinglePassRunAndCheck<InlineExhaustivePass>(assembly, assembly, false, true); 1451} 1452 1453TEST_F(InlineTest, ExternalFunctionIsNotInlined) { 1454 // In particular, don't crash. 1455 // See report https://github.com/KhronosGroup/SPIRV-Tools/issues/605 1456 const std::string assembly = 1457 R"(OpCapability Addresses 1458OpCapability Kernel 1459OpCapability Linkage 1460OpMemoryModel Physical32 OpenCL 1461OpEntryPoint Kernel %1 "entry_pt" 1462OpDecorate %2 LinkageAttributes "external" Import 1463%void = OpTypeVoid 1464%4 = OpTypeFunction %void 1465%2 = OpFunction %void None %4 1466OpFunctionEnd 1467%1 = OpFunction %void None %4 1468%5 = OpLabel 1469%6 = OpFunctionCall %void %2 1470OpReturn 1471OpFunctionEnd 1472)"; 1473 1474 SinglePassRunAndCheck<InlineExhaustivePass>(assembly, assembly, false, true); 1475} 1476 1477TEST_F(InlineTest, SingleBlockLoopCallsMultiBlockCallee) { 1478 // Example from https://github.com/KhronosGroup/SPIRV-Tools/issues/787 1479 // 1480 // CFG structure is: 1481 // foo: 1482 // fooentry -> fooexit 1483 // 1484 // main: 1485 // entry -> loop 1486 // loop -> loop, merge 1487 // loop calls foo() 1488 // merge 1489 // 1490 // Since the callee has multiple blocks, it will split the calling block 1491 // into at least two, resulting in a new "back-half" block that contains 1492 // the instructions after the inlined function call. If the calling block 1493 // has an OpLoopMerge that points back to the calling block itself, then 1494 // the OpLoopMerge can't remain in the back-half block, but must be 1495 // moved to the end of the original calling block, and it continue target 1496 // operand updated to point to the back-half block. 1497 1498 const std::string predefs = 1499 R"(OpCapability Shader 1500OpMemoryModel Logical GLSL450 1501OpEntryPoint GLCompute %1 "main" 1502OpSource OpenCL_C 120 1503%bool = OpTypeBool 1504%true = OpConstantTrue %bool 1505%void = OpTypeVoid 1506%5 = OpTypeFunction %void 1507)"; 1508 1509 const std::string nonEntryFuncs = 1510 R"(%6 = OpFunction %void None %5 1511%7 = OpLabel 1512OpBranch %8 1513%8 = OpLabel 1514OpReturn 1515OpFunctionEnd 1516)"; 1517 1518 const std::string before = 1519 R"(%1 = OpFunction %void None %5 1520%9 = OpLabel 1521OpBranch %10 1522%10 = OpLabel 1523%11 = OpFunctionCall %void %6 1524OpLoopMerge %12 %10 None 1525OpBranchConditional %true %10 %12 1526%12 = OpLabel 1527OpReturn 1528OpFunctionEnd 1529)"; 1530 1531 const std::string after = 1532 R"(%1 = OpFunction %void None %5 1533%9 = OpLabel 1534OpBranch %10 1535%10 = OpLabel 1536OpLoopMerge %12 %15 None 1537OpBranch %14 1538%14 = OpLabel 1539OpBranch %15 1540%15 = OpLabel 1541OpBranchConditional %true %10 %12 1542%12 = OpLabel 1543OpReturn 1544OpFunctionEnd 1545)"; 1546 1547 SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before, 1548 predefs + nonEntryFuncs + after, 1549 false, true); 1550} 1551 1552TEST_F(InlineTest, MultiBlockLoopHeaderCallsMultiBlockCallee) { 1553 // Like SingleBlockLoopCallsMultiBlockCallee but the loop has several 1554 // blocks, but the function call still occurs in the loop header. 1555 // Example from https://github.com/KhronosGroup/SPIRV-Tools/issues/800 1556 1557 const std::string predefs = 1558 R"(OpCapability Shader 1559OpMemoryModel Logical GLSL450 1560OpEntryPoint GLCompute %1 "main" 1561OpSource OpenCL_C 120 1562%bool = OpTypeBool 1563%true = OpConstantTrue %bool 1564%int = OpTypeInt 32 1 1565%int_1 = OpConstant %int 1 1566%int_2 = OpConstant %int 2 1567%int_3 = OpConstant %int 3 1568%int_4 = OpConstant %int 4 1569%int_5 = OpConstant %int 5 1570%void = OpTypeVoid 1571%11 = OpTypeFunction %void 1572)"; 1573 1574 const std::string nonEntryFuncs = 1575 R"(%12 = OpFunction %void None %11 1576%13 = OpLabel 1577%14 = OpCopyObject %int %int_1 1578OpBranch %15 1579%15 = OpLabel 1580%16 = OpCopyObject %int %int_2 1581OpReturn 1582OpFunctionEnd 1583)"; 1584 1585 const std::string before = 1586 R"(%1 = OpFunction %void None %11 1587%17 = OpLabel 1588OpBranch %18 1589%18 = OpLabel 1590%19 = OpCopyObject %int %int_3 1591%20 = OpFunctionCall %void %12 1592%21 = OpCopyObject %int %int_4 1593OpLoopMerge %22 %23 None 1594OpBranchConditional %true %23 %22 1595%23 = OpLabel 1596%24 = OpCopyObject %int %int_5 1597OpBranchConditional %true %18 %22 1598%22 = OpLabel 1599OpReturn 1600OpFunctionEnd 1601)"; 1602 1603 const std::string after = 1604 R"(%1 = OpFunction %void None %11 1605%17 = OpLabel 1606OpBranch %18 1607%18 = OpLabel 1608%19 = OpCopyObject %int %int_3 1609%26 = OpCopyObject %int %int_1 1610OpLoopMerge %22 %23 None 1611OpBranch %27 1612%27 = OpLabel 1613%28 = OpCopyObject %int %int_2 1614%21 = OpCopyObject %int %int_4 1615OpBranchConditional %true %23 %22 1616%23 = OpLabel 1617%24 = OpCopyObject %int %int_5 1618OpBranchConditional %true %18 %22 1619%22 = OpLabel 1620OpReturn 1621OpFunctionEnd 1622)"; 1623 1624 SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before, 1625 predefs + nonEntryFuncs + after, 1626 false, true); 1627} 1628 1629TEST_F(InlineTest, SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge) { 1630 // This is similar to SingleBlockLoopCallsMultiBlockCallee except 1631 // that calleee block also has a merge instruction in its first block. 1632 // That merge instruction must be an OpSelectionMerge (because the entry 1633 // block of a function can't be the header of a loop since the entry 1634 // block can't be the target of a branch). 1635 // 1636 // In this case the OpLoopMerge can't be placed in the same block as 1637 // the OpSelectionMerge, so inlining must create a new block to contain 1638 // the callee contents. 1639 // 1640 // Additionally, we have two extra OpCopyObject instructions to prove that 1641 // the OpLoopMerge is moved to the right location. 1642 // 1643 // Also ensure that OpPhis within the cloned callee code are valid. 1644 // We need to test that the predecessor blocks are remapped correctly so that 1645 // dominance rules are satisfied 1646 1647 const std::string predefs = 1648 R"(OpCapability Shader 1649OpMemoryModel Logical GLSL450 1650OpEntryPoint GLCompute %1 "main" 1651OpSource OpenCL_C 120 1652%bool = OpTypeBool 1653%true = OpConstantTrue %bool 1654%false = OpConstantFalse %bool 1655%void = OpTypeVoid 1656%6 = OpTypeFunction %void 1657)"; 1658 1659 // This callee has multiple blocks, and an OpPhi in the last block 1660 // that references a value from the first block. This tests that 1661 // cloned block IDs are remapped appropriately. The OpPhi dominance 1662 // requires that the remapped %9 must be in a block that dominates 1663 // the remapped %8. 1664 const std::string nonEntryFuncs = 1665 R"(%7 = OpFunction %void None %6 1666%8 = OpLabel 1667%9 = OpCopyObject %bool %true 1668OpSelectionMerge %10 None 1669OpBranchConditional %true %10 %10 1670%10 = OpLabel 1671%11 = OpPhi %bool %9 %8 1672OpReturn 1673OpFunctionEnd 1674)"; 1675 1676 const std::string before = 1677 R"(%1 = OpFunction %void None %6 1678%12 = OpLabel 1679OpBranch %13 1680%13 = OpLabel 1681%14 = OpCopyObject %bool %false 1682%15 = OpFunctionCall %void %7 1683OpLoopMerge %16 %13 None 1684OpBranchConditional %true %13 %16 1685%16 = OpLabel 1686OpReturn 1687OpFunctionEnd 1688)"; 1689 1690 // Note the remapped Phi uses %17 as the parent instead 1691 // of %13, demonstrating that the parent block has been remapped 1692 // correctly. 1693 const std::string after = 1694 R"(%1 = OpFunction %void None %6 1695%12 = OpLabel 1696OpBranch %13 1697%13 = OpLabel 1698%14 = OpCopyObject %bool %false 1699OpLoopMerge %16 %22 None 1700OpBranch %17 1701%17 = OpLabel 1702%19 = OpCopyObject %bool %true 1703OpSelectionMerge %20 None 1704OpBranchConditional %true %20 %20 1705%20 = OpLabel 1706%21 = OpPhi %bool %19 %17 1707OpBranch %22 1708%22 = OpLabel 1709OpBranchConditional %true %13 %16 1710%16 = OpLabel 1711OpReturn 1712OpFunctionEnd 1713)"; 1714 SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before, 1715 predefs + nonEntryFuncs + after, 1716 false, true); 1717} 1718 1719TEST_F(InlineTest, 1720 MultiBlockLoopHeaderCallsFromToMultiBlockCalleeHavingSelectionMerge) { 1721 // This is similar to SingleBlockLoopCallsMultiBlockCalleeHavingSelectionMerge 1722 // but the call is in the header block of a multi block loop. 1723 1724 const std::string predefs = 1725 R"(OpCapability Shader 1726OpMemoryModel Logical GLSL450 1727OpEntryPoint GLCompute %1 "main" 1728OpSource OpenCL_C 120 1729%bool = OpTypeBool 1730%true = OpConstantTrue %bool 1731%int = OpTypeInt 32 1 1732%int_1 = OpConstant %int 1 1733%int_2 = OpConstant %int 2 1734%int_3 = OpConstant %int 3 1735%int_4 = OpConstant %int 4 1736%int_5 = OpConstant %int 5 1737%void = OpTypeVoid 1738%11 = OpTypeFunction %void 1739)"; 1740 1741 const std::string nonEntryFuncs = 1742 R"(%12 = OpFunction %void None %11 1743%13 = OpLabel 1744%14 = OpCopyObject %int %int_1 1745OpSelectionMerge %15 None 1746OpBranchConditional %true %15 %15 1747%15 = OpLabel 1748%16 = OpCopyObject %int %int_2 1749OpReturn 1750OpFunctionEnd 1751)"; 1752 1753 const std::string before = 1754 R"(%1 = OpFunction %void None %11 1755%17 = OpLabel 1756OpBranch %18 1757%18 = OpLabel 1758%19 = OpCopyObject %int %int_3 1759%20 = OpFunctionCall %void %12 1760%21 = OpCopyObject %int %int_4 1761OpLoopMerge %22 %23 None 1762OpBranchConditional %true %23 %22 1763%23 = OpLabel 1764%24 = OpCopyObject %int %int_5 1765OpBranchConditional %true %18 %22 1766%22 = OpLabel 1767OpReturn 1768OpFunctionEnd 1769)"; 1770 1771 const std::string after = 1772 R"(%1 = OpFunction %void None %11 1773%17 = OpLabel 1774OpBranch %18 1775%18 = OpLabel 1776%19 = OpCopyObject %int %int_3 1777OpLoopMerge %22 %23 None 1778OpBranch %25 1779%25 = OpLabel 1780%27 = OpCopyObject %int %int_1 1781OpSelectionMerge %28 None 1782OpBranchConditional %true %28 %28 1783%28 = OpLabel 1784%29 = OpCopyObject %int %int_2 1785%21 = OpCopyObject %int %int_4 1786OpBranchConditional %true %23 %22 1787%23 = OpLabel 1788%24 = OpCopyObject %int %int_5 1789OpBranchConditional %true %18 %22 1790%22 = OpLabel 1791OpReturn 1792OpFunctionEnd 1793)"; 1794 1795 SinglePassRunAndCheck<InlineExhaustivePass>(predefs + nonEntryFuncs + before, 1796 predefs + nonEntryFuncs + after, 1797 false, true); 1798} 1799 1800TEST_F(InlineTest, NonInlinableCalleeWithSingleReturn) { 1801 // The case from https://github.com/KhronosGroup/SPIRV-Tools/issues/2018 1802 // 1803 // The callee has a single return, but cannot be inlined because the 1804 // return is inside a loop. 1805 1806 const std::string predefs = 1807 R"(OpCapability Shader 1808%1 = OpExtInstImport "GLSL.std.450" 1809OpMemoryModel Logical GLSL450 1810OpEntryPoint Fragment %main "main" %_GLF_color 1811OpExecutionMode %main OriginUpperLeft 1812OpSource ESSL 310 1813OpName %main "main" 1814OpName %f_ "f(" 1815OpName %i "i" 1816OpName %_GLF_color "_GLF_color" 1817OpDecorate %_GLF_color Location 0 1818%void = OpTypeVoid 1819%7 = OpTypeFunction %void 1820%float = OpTypeFloat 32 1821%9 = OpTypeFunction %float 1822%float_1 = OpConstant %float 1 1823%bool = OpTypeBool 1824%false = OpConstantFalse %bool 1825%int = OpTypeInt 32 1 1826%_ptr_Function_int = OpTypePointer Function %int 1827%int_0 = OpConstant %int 0 1828%int_1 = OpConstant %int 1 1829%v4float = OpTypeVector %float 4 1830%_ptr_Output_v4float = OpTypePointer Output %v4float 1831%_GLF_color = OpVariable %_ptr_Output_v4float Output 1832%float_0 = OpConstant %float 0 1833%20 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 1834%21 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 1835)"; 1836 1837 const std::string caller = 1838 R"(%main = OpFunction %void None %7 1839%22 = OpLabel 1840%i = OpVariable %_ptr_Function_int Function 1841OpStore %i %int_0 1842OpBranch %23 1843%23 = OpLabel 1844OpLoopMerge %24 %25 None 1845OpBranch %26 1846%26 = OpLabel 1847%27 = OpLoad %int %i 1848%28 = OpSLessThan %bool %27 %int_1 1849OpBranchConditional %28 %29 %24 1850%29 = OpLabel 1851OpStore %_GLF_color %20 1852%30 = OpFunctionCall %float %f_ 1853OpBranch %25 1854%25 = OpLabel 1855%31 = OpLoad %int %i 1856%32 = OpIAdd %int %31 %int_1 1857OpStore %i %32 1858OpBranch %23 1859%24 = OpLabel 1860OpStore %_GLF_color %21 1861OpReturn 1862OpFunctionEnd 1863)"; 1864 1865 const std::string callee = 1866 R"(%f_ = OpFunction %float None %9 1867%33 = OpLabel 1868OpBranch %34 1869%34 = OpLabel 1870OpLoopMerge %35 %36 None 1871OpBranch %37 1872%37 = OpLabel 1873OpReturnValue %float_1 1874%36 = OpLabel 1875OpBranch %34 1876%35 = OpLabel 1877OpUnreachable 1878OpFunctionEnd 1879)"; 1880 1881 SinglePassRunAndCheck<InlineExhaustivePass>( 1882 predefs + caller + callee, predefs + caller + callee, false, true); 1883} 1884 1885TEST_F(InlineTest, Decorated1) { 1886 // Same test as Simple with the difference 1887 // that OpFAdd in the outlined function is 1888 // decorated with RelaxedPrecision 1889 // Expected result is an equal decoration 1890 // of the corresponding inlined instruction 1891 // 1892 // #version 140 1893 // 1894 // in vec4 BaseColor; 1895 // 1896 // float foo(vec4 bar) 1897 // { 1898 // return bar.x + bar.y; 1899 // } 1900 // 1901 // void main() 1902 // { 1903 // vec4 color = vec4(foo(BaseColor)); 1904 // gl_FragColor = color; 1905 // } 1906 1907 const std::string predefs = 1908 R"(OpCapability Shader 1909%1 = OpExtInstImport "GLSL.std.450" 1910OpMemoryModel Logical GLSL450 1911OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 1912OpExecutionMode %main OriginUpperLeft 1913OpSource GLSL 140 1914OpName %main "main" 1915OpName %foo_vf4_ "foo(vf4;" 1916OpName %bar "bar" 1917OpName %color "color" 1918OpName %BaseColor "BaseColor" 1919OpName %param "param" 1920OpName %gl_FragColor "gl_FragColor" 1921OpDecorate %9 RelaxedPrecision 1922)"; 1923 1924 const std::string before = 1925 R"(%void = OpTypeVoid 1926%11 = OpTypeFunction %void 1927%float = OpTypeFloat 32 1928%v4float = OpTypeVector %float 4 1929%_ptr_Function_v4float = OpTypePointer Function %v4float 1930%15 = OpTypeFunction %float %_ptr_Function_v4float 1931%uint = OpTypeInt 32 0 1932%uint_0 = OpConstant %uint 0 1933%_ptr_Function_float = OpTypePointer Function %float 1934%uint_1 = OpConstant %uint 1 1935%_ptr_Input_v4float = OpTypePointer Input %v4float 1936%BaseColor = OpVariable %_ptr_Input_v4float Input 1937%_ptr_Output_v4float = OpTypePointer Output %v4float 1938%gl_FragColor = OpVariable %_ptr_Output_v4float Output 1939%main = OpFunction %void None %11 1940%22 = OpLabel 1941%color = OpVariable %_ptr_Function_v4float Function 1942%param = OpVariable %_ptr_Function_v4float Function 1943%23 = OpLoad %v4float %BaseColor 1944OpStore %param %23 1945%24 = OpFunctionCall %float %foo_vf4_ %param 1946%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 1947OpStore %color %25 1948%26 = OpLoad %v4float %color 1949OpStore %gl_FragColor %26 1950OpReturn 1951OpFunctionEnd 1952)"; 1953 1954 const std::string after = 1955 R"(OpDecorate %38 RelaxedPrecision 1956%void = OpTypeVoid 1957%11 = OpTypeFunction %void 1958%float = OpTypeFloat 32 1959%v4float = OpTypeVector %float 4 1960%_ptr_Function_v4float = OpTypePointer Function %v4float 1961%15 = OpTypeFunction %float %_ptr_Function_v4float 1962%uint = OpTypeInt 32 0 1963%uint_0 = OpConstant %uint 0 1964%_ptr_Function_float = OpTypePointer Function %float 1965%uint_1 = OpConstant %uint 1 1966%_ptr_Input_v4float = OpTypePointer Input %v4float 1967%BaseColor = OpVariable %_ptr_Input_v4float Input 1968%_ptr_Output_v4float = OpTypePointer Output %v4float 1969%gl_FragColor = OpVariable %_ptr_Output_v4float Output 1970%main = OpFunction %void None %11 1971%22 = OpLabel 1972%32 = OpVariable %_ptr_Function_float Function 1973%color = OpVariable %_ptr_Function_v4float Function 1974%param = OpVariable %_ptr_Function_v4float Function 1975%23 = OpLoad %v4float %BaseColor 1976OpStore %param %23 1977%34 = OpAccessChain %_ptr_Function_float %param %uint_0 1978%35 = OpLoad %float %34 1979%36 = OpAccessChain %_ptr_Function_float %param %uint_1 1980%37 = OpLoad %float %36 1981%38 = OpFAdd %float %35 %37 1982OpStore %32 %38 1983%24 = OpLoad %float %32 1984%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 1985OpStore %color %25 1986%26 = OpLoad %v4float %color 1987OpStore %gl_FragColor %26 1988OpReturn 1989OpFunctionEnd 1990)"; 1991 1992 const std::string nonEntryFuncs = 1993 R"(%foo_vf4_ = OpFunction %float None %15 1994%bar = OpFunctionParameter %_ptr_Function_v4float 1995%27 = OpLabel 1996%28 = OpAccessChain %_ptr_Function_float %bar %uint_0 1997%29 = OpLoad %float %28 1998%30 = OpAccessChain %_ptr_Function_float %bar %uint_1 1999%31 = OpLoad %float %30 2000%9 = OpFAdd %float %29 %31 2001OpReturnValue %9 2002OpFunctionEnd 2003)"; 2004 SinglePassRunAndCheck<InlineExhaustivePass>(predefs + before + nonEntryFuncs, 2005 predefs + after + nonEntryFuncs, 2006 false, true); 2007} 2008 2009TEST_F(InlineTest, Decorated2) { 2010 // Same test as Simple with the difference 2011 // that the Result <id> of the outlined OpFunction 2012 // is decorated with RelaxedPrecision 2013 // Expected result is an equal decoration 2014 // of the created return variable 2015 // 2016 // #version 140 2017 // 2018 // in vec4 BaseColor; 2019 // 2020 // float foo(vec4 bar) 2021 // { 2022 // return bar.x + bar.y; 2023 // } 2024 // 2025 // void main() 2026 // { 2027 // vec4 color = vec4(foo(BaseColor)); 2028 // gl_FragColor = color; 2029 // } 2030 2031 const std::string predefs = 2032 R"(OpCapability Shader 2033%1 = OpExtInstImport "GLSL.std.450" 2034OpMemoryModel Logical GLSL450 2035OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 2036OpExecutionMode %main OriginUpperLeft 2037OpSource GLSL 140 2038OpName %main "main" 2039OpName %foo_vf4_ "foo(vf4;" 2040OpName %bar "bar" 2041OpName %color "color" 2042OpName %BaseColor "BaseColor" 2043OpName %param "param" 2044OpName %gl_FragColor "gl_FragColor" 2045OpDecorate %foo_vf4_ RelaxedPrecision 2046)"; 2047 2048 const std::string before = 2049 R"(%void = OpTypeVoid 2050%10 = OpTypeFunction %void 2051%float = OpTypeFloat 32 2052%v4float = OpTypeVector %float 4 2053%_ptr_Function_v4float = OpTypePointer Function %v4float 2054%14 = OpTypeFunction %float %_ptr_Function_v4float 2055%uint = OpTypeInt 32 0 2056%uint_0 = OpConstant %uint 0 2057%_ptr_Function_float = OpTypePointer Function %float 2058%uint_1 = OpConstant %uint 1 2059%_ptr_Input_v4float = OpTypePointer Input %v4float 2060%BaseColor = OpVariable %_ptr_Input_v4float Input 2061%_ptr_Output_v4float = OpTypePointer Output %v4float 2062%gl_FragColor = OpVariable %_ptr_Output_v4float Output 2063%main = OpFunction %void None %10 2064%21 = OpLabel 2065%color = OpVariable %_ptr_Function_v4float Function 2066%param = OpVariable %_ptr_Function_v4float Function 2067%22 = OpLoad %v4float %BaseColor 2068OpStore %param %22 2069%23 = OpFunctionCall %float %foo_vf4_ %param 2070%24 = OpCompositeConstruct %v4float %23 %23 %23 %23 2071OpStore %color %24 2072%25 = OpLoad %v4float %color 2073OpStore %gl_FragColor %25 2074OpReturn 2075OpFunctionEnd 2076)"; 2077 2078 const std::string after = 2079 R"(OpDecorate %32 RelaxedPrecision 2080%void = OpTypeVoid 2081%10 = OpTypeFunction %void 2082%float = OpTypeFloat 32 2083%v4float = OpTypeVector %float 4 2084%_ptr_Function_v4float = OpTypePointer Function %v4float 2085%14 = OpTypeFunction %float %_ptr_Function_v4float 2086%uint = OpTypeInt 32 0 2087%uint_0 = OpConstant %uint 0 2088%_ptr_Function_float = OpTypePointer Function %float 2089%uint_1 = OpConstant %uint 1 2090%_ptr_Input_v4float = OpTypePointer Input %v4float 2091%BaseColor = OpVariable %_ptr_Input_v4float Input 2092%_ptr_Output_v4float = OpTypePointer Output %v4float 2093%gl_FragColor = OpVariable %_ptr_Output_v4float Output 2094%main = OpFunction %void None %10 2095%21 = OpLabel 2096%32 = OpVariable %_ptr_Function_float Function 2097%color = OpVariable %_ptr_Function_v4float Function 2098%param = OpVariable %_ptr_Function_v4float Function 2099%22 = OpLoad %v4float %BaseColor 2100OpStore %param %22 2101%34 = OpAccessChain %_ptr_Function_float %param %uint_0 2102%35 = OpLoad %float %34 2103%36 = OpAccessChain %_ptr_Function_float %param %uint_1 2104%37 = OpLoad %float %36 2105%38 = OpFAdd %float %35 %37 2106OpStore %32 %38 2107%23 = OpLoad %float %32 2108%24 = OpCompositeConstruct %v4float %23 %23 %23 %23 2109OpStore %color %24 2110%25 = OpLoad %v4float %color 2111OpStore %gl_FragColor %25 2112OpReturn 2113OpFunctionEnd 2114)"; 2115 2116 const std::string nonEntryFuncs = 2117 R"(%foo_vf4_ = OpFunction %float None %14 2118%bar = OpFunctionParameter %_ptr_Function_v4float 2119%26 = OpLabel 2120%27 = OpAccessChain %_ptr_Function_float %bar %uint_0 2121%28 = OpLoad %float %27 2122%29 = OpAccessChain %_ptr_Function_float %bar %uint_1 2123%30 = OpLoad %float %29 2124%31 = OpFAdd %float %28 %30 2125OpReturnValue %31 2126OpFunctionEnd 2127)"; 2128 SinglePassRunAndCheck<InlineExhaustivePass>(predefs + before + nonEntryFuncs, 2129 predefs + after + nonEntryFuncs, 2130 false, true); 2131} 2132 2133TEST_F(InlineTest, DeleteName) { 2134 // Test that the name of the result id of the call is deleted. 2135 const std::string before = 2136 R"( 2137 OpCapability Shader 2138 OpMemoryModel Logical GLSL450 2139 OpEntryPoint Vertex %main "main" 2140 OpName %main "main" 2141 OpName %main_entry "main_entry" 2142 OpName %foo_result "foo_result" 2143 OpName %void_fn "void_fn" 2144 OpName %foo "foo" 2145 OpName %foo_entry "foo_entry" 2146 %void = OpTypeVoid 2147 %void_fn = OpTypeFunction %void 2148 %foo = OpFunction %void None %void_fn 2149 %foo_entry = OpLabel 2150 OpReturn 2151 OpFunctionEnd 2152 %main = OpFunction %void None %void_fn 2153 %main_entry = OpLabel 2154 %foo_result = OpFunctionCall %void %foo 2155 OpReturn 2156 OpFunctionEnd 2157)"; 2158 2159 const std::string after = 2160 R"(OpCapability Shader 2161OpMemoryModel Logical GLSL450 2162OpEntryPoint Vertex %main "main" 2163OpName %main "main" 2164OpName %main_entry "main_entry" 2165OpName %void_fn "void_fn" 2166OpName %foo "foo" 2167OpName %foo_entry "foo_entry" 2168%void = OpTypeVoid 2169%void_fn = OpTypeFunction %void 2170%foo = OpFunction %void None %void_fn 2171%foo_entry = OpLabel 2172OpReturn 2173OpFunctionEnd 2174%main = OpFunction %void None %void_fn 2175%main_entry = OpLabel 2176OpReturn 2177OpFunctionEnd 2178)"; 2179 2180 SinglePassRunAndCheck<InlineExhaustivePass>(before, after, false, true); 2181} 2182 2183TEST_F(InlineTest, SetParent) { 2184 // Test that after inlining all basic blocks have the correct parent. 2185 const std::string text = 2186 R"( 2187 OpCapability Shader 2188 OpMemoryModel Logical GLSL450 2189 OpEntryPoint Vertex %main "main" 2190 OpName %main "main" 2191 OpName %main_entry "main_entry" 2192 OpName %foo_result "foo_result" 2193 OpName %void_fn "void_fn" 2194 OpName %foo "foo" 2195 OpName %foo_entry "foo_entry" 2196 %void = OpTypeVoid 2197 %void_fn = OpTypeFunction %void 2198 %foo = OpFunction %void None %void_fn 2199 %foo_entry = OpLabel 2200 OpReturn 2201 OpFunctionEnd 2202 %main = OpFunction %void None %void_fn 2203 %main_entry = OpLabel 2204 %foo_result = OpFunctionCall %void %foo 2205 OpReturn 2206 OpFunctionEnd 2207)"; 2208 2209 std::unique_ptr<IRContext> context = 2210 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 2211 InlineExhaustivePass pass; 2212 pass.Run(context.get()); 2213 2214 for (Function& func : *context->module()) { 2215 for (BasicBlock& bb : func) { 2216 EXPECT_TRUE(bb.GetParent() == &func); 2217 } 2218 } 2219} 2220 2221TEST_F(InlineTest, OpVariableWithInit) { 2222 // Check that there is a store that corresponds to the initializer. This 2223 // test makes sure that is a store to the variable in the loop and before any 2224 // load. 2225 const std::string text = R"( 2226; CHECK: OpFunction 2227; CHECK-NOT: OpFunctionEnd 2228; CHECK: [[var:%\w+]] = OpVariable %_ptr_Function_float Function %float_0 2229; CHECK: OpLoopMerge [[outer_merge:%\w+]] 2230; CHECK-NOT: OpLoad %float [[var]] 2231; CHECK: OpStore [[var]] %float_0 2232; CHECK: OpFunctionEnd 2233 OpCapability Shader 2234 %1 = OpExtInstImport "GLSL.std.450" 2235 OpMemoryModel Logical GLSL450 2236 OpEntryPoint Fragment %main "main" %o 2237 OpExecutionMode %main OriginUpperLeft 2238 OpSource GLSL 450 2239 OpDecorate %o Location 0 2240 %void = OpTypeVoid 2241 %3 = OpTypeFunction %void 2242 %float = OpTypeFloat 32 2243 %7 = OpTypeFunction %float 2244%_ptr_Function_float = OpTypePointer Function %float 2245 %float_0 = OpConstant %float 0 2246 %bool = OpTypeBool 2247 %float_1 = OpConstant %float 1 2248%_ptr_Output_float = OpTypePointer Output %float 2249 %o = OpVariable %_ptr_Output_float Output 2250 %int = OpTypeInt 32 1 2251%_ptr_Function_int = OpTypePointer Function %int 2252%_ptr_Input_int = OpTypePointer Input %int 2253 %int_0 = OpConstant %int 0 2254 %int_1 = OpConstant %int 1 2255 %int_2 = OpConstant %int 2 2256 %main = OpFunction %void None %3 2257 %5 = OpLabel 2258 OpStore %o %float_0 2259 OpBranch %34 2260 %34 = OpLabel 2261 %39 = OpPhi %int %int_0 %5 %47 %37 2262 OpLoopMerge %36 %37 None 2263 OpBranch %38 2264 %38 = OpLabel 2265 %41 = OpSLessThan %bool %39 %int_2 2266 OpBranchConditional %41 %35 %36 2267 %35 = OpLabel 2268 %42 = OpFunctionCall %float %foo_ 2269 %43 = OpLoad %float %o 2270 %44 = OpFAdd %float %43 %42 2271 OpStore %o %44 2272 OpBranch %37 2273 %37 = OpLabel 2274 %47 = OpIAdd %int %39 %int_1 2275 OpBranch %34 2276 %36 = OpLabel 2277 OpReturn 2278 OpFunctionEnd 2279 %foo_ = OpFunction %float None %7 2280 %9 = OpLabel 2281 %n = OpVariable %_ptr_Function_float Function %float_0 2282 %13 = OpLoad %float %n 2283 %15 = OpFOrdEqual %bool %13 %float_0 2284 OpSelectionMerge %17 None 2285 OpBranchConditional %15 %16 %17 2286 %16 = OpLabel 2287 %19 = OpLoad %float %n 2288 %20 = OpFAdd %float %19 %float_1 2289 OpStore %n %20 2290 OpBranch %17 2291 %17 = OpLabel 2292 %21 = OpLoad %float %n 2293 OpReturnValue %21 2294 OpFunctionEnd 2295)"; 2296 2297 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 2298} 2299 2300TEST_F(InlineTest, DontInlineDirectlyRecursiveFunc) { 2301 // Test that the name of the result id of the call is deleted. 2302 const std::string test = 2303 R"(OpCapability Shader 2304OpMemoryModel Logical GLSL450 2305OpEntryPoint Fragment %1 "main" 2306OpExecutionMode %1 OriginUpperLeft 2307%void = OpTypeVoid 2308%4 = OpTypeFunction %void 2309%float = OpTypeFloat 32 2310%_struct_6 = OpTypeStruct %float %float 2311%15 = OpConstantNull %_struct_6 2312%7 = OpTypeFunction %_struct_6 2313%1 = OpFunction %void Pure|Const %4 2314%8 = OpLabel 2315%2 = OpFunctionCall %_struct_6 %9 2316OpKill 2317OpFunctionEnd 2318%9 = OpFunction %_struct_6 None %7 2319%10 = OpLabel 2320%11 = OpFunctionCall %_struct_6 %9 2321OpReturnValue %15 2322OpFunctionEnd 2323)"; 2324 2325 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2326 SinglePassRunAndCheck<InlineExhaustivePass>(test, test, false, true); 2327} 2328 2329TEST_F(InlineTest, DontInlineInDirectlyRecursiveFunc) { 2330 // Test that the name of the result id of the call is deleted. 2331 const std::string test = 2332 R"(OpCapability Shader 2333OpMemoryModel Logical GLSL450 2334OpEntryPoint Fragment %1 "main" 2335OpExecutionMode %1 OriginUpperLeft 2336%void = OpTypeVoid 2337%4 = OpTypeFunction %void 2338%float = OpTypeFloat 32 2339%_struct_6 = OpTypeStruct %float %float 2340%15 = OpConstantNull %_struct_6 2341%7 = OpTypeFunction %_struct_6 2342%1 = OpFunction %void Pure|Const %4 2343%8 = OpLabel 2344%2 = OpFunctionCall %_struct_6 %9 2345OpKill 2346OpFunctionEnd 2347%9 = OpFunction %_struct_6 None %7 2348%10 = OpLabel 2349%11 = OpFunctionCall %_struct_6 %12 2350OpReturnValue %15 2351OpFunctionEnd 2352%12 = OpFunction %_struct_6 None %7 2353%13 = OpLabel 2354%14 = OpFunctionCall %_struct_6 %9 2355OpReturnValue %15 2356OpFunctionEnd 2357)"; 2358 2359 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2360 SinglePassRunAndCheck<InlineExhaustivePass>(test, test, false, true); 2361} 2362 2363TEST_F(InlineTest, DontInlineFuncWithOpKillInContinue) { 2364 const std::string test = 2365 R"(OpCapability Shader 2366%1 = OpExtInstImport "GLSL.std.450" 2367OpMemoryModel Logical GLSL450 2368OpEntryPoint Fragment %main "main" 2369OpExecutionMode %main OriginUpperLeft 2370OpSource GLSL 330 2371OpName %main "main" 2372OpName %kill_ "kill(" 2373%void = OpTypeVoid 2374%3 = OpTypeFunction %void 2375%bool = OpTypeBool 2376%true = OpConstantTrue %bool 2377%main = OpFunction %void None %3 2378%5 = OpLabel 2379OpBranch %9 2380%9 = OpLabel 2381OpLoopMerge %11 %12 None 2382OpBranch %13 2383%13 = OpLabel 2384OpBranchConditional %true %10 %11 2385%10 = OpLabel 2386OpBranch %12 2387%12 = OpLabel 2388%16 = OpFunctionCall %void %kill_ 2389OpBranch %9 2390%11 = OpLabel 2391OpReturn 2392OpFunctionEnd 2393%kill_ = OpFunction %void None %3 2394%7 = OpLabel 2395OpKill 2396OpFunctionEnd 2397)"; 2398 2399 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2400 SinglePassRunAndCheck<InlineExhaustivePass>(test, test, false, true); 2401} 2402 2403TEST_F(InlineTest, DontInlineFuncWithDontInline) { 2404 // Check that the function with DontInline flag is not inlined. 2405 const std::string text = R"( 2406; CHECK: %foo = OpFunction %int DontInline 2407; CHECK: OpReturnValue %int_0 2408 2409OpCapability Shader 2410OpMemoryModel Logical GLSL450 2411OpEntryPoint Fragment %main "main" 2412OpExecutionMode %main OriginUpperLeft 2413OpSource HLSL 600 2414OpName %main "main" 2415OpName %foo "foo" 2416%int = OpTypeInt 32 1 2417%int_0 = OpConstant %int 0 2418%void = OpTypeVoid 2419%6 = OpTypeFunction %void 2420%7 = OpTypeFunction %int 2421%main = OpFunction %void None %6 2422%8 = OpLabel 2423%9 = OpFunctionCall %int %foo 2424OpReturn 2425OpFunctionEnd 2426%foo = OpFunction %int DontInline %7 2427%10 = OpLabel 2428OpReturnValue %int_0 2429OpFunctionEnd 2430)"; 2431 2432 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 2433} 2434 2435TEST_F(InlineTest, InlineFuncWithOpKillNotInContinue) { 2436 const std::string before = 2437 R"(OpCapability Shader 2438%1 = OpExtInstImport "GLSL.std.450" 2439OpMemoryModel Logical GLSL450 2440OpEntryPoint Fragment %main "main" 2441OpExecutionMode %main OriginUpperLeft 2442OpSource GLSL 330 2443OpName %main "main" 2444OpName %kill_ "kill(" 2445%void = OpTypeVoid 2446%3 = OpTypeFunction %void 2447%bool = OpTypeBool 2448%true = OpConstantTrue %bool 2449%main = OpFunction %void None %3 2450%5 = OpLabel 2451%16 = OpFunctionCall %void %kill_ 2452OpReturn 2453OpFunctionEnd 2454%kill_ = OpFunction %void None %3 2455%7 = OpLabel 2456OpKill 2457OpFunctionEnd 2458)"; 2459 2460 const std::string after = 2461 R"(OpCapability Shader 2462%1 = OpExtInstImport "GLSL.std.450" 2463OpMemoryModel Logical GLSL450 2464OpEntryPoint Fragment %main "main" 2465OpExecutionMode %main OriginUpperLeft 2466OpSource GLSL 330 2467OpName %main "main" 2468OpName %kill_ "kill(" 2469%void = OpTypeVoid 2470%3 = OpTypeFunction %void 2471%bool = OpTypeBool 2472%true = OpConstantTrue %bool 2473%main = OpFunction %void None %3 2474%5 = OpLabel 2475OpKill 2476%18 = OpLabel 2477OpReturn 2478OpFunctionEnd 2479%kill_ = OpFunction %void None %3 2480%7 = OpLabel 2481OpKill 2482OpFunctionEnd 2483)"; 2484 2485 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2486 SinglePassRunAndCheck<InlineExhaustivePass>(before, after, false, true); 2487} 2488 2489TEST_F(InlineTest, DontInlineFuncWithOpTerminateInvocationInContinue) { 2490 const std::string test = 2491 R"(OpCapability Shader 2492OpExtension "SPV_KHR_terminate_invocation" 2493%1 = OpExtInstImport "GLSL.std.450" 2494OpMemoryModel Logical GLSL450 2495OpEntryPoint Fragment %main "main" 2496OpExecutionMode %main OriginUpperLeft 2497OpSource GLSL 330 2498OpName %main "main" 2499OpName %kill_ "kill(" 2500%void = OpTypeVoid 2501%3 = OpTypeFunction %void 2502%bool = OpTypeBool 2503%true = OpConstantTrue %bool 2504%main = OpFunction %void None %3 2505%5 = OpLabel 2506OpBranch %9 2507%9 = OpLabel 2508OpLoopMerge %11 %12 None 2509OpBranch %13 2510%13 = OpLabel 2511OpBranchConditional %true %10 %11 2512%10 = OpLabel 2513OpBranch %12 2514%12 = OpLabel 2515%16 = OpFunctionCall %void %kill_ 2516OpBranch %9 2517%11 = OpLabel 2518OpReturn 2519OpFunctionEnd 2520%kill_ = OpFunction %void None %3 2521%7 = OpLabel 2522OpTerminateInvocation 2523OpFunctionEnd 2524)"; 2525 2526 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2527 SinglePassRunAndCheck<InlineExhaustivePass>(test, test, false, true); 2528} 2529 2530TEST_F(InlineTest, InlineFuncWithOpTerminateInvocationNotInContinue) { 2531 const std::string before = 2532 R"(OpCapability Shader 2533OpExtension "SPV_KHR_terminate_invocation" 2534%1 = OpExtInstImport "GLSL.std.450" 2535OpMemoryModel Logical GLSL450 2536OpEntryPoint Fragment %main "main" 2537OpExecutionMode %main OriginUpperLeft 2538OpSource GLSL 330 2539OpName %main "main" 2540OpName %kill_ "kill(" 2541%void = OpTypeVoid 2542%3 = OpTypeFunction %void 2543%bool = OpTypeBool 2544%true = OpConstantTrue %bool 2545%main = OpFunction %void None %3 2546%5 = OpLabel 2547%16 = OpFunctionCall %void %kill_ 2548OpReturn 2549OpFunctionEnd 2550%kill_ = OpFunction %void None %3 2551%7 = OpLabel 2552OpTerminateInvocation 2553OpFunctionEnd 2554)"; 2555 2556 const std::string after = 2557 R"(OpCapability Shader 2558OpExtension "SPV_KHR_terminate_invocation" 2559%1 = OpExtInstImport "GLSL.std.450" 2560OpMemoryModel Logical GLSL450 2561OpEntryPoint Fragment %main "main" 2562OpExecutionMode %main OriginUpperLeft 2563OpSource GLSL 330 2564OpName %main "main" 2565OpName %kill_ "kill(" 2566%void = OpTypeVoid 2567%3 = OpTypeFunction %void 2568%bool = OpTypeBool 2569%true = OpConstantTrue %bool 2570%main = OpFunction %void None %3 2571%5 = OpLabel 2572OpTerminateInvocation 2573%18 = OpLabel 2574OpReturn 2575OpFunctionEnd 2576%kill_ = OpFunction %void None %3 2577%7 = OpLabel 2578OpTerminateInvocation 2579OpFunctionEnd 2580)"; 2581 2582 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2583 SinglePassRunAndCheck<InlineExhaustivePass>(before, after, false, true); 2584} 2585 2586TEST_F(InlineTest, InlineForLinkage) { 2587 const std::string before = 2588 R"(OpCapability SampledBuffer 2589OpCapability ImageBuffer 2590OpCapability Shader 2591OpCapability Linkage 2592OpMemoryModel Logical GLSL450 2593OpSource HLSL 630 2594OpName %type_buffer_image "type.buffer.image" 2595OpName %output "output" 2596OpName %main "main" 2597OpName %color "color" 2598OpName %bb_entry "bb.entry" 2599OpName %param_var_color "param.var.color" 2600OpName %fn "fn" 2601OpName %color_0 "color" 2602OpName %bb_entry_0 "bb.entry" 2603OpName %v "v" 2604OpDecorate %main LinkageAttributes "main" Export 2605OpDecorate %output DescriptorSet 0 2606OpDecorate %output Binding 1 2607%float = OpTypeFloat 32 2608%float_0_200000003 = OpConstant %float 0.200000003 2609%v4float = OpTypeVector %float 4 2610%6 = OpConstantComposite %v4float %float_0_200000003 %float_0_200000003 %float_0_200000003 %float_0_200000003 2611%int = OpTypeInt 32 1 2612%int_0 = OpConstant %int 0 2613%type_buffer_image = OpTypeImage %float Buffer 2 0 0 2 Rgba32f 2614%_ptr_UniformConstant_type_buffer_image = OpTypePointer UniformConstant %type_buffer_image 2615%_ptr_Function_v4float = OpTypePointer Function %v4float 2616%11 = OpTypeFunction %float %_ptr_Function_v4float 2617%_ptr_Function_float = OpTypePointer Function %float 2618%output = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant 2619%main = OpFunction %float None %11 2620%color = OpFunctionParameter %_ptr_Function_v4float 2621%bb_entry = OpLabel 2622%param_var_color = OpVariable %_ptr_Function_v4float Function 2623%16 = OpLoad %v4float %color 2624OpStore %param_var_color %16 2625%17 = OpFunctionCall %float %fn %param_var_color 2626OpReturnValue %17 2627OpFunctionEnd 2628%fn = OpFunction %float None %11 2629%color_0 = OpFunctionParameter %_ptr_Function_v4float 2630%bb_entry_0 = OpLabel 2631%v = OpVariable %_ptr_Function_v4float Function 2632%22 = OpLoad %v4float %color_0 2633OpStore %v %22 2634%23 = OpLoad %v4float %v 2635%24 = OpFMul %v4float %23 %6 2636OpStore %v %24 2637%26 = OpAccessChain %_ptr_Function_float %v %int_0 2638%27 = OpLoad %float %26 2639OpReturnValue %27 2640OpFunctionEnd 2641 )"; 2642 2643 const std::string after = 2644 R"(OpCapability SampledBuffer 2645OpCapability ImageBuffer 2646OpCapability Shader 2647OpCapability Linkage 2648OpMemoryModel Logical GLSL450 2649OpSource HLSL 630 2650OpName %type_buffer_image "type.buffer.image" 2651OpName %output "output" 2652OpName %main "main" 2653OpName %color "color" 2654OpName %bb_entry "bb.entry" 2655OpName %param_var_color "param.var.color" 2656OpName %fn "fn" 2657OpName %color_0 "color" 2658OpName %bb_entry_0 "bb.entry" 2659OpName %v "v" 2660OpDecorate %main LinkageAttributes "main" Export 2661OpDecorate %output DescriptorSet 0 2662OpDecorate %output Binding 1 2663%float = OpTypeFloat 32 2664%float_0_200000003 = OpConstant %float 0.200000003 2665%v4float = OpTypeVector %float 4 2666%6 = OpConstantComposite %v4float %float_0_200000003 %float_0_200000003 %float_0_200000003 %float_0_200000003 2667%int = OpTypeInt 32 1 2668%int_0 = OpConstant %int 0 2669%type_buffer_image = OpTypeImage %float Buffer 2 0 0 2 Rgba32f 2670%_ptr_UniformConstant_type_buffer_image = OpTypePointer UniformConstant %type_buffer_image 2671%_ptr_Function_v4float = OpTypePointer Function %v4float 2672%11 = OpTypeFunction %float %_ptr_Function_v4float 2673%_ptr_Function_float = OpTypePointer Function %float 2674%output = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant 2675%main = OpFunction %float None %11 2676%color = OpFunctionParameter %_ptr_Function_v4float 2677%bb_entry = OpLabel 2678%28 = OpVariable %_ptr_Function_v4float Function 2679%29 = OpVariable %_ptr_Function_float Function 2680%param_var_color = OpVariable %_ptr_Function_v4float Function 2681%16 = OpLoad %v4float %color 2682OpStore %param_var_color %16 2683%31 = OpLoad %v4float %param_var_color 2684OpStore %28 %31 2685%32 = OpLoad %v4float %28 2686%33 = OpFMul %v4float %32 %6 2687OpStore %28 %33 2688%34 = OpAccessChain %_ptr_Function_float %28 %int_0 2689%35 = OpLoad %float %34 2690OpStore %29 %35 2691%17 = OpLoad %float %29 2692OpReturnValue %17 2693OpFunctionEnd 2694%fn = OpFunction %float None %11 2695%color_0 = OpFunctionParameter %_ptr_Function_v4float 2696%bb_entry_0 = OpLabel 2697%v = OpVariable %_ptr_Function_v4float Function 2698%22 = OpLoad %v4float %color_0 2699OpStore %v %22 2700%23 = OpLoad %v4float %v 2701%24 = OpFMul %v4float %23 %6 2702OpStore %v %24 2703%26 = OpAccessChain %_ptr_Function_float %v %int_0 2704%27 = OpLoad %float %26 2705OpReturnValue %27 2706OpFunctionEnd 2707)"; 2708 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2709 SinglePassRunAndCheck<InlineExhaustivePass>(before, after, false, true); 2710} 2711 2712TEST_F(InlineTest, InlineFuncWithOpTerminateRayNotInContinue) { 2713 const std::string text = 2714 R"( 2715 OpCapability RayTracingKHR 2716 OpExtension "SPV_KHR_ray_tracing" 2717 OpMemoryModel Logical GLSL450 2718 OpEntryPoint AnyHitKHR %MyAHitMain2 "MyAHitMain2" %a 2719 OpSource HLSL 630 2720 OpName %a "a" 2721 OpName %MyAHitMain2 "MyAHitMain2" 2722 OpName %param_var_a "param.var.a" 2723 OpName %src_MyAHitMain2 "src.MyAHitMain2" 2724 OpName %a_0 "a" 2725 OpName %bb_entry "bb.entry" 2726 %int = OpTypeInt 32 1 2727%_ptr_IncomingRayPayloadKHR_int = OpTypePointer IncomingRayPayloadKHR %int 2728 %void = OpTypeVoid 2729 %6 = OpTypeFunction %void 2730%_ptr_Function_int = OpTypePointer Function %int 2731 %14 = OpTypeFunction %void %_ptr_Function_int 2732 %a = OpVariable %_ptr_IncomingRayPayloadKHR_int IncomingRayPayloadKHR 2733%MyAHitMain2 = OpFunction %void None %6 2734 %7 = OpLabel 2735%param_var_a = OpVariable %_ptr_Function_int Function 2736 %10 = OpLoad %int %a 2737 OpStore %param_var_a %10 2738 %11 = OpFunctionCall %void %src_MyAHitMain2 %param_var_a 2739 %13 = OpLoad %int %param_var_a 2740 OpStore %a %13 2741 OpReturn 2742 OpFunctionEnd 2743%src_MyAHitMain2 = OpFunction %void None %14 2744 %a_0 = OpFunctionParameter %_ptr_Function_int 2745 %bb_entry = OpLabel 2746 %17 = OpLoad %int %a_0 2747 OpStore %a %17 2748 OpTerminateRayKHR 2749 OpFunctionEnd 2750 2751; CHECK: %MyAHitMain2 = OpFunction %void None 2752; CHECK-NEXT: OpLabel 2753; CHECK-NEXT: %param_var_a = OpVariable %_ptr_Function_int Function 2754; CHECK-NEXT: OpLoad %int %a 2755; CHECK-NEXT: OpStore %param_var_a {{%\d+}} 2756; CHECK-NEXT: OpLoad %int %param_var_a 2757; CHECK-NEXT: OpStore %a {{%\d+}} 2758; CHECK-NEXT: OpTerminateRayKHR 2759; CHECK-NEXT: OpLabel 2760; CHECK-NEXT: OpLoad %int %param_var_a 2761; CHECK-NEXT: OpStore %a %16 2762; CHECK-NEXT: OpReturn 2763; CHECK-NEXT: OpFunctionEnd 2764)"; 2765 2766 SinglePassRunAndMatch<InlineExhaustivePass>(text, false); 2767} 2768 2769TEST_F(InlineTest, EarlyReturnFunctionInlined) { 2770 // #version 140 2771 // 2772 // in vec4 BaseColor; 2773 // 2774 // float foo(vec4 bar) 2775 // { 2776 // if (bar.x < 0.0) 2777 // return 0.0; 2778 // return bar.x; 2779 // } 2780 // 2781 // void main() 2782 // { 2783 // vec4 color = vec4(foo(BaseColor)); 2784 // gl_FragColor = color; 2785 // } 2786 2787 const std::string predefs = 2788 R"(OpCapability Shader 2789%1 = OpExtInstImport "GLSL.std.450" 2790OpMemoryModel Logical GLSL450 2791OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 2792OpExecutionMode %main OriginUpperLeft 2793OpSource GLSL 140 2794OpName %main "main" 2795OpName %foo_vf4_ "foo(vf4;" 2796OpName %bar "bar" 2797OpName %color "color" 2798OpName %BaseColor "BaseColor" 2799OpName %param "param" 2800OpName %gl_FragColor "gl_FragColor" 2801%void = OpTypeVoid 2802%10 = OpTypeFunction %void 2803%float = OpTypeFloat 32 2804%v4float = OpTypeVector %float 4 2805%_ptr_Function_v4float = OpTypePointer Function %v4float 2806%14 = OpTypeFunction %float %_ptr_Function_v4float 2807%uint = OpTypeInt 32 0 2808%uint_0 = OpConstant %uint 0 2809%_ptr_Function_float = OpTypePointer Function %float 2810%float_0 = OpConstant %float 0 2811%bool = OpTypeBool 2812%_ptr_Input_v4float = OpTypePointer Input %v4float 2813%BaseColor = OpVariable %_ptr_Input_v4float Input 2814%_ptr_Output_v4float = OpTypePointer Output %v4float 2815%gl_FragColor = OpVariable %_ptr_Output_v4float Output 2816)"; 2817 2818 const std::string foo = 2819 R"(%foo_vf4_ = OpFunction %float None %14 2820%bar = OpFunctionParameter %_ptr_Function_v4float 2821%27 = OpLabel 2822%28 = OpAccessChain %_ptr_Function_float %bar %uint_0 2823%29 = OpLoad %float %28 2824%30 = OpFOrdLessThan %bool %29 %float_0 2825OpSelectionMerge %31 None 2826OpBranchConditional %30 %32 %31 2827%32 = OpLabel 2828OpReturnValue %float_0 2829%31 = OpLabel 2830%33 = OpAccessChain %_ptr_Function_float %bar %uint_0 2831%34 = OpLoad %float %33 2832OpReturnValue %34 2833OpFunctionEnd 2834)"; 2835 2836 const std::string fooMergeReturn = 2837 R"(%foo_vf4_ = OpFunction %float None %14 2838%bar = OpFunctionParameter %_ptr_Function_v4float 2839%27 = OpLabel 2840%41 = OpVariable %_ptr_Function_bool Function %false 2841%36 = OpVariable %_ptr_Function_float Function 2842OpSelectionMerge %35 None 2843OpSwitch %uint_0 %38 2844%38 = OpLabel 2845%28 = OpAccessChain %_ptr_Function_float %bar %uint_0 2846%29 = OpLoad %float %28 2847%30 = OpFOrdLessThan %bool %29 %float_0 2848OpSelectionMerge %31 None 2849OpBranchConditional %30 %32 %31 2850%32 = OpLabel 2851OpStore %41 %true 2852OpStore %36 %float_0 2853OpBranch %35 2854%31 = OpLabel 2855%33 = OpAccessChain %_ptr_Function_float %bar %uint_0 2856%34 = OpLoad %float %33 2857OpStore %41 %true 2858OpStore %36 %34 2859OpBranch %35 2860%35 = OpLabel 2861%37 = OpLoad %float %36 2862OpReturnValue %37 2863OpFunctionEnd 2864)"; 2865 2866 const std::string before = 2867 R"(%main = OpFunction %void None %10 2868%22 = OpLabel 2869%color = OpVariable %_ptr_Function_v4float Function 2870%param = OpVariable %_ptr_Function_v4float Function 2871%23 = OpLoad %v4float %BaseColor 2872OpStore %param %23 2873%24 = OpFunctionCall %float %foo_vf4_ %param 2874%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 2875OpStore %color %25 2876%26 = OpLoad %v4float %color 2877OpStore %gl_FragColor %26 2878OpReturn 2879OpFunctionEnd 2880)"; 2881 2882 const std::string after = 2883 R"(%false = OpConstantFalse %bool 2884%_ptr_Function_bool = OpTypePointer Function %bool 2885%true = OpConstantTrue %bool 2886%main = OpFunction %void None %10 2887%22 = OpLabel 2888%43 = OpVariable %_ptr_Function_bool Function %false 2889%44 = OpVariable %_ptr_Function_float Function 2890%45 = OpVariable %_ptr_Function_float Function 2891%color = OpVariable %_ptr_Function_v4float Function 2892%param = OpVariable %_ptr_Function_v4float Function 2893%23 = OpLoad %v4float %BaseColor 2894OpStore %param %23 2895OpStore %43 %false 2896OpSelectionMerge %55 None 2897OpSwitch %uint_0 %47 2898%47 = OpLabel 2899%48 = OpAccessChain %_ptr_Function_float %param %uint_0 2900%49 = OpLoad %float %48 2901%50 = OpFOrdLessThan %bool %49 %float_0 2902OpSelectionMerge %52 None 2903OpBranchConditional %50 %51 %52 2904%51 = OpLabel 2905OpStore %43 %true 2906OpStore %44 %float_0 2907OpBranch %55 2908%52 = OpLabel 2909%53 = OpAccessChain %_ptr_Function_float %param %uint_0 2910%54 = OpLoad %float %53 2911OpStore %43 %true 2912OpStore %44 %54 2913OpBranch %55 2914%55 = OpLabel 2915%56 = OpLoad %float %44 2916OpStore %45 %56 2917%24 = OpLoad %float %45 2918%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 2919OpStore %color %25 2920%26 = OpLoad %v4float %color 2921OpStore %gl_FragColor %26 2922OpReturn 2923OpFunctionEnd 2924)"; 2925 2926 // The early return case must be handled by merge-return first. 2927 AddPass<MergeReturnPass>(); 2928 AddPass<InlineExhaustivePass>(); 2929 RunAndCheck(predefs + before + foo, predefs + after + fooMergeReturn); 2930} 2931 2932TEST_F(InlineTest, EarlyReturnNotAppearingLastInFunctionInlined) { 2933 // Example from https://github.com/KhronosGroup/SPIRV-Tools/issues/755 2934 // 2935 // Original example is derived from: 2936 // 2937 // #version 450 2938 // 2939 // float foo() { 2940 // if (true) { 2941 // } 2942 // } 2943 // 2944 // void main() { foo(); } 2945 // 2946 // But the order of basic blocks in foo is changed so that the return 2947 // block is listed second-last. There is only one return in the callee 2948 // but it does not appear last. 2949 2950 const std::string predefs = 2951 R"(OpCapability Shader 2952OpMemoryModel Logical GLSL450 2953OpEntryPoint Vertex %main "main" 2954OpSource GLSL 450 2955OpName %main "main" 2956OpName %foo_ "foo(" 2957%void = OpTypeVoid 2958%4 = OpTypeFunction %void 2959%bool = OpTypeBool 2960%true = OpConstantTrue %bool 2961)"; 2962 2963 const std::string foo = 2964 R"(%foo_ = OpFunction %void None %4 2965%7 = OpLabel 2966OpSelectionMerge %8 None 2967OpBranchConditional %true %9 %8 2968%8 = OpLabel 2969OpReturn 2970%9 = OpLabel 2971OpBranch %8 2972OpFunctionEnd 2973)"; 2974 2975 const std::string fooMergeReturn = 2976 R"(%uint = OpTypeInt 32 0 2977%uint_0 = OpConstant %uint 0 2978%false = OpConstantFalse %bool 2979%_ptr_Function_bool = OpTypePointer Function %bool 2980%foo_ = OpFunction %void None %4 2981%7 = OpLabel 2982%18 = OpVariable %_ptr_Function_bool Function %false 2983OpSelectionMerge %12 None 2984OpSwitch %uint_0 %13 2985%13 = OpLabel 2986OpSelectionMerge %8 None 2987OpBranchConditional %true %9 %8 2988%8 = OpLabel 2989OpStore %18 %true 2990OpBranch %12 2991%9 = OpLabel 2992OpBranch %8 2993%12 = OpLabel 2994OpReturn 2995OpFunctionEnd 2996)"; 2997 2998 const std::string before = 2999 R"(%main = OpFunction %void None %4 3000%10 = OpLabel 3001%11 = OpFunctionCall %void %foo_ 3002OpReturn 3003OpFunctionEnd 3004)"; 3005 3006 const std::string after = 3007 R"(%main = OpFunction %void None %4 3008%10 = OpLabel 3009%19 = OpVariable %_ptr_Function_bool Function %false 3010OpStore %19 %false 3011OpSelectionMerge %24 None 3012OpSwitch %uint_0 %21 3013%21 = OpLabel 3014OpSelectionMerge %22 None 3015OpBranchConditional %true %23 %22 3016%22 = OpLabel 3017OpStore %19 %true 3018OpBranch %24 3019%23 = OpLabel 3020OpBranch %22 3021%24 = OpLabel 3022OpReturn 3023OpFunctionEnd 3024)"; 3025 3026 // The early return case must be handled by merge-return first. 3027 AddPass<MergeReturnPass>(); 3028 AddPass<InlineExhaustivePass>(); 3029 RunAndCheck(predefs + foo + before, predefs + fooMergeReturn + after); 3030} 3031 3032TEST_F(InlineTest, CalleeWithSingleReturnNeedsSingleTripLoopWrapper) { 3033 // The case from https://github.com/KhronosGroup/SPIRV-Tools/issues/2018 3034 // 3035 // The callee has a single return, but needs single-trip loop wrapper 3036 // to be inlined because the return is in a selection structure. 3037 3038 const std::string predefs = 3039 R"(OpCapability Shader 3040%1 = OpExtInstImport "GLSL.std.450" 3041OpMemoryModel Logical GLSL450 3042OpEntryPoint Fragment %main "main" %_GLF_color 3043OpExecutionMode %main OriginUpperLeft 3044OpSource ESSL 310 3045OpName %main "main" 3046OpName %f_ "f(" 3047OpName %i "i" 3048OpName %_GLF_color "_GLF_color" 3049OpDecorate %_GLF_color Location 0 3050%void = OpTypeVoid 3051%7 = OpTypeFunction %void 3052%float = OpTypeFloat 32 3053%9 = OpTypeFunction %float 3054%float_1 = OpConstant %float 1 3055%bool = OpTypeBool 3056%false = OpConstantFalse %bool 3057%true = OpConstantTrue %bool 3058%int = OpTypeInt 32 1 3059%_ptr_Function_int = OpTypePointer Function %int 3060%int_0 = OpConstant %int 0 3061%int_1 = OpConstant %int 1 3062%v4float = OpTypeVector %float 4 3063%_ptr_Output_v4float = OpTypePointer Output %v4float 3064%_GLF_color = OpVariable %_ptr_Output_v4float Output 3065%float_0 = OpConstant %float 0 3066%21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 3067%22 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 3068)"; 3069 3070 const std::string new_predefs = 3071 R"(%_ptr_Function_float = OpTypePointer Function %float 3072%uint = OpTypeInt 32 0 3073%uint_0 = OpConstant %uint 0 3074%_ptr_Function_bool = OpTypePointer Function %bool 3075)"; 3076 3077 const std::string main_before = 3078 R"(%main = OpFunction %void None %7 3079%23 = OpLabel 3080%i = OpVariable %_ptr_Function_int Function 3081OpStore %i %int_0 3082OpBranch %24 3083%24 = OpLabel 3084OpLoopMerge %25 %26 None 3085OpBranch %27 3086%27 = OpLabel 3087%28 = OpLoad %int %i 3088%29 = OpSLessThan %bool %28 %int_1 3089OpBranchConditional %29 %30 %25 3090%30 = OpLabel 3091OpStore %_GLF_color %21 3092%31 = OpFunctionCall %float %f_ 3093OpBranch %26 3094%26 = OpLabel 3095%32 = OpLoad %int %i 3096%33 = OpIAdd %int %32 %int_1 3097OpStore %i %33 3098OpBranch %24 3099%25 = OpLabel 3100OpStore %_GLF_color %22 3101OpReturn 3102OpFunctionEnd 3103)"; 3104 3105 const std::string main_after = 3106 R"(%main = OpFunction %void None %7 3107%23 = OpLabel 3108%46 = OpVariable %_ptr_Function_bool Function %false 3109%47 = OpVariable %_ptr_Function_float Function 3110%48 = OpVariable %_ptr_Function_float Function 3111%i = OpVariable %_ptr_Function_int Function 3112OpStore %i %int_0 3113OpBranch %24 3114%24 = OpLabel 3115OpLoopMerge %25 %26 None 3116OpBranch %27 3117%27 = OpLabel 3118%28 = OpLoad %int %i 3119%29 = OpSLessThan %bool %28 %int_1 3120OpBranchConditional %29 %30 %25 3121%30 = OpLabel 3122OpStore %_GLF_color %21 3123OpStore %46 %false 3124OpSelectionMerge %53 None 3125OpSwitch %uint_0 %50 3126%50 = OpLabel 3127OpSelectionMerge %52 None 3128OpBranchConditional %true %51 %52 3129%51 = OpLabel 3130OpStore %46 %true 3131OpStore %47 %float_1 3132OpBranch %53 3133%52 = OpLabel 3134OpStore %46 %true 3135OpStore %47 %float_1 3136OpBranch %53 3137%53 = OpLabel 3138%54 = OpLoad %float %47 3139OpStore %48 %54 3140%31 = OpLoad %float %48 3141OpBranch %26 3142%26 = OpLabel 3143%32 = OpLoad %int %i 3144%33 = OpIAdd %int %32 %int_1 3145OpStore %i %33 3146OpBranch %24 3147%25 = OpLabel 3148OpStore %_GLF_color %22 3149OpReturn 3150OpFunctionEnd 3151)"; 3152 3153 const std::string callee = 3154 R"(%f_ = OpFunction %float None %9 3155%34 = OpLabel 3156OpSelectionMerge %35 None 3157OpBranchConditional %true %36 %35 3158%36 = OpLabel 3159OpReturnValue %float_1 3160%35 = OpLabel 3161OpReturnValue %float_1 3162OpFunctionEnd 3163)"; 3164 3165 const std::string calleeMergeReturn = 3166 R"(%f_ = OpFunction %float None %9 3167%34 = OpLabel 3168%45 = OpVariable %_ptr_Function_bool Function %false 3169%39 = OpVariable %_ptr_Function_float Function 3170OpSelectionMerge %37 None 3171OpSwitch %uint_0 %41 3172%41 = OpLabel 3173OpSelectionMerge %35 None 3174OpBranchConditional %true %36 %35 3175%36 = OpLabel 3176OpStore %45 %true 3177OpStore %39 %float_1 3178OpBranch %37 3179%35 = OpLabel 3180OpStore %45 %true 3181OpStore %39 %float_1 3182OpBranch %37 3183%37 = OpLabel 3184%40 = OpLoad %float %39 3185OpReturnValue %40 3186OpFunctionEnd 3187)"; 3188 3189 // The early return case must be handled by merge-return first. 3190 AddPass<MergeReturnPass>(); 3191 AddPass<InlineExhaustivePass>(); 3192 RunAndCheck(predefs + main_before + callee, 3193 predefs + new_predefs + main_after + calleeMergeReturn); 3194} 3195 3196TEST_F(InlineTest, ForwardReferencesInPhiInlined) { 3197 // The basic structure of the test case is like this: 3198 // 3199 // int foo() { 3200 // int result = 1; 3201 // if (true) { 3202 // result = 1; 3203 // } 3204 // return result; 3205 // } 3206 // 3207 // void main() { 3208 // int x = foo(); 3209 // } 3210 // 3211 // but with modifications: Using Phi instead of load/store, and the 3212 // return block in foo appears before the "then" block. 3213 3214 const std::string predefs = 3215 R"(OpCapability Shader 3216%1 = OpExtInstImport "GLSL.std.450" 3217OpMemoryModel Logical GLSL450 3218OpEntryPoint Vertex %main "main" 3219OpSource GLSL 450 3220OpName %main "main" 3221OpName %foo_ "foo(" 3222OpName %x "x" 3223%void = OpTypeVoid 3224%6 = OpTypeFunction %void 3225%int = OpTypeInt 32 1 3226%8 = OpTypeFunction %int 3227%bool = OpTypeBool 3228%true = OpConstantTrue %bool 3229%int_0 = OpConstant %int 0 3230%_ptr_Function_int = OpTypePointer Function %int 3231)"; 3232 3233 const std::string callee = 3234 R"(%foo_ = OpFunction %int None %8 3235%13 = OpLabel 3236%14 = OpCopyObject %int %int_0 3237OpSelectionMerge %15 None 3238OpBranchConditional %true %16 %15 3239%15 = OpLabel 3240%17 = OpPhi %int %14 %13 %18 %16 3241OpReturnValue %17 3242%16 = OpLabel 3243%18 = OpCopyObject %int %int_0 3244OpBranch %15 3245OpFunctionEnd 3246)"; 3247 3248 const std::string calleeMergeReturn = 3249 R"(%uint = OpTypeInt 32 0 3250%uint_0 = OpConstant %uint 0 3251%false = OpConstantFalse %bool 3252%_ptr_Function_bool = OpTypePointer Function %bool 3253%foo_ = OpFunction %int None %8 3254%13 = OpLabel 3255%29 = OpVariable %_ptr_Function_bool Function %false 3256%22 = OpVariable %_ptr_Function_int Function 3257OpSelectionMerge %21 None 3258OpSwitch %uint_0 %24 3259%24 = OpLabel 3260%14 = OpCopyObject %int %int_0 3261OpSelectionMerge %15 None 3262OpBranchConditional %true %16 %15 3263%15 = OpLabel 3264%17 = OpPhi %int %14 %24 %18 %16 3265OpStore %29 %true 3266OpStore %22 %17 3267OpBranch %21 3268%16 = OpLabel 3269%18 = OpCopyObject %int %int_0 3270OpBranch %15 3271%21 = OpLabel 3272%23 = OpLoad %int %22 3273OpReturnValue %23 3274OpFunctionEnd 3275)"; 3276 3277 const std::string before = 3278 R"(%main = OpFunction %void None %6 3279%19 = OpLabel 3280%x = OpVariable %_ptr_Function_int Function 3281%20 = OpFunctionCall %int %foo_ 3282OpStore %x %20 3283OpReturn 3284OpFunctionEnd 3285)"; 3286 3287 const std::string after = 3288 R"(%main = OpFunction %void None %6 3289%19 = OpLabel 3290%30 = OpVariable %_ptr_Function_bool Function %false 3291%31 = OpVariable %_ptr_Function_int Function 3292%32 = OpVariable %_ptr_Function_int Function 3293%x = OpVariable %_ptr_Function_int Function 3294OpStore %30 %false 3295OpSelectionMerge %40 None 3296OpSwitch %uint_0 %34 3297%34 = OpLabel 3298%35 = OpCopyObject %int %int_0 3299OpSelectionMerge %36 None 3300OpBranchConditional %true %38 %36 3301%36 = OpLabel 3302%37 = OpPhi %int %35 %34 %39 %38 3303OpStore %30 %true 3304OpStore %31 %37 3305OpBranch %40 3306%38 = OpLabel 3307%39 = OpCopyObject %int %int_0 3308OpBranch %36 3309%40 = OpLabel 3310%41 = OpLoad %int %31 3311OpStore %32 %41 3312%20 = OpLoad %int %32 3313OpStore %x %20 3314OpReturn 3315OpFunctionEnd 3316)"; 3317 3318 AddPass<MergeReturnPass>(); 3319 AddPass<InlineExhaustivePass>(); 3320 RunAndCheck(predefs + callee + before, predefs + calleeMergeReturn + after); 3321} 3322 3323TEST_F(InlineTest, DebugSimple) { 3324 // Check that it correctly generates DebugInlinedAt and maps it to DebugScope 3325 // for the inlined function foo(). 3326 const std::string text = R"( 3327; CHECK: [[main_name:%\d+]] = OpString "main" 3328; CHECK: [[foo_name:%\d+]] = OpString "foo" 3329; CHECK: [[dbg_main:%\d+]] = OpExtInst %void {{%\d+}} DebugFunction [[main_name]] {{%\d+}} {{%\d+}} 4 1 {{%\d+}} [[main_name]] FlagIsProtected|FlagIsPrivate 4 [[main:%\d+]] 3330; CHECK: [[dbg_foo:%\d+]] = OpExtInst %void {{%\d+}} DebugFunction [[foo_name]] {{%\d+}} {{%\d+}} 1 1 {{%\d+}} [[foo_name]] FlagIsProtected|FlagIsPrivate 1 [[foo:%\d+]] 3331; CHECK: [[foo_bb:%\d+]] = OpExtInst %void {{%\d+}} DebugLexicalBlock {{%\d+}} 1 14 [[dbg_foo]] 3332; CHECK: [[inlined_at:%\d+]] = OpExtInst %void {{%\d+}} DebugInlinedAt 4 [[dbg_main]] 3333; CHECK: [[main]] = OpFunction %void None 3334; CHECK: {{%\d+}} = OpExtInst %void {{%\d+}} DebugScope [[foo_bb]] [[inlined_at]] 3335; CHECK: [[foo]] = OpFunction %v4float None 3336 OpCapability Shader 3337 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 3338 OpMemoryModel Logical GLSL450 3339 OpEntryPoint Fragment %main "main" %3 %4 3340 OpExecutionMode %main OriginUpperLeft 3341 %5 = OpString "ps.hlsl" 3342 OpSource HLSL 600 %5 3343 %6 = OpString "float" 3344 %main_name = OpString "main" 3345 %foo_name = OpString "foo" 3346 OpDecorate %3 Location 0 3347 OpDecorate %4 Location 0 3348 %uint = OpTypeInt 32 0 3349 %uint_32 = OpConstant %uint 32 3350 %float = OpTypeFloat 32 3351 %float_1 = OpConstant %float 1 3352 %v4float = OpTypeVector %float 4 3353 %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3354%_ptr_Input_v4float = OpTypePointer Input %v4float 3355%_ptr_Output_v4float = OpTypePointer Output %v4float 3356 %void = OpTypeVoid 3357 %18 = OpTypeFunction %void 3358 %19 = OpTypeFunction %v4float 3359 %3 = OpVariable %_ptr_Input_v4float Input 3360 %4 = OpVariable %_ptr_Output_v4float Output 3361 %20 = OpExtInst %void %1 DebugSource %5 3362 %21 = OpExtInst %void %1 DebugCompilationUnit 1 4 %20 HLSL 3363 %22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float 3364 %23 = OpExtInst %void %1 DebugTypeVector %22 4 3365 %24 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 %23 3366 %25 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 3367 %dbg_main = OpExtInst %void %1 DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main 3368 %dbg_foo = OpExtInst %void %1 DebugFunction %foo_name %25 %20 1 1 %21 %foo_name FlagIsProtected|FlagIsPrivate 1 %foo 3369 %29 = OpExtInst %void %1 DebugLexicalBlock %20 1 14 %dbg_foo 3370 %main = OpFunction %void None %18 3371 %30 = OpLabel 3372 %31 = OpExtInst %void %1 DebugScope %dbg_main 3373 %32 = OpFunctionCall %v4float %foo 3374 %33 = OpLoad %v4float %3 3375 %34 = OpFAdd %v4float %32 %33 3376 OpStore %4 %34 3377 OpReturn 3378 OpFunctionEnd 3379 %foo = OpFunction %v4float None %19 3380 %35 = OpExtInst %void %1 DebugScope %dbg_foo 3381 %36 = OpLabel 3382 %37 = OpExtInst %void %1 DebugScope %29 3383 OpReturnValue %14 3384 OpFunctionEnd 3385)"; 3386 3387 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3388} 3389 3390TEST_F(InlineTest, ShaderDebugSimple) { 3391 // Same as DebugSimple but for NonSemantic.Shader.DebugInfo.100. 3392 const std::string text = R"( 3393; CHECK: [[main_name:%\d+]] = OpString "main" 3394; CHECK: [[foo_name:%\d+]] = OpString "foo" 3395; CHECK: [[dbg_main:%\d+]] = OpExtInst %void {{%\d+}} DebugFunction [[main_name]] {{%\d+}} {{%\d+}} %uint_4 %uint_1 {{%\d+}} [[main_name]] %uint_3 %uint_4 3396; CHECK: [[dbg_foo:%\d+]] = OpExtInst %void {{%\d+}} DebugFunction [[foo_name]] {{%\d+}} {{%\d+}} %uint_1 %uint_1 {{%\d+}} [[foo_name]] %uint_3 %uint_1 3397; CHECK: [[foo_bb:%\d+]] = OpExtInst %void {{%\d+}} DebugLexicalBlock {{%\d+}} %uint_1 %uint_14 [[dbg_foo]] 3398; CHECK: [[inlined_at:%\d+]] = OpExtInst %void {{%\d+}} DebugInlinedAt %uint_4 [[dbg_main]] 3399; CHECK: [[main:%\d+]] = OpFunction %void None 3400; CHECK: {{%\d+}} = OpExtInst %void {{%\d+}} DebugScope [[foo_bb]] [[inlined_at]] 3401; CHECK: [[foo:%\d+]] = OpFunction %v4float None 3402 OpCapability Shader 3403 OpExtension "SPV_KHR_non_semantic_info" 3404 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 3405 OpMemoryModel Logical GLSL450 3406 OpEntryPoint Fragment %main "main" %3 %4 3407 OpExecutionMode %main OriginUpperLeft 3408 %5 = OpString "ps.hlsl" 3409 OpSource HLSL 600 %5 3410 %6 = OpString "float" 3411 %main_name = OpString "main" 3412 %foo_name = OpString "foo" 3413 OpDecorate %3 Location 0 3414 OpDecorate %4 Location 0 3415 %uint = OpTypeInt 32 0 3416 %uint_0 = OpConstant %uint 0 3417 %uint_1 = OpConstant %uint 1 3418 %uint_2 = OpConstant %uint 2 3419 %uint_3 = OpConstant %uint 3 3420 %uint_4 = OpConstant %uint 4 3421 %uint_5 = OpConstant %uint 5 3422 %uint_14 = OpConstant %uint 14 3423 %uint_32 = OpConstant %uint 32 3424 %float = OpTypeFloat 32 3425 %float_1 = OpConstant %float 1 3426 %v4float = OpTypeVector %float 4 3427 %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3428%_ptr_Input_v4float = OpTypePointer Input %v4float 3429%_ptr_Output_v4float = OpTypePointer Output %v4float 3430 %void = OpTypeVoid 3431 %18 = OpTypeFunction %void 3432 %19 = OpTypeFunction %v4float 3433 %3 = OpVariable %_ptr_Input_v4float Input 3434 %4 = OpVariable %_ptr_Output_v4float Output 3435 %20 = OpExtInst %void %1 DebugSource %5 3436 %21 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %20 %uint_5 3437 %22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 %uint_3 %uint_0 3438 %23 = OpExtInst %void %1 DebugTypeVector %22 %uint_4 3439 %24 = OpExtInst %void %1 DebugTypeFunction %uint_3 %23 %23 3440 %25 = OpExtInst %void %1 DebugTypeFunction %uint_3 %23 3441 %dbg_main = OpExtInst %void %1 DebugFunction %main_name %24 %20 %uint_4 %uint_1 %21 %main_name %uint_3 %uint_4 3442 %dbg_foo = OpExtInst %void %1 DebugFunction %foo_name %25 %20 %uint_1 %uint_1 %21 %foo_name %uint_3 %uint_1 3443 %29 = OpExtInst %void %1 DebugLexicalBlock %20 %uint_1 %uint_14 %dbg_foo 3444 %main = OpFunction %void None %18 3445 %30 = OpLabel 3446%dbg_main_def = OpExtInst %void %1 DebugFunctionDefinition %dbg_main %main 3447 %31 = OpExtInst %void %1 DebugScope %dbg_main 3448 %32 = OpFunctionCall %v4float %foo 3449 %33 = OpLoad %v4float %3 3450 %34 = OpFAdd %v4float %32 %33 3451 OpStore %4 %34 3452 OpReturn 3453 OpFunctionEnd 3454 %foo = OpFunction %v4float None %19 3455 %36 = OpLabel 3456%dbg_foo_def = OpExtInst %void %1 DebugFunctionDefinition %dbg_foo %foo 3457 %35 = OpExtInst %void %1 DebugScope %dbg_foo 3458 %37 = OpExtInst %void %1 DebugScope %29 3459 OpReturnValue %14 3460 OpFunctionEnd 3461)"; 3462 3463 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3464} 3465 3466TEST_F(InlineTest, DebugNested) { 3467 // When function main() calls function zoo() and function zoo() calls 3468 // function bar() and function bar() calls function foo(), check that 3469 // the inline pass correctly generates DebugInlinedAt instructions 3470 // for the nested function calls. 3471 const std::string text = R"( 3472; CHECK: [[v4f1:%\d+]] = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3473; CHECK: [[v4f2:%\d+]] = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 3474; CHECK: [[v4f3:%\d+]] = OpConstantComposite %v4float %float_3 %float_3 %float_3 %float_3 3475; CHECK: [[color:%\d+]] = OpVariable %_ptr_Input_v4float Input 3476; CHECK: [[dbg_main:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction {{%\d+}} {{%\d+}} {{%\d+}} 10 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 10 [[main:%\d+]] 3477; CHECK: [[dbg_foo:%\d+]] = OpExtInst %void [[ext]] DebugFunction {{%\d+}} {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 [[foo:%\d+]] 3478; CHECK: [[dbg_bar:%\d+]] = OpExtInst %void [[ext]] DebugFunction {{%\d+}} {{%\d+}} {{%\d+}} 4 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 4 [[bar:%\d+]] 3479; CHECK: [[dbg_zoo:%\d+]] = OpExtInst %void [[ext]] DebugFunction {{%\d+}} {{%\d+}} {{%\d+}} 7 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 7 [[zoo:%\d+]] 3480; CHECK: [[inlined_to_main:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 600 [[dbg_main]] 3481; CHECK: [[inlined_to_zoo:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 700 [[dbg_zoo]] [[inlined_to_main]] 3482; CHECK: [[inlined_to_bar:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 300 [[dbg_bar]] [[inlined_to_zoo]] 3483; CHECK: [[main]] = OpFunction %void None 3484; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_foo]] [[inlined_to_bar]] 3485; CHECK-NEXT: OpLine {{%\d+}} 100 0 3486; CHECK-NEXT: OpStore {{%\d+}} [[v4f1]] 3487; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_bar]] [[inlined_to_zoo]] 3488; CHECK-NEXT: OpLine {{%\d+}} 300 0 3489; CHECK-NEXT: [[foo_ret:%\d+]] = OpLoad %v4float 3490; CHECK-NEXT: OpLine {{%\d+}} 400 0 3491; CHECK-NEXT: {{%\d+}} = OpFAdd %v4float [[foo_ret]] [[v4f2]] 3492; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_zoo]] [[inlined_to_main]] 3493; CHECK-NEXT: OpLine {{%\d+}} 700 0 3494; CHECK-NEXT: [[bar_ret:%\d+]] = OpLoad %v4float 3495; CHECK-NEXT: {{%\d+}} = OpFAdd %v4float [[bar_ret]] [[v4f3]] 3496; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_main]] 3497; CHECK-NEXT: OpLine {{%\d+}} 600 0 3498; CHECK-NEXT: [[zoo_ret:%\d+]] = OpLoad %v4float 3499; CHECK-NEXT: [[color_val:%\d+]] = OpLoad %v4float [[color]] 3500; CHECK-NEXT: {{%\d+}} = OpFAdd %v4float [[zoo_ret]] [[color_val]] 3501; CHECK: [[foo]] = OpFunction %v4float None 3502; CHECK: [[bar]] = OpFunction %v4float None 3503; CHECK: [[zoo]] = OpFunction %v4float None 3504 OpCapability Shader 3505 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 3506 OpMemoryModel Logical GLSL450 3507 OpEntryPoint Fragment %main "main" %3 %4 3508 OpExecutionMode %main OriginUpperLeft 3509 %5 = OpString "ps.hlsl" 3510 OpSource HLSL 600 %5 3511 %6 = OpString "float" 3512 %7 = OpString "main" 3513 %8 = OpString "foo" 3514 %9 = OpString "bar" 3515 %10 = OpString "zoo" 3516 OpDecorate %3 Location 0 3517 OpDecorate %4 Location 0 3518 %uint = OpTypeInt 32 0 3519 %uint_32 = OpConstant %uint 32 3520 %float = OpTypeFloat 32 3521 %float_1 = OpConstant %float 1 3522 %float_2 = OpConstant %float 2 3523 %float_3 = OpConstant %float 3 3524 %v4float = OpTypeVector %float 4 3525 %18 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3526 %19 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 3527 %20 = OpConstantComposite %v4float %float_3 %float_3 %float_3 %float_3 3528%_ptr_Input_v4float = OpTypePointer Input %v4float 3529%_ptr_Output_v4float = OpTypePointer Output %v4float 3530 %void = OpTypeVoid 3531 %24 = OpTypeFunction %void 3532 %25 = OpTypeFunction %v4float 3533 %3 = OpVariable %_ptr_Input_v4float Input 3534 %4 = OpVariable %_ptr_Output_v4float Output 3535 %26 = OpExtInst %void %1 DebugSource %5 3536 %27 = OpExtInst %void %1 DebugCompilationUnit 1 4 %26 HLSL 3537 %28 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float 3538 %29 = OpExtInst %void %1 DebugTypeVector %28 4 3539 %30 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %29 %29 3540 %31 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %29 3541 %32 = OpExtInst %void %1 DebugFunction %7 %30 %26 10 1 %27 %7 FlagIsProtected|FlagIsPrivate 10 %main 3542 %33 = OpExtInst %void %1 DebugFunction %8 %31 %26 1 1 %27 %8 FlagIsProtected|FlagIsPrivate 1 %foo 3543 %35 = OpExtInst %void %1 DebugFunction %9 %31 %26 4 1 %27 %9 FlagIsProtected|FlagIsPrivate 4 %bar 3544 %37 = OpExtInst %void %1 DebugFunction %10 %31 %26 7 1 %27 %10 FlagIsProtected|FlagIsPrivate 7 %zoo 3545 %main = OpFunction %void None %24 3546 %39 = OpLabel 3547 %40 = OpExtInst %void %1 DebugScope %32 3548 OpLine %5 600 0 3549 %41 = OpFunctionCall %v4float %zoo 3550 %42 = OpLoad %v4float %3 3551 %43 = OpFAdd %v4float %41 %42 3552 OpStore %4 %43 3553 OpReturn 3554 OpFunctionEnd 3555 %foo = OpFunction %v4float None %25 3556 %44 = OpExtInst %void %1 DebugScope %33 3557 %45 = OpLabel 3558 OpLine %5 100 0 3559 OpReturnValue %18 3560 OpFunctionEnd 3561 OpLine %5 200 0 3562 %bar = OpFunction %v4float None %25 3563 %46 = OpExtInst %void %1 DebugScope %35 3564 %47 = OpLabel 3565 OpLine %5 300 0 3566 %48 = OpFunctionCall %v4float %foo 3567 OpLine %5 400 0 3568 %49 = OpFAdd %v4float %48 %19 3569 OpLine %5 500 0 3570 OpReturnValue %49 3571 OpFunctionEnd 3572 %zoo = OpFunction %v4float None %25 3573 %50 = OpExtInst %void %1 DebugScope %37 3574 %51 = OpLabel 3575 OpLine %5 700 0 3576 %52 = OpFunctionCall %v4float %bar 3577 %53 = OpFAdd %v4float %52 %20 3578 OpReturnValue %53 3579 OpFunctionEnd 3580)"; 3581 3582 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3583} 3584 3585TEST_F(InlineTest, DebugSimpleHLSLPixelShader) { 3586 const std::string text = R"( 3587; CHECK: [[dbg_main:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction {{%\d+}} {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 %src_main 3588; CHECK: [[lex_blk:%\d+]] = OpExtInst %void [[ext]] DebugLexicalBlock {{%\d+}} 1 47 [[dbg_main]] 3589; CHECK: %main = OpFunction %void None 3590; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_main]] 3591; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare {{%\d+}} %param_var_color 3592; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[lex_blk]] 3593; CHECK: OpLine {{%\d+}} 2 10 3594; CHECK: {{%\d+}} = OpLoad %v4float %param_var_color 3595; CHECK: OpLine {{%\d+}} 2 3 3596; CHECK: OpFunctionEnd 3597; CHECK: %src_main = OpFunction %v4float None 3598 OpCapability Shader 3599 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 3600 OpMemoryModel Logical GLSL450 3601 OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 3602 OpExecutionMode %main OriginUpperLeft 3603 %5 = OpString "ps.hlsl" 3604 OpSource HLSL 600 %5 3605 %14 = OpString "#line 1 \"ps.hlsl\" 3606float4 main(float4 color : COLOR) : SV_TARGET { 3607 return color; 3608} 3609" 3610 %17 = OpString "float" 3611 %21 = OpString "src.main" 3612 %24 = OpString "color" 3613 OpName %in_var_COLOR "in.var.COLOR" 3614 OpName %out_var_SV_TARGET "out.var.SV_TARGET" 3615 OpName %main "main" 3616 OpName %param_var_color "param.var.color" 3617 OpName %src_main "src.main" 3618 OpName %color "color" 3619 OpName %bb_entry "bb.entry" 3620 OpDecorate %in_var_COLOR Location 0 3621 OpDecorate %out_var_SV_TARGET Location 0 3622 %uint = OpTypeInt 32 0 3623 %uint_32 = OpConstant %uint 32 3624 %float = OpTypeFloat 32 3625 %v4float = OpTypeVector %float 4 3626%_ptr_Input_v4float = OpTypePointer Input %v4float 3627%_ptr_Output_v4float = OpTypePointer Output %v4float 3628 %void = OpTypeVoid 3629 %27 = OpTypeFunction %void 3630%_ptr_Function_v4float = OpTypePointer Function %v4float 3631 %33 = OpTypeFunction %v4float %_ptr_Function_v4float 3632%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 3633%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 3634 %13 = OpExtInst %void %1 DebugExpression 3635 %15 = OpExtInst %void %1 DebugSource %5 %14 3636 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL 3637 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float 3638 %19 = OpExtInst %void %1 DebugTypeVector %18 4 3639 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %19 %19 3640 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %src_main 3641 %25 = OpExtInst %void %1 DebugLocalVariable %24 %19 %15 1 20 %22 FlagIsLocal 0 3642 %26 = OpExtInst %void %1 DebugLexicalBlock %15 1 47 %22 3643 %main = OpFunction %void None %27 3644 %28 = OpLabel 3645%param_var_color = OpVariable %_ptr_Function_v4float Function 3646 %31 = OpLoad %v4float %in_var_COLOR 3647 OpStore %param_var_color %31 3648 %32 = OpFunctionCall %v4float %src_main %param_var_color 3649 OpStore %out_var_SV_TARGET %32 3650 OpReturn 3651 OpFunctionEnd 3652 OpLine %5 1 1 3653 %src_main = OpFunction %v4float None %33 3654 %34 = OpExtInst %void %1 DebugScope %22 3655 %color = OpFunctionParameter %_ptr_Function_v4float 3656 %36 = OpExtInst %void %1 DebugDeclare %25 %color %13 3657 %bb_entry = OpLabel 3658 %38 = OpExtInst %void %1 DebugScope %26 3659 OpLine %5 2 10 3660 %39 = OpLoad %v4float %color 3661 OpLine %5 2 3 3662 OpReturnValue %39 3663 OpFunctionEnd 3664)"; 3665 3666 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3667} 3668 3669TEST_F(InlineTest, ShaderDebugSimpleHLSLPixelShader) { 3670 // Same as DebugSimpleHLSLPixelShader but for 3671 // NonSemantic.Shader.DebugInfo.100. 3672 const std::string text = R"( 3673; CHECK: [[dbg_main:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction {{%\d+}} {{%\d+}} {{%\d+}} %uint_1 %uint_1 {{%\d+}} {{%\d+}} %uint_3 %uint_1 3674; CHECK: [[lex_blk:%\d+]] = OpExtInst %void [[ext]] DebugLexicalBlock {{%\d+}} %uint_1 %uint_47 [[dbg_main]] 3675; CHECK: %main = OpFunction %void None 3676; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_main]] 3677; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare {{%\d+}} %param_var_color 3678; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[lex_blk]] 3679; CHECK: {{%\d+}} = OpExtInst %void %1 DebugLine {{%\d+}} %uint_2 %uint_2 %uint_10 %uint_10 3680; CHECK: {{%\d+}} = OpLoad %v4float %param_var_color 3681; CHECK: {{%\d+}} = OpExtInst %void %1 DebugLine {{%\d+}} %uint_2 %uint_2 %uint_3 %uint_3 3682; CHECK: OpFunctionEnd 3683; CHECK: %src_main = OpFunction %v4float None 3684 OpCapability Shader 3685 OpExtension "SPV_KHR_non_semantic_info" 3686 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 3687 OpMemoryModel Logical GLSL450 3688 OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 3689 OpExecutionMode %main OriginUpperLeft 3690 %5 = OpString "ps.hlsl" 3691 OpSource HLSL 600 %5 3692 %14 = OpString "#line 1 \"ps.hlsl\" 3693float4 main(float4 color : COLOR) : SV_TARGET { 3694 return color; 3695} 3696" 3697 %17 = OpString "float" 3698 %21 = OpString "src.main" 3699 %24 = OpString "color" 3700 OpName %in_var_COLOR "in.var.COLOR" 3701 OpName %out_var_SV_TARGET "out.var.SV_TARGET" 3702 OpName %main "main" 3703 OpName %param_var_color "param.var.color" 3704 OpName %src_main "src.main" 3705 OpName %color "color" 3706 OpName %bb_entry "bb.entry" 3707 OpDecorate %in_var_COLOR Location 0 3708 OpDecorate %out_var_SV_TARGET Location 0 3709 %uint = OpTypeInt 32 0 3710 %uint_0 = OpConstant %uint 0 3711 %uint_1 = OpConstant %uint 1 3712 %uint_2 = OpConstant %uint 2 3713 %uint_3 = OpConstant %uint 3 3714 %uint_4 = OpConstant %uint 4 3715 %uint_5 = OpConstant %uint 5 3716 %uint_10 = OpConstant %uint 10 3717 %uint_20 = OpConstant %uint 20 3718 %uint_32 = OpConstant %uint 32 3719 %uint_47 = OpConstant %uint 47 3720 %float = OpTypeFloat 32 3721 %v4float = OpTypeVector %float 4 3722%_ptr_Input_v4float = OpTypePointer Input %v4float 3723%_ptr_Output_v4float = OpTypePointer Output %v4float 3724 %void = OpTypeVoid 3725 %27 = OpTypeFunction %void 3726%_ptr_Function_v4float = OpTypePointer Function %v4float 3727 %33 = OpTypeFunction %v4float %_ptr_Function_v4float 3728%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 3729%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 3730 %13 = OpExtInst %void %1 DebugExpression 3731 %15 = OpExtInst %void %1 DebugSource %5 %14 3732 %16 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %15 %uint_5 3733 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 %uint_3 %uint_0 3734 %19 = OpExtInst %void %1 DebugTypeVector %18 %uint_4 3735 %20 = OpExtInst %void %1 DebugTypeFunction %uint_3 %19 %19 3736 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 %uint_1 %uint_1 %16 %21 %uint_3 %uint_1 3737 %25 = OpExtInst %void %1 DebugLocalVariable %24 %19 %15 %uint_1 %uint_20 %22 %uint_4 %uint_0 3738 %26 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_1 %uint_47 %22 3739 %main = OpFunction %void None %27 3740 %28 = OpLabel 3741%param_var_color = OpVariable %_ptr_Function_v4float Function 3742 %31 = OpLoad %v4float %in_var_COLOR 3743 OpStore %param_var_color %31 3744 %32 = OpFunctionCall %v4float %src_main %param_var_color 3745 OpStore %out_var_SV_TARGET %32 3746 OpReturn 3747 OpFunctionEnd 3748 %src_main = OpFunction %v4float None %33 3749 %color = OpFunctionParameter %_ptr_Function_v4float 3750 %bb_entry = OpLabel 3751 %140 = OpExtInst %void %1 DebugFunctionDefinition %22 %src_main 3752 %141 = OpExtInst %void %1 DebugLine %5 %uint_1 %uint_1 %uint_1 %uint_1 3753 %34 = OpExtInst %void %1 DebugScope %22 3754 %36 = OpExtInst %void %1 DebugDeclare %25 %color %13 3755 %38 = OpExtInst %void %1 DebugScope %26 3756 %142 = OpExtInst %void %1 DebugLine %5 %uint_2 %uint_2 %uint_10 %uint_10 3757 %39 = OpLoad %v4float %color 3758 %143 = OpExtInst %void %1 DebugLine %5 %uint_2 %uint_2 %uint_3 %uint_3 3759 OpReturnValue %39 3760 OpFunctionEnd 3761)"; 3762 3763 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3764} 3765 3766TEST_F(InlineTest, DebugDeclareForCalleeFunctionParam) { 3767 // Check that InlinePass correctly generates DebugDeclare instructions 3768 // for callee function's parameters and maps them to corresponding 3769 // local variables of caller function. 3770 const std::string text = R"( 3771; CHECK: [[add:%\d+]] = OpString "add" 3772; CHECK: [[a:%\d+]] = OpString "a" 3773; CHECK: [[b:%\d+]] = OpString "b" 3774; CHECK: [[dbg_add:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction [[add]] 3775; CHECK: [[dbg_a:%\d+]] = OpExtInst %void [[ext]] DebugLocalVariable [[a]] 3776; CHECK: [[dbg_b:%\d+]] = OpExtInst %void [[ext]] DebugLocalVariable [[b]] 3777; CHECK: [[inlinedat:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 5 3778; CHECK: OpStore [[param_a:%\d+]] 3779; CHECK: OpStore [[param_b:%\d+]] 3780; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_add]] [[inlinedat]] 3781; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare [[dbg_a]] [[param_a]] 3782; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare [[dbg_b]] [[param_b]] 3783 3784OpCapability Shader 3785%ext = OpExtInstImport "OpenCL.DebugInfo.100" 3786OpMemoryModel Logical GLSL450 3787OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 3788OpExecutionMode %main OriginUpperLeft 3789%file_name = OpString "ps.hlsl" 3790OpSource HLSL 600 %file_name 3791%float_name = OpString "float" 3792%main_name = OpString "main" 3793%add_name = OpString "add" 3794%a_name = OpString "a" 3795%b_name = OpString "b" 3796OpDecorate %in_var_COLOR Location 0 3797OpDecorate %out_var_SV_TARGET Location 0 3798%uint = OpTypeInt 32 0 3799%uint_32 = OpConstant %uint 32 3800%float = OpTypeFloat 32 3801%float_1 = OpConstant %float 1 3802%float_2 = OpConstant %float 2 3803%v4float = OpTypeVector %float 4 3804%v4f1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3805%v4f2 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 3806%_ptr_Input_v4float = OpTypePointer Input %v4float 3807%_ptr_Output_v4float = OpTypePointer Output %v4float 3808%_ptr_Function_v4float = OpTypePointer Function %v4float 3809%add_fn_type = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float 3810%void = OpTypeVoid 3811%void_fn_type = OpTypeFunction %void 3812%v4f_fn_type = OpTypeFunction %v4float 3813%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 3814%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 3815%null_expr = OpExtInst %void %ext DebugExpression 3816%src = OpExtInst %void %ext DebugSource %file_name 3817%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 3818%dbg_f = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 3819%dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_f 4 3820%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f 3821%add_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f %dbg_v4f 3822%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 5 1 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main 3823%dbg_add = OpExtInst %void %ext DebugFunction %add_name %add_ty %src 1 1 %cu %add_name FlagIsProtected|FlagIsPrivate 1 %add 3824%dbg_a = OpExtInst %void %ext DebugLocalVariable %a_name %dbg_v4f %src 1 13 %dbg_add FlagIsLocal 0 3825%dbg_b = OpExtInst %void %ext DebugLocalVariable %b_name %dbg_v4f %src 1 20 %dbg_add FlagIsLocal 1 3826%add_lb = OpExtInst %void %ext DebugLexicalBlock %src 1 23 %dbg_add 3827%main = OpFunction %void None %void_fn_type 3828%main_bb = OpLabel 3829%param_a = OpVariable %_ptr_Function_v4float Function 3830%param_b = OpVariable %_ptr_Function_v4float Function 3831%scope0 = OpExtInst %void %ext DebugScope %dbg_main 3832OpStore %param_a %v4f1 3833OpStore %param_b %v4f2 3834%result = OpFunctionCall %v4float %add %param_a %param_b 3835OpStore %out_var_SV_TARGET %result 3836OpReturn 3837OpFunctionEnd 3838%add = OpFunction %v4float None %add_fn_type 3839%scope1 = OpExtInst %void %ext DebugScope %dbg_add 3840%a = OpFunctionParameter %_ptr_Function_v4float 3841%b = OpFunctionParameter %_ptr_Function_v4float 3842%decl0 = OpExtInst %void %ext DebugDeclare %dbg_a %a %null_expr 3843%decl1 = OpExtInst %void %ext DebugDeclare %dbg_b %b %null_expr 3844%add_bb = OpLabel 3845%scope2 = OpExtInst %void %ext DebugScope %add_lb 3846%a_val = OpLoad %v4float %a 3847%b_val = OpLoad %v4float %b 3848%res = OpFAdd %v4float %a_val %b_val 3849OpReturnValue %res 3850OpFunctionEnd 3851)"; 3852 3853 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3854} 3855 3856TEST_F(InlineTest, DebugDeclareForCalleeLocalVar) { 3857 // Check that InlinePass correctly generates DebugDeclare instructions 3858 // for callee function's local variables and maps them to corresponding 3859 // local variables of caller function. 3860 const std::string text = R"( 3861; CHECK: [[add:%\d+]] = OpString "add" 3862; CHECK: [[foo:%\d+]] = OpString "foo" 3863; CHECK: [[dbg_add:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction [[add]] 3864; CHECK: [[dbg_foo:%\d+]] = OpExtInst %void [[ext]] DebugLocalVariable [[foo]] {{%\d+}} {{%\d+}} 2 2 [[dbg_add]] 3865; CHECK: [[inlinedat:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 5 3866 3867; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_add]] [[inlinedat]] 3868; CHECK: [[new_foo:%\d+]] = OpVariable %_ptr_Function_v4float Function 3869 3870; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_add]] [[inlinedat]] 3871; CHECK: [[a_val:%\d+]] = OpLoad %v4float 3872; CHECK: [[b_val:%\d+]] = OpLoad %v4float 3873; CHECK: [[res:%\d+]] = OpFAdd %v4float [[a_val]] [[b_val]] 3874; CHECK: OpStore [[new_foo]] [[res]] 3875; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare [[dbg_foo]] [[new_foo]] 3876 3877OpCapability Shader 3878%ext = OpExtInstImport "OpenCL.DebugInfo.100" 3879OpMemoryModel Logical GLSL450 3880OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 3881OpExecutionMode %main OriginUpperLeft 3882%file_name = OpString "ps.hlsl" 3883OpSource HLSL 600 %file_name 3884%float_name = OpString "float" 3885%main_name = OpString "main" 3886%add_name = OpString "add" 3887%foo_name = OpString "foo" 3888OpDecorate %in_var_COLOR Location 0 3889OpDecorate %out_var_SV_TARGET Location 0 3890%uint = OpTypeInt 32 0 3891%uint_32 = OpConstant %uint 32 3892%float = OpTypeFloat 32 3893%float_1 = OpConstant %float 1 3894%float_2 = OpConstant %float 2 3895%v4float = OpTypeVector %float 4 3896%v4f1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3897%v4f2 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 3898%_ptr_Input_v4float = OpTypePointer Input %v4float 3899%_ptr_Output_v4float = OpTypePointer Output %v4float 3900%_ptr_Function_v4float = OpTypePointer Function %v4float 3901%add_fn_type = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float 3902%void = OpTypeVoid 3903%void_fn_type = OpTypeFunction %void 3904%v4f_fn_type = OpTypeFunction %v4float 3905%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 3906%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 3907%null_expr = OpExtInst %void %ext DebugExpression 3908%src = OpExtInst %void %ext DebugSource %file_name 3909%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 3910%dbg_f = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 3911%dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_f 4 3912%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f 3913%add_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f %dbg_v4f 3914%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 5 1 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main 3915%dbg_add = OpExtInst %void %ext DebugFunction %add_name %add_ty %src 1 1 %cu %add_name FlagIsProtected|FlagIsPrivate 1 %add 3916%dbg_foo = OpExtInst %void %ext DebugLocalVariable %foo_name %dbg_v4f %src 2 2 %dbg_add FlagIsLocal 3917%main = OpFunction %void None %void_fn_type 3918%main_bb = OpLabel 3919%param_a = OpVariable %_ptr_Function_v4float Function 3920%param_b = OpVariable %_ptr_Function_v4float Function 3921%scope0 = OpExtInst %void %ext DebugScope %dbg_main 3922OpStore %param_a %v4f1 3923OpStore %param_b %v4f2 3924%result = OpFunctionCall %v4float %add %param_a %param_b 3925OpStore %out_var_SV_TARGET %result 3926OpReturn 3927OpFunctionEnd 3928%add = OpFunction %v4float None %add_fn_type 3929%scope1 = OpExtInst %void %ext DebugScope %dbg_add 3930%a = OpFunctionParameter %_ptr_Function_v4float 3931%b = OpFunctionParameter %_ptr_Function_v4float 3932%add_bb = OpLabel 3933%foo = OpVariable %_ptr_Function_v4float Function 3934%a_val = OpLoad %v4float %a 3935%b_val = OpLoad %v4float %b 3936%res = OpFAdd %v4float %a_val %b_val 3937OpStore %foo %res 3938%decl = OpExtInst %void %ext DebugDeclare %dbg_foo %foo %null_expr 3939%foo_val = OpLoad %v4float %foo 3940OpReturnValue %foo_val 3941OpFunctionEnd 3942)"; 3943 3944 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 3945} 3946 3947TEST_F(InlineTest, DebugDeclareMultiple) { 3948 // Check that InlinePass correctly generates DebugDeclare instructions 3949 // for callee function's parameters and maps them to corresponding 3950 // local variables of caller function. 3951 const std::string text = R"( 3952; CHECK: [[add:%\d+]] = OpString "add" 3953; CHECK: [[a:%\d+]] = OpString "a" 3954; CHECK: [[b:%\d+]] = OpString "b" 3955; CHECK: [[dbg_add:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction [[add]] 3956; CHECK: [[dbg_a:%\d+]] = OpExtInst %void [[ext]] DebugLocalVariable [[a]] 3957; CHECK: [[dbg_b:%\d+]] = OpExtInst %void [[ext]] DebugLocalVariable [[b]] 3958; CHECK: OpFunction 3959; CHECK-NOT: OpFunctionEnd 3960; CHECK: OpStore [[param_a:%\d+]] 3961; CHECK: OpStore [[param_b:%\d+]] 3962; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_add]] 3963; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare [[dbg_a]] [[param_a]] 3964; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugDeclare [[dbg_b]] [[param_b]] 3965; CHECK: [[a_val:%\d+]] = OpLoad %v4float [[param_a]] 3966; CHECK: OpStore [[foo:%\d+]] [[a_val]] 3967; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugValue [[dbg_a]] [[foo]] 3968 3969OpCapability Shader 3970%ext = OpExtInstImport "OpenCL.DebugInfo.100" 3971OpMemoryModel Logical GLSL450 3972OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 3973OpExecutionMode %main OriginUpperLeft 3974%file_name = OpString "ps.hlsl" 3975OpSource HLSL 600 %file_name 3976%float_name = OpString "float" 3977%main_name = OpString "main" 3978%add_name = OpString "add" 3979%a_name = OpString "a" 3980%b_name = OpString "b" 3981OpDecorate %in_var_COLOR Location 0 3982OpDecorate %out_var_SV_TARGET Location 0 3983%uint = OpTypeInt 32 0 3984%uint_32 = OpConstant %uint 32 3985%float = OpTypeFloat 32 3986%float_1 = OpConstant %float 1 3987%float_2 = OpConstant %float 2 3988%v4float = OpTypeVector %float 4 3989%v4f1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 3990%v4f2 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 3991%_ptr_Input_v4float = OpTypePointer Input %v4float 3992%_ptr_Output_v4float = OpTypePointer Output %v4float 3993%_ptr_Function_v4float = OpTypePointer Function %v4float 3994%add_fn_type = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float 3995%void = OpTypeVoid 3996%void_fn_type = OpTypeFunction %void 3997%v4f_fn_type = OpTypeFunction %v4float 3998%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 3999%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 4000%null_expr = OpExtInst %void %ext DebugExpression 4001%src = OpExtInst %void %ext DebugSource %file_name 4002%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 4003%dbg_f = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 4004%dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_f 4 4005%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f 4006%add_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f %dbg_v4f 4007%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 5 1 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main 4008%dbg_add = OpExtInst %void %ext DebugFunction %add_name %add_ty %src 1 1 %cu %add_name FlagIsProtected|FlagIsPrivate 1 %add 4009%dbg_a = OpExtInst %void %ext DebugLocalVariable %a_name %dbg_v4f %src 1 13 %dbg_add FlagIsLocal 0 4010%dbg_b = OpExtInst %void %ext DebugLocalVariable %b_name %dbg_v4f %src 1 20 %dbg_add FlagIsLocal 1 4011%main = OpFunction %void None %void_fn_type 4012%main_bb = OpLabel 4013%param_a = OpVariable %_ptr_Function_v4float Function 4014%param_b = OpVariable %_ptr_Function_v4float Function 4015%scope0 = OpExtInst %void %ext DebugScope %dbg_main 4016OpStore %param_a %v4f1 4017OpStore %param_b %v4f2 4018%result = OpFunctionCall %v4float %add %param_a %param_b 4019OpStore %out_var_SV_TARGET %result 4020OpReturn 4021OpFunctionEnd 4022%add = OpFunction %v4float None %add_fn_type 4023%scope1 = OpExtInst %void %ext DebugScope %dbg_add 4024%a = OpFunctionParameter %_ptr_Function_v4float 4025%b = OpFunctionParameter %_ptr_Function_v4float 4026%decl0 = OpExtInst %void %ext DebugDeclare %dbg_a %a %null_expr 4027%add_bb = OpLabel 4028%decl1 = OpExtInst %void %ext DebugDeclare %dbg_b %b %null_expr 4029%foo = OpVariable %_ptr_Function_v4float Function 4030%a_val = OpLoad %v4float %a 4031OpStore %foo %a_val 4032%dbg_val = OpExtInst %void %ext DebugValue %dbg_a %foo %null_expr 4033%b_val = OpLoad %v4float %b 4034%res = OpFAdd %v4float %a_val %b_val 4035OpReturnValue %res 4036OpFunctionEnd 4037)"; 4038 4039 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 4040} 4041 4042TEST_F(InlineTest, DebugValueForFunctionCallReturn) { 4043 // Check that InlinePass correctly generates DebugValue instruction 4044 // for function call's return value and maps it to a corresponding 4045 // value in the caller function. 4046 const std::string text = R"( 4047; CHECK: [[main:%\d+]] = OpString "main" 4048; CHECK: [[add:%\d+]] = OpString "add" 4049; CHECK: [[result:%\d+]] = OpString "result" 4050; CHECK: [[dbg_main:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction [[main]] 4051; CHECK: [[dbg_add:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction [[add]] 4052; CHECK: [[dbg_result:%\d+]] = OpExtInst %void [[ext]] DebugLocalVariable [[result]] {{%\d+}} {{%\d+}} 6 2 [[dbg_main]] 4053; CHECK: [[inlinedat:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 5 4054; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_add]] [[inlinedat]] 4055; CHECK: [[a_val:%\d+]] = OpLoad %v4float 4056; CHECK: [[b_val:%\d+]] = OpLoad %v4float 4057; CHECK: [[res:%\d+]] = OpFAdd %v4float [[a_val]] [[b_val]] 4058; CHECK: OpStore [[new_result:%\d+]] [[res]] 4059; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_main]] 4060; CHECK: [[result_val:%\d+]] = OpLoad %v4float [[new_result]] 4061; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugValue [[dbg_result]] [[result_val]] 4062 4063OpCapability Shader 4064%ext = OpExtInstImport "OpenCL.DebugInfo.100" 4065OpMemoryModel Logical GLSL450 4066OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 4067OpExecutionMode %main OriginUpperLeft 4068%file_name = OpString "ps.hlsl" 4069OpSource HLSL 600 %file_name 4070%float_name = OpString "float" 4071%main_name = OpString "main" 4072%add_name = OpString "add" 4073%result_name = OpString "result" 4074OpDecorate %in_var_COLOR Location 0 4075OpDecorate %out_var_SV_TARGET Location 0 4076%uint = OpTypeInt 32 0 4077%uint_32 = OpConstant %uint 32 4078%float = OpTypeFloat 32 4079%float_1 = OpConstant %float 1 4080%float_2 = OpConstant %float 2 4081%v4float = OpTypeVector %float 4 4082%v4f1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 4083%v4f2 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 4084%_ptr_Input_v4float = OpTypePointer Input %v4float 4085%_ptr_Output_v4float = OpTypePointer Output %v4float 4086%_ptr_Function_v4float = OpTypePointer Function %v4float 4087%add_fn_type = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float 4088%void = OpTypeVoid 4089%void_fn_type = OpTypeFunction %void 4090%v4f_fn_type = OpTypeFunction %v4float 4091%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 4092%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 4093%null_expr = OpExtInst %void %ext DebugExpression 4094%src = OpExtInst %void %ext DebugSource %file_name 4095%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 4096%dbg_f = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 4097%dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_f 4 4098%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f 4099%add_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f %dbg_v4f 4100%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 5 1 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main 4101%dbg_add = OpExtInst %void %ext DebugFunction %add_name %add_ty %src 1 1 %cu %add_name FlagIsProtected|FlagIsPrivate 1 %add 4102%dbg_result = OpExtInst %void %ext DebugLocalVariable %result_name %dbg_v4f %src 6 2 %dbg_main FlagIsLocal 4103%main = OpFunction %void None %void_fn_type 4104%main_bb = OpLabel 4105%param_a = OpVariable %_ptr_Function_v4float Function 4106%param_b = OpVariable %_ptr_Function_v4float Function 4107%scope0 = OpExtInst %void %ext DebugScope %dbg_main 4108OpStore %param_a %v4f1 4109OpStore %param_b %v4f2 4110%result = OpFunctionCall %v4float %add %param_a %param_b 4111%value = OpExtInst %void %ext DebugValue %dbg_result %result %null_expr 4112OpStore %out_var_SV_TARGET %result 4113OpReturn 4114OpFunctionEnd 4115%add = OpFunction %v4float None %add_fn_type 4116%scope1 = OpExtInst %void %ext DebugScope %dbg_add 4117%a = OpFunctionParameter %_ptr_Function_v4float 4118%b = OpFunctionParameter %_ptr_Function_v4float 4119%add_bb = OpLabel 4120%a_val = OpLoad %v4float %a 4121%b_val = OpLoad %v4float %b 4122%res = OpFAdd %v4float %a_val %b_val 4123OpReturnValue %res 4124OpFunctionEnd 4125)"; 4126 4127 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 4128} 4129 4130TEST_F(InlineTest, NestedWithAnExistingDebugInlinedAt) { 4131 // When a DebugScope instruction in a callee function already has a 4132 // DebugInlinedAt information, we have to create a recursive 4133 // DebugInlinedAt chain. See inlined_to_zoo and inlined_to_bar in 4134 // the following code. 4135 const std::string text = R"( 4136; CHECK: [[main:%\d+]] = OpString "main" 4137; CHECK: [[foo:%\d+]] = OpString "foo" 4138; CHECK: [[bar:%\d+]] = OpString "bar" 4139; CHECK: [[zoo:%\d+]] = OpString "zoo" 4140; CHECK: [[v4f1:%\d+]] = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 4141; CHECK: [[v4f2:%\d+]] = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 4142; CHECK: [[v4f3:%\d+]] = OpConstantComposite %v4float %float_3 %float_3 %float_3 %float_3 4143; CHECK: [[dbg_main:%\d+]] = OpExtInst %void [[ext:%\d+]] DebugFunction [[main]] 4144; CHECK: [[dbg_foo:%\d+]] = OpExtInst %void [[ext]] DebugFunction [[foo]] 4145; CHECK: [[dbg_bar:%\d+]] = OpExtInst %void [[ext]] DebugFunction [[bar]] 4146; CHECK: [[dbg_zoo:%\d+]] = OpExtInst %void [[ext]] DebugFunction [[zoo]] 4147; CHECK: [[inlined_to_main:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 10 [[dbg_main]] 4148; CHECK: [[inlined_to_zoo:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 7 [[dbg_zoo]] [[inlined_to_main]] 4149; CHECK: [[inlined_to_main:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 10 [[dbg_main]] 4150; CHECK: [[inlined_to_bar:%\d+]] = OpExtInst %void [[ext]] DebugInlinedAt 4 [[dbg_bar]] [[inlined_to_zoo]] 4151; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_foo]] [[inlined_to_bar]] 4152; CHECK: OpStore [[foo_ret:%\d+]] [[v4f1]] 4153; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_bar]] [[inlined_to_zoo]] 4154; CHECK: [[foo_ret_val:%\d+]] = OpLoad %v4float [[foo_ret]] 4155; CHECK: [[bar_ret:%\d+]] = OpFAdd %v4float [[foo_ret_val]] [[v4f2]] 4156; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_zoo]] [[inlined_to_main]] 4157; CHECK: [[zoo_result:%\d+]] = OpFAdd %v4float [[bar_ret]] [[v4f3]] 4158; CHECK: OpStore [[zoo_ret:%\d+]] [[zoo_result]] 4159; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugScope [[dbg_main]] 4160; CHECK: [[zoo_ret_val:%\d+]] = OpLoad %v4float [[zoo_ret]] 4161; CHECK: {{%\d+}} = OpFAdd %v4float [[zoo_ret_val]] {{%\d+}} 4162 4163OpCapability Shader 4164%ext = OpExtInstImport "OpenCL.DebugInfo.100" 4165OpMemoryModel Logical GLSL450 4166OpEntryPoint Fragment %main "main" %in_var_COLOR %out_var_SV_TARGET 4167OpExecutionMode %main OriginUpperLeft 4168%file_name = OpString "ps.hlsl" 4169OpSource HLSL 600 %file_name 4170%float_name = OpString "float" 4171%main_name = OpString "main" 4172%foo_name = OpString "foo" 4173%bar_name = OpString "bar" 4174%zoo_name = OpString "zoo" 4175OpDecorate %in_var_COLOR Location 0 4176OpDecorate %out_var_SV_TARGET Location 0 4177%uint = OpTypeInt 32 0 4178%uint_32 = OpConstant %uint 32 4179%float = OpTypeFloat 32 4180%float_1 = OpConstant %float 1 4181%float_2 = OpConstant %float 2 4182%float_3 = OpConstant %float 3 4183%v4float = OpTypeVector %float 4 4184%v4f1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 4185%v4f2 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 4186%v4f3 = OpConstantComposite %v4float %float_3 %float_3 %float_3 %float_3 4187%_ptr_Input_v4float = OpTypePointer Input %v4float 4188%_ptr_Output_v4float = OpTypePointer Output %v4float 4189%void = OpTypeVoid 4190%void_fn_type = OpTypeFunction %void 4191%v4f_fn_type = OpTypeFunction %v4float 4192%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 4193%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 4194%src = OpExtInst %void %ext DebugSource %file_name 4195%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 4196%dbg_f = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 4197%dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_f 4 4198%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f 4199%foo_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f 4200%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 10 1 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main 4201%dbg_foo = OpExtInst %void %ext DebugFunction %foo_name %foo_ty %src 1 1 %cu %foo_name FlagIsProtected|FlagIsPrivate 1 %foo 4202%dbg_bar = OpExtInst %void %ext DebugFunction %bar_name %foo_ty %src 4 1 %cu %bar_name FlagIsProtected|FlagIsPrivate 4 %bar 4203%dbg_zoo = OpExtInst %void %ext DebugFunction %zoo_name %foo_ty %src 7 1 %cu %zoo_name FlagIsProtected|FlagIsPrivate 7 %zoo 4204%inlined_to_zoo = OpExtInst %void %ext DebugInlinedAt 7 %dbg_zoo 4205%main = OpFunction %void None %void_fn_type 4206%main_bb = OpLabel 4207%scope0 = OpExtInst %void %ext DebugScope %dbg_main 4208%zoo_val = OpFunctionCall %v4float %zoo 4209%color = OpLoad %v4float %in_var_COLOR 4210%result = OpFAdd %v4float %zoo_val %color 4211OpStore %out_var_SV_TARGET %result 4212OpReturn 4213OpFunctionEnd 4214%foo = OpFunction %v4float None %v4f_fn_type 4215%scope1 = OpExtInst %void %ext DebugScope %dbg_foo 4216%foo_bb = OpLabel 4217OpReturnValue %v4f1 4218OpFunctionEnd 4219%zoo = OpFunction %v4float None %v4f_fn_type 4220%scope3 = OpExtInst %void %ext DebugScope %dbg_zoo 4221%zoo_bb = OpLabel 4222%scope2 = OpExtInst %void %ext DebugScope %dbg_bar %inlined_to_zoo 4223%foo_val = OpFunctionCall %v4float %foo 4224%bar_val = OpFAdd %v4float %foo_val %v4f2 4225%scope4 = OpExtInst %void %ext DebugScope %dbg_zoo 4226%zoo_ret = OpFAdd %v4float %bar_val %v4f3 4227OpReturnValue %zoo_ret 4228OpFunctionEnd 4229%bar = OpFunction %v4float None %v4f_fn_type 4230%scope5 = OpExtInst %void %ext DebugScope %dbg_bar 4231%bar_bb = OpLabel 4232%foo_val0 = OpFunctionCall %v4float %foo 4233%bar_ret = OpFAdd %v4float %foo_val0 %v4f2 4234OpReturnValue %bar_ret 4235OpFunctionEnd 4236)"; 4237 4238 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 4239} 4240 4241TEST_F(InlineTest, CreateConstantForInlinedAt) { 4242 // This shader causes CreateDebugInlinedAt to generate a constant. 4243 // Using the Constant manager would attempt to build the invalidated 4244 // DefUse manager during inlining which could cause an assert because 4245 // the function is in an inconsistent state. This test verifies that 4246 // CreateDebugInlinedAt detects that the DefUse manager is disabled 4247 // and creates a duplicate constant safely without the Constant manager. 4248 // 4249 // int function1() { 4250 // return 1; 4251 // } 4252 // 4253 // void main() { 4254 // function1(); 4255 // } 4256 4257 const std::string text = R"(OpCapability Shader 4258; CHECK: %uint_7 = OpConstant %uint 7 4259; CHECK: %uint_7_0 = OpConstant %uint 7 4260; CHECK: OpExtInst %void %1 DebugInlinedAt %uint_7_0 4261OpExtension "SPV_KHR_non_semantic_info" 4262%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 4263OpMemoryModel Logical GLSL450 4264OpEntryPoint Fragment %main "main" 4265OpExecutionMode %main OriginUpperLeft 4266%3 = OpString "parent3.hlsl" 4267%8 = OpString "int" 4268%19 = OpString "function1" 4269%20 = OpString "" 4270%26 = OpString "main" 4271OpName %main "main" 4272OpName %src_main "src.main" 4273OpName %bb_entry "bb.entry" 4274OpName %function1 "function1" 4275OpName %bb_entry_0 "bb.entry" 4276%int = OpTypeInt 32 1 4277%int_1 = OpConstant %int 1 4278%uint = OpTypeInt 32 0 4279%uint_32 = OpConstant %uint 32 4280%void = OpTypeVoid 4281%uint_4 = OpConstant %uint 4 4282%uint_0 = OpConstant %uint 0 4283%uint_3 = OpConstant %uint 3 4284%uint_1 = OpConstant %uint 1 4285%uint_5 = OpConstant %uint 5 4286%uint_2 = OpConstant %uint 2 4287%uint_17 = OpConstant %uint 17 4288%uint_6 = OpConstant %uint 6 4289%uint_13 = OpConstant %uint 13 4290%uint_7 = OpConstant %uint 7 4291%31 = OpTypeFunction %void 4292%42 = OpTypeFunction %int 4293%10 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_4 %uint_0 4294%13 = OpExtInst %void %1 DebugTypeFunction %uint_3 %10 4295%15 = OpExtInst %void %1 DebugSource %3 4296%16 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %15 %uint_5 4297%21 = OpExtInst %void %1 DebugFunction %19 %13 %15 %uint_2 %uint_1 %16 %20 %uint_3 %uint_2 4298%23 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_2 %uint_17 %21 4299%25 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void 4300%27 = OpExtInst %void %1 DebugFunction %26 %25 %15 %uint_6 %uint_1 %16 %20 %uint_3 %uint_6 4301%29 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_6 %uint_13 %27 4302%main = OpFunction %void None %31 4303%32 = OpLabel 4304%33 = OpFunctionCall %void %src_main 4305OpLine %3 8 1 4306OpReturn 4307OpFunctionEnd 4308OpLine %3 6 1 4309%src_main = OpFunction %void None %31 4310OpNoLine 4311%bb_entry = OpLabel 4312%47 = OpExtInst %void %1 DebugScope %27 4313%37 = OpExtInst %void %1 DebugFunctionDefinition %27 %src_main 4314%48 = OpExtInst %void %1 DebugScope %29 4315OpLine %3 7 3 4316%39 = OpFunctionCall %int %function1 4317%49 = OpExtInst %void %1 DebugScope %27 4318OpLine %3 8 1 4319OpReturn 4320%50 = OpExtInst %void %1 DebugNoScope 4321OpFunctionEnd 4322OpLine %3 2 1 4323%function1 = OpFunction %int None %42 4324OpNoLine 4325%bb_entry_0 = OpLabel 4326%51 = OpExtInst %void %1 DebugScope %21 4327%45 = OpExtInst %void %1 DebugFunctionDefinition %21 %function1 4328%52 = OpExtInst %void %1 DebugScope %23 4329OpLine %3 3 3 4330OpReturnValue %int_1 4331%53 = OpExtInst %void %1 DebugNoScope 4332OpFunctionEnd 4333)"; 4334 4335 SetTargetEnv(SPV_ENV_VULKAN_1_2); 4336 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4337 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 4338} 4339 4340TEST_F(InlineTest, CreateDebugInlinedAtFromDebugLine) { 4341 const std::string text = R"(OpCapability Shader 4342; CHECK: OpExtInst %void %1 DebugInlinedAt %uint_6 4343OpExtension "SPV_KHR_non_semantic_info" 4344%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 4345OpMemoryModel Logical GLSL450 4346OpEntryPoint Fragment %main "main" 4347OpExecutionMode %main OriginUpperLeft 4348%3 = OpString "debuginlinedat.frag" 4349%8 = OpString "int" 4350%15 = OpString "int function1() { 4351 return 1; 4352} 4353 4354void main() { 4355 function1(); 4356} 4357" 4358%20 = OpString "function1" 4359%21 = OpString "" 4360%26 = OpString "main" 4361OpName %main "main" 4362OpName %src_main "src.main" 4363OpName %bb_entry "bb.entry" 4364OpName %function1 "function1" 4365OpName %bb_entry_0 "bb.entry" 4366%int = OpTypeInt 32 1 4367%int_1 = OpConstant %int 1 4368%uint = OpTypeInt 32 0 4369%uint_32 = OpConstant %uint 32 4370%void = OpTypeVoid 4371%uint_4 = OpConstant %uint 4 4372%uint_0 = OpConstant %uint 0 4373%uint_3 = OpConstant %uint 3 4374%uint_1 = OpConstant %uint 1 4375%uint_5 = OpConstant %uint 5 4376%uint_17 = OpConstant %uint 17 4377%uint_13 = OpConstant %uint 13 4378%30 = OpTypeFunction %void 4379%uint_7 = OpConstant %uint 7 4380%uint_6 = OpConstant %uint 6 4381%uint_2 = OpConstant %uint 2 4382%uint_12 = OpConstant %uint 12 4383%48 = OpTypeFunction %int 4384%uint_9 = OpConstant %uint 9 4385%10 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_4 %uint_0 4386%13 = OpExtInst %void %1 DebugTypeFunction %uint_3 %10 4387%16 = OpExtInst %void %1 DebugSource %3 %15 4388%17 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %16 %uint_5 4389%22 = OpExtInst %void %1 DebugFunction %20 %13 %16 %uint_1 %uint_1 %17 %21 %uint_3 %uint_1 4390%23 = OpExtInst %void %1 DebugLexicalBlock %16 %uint_1 %uint_17 %22 4391%25 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void 4392%27 = OpExtInst %void %1 DebugFunction %26 %25 %16 %uint_5 %uint_1 %17 %21 %uint_3 %uint_5 4393%28 = OpExtInst %void %1 DebugLexicalBlock %16 %uint_5 %uint_13 %27 4394%main = OpFunction %void None %30 4395%31 = OpLabel 4396%32 = OpFunctionCall %void %src_main 4397%34 = OpExtInst %void %1 DebugLine %16 %uint_7 %uint_7 %uint_1 %uint_1 4398OpReturn 4399OpFunctionEnd 4400%src_main = OpFunction %void None %30 4401%bb_entry = OpLabel 4402%37 = OpExtInst %void %1 DebugScope %27 4403%38 = OpExtInst %void %1 DebugFunctionDefinition %27 %src_main 4404%39 = OpExtInst %void %1 DebugScope %28 4405%40 = OpExtInst %void %1 DebugLine %16 %uint_6 %uint_6 %uint_2 %uint_12 4406%44 = OpFunctionCall %int %function1 4407%46 = OpExtInst %void %1 DebugScope %27 4408%47 = OpExtInst %void %1 DebugLine %16 %uint_7 %uint_7 %uint_1 %uint_1 4409OpReturn 4410OpFunctionEnd 4411%function1 = OpFunction %int None %48 4412%bb_entry_0 = OpLabel 4413%50 = OpExtInst %void %1 DebugScope %22 4414%51 = OpExtInst %void %1 DebugFunctionDefinition %22 %function1 4415%52 = OpExtInst %void %1 DebugScope %23 4416%53 = OpExtInst %void %1 DebugLine %16 %uint_2 %uint_2 %uint_2 %uint_9 4417OpReturnValue %int_1 4418OpFunctionEnd 4419)"; 4420 4421 SetTargetEnv(SPV_ENV_VULKAN_1_2); 4422 SinglePassRunAndMatch<InlineExhaustivePass>(text, true); 4423} 4424 4425// TODO(greg-lunarg): Add tests to verify handling of these cases: 4426// 4427// Empty modules 4428// Modules without function definitions 4429// Modules in which all functions do not call other functions 4430// Caller and callee both accessing the same global variable 4431// Functions with OpLine & OpNoLine 4432// Others? 4433 4434// TODO(dneto): Test suggestions from code review 4435// https://github.com/KhronosGroup/SPIRV-Tools/pull/534 4436// 4437// Callee function returns a value generated outside the callee, 4438// e.g. a constant value. This might exercise some logic not yet 4439// exercised by the current tests: the false branch in the "if" 4440// inside the spv::Op::OpReturnValue case in InlinePass::GenInlineCode? 4441// SampledImage before function call, but callee is only single block. 4442// Then the SampledImage instruction is not cloned. Documents existing 4443// behaviour. 4444// SampledImage after function call. It is not cloned or changed. 4445 4446} // namespace 4447} // namespace opt 4448} // namespace spvtools 4449