hoist_double_nested_loops.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright (c) 2018 Google LLC.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string>
  15. #include "gmock/gmock.h"
  16. #include "source/opt/licm_pass.h"
  17. #include "test/opt/pass_fixture.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace {
  21. using ::testing::UnorderedElementsAre;
  22. using PassClassTest = PassTest<::testing::Test>;
  23. /*
  24. Tests that the LICM pass will move invariants through multiple loops
  25. Generated from the following GLSL fragment shader
  26. --eliminate-local-multi-store has also been run on the spv binary
  27. #version 440 core
  28. void main(){
  29. int a = 2;
  30. int b = 1;
  31. int hoist = 0;
  32. for (int i = 0; i < 10; i++) {
  33. for (int j = 0; j < 10; j++) {
  34. // hoist 'hoist = a - b' out of both loops
  35. hoist = a - b;
  36. }
  37. }
  38. }
  39. */
  40. TEST_F(PassClassTest, NestedDoubleHoist) {
  41. const std::string before_hoist = R"(OpCapability Shader
  42. %1 = OpExtInstImport "GLSL.std.450"
  43. OpMemoryModel Logical GLSL450
  44. OpEntryPoint Fragment %main "main"
  45. OpExecutionMode %main OriginUpperLeft
  46. OpSource GLSL 440
  47. OpName %main "main"
  48. %void = OpTypeVoid
  49. %4 = OpTypeFunction %void
  50. %int = OpTypeInt 32 1
  51. %_ptr_Function_int = OpTypePointer Function %int
  52. %int_2 = OpConstant %int 2
  53. %int_1 = OpConstant %int 1
  54. %int_0 = OpConstant %int 0
  55. %int_10 = OpConstant %int 10
  56. %bool = OpTypeBool
  57. %12 = OpUndef %int
  58. %main = OpFunction %void None %4
  59. %13 = OpLabel
  60. OpBranch %14
  61. %14 = OpLabel
  62. %15 = OpPhi %int %int_0 %13 %16 %17
  63. %18 = OpPhi %int %int_0 %13 %19 %17
  64. %20 = OpPhi %int %12 %13 %21 %17
  65. OpLoopMerge %22 %17 None
  66. OpBranch %23
  67. %23 = OpLabel
  68. %24 = OpSLessThan %bool %18 %int_10
  69. OpBranchConditional %24 %25 %22
  70. %25 = OpLabel
  71. OpBranch %26
  72. %26 = OpLabel
  73. %16 = OpPhi %int %15 %25 %27 %28
  74. %21 = OpPhi %int %int_0 %25 %29 %28
  75. OpLoopMerge %30 %28 None
  76. OpBranch %31
  77. %31 = OpLabel
  78. %32 = OpSLessThan %bool %21 %int_10
  79. OpBranchConditional %32 %33 %30
  80. %33 = OpLabel
  81. %27 = OpISub %int %int_2 %int_1
  82. OpBranch %28
  83. %28 = OpLabel
  84. %29 = OpIAdd %int %21 %int_1
  85. OpBranch %26
  86. %30 = OpLabel
  87. OpBranch %17
  88. %17 = OpLabel
  89. %19 = OpIAdd %int %18 %int_1
  90. OpBranch %14
  91. %22 = OpLabel
  92. OpReturn
  93. OpFunctionEnd
  94. )";
  95. const std::string after_hoist = R"(OpCapability Shader
  96. %1 = OpExtInstImport "GLSL.std.450"
  97. OpMemoryModel Logical GLSL450
  98. OpEntryPoint Fragment %main "main"
  99. OpExecutionMode %main OriginUpperLeft
  100. OpSource GLSL 440
  101. OpName %main "main"
  102. %void = OpTypeVoid
  103. %4 = OpTypeFunction %void
  104. %int = OpTypeInt 32 1
  105. %_ptr_Function_int = OpTypePointer Function %int
  106. %int_2 = OpConstant %int 2
  107. %int_1 = OpConstant %int 1
  108. %int_0 = OpConstant %int 0
  109. %int_10 = OpConstant %int 10
  110. %bool = OpTypeBool
  111. %12 = OpUndef %int
  112. %main = OpFunction %void None %4
  113. %13 = OpLabel
  114. %27 = OpISub %int %int_2 %int_1
  115. OpBranch %14
  116. %14 = OpLabel
  117. %15 = OpPhi %int %int_0 %13 %16 %17
  118. %18 = OpPhi %int %int_0 %13 %19 %17
  119. %20 = OpPhi %int %12 %13 %21 %17
  120. OpLoopMerge %22 %17 None
  121. OpBranch %23
  122. %23 = OpLabel
  123. %24 = OpSLessThan %bool %18 %int_10
  124. OpBranchConditional %24 %25 %22
  125. %25 = OpLabel
  126. OpBranch %26
  127. %26 = OpLabel
  128. %16 = OpPhi %int %15 %25 %27 %28
  129. %21 = OpPhi %int %int_0 %25 %29 %28
  130. OpLoopMerge %30 %28 None
  131. OpBranch %31
  132. %31 = OpLabel
  133. %32 = OpSLessThan %bool %21 %int_10
  134. OpBranchConditional %32 %33 %30
  135. %33 = OpLabel
  136. OpBranch %28
  137. %28 = OpLabel
  138. %29 = OpIAdd %int %21 %int_1
  139. OpBranch %26
  140. %30 = OpLabel
  141. OpBranch %17
  142. %17 = OpLabel
  143. %19 = OpIAdd %int %18 %int_1
  144. OpBranch %14
  145. %22 = OpLabel
  146. OpReturn
  147. OpFunctionEnd
  148. )";
  149. SinglePassRunAndCheck<LICMPass>(before_hoist, after_hoist, true);
  150. }
  151. } // namespace
  152. } // namespace opt
  153. } // namespace spvtools