Jlm
Loading...
Searching...
No Matches
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
8#include <jlm/rvsdg/theta.hpp>
9#include <jlm/rvsdg/Trace.hpp>
10
11#include <algorithm>
12
13namespace jlm::rvsdg
14{
15
17
18std::string
19ThetaOperation::debug_string() const
20{
21 return "THETA";
22}
23
24std::unique_ptr<Operation>
26{
27 return std::make_unique<ThetaOperation>(*this);
28}
29
31
33ThetaNode::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
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);
58
60}
61
62void
64{
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
88
91
94
97}
98
101{
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()));
124 }
125
126 return theta;
127}
128
131{
133 return LoopVar{ const_cast<rvsdg::Input *>(&input),
135 subregion()->result(input.index() + 1),
136 output(input.index()) };
137}
138
141{
143 return LoopVar{ input(argument.index()),
144 const_cast<rvsdg::Output *>(&argument),
145 subregion()->result(argument.index() + 1),
146 output(argument.index()) };
147}
148
151{
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]] std::variant<ThetaNode::LoopVar, ThetaNode::PredicateVar>
167{
169 if (result.index() == 0)
170 {
171 return PredicateVar{ const_cast<rvsdg::Input *>(&result) };
172 }
173 else
174 {
175 return LoopVar{ input(result.index() - 1),
176 subregion()->argument(result.index() - 1),
177 const_cast<rvsdg::Input *>(&result),
178 output(result.index() - 1) };
179 }
180}
181
184{
186 return LoopVar{ input(output.index()),
188 subregion()->result(output.index() + 1),
189 const_cast<rvsdg::Output *>(&output) };
190}
191
192[[nodiscard]] std::vector<ThetaNode::LoopVar>
194{
195 std::vector<LoopVar> loopvars;
196 for (size_t index = 0; index < ninputs(); ++index)
197 {
198 loopvars.push_back(LoopVar{ input(index),
199 subregion()->argument(index),
200 subregion()->result(index + 1),
201 output(index) });
202 }
203 return loopvars;
204}
205
206bool
208{
209 auto thetaNode = dynamic_cast<const ThetaNode *>(&node);
210 if (!thetaNode)
211 return false;
212
213 auto & tracedPredicate = traceOutput(*thetaNode->predicate()->origin(), false);
214 auto [constantNode, constantOp] =
216 if (!constantOp)
217 return false;
218
219 JLM_ASSERT(constantOp->value().nalternatives() == 2);
220 if (constantOp->value().alternative() != 0)
221 return false;
222
223 // At this point we know that the predicate is statically known to be false and we can copy the
224 // subregion into the theta node's parent region
226 for (const auto & loopVar : thetaNode->GetLoopVars())
227 smap.insert(loopVar.pre, loopVar.input->origin());
228
229 thetaNode->subregion()->copy(thetaNode->region(), smap);
230
231 for (const auto & loopVar : thetaNode->GetLoopVars())
232 loopVar.output->divert_users(&smap.lookup(*loopVar.post->origin()));
233
234 remove(&node);
235 return true;
236}
237
238}
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
NodeInput * input(size_t index) const noexcept
Definition node.hpp:615
NodeOutput * output(size_t index) const noexcept
Definition node.hpp:650
size_t RemoveInputs(const util::HashSet< size_t > &indices)
Definition node.cpp:306
rvsdg::Region * region() const noexcept
Definition node.hpp:761
size_t ninputs() const noexcept
Definition node.hpp:609
NodeOutput * addOutput(std::unique_ptr< NodeOutput > output)
Definition node.hpp:732
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
size_t index() const noexcept
Definition node.hpp:274
bool IsDead() const noexcept
Definition node.hpp:295
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
static RegionArgument & Create(rvsdg::Region &region, StructuralInput *input, std::shared_ptr< const rvsdg::Type > type)
Creates region entry argument.
Definition region.cpp:63
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:112
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
size_t RemoveResults(const util::HashSet< size_t > &indices)
Definition region.cpp:281
RegionArgument * argument(size_t index) const noexcept
Definition region.hpp:466
void copy(Region *target, SubstitutionMap &smap) const
Copy a region with substitutions.
Definition region.cpp:317
RegionResult * result(size_t index) const noexcept
Definition region.hpp:500
size_t RemoveArguments(const util::HashSet< size_t > &indices)
Definition region.cpp:213
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
void insert(const Output *original, Output *substitute)
LoopVar MapOutputLoopVar(const rvsdg::Output &output) const
Maps variable at exit to full varibale description.
Definition theta.cpp:183
void RemoveLoopVars(std::vector< LoopVar > loopVars)
Removes loop variables.
Definition theta.cpp:63
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:193
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 variable description.
Definition theta.cpp:150
rvsdg::Region * subregion() const noexcept
Definition theta.hpp:90
static bool reduceStaticallyKnownPredicate(Node &node)
Definition theta.cpp:207
std::variant< LoopVar, PredicateVar > mapResult(const rvsdg::Input &result) const
Maps variable at end of loop iteration to variable description.
Definition theta.cpp:166
static ThetaNode * create(rvsdg::Region *parent)
Definition theta.hpp:84
LoopVar MapInputLoopVar(const rvsdg::Input &input) const
Maps variable at entry to full varibale description.
Definition theta.cpp:130
RegionResult * predicate() const noexcept
Definition theta.hpp:96
~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
#define JLM_ASSERT(x)
Definition common.hpp:16
Output & traceOutput(Output &output, bool mayEnterSubregions, const Region *withinRegion)
Definition Trace.cpp:454
static void remove(Node *node)
Definition region.hpp:1035
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
Description of a loop-carried variable.
Definition theta.hpp:50
Description of the loop predicate variable.
Definition theta.hpp:73