function_test.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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 <memory>
  15. #include <sstream>
  16. #include <string>
  17. #include <vector>
  18. #include "function_utils.h"
  19. #include "gmock/gmock.h"
  20. #include "gtest/gtest.h"
  21. #include "source/opt/build_module.h"
  22. #include "source/opt/ir_context.h"
  23. namespace spvtools {
  24. namespace opt {
  25. namespace {
  26. using ::testing::Eq;
  27. TEST(FunctionTest, HasEarlyReturn) {
  28. std::string shader = R"(
  29. OpCapability Shader
  30. %1 = OpExtInstImport "GLSL.std.450"
  31. OpMemoryModel Logical GLSL450
  32. OpEntryPoint Vertex %6 "main"
  33. ; Types
  34. %2 = OpTypeBool
  35. %3 = OpTypeVoid
  36. %4 = OpTypeFunction %3
  37. ; Constants
  38. %5 = OpConstantTrue %2
  39. ; main function without early return
  40. %6 = OpFunction %3 None %4
  41. %7 = OpLabel
  42. OpBranch %8
  43. %8 = OpLabel
  44. OpBranch %9
  45. %9 = OpLabel
  46. OpBranch %10
  47. %10 = OpLabel
  48. OpReturn
  49. OpFunctionEnd
  50. ; function with early return
  51. %11 = OpFunction %3 None %4
  52. %12 = OpLabel
  53. OpSelectionMerge %15 None
  54. OpBranchConditional %5 %13 %14
  55. %13 = OpLabel
  56. OpReturn
  57. %14 = OpLabel
  58. OpBranch %15
  59. %15 = OpLabel
  60. OpReturn
  61. OpFunctionEnd
  62. )";
  63. const auto context =
  64. BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, shader,
  65. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  66. // Tests |function| without early return.
  67. auto* function = spvtest::GetFunction(context->module(), 6);
  68. ASSERT_FALSE(function->HasEarlyReturn());
  69. // Tests |function| with early return.
  70. function = spvtest::GetFunction(context->module(), 11);
  71. ASSERT_TRUE(function->HasEarlyReturn());
  72. }
  73. TEST(FunctionTest, IsNotRecursive) {
  74. const std::string text = R"(
  75. OpCapability Shader
  76. OpMemoryModel Logical GLSL450
  77. OpEntryPoint Fragment %1 "main"
  78. OpExecutionMode %1 OriginUpperLeft
  79. OpDecorate %2 DescriptorSet 439418829
  80. %void = OpTypeVoid
  81. %4 = OpTypeFunction %void
  82. %float = OpTypeFloat 32
  83. %_struct_6 = OpTypeStruct %float %float
  84. %7 = OpTypeFunction %_struct_6
  85. %1 = OpFunction %void Pure|Const %4
  86. %8 = OpLabel
  87. %2 = OpFunctionCall %_struct_6 %9
  88. OpKill
  89. OpFunctionEnd
  90. %9 = OpFunction %_struct_6 None %7
  91. %10 = OpLabel
  92. %11 = OpFunctionCall %_struct_6 %12
  93. OpUnreachable
  94. OpFunctionEnd
  95. %12 = OpFunction %_struct_6 None %7
  96. %13 = OpLabel
  97. OpUnreachable
  98. OpFunctionEnd
  99. )";
  100. std::unique_ptr<IRContext> ctx =
  101. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  102. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  103. auto* func = spvtest::GetFunction(ctx->module(), 9);
  104. EXPECT_FALSE(func->IsRecursive());
  105. func = spvtest::GetFunction(ctx->module(), 12);
  106. EXPECT_FALSE(func->IsRecursive());
  107. }
  108. TEST(FunctionTest, IsDirectlyRecursive) {
  109. const std::string text = R"(
  110. OpCapability Shader
  111. OpMemoryModel Logical GLSL450
  112. OpEntryPoint Fragment %1 "main"
  113. OpExecutionMode %1 OriginUpperLeft
  114. OpDecorate %2 DescriptorSet 439418829
  115. %void = OpTypeVoid
  116. %4 = OpTypeFunction %void
  117. %float = OpTypeFloat 32
  118. %_struct_6 = OpTypeStruct %float %float
  119. %7 = OpTypeFunction %_struct_6
  120. %1 = OpFunction %void Pure|Const %4
  121. %8 = OpLabel
  122. %2 = OpFunctionCall %_struct_6 %9
  123. OpKill
  124. OpFunctionEnd
  125. %9 = OpFunction %_struct_6 None %7
  126. %10 = OpLabel
  127. %11 = OpFunctionCall %_struct_6 %9
  128. OpUnreachable
  129. OpFunctionEnd
  130. )";
  131. std::unique_ptr<IRContext> ctx =
  132. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  133. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  134. auto* func = spvtest::GetFunction(ctx->module(), 9);
  135. EXPECT_TRUE(func->IsRecursive());
  136. }
  137. TEST(FunctionTest, IsIndirectlyRecursive) {
  138. const std::string text = R"(
  139. OpCapability Shader
  140. OpMemoryModel Logical GLSL450
  141. OpEntryPoint Fragment %1 "main"
  142. OpExecutionMode %1 OriginUpperLeft
  143. OpDecorate %2 DescriptorSet 439418829
  144. %void = OpTypeVoid
  145. %4 = OpTypeFunction %void
  146. %float = OpTypeFloat 32
  147. %_struct_6 = OpTypeStruct %float %float
  148. %7 = OpTypeFunction %_struct_6
  149. %1 = OpFunction %void Pure|Const %4
  150. %8 = OpLabel
  151. %2 = OpFunctionCall %_struct_6 %9
  152. OpKill
  153. OpFunctionEnd
  154. %9 = OpFunction %_struct_6 None %7
  155. %10 = OpLabel
  156. %11 = OpFunctionCall %_struct_6 %12
  157. OpUnreachable
  158. OpFunctionEnd
  159. %12 = OpFunction %_struct_6 None %7
  160. %13 = OpLabel
  161. %14 = OpFunctionCall %_struct_6 %9
  162. OpUnreachable
  163. OpFunctionEnd
  164. )";
  165. std::unique_ptr<IRContext> ctx =
  166. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  167. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  168. auto* func = spvtest::GetFunction(ctx->module(), 9);
  169. EXPECT_TRUE(func->IsRecursive());
  170. func = spvtest::GetFunction(ctx->module(), 12);
  171. EXPECT_TRUE(func->IsRecursive());
  172. }
  173. TEST(FunctionTest, IsNotRecuriseCallingRecursive) {
  174. const std::string text = R"(
  175. OpCapability Shader
  176. OpMemoryModel Logical GLSL450
  177. OpEntryPoint Fragment %1 "main"
  178. OpExecutionMode %1 OriginUpperLeft
  179. OpDecorate %2 DescriptorSet 439418829
  180. %void = OpTypeVoid
  181. %4 = OpTypeFunction %void
  182. %float = OpTypeFloat 32
  183. %_struct_6 = OpTypeStruct %float %float
  184. %7 = OpTypeFunction %_struct_6
  185. %1 = OpFunction %void Pure|Const %4
  186. %8 = OpLabel
  187. %2 = OpFunctionCall %_struct_6 %9
  188. OpKill
  189. OpFunctionEnd
  190. %9 = OpFunction %_struct_6 None %7
  191. %10 = OpLabel
  192. %11 = OpFunctionCall %_struct_6 %9
  193. OpUnreachable
  194. OpFunctionEnd
  195. )";
  196. std::unique_ptr<IRContext> ctx =
  197. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  198. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  199. auto* func = spvtest::GetFunction(ctx->module(), 1);
  200. EXPECT_FALSE(func->IsRecursive());
  201. }
  202. TEST(FunctionTest, NonSemanticInfoSkipIteration) {
  203. const std::string text = R"(
  204. OpCapability Shader
  205. OpCapability Linkage
  206. OpExtension "SPV_KHR_non_semantic_info"
  207. %1 = OpExtInstImport "NonSemantic.Test"
  208. OpMemoryModel Logical GLSL450
  209. %2 = OpTypeVoid
  210. %3 = OpTypeFunction %2
  211. %4 = OpFunction %2 None %3
  212. %5 = OpLabel
  213. %6 = OpExtInst %2 %1 1
  214. OpReturn
  215. OpFunctionEnd
  216. %7 = OpExtInst %2 %1 2
  217. %8 = OpExtInst %2 %1 3
  218. )";
  219. std::unique_ptr<IRContext> ctx =
  220. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  221. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  222. auto* func = spvtest::GetFunction(ctx->module(), 4);
  223. ASSERT_TRUE(func != nullptr);
  224. std::unordered_set<uint32_t> non_semantic_ids;
  225. func->ForEachInst(
  226. [&non_semantic_ids](const Instruction* inst) {
  227. if (inst->opcode() == SpvOpExtInst) {
  228. non_semantic_ids.insert(inst->result_id());
  229. }
  230. },
  231. true, false);
  232. EXPECT_EQ(1, non_semantic_ids.count(6));
  233. EXPECT_EQ(0, non_semantic_ids.count(7));
  234. EXPECT_EQ(0, non_semantic_ids.count(8));
  235. }
  236. TEST(FunctionTest, NonSemanticInfoIncludeIteration) {
  237. const std::string text = R"(
  238. OpCapability Shader
  239. OpCapability Linkage
  240. OpExtension "SPV_KHR_non_semantic_info"
  241. %1 = OpExtInstImport "NonSemantic.Test"
  242. OpMemoryModel Logical GLSL450
  243. %2 = OpTypeVoid
  244. %3 = OpTypeFunction %2
  245. %4 = OpFunction %2 None %3
  246. %5 = OpLabel
  247. %6 = OpExtInst %2 %1 1
  248. OpReturn
  249. OpFunctionEnd
  250. %7 = OpExtInst %2 %1 2
  251. %8 = OpExtInst %2 %1 3
  252. )";
  253. std::unique_ptr<IRContext> ctx =
  254. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  255. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  256. auto* func = spvtest::GetFunction(ctx->module(), 4);
  257. ASSERT_TRUE(func != nullptr);
  258. std::unordered_set<uint32_t> non_semantic_ids;
  259. func->ForEachInst(
  260. [&non_semantic_ids](const Instruction* inst) {
  261. if (inst->opcode() == SpvOpExtInst) {
  262. non_semantic_ids.insert(inst->result_id());
  263. }
  264. },
  265. true, true);
  266. EXPECT_EQ(1, non_semantic_ids.count(6));
  267. EXPECT_EQ(1, non_semantic_ids.count(7));
  268. EXPECT_EQ(1, non_semantic_ids.count(8));
  269. }
  270. } // namespace
  271. } // namespace opt
  272. } // namespace spvtools