if_conversion_test.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  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, DontFlatten) {
  311. const std::string text = R"(OpCapability Shader
  312. OpMemoryModel Logical GLSL450
  313. OpEntryPoint Vertex %1 "func" %2
  314. %void = OpTypeVoid
  315. %bool = OpTypeBool
  316. %true = OpConstantTrue %bool
  317. %uint = OpTypeInt 32 0
  318. %uint_0 = OpConstant %uint 0
  319. %uint_1 = OpConstant %uint 1
  320. %v2uint = OpTypeVector %uint 2
  321. %10 = OpConstantComposite %v2uint %uint_0 %uint_1
  322. %11 = OpConstantComposite %v2uint %uint_1 %uint_0
  323. %_ptr_Output_v2uint = OpTypePointer Output %v2uint
  324. %2 = OpVariable %_ptr_Output_v2uint Output
  325. %13 = OpTypeFunction %void
  326. %1 = OpFunction %void None %13
  327. %14 = OpLabel
  328. OpSelectionMerge %15 DontFlatten
  329. OpBranchConditional %true %16 %17
  330. %16 = OpLabel
  331. OpBranch %15
  332. %17 = OpLabel
  333. OpBranch %15
  334. %15 = OpLabel
  335. %18 = OpPhi %v2uint %10 %16 %11 %17
  336. OpStore %2 %18
  337. OpReturn
  338. OpFunctionEnd
  339. )";
  340. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  341. }
  342. TEST_F(IfConversionTest, LoopUntouched) {
  343. const std::string text = R"(OpCapability Shader
  344. OpMemoryModel Logical GLSL450
  345. OpEntryPoint Vertex %1 "func" %2
  346. %void = OpTypeVoid
  347. %uint = OpTypeInt 32 0
  348. %uint_0 = OpConstant %uint 0
  349. %uint_1 = OpConstant %uint 1
  350. %_ptr_Output_uint = OpTypePointer Output %uint
  351. %2 = OpVariable %_ptr_Output_uint Output
  352. %8 = OpTypeFunction %void
  353. %bool = OpTypeBool
  354. %true = OpConstantTrue %bool
  355. %1 = OpFunction %void None %8
  356. %11 = OpLabel
  357. OpBranch %12
  358. %12 = OpLabel
  359. %13 = OpPhi %uint %uint_0 %11 %uint_1 %12
  360. OpLoopMerge %14 %12 None
  361. OpBranchConditional %true %14 %12
  362. %14 = OpLabel
  363. OpStore %2 %13
  364. OpReturn
  365. OpFunctionEnd
  366. )";
  367. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  368. }
  369. TEST_F(IfConversionTest, TooManyPredecessors) {
  370. const std::string text = R"(OpCapability Shader
  371. OpMemoryModel Logical GLSL450
  372. OpEntryPoint Vertex %1 "func" %2
  373. %void = OpTypeVoid
  374. %uint = OpTypeInt 32 0
  375. %uint_0 = OpConstant %uint 0
  376. %uint_1 = OpConstant %uint 1
  377. %_ptr_Output_uint = OpTypePointer Output %uint
  378. %2 = OpVariable %_ptr_Output_uint Output
  379. %8 = OpTypeFunction %void
  380. %bool = OpTypeBool
  381. %true = OpConstantTrue %bool
  382. %1 = OpFunction %void None %8
  383. %11 = OpLabel
  384. OpSelectionMerge %12 None
  385. OpBranchConditional %true %13 %12
  386. %13 = OpLabel
  387. OpBranchConditional %true %14 %12
  388. %14 = OpLabel
  389. OpBranch %12
  390. %12 = OpLabel
  391. %15 = OpPhi %uint %uint_0 %11 %uint_0 %13 %uint_1 %14
  392. OpStore %2 %15
  393. OpReturn
  394. OpFunctionEnd
  395. )";
  396. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  397. }
  398. TEST_F(IfConversionTest, NoCodeMotion) {
  399. const std::string text = R"(OpCapability Shader
  400. OpMemoryModel Logical GLSL450
  401. OpEntryPoint Vertex %1 "func" %2
  402. %void = OpTypeVoid
  403. %uint = OpTypeInt 32 0
  404. %uint_0 = OpConstant %uint 0
  405. %uint_1 = OpConstant %uint 1
  406. %_ptr_Output_uint = OpTypePointer Output %uint
  407. %2 = OpVariable %_ptr_Output_uint Output
  408. %8 = OpTypeFunction %void
  409. %bool = OpTypeBool
  410. %true = OpConstantTrue %bool
  411. %1 = OpFunction %void None %8
  412. %11 = OpLabel
  413. OpSelectionMerge %12 None
  414. OpBranchConditional %true %13 %12
  415. %13 = OpLabel
  416. %14 = OpIAdd %uint %uint_0 %uint_1
  417. OpBranch %12
  418. %12 = OpLabel
  419. %15 = OpPhi %uint %uint_0 %11 %14 %13
  420. OpStore %2 %15
  421. OpReturn
  422. OpFunctionEnd
  423. )";
  424. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  425. }
  426. TEST_F(IfConversionTest, NoCodeMotionImmovableInst) {
  427. const std::string text = R"(OpCapability Shader
  428. OpMemoryModel Logical GLSL450
  429. OpEntryPoint Vertex %1 "func" %2
  430. %void = OpTypeVoid
  431. %uint = OpTypeInt 32 0
  432. %uint_0 = OpConstant %uint 0
  433. %uint_1 = OpConstant %uint 1
  434. %_ptr_Output_uint = OpTypePointer Output %uint
  435. %2 = OpVariable %_ptr_Output_uint Output
  436. %8 = OpTypeFunction %void
  437. %bool = OpTypeBool
  438. %true = OpConstantTrue %bool
  439. %1 = OpFunction %void None %8
  440. %11 = OpLabel
  441. OpSelectionMerge %12 None
  442. OpBranchConditional %true %13 %14
  443. %13 = OpLabel
  444. OpSelectionMerge %15 None
  445. OpBranchConditional %true %16 %15
  446. %16 = OpLabel
  447. %17 = OpIAdd %uint %uint_0 %uint_1
  448. OpBranch %15
  449. %15 = OpLabel
  450. %18 = OpPhi %uint %uint_0 %13 %17 %16
  451. %19 = OpIAdd %uint %18 %uint_1
  452. OpBranch %12
  453. %14 = OpLabel
  454. OpSelectionMerge %20 None
  455. OpBranchConditional %true %21 %20
  456. %21 = OpLabel
  457. %22 = OpIAdd %uint %uint_0 %uint_1
  458. OpBranch %20
  459. %20 = OpLabel
  460. %23 = OpPhi %uint %uint_0 %14 %22 %21
  461. %24 = OpIAdd %uint %23 %uint_1
  462. OpBranch %12
  463. %12 = OpLabel
  464. %25 = OpPhi %uint %24 %20 %19 %15
  465. OpStore %2 %25
  466. OpReturn
  467. OpFunctionEnd
  468. )";
  469. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  470. }
  471. TEST_F(IfConversionTest, InvalidCommonDominator) {
  472. const std::string text = R"(OpCapability Shader
  473. OpCapability Linkage
  474. OpMemoryModel Logical GLSL450
  475. %void = OpTypeVoid
  476. %float = OpTypeFloat 32
  477. %float_0 = OpConstant %float 0
  478. %float_1 = OpConstant %float 1
  479. %bool = OpTypeBool
  480. %true = OpConstantTrue %bool
  481. %1 = OpTypeFunction %void
  482. %2 = OpFunction %void None %1
  483. %3 = OpLabel
  484. OpBranch %4
  485. %4 = OpLabel
  486. OpLoopMerge %5 %6 None
  487. OpBranch %7
  488. %7 = OpLabel
  489. OpSelectionMerge %8 None
  490. OpBranchConditional %true %8 %9
  491. %9 = OpLabel
  492. OpSelectionMerge %10 None
  493. OpBranchConditional %true %10 %5
  494. %10 = OpLabel
  495. OpBranch %8
  496. %8 = OpLabel
  497. OpBranch %6
  498. %6 = OpLabel
  499. OpBranchConditional %true %4 %5
  500. %5 = OpLabel
  501. %11 = OpPhi %float %float_0 %6 %float_1 %9
  502. OpReturn
  503. OpFunctionEnd
  504. )";
  505. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  506. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  507. }
  508. TEST_F(IfConversionTest, DebugInfoSimpleIfThenElse) {
  509. // When it replaces an OpPhi with OpSelect, the new OpSelect must have
  510. // the same scope and line information with the OpPhi.
  511. const std::string text = R"(
  512. ; CHECK: OpSelectionMerge [[merge:%\w+]]
  513. ; CHECK: [[merge]] = OpLabel
  514. ; CHECK-NOT: OpPhi
  515. ; CHECK: DebugScope
  516. ; CHECK-NEXT: OpLine {{%\w+}} 3 7
  517. ; CHECK-NEXT: [[sel:%\w+]] = OpSelect %uint %true %uint_0 %uint_1
  518. ; CHECK-NEXT: DebugValue {{%\w+}} [[sel]]
  519. ; CHECK: OpStore {{%\w+}} [[sel]]
  520. OpCapability Shader
  521. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  522. OpMemoryModel Logical GLSL450
  523. OpEntryPoint Vertex %1 "func" %2
  524. %name = OpString "test"
  525. %void = OpTypeVoid
  526. %bool = OpTypeBool
  527. %true = OpConstantTrue %bool
  528. %uint = OpTypeInt 32 0
  529. %uint_0 = OpConstant %uint 0
  530. %uint_1 = OpConstant %uint 1
  531. %uint_32 = OpConstant %uint 32
  532. %_ptr_Output_uint = OpTypePointer Output %uint
  533. %2 = OpVariable %_ptr_Output_uint Output
  534. %11 = OpTypeFunction %void
  535. %null_expr = OpExtInst %void %ext DebugExpression
  536. %src = OpExtInst %void %ext DebugSource %name
  537. %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
  538. %dbg_tf = OpExtInst %void %ext DebugTypeBasic %name %uint_32 Float
  539. %dbg_f = OpExtInst %void %ext DebugLocalVariable %name %dbg_tf %src 0 0 %cu FlagIsLocal
  540. %1 = OpFunction %void None %11
  541. %12 = OpLabel
  542. OpSelectionMerge %14 None
  543. OpBranchConditional %true %15 %16
  544. %15 = OpLabel
  545. OpBranch %14
  546. %16 = OpLabel
  547. OpBranch %14
  548. %14 = OpLabel
  549. %scope = OpExtInst %void %ext DebugScope %cu
  550. OpLine %name 3 7
  551. %18 = OpPhi %uint %uint_0 %15 %uint_1 %16
  552. %value = OpExtInst %void %ext DebugValue %dbg_f %18 %null_expr
  553. OpStore %2 %18
  554. OpReturn
  555. OpFunctionEnd
  556. )";
  557. SinglePassRunAndMatch<IfConversion>(text, true);
  558. }
  559. TEST_F(IfConversionTest, MultipleEdgesFromSameBlock) {
  560. // If a block has two out going edges that go to the same block, then there
  561. // can be an OpPhi instruction with fewer entries than the number of incoming
  562. // edges. This must be handled.
  563. const std::string text = R"(OpCapability Shader
  564. %1 = OpExtInstImport "GLSL.std.450"
  565. OpMemoryModel Logical GLSL450
  566. OpEntryPoint Fragment %2 "main"
  567. OpExecutionMode %2 OriginUpperLeft
  568. %void = OpTypeVoid
  569. %4 = OpTypeFunction %void
  570. %bool = OpTypeBool
  571. %true = OpConstantTrue %bool
  572. %true_0 = OpConstantTrue %bool
  573. %2 = OpFunction %void None %4
  574. %8 = OpLabel
  575. OpSelectionMerge %9 None
  576. OpBranchConditional %true_0 %9 %9
  577. %9 = OpLabel
  578. %10 = OpPhi %bool %true %8
  579. OpReturn
  580. OpFunctionEnd
  581. )";
  582. SinglePassRunAndCheck<IfConversion>(text, text, true, true);
  583. }
  584. } // namespace
  585. } // namespace opt
  586. } // namespace spvtools