transformation_set_loop_control_test.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. // Copyright (c) 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "source/fuzz/transformation_set_loop_control.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "test/fuzz/fuzz_test_util.h"
  18. namespace spvtools {
  19. namespace fuzz {
  20. namespace {
  21. TEST(TransformationSetLoopControlTest, VariousScenarios) {
  22. // This test features loops with various different controls, and goes through
  23. // a number of acceptable and unacceptable transformations to those controls.
  24. std::string shader = R"(
  25. OpCapability Shader
  26. %1 = OpExtInstImport "GLSL.std.450"
  27. OpMemoryModel Logical GLSL450
  28. OpEntryPoint Fragment %4 "main"
  29. OpExecutionMode %4 OriginUpperLeft
  30. OpSource ESSL 310
  31. OpName %4 "main"
  32. %2 = OpTypeVoid
  33. %3 = OpTypeFunction %2
  34. %6 = OpTypeInt 32 1
  35. %7 = OpTypePointer Function %6
  36. %9 = OpConstant %6 0
  37. %16 = OpConstant %6 100
  38. %17 = OpTypeBool
  39. %20 = OpConstant %6 1
  40. %4 = OpFunction %2 None %3
  41. %5 = OpLabel
  42. %8 = OpVariable %7 Function
  43. %22 = OpVariable %7 Function
  44. %32 = OpVariable %7 Function
  45. %42 = OpVariable %7 Function
  46. %52 = OpVariable %7 Function
  47. %62 = OpVariable %7 Function
  48. %72 = OpVariable %7 Function
  49. %82 = OpVariable %7 Function
  50. %92 = OpVariable %7 Function
  51. %102 = OpVariable %7 Function
  52. %112 = OpVariable %7 Function
  53. %122 = OpVariable %7 Function
  54. OpStore %8 %9
  55. OpBranch %10
  56. %10 = OpLabel
  57. %132 = OpPhi %6 %9 %5 %21 %13
  58. OpLoopMerge %12 %13 None
  59. OpBranch %14
  60. %14 = OpLabel
  61. %18 = OpSLessThan %17 %132 %16
  62. OpBranchConditional %18 %11 %12
  63. %11 = OpLabel
  64. OpBranch %13
  65. %13 = OpLabel
  66. %21 = OpIAdd %6 %132 %20
  67. OpStore %8 %21
  68. OpBranch %10
  69. %12 = OpLabel
  70. OpStore %22 %9
  71. OpBranch %23
  72. %23 = OpLabel
  73. %133 = OpPhi %6 %9 %12 %31 %26
  74. OpLoopMerge %25 %26 Unroll
  75. OpBranch %27
  76. %27 = OpLabel
  77. %29 = OpSLessThan %17 %133 %16
  78. OpBranchConditional %29 %24 %25
  79. %24 = OpLabel
  80. OpBranch %26
  81. %26 = OpLabel
  82. %31 = OpIAdd %6 %133 %20
  83. OpStore %22 %31
  84. OpBranch %23
  85. %25 = OpLabel
  86. OpStore %32 %9
  87. OpBranch %33
  88. %33 = OpLabel
  89. %134 = OpPhi %6 %9 %25 %41 %36
  90. OpLoopMerge %35 %36 DontUnroll
  91. OpBranch %37
  92. %37 = OpLabel
  93. %39 = OpSLessThan %17 %134 %16
  94. OpBranchConditional %39 %34 %35
  95. %34 = OpLabel
  96. OpBranch %36
  97. %36 = OpLabel
  98. %41 = OpIAdd %6 %134 %20
  99. OpStore %32 %41
  100. OpBranch %33
  101. %35 = OpLabel
  102. OpStore %42 %9
  103. OpBranch %43
  104. %43 = OpLabel
  105. %135 = OpPhi %6 %9 %35 %51 %46
  106. OpLoopMerge %45 %46 DependencyInfinite
  107. OpBranch %47
  108. %47 = OpLabel
  109. %49 = OpSLessThan %17 %135 %16
  110. OpBranchConditional %49 %44 %45
  111. %44 = OpLabel
  112. OpBranch %46
  113. %46 = OpLabel
  114. %51 = OpIAdd %6 %135 %20
  115. OpStore %42 %51
  116. OpBranch %43
  117. %45 = OpLabel
  118. OpStore %52 %9
  119. OpBranch %53
  120. %53 = OpLabel
  121. %136 = OpPhi %6 %9 %45 %61 %56
  122. OpLoopMerge %55 %56 DependencyLength 3
  123. OpBranch %57
  124. %57 = OpLabel
  125. %59 = OpSLessThan %17 %136 %16
  126. OpBranchConditional %59 %54 %55
  127. %54 = OpLabel
  128. OpBranch %56
  129. %56 = OpLabel
  130. %61 = OpIAdd %6 %136 %20
  131. OpStore %52 %61
  132. OpBranch %53
  133. %55 = OpLabel
  134. OpStore %62 %9
  135. OpBranch %63
  136. %63 = OpLabel
  137. %137 = OpPhi %6 %9 %55 %71 %66
  138. OpLoopMerge %65 %66 MinIterations 10
  139. OpBranch %67
  140. %67 = OpLabel
  141. %69 = OpSLessThan %17 %137 %16
  142. OpBranchConditional %69 %64 %65
  143. %64 = OpLabel
  144. OpBranch %66
  145. %66 = OpLabel
  146. %71 = OpIAdd %6 %137 %20
  147. OpStore %62 %71
  148. OpBranch %63
  149. %65 = OpLabel
  150. OpStore %72 %9
  151. OpBranch %73
  152. %73 = OpLabel
  153. %138 = OpPhi %6 %9 %65 %81 %76
  154. OpLoopMerge %75 %76 MaxIterations 50
  155. OpBranch %77
  156. %77 = OpLabel
  157. %79 = OpSLessThan %17 %138 %16
  158. OpBranchConditional %79 %74 %75
  159. %74 = OpLabel
  160. OpBranch %76
  161. %76 = OpLabel
  162. %81 = OpIAdd %6 %138 %20
  163. OpStore %72 %81
  164. OpBranch %73
  165. %75 = OpLabel
  166. OpStore %82 %9
  167. OpBranch %83
  168. %83 = OpLabel
  169. %139 = OpPhi %6 %9 %75 %91 %86
  170. OpLoopMerge %85 %86 IterationMultiple 4
  171. OpBranch %87
  172. %87 = OpLabel
  173. %89 = OpSLessThan %17 %139 %16
  174. OpBranchConditional %89 %84 %85
  175. %84 = OpLabel
  176. OpBranch %86
  177. %86 = OpLabel
  178. %91 = OpIAdd %6 %139 %20
  179. OpStore %82 %91
  180. OpBranch %83
  181. %85 = OpLabel
  182. OpStore %92 %9
  183. OpBranch %93
  184. %93 = OpLabel
  185. %140 = OpPhi %6 %9 %85 %101 %96
  186. OpLoopMerge %95 %96 PeelCount 2
  187. OpBranch %97
  188. %97 = OpLabel
  189. %99 = OpSLessThan %17 %140 %16
  190. OpBranchConditional %99 %94 %95
  191. %94 = OpLabel
  192. OpBranch %96
  193. %96 = OpLabel
  194. %101 = OpIAdd %6 %140 %20
  195. OpStore %92 %101
  196. OpBranch %93
  197. %95 = OpLabel
  198. OpStore %102 %9
  199. OpBranch %103
  200. %103 = OpLabel
  201. %141 = OpPhi %6 %9 %95 %111 %106
  202. OpLoopMerge %105 %106 PartialCount 3
  203. OpBranch %107
  204. %107 = OpLabel
  205. %109 = OpSLessThan %17 %141 %16
  206. OpBranchConditional %109 %104 %105
  207. %104 = OpLabel
  208. OpBranch %106
  209. %106 = OpLabel
  210. %111 = OpIAdd %6 %141 %20
  211. OpStore %102 %111
  212. OpBranch %103
  213. %105 = OpLabel
  214. OpStore %112 %9
  215. OpBranch %113
  216. %113 = OpLabel
  217. %142 = OpPhi %6 %9 %105 %121 %116
  218. OpLoopMerge %115 %116 Unroll|PeelCount|PartialCount 3 4
  219. OpBranch %117
  220. %117 = OpLabel
  221. %119 = OpSLessThan %17 %142 %16
  222. OpBranchConditional %119 %114 %115
  223. %114 = OpLabel
  224. OpBranch %116
  225. %116 = OpLabel
  226. %121 = OpIAdd %6 %142 %20
  227. OpStore %112 %121
  228. OpBranch %113
  229. %115 = OpLabel
  230. OpStore %122 %9
  231. OpBranch %123
  232. %123 = OpLabel
  233. %143 = OpPhi %6 %9 %115 %131 %126
  234. OpLoopMerge %125 %126 DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount 2 5 90 4 7 14
  235. OpBranch %127
  236. %127 = OpLabel
  237. %129 = OpSLessThan %17 %143 %16
  238. OpBranchConditional %129 %124 %125
  239. %124 = OpLabel
  240. OpBranch %126
  241. %126 = OpLabel
  242. %131 = OpIAdd %6 %143 %20
  243. OpStore %122 %131
  244. OpBranch %123
  245. %125 = OpLabel
  246. OpReturn
  247. OpFunctionEnd
  248. )";
  249. const auto env = SPV_ENV_UNIVERSAL_1_4;
  250. const auto consumer = nullptr;
  251. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  252. spvtools::ValidatorOptions validator_options;
  253. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  254. kConsoleMessageConsumer));
  255. TransformationContext transformation_context(
  256. MakeUnique<FactManager>(context.get()), validator_options);
  257. // These are the loop headers together with the selection controls of their
  258. // merge instructions:
  259. // %10 None
  260. // %23 Unroll
  261. // %33 DontUnroll
  262. // %43 DependencyInfinite
  263. // %53 DependencyLength 3
  264. // %63 MinIterations 10
  265. // %73 MaxIterations 50
  266. // %83 IterationMultiple 4
  267. // %93 PeelCount 2
  268. // %103 PartialCount 3
  269. // %113 Unroll|PeelCount|PartialCount 3 4
  270. // %123
  271. // DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount
  272. // 2 5 90 4 7 14
  273. ASSERT_TRUE(TransformationSetLoopControl(
  274. 10, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  275. .IsApplicable(context.get(), transformation_context));
  276. ASSERT_TRUE(TransformationSetLoopControl(
  277. 10, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  278. .IsApplicable(context.get(), transformation_context));
  279. ASSERT_TRUE(TransformationSetLoopControl(
  280. 10, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  281. .IsApplicable(context.get(), transformation_context));
  282. ASSERT_FALSE(TransformationSetLoopControl(
  283. 10, (uint32_t)spv::LoopControlMask::DependencyInfinite, 0, 0)
  284. .IsApplicable(context.get(), transformation_context));
  285. ASSERT_FALSE(TransformationSetLoopControl(
  286. 10, (uint32_t)spv::LoopControlMask::DependencyLength, 0, 0)
  287. .IsApplicable(context.get(), transformation_context));
  288. ASSERT_FALSE(TransformationSetLoopControl(
  289. 10, (uint32_t)spv::LoopControlMask::MinIterations, 0, 0)
  290. .IsApplicable(context.get(), transformation_context));
  291. ASSERT_FALSE(TransformationSetLoopControl(
  292. 10, (uint32_t)spv::LoopControlMask::MaxIterations, 0, 0)
  293. .IsApplicable(context.get(), transformation_context));
  294. ASSERT_FALSE(TransformationSetLoopControl(
  295. 10, (uint32_t)spv::LoopControlMask::IterationMultiple, 0, 0)
  296. .IsApplicable(context.get(), transformation_context));
  297. ASSERT_TRUE(TransformationSetLoopControl(
  298. 10, (uint32_t)spv::LoopControlMask::PeelCount, 3, 0)
  299. .IsApplicable(context.get(), transformation_context));
  300. ASSERT_FALSE(TransformationSetLoopControl(
  301. 10, (uint32_t)spv::LoopControlMask::PeelCount, 3, 3)
  302. .IsApplicable(context.get(), transformation_context));
  303. ASSERT_TRUE(TransformationSetLoopControl(
  304. 10, (uint32_t)spv::LoopControlMask::PartialCount, 0, 3)
  305. .IsApplicable(context.get(), transformation_context));
  306. ASSERT_FALSE(TransformationSetLoopControl(
  307. 10, (uint32_t)spv::LoopControlMask::PartialCount, 3, 3)
  308. .IsApplicable(context.get(), transformation_context));
  309. ASSERT_TRUE(TransformationSetLoopControl(
  310. 10,
  311. (uint32_t)spv::LoopControlMask::PeelCount |
  312. (uint32_t)spv::LoopControlMask::PartialCount,
  313. 3, 3)
  314. .IsApplicable(context.get(), transformation_context));
  315. ASSERT_TRUE(TransformationSetLoopControl(
  316. 10,
  317. (uint32_t)spv::LoopControlMask::Unroll |
  318. (uint32_t)spv::LoopControlMask::PeelCount |
  319. (uint32_t)spv::LoopControlMask::PartialCount,
  320. 3, 3)
  321. .IsApplicable(context.get(), transformation_context));
  322. ASSERT_FALSE(TransformationSetLoopControl(
  323. 10,
  324. (uint32_t)spv::LoopControlMask::DontUnroll |
  325. (uint32_t)spv::LoopControlMask::PeelCount |
  326. (uint32_t)spv::LoopControlMask::PartialCount,
  327. 3, 3)
  328. .IsApplicable(context.get(), transformation_context));
  329. ASSERT_TRUE(TransformationSetLoopControl(
  330. 23, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  331. .IsApplicable(context.get(), transformation_context));
  332. ASSERT_TRUE(TransformationSetLoopControl(
  333. 23, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  334. .IsApplicable(context.get(), transformation_context));
  335. ASSERT_TRUE(TransformationSetLoopControl(
  336. 23, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  337. .IsApplicable(context.get(), transformation_context));
  338. ASSERT_TRUE(TransformationSetLoopControl(
  339. 23,
  340. (uint32_t)spv::LoopControlMask::PeelCount |
  341. (uint32_t)spv::LoopControlMask::PartialCount,
  342. 3, 3)
  343. .IsApplicable(context.get(), transformation_context));
  344. ASSERT_FALSE(TransformationSetLoopControl(
  345. 23, (uint32_t)spv::LoopControlMask::MaxIterations, 2, 3)
  346. .IsApplicable(context.get(), transformation_context));
  347. ASSERT_TRUE(TransformationSetLoopControl(
  348. 33, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  349. .IsApplicable(context.get(), transformation_context));
  350. ASSERT_TRUE(TransformationSetLoopControl(
  351. 33, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  352. .IsApplicable(context.get(), transformation_context));
  353. ASSERT_TRUE(TransformationSetLoopControl(
  354. 33, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  355. .IsApplicable(context.get(), transformation_context));
  356. ASSERT_FALSE(TransformationSetLoopControl(
  357. 33, (uint32_t)spv::LoopControlMask::MinIterations, 0, 0)
  358. .IsApplicable(context.get(), transformation_context));
  359. ASSERT_TRUE(TransformationSetLoopControl(
  360. 33,
  361. (uint32_t)spv::LoopControlMask::Unroll |
  362. (uint32_t)spv::LoopControlMask::PeelCount,
  363. 5, 0)
  364. .IsApplicable(context.get(), transformation_context));
  365. ASSERT_FALSE(TransformationSetLoopControl(
  366. 33,
  367. (uint32_t)spv::LoopControlMask::DontUnroll |
  368. (uint32_t)spv::LoopControlMask::PartialCount,
  369. 0, 10)
  370. .IsApplicable(context.get(), transformation_context));
  371. ASSERT_TRUE(TransformationSetLoopControl(
  372. 43, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  373. .IsApplicable(context.get(), transformation_context));
  374. ASSERT_TRUE(TransformationSetLoopControl(
  375. 43, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  376. .IsApplicable(context.get(), transformation_context));
  377. ASSERT_TRUE(TransformationSetLoopControl(
  378. 43, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  379. .IsApplicable(context.get(), transformation_context));
  380. ASSERT_TRUE(TransformationSetLoopControl(
  381. 43,
  382. (uint32_t)spv::LoopControlMask::MaskNone |
  383. (uint32_t)spv::LoopControlMask::DependencyInfinite,
  384. 0, 0)
  385. .IsApplicable(context.get(), transformation_context));
  386. ASSERT_TRUE(TransformationSetLoopControl(
  387. 43,
  388. (uint32_t)spv::LoopControlMask::Unroll |
  389. (uint32_t)spv::LoopControlMask::DependencyInfinite,
  390. 0, 0)
  391. .IsApplicable(context.get(), transformation_context));
  392. ASSERT_TRUE(TransformationSetLoopControl(
  393. 43,
  394. (uint32_t)spv::LoopControlMask::DontUnroll |
  395. (uint32_t)spv::LoopControlMask::DependencyInfinite,
  396. 0, 0)
  397. .IsApplicable(context.get(), transformation_context));
  398. ASSERT_FALSE(TransformationSetLoopControl(
  399. 43,
  400. (uint32_t)spv::LoopControlMask::DependencyInfinite |
  401. (uint32_t)spv::LoopControlMask::DependencyLength,
  402. 0, 0)
  403. .IsApplicable(context.get(), transformation_context));
  404. ASSERT_TRUE(TransformationSetLoopControl(
  405. 43,
  406. (uint32_t)spv::LoopControlMask::Unroll |
  407. (uint32_t)spv::LoopControlMask::PeelCount,
  408. 5, 0)
  409. .IsApplicable(context.get(), transformation_context));
  410. ASSERT_TRUE(TransformationSetLoopControl(
  411. 53, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  412. .IsApplicable(context.get(), transformation_context));
  413. ASSERT_TRUE(TransformationSetLoopControl(
  414. 53, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  415. .IsApplicable(context.get(), transformation_context));
  416. ASSERT_TRUE(TransformationSetLoopControl(
  417. 53, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  418. .IsApplicable(context.get(), transformation_context));
  419. ASSERT_FALSE(TransformationSetLoopControl(
  420. 53, (uint32_t)spv::LoopControlMask::MaxIterations, 0, 0)
  421. .IsApplicable(context.get(), transformation_context));
  422. ASSERT_TRUE(TransformationSetLoopControl(
  423. 53,
  424. (uint32_t)spv::LoopControlMask::MaskNone |
  425. (uint32_t)spv::LoopControlMask::DependencyLength,
  426. 0, 0)
  427. .IsApplicable(context.get(), transformation_context));
  428. ASSERT_FALSE(TransformationSetLoopControl(
  429. 53,
  430. (uint32_t)spv::LoopControlMask::Unroll |
  431. (uint32_t)spv::LoopControlMask::DependencyInfinite,
  432. 0, 0)
  433. .IsApplicable(context.get(), transformation_context));
  434. ASSERT_TRUE(TransformationSetLoopControl(
  435. 53,
  436. (uint32_t)spv::LoopControlMask::DontUnroll |
  437. (uint32_t)spv::LoopControlMask::DependencyLength,
  438. 0, 0)
  439. .IsApplicable(context.get(), transformation_context));
  440. ASSERT_FALSE(TransformationSetLoopControl(
  441. 53,
  442. (uint32_t)spv::LoopControlMask::DependencyInfinite |
  443. (uint32_t)spv::LoopControlMask::DependencyLength,
  444. 0, 0)
  445. .IsApplicable(context.get(), transformation_context));
  446. ASSERT_TRUE(TransformationSetLoopControl(
  447. 53,
  448. (uint32_t)spv::LoopControlMask::Unroll |
  449. (uint32_t)spv::LoopControlMask::DependencyLength |
  450. (uint32_t)spv::LoopControlMask::PeelCount |
  451. (uint32_t)spv::LoopControlMask::PartialCount,
  452. 5, 3)
  453. .IsApplicable(context.get(), transformation_context));
  454. ASSERT_TRUE(TransformationSetLoopControl(
  455. 63, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  456. .IsApplicable(context.get(), transformation_context));
  457. ASSERT_TRUE(TransformationSetLoopControl(
  458. 63, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  459. .IsApplicable(context.get(), transformation_context));
  460. ASSERT_TRUE(TransformationSetLoopControl(
  461. 63, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  462. .IsApplicable(context.get(), transformation_context));
  463. ASSERT_TRUE(TransformationSetLoopControl(
  464. 63,
  465. (uint32_t)spv::LoopControlMask::Unroll |
  466. (uint32_t)spv::LoopControlMask::MinIterations |
  467. (uint32_t)spv::LoopControlMask::PeelCount |
  468. (uint32_t)spv::LoopControlMask::PartialCount,
  469. 5, 3)
  470. .IsApplicable(context.get(), transformation_context));
  471. ASSERT_TRUE(TransformationSetLoopControl(
  472. 63,
  473. (uint32_t)spv::LoopControlMask::Unroll |
  474. (uint32_t)spv::LoopControlMask::MinIterations |
  475. (uint32_t)spv::LoopControlMask::PeelCount,
  476. 23, 0)
  477. .IsApplicable(context.get(), transformation_context));
  478. ASSERT_FALSE(TransformationSetLoopControl(
  479. 63,
  480. (uint32_t)spv::LoopControlMask::Unroll |
  481. (uint32_t)spv::LoopControlMask::MinIterations |
  482. (uint32_t)spv::LoopControlMask::PeelCount,
  483. 2, 23)
  484. .IsApplicable(context.get(), transformation_context));
  485. ASSERT_TRUE(TransformationSetLoopControl(
  486. 73, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  487. .IsApplicable(context.get(), transformation_context));
  488. ASSERT_TRUE(TransformationSetLoopControl(
  489. 73, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  490. .IsApplicable(context.get(), transformation_context));
  491. ASSERT_TRUE(TransformationSetLoopControl(
  492. 73, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  493. .IsApplicable(context.get(), transformation_context));
  494. ASSERT_FALSE(TransformationSetLoopControl(
  495. 73,
  496. (uint32_t)spv::LoopControlMask::Unroll |
  497. (uint32_t)spv::LoopControlMask::MinIterations |
  498. (uint32_t)spv::LoopControlMask::PeelCount |
  499. (uint32_t)spv::LoopControlMask::PartialCount,
  500. 5, 3)
  501. .IsApplicable(context.get(), transformation_context));
  502. ASSERT_TRUE(TransformationSetLoopControl(
  503. 73,
  504. (uint32_t)spv::LoopControlMask::Unroll |
  505. (uint32_t)spv::LoopControlMask::MaxIterations |
  506. (uint32_t)spv::LoopControlMask::PeelCount,
  507. 23, 0)
  508. .IsApplicable(context.get(), transformation_context));
  509. ASSERT_FALSE(TransformationSetLoopControl(
  510. 73,
  511. (uint32_t)spv::LoopControlMask::Unroll |
  512. (uint32_t)spv::LoopControlMask::MaxIterations |
  513. (uint32_t)spv::LoopControlMask::PeelCount,
  514. 2, 23)
  515. .IsApplicable(context.get(), transformation_context));
  516. ASSERT_TRUE(TransformationSetLoopControl(
  517. 83, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  518. .IsApplicable(context.get(), transformation_context));
  519. ASSERT_TRUE(TransformationSetLoopControl(
  520. 83, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  521. .IsApplicable(context.get(), transformation_context));
  522. ASSERT_TRUE(TransformationSetLoopControl(
  523. 83, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  524. .IsApplicable(context.get(), transformation_context));
  525. ASSERT_FALSE(TransformationSetLoopControl(
  526. 83,
  527. (uint32_t)spv::LoopControlMask::Unroll |
  528. (uint32_t)spv::LoopControlMask::MinIterations |
  529. (uint32_t)spv::LoopControlMask::PeelCount |
  530. (uint32_t)spv::LoopControlMask::PartialCount,
  531. 5, 3)
  532. .IsApplicable(context.get(), transformation_context));
  533. ASSERT_TRUE(TransformationSetLoopControl(
  534. 83,
  535. (uint32_t)spv::LoopControlMask::Unroll |
  536. (uint32_t)spv::LoopControlMask::IterationMultiple |
  537. (uint32_t)spv::LoopControlMask::PeelCount,
  538. 23, 0)
  539. .IsApplicable(context.get(), transformation_context));
  540. ASSERT_FALSE(TransformationSetLoopControl(
  541. 83,
  542. (uint32_t)spv::LoopControlMask::Unroll |
  543. (uint32_t)spv::LoopControlMask::IterationMultiple |
  544. (uint32_t)spv::LoopControlMask::PeelCount,
  545. 2, 23)
  546. .IsApplicable(context.get(), transformation_context));
  547. ASSERT_TRUE(TransformationSetLoopControl(
  548. 93, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  549. .IsApplicable(context.get(), transformation_context));
  550. ASSERT_TRUE(TransformationSetLoopControl(
  551. 93, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  552. .IsApplicable(context.get(), transformation_context));
  553. ASSERT_TRUE(TransformationSetLoopControl(
  554. 93, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  555. .IsApplicable(context.get(), transformation_context));
  556. ASSERT_TRUE(TransformationSetLoopControl(
  557. 93, (uint32_t)spv::LoopControlMask::PeelCount, 8, 0)
  558. .IsApplicable(context.get(), transformation_context));
  559. ASSERT_FALSE(TransformationSetLoopControl(
  560. 93, (uint32_t)spv::LoopControlMask::PeelCount, 8, 8)
  561. .IsApplicable(context.get(), transformation_context));
  562. ASSERT_TRUE(TransformationSetLoopControl(
  563. 93, (uint32_t)spv::LoopControlMask::PartialCount, 0, 8)
  564. .IsApplicable(context.get(), transformation_context));
  565. ASSERT_TRUE(TransformationSetLoopControl(
  566. 93,
  567. (uint32_t)spv::LoopControlMask::PeelCount |
  568. (uint32_t)spv::LoopControlMask::PartialCount,
  569. 16, 8)
  570. .IsApplicable(context.get(), transformation_context));
  571. ASSERT_TRUE(TransformationSetLoopControl(
  572. 103, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  573. .IsApplicable(context.get(), transformation_context));
  574. ASSERT_TRUE(TransformationSetLoopControl(
  575. 103, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  576. .IsApplicable(context.get(), transformation_context));
  577. ASSERT_TRUE(TransformationSetLoopControl(
  578. 103, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  579. .IsApplicable(context.get(), transformation_context));
  580. ASSERT_TRUE(TransformationSetLoopControl(
  581. 103, (uint32_t)spv::LoopControlMask::PartialCount, 0, 60)
  582. .IsApplicable(context.get(), transformation_context));
  583. ASSERT_FALSE(TransformationSetLoopControl(
  584. 103,
  585. (uint32_t)spv::LoopControlMask::DontUnroll |
  586. (uint32_t)spv::LoopControlMask::PartialCount,
  587. 0, 60)
  588. .IsApplicable(context.get(), transformation_context));
  589. ASSERT_TRUE(TransformationSetLoopControl(
  590. 113, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  591. .IsApplicable(context.get(), transformation_context));
  592. ASSERT_TRUE(TransformationSetLoopControl(
  593. 113, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  594. .IsApplicable(context.get(), transformation_context));
  595. ASSERT_TRUE(TransformationSetLoopControl(
  596. 113, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  597. .IsApplicable(context.get(), transformation_context));
  598. ASSERT_TRUE(TransformationSetLoopControl(
  599. 113, (uint32_t)spv::LoopControlMask::PeelCount, 12, 0)
  600. .IsApplicable(context.get(), transformation_context));
  601. ASSERT_FALSE(TransformationSetLoopControl(
  602. 113,
  603. (uint32_t)spv::LoopControlMask::IterationMultiple |
  604. (uint32_t)spv::LoopControlMask::PeelCount,
  605. 12, 0)
  606. .IsApplicable(context.get(), transformation_context));
  607. ASSERT_TRUE(TransformationSetLoopControl(
  608. 123, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
  609. .IsApplicable(context.get(), transformation_context));
  610. ASSERT_TRUE(TransformationSetLoopControl(
  611. 123, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
  612. .IsApplicable(context.get(), transformation_context));
  613. ASSERT_TRUE(TransformationSetLoopControl(
  614. 123, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
  615. .IsApplicable(context.get(), transformation_context));
  616. ASSERT_TRUE(TransformationSetLoopControl(
  617. 123,
  618. (uint32_t)spv::LoopControlMask::MinIterations |
  619. (uint32_t)spv::LoopControlMask::MaxIterations |
  620. (uint32_t)spv::LoopControlMask::IterationMultiple |
  621. (uint32_t)spv::LoopControlMask::PeelCount |
  622. (uint32_t)spv::LoopControlMask::PartialCount,
  623. 7, 8)
  624. .IsApplicable(context.get(), transformation_context));
  625. ASSERT_TRUE(TransformationSetLoopControl(
  626. 123,
  627. (uint32_t)spv::LoopControlMask::Unroll |
  628. (uint32_t)spv::LoopControlMask::MinIterations |
  629. (uint32_t)spv::LoopControlMask::MaxIterations |
  630. (uint32_t)spv::LoopControlMask::PartialCount,
  631. 0, 9)
  632. .IsApplicable(context.get(), transformation_context));
  633. ASSERT_FALSE(TransformationSetLoopControl(
  634. 123,
  635. (uint32_t)spv::LoopControlMask::Unroll |
  636. (uint32_t)spv::LoopControlMask::MinIterations |
  637. (uint32_t)spv::LoopControlMask::MaxIterations |
  638. (uint32_t)spv::LoopControlMask::PartialCount,
  639. 7, 9)
  640. .IsApplicable(context.get(), transformation_context));
  641. ASSERT_FALSE(TransformationSetLoopControl(
  642. 123,
  643. (uint32_t)spv::LoopControlMask::DontUnroll |
  644. (uint32_t)spv::LoopControlMask::MinIterations |
  645. (uint32_t)spv::LoopControlMask::MaxIterations |
  646. (uint32_t)spv::LoopControlMask::PartialCount,
  647. 7, 9)
  648. .IsApplicable(context.get(), transformation_context));
  649. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  650. 10,
  651. (uint32_t)spv::LoopControlMask::Unroll |
  652. (uint32_t)spv::LoopControlMask::PeelCount |
  653. (uint32_t)spv::LoopControlMask::PartialCount,
  654. 3, 3),
  655. context.get(), &transformation_context);
  656. ApplyAndCheckFreshIds(
  657. TransformationSetLoopControl(
  658. 23, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0),
  659. context.get(), &transformation_context);
  660. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  661. 33, (uint32_t)spv::LoopControlMask::Unroll, 0, 0),
  662. context.get(), &transformation_context);
  663. ApplyAndCheckFreshIds(
  664. TransformationSetLoopControl(
  665. 43,
  666. (uint32_t)spv::LoopControlMask::DontUnroll |
  667. (uint32_t)spv::LoopControlMask::DependencyInfinite,
  668. 0, 0),
  669. context.get(), &transformation_context);
  670. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  671. 53, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0),
  672. context.get(), &transformation_context);
  673. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  674. 63,
  675. (uint32_t)spv::LoopControlMask::Unroll |
  676. (uint32_t)spv::LoopControlMask::MinIterations |
  677. (uint32_t)spv::LoopControlMask::PeelCount,
  678. 23, 0),
  679. context.get(), &transformation_context);
  680. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  681. 73,
  682. (uint32_t)spv::LoopControlMask::Unroll |
  683. (uint32_t)spv::LoopControlMask::MaxIterations |
  684. (uint32_t)spv::LoopControlMask::PeelCount,
  685. 23, 0),
  686. context.get(), &transformation_context);
  687. ApplyAndCheckFreshIds(
  688. TransformationSetLoopControl(
  689. 83, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0),
  690. context.get(), &transformation_context);
  691. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  692. 93,
  693. (uint32_t)spv::LoopControlMask::PeelCount |
  694. (uint32_t)spv::LoopControlMask::PartialCount,
  695. 16, 8),
  696. context.get(), &transformation_context);
  697. ApplyAndCheckFreshIds(
  698. TransformationSetLoopControl(
  699. 103, (uint32_t)spv::LoopControlMask::PartialCount, 0, 60),
  700. context.get(), &transformation_context);
  701. ApplyAndCheckFreshIds(
  702. TransformationSetLoopControl(
  703. 113, (uint32_t)spv::LoopControlMask::PeelCount, 12, 0),
  704. context.get(), &transformation_context);
  705. ApplyAndCheckFreshIds(TransformationSetLoopControl(
  706. 123,
  707. (uint32_t)spv::LoopControlMask::Unroll |
  708. (uint32_t)spv::LoopControlMask::MinIterations |
  709. (uint32_t)spv::LoopControlMask::MaxIterations |
  710. (uint32_t)spv::LoopControlMask::PartialCount,
  711. 0, 9),
  712. context.get(), &transformation_context);
  713. std::string after_transformation = R"(
  714. OpCapability Shader
  715. %1 = OpExtInstImport "GLSL.std.450"
  716. OpMemoryModel Logical GLSL450
  717. OpEntryPoint Fragment %4 "main"
  718. OpExecutionMode %4 OriginUpperLeft
  719. OpSource ESSL 310
  720. OpName %4 "main"
  721. %2 = OpTypeVoid
  722. %3 = OpTypeFunction %2
  723. %6 = OpTypeInt 32 1
  724. %7 = OpTypePointer Function %6
  725. %9 = OpConstant %6 0
  726. %16 = OpConstant %6 100
  727. %17 = OpTypeBool
  728. %20 = OpConstant %6 1
  729. %4 = OpFunction %2 None %3
  730. %5 = OpLabel
  731. %8 = OpVariable %7 Function
  732. %22 = OpVariable %7 Function
  733. %32 = OpVariable %7 Function
  734. %42 = OpVariable %7 Function
  735. %52 = OpVariable %7 Function
  736. %62 = OpVariable %7 Function
  737. %72 = OpVariable %7 Function
  738. %82 = OpVariable %7 Function
  739. %92 = OpVariable %7 Function
  740. %102 = OpVariable %7 Function
  741. %112 = OpVariable %7 Function
  742. %122 = OpVariable %7 Function
  743. OpStore %8 %9
  744. OpBranch %10
  745. %10 = OpLabel
  746. %132 = OpPhi %6 %9 %5 %21 %13
  747. OpLoopMerge %12 %13 Unroll|PeelCount|PartialCount 3 3
  748. OpBranch %14
  749. %14 = OpLabel
  750. %18 = OpSLessThan %17 %132 %16
  751. OpBranchConditional %18 %11 %12
  752. %11 = OpLabel
  753. OpBranch %13
  754. %13 = OpLabel
  755. %21 = OpIAdd %6 %132 %20
  756. OpStore %8 %21
  757. OpBranch %10
  758. %12 = OpLabel
  759. OpStore %22 %9
  760. OpBranch %23
  761. %23 = OpLabel
  762. %133 = OpPhi %6 %9 %12 %31 %26
  763. OpLoopMerge %25 %26 DontUnroll
  764. OpBranch %27
  765. %27 = OpLabel
  766. %29 = OpSLessThan %17 %133 %16
  767. OpBranchConditional %29 %24 %25
  768. %24 = OpLabel
  769. OpBranch %26
  770. %26 = OpLabel
  771. %31 = OpIAdd %6 %133 %20
  772. OpStore %22 %31
  773. OpBranch %23
  774. %25 = OpLabel
  775. OpStore %32 %9
  776. OpBranch %33
  777. %33 = OpLabel
  778. %134 = OpPhi %6 %9 %25 %41 %36
  779. OpLoopMerge %35 %36 Unroll
  780. OpBranch %37
  781. %37 = OpLabel
  782. %39 = OpSLessThan %17 %134 %16
  783. OpBranchConditional %39 %34 %35
  784. %34 = OpLabel
  785. OpBranch %36
  786. %36 = OpLabel
  787. %41 = OpIAdd %6 %134 %20
  788. OpStore %32 %41
  789. OpBranch %33
  790. %35 = OpLabel
  791. OpStore %42 %9
  792. OpBranch %43
  793. %43 = OpLabel
  794. %135 = OpPhi %6 %9 %35 %51 %46
  795. OpLoopMerge %45 %46 DontUnroll|DependencyInfinite
  796. OpBranch %47
  797. %47 = OpLabel
  798. %49 = OpSLessThan %17 %135 %16
  799. OpBranchConditional %49 %44 %45
  800. %44 = OpLabel
  801. OpBranch %46
  802. %46 = OpLabel
  803. %51 = OpIAdd %6 %135 %20
  804. OpStore %42 %51
  805. OpBranch %43
  806. %45 = OpLabel
  807. OpStore %52 %9
  808. OpBranch %53
  809. %53 = OpLabel
  810. %136 = OpPhi %6 %9 %45 %61 %56
  811. OpLoopMerge %55 %56 None
  812. OpBranch %57
  813. %57 = OpLabel
  814. %59 = OpSLessThan %17 %136 %16
  815. OpBranchConditional %59 %54 %55
  816. %54 = OpLabel
  817. OpBranch %56
  818. %56 = OpLabel
  819. %61 = OpIAdd %6 %136 %20
  820. OpStore %52 %61
  821. OpBranch %53
  822. %55 = OpLabel
  823. OpStore %62 %9
  824. OpBranch %63
  825. %63 = OpLabel
  826. %137 = OpPhi %6 %9 %55 %71 %66
  827. OpLoopMerge %65 %66 Unroll|MinIterations|PeelCount 10 23
  828. OpBranch %67
  829. %67 = OpLabel
  830. %69 = OpSLessThan %17 %137 %16
  831. OpBranchConditional %69 %64 %65
  832. %64 = OpLabel
  833. OpBranch %66
  834. %66 = OpLabel
  835. %71 = OpIAdd %6 %137 %20
  836. OpStore %62 %71
  837. OpBranch %63
  838. %65 = OpLabel
  839. OpStore %72 %9
  840. OpBranch %73
  841. %73 = OpLabel
  842. %138 = OpPhi %6 %9 %65 %81 %76
  843. OpLoopMerge %75 %76 Unroll|MaxIterations|PeelCount 50 23
  844. OpBranch %77
  845. %77 = OpLabel
  846. %79 = OpSLessThan %17 %138 %16
  847. OpBranchConditional %79 %74 %75
  848. %74 = OpLabel
  849. OpBranch %76
  850. %76 = OpLabel
  851. %81 = OpIAdd %6 %138 %20
  852. OpStore %72 %81
  853. OpBranch %73
  854. %75 = OpLabel
  855. OpStore %82 %9
  856. OpBranch %83
  857. %83 = OpLabel
  858. %139 = OpPhi %6 %9 %75 %91 %86
  859. OpLoopMerge %85 %86 DontUnroll
  860. OpBranch %87
  861. %87 = OpLabel
  862. %89 = OpSLessThan %17 %139 %16
  863. OpBranchConditional %89 %84 %85
  864. %84 = OpLabel
  865. OpBranch %86
  866. %86 = OpLabel
  867. %91 = OpIAdd %6 %139 %20
  868. OpStore %82 %91
  869. OpBranch %83
  870. %85 = OpLabel
  871. OpStore %92 %9
  872. OpBranch %93
  873. %93 = OpLabel
  874. %140 = OpPhi %6 %9 %85 %101 %96
  875. OpLoopMerge %95 %96 PeelCount|PartialCount 16 8
  876. OpBranch %97
  877. %97 = OpLabel
  878. %99 = OpSLessThan %17 %140 %16
  879. OpBranchConditional %99 %94 %95
  880. %94 = OpLabel
  881. OpBranch %96
  882. %96 = OpLabel
  883. %101 = OpIAdd %6 %140 %20
  884. OpStore %92 %101
  885. OpBranch %93
  886. %95 = OpLabel
  887. OpStore %102 %9
  888. OpBranch %103
  889. %103 = OpLabel
  890. %141 = OpPhi %6 %9 %95 %111 %106
  891. OpLoopMerge %105 %106 PartialCount 60
  892. OpBranch %107
  893. %107 = OpLabel
  894. %109 = OpSLessThan %17 %141 %16
  895. OpBranchConditional %109 %104 %105
  896. %104 = OpLabel
  897. OpBranch %106
  898. %106 = OpLabel
  899. %111 = OpIAdd %6 %141 %20
  900. OpStore %102 %111
  901. OpBranch %103
  902. %105 = OpLabel
  903. OpStore %112 %9
  904. OpBranch %113
  905. %113 = OpLabel
  906. %142 = OpPhi %6 %9 %105 %121 %116
  907. OpLoopMerge %115 %116 PeelCount 12
  908. OpBranch %117
  909. %117 = OpLabel
  910. %119 = OpSLessThan %17 %142 %16
  911. OpBranchConditional %119 %114 %115
  912. %114 = OpLabel
  913. OpBranch %116
  914. %116 = OpLabel
  915. %121 = OpIAdd %6 %142 %20
  916. OpStore %112 %121
  917. OpBranch %113
  918. %115 = OpLabel
  919. OpStore %122 %9
  920. OpBranch %123
  921. %123 = OpLabel
  922. %143 = OpPhi %6 %9 %115 %131 %126
  923. OpLoopMerge %125 %126 Unroll|MinIterations|MaxIterations|PartialCount 5 90 9
  924. OpBranch %127
  925. %127 = OpLabel
  926. %129 = OpSLessThan %17 %143 %16
  927. OpBranchConditional %129 %124 %125
  928. %124 = OpLabel
  929. OpBranch %126
  930. %126 = OpLabel
  931. %131 = OpIAdd %6 %143 %20
  932. OpStore %122 %131
  933. OpBranch %123
  934. %125 = OpLabel
  935. OpReturn
  936. OpFunctionEnd
  937. )";
  938. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  939. }
  940. TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
  941. // This test checks that we do not allow introducing PeelCount and
  942. // PartialCount loop controls if the SPIR-V version being used does not
  943. // support them.
  944. std::string shader = R"(
  945. OpCapability Shader
  946. %1 = OpExtInstImport "GLSL.std.450"
  947. OpMemoryModel Logical GLSL450
  948. OpEntryPoint Fragment %4 "main"
  949. OpExecutionMode %4 OriginUpperLeft
  950. OpSource ESSL 310
  951. OpName %4 "main"
  952. OpName %8 "i"
  953. %2 = OpTypeVoid
  954. %3 = OpTypeFunction %2
  955. %6 = OpTypeInt 32 1
  956. %7 = OpTypePointer Function %6
  957. %9 = OpConstant %6 0
  958. %16 = OpConstant %6 10
  959. %17 = OpTypeBool
  960. %20 = OpConstant %6 1
  961. %4 = OpFunction %2 None %3
  962. %5 = OpLabel
  963. %8 = OpVariable %7 Function
  964. OpStore %8 %9
  965. OpBranch %10
  966. %10 = OpLabel
  967. OpLoopMerge %12 %13 None
  968. OpBranch %14
  969. %14 = OpLabel
  970. %15 = OpLoad %6 %8
  971. %18 = OpSLessThan %17 %15 %16
  972. OpBranchConditional %18 %11 %12
  973. %11 = OpLabel
  974. OpBranch %13
  975. %13 = OpLabel
  976. %19 = OpLoad %6 %8
  977. %21 = OpIAdd %6 %19 %20
  978. OpStore %8 %21
  979. OpBranch %10
  980. %12 = OpLabel
  981. OpReturn
  982. OpFunctionEnd
  983. )";
  984. for (auto env :
  985. {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
  986. SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
  987. SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1_SPIRV_1_4,
  988. SPV_ENV_VULKAN_1_2}) {
  989. const auto consumer = nullptr;
  990. const auto context =
  991. BuildModule(env, consumer, shader, kFuzzAssembleOption);
  992. spvtools::ValidatorOptions validator_options;
  993. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  994. context.get(), validator_options, kConsoleMessageConsumer));
  995. TransformationContext transformation_context(
  996. MakeUnique<FactManager>(context.get()), validator_options);
  997. TransformationSetLoopControl peel_count(
  998. 10, (uint32_t)spv::LoopControlMask::PeelCount, 4, 0);
  999. TransformationSetLoopControl partial_count(
  1000. 10, (uint32_t)spv::LoopControlMask::PartialCount, 0, 4);
  1001. switch (env) {
  1002. case SPV_ENV_UNIVERSAL_1_0:
  1003. case SPV_ENV_UNIVERSAL_1_1:
  1004. case SPV_ENV_UNIVERSAL_1_2:
  1005. case SPV_ENV_UNIVERSAL_1_3:
  1006. case SPV_ENV_VULKAN_1_0:
  1007. case SPV_ENV_VULKAN_1_1:
  1008. // PeelCount and PartialCount were introduced in SPIRV 1.4, so are not
  1009. // valid in the context of older versions.
  1010. ASSERT_FALSE(
  1011. peel_count.IsApplicable(context.get(), transformation_context));
  1012. ASSERT_FALSE(
  1013. partial_count.IsApplicable(context.get(), transformation_context));
  1014. break;
  1015. case SPV_ENV_UNIVERSAL_1_4:
  1016. case SPV_ENV_UNIVERSAL_1_5:
  1017. case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
  1018. case SPV_ENV_VULKAN_1_2:
  1019. ASSERT_TRUE(
  1020. peel_count.IsApplicable(context.get(), transformation_context));
  1021. ASSERT_TRUE(
  1022. partial_count.IsApplicable(context.get(), transformation_context));
  1023. break;
  1024. default:
  1025. assert(false && "Unhandled environment");
  1026. break;
  1027. }
  1028. }
  1029. }
  1030. } // namespace
  1031. } // namespace fuzz
  1032. } // namespace spvtools