CFGSimplificationPass.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Compiler/Passes/CFGSimplificationPass.h"
  7. #include "AST/AST.h"
  8. #include "Function.h"
  9. namespace JSSpecCompiler {
  10. void CFGSimplificationPass::process_function()
  11. {
  12. auto& graph = *m_function->m_cfg;
  13. m_replacement.clear();
  14. m_replacement.resize(graph.blocks_count());
  15. m_state.clear();
  16. m_state.resize(graph.blocks_count());
  17. for (auto const& block : graph.blocks) {
  18. m_replacement[block->m_index] = block;
  19. if (block->m_expressions.size() == 0)
  20. if (auto jump = as<ControlFlowJump>(block->m_continuation); jump)
  21. m_replacement[block->m_index] = jump->m_block;
  22. }
  23. for (size_t i = 0; i < graph.blocks_count(); ++i)
  24. if (m_state[i] == State::NotUsed)
  25. VERIFY(compute_replacement_block(i));
  26. // Fixing references
  27. graph.start_block = m_replacement[graph.start_block->m_index];
  28. for (auto const& block : graph.blocks) {
  29. for (auto* next_block : block->m_continuation->references())
  30. *next_block = m_replacement[(*next_block)->m_index];
  31. }
  32. // Removing unused nodes
  33. m_state.span().fill(State::NotUsed);
  34. compute_referenced_blocks(graph.start_block);
  35. size_t j = 0;
  36. for (size_t i = 0; i < graph.blocks_count(); ++i) {
  37. if (m_state[graph.blocks[i]->m_index] == State::Used) {
  38. graph.blocks[j] = graph.blocks[i];
  39. graph.blocks[j]->m_index = j;
  40. ++j;
  41. }
  42. }
  43. graph.blocks.shrink(j);
  44. }
  45. bool CFGSimplificationPass::compute_replacement_block(size_t i)
  46. {
  47. if (m_state[i] == State::CurrentlyInside)
  48. return false;
  49. VERIFY(m_state[i] == State::NotUsed);
  50. m_state[i] = State::CurrentlyInside;
  51. size_t j = m_replacement[i]->m_index;
  52. if (i == j)
  53. return true;
  54. if (m_state[j] == State::NotUsed)
  55. if (!compute_replacement_block(j))
  56. return false;
  57. m_replacement[i] = m_replacement[j];
  58. m_state[i] = State::Used;
  59. return true;
  60. }
  61. void CFGSimplificationPass::compute_referenced_blocks(BasicBlockRef block)
  62. {
  63. if (m_state[block->m_index] == State::Used)
  64. return;
  65. m_state[block->m_index] = State::Used;
  66. for (auto* next : block->m_continuation->references())
  67. compute_referenced_blocks(*next);
  68. }
  69. }