Jlm
theta.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2012 2013 2014 Helge Bahmann <hcb@chaoticmind.net>
3  * Copyright 2013 2014 2015 Nico Reißmann <nico.reissmann@gmail.com>
4  * See COPYING for terms of redistribution.
5  */
6 
7 #include <algorithm>
9 #include <jlm/rvsdg/theta.hpp>
10 
11 #include <algorithm>
12 
13 namespace jlm::rvsdg
14 {
15 
16 ThetaOperation::~ThetaOperation() noexcept = default;
17 
18 std::string
19 ThetaOperation::debug_string() const
20 {
21  return "THETA";
22 }
23 
24 std::unique_ptr<Operation>
26 {
27  return std::make_unique<ThetaOperation>(*this);
28 }
29 
30 ThetaNode::~ThetaNode() noexcept = default;
31 
32 [[nodiscard]] const ThetaOperation &
33 ThetaNode::GetOperation() const noexcept
34 {
35  // Theta presently has no parametrization, so we can indeed
36  // just return a singleton here.
37  static const ThetaOperation singleton;
38  return singleton;
39 }
40 
42  : StructuralNode(&parent, 1)
43 {
46 }
47 
50 {
51  Node::addInput(std::make_unique<StructuralInput>(this, origin, origin->Type()), true);
52  Node::addOutput(std::make_unique<StructuralOutput>(this, origin->Type()));
53 
54  auto input = ThetaNode::input(ninputs() - 1);
55  auto output = ThetaNode::output(noutputs() - 1);
56  auto & thetaArgument = RegionArgument::Create(*subregion(), input, input->Type());
57  auto & thetaResult = RegionResult::Create(*subregion(), thetaArgument, output, output->Type());
58 
59  return LoopVar{ input, &thetaArgument, &thetaResult, output };
60 }
61 
62 void
63 ThetaNode::RemoveLoopVars(std::vector<LoopVar> loopVars)
64 {
65  util::HashSet<size_t> inputIndices;
66  util::HashSet<size_t> argumentIndices;
67  util::HashSet<size_t> resultIndices;
68  util::HashSet<size_t> outputIndices;
69  for (const auto & [input, pre, post, output] : loopVars)
70  {
72 
73  // If the pre argument has a user, it can only be the corresponding post result
74  JLM_ASSERT(pre->nusers() <= 1);
75  if (pre->nusers() == 1)
76  {
77  JLM_ASSERT(post->origin() == pre);
78  }
79 
80  inputIndices.insert(input->index());
81  argumentIndices.insert(pre->index());
82  resultIndices.insert(post->index());
83  outputIndices.insert(output->index());
84  }
85 
86  [[maybe_unused]] const auto numRemovedResults = subregion()->RemoveResults(resultIndices);
87  JLM_ASSERT(numRemovedResults == resultIndices.Size());
88 
89  [[maybe_unused]] const auto numRemovedArguments = subregion()->RemoveArguments(argumentIndices);
90  JLM_ASSERT(numRemovedArguments == argumentIndices.Size());
91 
92  [[maybe_unused]] const auto numRemovedOutputs = RemoveOutputs(outputIndices);
93  JLM_ASSERT(numRemovedOutputs == outputIndices.Size());
94 
95  [[maybe_unused]] const auto numRemovedInputs = RemoveInputs(inputIndices);
96  JLM_ASSERT(numRemovedInputs == inputIndices.Size());
97 }
98 
99 ThetaNode *
101 {
102  SubstitutionMap rmap;
103  auto theta = create(region);
104 
105  /* add loop variables */
106  std::vector<LoopVar> oldLoopVars = GetLoopVars();
107  std::vector<LoopVar> newLoopVars;
108  for (auto olv : oldLoopVars)
109  {
110  auto nlv = theta->AddLoopVar(&smap.lookup(*olv.input->origin()));
111  newLoopVars.push_back(nlv);
112  rmap.insert(olv.pre, nlv.pre);
113  }
114 
115  /* copy subregion */
116  subregion()->copy(theta->subregion(), rmap);
117  theta->set_predicate(&rmap.lookup(*predicate()->origin()));
118 
119  /* redirect loop variables */
120  for (size_t i = 0; i < oldLoopVars.size(); ++i)
121  {
122  newLoopVars[i].post->divert_to(&rmap.lookup(*oldLoopVars[i].post->origin()));
123  smap.insert(oldLoopVars[i].output, newLoopVars[i].output);
124  }
125 
126  return theta;
127 }
128 
129 [[nodiscard]] ThetaNode::LoopVar
131 {
132  JLM_ASSERT(rvsdg::TryGetOwnerNode<ThetaNode>(input) == this);
133  return LoopVar{ const_cast<rvsdg::Input *>(&input),
135  subregion()->result(input.index() + 1),
136  output(input.index()) };
137 }
138 
139 [[nodiscard]] ThetaNode::LoopVar
141 {
142  JLM_ASSERT(rvsdg::TryGetRegionParentNode<ThetaNode>(argument) == this);
143  return LoopVar{ input(argument.index()),
144  const_cast<rvsdg::Output *>(&argument),
145  subregion()->result(argument.index() + 1),
146  output(argument.index()) };
147 }
148 
149 [[nodiscard]] ThetaNode::LoopVar
151 {
152  JLM_ASSERT(rvsdg::TryGetRegionParentNode<ThetaNode>(result) == this);
153  if (result.index() == 0)
154  {
155  // This is the loop continuation predicate.
156  // There is nothing sensible to return here.
157  throw std::logic_error("cannot map loop continuation predicate to loop variable");
158  }
159  return LoopVar{ input(result.index() - 1),
160  subregion()->argument(result.index() - 1),
161  const_cast<rvsdg::Input *>(&result),
162  output(result.index() - 1) };
163 }
164 
165 [[nodiscard]] ThetaNode::LoopVar
167 {
168  JLM_ASSERT(rvsdg::TryGetOwnerNode<ThetaNode>(output) == this);
169  return LoopVar{ input(output.index()),
171  subregion()->result(output.index() + 1),
172  const_cast<rvsdg::Output *>(&output) };
173 }
174 
175 [[nodiscard]] std::vector<ThetaNode::LoopVar>
177 {
178  std::vector<LoopVar> loopvars;
179  for (size_t index = 0; index < ninputs(); ++index)
180  {
181  loopvars.push_back(LoopVar{ input(index),
182  subregion()->argument(index),
183  subregion()->result(index + 1),
184  output(index) });
185  }
186  return loopvars;
187 }
188 
189 }
static Output & createFalse(Region &region)
Definition: control.hpp:134
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
Definition: control.cpp:50
size_t index() const noexcept
Definition: node.hpp:52
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:67
NodeOutput * addOutput(std::unique_ptr< NodeOutput > output)
Definition: node.hpp:732
rvsdg::Region * region() const noexcept
Definition: node.hpp:761
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
NodeInput * addInput(std::unique_ptr< NodeInput > input, bool notifyRegion)
Definition: node.cpp:288
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
bool IsDead() const noexcept
Definition: node.hpp:295
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
size_t RemoveResults(const util::HashSet< size_t > &indices)
Definition: region.cpp:278
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition: region.cpp:314
RegionArgument * argument(size_t index) const noexcept
Definition: region.hpp:437
size_t RemoveArguments(const util::HashSet< size_t > &indices)
Definition: region.cpp:210
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
void insert(const Output *original, Output *substitute)
Output & lookup(const Output &original) const
LoopVar MapOutputLoopVar(const rvsdg::Output &output) const
Maps variable at exit to full varibale description.
Definition: theta.cpp:166
void RemoveLoopVars(std::vector< LoopVar > loopVars)
Removes loop variables.
Definition: theta.cpp:63
RegionResult * predicate() const noexcept
Definition: theta.hpp:85
LoopVar MapPreLoopVar(const rvsdg::Output &argument) const
Maps variable at start of loop iteration to full varibale description.
Definition: theta.cpp:140
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
Definition: theta.cpp:176
ThetaNode * copy(rvsdg::Region *region, rvsdg::SubstitutionMap &smap) const override
Copy a node with substitutions.
Definition: theta.cpp:100
LoopVar MapPostLoopVar(const rvsdg::Input &result) const
Maps variable at end of loop iteration to full varibale description.
Definition: theta.cpp:150
rvsdg::Region * subregion() const noexcept
Definition: theta.hpp:79
LoopVar MapInputLoopVar(const rvsdg::Input &input) const
Maps variable at entry to full varibale description.
Definition: theta.cpp:130
static ThetaNode * create(rvsdg::Region *parent)
Definition: theta.hpp:73
~ThetaNode() noexcept override
ThetaNode(rvsdg::Region &parent)
Definition: theta.cpp:41
LoopVar AddLoopVar(rvsdg::Output *origin)
Creates a new loop-carried variable.
Definition: theta.cpp:49
std::unique_ptr< Operation > copy() const override
Definition: theta.cpp:25
~ThetaOperation() noexcept override
bool insert(ItemType item)
Definition: HashSet.hpp:210
std::size_t Size() const noexcept
Definition: HashSet.hpp:187
#define JLM_ASSERT(x)
Definition: common.hpp:16
Description of a loop-carried variable.
Definition: theta.hpp:50