transformation_set_loop_control_test.cpp 38 KB

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