DeadCodeEliminationPass.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * Copyright (c) 2023, Dan Klishch <danilklishch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Compiler/Passes/DeadCodeEliminationPass.h"
  7. #include "AST/AST.h"
  8. #include "Compiler/ControlFlowGraph.h"
  9. #include "Compiler/StronglyConnectedComponents.h"
  10. #include "Function.h"
  11. namespace JSSpecCompiler {
  12. void DeadCodeEliminationPass::process_function()
  13. {
  14. with_graph(m_function->m_local_ssa_variables.size(), [&] {
  15. remove_unused_phi_nodes();
  16. });
  17. m_function->reindex_ssa_variables();
  18. }
  19. DeadCodeEliminationPass::Vertex DeadCodeEliminationPass::as_vertex(Variable* variable)
  20. {
  21. return Vertex(variable->m_ssa);
  22. }
  23. RecursionDecision DeadCodeEliminationPass::on_entry(Tree tree)
  24. {
  25. if (tree->is_statement())
  26. TODO();
  27. return RecursionDecision::Recurse;
  28. }
  29. void DeadCodeEliminationPass::on_leave(Tree tree)
  30. {
  31. if (auto variable = as<Variable>(tree); variable)
  32. as_vertex(variable)->is_referenced = true;
  33. }
  34. void DeadCodeEliminationPass::remove_unused_phi_nodes()
  35. {
  36. for (auto const& block : m_function->m_cfg->blocks) {
  37. for (auto const& phi_node : block->m_phi_nodes) {
  38. auto to = as_vertex(phi_node.var);
  39. for (auto const& branch : phi_node.branches) {
  40. auto from = as_vertex(branch.value);
  41. from->outgoing_edges.append(to);
  42. to->incoming_edges.append(from);
  43. }
  44. }
  45. for (auto& expr : block->m_expressions)
  46. run_in_subtree(expr);
  47. run_in_const_subtree(block->m_continuation);
  48. }
  49. // FIXME?: There surely must be a way to do this in a linear time without finding strongly
  50. // connected components.
  51. for (auto const& component : find_strongly_connected_components(m_nodes)) {
  52. bool is_referenced = false;
  53. for (Vertex u : component)
  54. for (Vertex v : u->outgoing_edges)
  55. is_referenced |= v->is_referenced;
  56. if (is_referenced)
  57. for (Vertex u : component)
  58. u->is_referenced = true;
  59. }
  60. for (auto const& block : m_function->m_cfg->blocks) {
  61. block->m_phi_nodes.remove_all_matching([&](auto const& node) {
  62. return !as_vertex(node.var)->is_referenced;
  63. });
  64. }
  65. m_function->m_local_ssa_variables.remove_all_matching([&](auto const& variable) {
  66. return !Vertex(variable)->is_referenced;
  67. });
  68. }
  69. }