if_conversion_test.cpp 17 KB

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