val_ssa_test.cpp 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. // Copyright (c) 2015-2016 The Khronos Group Inc.
  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. // Validation tests for SSA
  15. #include <sstream>
  16. #include <string>
  17. #include <utility>
  18. #include "gmock/gmock.h"
  19. #include "test/unit_spirv.h"
  20. #include "test/val/val_fixtures.h"
  21. namespace spvtools {
  22. namespace val {
  23. namespace {
  24. using ::testing::HasSubstr;
  25. using ::testing::MatchesRegex;
  26. using ValidateSSA = spvtest::ValidateBase<std::pair<std::string, bool>>;
  27. TEST_F(ValidateSSA, Default) {
  28. char str[] = R"(
  29. OpCapability Shader
  30. OpCapability Linkage
  31. OpMemoryModel Logical GLSL450
  32. OpEntryPoint GLCompute %3 ""
  33. OpExecutionMode %3 LocalSize 1 1 1
  34. %1 = OpTypeVoid
  35. %2 = OpTypeFunction %1
  36. %3 = OpFunction %1 None %2
  37. %4 = OpLabel
  38. OpReturn
  39. OpFunctionEnd
  40. )";
  41. CompileSuccessfully(str);
  42. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  43. }
  44. TEST_F(ValidateSSA, IdUndefinedBad) {
  45. char str[] = R"(
  46. OpCapability Shader
  47. OpCapability Linkage
  48. OpMemoryModel Logical GLSL450
  49. OpName %missing "missing"
  50. %voidt = OpTypeVoid
  51. %vfunct = OpTypeFunction %voidt
  52. %func = OpFunction %vfunct None %missing
  53. %flabel = OpLabel
  54. OpReturn
  55. OpFunctionEnd
  56. )";
  57. CompileSuccessfully(str);
  58. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  59. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  60. }
  61. TEST_F(ValidateSSA, IdRedefinedBad) {
  62. char str[] = R"(
  63. OpCapability Shader
  64. OpCapability Linkage
  65. OpMemoryModel Logical GLSL450
  66. OpName %2 "redefined"
  67. %1 = OpTypeVoid
  68. %2 = OpTypeFunction %1
  69. %2 = OpFunction %1 None %2
  70. %4 = OpLabel
  71. OpReturn
  72. OpFunctionEnd
  73. )";
  74. CompileSuccessfully(str);
  75. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  76. }
  77. TEST_F(ValidateSSA, DominateUsageBad) {
  78. char str[] = R"(
  79. OpCapability Shader
  80. OpCapability Linkage
  81. OpMemoryModel Logical GLSL450
  82. OpName %1 "not_dominant"
  83. %2 = OpTypeFunction %1 ; uses %1 before it's definition
  84. %1 = OpTypeVoid
  85. )";
  86. CompileSuccessfully(str);
  87. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  88. EXPECT_THAT(getDiagnosticString(), HasSubstr("not_dominant"));
  89. }
  90. TEST_F(ValidateSSA, DominateUsageWithinBlockBad) {
  91. char str[] = R"(
  92. OpCapability Shader
  93. OpCapability Linkage
  94. OpMemoryModel Logical GLSL450
  95. OpName %bad "bad"
  96. %voidt = OpTypeVoid
  97. %funct = OpTypeFunction %voidt
  98. %uintt = OpTypeInt 32 0
  99. %one = OpConstant %uintt 1
  100. %func = OpFunction %voidt None %funct
  101. %entry = OpLabel
  102. %sum = OpIAdd %uintt %one %bad
  103. %bad = OpCopyObject %uintt %sum
  104. OpReturn
  105. OpFunctionEnd
  106. )";
  107. CompileSuccessfully(str);
  108. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  109. EXPECT_THAT(getDiagnosticString(),
  110. MatchesRegex("ID '.\\[%bad\\]' has not been defined\n"
  111. " %8 = OpIAdd %uint %uint_1 %bad\n"));
  112. }
  113. TEST_F(ValidateSSA, DominateUsageSameInstructionBad) {
  114. char str[] = R"(
  115. OpCapability Shader
  116. OpCapability Linkage
  117. OpMemoryModel Logical GLSL450
  118. OpName %sum "sum"
  119. %voidt = OpTypeVoid
  120. %funct = OpTypeFunction %voidt
  121. %uintt = OpTypeInt 32 0
  122. %one = OpConstant %uintt 1
  123. %func = OpFunction %voidt None %funct
  124. %entry = OpLabel
  125. %sum = OpIAdd %uintt %one %sum
  126. OpReturn
  127. OpFunctionEnd
  128. )";
  129. CompileSuccessfully(str);
  130. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  131. EXPECT_THAT(getDiagnosticString(),
  132. MatchesRegex("ID '.\\[%sum\\]' has not been defined\n"
  133. " %sum = OpIAdd %uint %uint_1 %sum\n"));
  134. }
  135. TEST_F(ValidateSSA, ForwardNameGood) {
  136. char str[] = R"(
  137. OpCapability Shader
  138. OpCapability Linkage
  139. OpMemoryModel Logical GLSL450
  140. OpName %3 "main"
  141. %1 = OpTypeVoid
  142. %2 = OpTypeFunction %1
  143. %3 = OpFunction %1 None %2
  144. %4 = OpLabel
  145. OpReturn
  146. OpFunctionEnd
  147. )";
  148. CompileSuccessfully(str);
  149. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  150. }
  151. TEST_F(ValidateSSA, ForwardNameMissingTargetBad) {
  152. char str[] = R"(
  153. OpCapability Shader
  154. OpCapability Linkage
  155. OpMemoryModel Logical GLSL450
  156. OpName %5 "main" ; Target never defined
  157. )";
  158. CompileSuccessfully(str);
  159. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  160. EXPECT_THAT(getDiagnosticString(), HasSubstr("main"));
  161. }
  162. TEST_F(ValidateSSA, ForwardMemberNameGood) {
  163. char str[] = R"(
  164. OpCapability Shader
  165. OpCapability Linkage
  166. OpMemoryModel Logical GLSL450
  167. OpMemberName %struct 0 "value"
  168. OpMemberName %struct 1 "size"
  169. %intt = OpTypeInt 32 1
  170. %uintt = OpTypeInt 32 0
  171. %struct = OpTypeStruct %intt %uintt
  172. )";
  173. CompileSuccessfully(str);
  174. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  175. }
  176. TEST_F(ValidateSSA, ForwardMemberNameMissingTargetBad) {
  177. char str[] = R"(
  178. OpCapability Shader
  179. OpCapability Linkage
  180. OpMemoryModel Logical GLSL450
  181. OpMemberName %struct 0 "value"
  182. OpMemberName %bad 1 "size" ; Target is not defined
  183. %intt = OpTypeInt 32 1
  184. %uintt = OpTypeInt 32 0
  185. %struct = OpTypeStruct %intt %uintt
  186. )";
  187. CompileSuccessfully(str);
  188. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  189. EXPECT_THAT(getDiagnosticString(),
  190. HasSubstr("The following forward referenced IDs have not been "
  191. "defined:\n'2[%2]'"));
  192. }
  193. TEST_F(ValidateSSA, ForwardDecorateGood) {
  194. char str[] = R"(
  195. OpCapability Shader
  196. OpCapability Linkage
  197. OpMemoryModel Logical GLSL450
  198. OpDecorate %var Restrict
  199. %intt = OpTypeInt 32 1
  200. %ptrt = OpTypePointer UniformConstant %intt
  201. %var = OpVariable %ptrt UniformConstant
  202. )";
  203. CompileSuccessfully(str);
  204. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  205. }
  206. TEST_F(ValidateSSA, ForwardDecorateInvalidIDBad) {
  207. char str[] = R"(
  208. OpCapability Shader
  209. OpCapability Linkage
  210. OpMemoryModel Logical GLSL450
  211. OpName %missing "missing"
  212. OpDecorate %missing Restrict ;Missing ID
  213. %voidt = OpTypeVoid
  214. %intt = OpTypeInt 32 1
  215. %ptrt = OpTypePointer UniformConstant %intt
  216. %var = OpVariable %ptrt UniformConstant
  217. %2 = OpTypeFunction %voidt
  218. %3 = OpFunction %voidt None %2
  219. %4 = OpLabel
  220. OpReturn
  221. OpFunctionEnd
  222. )";
  223. CompileSuccessfully(str);
  224. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  225. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  226. }
  227. TEST_F(ValidateSSA, ForwardMemberDecorateGood) {
  228. char str[] = R"(
  229. OpCapability Shader
  230. OpCapability Linkage
  231. OpMemoryModel Logical GLSL450
  232. OpMemberDecorate %struct 1 RowMajor
  233. %intt = OpTypeInt 32 1
  234. %f32 = OpTypeFloat 32
  235. %vec3 = OpTypeVector %f32 3
  236. %mat33 = OpTypeMatrix %vec3 3
  237. %struct = OpTypeStruct %intt %mat33
  238. )";
  239. CompileSuccessfully(str);
  240. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  241. }
  242. TEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) {
  243. char str[] = R"(
  244. OpCapability Shader
  245. OpCapability Linkage
  246. OpMemoryModel Logical GLSL450
  247. OpName %missing "missing"
  248. OpMemberDecorate %missing 1 RowMajor ; Target not defined
  249. %intt = OpTypeInt 32 1
  250. %f32 = OpTypeFloat 32
  251. %vec3 = OpTypeVector %f32 3
  252. %mat33 = OpTypeMatrix %vec3 3
  253. %struct = OpTypeStruct %intt %mat33
  254. )";
  255. CompileSuccessfully(str);
  256. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  257. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  258. }
  259. TEST_F(ValidateSSA, ForwardGroupDecorateGood) {
  260. char str[] = R"(
  261. OpCapability Shader
  262. OpCapability Linkage
  263. OpMemoryModel Logical GLSL450
  264. OpDecorate %dgrp RowMajor
  265. %dgrp = OpDecorationGroup
  266. OpGroupDecorate %dgrp %mat33 %mat44
  267. %f32 = OpTypeFloat 32
  268. %vec3 = OpTypeVector %f32 3
  269. %vec4 = OpTypeVector %f32 4
  270. %mat33 = OpTypeMatrix %vec3 3
  271. %mat44 = OpTypeMatrix %vec4 4
  272. )";
  273. CompileSuccessfully(str);
  274. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  275. }
  276. TEST_F(ValidateSSA, ForwardGroupDecorateMissingGroupBad) {
  277. char str[] = R"(
  278. OpCapability Shader
  279. OpCapability Linkage
  280. OpMemoryModel Logical GLSL450
  281. OpName %missing "missing"
  282. OpDecorate %dgrp RowMajor
  283. %dgrp = OpDecorationGroup
  284. OpGroupDecorate %missing %mat33 %mat44 ; Target not defined
  285. %intt = OpTypeInt 32 1
  286. %vec3 = OpTypeVector %intt 3
  287. %vec4 = OpTypeVector %intt 4
  288. %mat33 = OpTypeMatrix %vec3 3
  289. %mat44 = OpTypeMatrix %vec4 4
  290. )";
  291. CompileSuccessfully(str);
  292. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  293. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  294. }
  295. TEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) {
  296. char str[] = R"(
  297. OpCapability Shader
  298. OpCapability Linkage
  299. OpMemoryModel Logical GLSL450
  300. OpName %missing "missing"
  301. OpDecorate %dgrp RowMajor
  302. %dgrp = OpDecorationGroup
  303. OpGroupDecorate %dgrp %missing %mat44 ; Target not defined
  304. %f32 = OpTypeFloat 32
  305. %vec3 = OpTypeVector %f32 3
  306. %vec4 = OpTypeVector %f32 4
  307. %mat33 = OpTypeMatrix %vec3 3
  308. %mat44 = OpTypeMatrix %vec4 4
  309. )";
  310. CompileSuccessfully(str);
  311. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  312. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  313. }
  314. TEST_F(ValidateSSA, ForwardGroupDecorateDecorationGroupDominateBad) {
  315. char str[] = R"(
  316. OpCapability Shader
  317. OpCapability Linkage
  318. OpMemoryModel Logical GLSL450
  319. OpName %dgrp "group"
  320. OpDecorate %dgrp RowMajor
  321. OpGroupDecorate %dgrp %mat33 %mat44 ; Decoration group does not dominate usage
  322. %dgrp = OpDecorationGroup
  323. %intt = OpTypeInt 32 1
  324. %vec3 = OpTypeVector %intt 3
  325. %vec4 = OpTypeVector %intt 4
  326. %mat33 = OpTypeMatrix %vec3 3
  327. %mat44 = OpTypeMatrix %vec4 4
  328. )";
  329. CompileSuccessfully(str);
  330. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  331. EXPECT_THAT(getDiagnosticString(), HasSubstr("group"));
  332. }
  333. TEST_F(ValidateSSA, ForwardDecorateInvalidIdBad) {
  334. char str[] = R"(
  335. OpCapability Shader
  336. OpCapability Linkage
  337. OpMemoryModel Logical GLSL450
  338. OpName %missing "missing"
  339. OpDecorate %missing Restrict ; Missing target
  340. %voidt = OpTypeVoid
  341. %intt = OpTypeInt 32 1
  342. %ptrt = OpTypePointer UniformConstant %intt
  343. %var = OpVariable %ptrt UniformConstant
  344. %2 = OpTypeFunction %voidt
  345. %3 = OpFunction %voidt None %2
  346. %4 = OpLabel
  347. OpReturn
  348. OpFunctionEnd
  349. )";
  350. CompileSuccessfully(str);
  351. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  352. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  353. }
  354. TEST_F(ValidateSSA, FunctionCallGood) {
  355. char str[] = R"(
  356. OpCapability Shader
  357. OpCapability Linkage
  358. OpMemoryModel Logical GLSL450
  359. %1 = OpTypeVoid
  360. %2 = OpTypeInt 32 1
  361. %3 = OpTypeInt 32 0
  362. %4 = OpTypeFunction %1
  363. %8 = OpTypeFunction %1 %2 %3
  364. %four = OpConstant %2 4
  365. %five = OpConstant %3 5
  366. %9 = OpFunction %1 None %8
  367. %10 = OpFunctionParameter %2
  368. %11 = OpFunctionParameter %3
  369. %12 = OpLabel
  370. OpReturn
  371. OpFunctionEnd
  372. %5 = OpFunction %1 None %4
  373. %6 = OpLabel
  374. %7 = OpFunctionCall %1 %9 %four %five
  375. OpReturn
  376. OpFunctionEnd
  377. )";
  378. CompileSuccessfully(str);
  379. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  380. }
  381. TEST_F(ValidateSSA, ForwardFunctionCallGood) {
  382. char str[] = R"(
  383. OpCapability Shader
  384. OpCapability Linkage
  385. OpMemoryModel Logical GLSL450
  386. %1 = OpTypeVoid
  387. %2 = OpTypeInt 32 1
  388. %3 = OpTypeInt 32 0
  389. %four = OpConstant %2 4
  390. %five = OpConstant %3 5
  391. %8 = OpTypeFunction %1 %2 %3
  392. %4 = OpTypeFunction %1
  393. %5 = OpFunction %1 None %4
  394. %6 = OpLabel
  395. %7 = OpFunctionCall %1 %9 %four %five
  396. OpReturn
  397. OpFunctionEnd
  398. %9 = OpFunction %1 None %8
  399. %10 = OpFunctionParameter %2
  400. %11 = OpFunctionParameter %3
  401. %12 = OpLabel
  402. OpReturn
  403. OpFunctionEnd
  404. )";
  405. CompileSuccessfully(str);
  406. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  407. }
  408. TEST_F(ValidateSSA, ForwardBranchConditionalGood) {
  409. char str[] = R"(
  410. OpCapability Shader
  411. OpCapability Linkage
  412. OpMemoryModel Logical GLSL450
  413. %voidt = OpTypeVoid
  414. %boolt = OpTypeBool
  415. %vfunct = OpTypeFunction %voidt
  416. %true = OpConstantTrue %boolt
  417. %main = OpFunction %voidt None %vfunct
  418. %mainl = OpLabel
  419. OpSelectionMerge %endl None
  420. OpBranchConditional %true %truel %falsel
  421. %truel = OpLabel
  422. OpNop
  423. OpBranch %endl
  424. %falsel = OpLabel
  425. OpNop
  426. OpBranch %endl
  427. %endl = OpLabel
  428. OpReturn
  429. OpFunctionEnd
  430. )";
  431. CompileSuccessfully(str);
  432. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  433. }
  434. TEST_F(ValidateSSA, ForwardBranchConditionalWithWeightsGood) {
  435. char str[] = R"(
  436. OpCapability Shader
  437. OpCapability Linkage
  438. OpMemoryModel Logical GLSL450
  439. %voidt = OpTypeVoid
  440. %boolt = OpTypeBool
  441. %vfunct = OpTypeFunction %voidt
  442. %true = OpConstantTrue %boolt
  443. %main = OpFunction %voidt None %vfunct
  444. %mainl = OpLabel
  445. OpSelectionMerge %endl None
  446. OpBranchConditional %true %truel %falsel 1 9
  447. %truel = OpLabel
  448. OpNop
  449. OpBranch %endl
  450. %falsel = OpLabel
  451. OpNop
  452. OpBranch %endl
  453. %endl = OpLabel
  454. OpReturn
  455. OpFunctionEnd
  456. )";
  457. CompileSuccessfully(str);
  458. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  459. }
  460. TEST_F(ValidateSSA, ForwardBranchConditionalNonDominantConditionBad) {
  461. char str[] = R"(
  462. OpCapability Shader
  463. OpCapability Linkage
  464. OpMemoryModel Logical GLSL450
  465. OpName %tcpy "conditional"
  466. %voidt = OpTypeVoid
  467. %boolt = OpTypeBool
  468. %vfunct = OpTypeFunction %voidt
  469. %true = OpConstantTrue %boolt
  470. %main = OpFunction %voidt None %vfunct
  471. %mainl = OpLabel
  472. OpSelectionMerge %endl None
  473. OpBranchConditional %tcpy %truel %falsel ;
  474. %truel = OpLabel
  475. OpNop
  476. OpBranch %endl
  477. %falsel = OpLabel
  478. OpNop
  479. OpBranch %endl
  480. %endl = OpLabel
  481. %tcpy = OpCopyObject %boolt %true
  482. OpReturn
  483. OpFunctionEnd
  484. )";
  485. CompileSuccessfully(str);
  486. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  487. EXPECT_THAT(getDiagnosticString(), HasSubstr("conditional"));
  488. }
  489. TEST_F(ValidateSSA, ForwardBranchConditionalMissingTargetBad) {
  490. char str[] = R"(
  491. OpCapability Shader
  492. OpCapability Linkage
  493. OpMemoryModel Logical GLSL450
  494. OpName %missing "missing"
  495. %voidt = OpTypeVoid
  496. %boolt = OpTypeBool
  497. %vfunct = OpTypeFunction %voidt
  498. %true = OpConstantTrue %boolt
  499. %main = OpFunction %voidt None %vfunct
  500. %mainl = OpLabel
  501. OpSelectionMerge %endl None
  502. OpBranchConditional %true %missing %falsel
  503. %truel = OpLabel
  504. OpNop
  505. OpBranch %endl
  506. %falsel = OpLabel
  507. OpNop
  508. OpBranch %endl
  509. %endl = OpLabel
  510. OpReturn
  511. OpFunctionEnd
  512. )";
  513. CompileSuccessfully(str);
  514. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  515. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  516. }
  517. // Since Int8 requires the Kernel capability, the signedness of int types may
  518. // not be "1".
  519. const std::string kHeader = R"(
  520. OpCapability Int8
  521. OpCapability DeviceEnqueue
  522. OpCapability Linkage
  523. OpMemoryModel Logical OpenCL
  524. )";
  525. const std::string kBasicTypes = R"(
  526. %voidt = OpTypeVoid
  527. %boolt = OpTypeBool
  528. %int8t = OpTypeInt 8 0
  529. %uintt = OpTypeInt 32 0
  530. %vfunct = OpTypeFunction %voidt
  531. %intptrt = OpTypePointer UniformConstant %uintt
  532. %zero = OpConstant %uintt 0
  533. %one = OpConstant %uintt 1
  534. %ten = OpConstant %uintt 10
  535. %false = OpConstantFalse %boolt
  536. )";
  537. const std::string kKernelTypesAndConstants = R"(
  538. %queuet = OpTypeQueue
  539. %three = OpConstant %uintt 3
  540. %arr3t = OpTypeArray %uintt %three
  541. %ndt = OpTypeStruct %uintt %arr3t %arr3t %arr3t
  542. %eventt = OpTypeEvent
  543. %offset = OpConstant %uintt 0
  544. %local = OpConstant %uintt 1
  545. %gl = OpConstant %uintt 1
  546. %nevent = OpConstant %uintt 0
  547. %event = OpConstantNull %eventt
  548. %firstp = OpConstant %int8t 0
  549. %psize = OpConstant %uintt 0
  550. %palign = OpConstant %uintt 32
  551. %lsize = OpConstant %uintt 1
  552. %flags = OpConstant %uintt 0 ; NoWait
  553. %kfunct = OpTypeFunction %voidt %intptrt
  554. )";
  555. const std::string kKernelSetup = R"(
  556. %dqueue = OpGetDefaultQueue %queuet
  557. %ndval = OpBuildNDRange %ndt %gl %local %offset
  558. %revent = OpUndef %eventt
  559. )";
  560. const std::string kKernelDefinition = R"(
  561. %kfunc = OpFunction %voidt None %kfunct
  562. %iparam = OpFunctionParameter %intptrt
  563. %kfuncl = OpLabel
  564. OpNop
  565. OpReturn
  566. OpFunctionEnd
  567. )";
  568. TEST_F(ValidateSSA, EnqueueKernelGood) {
  569. std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants +
  570. kKernelDefinition + R"(
  571. %main = OpFunction %voidt None %vfunct
  572. %mainl = OpLabel
  573. )" + kKernelSetup + R"(
  574. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  575. %event %revent %kfunc %firstp %psize
  576. %palign %lsize
  577. OpReturn
  578. OpFunctionEnd
  579. )";
  580. CompileSuccessfully(str);
  581. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  582. }
  583. TEST_F(ValidateSSA, ForwardEnqueueKernelGood) {
  584. std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + R"(
  585. %main = OpFunction %voidt None %vfunct
  586. %mainl = OpLabel
  587. )" +
  588. kKernelSetup + R"(
  589. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  590. %event %revent %kfunc %firstp %psize
  591. %palign %lsize
  592. OpReturn
  593. OpFunctionEnd
  594. )" + kKernelDefinition;
  595. CompileSuccessfully(str);
  596. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  597. }
  598. TEST_F(ValidateSSA, EnqueueMissingFunctionBad) {
  599. std::string str = kHeader + "OpName %kfunc \"kfunc\"" + kBasicTypes +
  600. kKernelTypesAndConstants + R"(
  601. %main = OpFunction %voidt None %vfunct
  602. %mainl = OpLabel
  603. )" + kKernelSetup + R"(
  604. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  605. %event %revent %kfunc %firstp %psize
  606. %palign %lsize
  607. OpReturn
  608. OpFunctionEnd
  609. )";
  610. CompileSuccessfully(str);
  611. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  612. EXPECT_THAT(getDiagnosticString(), HasSubstr("kfunc"));
  613. }
  614. std::string forwardKernelNonDominantParameterBaseCode(
  615. std::string name = std::string()) {
  616. std::string op_name;
  617. if (name.empty()) {
  618. op_name = "";
  619. } else {
  620. op_name = "\nOpName %" + name + " \"" + name + "\"\n";
  621. }
  622. std::string out = kHeader + op_name + kBasicTypes + kKernelTypesAndConstants +
  623. kKernelDefinition +
  624. R"(
  625. %main = OpFunction %voidt None %vfunct
  626. %mainl = OpLabel
  627. )" + kKernelSetup;
  628. return out;
  629. }
  630. TEST_F(ValidateSSA, ForwardEnqueueKernelMissingParameter1Bad) {
  631. std::string str = forwardKernelNonDominantParameterBaseCode("missing") + R"(
  632. %err = OpEnqueueKernel %missing %dqueue %flags %ndval
  633. %nevent %event %revent %kfunc %firstp
  634. %psize %palign %lsize
  635. OpReturn
  636. OpFunctionEnd
  637. )";
  638. CompileSuccessfully(str);
  639. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  640. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  641. }
  642. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter2Bad) {
  643. std::string str = forwardKernelNonDominantParameterBaseCode("dqueue2") + R"(
  644. %err = OpEnqueueKernel %uintt %dqueue2 %flags %ndval
  645. %nevent %event %revent %kfunc
  646. %firstp %psize %palign %lsize
  647. %dqueue2 = OpGetDefaultQueue %queuet
  648. OpReturn
  649. OpFunctionEnd
  650. )";
  651. CompileSuccessfully(str);
  652. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  653. EXPECT_THAT(getDiagnosticString(), HasSubstr("dqueue2"));
  654. }
  655. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter3Bad) {
  656. std::string str = forwardKernelNonDominantParameterBaseCode("ndval2") + R"(
  657. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval2
  658. %nevent %event %revent %kfunc %firstp
  659. %psize %palign %lsize
  660. %ndval2 = OpBuildNDRange %ndt %gl %local %offset
  661. OpReturn
  662. OpFunctionEnd
  663. )";
  664. CompileSuccessfully(str);
  665. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  666. EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2"));
  667. }
  668. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter4Bad) {
  669. std::string str = forwardKernelNonDominantParameterBaseCode("nevent2") + R"(
  670. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent2
  671. %event %revent %kfunc %firstp %psize
  672. %palign %lsize
  673. %nevent2 = OpCopyObject %uintt %nevent
  674. OpReturn
  675. OpFunctionEnd
  676. )";
  677. CompileSuccessfully(str);
  678. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  679. EXPECT_THAT(getDiagnosticString(), HasSubstr("nevent2"));
  680. }
  681. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter5Bad) {
  682. std::string str = forwardKernelNonDominantParameterBaseCode("event2") + R"(
  683. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  684. %event2 %revent %kfunc %firstp %psize
  685. %palign %lsize
  686. %event2 = OpCopyObject %eventt %event
  687. OpReturn
  688. OpFunctionEnd
  689. )";
  690. CompileSuccessfully(str);
  691. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  692. EXPECT_THAT(getDiagnosticString(), HasSubstr("event2"));
  693. }
  694. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter6Bad) {
  695. std::string str = forwardKernelNonDominantParameterBaseCode("revent2") + R"(
  696. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  697. %event %revent2 %kfunc %firstp %psize
  698. %palign %lsize
  699. %revent2 = OpCopyObject %eventt %revent
  700. OpReturn
  701. OpFunctionEnd
  702. )";
  703. CompileSuccessfully(str);
  704. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  705. EXPECT_THAT(getDiagnosticString(), HasSubstr("revent2"));
  706. }
  707. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter8Bad) {
  708. std::string str = forwardKernelNonDominantParameterBaseCode("firstp2") + R"(
  709. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  710. %event %revent %kfunc %firstp2 %psize
  711. %palign %lsize
  712. %firstp2 = OpCopyObject %int8t %firstp
  713. OpReturn
  714. OpFunctionEnd
  715. )";
  716. CompileSuccessfully(str);
  717. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  718. EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2"));
  719. }
  720. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter9Bad) {
  721. std::string str = forwardKernelNonDominantParameterBaseCode("psize2") + R"(
  722. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  723. %event %revent %kfunc %firstp %psize2
  724. %palign %lsize
  725. %psize2 = OpCopyObject %uintt %psize
  726. OpReturn
  727. OpFunctionEnd
  728. )";
  729. CompileSuccessfully(str);
  730. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  731. EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2"));
  732. }
  733. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter10Bad) {
  734. std::string str = forwardKernelNonDominantParameterBaseCode("palign2") + R"(
  735. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  736. %event %revent %kfunc %firstp %psize
  737. %palign2 %lsize
  738. %palign2 = OpCopyObject %uintt %palign
  739. OpReturn
  740. OpFunctionEnd
  741. )";
  742. CompileSuccessfully(str);
  743. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  744. EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2"));
  745. }
  746. TEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter11Bad) {
  747. std::string str = forwardKernelNonDominantParameterBaseCode("lsize2") + R"(
  748. %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
  749. %event %revent %kfunc %firstp %psize
  750. %palign %lsize2
  751. %lsize2 = OpCopyObject %uintt %lsize
  752. OpReturn
  753. OpFunctionEnd
  754. )";
  755. CompileSuccessfully(str);
  756. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  757. EXPECT_THAT(getDiagnosticString(), HasSubstr("lsize2"));
  758. }
  759. static const bool kWithNDrange = true;
  760. static const bool kNoNDrange = false;
  761. std::pair<std::string, bool> cases[] = {
  762. {"OpGetKernelNDrangeSubGroupCount", kWithNDrange},
  763. {"OpGetKernelNDrangeMaxSubGroupSize", kWithNDrange},
  764. {"OpGetKernelWorkGroupSize", kNoNDrange},
  765. {"OpGetKernelPreferredWorkGroupSizeMultiple", kNoNDrange}};
  766. INSTANTIATE_TEST_SUITE_P(KernelArgs, ValidateSSA, ::testing::ValuesIn(cases));
  767. static const std::string return_instructions = R"(
  768. OpReturn
  769. OpFunctionEnd
  770. )";
  771. TEST_P(ValidateSSA, GetKernelGood) {
  772. std::string instruction = GetParam().first;
  773. bool with_ndrange = GetParam().second;
  774. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  775. std::stringstream ss;
  776. // clang-format off
  777. ss << forwardKernelNonDominantParameterBaseCode() + " %numsg = "
  778. << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
  779. << return_instructions;
  780. // clang-format on
  781. CompileSuccessfully(ss.str());
  782. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  783. }
  784. TEST_P(ValidateSSA, ForwardGetKernelGood) {
  785. std::string instruction = GetParam().first;
  786. bool with_ndrange = GetParam().second;
  787. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  788. // clang-format off
  789. std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants +
  790. R"(
  791. %main = OpFunction %voidt None %vfunct
  792. %mainl = OpLabel
  793. )"
  794. + kKernelSetup + " %numsg = "
  795. + instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
  796. + return_instructions + kKernelDefinition;
  797. // clang-format on
  798. CompileSuccessfully(str);
  799. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  800. }
  801. TEST_P(ValidateSSA, ForwardGetKernelMissingDefinitionBad) {
  802. std::string instruction = GetParam().first;
  803. bool with_ndrange = GetParam().second;
  804. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  805. std::stringstream ss;
  806. // clang-format off
  807. ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = "
  808. << instruction + " %uintt" + ndrange_param + "%missing %firstp %psize %palign"
  809. << return_instructions;
  810. // clang-format on
  811. CompileSuccessfully(ss.str());
  812. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  813. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  814. }
  815. TEST_P(ValidateSSA, ForwardGetKernelNDrangeSubGroupCountMissingParameter1Bad) {
  816. std::string instruction = GetParam().first;
  817. bool with_ndrange = GetParam().second;
  818. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  819. std::stringstream ss;
  820. // clang-format off
  821. ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = "
  822. << instruction + " %missing" + ndrange_param + "%kfunc %firstp %psize %palign"
  823. << return_instructions;
  824. // clang-format on
  825. CompileSuccessfully(ss.str());
  826. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  827. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  828. }
  829. TEST_P(ValidateSSA,
  830. ForwardGetKernelNDrangeSubGroupCountNonDominantParameter2Bad) {
  831. std::string instruction = GetParam().first;
  832. bool with_ndrange = GetParam().second;
  833. std::string ndrange_param = with_ndrange ? " %ndval2 " : " ";
  834. std::stringstream ss;
  835. // clang-format off
  836. ss << forwardKernelNonDominantParameterBaseCode("ndval2") + " %numsg = "
  837. << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
  838. << "\n %ndval2 = OpBuildNDRange %ndt %gl %local %offset"
  839. << return_instructions;
  840. // clang-format on
  841. if (GetParam().second) {
  842. CompileSuccessfully(ss.str());
  843. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  844. EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2"));
  845. }
  846. }
  847. TEST_P(ValidateSSA,
  848. ForwardGetKernelNDrangeSubGroupCountNonDominantParameter4Bad) {
  849. std::string instruction = GetParam().first;
  850. bool with_ndrange = GetParam().second;
  851. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  852. std::stringstream ss;
  853. // clang-format off
  854. ss << forwardKernelNonDominantParameterBaseCode("firstp2") + " %numsg = "
  855. << instruction + " %uintt" + ndrange_param + "%kfunc %firstp2 %psize %palign"
  856. << "\n %firstp2 = OpCopyObject %int8t %firstp"
  857. << return_instructions;
  858. // clang-format on
  859. CompileSuccessfully(ss.str());
  860. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  861. EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2"));
  862. }
  863. TEST_P(ValidateSSA,
  864. ForwardGetKernelNDrangeSubGroupCountNonDominantParameter5Bad) {
  865. std::string instruction = GetParam().first;
  866. bool with_ndrange = GetParam().second;
  867. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  868. std::stringstream ss;
  869. // clang-format off
  870. ss << forwardKernelNonDominantParameterBaseCode("psize2") + " %numsg = "
  871. << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize2 %palign"
  872. << "\n %psize2 = OpCopyObject %uintt %psize"
  873. << return_instructions;
  874. // clang-format on
  875. CompileSuccessfully(ss.str());
  876. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  877. EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2"));
  878. }
  879. TEST_P(ValidateSSA,
  880. ForwardGetKernelNDrangeSubGroupCountNonDominantParameter6Bad) {
  881. std::string instruction = GetParam().first;
  882. bool with_ndrange = GetParam().second;
  883. std::string ndrange_param = with_ndrange ? " %ndval " : " ";
  884. std::stringstream ss;
  885. // clang-format off
  886. ss << forwardKernelNonDominantParameterBaseCode("palign2") + " %numsg = "
  887. << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign2"
  888. << "\n %palign2 = OpCopyObject %uintt %palign"
  889. << return_instructions;
  890. // clang-format on
  891. if (GetParam().second) {
  892. CompileSuccessfully(ss.str());
  893. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  894. EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2"));
  895. }
  896. }
  897. TEST_F(ValidateSSA, PhiGood) {
  898. std::string str = kHeader + kBasicTypes +
  899. R"(
  900. %func = OpFunction %voidt None %vfunct
  901. %preheader = OpLabel
  902. %init = OpCopyObject %uintt %zero
  903. OpBranch %loop
  904. %loop = OpLabel
  905. %i = OpPhi %uintt %init %preheader %loopi %loop
  906. %loopi = OpIAdd %uintt %i %one
  907. OpNop
  908. %cond = OpSLessThan %boolt %i %ten
  909. OpLoopMerge %endl %loop None
  910. OpBranchConditional %cond %loop %endl
  911. %endl = OpLabel
  912. OpReturn
  913. OpFunctionEnd
  914. )";
  915. CompileSuccessfully(str);
  916. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  917. }
  918. TEST_F(ValidateSSA, PhiMissingTypeBad) {
  919. std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
  920. R"(
  921. %func = OpFunction %voidt None %vfunct
  922. %preheader = OpLabel
  923. %init = OpCopyObject %uintt %zero
  924. OpBranch %loop
  925. %loop = OpLabel
  926. %i = OpPhi %missing %init %preheader %loopi %loop
  927. %loopi = OpIAdd %uintt %i %one
  928. OpNop
  929. %cond = OpSLessThan %boolt %i %ten
  930. OpLoopMerge %endl %loop None
  931. OpBranchConditional %cond %loop %endl
  932. %endl = OpLabel
  933. OpReturn
  934. OpFunctionEnd
  935. )";
  936. CompileSuccessfully(str);
  937. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  938. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  939. }
  940. TEST_F(ValidateSSA, PhiMissingIdBad) {
  941. std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
  942. R"(
  943. %func = OpFunction %voidt None %vfunct
  944. %preheader = OpLabel
  945. %init = OpCopyObject %uintt %zero
  946. OpBranch %loop
  947. %loop = OpLabel
  948. %i = OpPhi %uintt %missing %preheader %loopi %loop
  949. %loopi = OpIAdd %uintt %i %one
  950. OpNop
  951. %cond = OpSLessThan %boolt %i %ten
  952. OpLoopMerge %endl %loop None
  953. OpBranchConditional %cond %loop %endl
  954. %endl = OpLabel
  955. OpReturn
  956. OpFunctionEnd
  957. )";
  958. CompileSuccessfully(str);
  959. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  960. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  961. }
  962. TEST_F(ValidateSSA, PhiMissingLabelBad) {
  963. std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
  964. R"(
  965. %func = OpFunction %voidt None %vfunct
  966. %preheader = OpLabel
  967. %init = OpCopyObject %uintt %zero
  968. OpBranch %loop
  969. %loop = OpLabel
  970. %i = OpPhi %uintt %init %missing %loopi %loop
  971. %loopi = OpIAdd %uintt %i %one
  972. OpNop
  973. %cond = OpSLessThan %boolt %i %ten
  974. OpLoopMerge %endl %loop None
  975. OpBranchConditional %cond %loop %endl
  976. %endl = OpLabel
  977. OpReturn
  978. OpFunctionEnd
  979. )";
  980. CompileSuccessfully(str);
  981. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  982. EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
  983. }
  984. TEST_F(ValidateSSA, IdDominatesItsUseGood) {
  985. std::string str = kHeader + kBasicTypes +
  986. R"(
  987. %func = OpFunction %voidt None %vfunct
  988. %entry = OpLabel
  989. %cond = OpSLessThan %boolt %one %ten
  990. %eleven = OpIAdd %uintt %one %ten
  991. OpSelectionMerge %merge None
  992. OpBranchConditional %cond %t %f
  993. %t = OpLabel
  994. %twelve = OpIAdd %uintt %eleven %one
  995. OpBranch %merge
  996. %f = OpLabel
  997. %twentytwo = OpIAdd %uintt %eleven %ten
  998. OpBranch %merge
  999. %merge = OpLabel
  1000. OpReturn
  1001. OpFunctionEnd
  1002. )";
  1003. CompileSuccessfully(str);
  1004. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1005. }
  1006. TEST_F(ValidateSSA, IdDoesNotDominateItsUseBad) {
  1007. std::string str = kHeader +
  1008. "OpName %eleven \"eleven\"\n"
  1009. "OpName %true_block \"true_block\"\n"
  1010. "OpName %false_block \"false_block\"" +
  1011. kBasicTypes +
  1012. R"(
  1013. %func = OpFunction %voidt None %vfunct
  1014. %entry = OpLabel
  1015. %cond = OpSLessThan %boolt %one %ten
  1016. OpSelectionMerge %merge None
  1017. OpBranchConditional %cond %true_block %false_block
  1018. %true_block = OpLabel
  1019. %eleven = OpIAdd %uintt %one %ten
  1020. %twelve = OpIAdd %uintt %eleven %one
  1021. OpBranch %merge
  1022. %false_block = OpLabel
  1023. %twentytwo = OpIAdd %uintt %eleven %ten
  1024. OpBranch %merge
  1025. %merge = OpLabel
  1026. OpReturn
  1027. OpFunctionEnd
  1028. )";
  1029. CompileSuccessfully(str);
  1030. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1031. EXPECT_THAT(
  1032. getDiagnosticString(),
  1033. MatchesRegex("ID '.\\[%eleven\\]' defined in block '.\\[%true_block\\]' "
  1034. "does not dominate its use in block '.\\[%false_block\\]'\n"
  1035. " %false_block = OpLabel\n"));
  1036. }
  1037. TEST_F(ValidateSSA, PhiUseDoesntDominateDefinitionGood) {
  1038. std::string str = kHeader + kBasicTypes +
  1039. R"(
  1040. %funcintptrt = OpTypePointer Function %uintt
  1041. %func = OpFunction %voidt None %vfunct
  1042. %entry = OpLabel
  1043. %var_one = OpVariable %funcintptrt Function %one
  1044. %one_val = OpLoad %uintt %var_one
  1045. OpBranch %loop
  1046. %loop = OpLabel
  1047. %i = OpPhi %uintt %one_val %entry %inew %cont
  1048. %cond = OpSLessThan %boolt %one %ten
  1049. OpLoopMerge %merge %cont None
  1050. OpBranchConditional %cond %body %merge
  1051. %body = OpLabel
  1052. OpBranch %cont
  1053. %cont = OpLabel
  1054. %inew = OpIAdd %uintt %i %one
  1055. OpBranch %loop
  1056. %merge = OpLabel
  1057. OpReturn
  1058. OpFunctionEnd
  1059. )";
  1060. CompileSuccessfully(str);
  1061. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1062. }
  1063. TEST_F(ValidateSSA,
  1064. PhiUseDoesntDominateUseOfPhiOperandUsedBeforeDefinitionBad) {
  1065. std::string str = kHeader + "OpName %inew \"inew\"" + kBasicTypes +
  1066. R"(
  1067. %func = OpFunction %voidt None %vfunct
  1068. %entry = OpLabel
  1069. %var_one = OpVariable %intptrt Function %one
  1070. %one_val = OpLoad %uintt %var_one
  1071. OpBranch %loop
  1072. %loop = OpLabel
  1073. %i = OpPhi %uintt %one_val %entry %inew %cont
  1074. %bad = OpIAdd %uintt %inew %one
  1075. %cond = OpSLessThan %boolt %one %ten
  1076. OpLoopMerge %merge %cont None
  1077. OpBranchConditional %cond %body %merge
  1078. %body = OpLabel
  1079. OpBranch %cont
  1080. %cont = OpLabel
  1081. %inew = OpIAdd %uintt %i %one
  1082. OpBranch %loop
  1083. %merge = OpLabel
  1084. OpReturn
  1085. OpFunctionEnd
  1086. )";
  1087. CompileSuccessfully(str);
  1088. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1089. EXPECT_THAT(getDiagnosticString(),
  1090. MatchesRegex("ID '.\\[%inew\\]' has not been defined\n"
  1091. " %19 = OpIAdd %uint %inew %uint_1\n"));
  1092. }
  1093. TEST_F(ValidateSSA, PhiUseMayComeFromNonDominatingBlockGood) {
  1094. std::string str = kHeader + "OpName %if_true \"if_true\"\n" +
  1095. "OpName %exit \"exit\"\n" + "OpName %copy \"copy\"\n" +
  1096. kBasicTypes +
  1097. R"(
  1098. %func = OpFunction %voidt None %vfunct
  1099. %entry = OpLabel
  1100. OpBranchConditional %false %if_true %exit
  1101. %if_true = OpLabel
  1102. %copy = OpCopyObject %boolt %false
  1103. OpBranch %exit
  1104. ; The use of %copy here is ok, even though it was defined
  1105. ; in a block that does not dominate %exit. That's the point
  1106. ; of an OpPhi.
  1107. %exit = OpLabel
  1108. %value = OpPhi %boolt %false %entry %copy %if_true
  1109. OpReturn
  1110. OpFunctionEnd
  1111. )";
  1112. CompileSuccessfully(str);
  1113. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  1114. }
  1115. TEST_F(ValidateSSA, PhiUsesItsOwnDefinitionGood) {
  1116. // See https://github.com/KhronosGroup/SPIRV-Tools/issues/415
  1117. //
  1118. // Non-phi instructions can't use their own definitions, as
  1119. // already checked in test DominateUsageSameInstructionBad.
  1120. std::string str = kHeader + "OpName %loop \"loop\"\n" +
  1121. "OpName %value \"value\"\n" + kBasicTypes +
  1122. R"(
  1123. %func = OpFunction %voidt None %vfunct
  1124. %entry = OpLabel
  1125. OpBranch %loop
  1126. %loop = OpLabel
  1127. %value = OpPhi %boolt %false %entry %value %loop
  1128. OpBranch %loop
  1129. OpFunctionEnd
  1130. )";
  1131. CompileSuccessfully(str);
  1132. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  1133. }
  1134. TEST_F(ValidateSSA, PhiVariableDefNotDominatedByParentBlockBad) {
  1135. std::string str = kHeader + "OpName %if_true \"if_true\"\n" +
  1136. "OpName %if_false \"if_false\"\n" +
  1137. "OpName %exit \"exit\"\n" + "OpName %value \"phi\"\n" +
  1138. "OpName %true_copy \"true_copy\"\n" +
  1139. "OpName %false_copy \"false_copy\"\n" + kBasicTypes +
  1140. R"(
  1141. %func = OpFunction %voidt None %vfunct
  1142. %entry = OpLabel
  1143. OpBranchConditional %false %if_true %if_false
  1144. %if_true = OpLabel
  1145. %true_copy = OpCopyObject %boolt %false
  1146. OpBranch %exit
  1147. %if_false = OpLabel
  1148. %false_copy = OpCopyObject %boolt %false
  1149. OpBranch %exit
  1150. ; The (variable,Id) pairs are swapped.
  1151. %exit = OpLabel
  1152. %value = OpPhi %boolt %true_copy %if_false %false_copy %if_true
  1153. OpReturn
  1154. OpFunctionEnd
  1155. )";
  1156. CompileSuccessfully(str);
  1157. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1158. EXPECT_THAT(getDiagnosticString(),
  1159. MatchesRegex(
  1160. "In OpPhi instruction '.\\[%phi\\]', ID '.\\[%true_copy\\]' "
  1161. "definition does not dominate its parent '.\\[%if_false\\]'\n"
  1162. " %phi = OpPhi %bool %true_copy %if_false %false_copy "
  1163. "%if_true\n"));
  1164. }
  1165. TEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) {
  1166. std::string str = kHeader + "OpName %if_true \"if_true\"\n" + kBasicTypes +
  1167. R"(
  1168. %func = OpFunction %voidt None %vfunct
  1169. %entry = OpLabel
  1170. OpBranchConditional %false %if_true %if_false
  1171. %if_true = OpLabel
  1172. %true_copy = OpCopyObject %boolt %false
  1173. OpBranch %if_tnext
  1174. %if_tnext = OpLabel
  1175. OpBranch %exit
  1176. %if_false = OpLabel
  1177. %false_copy = OpCopyObject %boolt %false
  1178. OpBranch %if_fnext
  1179. %if_fnext = OpLabel
  1180. OpBranch %exit
  1181. %exit = OpLabel
  1182. %value = OpPhi %boolt %true_copy %if_tnext %false_copy %if_fnext
  1183. OpReturn
  1184. OpFunctionEnd
  1185. )";
  1186. CompileSuccessfully(str);
  1187. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1188. }
  1189. TEST_F(ValidateSSA,
  1190. DominanceCheckIgnoresUsesInUnreachableBlocksDefInBlockGood) {
  1191. std::string str = kHeader + kBasicTypes +
  1192. R"(
  1193. %func = OpFunction %voidt None %vfunct
  1194. %entry = OpLabel
  1195. %def = OpCopyObject %boolt %false
  1196. OpReturn
  1197. %unreach = OpLabel
  1198. %use = OpCopyObject %boolt %def
  1199. OpReturn
  1200. OpFunctionEnd
  1201. )";
  1202. CompileSuccessfully(str);
  1203. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  1204. }
  1205. TEST_F(ValidateSSA, PhiVariableUnreachableDefNotInParentBlock) {
  1206. std::string str = kHeader + "OpName %unreachable \"unreachable\"\n" +
  1207. kBasicTypes +
  1208. R"(
  1209. %func = OpFunction %voidt None %vfunct
  1210. %entry = OpLabel
  1211. OpBranch %if_false
  1212. %unreachable = OpLabel
  1213. %copy = OpCopyObject %boolt %false
  1214. OpBranch %if_tnext
  1215. %if_tnext = OpLabel
  1216. OpBranch %exit
  1217. %if_false = OpLabel
  1218. %false_copy = OpCopyObject %boolt %false
  1219. OpBranch %if_fnext
  1220. %if_fnext = OpLabel
  1221. OpBranch %exit
  1222. %exit = OpLabel
  1223. %value = OpPhi %boolt %copy %if_tnext %false_copy %if_fnext
  1224. OpReturn
  1225. OpFunctionEnd
  1226. )";
  1227. CompileSuccessfully(str);
  1228. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1229. }
  1230. TEST_F(ValidateSSA,
  1231. DominanceCheckIgnoresUsesInUnreachableBlocksDefIsParamGood) {
  1232. std::string str = kHeader + kBasicTypes +
  1233. R"(
  1234. %void_fn_int = OpTypeFunction %voidt %uintt
  1235. %func = OpFunction %voidt None %void_fn_int
  1236. %int_param = OpFunctionParameter %uintt
  1237. %entry = OpLabel
  1238. OpReturn
  1239. %unreach = OpLabel
  1240. %use = OpCopyObject %uintt %int_param
  1241. OpReturn
  1242. OpFunctionEnd
  1243. )";
  1244. CompileSuccessfully(str);
  1245. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  1246. }
  1247. TEST_F(ValidateSSA, UseFunctionParameterFromOtherFunctionBad) {
  1248. std::string str = kHeader +
  1249. "OpName %first \"first\"\n"
  1250. "OpName %func \"func\"\n" +
  1251. "OpName %func2 \"func2\"\n" + kBasicTypes +
  1252. R"(
  1253. %viifunct = OpTypeFunction %voidt %uintt %uintt
  1254. %func = OpFunction %voidt None %viifunct
  1255. %first = OpFunctionParameter %uintt
  1256. %second = OpFunctionParameter %uintt
  1257. OpFunctionEnd
  1258. %func2 = OpFunction %voidt None %viifunct
  1259. %first2 = OpFunctionParameter %uintt
  1260. %second2 = OpFunctionParameter %uintt
  1261. %entry2 = OpLabel
  1262. %baduse = OpIAdd %uintt %first %first2
  1263. OpReturn
  1264. OpFunctionEnd
  1265. )";
  1266. CompileSuccessfully(str);
  1267. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1268. EXPECT_THAT(getDiagnosticString(),
  1269. MatchesRegex(
  1270. "ID '.\\[%first\\]' used in function '.\\[%func2\\]' is used "
  1271. "outside of it's defining function '.\\[%func\\]'\n"
  1272. " %func = OpFunction %void None %14\n"));
  1273. }
  1274. TEST_F(ValidateSSA, TypeForwardPointerForwardReference) {
  1275. // See https://github.com/KhronosGroup/SPIRV-Tools/issues/429
  1276. //
  1277. // ForwardPointers can references instructions that have not been defined
  1278. std::string str = R"(
  1279. OpCapability Kernel
  1280. OpCapability Addresses
  1281. OpCapability Linkage
  1282. OpMemoryModel Logical OpenCL
  1283. OpName %intptrt "intptrt"
  1284. OpTypeForwardPointer %intptrt UniformConstant
  1285. %uint = OpTypeInt 32 0
  1286. %struct = OpTypeStruct %uint
  1287. %intptrt = OpTypePointer UniformConstant %struct
  1288. )";
  1289. CompileSuccessfully(str);
  1290. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1291. }
  1292. TEST_F(ValidateSSA, TypeStructForwardReference) {
  1293. std::string str = R"(
  1294. OpCapability Kernel
  1295. OpCapability Addresses
  1296. OpCapability Linkage
  1297. OpMemoryModel Logical OpenCL
  1298. OpName %structptr "structptr"
  1299. OpTypeForwardPointer %structptr UniformConstant
  1300. %uint = OpTypeInt 32 0
  1301. %structt1 = OpTypeStruct %structptr %uint
  1302. %structt2 = OpTypeStruct %uint %structptr
  1303. %structt3 = OpTypeStruct %uint %uint %structptr
  1304. %structt4 = OpTypeStruct %uint %uint %uint %structptr
  1305. %structptr = OpTypePointer UniformConstant %structt1
  1306. )";
  1307. CompileSuccessfully(str);
  1308. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  1309. }
  1310. // TODO(umar): OpGroupMemberDecorate
  1311. } // namespace
  1312. } // namespace val
  1313. } // namespace spvtools