if_conversion_test.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. // Copyright (c) 2018 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string>
  15. #include "gmock/gmock.h"
  16. #include "test/opt/assembly_builder.h"
  17. #include "test/opt/pass_fixture.h"
  18. #include "test/opt/pass_utils.h"
  19. namespace spvtools {
  20. namespace opt {
  21. namespace {
  22. using IfConversionTest = PassTest<::testing::Test>;
  23. TEST_F(IfConversionTest, TestSimpleIfThenElse) {
  24. const std::string text = R"(
  25. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  26. ; CHECK: [[merge]] = OpLabel
  27. ; CHECK-NOT: OpPhi
  28. ; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1
  29. ; CHECK OpStore {{%\w+}} [[sel]]
  30. OpCapability Shader
  31. OpMemoryModel Logical GLSL450
  32. OpEntryPoint Vertex %1 "func" %2
  33. %void = OpTypeVoid
  34. %bool = OpTypeBool
  35. %true = OpConstantTrue %bool
  36. %uint = OpTypeInt 32 0
  37. %uint_0 = OpConstant %uint 0
  38. %uint_1 = OpConstant %uint 1
  39. %_ptr_Output_uint = OpTypePointer Output %uint
  40. %2 = OpVariable %_ptr_Output_uint Output
  41. %11 = OpTypeFunction %void
  42. %1 = OpFunction %void None %11
  43. %12 = OpLabel
  44. OpSelectionMerge %14 None
  45. OpBranchConditional %true %15 %16
  46. %15 = OpLabel
  47. OpBranch %14
  48. %16 = OpLabel
  49. OpBranch %14
  50. %14 = OpLabel
  51. %18 = OpPhi %uint %uint_0 %15 %uint_1 %16
  52. OpStore %2 %18
  53. OpReturn
  54. OpFunctionEnd
  55. )";
  56. SinglePassRunAndMatch<IfConversion>(text, true);
  57. }
  58. TEST_F(IfConversionTest, TestSimpleHalfIfTrue) {
  59. const std::string text = R"(
  60. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  61. ; CHECK: [[merge]] = OpLabel
  62. ; CHECK-NOT: OpPhi
  63. ; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1
  64. ; CHECK OpStore {{%\w+}} [[sel]]
  65. OpCapability Shader
  66. OpMemoryModel Logical GLSL450
  67. OpEntryPoint Vertex %1 "func" %2
  68. %void = OpTypeVoid
  69. %bool = OpTypeBool
  70. %true = OpConstantTrue %bool
  71. %uint = OpTypeInt 32 0
  72. %uint_0 = OpConstant %uint 0
  73. %uint_1 = OpConstant %uint 1
  74. %_ptr_Output_uint = OpTypePointer Output %uint
  75. %2 = OpVariable %_ptr_Output_uint Output
  76. %11 = OpTypeFunction %void
  77. %1 = OpFunction %void None %11
  78. %12 = OpLabel
  79. OpSelectionMerge %14 None
  80. OpBranchConditional %true %15 %14
  81. %15 = OpLabel
  82. OpBranch %14
  83. %14 = OpLabel
  84. %18 = OpPhi %uint %uint_0 %15 %uint_1 %12
  85. OpStore %2 %18
  86. OpReturn
  87. OpFunctionEnd
  88. )";
  89. SinglePassRunAndMatch<IfConversion>(text, true);
  90. }
  91. TEST_F(IfConversionTest, TestSimpleHalfIfExtraBlock) {
  92. const std::string text = R"(
  93. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  94. ; CHECK: [[merge]] = OpLabel
  95. ; CHECK-NOT: OpPhi
  96. ; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1
  97. ; CHECK OpStore {{%\w+}} [[sel]]
  98. OpCapability Shader
  99. OpMemoryModel Logical GLSL450
  100. OpEntryPoint Vertex %1 "func" %2
  101. %void = OpTypeVoid
  102. %bool = OpTypeBool
  103. %true = OpConstantTrue %bool
  104. %uint = OpTypeInt 32 0
  105. %uint_0 = OpConstant %uint 0
  106. %uint_1 = OpConstant %uint 1
  107. %_ptr_Output_uint = OpTypePointer Output %uint
  108. %2 = OpVariable %_ptr_Output_uint Output
  109. %11 = OpTypeFunction %void
  110. %1 = OpFunction %void None %11
  111. %12 = OpLabel
  112. OpSelectionMerge %14 None
  113. OpBranchConditional %true %15 %14
  114. %15 = OpLabel
  115. OpBranch %16
  116. %16 = OpLabel
  117. OpBranch %14
  118. %14 = OpLabel
  119. %18 = OpPhi %uint %uint_0 %15 %uint_1 %12
  120. OpStore %2 %18
  121. OpReturn
  122. OpFunctionEnd
  123. )";
  124. SinglePassRunAndMatch<IfConversion>(text, true);
  125. }
  126. TEST_F(IfConversionTest, TestSimpleHalfIfFalse) {
  127. const std::string text = R"(
  128. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  129. ; CHECK: [[merge]] = OpLabel
  130. ; CHECK-NOT: OpPhi
  131. ; CHECK: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1
  132. ; CHECK OpStore {{%\w+}} [[sel]]
  133. OpCapability Shader
  134. OpMemoryModel Logical GLSL450
  135. OpEntryPoint Vertex %1 "func" %2
  136. %void = OpTypeVoid
  137. %bool = OpTypeBool
  138. %true = OpConstantTrue %bool
  139. %uint = OpTypeInt 32 0
  140. %uint_0 = OpConstant %uint 0
  141. %uint_1 = OpConstant %uint 1
  142. %_ptr_Output_uint = OpTypePointer Output %uint
  143. %2 = OpVariable %_ptr_Output_uint Output
  144. %11 = OpTypeFunction %void
  145. %1 = OpFunction %void None %11
  146. %12 = OpLabel
  147. OpSelectionMerge %14 None
  148. OpBranchConditional %true %14 %15
  149. %15 = OpLabel
  150. OpBranch %14
  151. %14 = OpLabel
  152. %18 = OpPhi %uint %uint_0 %12 %uint_1 %15
  153. OpStore %2 %18
  154. OpReturn
  155. OpFunctionEnd
  156. )";
  157. SinglePassRunAndMatch<IfConversion>(text, true);
  158. }
  159. TEST_F(IfConversionTest, TestVectorSplat) {
  160. const std::string text = R"(
  161. ; CHECK: [[bool_vec:%\w+]] = OpTypeVector %bool 2
  162. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  163. ; CHECK: [[merge]] = OpLabel
  164. ; CHECK-NOT: OpPhi
  165. ; CHECK: [[comp:%\w+]] = OpCompositeConstruct [[bool_vec]] %true %true
  166. ; CHECK: [[sel:%\w+]] = OpSelect {{%\w+}} [[comp]]
  167. ; CHECK OpStore {{%\w+}} [[sel]]
  168. OpCapability Shader
  169. OpMemoryModel Logical GLSL450
  170. OpEntryPoint Vertex %1 "func" %2
  171. %void = OpTypeVoid
  172. %bool = OpTypeBool
  173. %true = OpConstantTrue %bool
  174. %uint = OpTypeInt 32 0
  175. %uint_0 = OpConstant %uint 0
  176. %uint_1 = OpConstant %uint 1
  177. %uint_vec2 = OpTypeVector %uint 2
  178. %vec2_01 = OpConstantComposite %uint_vec2 %uint_0 %uint_1
  179. %vec2_10 = OpConstantComposite %uint_vec2 %uint_1 %uint_0
  180. %_ptr_Output_uint = OpTypePointer Output %uint_vec2
  181. %2 = OpVariable %_ptr_Output_uint Output
  182. %11 = OpTypeFunction %void
  183. %1 = OpFunction %void None %11
  184. %12 = OpLabel
  185. OpSelectionMerge %14 None
  186. OpBranchConditional %true %15 %16
  187. %15 = OpLabel
  188. OpBranch %14
  189. %16 = OpLabel
  190. OpBranch %14
  191. %14 = OpLabel
  192. %18 = OpPhi %uint_vec2 %vec2_01 %15 %vec2_10 %16
  193. OpStore %2 %18
  194. OpReturn
  195. OpFunctionEnd
  196. )";
  197. SinglePassRunAndMatch<IfConversion>(text, true);
  198. }
  199. TEST_F(IfConversionTest, CodeMotionSameValue) {
  200. const std::string text = R"(
  201. ; CHECK: [[var:%\w+]] = OpVariable
  202. ; CHECK: OpFunction
  203. ; CHECK: OpLabel
  204. ; CHECK-NOT: OpLabel
  205. ; CHECK: [[add:%\w+]] = OpIAdd %uint %uint_0 %uint_1
  206. ; CHECK: OpSelectionMerge [[merge_lab:%\w+]] None
  207. ; CHECK-NEXT: OpBranchConditional
  208. ; CHECK: [[merge_lab]] = OpLabel
  209. ; CHECK-NOT: OpLabel
  210. ; CHECK: OpStore [[var]] [[add]]
  211. OpCapability Shader
  212. OpMemoryModel Logical GLSL450
  213. OpEntryPoint Vertex %1 "func" %2
  214. %void = OpTypeVoid
  215. %uint = OpTypeInt 32 0
  216. %uint_0 = OpConstant %uint 0
  217. %uint_1 = OpConstant %uint 1
  218. %_ptr_Output_uint = OpTypePointer Output %uint
  219. %2 = OpVariable %_ptr_Output_uint Output
  220. %8 = OpTypeFunction %void
  221. %bool = OpTypeBool
  222. %true = OpConstantTrue %bool
  223. %1 = OpFunction %void None %8
  224. %11 = OpLabel
  225. OpSelectionMerge %12 None
  226. OpBranchConditional %true %13 %15
  227. %13 = OpLabel
  228. %14 = OpIAdd %uint %uint_0 %uint_1
  229. OpBranch %12
  230. %15 = OpLabel
  231. %16 = OpIAdd %uint %uint_0 %uint_1
  232. OpBranch %12
  233. %12 = OpLabel
  234. %17 = OpPhi %uint %16 %15 %14 %13
  235. OpStore %2 %17
  236. OpReturn
  237. OpFunctionEnd
  238. )";
  239. SinglePassRunAndMatch<IfConversion>(text, true);
  240. }
  241. TEST_F(IfConversionTest, CodeMotionMultipleInstructions) {
  242. const std::string text = R"(
  243. ; CHECK: [[var:%\w+]] = OpVariable
  244. ; CHECK: OpFunction
  245. ; CHECK: OpLabel
  246. ; CHECK-NOT: OpLabel
  247. ; CHECK: [[a1:%\w+]] = OpIAdd %uint %uint_0 %uint_1
  248. ; CHECK: [[a2:%\w+]] = OpIAdd %uint [[a1]] %uint_1
  249. ; CHECK: OpSelectionMerge [[merge_lab:%\w+]] None
  250. ; CHECK-NEXT: OpBranchConditional
  251. ; CHECK: [[merge_lab]] = OpLabel
  252. ; CHECK-NOT: OpLabel
  253. ; CHECK: OpStore [[var]] [[a2]]
  254. OpCapability Shader
  255. OpMemoryModel Logical GLSL450
  256. OpEntryPoint Vertex %1 "func" %2
  257. %void = OpTypeVoid
  258. %uint = OpTypeInt 32 0
  259. %uint_0 = OpConstant %uint 0
  260. %uint_1 = OpConstant %uint 1
  261. %_ptr_Output_uint = OpTypePointer Output %uint
  262. %2 = OpVariable %_ptr_Output_uint Output
  263. %8 = OpTypeFunction %void
  264. %bool = OpTypeBool
  265. %true = OpConstantTrue %bool
  266. %1 = OpFunction %void None %8
  267. %11 = OpLabel
  268. OpSelectionMerge %12 None
  269. OpBranchConditional %true %13 %15
  270. %13 = OpLabel
  271. %a1 = OpIAdd %uint %uint_0 %uint_1
  272. %a2 = OpIAdd %uint %a1 %uint_1
  273. OpBranch %12
  274. %15 = OpLabel
  275. %b1 = OpIAdd %uint %uint_0 %uint_1
  276. %b2 = OpIAdd %uint %b1 %uint_1
  277. OpBranch %12
  278. %12 = OpLabel
  279. %17 = OpPhi %uint %b2 %15 %a2 %13
  280. OpStore %2 %17
  281. OpReturn
  282. OpFunctionEnd
  283. )";
  284. SinglePassRunAndMatch<IfConversion>(text, true);
  285. }
  286. TEST_F(IfConversionTest, NoCommonDominator) {
  287. const std::string text = R"(OpCapability Shader
  288. OpMemoryModel Logical GLSL450
  289. OpEntryPoint Vertex %1 "func" %2
  290. %void = OpTypeVoid
  291. %uint = OpTypeInt 32 0
  292. %uint_0 = OpConstant %uint 0
  293. %uint_1 = OpConstant %uint 1
  294. %_ptr_Output_uint = OpTypePointer Output %uint
  295. %2 = OpVariable %_ptr_Output_uint Output
  296. %8 = OpTypeFunction %void
  297. %1 = OpFunction %void None %8
  298. %9 = OpLabel
  299. OpBranch %10
  300. %11 = OpLabel
  301. OpBranch %10
  302. %10 = OpLabel
  303. %12 = OpPhi %uint %uint_0 %9 %uint_1 %11
  304. OpStore %2 %12
  305. OpReturn
  306. OpFunctionEnd
  307. )";
  308. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  309. }
  310. TEST_F(IfConversionTest, LoopUntouched) {
  311. const std::string text = R"(OpCapability Shader
  312. OpMemoryModel Logical GLSL450
  313. OpEntryPoint Vertex %1 "func" %2
  314. %void = OpTypeVoid
  315. %uint = OpTypeInt 32 0
  316. %uint_0 = OpConstant %uint 0
  317. %uint_1 = OpConstant %uint 1
  318. %_ptr_Output_uint = OpTypePointer Output %uint
  319. %2 = OpVariable %_ptr_Output_uint Output
  320. %8 = OpTypeFunction %void
  321. %bool = OpTypeBool
  322. %true = OpConstantTrue %bool
  323. %1 = OpFunction %void None %8
  324. %11 = OpLabel
  325. OpBranch %12
  326. %12 = OpLabel
  327. %13 = OpPhi %uint %uint_0 %11 %uint_1 %12
  328. OpLoopMerge %14 %12 None
  329. OpBranchConditional %true %14 %12
  330. %14 = OpLabel
  331. OpStore %2 %13
  332. OpReturn
  333. OpFunctionEnd
  334. )";
  335. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  336. }
  337. TEST_F(IfConversionTest, TooManyPredecessors) {
  338. const std::string text = R"(OpCapability Shader
  339. OpMemoryModel Logical GLSL450
  340. OpEntryPoint Vertex %1 "func" %2
  341. %void = OpTypeVoid
  342. %uint = OpTypeInt 32 0
  343. %uint_0 = OpConstant %uint 0
  344. %uint_1 = OpConstant %uint 1
  345. %_ptr_Output_uint = OpTypePointer Output %uint
  346. %2 = OpVariable %_ptr_Output_uint Output
  347. %8 = OpTypeFunction %void
  348. %bool = OpTypeBool
  349. %true = OpConstantTrue %bool
  350. %1 = OpFunction %void None %8
  351. %11 = OpLabel
  352. OpSelectionMerge %12 None
  353. OpBranchConditional %true %13 %12
  354. %13 = OpLabel
  355. OpBranchConditional %true %14 %12
  356. %14 = OpLabel
  357. OpBranch %12
  358. %12 = OpLabel
  359. %15 = OpPhi %uint %uint_0 %11 %uint_0 %13 %uint_1 %14
  360. OpStore %2 %15
  361. OpReturn
  362. OpFunctionEnd
  363. )";
  364. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  365. }
  366. TEST_F(IfConversionTest, NoCodeMotion) {
  367. const std::string text = R"(OpCapability Shader
  368. OpMemoryModel Logical GLSL450
  369. OpEntryPoint Vertex %1 "func" %2
  370. %void = OpTypeVoid
  371. %uint = OpTypeInt 32 0
  372. %uint_0 = OpConstant %uint 0
  373. %uint_1 = OpConstant %uint 1
  374. %_ptr_Output_uint = OpTypePointer Output %uint
  375. %2 = OpVariable %_ptr_Output_uint Output
  376. %8 = OpTypeFunction %void
  377. %bool = OpTypeBool
  378. %true = OpConstantTrue %bool
  379. %1 = OpFunction %void None %8
  380. %11 = OpLabel
  381. OpSelectionMerge %12 None
  382. OpBranchConditional %true %13 %12
  383. %13 = OpLabel
  384. %14 = OpIAdd %uint %uint_0 %uint_1
  385. OpBranch %12
  386. %12 = OpLabel
  387. %15 = OpPhi %uint %uint_0 %11 %14 %13
  388. OpStore %2 %15
  389. OpReturn
  390. OpFunctionEnd
  391. )";
  392. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  393. }
  394. TEST_F(IfConversionTest, NoCodeMotionImmovableInst) {
  395. const std::string text = R"(OpCapability Shader
  396. OpMemoryModel Logical GLSL450
  397. OpEntryPoint Vertex %1 "func" %2
  398. %void = OpTypeVoid
  399. %uint = OpTypeInt 32 0
  400. %uint_0 = OpConstant %uint 0
  401. %uint_1 = OpConstant %uint 1
  402. %_ptr_Output_uint = OpTypePointer Output %uint
  403. %2 = OpVariable %_ptr_Output_uint Output
  404. %8 = OpTypeFunction %void
  405. %bool = OpTypeBool
  406. %true = OpConstantTrue %bool
  407. %1 = OpFunction %void None %8
  408. %11 = OpLabel
  409. OpSelectionMerge %12 None
  410. OpBranchConditional %true %13 %14
  411. %13 = OpLabel
  412. OpSelectionMerge %15 None
  413. OpBranchConditional %true %16 %15
  414. %16 = OpLabel
  415. %17 = OpIAdd %uint %uint_0 %uint_1
  416. OpBranch %15
  417. %15 = OpLabel
  418. %18 = OpPhi %uint %uint_0 %13 %17 %16
  419. %19 = OpIAdd %uint %18 %uint_1
  420. OpBranch %12
  421. %14 = OpLabel
  422. OpSelectionMerge %20 None
  423. OpBranchConditional %true %21 %20
  424. %21 = OpLabel
  425. %22 = OpIAdd %uint %uint_0 %uint_1
  426. OpBranch %20
  427. %20 = OpLabel
  428. %23 = OpPhi %uint %uint_0 %14 %22 %21
  429. %24 = OpIAdd %uint %23 %uint_1
  430. OpBranch %12
  431. %12 = OpLabel
  432. %25 = OpPhi %uint %24 %20 %19 %15
  433. OpStore %2 %25
  434. OpReturn
  435. OpFunctionEnd
  436. )";
  437. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  438. }
  439. TEST_F(IfConversionTest, InvalidCommonDominator) {
  440. const std::string text = R"(OpCapability Shader
  441. OpCapability Linkage
  442. OpMemoryModel Logical GLSL450
  443. %void = OpTypeVoid
  444. %float = OpTypeFloat 32
  445. %float_0 = OpConstant %float 0
  446. %float_1 = OpConstant %float 1
  447. %bool = OpTypeBool
  448. %true = OpConstantTrue %bool
  449. %1 = OpTypeFunction %void
  450. %2 = OpFunction %void None %1
  451. %3 = OpLabel
  452. OpBranch %4
  453. %4 = OpLabel
  454. OpLoopMerge %5 %6 None
  455. OpBranch %7
  456. %7 = OpLabel
  457. OpSelectionMerge %8 None
  458. OpBranchConditional %true %8 %9
  459. %9 = OpLabel
  460. OpSelectionMerge %10 None
  461. OpBranchConditional %true %10 %5
  462. %10 = OpLabel
  463. OpBranch %8
  464. %8 = OpLabel
  465. OpBranch %6
  466. %6 = OpLabel
  467. OpBranchConditional %true %4 %5
  468. %5 = OpLabel
  469. %11 = OpPhi %float %float_0 %6 %float_1 %9
  470. OpReturn
  471. OpFunctionEnd
  472. )";
  473. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  474. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  475. }
  476. TEST_F(IfConversionTest, DebugInfoSimpleIfThenElse) {
  477. // When it replaces an OpPhi with OpSelect, the new OpSelect must have
  478. // the same scope and line information with the OpPhi.
  479. const std::string text = R"(
  480. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  481. ; CHECK: [[merge]] = OpLabel
  482. ; CHECK-NOT: OpPhi
  483. ; CHECK: DebugScope
  484. ; CHECK-NEXT: OpLine {{%\w+}} 3 7
  485. ; CHECK-NEXT: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1
  486. ; CHECK-NEXT: DebugValue {{%\w+}} [[sel]]
  487. ; CHECK: OpStore {{%\w+}} [[sel]]
  488. OpCapability Shader
  489. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  490. OpMemoryModel Logical GLSL450
  491. OpEntryPoint Vertex %1 "func" %2
  492. %name = OpString "test"
  493. %void = OpTypeVoid
  494. %bool = OpTypeBool
  495. %true = OpConstantTrue %bool
  496. %uint = OpTypeInt 32 0
  497. %uint_0 = OpConstant %uint 0
  498. %uint_1 = OpConstant %uint 1
  499. %uint_32 = OpConstant %uint 32
  500. %_ptr_Output_uint = OpTypePointer Output %uint
  501. %2 = OpVariable %_ptr_Output_uint Output
  502. %11 = OpTypeFunction %void
  503. %null_expr = OpExtInst %void %ext DebugExpression
  504. %src = OpExtInst %void %ext DebugSource %name
  505. %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
  506. %dbg_tf = OpExtInst %void %ext DebugTypeBasic %name %uint_32 Float
  507. %dbg_f = OpExtInst %void %ext DebugLocalVariable %name %dbg_tf %src 0 0 %cu FlagIsLocal
  508. %1 = OpFunction %void None %11
  509. %12 = OpLabel
  510. OpSelectionMerge %14 None
  511. OpBranchConditional %true %15 %16
  512. %15 = OpLabel
  513. OpBranch %14
  514. %16 = OpLabel
  515. OpBranch %14
  516. %14 = OpLabel
  517. %scope = OpExtInst %void %ext DebugScope %cu
  518. OpLine %name 3 7
  519. %18 = OpPhi %uint %uint_0 %15 %uint_1 %16
  520. %value = OpExtInst %void %ext DebugValue %dbg_f %18 %null_expr
  521. OpStore %2 %18
  522. OpReturn
  523. OpFunctionEnd
  524. )";
  525. SinglePassRunAndMatch<IfConversion>(text, true);
  526. }
  527. } // namespace
  528. } // namespace opt
  529. } // namespace spvtools