fold_spec_const_op_composite_test.cpp 89 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006
  1. // Copyright (c) 2016 Google 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. #include <sstream>
  15. #include <string>
  16. #include <vector>
  17. #include "test/opt/assembly_builder.h"
  18. #include "test/opt/pass_fixture.h"
  19. #include "test/opt/pass_utils.h"
  20. namespace spvtools {
  21. namespace opt {
  22. namespace {
  23. using FoldSpecConstantOpAndCompositePassBasicTest = PassTest<::testing::Test>;
  24. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Empty) {
  25. SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
  26. "", "", /* skip_nop = */ true);
  27. }
  28. // A test of the basic functionality of FoldSpecConstantOpAndCompositePass.
  29. // A spec constant defined with an integer addition operation should be folded
  30. // to a normal constant with fixed value.
  31. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Basic) {
  32. AssemblyBuilder builder;
  33. builder.AppendTypesConstantsGlobals({
  34. // clang-format off
  35. "%int = OpTypeInt 32 1",
  36. "%frozen_spec_const_int = OpConstant %int 1",
  37. "%const_int = OpConstant %int 2",
  38. // Folding target:
  39. "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int",
  40. // clang-format on
  41. });
  42. std::vector<const char*> expected = {
  43. // clang-format off
  44. "OpCapability Shader",
  45. "OpCapability Float64",
  46. "%1 = OpExtInstImport \"GLSL.std.450\"",
  47. "OpMemoryModel Logical GLSL450",
  48. "OpEntryPoint Vertex %main \"main\"",
  49. "OpName %void \"void\"",
  50. "OpName %main_func_type \"main_func_type\"",
  51. "OpName %main \"main\"",
  52. "OpName %main_func_entry_block \"main_func_entry_block\"",
  53. "OpName %int \"int\"",
  54. "OpName %frozen_spec_const_int \"frozen_spec_const_int\"",
  55. "OpName %const_int \"const_int\"",
  56. "OpName %spec_add \"spec_add\"",
  57. "%void = OpTypeVoid",
  58. "%main_func_type = OpTypeFunction %void",
  59. "%int = OpTypeInt 32 1",
  60. "%frozen_spec_const_int = OpConstant %int 1",
  61. "%const_int = OpConstant %int 2",
  62. // The SpecConstantOp IAdd instruction should be replace by OpConstant
  63. // instruction:
  64. "%spec_add = OpConstant %int 3",
  65. "%main = OpFunction %void None %main_func_type",
  66. "%main_func_entry_block = OpLabel",
  67. "OpReturn",
  68. "OpFunctionEnd",
  69. // clang-format on
  70. };
  71. SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
  72. builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
  73. }
  74. // A test of skipping folding an instruction when the instruction result type
  75. // has decorations.
  76. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  77. SkipWhenTypeHasDecorations) {
  78. AssemblyBuilder builder;
  79. builder
  80. .AppendAnnotations({
  81. // clang-format off
  82. "OpDecorate %int RelaxedPrecision",
  83. // clang-format on
  84. })
  85. .AppendTypesConstantsGlobals({
  86. // clang-format off
  87. "%int = OpTypeInt 32 1",
  88. "%frozen_spec_const_int = OpConstant %int 1",
  89. "%const_int = OpConstant %int 2",
  90. // The following spec constant should not be folded as the result type
  91. // has relaxed precision decoration.
  92. "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int",
  93. // clang-format on
  94. });
  95. SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
  96. builder.GetCode(), builder.GetCode(), /* skip_nop = */ true);
  97. }
  98. // Test where OpSpecConstantOp depends on another OpSpecConstantOp with
  99. // CompositeExtract
  100. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedCompositeExtract) {
  101. AssemblyBuilder builder;
  102. builder.AppendTypesConstantsGlobals({
  103. // clang-format off
  104. "%uint = OpTypeInt 32 0",
  105. "%v3uint = OpTypeVector %uint 3",
  106. "%uint_2 = OpConstant %uint 2",
  107. "%uint_3 = OpConstant %uint 3",
  108. // Folding target:
  109. "%composite_0 = OpSpecConstantComposite %v3uint %uint_2 %uint_3 %uint_2",
  110. "%op_0 = OpSpecConstantOp %uint CompositeExtract %composite_0 0",
  111. "%op_1 = OpSpecConstantOp %uint CompositeExtract %composite_0 1",
  112. "%op_2 = OpSpecConstantOp %uint IMul %op_0 %op_1",
  113. "%composite_1 = OpSpecConstantComposite %v3uint %op_0 %op_1 %op_2",
  114. "%op_3 = OpSpecConstantOp %uint CompositeExtract %composite_1 0",
  115. "%op_4 = OpSpecConstantOp %uint IMul %op_2 %op_3",
  116. // clang-format on
  117. });
  118. std::vector<const char*> expected = {
  119. // clang-format off
  120. "OpCapability Shader",
  121. "OpCapability Float64",
  122. "%1 = OpExtInstImport \"GLSL.std.450\"",
  123. "OpMemoryModel Logical GLSL450",
  124. "OpEntryPoint Vertex %main \"main\"",
  125. "OpName %void \"void\"",
  126. "OpName %main_func_type \"main_func_type\"",
  127. "OpName %main \"main\"",
  128. "OpName %main_func_entry_block \"main_func_entry_block\"",
  129. "OpName %uint \"uint\"",
  130. "OpName %v3uint \"v3uint\"",
  131. "OpName %uint_2 \"uint_2\"",
  132. "OpName %uint_3 \"uint_3\"",
  133. "OpName %composite_0 \"composite_0\"",
  134. "OpName %op_0 \"op_0\"",
  135. "OpName %op_1 \"op_1\"",
  136. "OpName %op_2 \"op_2\"",
  137. "OpName %composite_1 \"composite_1\"",
  138. "OpName %op_3 \"op_3\"",
  139. "OpName %op_4 \"op_4\"",
  140. "%void = OpTypeVoid",
  141. "%main_func_type = OpTypeFunction %void",
  142. "%uint = OpTypeInt 32 0",
  143. "%v3uint = OpTypeVector %uint 3",
  144. "%uint_2 = OpConstant %uint 2",
  145. "%uint_3 = OpConstant %uint 3",
  146. "%composite_0 = OpConstantComposite %v3uint %uint_2 %uint_3 %uint_2",
  147. "%op_0 = OpConstant %uint 2",
  148. "%op_1 = OpConstant %uint 3",
  149. "%op_2 = OpConstant %uint 6",
  150. "%composite_1 = OpConstantComposite %v3uint %op_0 %op_1 %op_2",
  151. "%op_3 = OpConstant %uint 2",
  152. "%op_4 = OpConstant %uint 12",
  153. "%main = OpFunction %void None %main_func_type",
  154. "%main_func_entry_block = OpLabel",
  155. "OpReturn",
  156. "OpFunctionEnd",
  157. // clang-format on
  158. };
  159. SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
  160. builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
  161. }
  162. // Test where OpSpecConstantOp depends on another OpSpecConstantOp with
  163. // VectorShuffle
  164. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedVectorShuffle) {
  165. AssemblyBuilder builder;
  166. builder.AppendTypesConstantsGlobals({
  167. // clang-format off
  168. "%uint = OpTypeInt 32 0",
  169. "%v3uint = OpTypeVector %uint 3",
  170. "%uint_1 = OpConstant %uint 1",
  171. "%uint_2 = OpConstant %uint 2",
  172. "%uint_3 = OpConstant %uint 3",
  173. "%uint_4 = OpConstant %uint 4",
  174. "%uint_5 = OpConstant %uint 5",
  175. "%uint_6 = OpConstant %uint 6",
  176. // Folding target:
  177. "%composite_0 = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_3",
  178. "%composite_1 = OpSpecConstantComposite %v3uint %uint_4 %uint_5 %uint_6",
  179. "%vecshuffle = OpSpecConstantOp %v3uint VectorShuffle %composite_0 %composite_1 0 5 3",
  180. "%op = OpSpecConstantOp %uint CompositeExtract %vecshuffle 1",
  181. // clang-format on
  182. });
  183. std::vector<const char*> expected = {
  184. // clang-format off
  185. "OpCapability Shader",
  186. "OpCapability Float64",
  187. "%1 = OpExtInstImport \"GLSL.std.450\"",
  188. "OpMemoryModel Logical GLSL450",
  189. "OpEntryPoint Vertex %main \"main\"",
  190. "OpName %void \"void\"",
  191. "OpName %main_func_type \"main_func_type\"",
  192. "OpName %main \"main\"",
  193. "OpName %main_func_entry_block \"main_func_entry_block\"",
  194. "OpName %uint \"uint\"",
  195. "OpName %v3uint \"v3uint\"",
  196. "OpName %uint_1 \"uint_1\"",
  197. "OpName %uint_2 \"uint_2\"",
  198. "OpName %uint_3 \"uint_3\"",
  199. "OpName %uint_4 \"uint_4\"",
  200. "OpName %uint_5 \"uint_5\"",
  201. "OpName %uint_6 \"uint_6\"",
  202. "OpName %composite_0 \"composite_0\"",
  203. "OpName %composite_1 \"composite_1\"",
  204. "OpName %vecshuffle \"vecshuffle\"",
  205. "OpName %op \"op\"",
  206. "%void = OpTypeVoid",
  207. "%main_func_type = OpTypeFunction %void",
  208. "%uint = OpTypeInt 32 0",
  209. "%v3uint = OpTypeVector %uint 3",
  210. "%uint_1 = OpConstant %uint 1",
  211. "%uint_2 = OpConstant %uint 2",
  212. "%uint_3 = OpConstant %uint 3",
  213. "%uint_4 = OpConstant %uint 4",
  214. "%uint_5 = OpConstant %uint 5",
  215. "%uint_6 = OpConstant %uint 6",
  216. "%composite_0 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3",
  217. "%composite_1 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6",
  218. "%vecshuffle = OpConstantComposite %v3uint %uint_1 %uint_6 %uint_4",
  219. "%op = OpConstant %uint 6",
  220. "%main = OpFunction %void None %main_func_type",
  221. "%main_func_entry_block = OpLabel",
  222. "OpReturn",
  223. "OpFunctionEnd",
  224. // clang-format on
  225. };
  226. SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
  227. builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
  228. }
  229. // Test CompositeExtract with matrix
  230. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeExtractMaxtrix) {
  231. AssemblyBuilder builder;
  232. builder.AppendTypesConstantsGlobals({
  233. // clang-format off
  234. "%uint = OpTypeInt 32 0",
  235. "%v3uint = OpTypeVector %uint 3",
  236. "%mat3x3 = OpTypeMatrix %v3uint 3",
  237. "%uint_1 = OpConstant %uint 1",
  238. "%uint_2 = OpConstant %uint 2",
  239. "%uint_3 = OpConstant %uint 3",
  240. // Folding target:
  241. "%a = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_1",
  242. "%b = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_3",
  243. "%c = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_1",
  244. "%op = OpSpecConstantComposite %mat3x3 %a %b %c",
  245. "%x = OpSpecConstantOp %uint CompositeExtract %op 2 1",
  246. "%y = OpSpecConstantOp %uint CompositeExtract %op 1 2",
  247. // clang-format on
  248. });
  249. std::vector<const char*> expected = {
  250. // clang-format off
  251. "OpCapability Shader",
  252. "OpCapability Float64",
  253. "%1 = OpExtInstImport \"GLSL.std.450\"",
  254. "OpMemoryModel Logical GLSL450",
  255. "OpEntryPoint Vertex %main \"main\"",
  256. "OpName %void \"void\"",
  257. "OpName %main_func_type \"main_func_type\"",
  258. "OpName %main \"main\"",
  259. "OpName %main_func_entry_block \"main_func_entry_block\"",
  260. "OpName %uint \"uint\"",
  261. "OpName %v3uint \"v3uint\"",
  262. "OpName %mat3x3 \"mat3x3\"",
  263. "OpName %uint_1 \"uint_1\"",
  264. "OpName %uint_2 \"uint_2\"",
  265. "OpName %uint_3 \"uint_3\"",
  266. "OpName %a \"a\"",
  267. "OpName %b \"b\"",
  268. "OpName %c \"c\"",
  269. "OpName %op \"op\"",
  270. "OpName %x \"x\"",
  271. "OpName %y \"y\"",
  272. "%void = OpTypeVoid",
  273. "%main_func_type = OpTypeFunction %void",
  274. "%uint = OpTypeInt 32 0",
  275. "%v3uint = OpTypeVector %uint 3",
  276. "%mat3x3 = OpTypeMatrix %v3uint 3",
  277. "%uint_1 = OpConstant %uint 1",
  278. "%uint_2 = OpConstant %uint 2",
  279. "%uint_3 = OpConstant %uint 3",
  280. "%a = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1",
  281. "%b = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_3",
  282. "%c = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_1",
  283. "%op = OpConstantComposite %mat3x3 %a %b %c",
  284. "%x = OpConstant %uint 2",
  285. "%y = OpConstant %uint 3",
  286. "%main = OpFunction %void None %main_func_type",
  287. "%main_func_entry_block = OpLabel",
  288. "OpReturn",
  289. "OpFunctionEnd",
  290. // clang-format on
  291. };
  292. SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
  293. builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
  294. }
  295. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVector) {
  296. const std::string test =
  297. R"(
  298. OpCapability Shader
  299. OpMemoryModel Logical GLSL450
  300. OpEntryPoint GLCompute %1 "main"
  301. OpExecutionMode %1 LocalSize 1 1 1
  302. %void = OpTypeVoid
  303. %3 = OpTypeFunction %void
  304. %uint = OpTypeInt 32 0
  305. %v3uint = OpTypeVector %uint 3
  306. %uint_2 = OpConstant %uint 2
  307. %uint_3 = OpConstant %uint 3
  308. %8 = OpConstantNull %uint
  309. %9 = OpSpecConstantComposite %v3uint %uint_2 %uint_2 %uint_2
  310. ; CHECK: %15 = OpConstantComposite %v3uint %uint_3 %uint_2 %uint_2
  311. ; CHECK: %uint_3_0 = OpConstant %uint 3
  312. ; CHECK: %17 = OpConstantComposite %v3uint %8 %uint_2 %uint_2
  313. ; CHECK: %18 = OpConstantNull %uint
  314. %10 = OpSpecConstantOp %v3uint CompositeInsert %uint_3 %9 0
  315. %11 = OpSpecConstantOp %uint CompositeExtract %10 0
  316. %12 = OpSpecConstantOp %v3uint CompositeInsert %8 %9 0
  317. %13 = OpSpecConstantOp %uint CompositeExtract %12 0
  318. %1 = OpFunction %void None %3
  319. %14 = OpLabel
  320. OpReturn
  321. OpFunctionEnd
  322. )";
  323. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  324. }
  325. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  326. CompositeInsertVectorIntoMatrix) {
  327. const std::string test =
  328. R"(
  329. OpCapability Shader
  330. OpMemoryModel Logical GLSL450
  331. OpEntryPoint GLCompute %1 "main"
  332. OpExecutionMode %1 LocalSize 1 1 1
  333. %void = OpTypeVoid
  334. %3 = OpTypeFunction %void
  335. %float = OpTypeFloat 32
  336. %v2float = OpTypeVector %float 2
  337. %mat2v2float = OpTypeMatrix %v2float 2
  338. %float_0 = OpConstant %float 0
  339. %float_1 = OpConstant %float 1
  340. %float_2 = OpConstant %float 2
  341. %v2float_01 = OpConstantComposite %v2float %float_0 %float_1
  342. %v2float_12 = OpConstantComposite %v2float %float_1 %float_2
  343. ; CHECK: %10 = OpConstantComposite %v2float %float_0 %float_1
  344. ; CHECK: %11 = OpConstantComposite %v2float %float_1 %float_2
  345. ; CHECK: %12 = OpConstantComposite %mat2v2float %11 %11
  346. %mat2v2float_1212 = OpConstantComposite %mat2v2float %v2float_12 %v2float_12
  347. ; CHECK: %15 = OpConstantComposite %mat2v2float %10 %11
  348. %spec_0 = OpSpecConstantOp %mat2v2float CompositeInsert %v2float_01 %mat2v2float_1212 0
  349. %1 = OpFunction %void None %3
  350. %label = OpLabel
  351. OpReturn
  352. OpFunctionEnd
  353. )";
  354. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  355. }
  356. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrix) {
  357. const std::string test =
  358. R"(
  359. OpCapability Shader
  360. OpMemoryModel Logical GLSL450
  361. OpEntryPoint GLCompute %1 "main"
  362. OpExecutionMode %1 LocalSize 1 1 1
  363. %void = OpTypeVoid
  364. %3 = OpTypeFunction %void
  365. %float = OpTypeFloat 32
  366. %v3float = OpTypeVector %float 3
  367. %mat3v3float = OpTypeMatrix %v3float 3
  368. %float_1 = OpConstant %float 1
  369. %float_2 = OpConstant %float 2
  370. %9 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1
  371. %10 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1
  372. %11 = OpSpecConstantComposite %v3float %float_1 %float_2 %float_1
  373. %12 = OpSpecConstantComposite %mat3v3float %9 %10 %11
  374. ; CHECK: %float_2_0 = OpConstant %float 2
  375. ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_2
  376. ; CHECK: %19 = OpConstantComposite %mat3v3float %9 %18 %11
  377. ; CHECK: %float_2_1 = OpConstant %float 2
  378. %13 = OpSpecConstantOp %float CompositeExtract %12 2 1
  379. %14 = OpSpecConstantOp %mat3v3float CompositeInsert %13 %12 1 2
  380. %15 = OpSpecConstantOp %float CompositeExtract %14 1 2
  381. %1 = OpFunction %void None %3
  382. %16 = OpLabel
  383. OpReturn
  384. OpFunctionEnd
  385. )";
  386. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  387. }
  388. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertFloatNull) {
  389. const std::string test =
  390. R"(
  391. OpCapability Shader
  392. OpMemoryModel Logical GLSL450
  393. OpEntryPoint GLCompute %1 "main"
  394. OpExecutionMode %1 LocalSize 1 1 1
  395. %void = OpTypeVoid
  396. %3 = OpTypeFunction %void
  397. %float = OpTypeFloat 32
  398. %v3float = OpTypeVector %float 3
  399. %float_1 = OpConstant %float 1
  400. ; CHECK: %7 = OpConstantNull %float
  401. ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %7
  402. ; CHECK: %12 = OpConstantComposite %v3float %7 %7 %float_1
  403. %null = OpConstantNull %float
  404. %spec_0 = OpConstantComposite %v3float %null %null %null
  405. %spec_1 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_0 2
  406. ; CHECK: %float_1_0 = OpConstant %float 1
  407. %spec_2 = OpSpecConstantOp %float CompositeExtract %spec_1 2
  408. %1 = OpFunction %void None %3
  409. %label = OpLabel
  410. OpReturn
  411. OpFunctionEnd
  412. )";
  413. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  414. }
  415. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  416. CompositeInsertFloatSetNull) {
  417. const std::string test =
  418. R"(
  419. OpCapability Shader
  420. OpMemoryModel Logical GLSL450
  421. OpEntryPoint GLCompute %1 "main"
  422. OpExecutionMode %1 LocalSize 1 1 1
  423. %void = OpTypeVoid
  424. %3 = OpTypeFunction %void
  425. %float = OpTypeFloat 32
  426. %v3float = OpTypeVector %float 3
  427. %float_1 = OpConstant %float 1
  428. ; CHECK: %7 = OpConstantNull %float
  429. ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %float_1
  430. ; CHECK: %12 = OpConstantComposite %v3float %7 %7 %7
  431. %null = OpConstantNull %float
  432. %spec_0 = OpConstantComposite %v3float %null %null %float_1
  433. %spec_1 = OpSpecConstantOp %v3float CompositeInsert %null %spec_0 2
  434. ; CHECK: %13 = OpConstantNull %float
  435. %spec_2 = OpSpecConstantOp %float CompositeExtract %spec_1 2
  436. %1 = OpFunction %void None %3
  437. %label = OpLabel
  438. OpReturn
  439. OpFunctionEnd
  440. )";
  441. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  442. }
  443. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorNull) {
  444. const std::string test =
  445. R"(
  446. OpCapability Shader
  447. OpMemoryModel Logical GLSL450
  448. OpEntryPoint GLCompute %1 "main"
  449. OpExecutionMode %1 LocalSize 1 1 1
  450. %void = OpTypeVoid
  451. %3 = OpTypeFunction %void
  452. %float = OpTypeFloat 32
  453. %v3float = OpTypeVector %float 3
  454. %float_1 = OpConstant %float 1
  455. %null = OpConstantNull %v3float
  456. ; CHECK: %11 = OpConstantNull %float
  457. ; CHECK: %12 = OpConstantComposite %v3float %11 %11 %float_1
  458. %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_1 %null 2
  459. ; CHECK: %float_1_0 = OpConstant %float 1
  460. %spec_1 = OpSpecConstantOp %float CompositeExtract %spec_0 2
  461. %1 = OpFunction %void None %3
  462. %label = OpLabel
  463. OpReturn
  464. OpFunctionEnd
  465. )";
  466. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  467. }
  468. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  469. CompositeInsertNullVectorIntoMatrix) {
  470. const std::string test =
  471. R"(
  472. OpCapability Shader
  473. OpMemoryModel Logical GLSL450
  474. OpEntryPoint GLCompute %1 "main"
  475. OpExecutionMode %1 LocalSize 1 1 1
  476. %void = OpTypeVoid
  477. %3 = OpTypeFunction %void
  478. %float = OpTypeFloat 32
  479. %v2float = OpTypeVector %float 2
  480. %mat2v2float = OpTypeMatrix %v2float 2
  481. %null = OpConstantNull %mat2v2float
  482. %float_1 = OpConstant %float 1
  483. %float_2 = OpConstant %float 2
  484. %v2float_12 = OpConstantComposite %v2float %float_1 %float_2
  485. ; CHECK: %13 = OpConstantNull %v2float
  486. ; CHECK: %14 = OpConstantComposite %mat2v2float %10 %13
  487. %spec_0 = OpSpecConstantOp %mat2v2float CompositeInsert %v2float_12 %null 0
  488. %1 = OpFunction %void None %3
  489. %label = OpLabel
  490. OpReturn
  491. OpFunctionEnd
  492. )";
  493. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  494. }
  495. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  496. CompositeInsertVectorKeepNull) {
  497. const std::string test =
  498. R"(
  499. OpCapability Shader
  500. OpMemoryModel Logical GLSL450
  501. OpEntryPoint GLCompute %1 "main"
  502. OpExecutionMode %1 LocalSize 1 1 1
  503. %void = OpTypeVoid
  504. %3 = OpTypeFunction %void
  505. %float = OpTypeFloat 32
  506. %v3float = OpTypeVector %float 3
  507. %float_0 = OpConstant %float 0
  508. %null_float = OpConstantNull %float
  509. %null_vec = OpConstantNull %v3float
  510. ; CHECK: %15 = OpConstantComposite %v3float %7 %7 %float_0
  511. %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_0 %null_vec 2
  512. ; CHECK: %float_0_0 = OpConstant %float 0
  513. %spec_1 = OpSpecConstantOp %float CompositeExtract %spec_0 2
  514. ; CHECK: %17 = OpConstantComposite %v3float %7 %7 %7
  515. %spec_2 = OpSpecConstantOp %v3float CompositeInsert %null_float %null_vec 2
  516. ; CHECK: %18 = OpConstantNull %float
  517. %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 2
  518. %1 = OpFunction %void None %3
  519. %label = OpLabel
  520. %add = OpFAdd %float %spec_3 %spec_3
  521. OpReturn
  522. OpFunctionEnd
  523. )";
  524. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  525. }
  526. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  527. CompositeInsertVectorChainNull) {
  528. const std::string test =
  529. R"(
  530. OpCapability Shader
  531. OpMemoryModel Logical GLSL450
  532. OpEntryPoint GLCompute %1 "main"
  533. OpExecutionMode %1 LocalSize 1 1 1
  534. %void = OpTypeVoid
  535. %3 = OpTypeFunction %void
  536. %float = OpTypeFloat 32
  537. %v3float = OpTypeVector %float 3
  538. %float_1 = OpConstant %float 1
  539. %null = OpConstantNull %v3float
  540. ; CHECK: %15 = OpConstantNull %float
  541. ; CHECK: %16 = OpConstantComposite %v3float %15 %15 %float_1
  542. ; CHECK: %17 = OpConstantComposite %v3float %15 %float_1 %float_1
  543. ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_1
  544. %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_1 %null 2
  545. %spec_1 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_0 1
  546. %spec_2 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_1 0
  547. ; CHECK: %float_1_0 = OpConstant %float 1
  548. ; CHECK: %float_1_1 = OpConstant %float 1
  549. ; CHECK: %float_1_2 = OpConstant %float 1
  550. %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 0
  551. %spec_4 = OpSpecConstantOp %float CompositeExtract %spec_2 1
  552. %spec_5 = OpSpecConstantOp %float CompositeExtract %spec_2 2
  553. %1 = OpFunction %void None %3
  554. %label = OpLabel
  555. OpReturn
  556. OpFunctionEnd
  557. )";
  558. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  559. }
  560. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
  561. CompositeInsertVectorChainReset) {
  562. const std::string test =
  563. R"(
  564. OpCapability Shader
  565. OpMemoryModel Logical GLSL450
  566. OpEntryPoint GLCompute %1 "main"
  567. OpExecutionMode %1 LocalSize 1 1 1
  568. %void = OpTypeVoid
  569. %3 = OpTypeFunction %void
  570. %float = OpTypeFloat 32
  571. %v3float = OpTypeVector %float 3
  572. %float_1 = OpConstant %float 1
  573. %null = OpConstantNull %float
  574. ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %float_1
  575. %spec_0 = OpConstantComposite %v3float %null %null %float_1
  576. ; set to null
  577. ; CHECK: %13 = OpConstantComposite %v3float %7 %7 %7
  578. %spec_1 = OpSpecConstantOp %v3float CompositeInsert %null %spec_0 2
  579. ; set to back to original value
  580. ; CHECK: %14 = OpConstantComposite %v3float %7 %7 %float_1
  581. %spec_2 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_1 2
  582. ; CHECK: %float_1_0 = OpConstant %float 1
  583. %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 2
  584. %1 = OpFunction %void None %3
  585. %label = OpLabel
  586. OpReturn
  587. OpFunctionEnd
  588. )";
  589. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  590. }
  591. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrixNull) {
  592. const std::string test =
  593. R"(
  594. OpCapability Shader
  595. OpMemoryModel Logical GLSL450
  596. OpEntryPoint GLCompute %main "main"
  597. OpExecutionMode %main LocalSize 1 1 1
  598. %void = OpTypeVoid
  599. %func = OpTypeFunction %void
  600. %float = OpTypeFloat 32
  601. %int = OpTypeInt 32 0
  602. %v2float = OpTypeVector %float 2
  603. %mat2v2float = OpTypeMatrix %v2float 2
  604. %null = OpConstantNull %mat2v2float
  605. %float_1 = OpConstant %float 1
  606. ; CHECK: %13 = OpConstantNull %v2float
  607. ; CHECK: %14 = OpConstantNull %float
  608. ; CHECK: %15 = OpConstantComposite %v2float %float_1 %14
  609. ; CHECK: %16 = OpConstantComposite %mat2v2float %13 %15
  610. %spec = OpSpecConstantOp %mat2v2float CompositeInsert %float_1 %null 1 0
  611. ; extra type def to make sure new type def are not just thrown at end
  612. %v2int = OpTypeVector %int 2
  613. %main = OpFunction %void None %func
  614. %label = OpLabel
  615. OpReturn
  616. OpFunctionEnd
  617. )";
  618. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  619. }
  620. // Silently ignore spec constants that cannot be folded
  621. TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, UnfoldableOp) {
  622. const std::string test = R"(
  623. OpCapability Shader
  624. OpCapability SignedZeroInfNanPreserve
  625. OpExtension "SPV_KHR_float_controls"
  626. OpMemoryModel Logical GLSL450
  627. OpEntryPoint Vertex %main "main"
  628. OpSource GLSL 450
  629. OpDecorate %v SpecId 1
  630. %void = OpTypeVoid
  631. %3 = OpTypeFunction %void
  632. %float = OpTypeFloat 32
  633. %v = OpConstant %float 0x1p-1
  634. %c = OpSpecConstantOp %float QuantizeToF16 %v
  635. ;CHECK: {{%\w+}} = OpSpecConstantOp {{%\w+}} QuantizeToF16 {{%\w+}}
  636. %main = OpFunction %void None %3
  637. %5 = OpLabel
  638. OpReturn
  639. OpFunctionEnd
  640. )";
  641. SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
  642. }
  643. // All types and some common constants that are potentially required in
  644. // FoldSpecConstantOpAndCompositeTest.
  645. std::vector<std::string> CommonTypesAndConstants() {
  646. return std::vector<std::string>{
  647. // clang-format off
  648. // scalar types
  649. "%bool = OpTypeBool",
  650. "%ushort = OpTypeInt 16 0",
  651. "%short = OpTypeInt 16 1",
  652. "%uint = OpTypeInt 32 0",
  653. "%int = OpTypeInt 32 1",
  654. "%ulong = OpTypeInt 64 0",
  655. "%long = OpTypeInt 64 1",
  656. "%float = OpTypeFloat 32",
  657. "%double = OpTypeFloat 64",
  658. // vector types
  659. "%v2bool = OpTypeVector %bool 2",
  660. "%v2uint = OpTypeVector %uint 2",
  661. "%v2int = OpTypeVector %int 2",
  662. "%v3int = OpTypeVector %int 3",
  663. "%v4int = OpTypeVector %int 4",
  664. "%v2long = OpTypeVector %long 2",
  665. "%v2ulong = OpTypeVector %ulong 2",
  666. "%v2float = OpTypeVector %float 2",
  667. "%v2double = OpTypeVector %double 2",
  668. // variable pointer types
  669. "%_pf_bool = OpTypePointer Function %bool",
  670. "%_pf_uint = OpTypePointer Function %uint",
  671. "%_pf_int = OpTypePointer Function %int",
  672. "%_pf_float = OpTypePointer Function %float",
  673. "%_pf_double = OpTypePointer Function %double",
  674. "%_pf_v2int = OpTypePointer Function %v2int",
  675. "%_pf_v2float = OpTypePointer Function %v2float",
  676. "%_pf_v2double = OpTypePointer Function %v2double",
  677. // struct types
  678. "%inner_struct = OpTypeStruct %bool %int %float",
  679. "%outer_struct = OpTypeStruct %inner_struct %int",
  680. "%flat_struct = OpTypeStruct %bool %int %float",
  681. // common constants
  682. // scalar constants:
  683. "%bool_true = OpConstantTrue %bool",
  684. "%bool_false = OpConstantFalse %bool",
  685. "%bool_null = OpConstantNull %bool",
  686. "%signed_zero = OpConstant %int 0",
  687. "%unsigned_zero = OpConstant %uint 0",
  688. "%long_zero = OpConstant %long 0",
  689. "%ulong_zero = OpConstant %ulong 0",
  690. "%signed_one = OpConstant %int 1",
  691. "%unsigned_one = OpConstant %uint 1",
  692. "%signed_two = OpConstant %int 2",
  693. "%unsigned_two = OpConstant %uint 2",
  694. "%signed_three = OpConstant %int 3",
  695. "%unsigned_three = OpConstant %uint 3",
  696. "%signed_null = OpConstantNull %int",
  697. "%unsigned_null = OpConstantNull %uint",
  698. "%signed_minus_one = OpConstant %int -1",
  699. // vector constants:
  700. "%bool_true_vec = OpConstantComposite %v2bool %bool_true %bool_true",
  701. "%bool_false_vec = OpConstantComposite %v2bool %bool_false %bool_false",
  702. "%bool_null_vec = OpConstantNull %v2bool",
  703. "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
  704. "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
  705. "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
  706. "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
  707. "%signed_two_vec = OpConstantComposite %v2int %signed_two %signed_two",
  708. "%unsigned_two_vec = OpConstantComposite %v2uint %unsigned_two %unsigned_two",
  709. "%signed_three_vec = OpConstantComposite %v2int %signed_three %signed_three",
  710. "%unsigned_three_vec = OpConstantComposite %v2uint %unsigned_three %unsigned_three",
  711. "%signed_null_vec = OpConstantNull %v2int",
  712. "%unsigned_null_vec = OpConstantNull %v2uint",
  713. "%signed_minus_one_vec = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
  714. "%v4int_0_1_2_3 = OpConstantComposite %v4int %signed_zero %signed_one %signed_two %signed_three",
  715. // clang-format on
  716. };
  717. }
  718. // A helper function to strip OpName instructions from the given string of
  719. // disassembly code. Returns the string with all OpName instruction stripped.
  720. std::string StripOpNameInstructions(const std::string& str) {
  721. std::stringstream ss(str);
  722. std::ostringstream oss;
  723. std::string inst_str;
  724. while (std::getline(ss, inst_str, '\n')) {
  725. if (inst_str.find("OpName %") == std::string::npos) {
  726. oss << inst_str << '\n';
  727. }
  728. }
  729. return oss.str();
  730. }
  731. struct FoldSpecConstantOpAndCompositePassTestCase {
  732. // Original constants with unfolded spec constants.
  733. std::vector<std::string> original;
  734. // Expected constant after folding.
  735. std::vector<std::string> expected;
  736. };
  737. using FoldSpecConstantOpAndCompositePassTest = PassTest<
  738. ::testing::TestWithParam<FoldSpecConstantOpAndCompositePassTestCase>>;
  739. TEST_P(FoldSpecConstantOpAndCompositePassTest, ParamTestCase) {
  740. AssemblyBuilder test_code_builder, expected_code_builder;
  741. const auto& tc = GetParam();
  742. test_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants());
  743. test_code_builder.AppendTypesConstantsGlobals(tc.original);
  744. expected_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants());
  745. expected_code_builder.AppendTypesConstantsGlobals(tc.expected);
  746. const std::string original = test_code_builder.GetCode();
  747. const std::string expected = expected_code_builder.GetCode();
  748. // Run the optimization and get the result code in disassembly.
  749. std::string optimized;
  750. auto status = Pass::Status::SuccessWithoutChange;
  751. std::tie(optimized, status) =
  752. SinglePassRunAndDisassemble<FoldSpecConstantOpAndCompositePass>(
  753. original, /* skip_nop = */ true, /* do_validation = */ false);
  754. // Check the optimized code, but ignore the OpName instructions.
  755. EXPECT_NE(Pass::Status::Failure, status);
  756. EXPECT_EQ(
  757. StripOpNameInstructions(expected) == StripOpNameInstructions(original),
  758. status == Pass::Status::SuccessWithoutChange);
  759. EXPECT_EQ(StripOpNameInstructions(expected),
  760. StripOpNameInstructions(optimized));
  761. }
  762. // Tests that OpSpecConstantComposite opcodes are replace with
  763. // OpConstantComposite correctly.
  764. INSTANTIATE_TEST_SUITE_P(
  765. Composite, FoldSpecConstantOpAndCompositePassTest,
  766. ::testing::ValuesIn(std::vector<
  767. FoldSpecConstantOpAndCompositePassTestCase>({
  768. // clang-format off
  769. // normal vector
  770. {
  771. // original
  772. {
  773. "%spec_v2bool = OpSpecConstantComposite %v2bool %bool_true %bool_false",
  774. "%spec_v2uint = OpSpecConstantComposite %v2uint %unsigned_one %unsigned_one",
  775. "%spec_v2int_a = OpSpecConstantComposite %v2int %signed_one %signed_two",
  776. // Spec constants whose value can not be fully resolved should
  777. // not be processed.
  778. "%spec_int = OpSpecConstant %int 99",
  779. "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int",
  780. },
  781. // expected
  782. {
  783. "%spec_v2bool = OpConstantComposite %v2bool %bool_true %bool_false",
  784. "%spec_v2uint = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
  785. "%spec_v2int_a = OpConstantComposite %v2int %signed_one %signed_two",
  786. "%spec_int = OpSpecConstant %int 99",
  787. "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int",
  788. },
  789. },
  790. // vector with null constants
  791. {
  792. // original
  793. {
  794. "%null_bool = OpConstantNull %bool",
  795. "%null_int = OpConstantNull %int",
  796. "%spec_v2bool = OpSpecConstantComposite %v2bool %null_bool %null_bool",
  797. "%spec_v3int = OpSpecConstantComposite %v3int %null_int %null_int %null_int",
  798. "%spec_v4int = OpSpecConstantComposite %v4int %null_int %null_int %null_int %null_int",
  799. },
  800. // expected
  801. {
  802. "%null_bool = OpConstantNull %bool",
  803. "%null_int = OpConstantNull %int",
  804. "%spec_v2bool = OpConstantComposite %v2bool %null_bool %null_bool",
  805. "%spec_v3int = OpConstantComposite %v3int %null_int %null_int %null_int",
  806. "%spec_v4int = OpConstantComposite %v4int %null_int %null_int %null_int %null_int",
  807. },
  808. },
  809. // flat struct
  810. {
  811. // original
  812. {
  813. "%float_1 = OpConstant %float 1",
  814. "%flat_1 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1",
  815. // following struct should not be folded as the value of
  816. // %spec_float is not determined.
  817. "%spec_float = OpSpecConstant %float 1",
  818. "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float",
  819. },
  820. // expected
  821. {
  822. "%float_1 = OpConstant %float 1",
  823. "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
  824. "%spec_float = OpSpecConstant %float 1",
  825. "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float",
  826. }
  827. },
  828. // nested struct
  829. {
  830. // original
  831. {
  832. "%float_1 = OpConstant %float 1",
  833. "%inner_1 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %float_1",
  834. "%outer_1 = OpSpecConstantComposite %outer_struct %inner_1 %signed_one",
  835. // following structs should not be folded as the value of
  836. // %spec_float is not determined.
  837. "%spec_float = OpSpecConstant %float 1",
  838. "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
  839. "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one",
  840. },
  841. // expected
  842. {
  843. "%float_1 = OpConstant %float 1",
  844. "%inner_1 = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
  845. "%outer_1 = OpConstantComposite %outer_struct %inner_1 %signed_one",
  846. "%spec_float = OpSpecConstant %float 1",
  847. "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
  848. "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one",
  849. }
  850. },
  851. // composite constants touched by OpUndef should be skipped
  852. {
  853. // original
  854. {
  855. "%undef = OpUndef %float",
  856. "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
  857. "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one",
  858. },
  859. // expected
  860. {
  861. "%undef = OpUndef %float",
  862. "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
  863. "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one",
  864. },
  865. },
  866. // Fold an QuantizetoF16 instruction
  867. {
  868. // original
  869. {
  870. "%float_1 = OpConstant %float 1",
  871. "%quant_float = OpSpecConstantOp %float QuantizeToF16 %float_1",
  872. },
  873. // expected
  874. {
  875. "%float_1 = OpConstant %float 1",
  876. "%quant_float = OpConstant %float 1",
  877. },
  878. }
  879. // clang-format on
  880. })));
  881. // Tests for operations that resulting in different types.
  882. INSTANTIATE_TEST_SUITE_P(
  883. Cast, FoldSpecConstantOpAndCompositePassTest,
  884. ::testing::ValuesIn(std::vector<
  885. FoldSpecConstantOpAndCompositePassTestCase>({
  886. // clang-format off
  887. // int -> bool scalar
  888. {
  889. // original
  890. {
  891. "%spec_bool_t = OpSpecConstantOp %bool INotEqual %signed_three %signed_zero",
  892. "%spec_bool_f = OpSpecConstantOp %bool INotEqual %signed_zero %signed_zero",
  893. "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %signed_null %signed_zero",
  894. },
  895. // expected
  896. {
  897. "%spec_bool_t = OpConstantTrue %bool",
  898. "%spec_bool_f = OpConstantFalse %bool",
  899. "%spec_bool_from_null = OpConstantFalse %bool",
  900. },
  901. },
  902. // uint -> bool scalar
  903. {
  904. // original
  905. {
  906. "%spec_bool_t = OpSpecConstantOp %bool INotEqual %unsigned_three %unsigned_zero",
  907. "%spec_bool_f = OpSpecConstantOp %bool INotEqual %unsigned_zero %unsigned_zero",
  908. "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %unsigned_null %unsigned_zero",
  909. },
  910. // expected
  911. {
  912. "%spec_bool_t = OpConstantTrue %bool",
  913. "%spec_bool_f = OpConstantFalse %bool",
  914. "%spec_bool_from_null = OpConstantFalse %bool",
  915. },
  916. },
  917. // bool -> int scalar
  918. {
  919. // original
  920. {
  921. "%spec_int_one = OpSpecConstantOp %int Select %bool_true %signed_one %signed_zero",
  922. "%spec_int_zero = OpSpecConstantOp %int Select %bool_false %signed_one %signed_zero",
  923. "%spec_int_from_null = OpSpecConstantOp %int Select %bool_null %signed_one %signed_zero",
  924. },
  925. // expected
  926. {
  927. "%spec_int_one = OpConstant %int 1",
  928. "%spec_int_zero = OpConstant %int 0",
  929. "%spec_int_from_null = OpConstant %int 0",
  930. },
  931. },
  932. // uint -> int scalar
  933. {
  934. // original
  935. {
  936. "%spec_int_one = OpSpecConstantOp %int IAdd %unsigned_one %signed_zero",
  937. "%spec_int_zero = OpSpecConstantOp %int IAdd %unsigned_zero %signed_zero",
  938. "%spec_int_from_null = OpSpecConstantOp %int IAdd %unsigned_null %unsigned_zero",
  939. },
  940. // expected
  941. {
  942. "%spec_int_one = OpConstant %int 1",
  943. "%spec_int_zero = OpConstant %int 0",
  944. "%spec_int_from_null = OpConstant %int 0",
  945. },
  946. },
  947. // bool -> uint scalar
  948. {
  949. // original
  950. {
  951. "%spec_uint_one = OpSpecConstantOp %uint Select %bool_true %unsigned_one %unsigned_zero",
  952. "%spec_uint_zero = OpSpecConstantOp %uint Select %bool_false %unsigned_one %unsigned_zero",
  953. "%spec_uint_from_null = OpSpecConstantOp %uint Select %bool_null %unsigned_one %unsigned_zero",
  954. },
  955. // expected
  956. {
  957. "%spec_uint_one = OpConstant %uint 1",
  958. "%spec_uint_zero = OpConstant %uint 0",
  959. "%spec_uint_from_null = OpConstant %uint 0",
  960. },
  961. },
  962. // int -> uint scalar
  963. {
  964. // original
  965. {
  966. "%spec_uint_one = OpSpecConstantOp %uint IAdd %signed_one %unsigned_zero",
  967. "%spec_uint_zero = OpSpecConstantOp %uint IAdd %signed_zero %unsigned_zero",
  968. "%spec_uint_from_null = OpSpecConstantOp %uint IAdd %signed_null %unsigned_zero",
  969. },
  970. // expected
  971. {
  972. "%spec_uint_one = OpConstant %uint 1",
  973. "%spec_uint_zero = OpConstant %uint 0",
  974. "%spec_uint_from_null = OpConstant %uint 0",
  975. },
  976. },
  977. // int -> bool vector
  978. {
  979. // original
  980. {
  981. "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %signed_three_vec %signed_zero_vec",
  982. "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %signed_zero_vec %signed_zero_vec",
  983. "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %signed_null_vec %signed_zero_vec",
  984. },
  985. // expected
  986. {
  987. "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true",
  988. "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false",
  989. "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false",
  990. },
  991. },
  992. // uint -> bool vector
  993. {
  994. // original
  995. {
  996. "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_three_vec %unsigned_zero_vec",
  997. "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_zero_vec %unsigned_zero_vec",
  998. "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %unsigned_null_vec %unsigned_zero_vec",
  999. },
  1000. // expected
  1001. {
  1002. "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true",
  1003. "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false",
  1004. "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false",
  1005. },
  1006. },
  1007. // bool -> int vector
  1008. {
  1009. // original
  1010. {
  1011. "%spec_int_one_vec = OpSpecConstantOp %v2int Select %bool_true_vec %signed_one_vec %signed_zero_vec",
  1012. "%spec_int_zero_vec = OpSpecConstantOp %v2int Select %bool_false_vec %signed_one_vec %signed_zero_vec",
  1013. "%spec_int_from_null = OpSpecConstantOp %v2int Select %bool_null_vec %signed_one_vec %signed_zero_vec",
  1014. },
  1015. // expected
  1016. {
  1017. "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
  1018. "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
  1019. "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero",
  1020. },
  1021. },
  1022. // uint -> int vector
  1023. {
  1024. // original
  1025. {
  1026. "%spec_int_one_vec = OpSpecConstantOp %v2int IAdd %unsigned_one_vec %signed_zero_vec",
  1027. "%spec_int_zero_vec = OpSpecConstantOp %v2int IAdd %unsigned_zero_vec %signed_zero_vec",
  1028. "%spec_int_from_null = OpSpecConstantOp %v2int IAdd %unsigned_null_vec %signed_zero_vec",
  1029. },
  1030. // expected
  1031. {
  1032. "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
  1033. "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
  1034. "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero",
  1035. },
  1036. },
  1037. // bool -> uint vector
  1038. {
  1039. // original
  1040. {
  1041. "%spec_uint_one_vec = OpSpecConstantOp %v2uint Select %bool_true_vec %unsigned_one_vec %unsigned_zero_vec",
  1042. "%spec_uint_zero_vec = OpSpecConstantOp %v2uint Select %bool_false_vec %unsigned_one_vec %unsigned_zero_vec",
  1043. "%spec_uint_from_null = OpSpecConstantOp %v2uint Select %bool_null_vec %unsigned_one_vec %unsigned_zero_vec",
  1044. },
  1045. // expected
  1046. {
  1047. "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
  1048. "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
  1049. "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
  1050. },
  1051. },
  1052. // int -> uint vector
  1053. {
  1054. // original
  1055. {
  1056. "%spec_uint_one_vec = OpSpecConstantOp %v2uint IAdd %signed_one_vec %unsigned_zero_vec",
  1057. "%spec_uint_zero_vec = OpSpecConstantOp %v2uint IAdd %signed_zero_vec %unsigned_zero_vec",
  1058. "%spec_uint_from_null = OpSpecConstantOp %v2uint IAdd %signed_null_vec %unsigned_zero_vec",
  1059. },
  1060. // expected
  1061. {
  1062. "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
  1063. "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
  1064. "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
  1065. },
  1066. },
  1067. // UConvert scalar
  1068. {
  1069. // original
  1070. {
  1071. "%spec_ulong_zero = OpSpecConstantOp %ulong UConvert %unsigned_zero",
  1072. "%spec_ulong_one = OpSpecConstantOp %ulong UConvert %unsigned_one",
  1073. "%spec_short_zero = OpSpecConstantOp %ushort UConvert %unsigned_zero",
  1074. "%spec_short_one = OpSpecConstantOp %ushort UConvert %unsigned_one",
  1075. "%uint_max = OpConstant %uint 4294967295",
  1076. "%spec_ushort_max = OpSpecConstantOp %ushort UConvert %uint_max",
  1077. "%uint_0xDDDDDDDD = OpConstant %uint 3722304989",
  1078. "%spec_ushort_0xDDDD = OpSpecConstantOp %ushort UConvert %uint_0xDDDDDDDD",
  1079. },
  1080. // expected
  1081. {
  1082. "%spec_ulong_zero = OpConstant %ulong 0",
  1083. "%spec_ulong_one = OpConstant %ulong 1",
  1084. "%spec_short_zero = OpConstant %ushort 0",
  1085. "%spec_short_one = OpConstant %ushort 1",
  1086. "%uint_max = OpConstant %uint 4294967295",
  1087. "%spec_ushort_max = OpConstant %ushort 65535",
  1088. "%uint_0xDDDDDDDD = OpConstant %uint 3722304989",
  1089. "%spec_ushort_0xDDDD = OpConstant %ushort 56797",
  1090. },
  1091. },
  1092. // SConvert scalar
  1093. {
  1094. // original
  1095. {
  1096. "%spec_long_zero = OpSpecConstantOp %long SConvert %signed_zero",
  1097. "%spec_long_one = OpSpecConstantOp %long SConvert %signed_one",
  1098. "%spec_long_minus_one = OpSpecConstantOp %long SConvert %signed_minus_one",
  1099. "%spec_short_minus_one_trunc = OpSpecConstantOp %short SConvert %signed_minus_one",
  1100. "%int_2_to_17_minus_one = OpConstant %int 131071",
  1101. "%spec_short_minus_one_trunc2 = OpSpecConstantOp %short SConvert %int_2_to_17_minus_one",
  1102. },
  1103. // expected
  1104. {
  1105. "%spec_long_zero = OpConstant %long 0",
  1106. "%spec_long_one = OpConstant %long 1",
  1107. "%spec_long_minus_one = OpConstant %long -1",
  1108. "%spec_short_minus_one_trunc = OpConstant %short -1",
  1109. "%int_2_to_17_minus_one = OpConstant %int 131071",
  1110. "%spec_short_minus_one_trunc2 = OpConstant %short -1",
  1111. },
  1112. },
  1113. // UConvert vector
  1114. {
  1115. // original
  1116. {
  1117. "%spec_v2ulong_zero = OpSpecConstantOp %v2ulong UConvert %unsigned_zero_vec",
  1118. "%spec_v2ulong_one = OpSpecConstantOp %v2ulong UConvert %unsigned_one_vec",
  1119. },
  1120. // expected
  1121. {
  1122. "%spec_v2ulong_zero = OpConstantComposite %v2ulong %ulong_zero %ulong_zero",
  1123. "%ulong_1 = OpConstant %ulong 1",
  1124. "%spec_v2ulong_one = OpConstantComposite %v2ulong %ulong_1 %ulong_1",
  1125. },
  1126. },
  1127. // SConvert vector
  1128. {
  1129. // original
  1130. {
  1131. "%spec_v2long_zero = OpSpecConstantOp %v2long SConvert %signed_zero_vec",
  1132. "%spec_v2long_one = OpSpecConstantOp %v2long SConvert %signed_one_vec",
  1133. "%spec_v2long_minus_one = OpSpecConstantOp %v2long SConvert %signed_minus_one_vec",
  1134. },
  1135. // expected
  1136. {
  1137. "%spec_v2long_zero = OpConstantComposite %v2long %long_zero %long_zero",
  1138. "%long_1 = OpConstant %long 1",
  1139. "%spec_v2long_one = OpConstantComposite %v2long %long_1 %long_1",
  1140. "%long_n1 = OpConstant %long -1",
  1141. "%spec_v2long_minus_one = OpConstantComposite %v2long %long_n1 %long_n1",
  1142. },
  1143. },
  1144. // clang-format on
  1145. })));
  1146. // Tests about boolean scalar logical operations and comparison operations with
  1147. // scalar int/uint type.
  1148. INSTANTIATE_TEST_SUITE_P(
  1149. Logical, FoldSpecConstantOpAndCompositePassTest,
  1150. ::testing::ValuesIn(std::vector<
  1151. FoldSpecConstantOpAndCompositePassTestCase>({
  1152. // clang-format off
  1153. // scalar integer comparison
  1154. {
  1155. // original
  1156. {
  1157. "%int_minus_1 = OpConstant %int -1",
  1158. "%slt_0_1 = OpSpecConstantOp %bool SLessThan %signed_zero %signed_one",
  1159. "%sgt_0_1 = OpSpecConstantOp %bool SGreaterThan %signed_zero %signed_one",
  1160. "%sle_2_2 = OpSpecConstantOp %bool SLessThanEqual %signed_two %signed_two",
  1161. "%sge_2_1 = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_one",
  1162. "%sge_2_null = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_null",
  1163. "%sge_minus_1_null = OpSpecConstantOp %bool SGreaterThanEqual %int_minus_1 %signed_null",
  1164. "%ult_0_1 = OpSpecConstantOp %bool ULessThan %unsigned_zero %unsigned_one",
  1165. "%ugt_0_1 = OpSpecConstantOp %bool UGreaterThan %unsigned_zero %unsigned_one",
  1166. "%ule_2_3 = OpSpecConstantOp %bool ULessThanEqual %unsigned_two %unsigned_three",
  1167. "%uge_1_1 = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_one %unsigned_one",
  1168. "%uge_2_null = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_two %unsigned_null",
  1169. "%uge_minus_1_null = OpSpecConstantOp %bool UGreaterThanEqual %int_minus_1 %unsigned_null",
  1170. },
  1171. // expected
  1172. {
  1173. "%int_minus_1 = OpConstant %int -1",
  1174. "%slt_0_1 = OpConstantTrue %bool",
  1175. "%sgt_0_1 = OpConstantFalse %bool",
  1176. "%sle_2_2 = OpConstantTrue %bool",
  1177. "%sge_2_1 = OpConstantTrue %bool",
  1178. "%sge_2_null = OpConstantTrue %bool",
  1179. "%sge_minus_1_null = OpConstantFalse %bool",
  1180. "%ult_0_1 = OpConstantTrue %bool",
  1181. "%ugt_0_1 = OpConstantFalse %bool",
  1182. "%ule_2_3 = OpConstantTrue %bool",
  1183. "%uge_1_1 = OpConstantTrue %bool",
  1184. "%uge_2_null = OpConstantTrue %bool",
  1185. "%uge_minus_1_null = OpConstantTrue %bool",
  1186. },
  1187. },
  1188. // Logical and, or, xor.
  1189. {
  1190. // original
  1191. {
  1192. "%logical_or = OpSpecConstantOp %bool LogicalOr %bool_true %bool_false",
  1193. "%logical_and = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_false",
  1194. "%logical_not = OpSpecConstantOp %bool LogicalNot %bool_true",
  1195. "%logical_eq = OpSpecConstantOp %bool LogicalEqual %bool_true %bool_true",
  1196. "%logical_neq = OpSpecConstantOp %bool LogicalNotEqual %bool_true %bool_true",
  1197. "%logical_and_null = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_null",
  1198. },
  1199. // expected
  1200. {
  1201. "%logical_or = OpConstantTrue %bool",
  1202. "%logical_and = OpConstantFalse %bool",
  1203. "%logical_not = OpConstantFalse %bool",
  1204. "%logical_eq = OpConstantTrue %bool",
  1205. "%logical_neq = OpConstantFalse %bool",
  1206. "%logical_and_null = OpConstantFalse %bool",
  1207. },
  1208. },
  1209. // clang-format on
  1210. })));
  1211. // Tests about arithmetic operations for scalar int and uint types.
  1212. INSTANTIATE_TEST_SUITE_P(
  1213. ScalarArithmetic, FoldSpecConstantOpAndCompositePassTest,
  1214. ::testing::ValuesIn(std::vector<
  1215. FoldSpecConstantOpAndCompositePassTestCase>({
  1216. // clang-format off
  1217. // scalar integer negate
  1218. {
  1219. // original
  1220. {
  1221. "%int_minus_1 = OpSpecConstantOp %int SNegate %signed_one",
  1222. "%int_minus_2 = OpSpecConstantOp %int SNegate %signed_two",
  1223. "%int_neg_null = OpSpecConstantOp %int SNegate %signed_null",
  1224. "%int_max = OpConstant %int 2147483647",
  1225. "%int_neg_max = OpSpecConstantOp %int SNegate %int_max",
  1226. },
  1227. // expected
  1228. {
  1229. "%int_minus_1 = OpConstant %int -1",
  1230. "%int_minus_2 = OpConstant %int -2",
  1231. "%int_neg_null = OpConstantNull %int",
  1232. "%int_max = OpConstant %int 2147483647",
  1233. "%int_neg_max = OpConstant %int -2147483647",
  1234. },
  1235. },
  1236. // scalar integer not
  1237. {
  1238. // original
  1239. {
  1240. "%uint_4294967294 = OpSpecConstantOp %uint Not %unsigned_one",
  1241. "%uint_4294967293 = OpSpecConstantOp %uint Not %unsigned_two",
  1242. "%uint_neg_null = OpSpecConstantOp %uint Not %unsigned_null",
  1243. },
  1244. // expected
  1245. {
  1246. "%uint_4294967294 = OpConstant %uint 4294967294",
  1247. "%uint_4294967293 = OpConstant %uint 4294967293",
  1248. "%uint_neg_null = OpConstant %uint 4294967295",
  1249. },
  1250. },
  1251. // scalar integer add, sub, mul, div
  1252. {
  1253. // original
  1254. {
  1255. "%signed_max = OpConstant %int 2147483647",
  1256. "%signed_min = OpConstant %int -2147483648",
  1257. "%spec_int_iadd = OpSpecConstantOp %int IAdd %signed_three %signed_two",
  1258. "%spec_int_isub = OpSpecConstantOp %int ISub %signed_one %spec_int_iadd",
  1259. "%spec_int_sdiv = OpSpecConstantOp %int SDiv %spec_int_isub %signed_two",
  1260. "%spec_int_imul = OpSpecConstantOp %int IMul %spec_int_sdiv %signed_three",
  1261. "%spec_int_iadd_null = OpSpecConstantOp %int IAdd %spec_int_imul %signed_null",
  1262. "%spec_int_imul_null = OpSpecConstantOp %int IMul %spec_int_iadd_null %signed_null",
  1263. "%spec_int_iadd_overflow = OpSpecConstantOp %int IAdd %signed_max %signed_three",
  1264. "%spec_int_isub_overflow = OpSpecConstantOp %int ISub %signed_min %signed_three",
  1265. "%spec_uint_iadd = OpSpecConstantOp %uint IAdd %unsigned_three %unsigned_two",
  1266. "%spec_uint_isub = OpSpecConstantOp %uint ISub %unsigned_one %spec_uint_iadd",
  1267. "%spec_uint_udiv = OpSpecConstantOp %uint UDiv %spec_uint_isub %unsigned_three",
  1268. "%spec_uint_imul = OpSpecConstantOp %uint IMul %spec_uint_udiv %unsigned_two",
  1269. "%spec_uint_isub_null = OpSpecConstantOp %uint ISub %spec_uint_imul %signed_null",
  1270. },
  1271. // expected
  1272. {
  1273. "%signed_max = OpConstant %int 2147483647",
  1274. "%signed_min = OpConstant %int -2147483648",
  1275. "%spec_int_iadd = OpConstant %int 5",
  1276. "%spec_int_isub = OpConstant %int -4",
  1277. "%spec_int_sdiv = OpConstant %int -2",
  1278. "%spec_int_imul = OpConstant %int -6",
  1279. "%spec_int_iadd_null = OpConstant %int -6",
  1280. "%spec_int_imul_null = OpConstant %int 0",
  1281. "%spec_int_iadd_overflow = OpConstant %int -2147483646",
  1282. "%spec_int_isub_overflow = OpConstant %int 2147483645",
  1283. "%spec_uint_iadd = OpConstant %uint 5",
  1284. "%spec_uint_isub = OpConstant %uint 4294967292",
  1285. "%spec_uint_udiv = OpConstant %uint 1431655764",
  1286. "%spec_uint_imul = OpConstant %uint 2863311528",
  1287. "%spec_uint_isub_null = OpConstant %uint 2863311528",
  1288. },
  1289. },
  1290. // scalar integer rem, mod
  1291. {
  1292. // original
  1293. {
  1294. // common constants
  1295. "%int_7 = OpConstant %int 7",
  1296. "%uint_7 = OpConstant %uint 7",
  1297. "%int_minus_7 = OpConstant %int -7",
  1298. "%int_minus_3 = OpConstant %int -3",
  1299. // srem
  1300. "%7_srem_3 = OpSpecConstantOp %int SRem %int_7 %signed_three",
  1301. "%minus_7_srem_3 = OpSpecConstantOp %int SRem %int_minus_7 %signed_three",
  1302. "%7_srem_minus_3 = OpSpecConstantOp %int SRem %int_7 %int_minus_3",
  1303. "%minus_7_srem_minus_3 = OpSpecConstantOp %int SRem %int_minus_7 %int_minus_3",
  1304. // smod
  1305. "%7_smod_3 = OpSpecConstantOp %int SMod %int_7 %signed_three",
  1306. "%minus_7_smod_3 = OpSpecConstantOp %int SMod %int_minus_7 %signed_three",
  1307. "%7_smod_minus_3 = OpSpecConstantOp %int SMod %int_7 %int_minus_3",
  1308. "%minus_7_smod_minus_3 = OpSpecConstantOp %int SMod %int_minus_7 %int_minus_3",
  1309. // umod
  1310. "%7_umod_3 = OpSpecConstantOp %uint UMod %uint_7 %unsigned_three",
  1311. // null constant
  1312. "%null_srem_3 = OpSpecConstantOp %int SRem %signed_null %signed_three",
  1313. "%null_smod_3 = OpSpecConstantOp %int SMod %signed_null %signed_three",
  1314. "%null_umod_3 = OpSpecConstantOp %uint UMod %unsigned_null %unsigned_three",
  1315. },
  1316. // expected
  1317. {
  1318. // common constants
  1319. "%int_7 = OpConstant %int 7",
  1320. "%uint_7 = OpConstant %uint 7",
  1321. "%int_minus_7 = OpConstant %int -7",
  1322. "%int_minus_3 = OpConstant %int -3",
  1323. // srem
  1324. "%7_srem_3 = OpConstant %int 1",
  1325. "%minus_7_srem_3 = OpConstant %int -1",
  1326. "%7_srem_minus_3 = OpConstant %int 1",
  1327. "%minus_7_srem_minus_3 = OpConstant %int -1",
  1328. // smod
  1329. "%7_smod_3 = OpConstant %int 1",
  1330. "%minus_7_smod_3 = OpConstant %int 2",
  1331. "%7_smod_minus_3 = OpConstant %int -2",
  1332. "%minus_7_smod_minus_3 = OpConstant %int -1",
  1333. // umod
  1334. "%7_umod_3 = OpConstant %uint 1",
  1335. // null constant
  1336. "%null_srem_3 = OpConstant %int 0",
  1337. "%null_smod_3 = OpConstant %int 0",
  1338. "%null_umod_3 = OpConstant %uint 0",
  1339. },
  1340. },
  1341. // scalar integer bitwise and shift
  1342. {
  1343. // original
  1344. {
  1345. // bitwise
  1346. "%xor_1_3 = OpSpecConstantOp %int BitwiseXor %signed_one %signed_three",
  1347. "%and_1_2 = OpSpecConstantOp %int BitwiseAnd %signed_one %xor_1_3",
  1348. "%or_1_2 = OpSpecConstantOp %int BitwiseOr %signed_one %xor_1_3",
  1349. "%xor_3_null = OpSpecConstantOp %int BitwiseXor %or_1_2 %signed_null",
  1350. // shift
  1351. "%unsigned_31 = OpConstant %uint 31",
  1352. "%unsigned_left_shift_max = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_one %unsigned_31",
  1353. "%unsigned_right_shift_logical = OpSpecConstantOp %uint ShiftRightLogical %unsigned_left_shift_max %unsigned_31",
  1354. "%signed_right_shift_arithmetic = OpSpecConstantOp %int ShiftRightArithmetic %unsigned_left_shift_max %unsigned_31",
  1355. "%left_shift_null_31 = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_null %unsigned_31",
  1356. "%right_shift_31_null = OpSpecConstantOp %uint ShiftRightLogical %unsigned_31 %unsigned_null",
  1357. },
  1358. // expected
  1359. {
  1360. "%xor_1_3 = OpConstant %int 2",
  1361. "%and_1_2 = OpConstant %int 0",
  1362. "%or_1_2 = OpConstant %int 3",
  1363. "%xor_3_null = OpConstant %int 3",
  1364. "%unsigned_31 = OpConstant %uint 31",
  1365. "%unsigned_left_shift_max = OpConstant %uint 2147483648",
  1366. "%unsigned_right_shift_logical = OpConstant %uint 1",
  1367. "%signed_right_shift_arithmetic = OpConstant %int -1",
  1368. "%left_shift_null_31 = OpConstant %uint 0",
  1369. "%right_shift_31_null = OpConstant %uint 31",
  1370. },
  1371. },
  1372. // Skip folding if any operands have undetermined value.
  1373. {
  1374. // original
  1375. {
  1376. "%spec_int = OpSpecConstant %int 1",
  1377. "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int",
  1378. },
  1379. // expected
  1380. {
  1381. "%spec_int = OpSpecConstant %int 1",
  1382. "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int",
  1383. },
  1384. },
  1385. // clang-format on
  1386. })));
  1387. // Tests about arithmetic operations for vector int and uint types.
  1388. INSTANTIATE_TEST_SUITE_P(
  1389. VectorArithmetic, FoldSpecConstantOpAndCompositePassTest,
  1390. ::testing::ValuesIn(std::vector<
  1391. FoldSpecConstantOpAndCompositePassTestCase>({
  1392. // clang-format off
  1393. // vector integer negate
  1394. {
  1395. // original
  1396. {
  1397. "%v2int_minus_1 = OpSpecConstantOp %v2int SNegate %signed_one_vec",
  1398. "%v2int_minus_2 = OpSpecConstantOp %v2int SNegate %signed_two_vec",
  1399. "%v2int_neg_null = OpSpecConstantOp %v2int SNegate %signed_null_vec",
  1400. },
  1401. // expected
  1402. {
  1403. "%v2int_minus_1 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
  1404. "%int_n2 = OpConstant %int -2",
  1405. "%v2int_minus_2 = OpConstantComposite %v2int %int_n2 %int_n2",
  1406. "%v2int_neg_null = OpConstantComposite %v2int %signed_null %signed_null",
  1407. },
  1408. },
  1409. // vector integer (including null vetors) add, sub, div, mul
  1410. {
  1411. // original
  1412. {
  1413. "%spec_v2int_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %signed_two_vec",
  1414. "%spec_v2int_isub = OpSpecConstantOp %v2int ISub %signed_one_vec %spec_v2int_iadd",
  1415. "%spec_v2int_sdiv = OpSpecConstantOp %v2int SDiv %spec_v2int_isub %signed_two_vec",
  1416. "%spec_v2int_imul = OpSpecConstantOp %v2int IMul %spec_v2int_sdiv %signed_three_vec",
  1417. "%spec_v2int_iadd_null = OpSpecConstantOp %v2int IAdd %spec_v2int_imul %signed_null_vec",
  1418. "%spec_v2uint_iadd = OpSpecConstantOp %v2uint IAdd %unsigned_three_vec %unsigned_two_vec",
  1419. "%spec_v2uint_isub = OpSpecConstantOp %v2uint ISub %unsigned_one_vec %spec_v2uint_iadd",
  1420. "%spec_v2uint_udiv = OpSpecConstantOp %v2uint UDiv %spec_v2uint_isub %unsigned_three_vec",
  1421. "%spec_v2uint_imul = OpSpecConstantOp %v2uint IMul %spec_v2uint_udiv %unsigned_two_vec",
  1422. "%spec_v2uint_isub_null = OpSpecConstantOp %v2uint ISub %spec_v2uint_imul %signed_null_vec",
  1423. },
  1424. // expected
  1425. {
  1426. "%int_5 = OpConstant %int 5",
  1427. "%spec_v2int_iadd = OpConstantComposite %v2int %int_5 %int_5",
  1428. "%int_n4 = OpConstant %int -4",
  1429. "%spec_v2int_isub = OpConstantComposite %v2int %int_n4 %int_n4",
  1430. "%int_n2 = OpConstant %int -2",
  1431. "%spec_v2int_sdiv = OpConstantComposite %v2int %int_n2 %int_n2",
  1432. "%int_n6 = OpConstant %int -6",
  1433. "%spec_v2int_imul = OpConstantComposite %v2int %int_n6 %int_n6",
  1434. "%spec_v2int_iadd_null = OpConstantComposite %v2int %int_n6 %int_n6",
  1435. "%uint_5 = OpConstant %uint 5",
  1436. "%spec_v2uint_iadd = OpConstantComposite %v2uint %uint_5 %uint_5",
  1437. "%uint_4294967292 = OpConstant %uint 4294967292",
  1438. "%spec_v2uint_isub = OpConstantComposite %v2uint %uint_4294967292 %uint_4294967292",
  1439. "%uint_1431655764 = OpConstant %uint 1431655764",
  1440. "%spec_v2uint_udiv = OpConstantComposite %v2uint %uint_1431655764 %uint_1431655764",
  1441. "%uint_2863311528 = OpConstant %uint 2863311528",
  1442. "%spec_v2uint_imul = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528",
  1443. "%spec_v2uint_isub_null = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528",
  1444. },
  1445. },
  1446. // vector integer rem, mod
  1447. {
  1448. // original
  1449. {
  1450. // common constants
  1451. "%int_7 = OpConstant %int 7",
  1452. "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7",
  1453. "%uint_7 = OpConstant %uint 7",
  1454. "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7",
  1455. "%int_minus_7 = OpConstant %int -7",
  1456. "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7",
  1457. "%int_minus_3 = OpConstant %int -3",
  1458. "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
  1459. // srem
  1460. "%7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_7 %signed_three_vec",
  1461. "%minus_7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %signed_three_vec",
  1462. "%7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_7 %v2int_minus_3",
  1463. "%minus_7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %v2int_minus_3",
  1464. // smod
  1465. "%7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_7 %signed_three_vec",
  1466. "%minus_7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %signed_three_vec",
  1467. "%7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_7 %v2int_minus_3",
  1468. "%minus_7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %v2int_minus_3",
  1469. // umod
  1470. "%7_umod_3 = OpSpecConstantOp %v2uint UMod %v2uint_7 %unsigned_three_vec",
  1471. },
  1472. // expected
  1473. {
  1474. // common constants
  1475. "%int_7 = OpConstant %int 7",
  1476. "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7",
  1477. "%uint_7 = OpConstant %uint 7",
  1478. "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7",
  1479. "%int_minus_7 = OpConstant %int -7",
  1480. "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7",
  1481. "%int_minus_3 = OpConstant %int -3",
  1482. "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
  1483. // srem
  1484. "%7_srem_3 = OpConstantComposite %v2int %signed_one %signed_one",
  1485. "%minus_7_srem_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
  1486. "%7_srem_minus_3 = OpConstantComposite %v2int %signed_one %signed_one",
  1487. "%minus_7_srem_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
  1488. // smod
  1489. "%7_smod_3 = OpConstantComposite %v2int %signed_one %signed_one",
  1490. "%minus_7_smod_3 = OpConstantComposite %v2int %signed_two %signed_two",
  1491. "%int_n2 = OpConstant %int -2",
  1492. "%7_smod_minus_3 = OpConstantComposite %v2int %int_n2 %int_n2",
  1493. "%minus_7_smod_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
  1494. // umod
  1495. "%7_umod_3 = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
  1496. },
  1497. },
  1498. // vector integer bitwise, shift
  1499. {
  1500. // original
  1501. {
  1502. "%xor_1_3 = OpSpecConstantOp %v2int BitwiseXor %signed_one_vec %signed_three_vec",
  1503. "%and_1_2 = OpSpecConstantOp %v2int BitwiseAnd %signed_one_vec %xor_1_3",
  1504. "%or_1_2 = OpSpecConstantOp %v2int BitwiseOr %signed_one_vec %xor_1_3",
  1505. "%unsigned_31 = OpConstant %uint 31",
  1506. "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
  1507. "%unsigned_left_shift_max = OpSpecConstantOp %v2uint ShiftLeftLogical %unsigned_one_vec %v2unsigned_31",
  1508. "%unsigned_right_shift_logical = OpSpecConstantOp %v2uint ShiftRightLogical %unsigned_left_shift_max %v2unsigned_31",
  1509. "%signed_right_shift_arithmetic = OpSpecConstantOp %v2int ShiftRightArithmetic %unsigned_left_shift_max %v2unsigned_31",
  1510. },
  1511. // expected
  1512. {
  1513. "%xor_1_3 = OpConstantComposite %v2int %signed_two %signed_two",
  1514. "%and_1_2 = OpConstantComposite %v2int %signed_zero %signed_zero",
  1515. "%or_1_2 = OpConstantComposite %v2int %signed_three %signed_three",
  1516. "%unsigned_31 = OpConstant %uint 31",
  1517. "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
  1518. "%uint_2147483648 = OpConstant %uint 2147483648",
  1519. "%unsigned_left_shift_max = OpConstantComposite %v2uint %uint_2147483648 %uint_2147483648",
  1520. "%unsigned_right_shift_logical = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
  1521. "%signed_right_shift_arithmetic = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
  1522. },
  1523. },
  1524. // Skip folding if any vector operands or components of the operands
  1525. // have undetermined value.
  1526. {
  1527. // original
  1528. {
  1529. "%spec_int = OpSpecConstant %int 1",
  1530. "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int",
  1531. "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec",
  1532. },
  1533. // expected
  1534. {
  1535. "%spec_int = OpSpecConstant %int 1",
  1536. "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int",
  1537. "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec",
  1538. },
  1539. },
  1540. // Skip folding if any vector operands are defined by OpUndef
  1541. {
  1542. // original
  1543. {
  1544. "%undef = OpUndef %int",
  1545. "%vec = OpConstantComposite %v2int %undef %signed_one",
  1546. "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec",
  1547. },
  1548. // expected
  1549. {
  1550. "%undef = OpUndef %int",
  1551. "%vec = OpConstantComposite %v2int %undef %signed_one",
  1552. "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec",
  1553. },
  1554. },
  1555. // clang-format on
  1556. })));
  1557. // Tests for SpecConstantOp CompositeExtract instruction
  1558. INSTANTIATE_TEST_SUITE_P(
  1559. CompositeExtract, FoldSpecConstantOpAndCompositePassTest,
  1560. ::testing::ValuesIn(std::vector<
  1561. FoldSpecConstantOpAndCompositePassTestCase>({
  1562. // clang-format off
  1563. // normal vector
  1564. {
  1565. // original
  1566. {
  1567. "%r = OpSpecConstantOp %int CompositeExtract %signed_three_vec 0",
  1568. "%x = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 0",
  1569. "%y = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 1",
  1570. "%z = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 2",
  1571. "%w = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 3",
  1572. },
  1573. // expected
  1574. {
  1575. "%r = OpConstant %int 3",
  1576. "%x = OpConstant %int 0",
  1577. "%y = OpConstant %int 1",
  1578. "%z = OpConstant %int 2",
  1579. "%w = OpConstant %int 3",
  1580. },
  1581. },
  1582. // null vector
  1583. {
  1584. // original
  1585. {
  1586. "%x = OpSpecConstantOp %int CompositeExtract %signed_null_vec 0",
  1587. "%y = OpSpecConstantOp %int CompositeExtract %signed_null_vec 1",
  1588. "%null_v4int = OpConstantNull %v4int",
  1589. "%z = OpSpecConstantOp %int CompositeExtract %signed_null_vec 2",
  1590. },
  1591. // expected
  1592. {
  1593. "%x = OpConstantNull %int",
  1594. "%y = OpConstantNull %int",
  1595. "%null_v4int = OpConstantNull %v4int",
  1596. "%z = OpConstantNull %int",
  1597. }
  1598. },
  1599. // normal flat struct
  1600. {
  1601. // original
  1602. {
  1603. "%float_1 = OpConstant %float 1",
  1604. "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
  1605. "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat_1 0",
  1606. "%extract_int = OpSpecConstantOp %int CompositeExtract %flat_1 1",
  1607. "%extract_float_1 = OpSpecConstantOp %float CompositeExtract %flat_1 2",
  1608. // foldable composite constants built with OpSpecConstantComposite
  1609. // should also be processed.
  1610. "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1",
  1611. "%extract_float_2 = OpSpecConstantOp %float CompositeExtract %flat_2 2",
  1612. },
  1613. // expected
  1614. {
  1615. "%float_1 = OpConstant %float 1",
  1616. "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
  1617. "%extract_bool = OpConstantTrue %bool",
  1618. "%extract_int = OpConstantNull %int",
  1619. "%extract_float_1 = OpConstant %float 1",
  1620. "%flat_2 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
  1621. "%extract_float_2 = OpConstant %float 1",
  1622. },
  1623. },
  1624. // null flat struct
  1625. {
  1626. // original
  1627. {
  1628. "%flat = OpConstantNull %flat_struct",
  1629. "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat 0",
  1630. "%extract_int = OpSpecConstantOp %int CompositeExtract %flat 1",
  1631. "%extract_float = OpSpecConstantOp %float CompositeExtract %flat 2",
  1632. },
  1633. // expected
  1634. {
  1635. "%flat = OpConstantNull %flat_struct",
  1636. "%extract_bool = OpConstantNull %bool",
  1637. "%extract_int = OpConstantNull %int",
  1638. "%extract_float = OpConstantNull %float",
  1639. },
  1640. },
  1641. // normal nested struct
  1642. {
  1643. // original
  1644. {
  1645. "%float_1 = OpConstant %float 1",
  1646. "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
  1647. "%outer = OpConstantComposite %outer_struct %inner %signed_one",
  1648. "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0",
  1649. "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1",
  1650. "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2",
  1651. },
  1652. // expected
  1653. {
  1654. "%float_1 = OpConstant %float 1",
  1655. "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
  1656. "%outer = OpConstantComposite %outer_struct %inner %signed_one",
  1657. "%extract_inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
  1658. "%extract_int = OpConstant %int 1",
  1659. "%extract_inner_float = OpConstant %float 1",
  1660. },
  1661. },
  1662. // null nested struct
  1663. {
  1664. // original
  1665. {
  1666. "%outer = OpConstantNull %outer_struct",
  1667. "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0",
  1668. "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1",
  1669. "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2",
  1670. },
  1671. // expected
  1672. {
  1673. "%outer = OpConstantNull %outer_struct",
  1674. "%extract_inner = OpConstantNull %inner_struct",
  1675. "%extract_int = OpConstantNull %int",
  1676. "%extract_inner_float = OpConstantNull %float",
  1677. },
  1678. },
  1679. // skip folding if the any composite constant's value are not fully
  1680. // determined, even though the extracting target might have
  1681. // determined value.
  1682. {
  1683. // original
  1684. {
  1685. "%float_1 = OpConstant %float 1",
  1686. "%spec_float = OpSpecConstant %float 1",
  1687. "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
  1688. "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one",
  1689. "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1",
  1690. "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1",
  1691. "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1",
  1692. "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1",
  1693. },
  1694. // expected
  1695. {
  1696. "%float_1 = OpConstant %float 1",
  1697. "%spec_float = OpSpecConstant %float 1",
  1698. "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
  1699. "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one",
  1700. "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1",
  1701. "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1",
  1702. "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1",
  1703. "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1",
  1704. },
  1705. },
  1706. // skip if the composite constant depends on the result of OpUndef,
  1707. // even though the composite extract target element does not depends
  1708. // on the OpUndef.
  1709. {
  1710. // original
  1711. {
  1712. "%undef = OpUndef %float",
  1713. "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
  1714. "%outer = OpConstantComposite %outer_struct %inner %signed_one",
  1715. "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1",
  1716. "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1",
  1717. },
  1718. // expected
  1719. {
  1720. "%undef = OpUndef %float",
  1721. "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
  1722. "%outer = OpConstantComposite %outer_struct %inner %signed_one",
  1723. "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1",
  1724. "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1",
  1725. },
  1726. },
  1727. // TODO(qining): Add tests for Array and other composite type constants.
  1728. // clang-format on
  1729. })));
  1730. // Tests the swizzle operations for spec const vectors.
  1731. INSTANTIATE_TEST_SUITE_P(
  1732. VectorShuffle, FoldSpecConstantOpAndCompositePassTest,
  1733. ::testing::ValuesIn(std::vector<
  1734. FoldSpecConstantOpAndCompositePassTestCase>({
  1735. // clang-format off
  1736. // normal vector
  1737. {
  1738. // original
  1739. {
  1740. "%xy = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 1",
  1741. "%yz = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 2",
  1742. "%zw = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 3",
  1743. "%wx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 3 0",
  1744. "%xx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 0",
  1745. "%yyy = OpSpecConstantOp %v3int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 1 1",
  1746. "%wwww = OpSpecConstantOp %v4int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 2 2 2",
  1747. },
  1748. // expected
  1749. {
  1750. "%xy = OpConstantComposite %v2int %signed_zero %signed_one",
  1751. "%yz = OpConstantComposite %v2int %signed_one %signed_two",
  1752. "%zw = OpConstantComposite %v2int %signed_two %signed_three",
  1753. "%wx = OpConstantComposite %v2int %signed_three %signed_zero",
  1754. "%xx = OpConstantComposite %v2int %signed_zero %signed_zero",
  1755. "%yyy = OpConstantComposite %v3int %signed_one %signed_one %signed_one",
  1756. "%wwww = OpConstantComposite %v4int %signed_two %signed_two %signed_two %signed_two",
  1757. },
  1758. },
  1759. // null vector
  1760. {
  1761. // original
  1762. {
  1763. "%a = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 0 1",
  1764. "%b = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 2 3",
  1765. "%c = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %signed_null_vec 3 4",
  1766. "%d = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %signed_null_vec 1 2",
  1767. },
  1768. // expected
  1769. {
  1770. "%a = OpConstantComposite %v2int %signed_null %signed_null",
  1771. "%b = OpConstantComposite %v2int %signed_zero %signed_one",
  1772. "%c = OpConstantComposite %v2int %signed_three %signed_null",
  1773. "%d = OpConstantComposite %v2int %signed_null %signed_null",
  1774. }
  1775. },
  1776. // skip if any of the components of the vector operands do not have
  1777. // determined value, even though the result vector might not be
  1778. // built with those undermined values.
  1779. {
  1780. // original
  1781. {
  1782. "%spec_int = OpSpecConstant %int 1",
  1783. "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int",
  1784. "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1",
  1785. "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4",
  1786. },
  1787. // expected
  1788. {
  1789. "%spec_int = OpSpecConstant %int 1",
  1790. "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int",
  1791. "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1",
  1792. "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4",
  1793. },
  1794. },
  1795. // Skip if any components of the two vector operands depend on
  1796. // the result of OpUndef. Even though the selected components do
  1797. // not depend on the OpUndef result.
  1798. {
  1799. // original
  1800. {
  1801. "%undef = OpUndef %int",
  1802. "%vec_1 = OpConstantComposite %v2int %undef %signed_one",
  1803. "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3",
  1804. "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3",
  1805. "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3",
  1806. },
  1807. // expected
  1808. {
  1809. "%undef = OpUndef %int",
  1810. "%vec_1 = OpConstantComposite %v2int %undef %signed_one",
  1811. "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3",
  1812. "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3",
  1813. "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3",
  1814. },
  1815. },
  1816. // clang-format on
  1817. })));
  1818. // Test with long use-def chain.
  1819. INSTANTIATE_TEST_SUITE_P(
  1820. LongDefUseChain, FoldSpecConstantOpAndCompositePassTest,
  1821. ::testing::ValuesIn(std::vector<
  1822. FoldSpecConstantOpAndCompositePassTestCase>({
  1823. // clang-format off
  1824. // Long Def-Use chain with binary operations.
  1825. {
  1826. // original
  1827. {
  1828. "%array_size = OpConstant %int 4",
  1829. "%type_arr_int_4 = OpTypeArray %int %array_size",
  1830. "%spec_int_0 = OpConstant %int 100",
  1831. "%spec_int_1 = OpConstant %int 1",
  1832. "%spec_int_2 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_1",
  1833. "%spec_int_3 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_2",
  1834. "%spec_int_4 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_3",
  1835. "%spec_int_5 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_4",
  1836. "%spec_int_6 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_5",
  1837. "%spec_int_7 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_6",
  1838. "%spec_int_8 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_7",
  1839. "%spec_int_9 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_8",
  1840. "%spec_int_10 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_9",
  1841. "%spec_int_11 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_10",
  1842. "%spec_int_12 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_11",
  1843. "%spec_int_13 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_12",
  1844. "%spec_int_14 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_13",
  1845. "%spec_int_15 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_14",
  1846. "%spec_int_16 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_15",
  1847. "%spec_int_17 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_16",
  1848. "%spec_int_18 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_17",
  1849. "%spec_int_19 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_18",
  1850. "%spec_int_20 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_19",
  1851. "%used_vec_a = OpSpecConstantComposite %v2int %spec_int_18 %spec_int_19",
  1852. "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a",
  1853. "%spec_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0",
  1854. "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
  1855. // Spec constants whose values can not be fully resolved should
  1856. // not be processed.
  1857. "%spec_int_22 = OpSpecConstant %int 123",
  1858. "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one",
  1859. },
  1860. // expected
  1861. {
  1862. "%array_size = OpConstant %int 4",
  1863. "%type_arr_int_4 = OpTypeArray %int %array_size",
  1864. "%spec_int_0 = OpConstant %int 100",
  1865. "%spec_int_1 = OpConstant %int 1",
  1866. "%spec_int_2 = OpConstant %int 101",
  1867. "%spec_int_3 = OpConstant %int -1",
  1868. "%spec_int_4 = OpConstant %int 99",
  1869. "%spec_int_5 = OpConstant %int 1",
  1870. "%spec_int_6 = OpConstant %int 101",
  1871. "%spec_int_7 = OpConstant %int -1",
  1872. "%spec_int_8 = OpConstant %int 99",
  1873. "%spec_int_9 = OpConstant %int 1",
  1874. "%spec_int_10 = OpConstant %int 101",
  1875. "%spec_int_11 = OpConstant %int -1",
  1876. "%spec_int_12 = OpConstant %int 99",
  1877. "%spec_int_13 = OpConstant %int 1",
  1878. "%spec_int_14 = OpConstant %int 101",
  1879. "%spec_int_15 = OpConstant %int -1",
  1880. "%spec_int_16 = OpConstant %int 101",
  1881. "%spec_int_17 = OpConstant %int 201",
  1882. "%spec_int_18 = OpConstant %int -101",
  1883. "%spec_int_19 = OpConstant %int -1",
  1884. "%spec_int_20 = OpConstant %int 101",
  1885. "%used_vec_a = OpConstantComposite %v2int %spec_int_18 %spec_int_19",
  1886. "%int_10201 = OpConstant %int 10201",
  1887. "%used_vec_b = OpConstantComposite %v2int %int_10201 %signed_one",
  1888. "%spec_int_21 = OpConstant %int 10201",
  1889. "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
  1890. "%spec_int_22 = OpSpecConstant %int 123",
  1891. "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one",
  1892. },
  1893. },
  1894. // Long Def-Use chain with swizzle
  1895. })));
  1896. } // namespace
  1897. } // namespace opt
  1898. } // namespace spvtools