Jlm
DeadNodeElimination.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2021 David Metz <david.c.metz@ntnu.no>
3  * See COPYING for terms of redistribution.
4  */
5 
9 
10 namespace jlm::hls
11 {
12 
13 static bool
15 {
16  bool anyChanged = false;
17 
18  // go through in reverse because we might remove outputs
19  for (int i = loopNode.noutputs() - 1; i >= 0; --i)
20  {
21  auto output = loopNode.output(i);
22  if (output->nusers() == 0)
23  {
24  loopNode.removeLoopOutput(output);
25  anyChanged = true;
26  }
27  }
28  return anyChanged;
29 }
30 
31 static bool
33 {
34  bool anyChanged = false;
35  auto loopSubregion = loopNode.subregion();
36 
37  // go through in reverse because we might remove inputs
38  for (int i = loopNode.ninputs() - 1; i >= 0; --i)
39  {
40  auto input = loopNode.input(i);
41  JLM_ASSERT(input->arguments.size() == 1);
42  auto argument = input->arguments.begin();
43 
44  if (argument->nusers() == 0)
45  {
46  loopNode.removeLoopInput(input);
47  anyChanged = true;
48  }
49  }
50 
51  // clean up unused arguments - only ones without an input should be left
52  // go through in reverse because we might remove some
53  for (int i = loopSubregion->narguments() - 1; i >= 0; --i)
54  {
55  auto argument = loopSubregion->argument(i);
56 
57  if (auto backedgeArgument = dynamic_cast<BackEdgeArgument *>(argument))
58  {
59  auto result = backedgeArgument->result();
60  JLM_ASSERT(*result->Type() == *argument->Type());
61 
62  if (argument->nusers() == 0 || (argument->nusers() == 1 && result->origin() == argument))
63  {
64  loopSubregion->RemoveResults({ result->index() });
65  loopSubregion->RemoveArguments({ argument->index() });
66  }
67  }
68  else
69  {
70  JLM_ASSERT(argument->nusers() != 0);
71  }
72  }
73 
74  return anyChanged;
75 }
76 
77 static bool
79 {
80  bool changed = false;
81  bool anyChanged = false;
82 
83  do
84  {
85  changed = false;
86  for (auto & node : rvsdg::BottomUpTraverser(&region))
87  {
88  if (node->IsDead())
89  {
90  remove(node);
91  changed = true;
92  }
93  else if (auto loopNode = dynamic_cast<LoopNode *>(node))
94  {
95  changed |= RemoveUnusedLoopOutputs(*loopNode);
96  changed |= RemoveUnusedInputs(*loopNode);
97  changed |= EliminateDeadNodesInRegion(*loopNode->subregion());
98  }
99  }
100  anyChanged |= changed;
101  } while (changed);
102 
103  JLM_ASSERT(region.numBottomNodes() == 0);
104  return anyChanged;
105 }
106 
107 void
109 {
110  auto & rootRegion = rvsdgModule.Rvsdg().GetRootRegion();
111 
112  if (rootRegion.numNodes() != 1)
113  {
114  throw util::Error("Root should have only one node now");
115  }
116 
117  auto lambdaNode = dynamic_cast<const rvsdg::LambdaNode *>(rootRegion.Nodes().begin().ptr());
118  if (!lambdaNode)
119  {
120  throw util::Error("Node needs to be a lambda");
121  }
122 
123  EliminateDeadNodesInRegion(*lambdaNode->subregion());
124 }
125 
126 }
rvsdg::Region * subregion() const noexcept
Definition: hls.hpp:725
void removeLoopOutput(rvsdg::StructuralOutput *output)
Definition: hls.cpp:197
void removeLoopInput(rvsdg::StructuralInput *input)
Definition: hls.cpp:209
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Lambda node.
Definition: lambda.hpp:83
size_t ninputs() const noexcept
Definition: node.hpp:609
size_t noutputs() const noexcept
Definition: node.hpp:644
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
size_t numBottomNodes() const noexcept
Definition: region.hpp:499
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
#define JLM_ASSERT(x)
Definition: common.hpp:16
static bool RemoveUnusedLoopOutputs(LoopNode &loopNode)
static bool RemoveUnusedInputs(LoopNode &loopNode)
static bool EliminateDeadNodesInRegion(rvsdg::Region &region)
void EliminateDeadNodes(llvm::LlvmRvsdgModule &rvsdgModule)
static void remove(Node *node)
Definition: region.hpp:932