ir_context.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. // Copyright (c) 2017 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 "source/opt/ir_context.h"
  15. #include <cstring>
  16. #include "source/latest_version_glsl_std_450_header.h"
  17. #include "source/opt/log.h"
  18. #include "source/opt/mem_pass.h"
  19. #include "source/opt/reflect.h"
  20. namespace spvtools {
  21. namespace opt {
  22. void IRContext::BuildInvalidAnalyses(IRContext::Analysis set) {
  23. if (set & kAnalysisDefUse) {
  24. BuildDefUseManager();
  25. }
  26. if (set & kAnalysisInstrToBlockMapping) {
  27. BuildInstrToBlockMapping();
  28. }
  29. if (set & kAnalysisDecorations) {
  30. BuildDecorationManager();
  31. }
  32. if (set & kAnalysisCFG) {
  33. BuildCFG();
  34. }
  35. if (set & kAnalysisDominatorAnalysis) {
  36. ResetDominatorAnalysis();
  37. }
  38. if (set & kAnalysisLoopAnalysis) {
  39. ResetLoopAnalysis();
  40. }
  41. if (set & kAnalysisNameMap) {
  42. BuildIdToNameMap();
  43. }
  44. if (set & kAnalysisScalarEvolution) {
  45. BuildScalarEvolutionAnalysis();
  46. }
  47. if (set & kAnalysisRegisterPressure) {
  48. BuildRegPressureAnalysis();
  49. }
  50. if (set & kAnalysisValueNumberTable) {
  51. BuildValueNumberTable();
  52. }
  53. }
  54. void IRContext::InvalidateAnalysesExceptFor(
  55. IRContext::Analysis preserved_analyses) {
  56. uint32_t analyses_to_invalidate = valid_analyses_ & (~preserved_analyses);
  57. InvalidateAnalyses(static_cast<IRContext::Analysis>(analyses_to_invalidate));
  58. }
  59. void IRContext::InvalidateAnalyses(IRContext::Analysis analyses_to_invalidate) {
  60. if (analyses_to_invalidate & kAnalysisDefUse) {
  61. def_use_mgr_.reset(nullptr);
  62. }
  63. if (analyses_to_invalidate & kAnalysisInstrToBlockMapping) {
  64. instr_to_block_.clear();
  65. }
  66. if (analyses_to_invalidate & kAnalysisDecorations) {
  67. decoration_mgr_.reset(nullptr);
  68. }
  69. if (analyses_to_invalidate & kAnalysisCombinators) {
  70. combinator_ops_.clear();
  71. }
  72. if (analyses_to_invalidate & kAnalysisCFG) {
  73. cfg_.reset(nullptr);
  74. }
  75. if (analyses_to_invalidate & kAnalysisDominatorAnalysis) {
  76. dominator_trees_.clear();
  77. post_dominator_trees_.clear();
  78. }
  79. if (analyses_to_invalidate & kAnalysisNameMap) {
  80. id_to_name_.reset(nullptr);
  81. }
  82. if (analyses_to_invalidate & kAnalysisValueNumberTable) {
  83. vn_table_.reset(nullptr);
  84. }
  85. valid_analyses_ = Analysis(valid_analyses_ & ~analyses_to_invalidate);
  86. }
  87. Instruction* IRContext::KillInst(Instruction* inst) {
  88. if (!inst) {
  89. return nullptr;
  90. }
  91. KillNamesAndDecorates(inst);
  92. if (AreAnalysesValid(kAnalysisDefUse)) {
  93. get_def_use_mgr()->ClearInst(inst);
  94. }
  95. if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
  96. instr_to_block_.erase(inst);
  97. }
  98. if (AreAnalysesValid(kAnalysisDecorations)) {
  99. if (inst->result_id() != 0) {
  100. decoration_mgr_->RemoveDecorationsFrom(inst->result_id());
  101. }
  102. if (inst->IsDecoration()) {
  103. decoration_mgr_->RemoveDecoration(inst);
  104. }
  105. }
  106. if (type_mgr_ && IsTypeInst(inst->opcode())) {
  107. type_mgr_->RemoveId(inst->result_id());
  108. }
  109. if (constant_mgr_ && IsConstantInst(inst->opcode())) {
  110. constant_mgr_->RemoveId(inst->result_id());
  111. }
  112. RemoveFromIdToName(inst);
  113. Instruction* next_instruction = nullptr;
  114. if (inst->IsInAList()) {
  115. next_instruction = inst->NextNode();
  116. inst->RemoveFromList();
  117. delete inst;
  118. } else {
  119. // Needed for instructions that are not part of a list like OpLabels,
  120. // OpFunction, OpFunctionEnd, etc..
  121. inst->ToNop();
  122. }
  123. return next_instruction;
  124. }
  125. bool IRContext::KillDef(uint32_t id) {
  126. Instruction* def = get_def_use_mgr()->GetDef(id);
  127. if (def != nullptr) {
  128. KillInst(def);
  129. return true;
  130. }
  131. return false;
  132. }
  133. bool IRContext::ReplaceAllUsesWith(uint32_t before, uint32_t after) {
  134. if (before == after) return false;
  135. // Ensure that |after| has been registered as def.
  136. assert(get_def_use_mgr()->GetDef(after) &&
  137. "'after' is not a registered def.");
  138. std::vector<std::pair<Instruction*, uint32_t>> uses_to_update;
  139. get_def_use_mgr()->ForEachUse(
  140. before, [&uses_to_update](Instruction* user, uint32_t index) {
  141. uses_to_update.emplace_back(user, index);
  142. });
  143. Instruction* prev = nullptr;
  144. for (auto p : uses_to_update) {
  145. Instruction* user = p.first;
  146. uint32_t index = p.second;
  147. if (prev == nullptr || prev != user) {
  148. ForgetUses(user);
  149. prev = user;
  150. }
  151. const uint32_t type_result_id_count =
  152. (user->result_id() != 0) + (user->type_id() != 0);
  153. if (index < type_result_id_count) {
  154. // Update the type_id. Note that result id is immutable so it should
  155. // never be updated.
  156. if (user->type_id() != 0 && index == 0) {
  157. user->SetResultType(after);
  158. } else if (user->type_id() == 0) {
  159. SPIRV_ASSERT(consumer_, false,
  160. "Result type id considered as use while the instruction "
  161. "doesn't have a result type id.");
  162. (void)consumer_; // Makes the compiler happy for release build.
  163. } else {
  164. SPIRV_ASSERT(consumer_, false,
  165. "Trying setting the immutable result id.");
  166. }
  167. } else {
  168. // Update an in-operand.
  169. uint32_t in_operand_pos = index - type_result_id_count;
  170. // Make the modification in the instruction.
  171. user->SetInOperand(in_operand_pos, {after});
  172. }
  173. AnalyzeUses(user);
  174. }
  175. return true;
  176. }
  177. bool IRContext::IsConsistent() {
  178. #ifndef SPIRV_CHECK_CONTEXT
  179. return true;
  180. #endif
  181. if (AreAnalysesValid(kAnalysisDefUse)) {
  182. analysis::DefUseManager new_def_use(module());
  183. if (*get_def_use_mgr() != new_def_use) {
  184. return false;
  185. }
  186. }
  187. if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
  188. for (auto& func : *module()) {
  189. for (auto& block : func) {
  190. if (!block.WhileEachInst([this, &block](Instruction* inst) {
  191. if (get_instr_block(inst) != &block) {
  192. return false;
  193. }
  194. return true;
  195. }))
  196. return false;
  197. }
  198. }
  199. }
  200. if (!CheckCFG()) {
  201. return false;
  202. }
  203. return true;
  204. }
  205. void IRContext::ForgetUses(Instruction* inst) {
  206. if (AreAnalysesValid(kAnalysisDefUse)) {
  207. get_def_use_mgr()->EraseUseRecordsOfOperandIds(inst);
  208. }
  209. if (AreAnalysesValid(kAnalysisDecorations)) {
  210. if (inst->IsDecoration()) {
  211. get_decoration_mgr()->RemoveDecoration(inst);
  212. }
  213. }
  214. RemoveFromIdToName(inst);
  215. }
  216. void IRContext::AnalyzeUses(Instruction* inst) {
  217. if (AreAnalysesValid(kAnalysisDefUse)) {
  218. get_def_use_mgr()->AnalyzeInstUse(inst);
  219. }
  220. if (AreAnalysesValid(kAnalysisDecorations)) {
  221. if (inst->IsDecoration()) {
  222. get_decoration_mgr()->AddDecoration(inst);
  223. }
  224. }
  225. if (id_to_name_ &&
  226. (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
  227. id_to_name_->insert({inst->GetSingleWordInOperand(0), inst});
  228. }
  229. }
  230. void IRContext::KillNamesAndDecorates(uint32_t id) {
  231. std::vector<Instruction*> decorations =
  232. get_decoration_mgr()->GetDecorationsFor(id, true);
  233. for (Instruction* inst : decorations) {
  234. KillInst(inst);
  235. }
  236. std::vector<Instruction*> name_to_kill;
  237. for (auto name : GetNames(id)) {
  238. name_to_kill.push_back(name.second);
  239. }
  240. for (Instruction* name_inst : name_to_kill) {
  241. KillInst(name_inst);
  242. }
  243. }
  244. void IRContext::KillNamesAndDecorates(Instruction* inst) {
  245. const uint32_t rId = inst->result_id();
  246. if (rId == 0) return;
  247. KillNamesAndDecorates(rId);
  248. }
  249. void IRContext::AddCombinatorsForCapability(uint32_t capability) {
  250. if (capability == SpvCapabilityShader) {
  251. combinator_ops_[0].insert({SpvOpNop,
  252. SpvOpUndef,
  253. SpvOpConstant,
  254. SpvOpConstantTrue,
  255. SpvOpConstantFalse,
  256. SpvOpConstantComposite,
  257. SpvOpConstantSampler,
  258. SpvOpConstantNull,
  259. SpvOpTypeVoid,
  260. SpvOpTypeBool,
  261. SpvOpTypeInt,
  262. SpvOpTypeFloat,
  263. SpvOpTypeVector,
  264. SpvOpTypeMatrix,
  265. SpvOpTypeImage,
  266. SpvOpTypeSampler,
  267. SpvOpTypeSampledImage,
  268. SpvOpTypeArray,
  269. SpvOpTypeRuntimeArray,
  270. SpvOpTypeStruct,
  271. SpvOpTypeOpaque,
  272. SpvOpTypePointer,
  273. SpvOpTypeFunction,
  274. SpvOpTypeEvent,
  275. SpvOpTypeDeviceEvent,
  276. SpvOpTypeReserveId,
  277. SpvOpTypeQueue,
  278. SpvOpTypePipe,
  279. SpvOpTypeForwardPointer,
  280. SpvOpVariable,
  281. SpvOpImageTexelPointer,
  282. SpvOpLoad,
  283. SpvOpAccessChain,
  284. SpvOpInBoundsAccessChain,
  285. SpvOpArrayLength,
  286. SpvOpVectorExtractDynamic,
  287. SpvOpVectorInsertDynamic,
  288. SpvOpVectorShuffle,
  289. SpvOpCompositeConstruct,
  290. SpvOpCompositeExtract,
  291. SpvOpCompositeInsert,
  292. SpvOpCopyObject,
  293. SpvOpTranspose,
  294. SpvOpSampledImage,
  295. SpvOpImageSampleImplicitLod,
  296. SpvOpImageSampleExplicitLod,
  297. SpvOpImageSampleDrefImplicitLod,
  298. SpvOpImageSampleDrefExplicitLod,
  299. SpvOpImageSampleProjImplicitLod,
  300. SpvOpImageSampleProjExplicitLod,
  301. SpvOpImageSampleProjDrefImplicitLod,
  302. SpvOpImageSampleProjDrefExplicitLod,
  303. SpvOpImageFetch,
  304. SpvOpImageGather,
  305. SpvOpImageDrefGather,
  306. SpvOpImageRead,
  307. SpvOpImage,
  308. SpvOpImageQueryFormat,
  309. SpvOpImageQueryOrder,
  310. SpvOpImageQuerySizeLod,
  311. SpvOpImageQuerySize,
  312. SpvOpImageQueryLevels,
  313. SpvOpImageQuerySamples,
  314. SpvOpConvertFToU,
  315. SpvOpConvertFToS,
  316. SpvOpConvertSToF,
  317. SpvOpConvertUToF,
  318. SpvOpUConvert,
  319. SpvOpSConvert,
  320. SpvOpFConvert,
  321. SpvOpQuantizeToF16,
  322. SpvOpBitcast,
  323. SpvOpSNegate,
  324. SpvOpFNegate,
  325. SpvOpIAdd,
  326. SpvOpFAdd,
  327. SpvOpISub,
  328. SpvOpFSub,
  329. SpvOpIMul,
  330. SpvOpFMul,
  331. SpvOpUDiv,
  332. SpvOpSDiv,
  333. SpvOpFDiv,
  334. SpvOpUMod,
  335. SpvOpSRem,
  336. SpvOpSMod,
  337. SpvOpFRem,
  338. SpvOpFMod,
  339. SpvOpVectorTimesScalar,
  340. SpvOpMatrixTimesScalar,
  341. SpvOpVectorTimesMatrix,
  342. SpvOpMatrixTimesVector,
  343. SpvOpMatrixTimesMatrix,
  344. SpvOpOuterProduct,
  345. SpvOpDot,
  346. SpvOpIAddCarry,
  347. SpvOpISubBorrow,
  348. SpvOpUMulExtended,
  349. SpvOpSMulExtended,
  350. SpvOpAny,
  351. SpvOpAll,
  352. SpvOpIsNan,
  353. SpvOpIsInf,
  354. SpvOpLogicalEqual,
  355. SpvOpLogicalNotEqual,
  356. SpvOpLogicalOr,
  357. SpvOpLogicalAnd,
  358. SpvOpLogicalNot,
  359. SpvOpSelect,
  360. SpvOpIEqual,
  361. SpvOpINotEqual,
  362. SpvOpUGreaterThan,
  363. SpvOpSGreaterThan,
  364. SpvOpUGreaterThanEqual,
  365. SpvOpSGreaterThanEqual,
  366. SpvOpULessThan,
  367. SpvOpSLessThan,
  368. SpvOpULessThanEqual,
  369. SpvOpSLessThanEqual,
  370. SpvOpFOrdEqual,
  371. SpvOpFUnordEqual,
  372. SpvOpFOrdNotEqual,
  373. SpvOpFUnordNotEqual,
  374. SpvOpFOrdLessThan,
  375. SpvOpFUnordLessThan,
  376. SpvOpFOrdGreaterThan,
  377. SpvOpFUnordGreaterThan,
  378. SpvOpFOrdLessThanEqual,
  379. SpvOpFUnordLessThanEqual,
  380. SpvOpFOrdGreaterThanEqual,
  381. SpvOpFUnordGreaterThanEqual,
  382. SpvOpShiftRightLogical,
  383. SpvOpShiftRightArithmetic,
  384. SpvOpShiftLeftLogical,
  385. SpvOpBitwiseOr,
  386. SpvOpBitwiseXor,
  387. SpvOpBitwiseAnd,
  388. SpvOpNot,
  389. SpvOpBitFieldInsert,
  390. SpvOpBitFieldSExtract,
  391. SpvOpBitFieldUExtract,
  392. SpvOpBitReverse,
  393. SpvOpBitCount,
  394. SpvOpPhi,
  395. SpvOpImageSparseSampleImplicitLod,
  396. SpvOpImageSparseSampleExplicitLod,
  397. SpvOpImageSparseSampleDrefImplicitLod,
  398. SpvOpImageSparseSampleDrefExplicitLod,
  399. SpvOpImageSparseSampleProjImplicitLod,
  400. SpvOpImageSparseSampleProjExplicitLod,
  401. SpvOpImageSparseSampleProjDrefImplicitLod,
  402. SpvOpImageSparseSampleProjDrefExplicitLod,
  403. SpvOpImageSparseFetch,
  404. SpvOpImageSparseGather,
  405. SpvOpImageSparseDrefGather,
  406. SpvOpImageSparseTexelsResident,
  407. SpvOpImageSparseRead,
  408. SpvOpSizeOf});
  409. }
  410. }
  411. void IRContext::AddCombinatorsForExtension(Instruction* extension) {
  412. assert(extension->opcode() == SpvOpExtInstImport &&
  413. "Expecting an import of an extension's instruction set.");
  414. const char* extension_name =
  415. reinterpret_cast<const char*>(&extension->GetInOperand(0).words[0]);
  416. if (!strcmp(extension_name, "GLSL.std.450")) {
  417. combinator_ops_[extension->result_id()] = {GLSLstd450Round,
  418. GLSLstd450RoundEven,
  419. GLSLstd450Trunc,
  420. GLSLstd450FAbs,
  421. GLSLstd450SAbs,
  422. GLSLstd450FSign,
  423. GLSLstd450SSign,
  424. GLSLstd450Floor,
  425. GLSLstd450Ceil,
  426. GLSLstd450Fract,
  427. GLSLstd450Radians,
  428. GLSLstd450Degrees,
  429. GLSLstd450Sin,
  430. GLSLstd450Cos,
  431. GLSLstd450Tan,
  432. GLSLstd450Asin,
  433. GLSLstd450Acos,
  434. GLSLstd450Atan,
  435. GLSLstd450Sinh,
  436. GLSLstd450Cosh,
  437. GLSLstd450Tanh,
  438. GLSLstd450Asinh,
  439. GLSLstd450Acosh,
  440. GLSLstd450Atanh,
  441. GLSLstd450Atan2,
  442. GLSLstd450Pow,
  443. GLSLstd450Exp,
  444. GLSLstd450Log,
  445. GLSLstd450Exp2,
  446. GLSLstd450Log2,
  447. GLSLstd450Sqrt,
  448. GLSLstd450InverseSqrt,
  449. GLSLstd450Determinant,
  450. GLSLstd450MatrixInverse,
  451. GLSLstd450ModfStruct,
  452. GLSLstd450FMin,
  453. GLSLstd450UMin,
  454. GLSLstd450SMin,
  455. GLSLstd450FMax,
  456. GLSLstd450UMax,
  457. GLSLstd450SMax,
  458. GLSLstd450FClamp,
  459. GLSLstd450UClamp,
  460. GLSLstd450SClamp,
  461. GLSLstd450FMix,
  462. GLSLstd450IMix,
  463. GLSLstd450Step,
  464. GLSLstd450SmoothStep,
  465. GLSLstd450Fma,
  466. GLSLstd450FrexpStruct,
  467. GLSLstd450Ldexp,
  468. GLSLstd450PackSnorm4x8,
  469. GLSLstd450PackUnorm4x8,
  470. GLSLstd450PackSnorm2x16,
  471. GLSLstd450PackUnorm2x16,
  472. GLSLstd450PackHalf2x16,
  473. GLSLstd450PackDouble2x32,
  474. GLSLstd450UnpackSnorm2x16,
  475. GLSLstd450UnpackUnorm2x16,
  476. GLSLstd450UnpackHalf2x16,
  477. GLSLstd450UnpackSnorm4x8,
  478. GLSLstd450UnpackUnorm4x8,
  479. GLSLstd450UnpackDouble2x32,
  480. GLSLstd450Length,
  481. GLSLstd450Distance,
  482. GLSLstd450Cross,
  483. GLSLstd450Normalize,
  484. GLSLstd450FaceForward,
  485. GLSLstd450Reflect,
  486. GLSLstd450Refract,
  487. GLSLstd450FindILsb,
  488. GLSLstd450FindSMsb,
  489. GLSLstd450FindUMsb,
  490. GLSLstd450InterpolateAtCentroid,
  491. GLSLstd450InterpolateAtSample,
  492. GLSLstd450InterpolateAtOffset,
  493. GLSLstd450NMin,
  494. GLSLstd450NMax,
  495. GLSLstd450NClamp};
  496. } else {
  497. // Map the result id to the empty set.
  498. combinator_ops_[extension->result_id()];
  499. }
  500. }
  501. void IRContext::InitializeCombinators() {
  502. get_feature_mgr()->GetCapabilities()->ForEach(
  503. [this](SpvCapability cap) { AddCombinatorsForCapability(cap); });
  504. for (auto& extension : module()->ext_inst_imports()) {
  505. AddCombinatorsForExtension(&extension);
  506. }
  507. valid_analyses_ |= kAnalysisCombinators;
  508. }
  509. void IRContext::RemoveFromIdToName(const Instruction* inst) {
  510. if (id_to_name_ &&
  511. (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
  512. auto range = id_to_name_->equal_range(inst->GetSingleWordInOperand(0));
  513. for (auto it = range.first; it != range.second; ++it) {
  514. if (it->second == inst) {
  515. id_to_name_->erase(it);
  516. break;
  517. }
  518. }
  519. }
  520. }
  521. LoopDescriptor* IRContext::GetLoopDescriptor(const Function* f) {
  522. if (!AreAnalysesValid(kAnalysisLoopAnalysis)) {
  523. ResetLoopAnalysis();
  524. }
  525. std::unordered_map<const Function*, LoopDescriptor>::iterator it =
  526. loop_descriptors_.find(f);
  527. if (it == loop_descriptors_.end()) {
  528. return &loop_descriptors_
  529. .emplace(std::make_pair(f, LoopDescriptor(this, f)))
  530. .first->second;
  531. }
  532. return &it->second;
  533. }
  534. // Gets the dominator analysis for function |f|.
  535. DominatorAnalysis* IRContext::GetDominatorAnalysis(const Function* f) {
  536. if (!AreAnalysesValid(kAnalysisDominatorAnalysis)) {
  537. ResetDominatorAnalysis();
  538. }
  539. if (dominator_trees_.find(f) == dominator_trees_.end()) {
  540. dominator_trees_[f].InitializeTree(*cfg(), f);
  541. }
  542. return &dominator_trees_[f];
  543. }
  544. // Gets the postdominator analysis for function |f|.
  545. PostDominatorAnalysis* IRContext::GetPostDominatorAnalysis(const Function* f) {
  546. if (!AreAnalysesValid(kAnalysisDominatorAnalysis)) {
  547. ResetDominatorAnalysis();
  548. }
  549. if (post_dominator_trees_.find(f) == post_dominator_trees_.end()) {
  550. post_dominator_trees_[f].InitializeTree(*cfg(), f);
  551. }
  552. return &post_dominator_trees_[f];
  553. }
  554. bool IRContext::CheckCFG() {
  555. std::unordered_map<uint32_t, std::vector<uint32_t>> real_preds;
  556. if (!AreAnalysesValid(kAnalysisCFG)) {
  557. return true;
  558. }
  559. for (Function& function : *module()) {
  560. for (const auto& bb : function) {
  561. bb.ForEachSuccessorLabel([&bb, &real_preds](const uint32_t lab_id) {
  562. real_preds[lab_id].push_back(bb.id());
  563. });
  564. }
  565. for (auto& bb : function) {
  566. std::vector<uint32_t> preds = cfg()->preds(bb.id());
  567. std::vector<uint32_t> real = real_preds[bb.id()];
  568. std::sort(preds.begin(), preds.end());
  569. std::sort(real.begin(), real.end());
  570. bool same = true;
  571. if (preds.size() != real.size()) {
  572. same = false;
  573. }
  574. for (size_t i = 0; i < real.size() && same; i++) {
  575. if (preds[i] != real[i]) {
  576. same = false;
  577. }
  578. }
  579. if (!same) {
  580. std::cerr << "Predecessors for " << bb.id() << " are different:\n";
  581. std::cerr << "Real:";
  582. for (uint32_t i : real) {
  583. std::cerr << ' ' << i;
  584. }
  585. std::cerr << std::endl;
  586. std::cerr << "Recorded:";
  587. for (uint32_t i : preds) {
  588. std::cerr << ' ' << i;
  589. }
  590. std::cerr << std::endl;
  591. }
  592. if (!same) return false;
  593. }
  594. }
  595. return true;
  596. }
  597. } // namespace opt
  598. } // namespace spvtools