Jlm
TestNodes.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2025 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
8 
9 namespace jlm::rvsdg
10 {
11 
13 
14 std::string
15 TestStructuralOperation::debug_string() const
16 {
17  return "TestStructuralOperation";
18 }
19 
20 std::unique_ptr<Operation>
22 {
23  return std::make_unique<TestStructuralOperation>(*this);
24 }
25 
26 TestStructuralNode::~TestStructuralNode() noexcept = default;
27 
28 [[nodiscard]] const TestStructuralOperation &
29 TestStructuralNode::GetOperation() const noexcept
30 {
31  static TestStructuralOperation singleton;
32  return singleton;
33 }
34 
37 {
38  auto node = create(parent, nsubregions());
39 
40  // copy inputs and arguments
41  for (auto & argument : subregion(0)->Arguments())
42  {
43  if (const auto input = argument->input())
44  {
45  auto oldInputVar = mapInput(*input);
46  auto & newOrigin = smap.lookup(*input->origin());
47  auto newInputVar = node->addInputWithArguments(newOrigin);
48  for (size_t n = 0; n < oldInputVar.argument.size(); n++)
49  {
50  auto oldArgument = oldInputVar.argument[n];
51  auto newArgument = newInputVar.argument[n];
52  smap.insert(oldArgument, newArgument);
53  }
54  }
55  else
56  {
57  auto newInputVar = node->addArguments(argument->Type());
58  for (auto & subregion : Subregions())
59  {
60  auto oldArgument = subregion.argument(argument->index());
61  JLM_ASSERT(oldArgument->input() == nullptr);
62  smap.insert(oldArgument, newInputVar.argument[subregion.index()]);
63  }
64  }
65  }
66 
67  JLM_ASSERT(ninputs() == node->ninputs());
68  for (auto & subregion : Subregions())
69  {
70  JLM_ASSERT(subregion.narguments() == node->subregion(subregion.index())->narguments());
71  }
72 
73  // copy subregions
74  for (auto & subregion : Subregions())
75  {
76  subregion.copy(node->subregion(subregion.index()), smap);
77  }
78 
79  // copy results and outputs
80  for (auto & result : subregion(0)->Results())
81  {
82  if (const auto output = result->output())
83  {
84  auto oldOutputVar = mapOutput(*output);
85 
86  std::vector<Output *> newOrigins;
87  for (auto oldOutputVarResult : oldOutputVar.result)
88  {
89  auto & newOrigin = smap.lookup(*oldOutputVarResult->origin());
90  newOrigins.push_back(&newOrigin);
91  }
92  auto newOutputVar = node->addOutputWithResults(newOrigins);
93  smap.insert(oldOutputVar.output, newOutputVar.output);
94  }
95  else
96  {
97  std::vector<Output *> newOrigins;
98  for (auto & subregion : Subregions())
99  {
100  auto subregionResult = subregion.result(result->index());
101  JLM_ASSERT(subregionResult->output() == nullptr);
102  auto & newOrigin = smap.lookup(*subregionResult->origin());
103  newOrigins.push_back(&newOrigin);
104  }
105  node->addResults(newOrigins);
106  }
107  }
108 
109  JLM_ASSERT(noutputs() == node->noutputs());
110  for (auto & subregion : Subregions())
111  {
112  JLM_ASSERT(subregion.nresults() == node->subregion(subregion.index())->nresults());
113  }
114 
115  return node;
116 }
117 
120 {
121  JLM_ASSERT(rvsdg::TryGetOwnerNode<TestStructuralNode>(input) == this);
122 
123  InputVar inputVar;
124  inputVar.input = this->input(input.index());
125  for (auto & subregion : Subregions())
126  {
127  for (auto & argument : subregion.Arguments())
128  {
129  if (argument->input() == inputVar.input)
130  {
131  inputVar.argument.push_back(argument);
132  }
133  }
134  }
135 
136  JLM_ASSERT(inputVar.argument.size() == nsubregions());
137  return inputVar;
138 }
139 
142 {
143  JLM_ASSERT(rvsdg::TryGetOwnerNode<TestStructuralNode>(output) == this);
144 
145  OutputVar outputVar;
146  outputVar.output = this->output(output.index());
147  for (auto & subregion : Subregions())
148  {
149  for (auto & result : subregion.Results())
150  {
151  if (result->output() == outputVar.output)
152  {
153  outputVar.result.push_back(result);
154  }
155  }
156  }
157 
158  JLM_ASSERT(outputVar.result.size() == nsubregions());
159  return outputVar;
160 }
161 
164 {
165  InputVar inputVar{ &addInputOnly(origin), {} };
166 
167  for (auto & subregion : Subregions())
168  {
169  const auto argument = &RegionArgument::Create(
170  subregion,
171  util::assertedCast<StructuralInput>(inputVar.input),
172  inputVar.input->Type());
173  inputVar.argument.push_back(argument);
174  }
175 
176  return inputVar;
177 }
178 
179 void
181 {
182  if (index >= ninputs())
183  throw std::out_of_range("Invalid input index.");
184 
185  auto in = input(index);
186  for (auto & argument : in->arguments)
187  {
188  argument.region()->RemoveArguments({ argument.index() });
189  }
190 
191  RemoveInputs({ index });
192 }
193 
195 TestStructuralNode::addArguments(const std::shared_ptr<const Type> & type)
196 {
197  std::vector<RegionArgument *> arguments;
198  for (auto & subregion : Subregions())
199  {
200  const auto argument = &RegionArgument::Create(subregion, nullptr, type);
201  arguments.push_back(argument);
202  }
203 
204  return { nullptr, std::move(arguments) };
205 }
206 
209 {
210  return *addInput(std::make_unique<StructuralInput>(this, &origin, origin.Type()), true);
211 }
212 
214 TestStructuralNode::addOutputOnly(std::shared_ptr<const Type> type)
215 {
216  return *addOutput(std::make_unique<StructuralOutput>(this, std::move(type)));
217 }
218 
220 TestStructuralNode::addOutputWithResults(const std::vector<Output *> & origins)
221 {
222  if (origins.size() != nsubregions())
223  throw util::Error("Insufficient number of origins.");
224 
225  size_t n = 0;
226  OutputVar outputVar{ &addOutputOnly(origins[0]->Type()), {} };
227  for (auto & subregion : Subregions())
228  {
229  const auto origin = origins[n++];
230  const auto result = &RegionResult::Create(
231  subregion,
232  *origin,
233  util::assertedCast<StructuralOutput>(outputVar.output),
234  origin->Type());
235  outputVar.result.push_back(result);
236  }
237 
238  return outputVar;
239 }
240 
241 void
243 {
244  if (index >= noutputs())
245  throw std::out_of_range("Invalid output index.");
246 
247  auto out = output(index);
248  for (auto & result : out->results)
249  {
250  result.region()->RemoveResults({ result.index() });
251  }
252 
253  RemoveOutputs({ index });
254 }
255 
257 TestStructuralNode::addResults(const std::vector<Output *> & origins)
258 {
259  if (origins.size() != nsubregions())
260  throw util::Error("Insufficient number of origins.");
261 
262  size_t n = 0;
263  std::vector<RegionResult *> results;
264  for (auto & subregion : Subregions())
265  {
266  const auto origin = origins[n++];
267  const auto result = &RegionResult::Create(subregion, *origin, nullptr, origin->Type());
268  results.push_back(result);
269  }
270 
271  return { nullptr, std::move(results) };
272 }
273 
274 }
Output * origin() const noexcept
Definition: node.hpp:58
size_t index() const noexcept
Definition: node.hpp:52
size_t RemoveInputs(const util::HashSet< size_t > &indices)
Definition: node.cpp:306
size_t ninputs() const noexcept
Definition: node.hpp:609
size_t noutputs() const noexcept
Definition: node.hpp:644
size_t RemoveOutputs(const util::HashSet< size_t > &indices)
Definition: node.cpp:342
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
size_t index() const noexcept
Definition: node.hpp:274
static RegionArgument & Create(rvsdg::Region &region, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Creates region entry argument.
Definition: region.cpp:62
static RegionResult & Create(rvsdg::Region &region, rvsdg::Output &origin, StructuralOutput *output, std::shared_ptr< const rvsdg::Type > type)
Create region exit result.
Definition: region.cpp:111
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
RegionResult * result(size_t index) const noexcept
Definition: region.hpp:471
RegionArgumentRange Arguments() noexcept
Definition: region.hpp:272
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition: region.cpp:314
size_t nresults() const noexcept
Definition: region.hpp:465
size_t index() const noexcept
Definition: region.hpp:375
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
size_t narguments() const noexcept
Definition: region.hpp:431
RegionResultRange Results() noexcept
Definition: region.hpp:290
StructuralInput * addInput(std::unique_ptr< StructuralInput > input, bool notifyRegion)
StructuralOutput * addOutput(std::unique_ptr< StructuralOutput > input)
SubregionIteratorRange Subregions()
size_t nsubregions() const noexcept
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
void insert(const Output *original, Output *substitute)
Output & lookup(const Output &original) const
void removeInputAndArguments(size_t index)
Definition: TestNodes.cpp:180
OutputVar addOutputWithResults(const std::vector< Output * > &origins)
Definition: TestNodes.cpp:220
InputVar addInputWithArguments(Output &origin)
Definition: TestNodes.cpp:163
OutputVar mapOutput(const Output &output) const
Definition: TestNodes.cpp:141
~TestStructuralNode() noexcept override
OutputVar addResults(const std::vector< Output * > &origins)
Definition: TestNodes.cpp:257
static TestStructuralNode * create(Region *parent, const size_t numSubregions)
Definition: TestNodes.hpp:152
InputVar mapInput(const Input &input) const
Definition: TestNodes.cpp:119
void removeOutputAndResults(size_t index)
Definition: TestNodes.cpp:242
StructuralOutput & addOutputOnly(std::shared_ptr< const Type > type)
Definition: TestNodes.cpp:214
InputVar addArguments(const std::shared_ptr< const Type > &type)
Definition: TestNodes.cpp:195
TestStructuralNode * copy(Region *region, SubstitutionMap &smap) const override
Copy a node with substitutions.
Definition: TestNodes.cpp:36
StructuralInput & addInputOnly(Output &origin)
Definition: TestNodes.cpp:208
std::unique_ptr< Operation > copy() const override
Definition: TestNodes.cpp:21
~TestStructuralOperation() noexcept override
#define JLM_ASSERT(x)
Definition: common.hpp:16
static std::string type(const Node *n)
Definition: view.cpp:255
A variable routed in a TestStructuralNode.
Definition: TestNodes.hpp:42
std::vector< RegionArgument * > argument
Definition: TestNodes.hpp:44
A variable routed out of a TestStructuralNode.
Definition: TestNodes.hpp:51
std::vector< RegionResult * > result
Definition: TestNodes.hpp:53