44 static std::unique_ptr<Statistics>
47 return std::make_unique<Statistics>(sourceFile);
54 auto [matchNode, matchOperation] =
55 rvsdg::TryGetSimpleNodeAndOptionalOp<rvsdg::MatchOperation>(*theta.
predicate()->
origin());
60 if (matchNode->output(0)->nusers() != 2)
64 for (
const auto & user : matchNode->output(0)->Users())
69 gammaNode = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(user);
78 const auto origin = loopVar.post->origin();
79 if (rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*origin))
83 else if (rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(*origin) == gammaNode)
105 for (
const auto & loopVar : thetaNode.
GetLoopVars())
107 if (rvsdg::TryGetOwnerNode<rvsdg::Node>(*loopVar.post->origin()) != &gammaNode)
109 auto [input, branchArgument] = gammaNode.
AddEntryVar(loopVar.post->origin());
111 auto [_, output] = gammaNode.
AddExitVar({ branchArgument[0], branchArgument[1] });
112 loopVar.post->divert_to(output);
119 std::vector<std::vector<rvsdg::Node *>>
128 std::vector<std::vector<rvsdg::Node *>> nodes;
131 if (&node == &gammaNode)
134 const auto depth = depthMap[&node];
135 if (depth >= nodes.size())
136 nodes.resize(depth + 1);
137 nodes[depth].push_back(&node);
147 const std::vector<std::vector<rvsdg::Node *>> & nodes)
149 for (
auto & sameDepthNodes : nodes)
151 for (
const auto & node : sameDepthNodes)
152 node->copy(&target, substitutionMap);
168 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
169 substitutionMap.
insert(oldLoopVar.pre, oldLoopVar.input->origin());
173 &substitutionMap.
lookup(*oldGammaNode->predicate()->origin()),
174 oldGammaNode->nsubregions());
180 auto oldSubregion0 = oldGammaNode->subregion(0);
181 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
183 if (rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*oldInput->origin()))
185 auto oldLoopVar = oldThetaNode.
MapPreLoopVar(*oldInput->origin());
186 auto [_, branchArgument] = newGammaNode->AddEntryVar(oldLoopVar.input->origin());
187 subregion0Map.
insert(oldBranchArgument[0], branchArgument[0]);
191 auto substitute = &substitutionMap.
lookup(*oldInput->origin());
192 auto [_, branchArgument] = newGammaNode->AddEntryVar(substitute);
193 subregion0Map.
insert(oldBranchArgument[0], branchArgument[0]);
198 oldSubregion0->copy(newGammaNode->subregion(0), subregion0Map);
201 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
203 auto output = oldLoopVar.post->origin();
204 auto substitute = &subregion0Map.
lookup(*oldSubregion0->result(output->index())->origin());
205 subregion0Map.
insert(oldLoopVar.post->origin(), substitute);
215 auto oldSubregion0 = oldGammaNode->subregion(0);
216 auto oldSubregion1 = oldGammaNode->subregion(1);
218 std::unordered_map<rvsdg::Input *, rvsdg::ThetaNode::LoopVar> newLoopVars;
219 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
221 auto [_, branchArgument] = newGammaNode->AddEntryVar(oldLoopVar.input->origin());
222 auto newLoopVar = newThetaNode->AddLoopVar(branchArgument[1]);
223 subregion1Map.
insert(oldLoopVar.pre, newLoopVar.pre);
224 newLoopVars[oldLoopVar.input] = newLoopVar;
226 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
228 if (rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*oldInput->origin()))
230 auto oldLoopVar = oldThetaNode.
MapPreLoopVar(*oldInput->origin());
231 subregion1Map.
insert(oldBranchArgument[1], newLoopVars[oldLoopVar.input].pre);
235 auto [_, newBranchArgument] =
236 newGammaNode->AddEntryVar(&substitutionMap.
lookup(*oldInput->origin()));
237 auto newLoopVar = newThetaNode->AddLoopVar(newBranchArgument[1]);
238 subregion1Map.
insert(oldBranchArgument[1], newLoopVar.pre);
239 newLoopVars[oldInput] = newLoopVar;
244 oldSubregion1->copy(newThetaNode->subregion(), subregion1Map);
247 for (
const auto & oldLopVar : oldThetaNode.
GetLoopVars())
249 auto output = oldLopVar.post->origin();
250 auto substitute = &subregion1Map.
lookup(*oldSubregion1->result(output->index())->origin());
251 subregion1Map.
insert(oldLopVar.pre, substitute);
256 auto predicate = &subregion1Map.
lookup(*oldGammaNode->predicate()->origin());
259 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
261 auto output = oldLoopVar.post->origin();
262 auto substitute = &subregion1Map.
lookup(*oldSubregion1->result(output->index())->origin());
263 newLoopVars[oldLoopVar.input].post->divert_to(substitute);
264 subregion1Map.
insert(oldLoopVar.post->origin(), newLoopVars[oldLoopVar.input].output);
266 for (
const auto & [input, branchArgument] : oldGammaNode->GetEntryVars())
268 if (rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*input->origin()))
270 auto oldLoopVar = oldThetaNode.
MapPreLoopVar(*input->origin());
271 subregion1Map.
insert(branchArgument[0], newLoopVars[oldLoopVar.input].output);
275 auto substitute = &subregion1Map.
lookup(*input->origin());
276 newLoopVars[input].post->divert_to(substitute);
277 subregion1Map.
insert(branchArgument[0], newLoopVars[input].output);
281 newThetaNode->set_predicate(predicate);
284 oldSubregion0->copy(newGammaNode->subregion(1), subregion1Map);
287 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
289 auto output = oldLoopVar.post->origin();
290 auto substitute = &subregion1Map.
lookup(*oldSubregion0->result(output->index())->origin());
291 subregion1Map.
insert(oldLoopVar.post->origin(), substitute);
296 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
298 auto o0 = &subregion0Map.
lookup(*oldLoopVar.post->origin());
299 auto o1 = &subregion1Map.
lookup(*oldLoopVar.post->origin());
300 auto [_, output] = newGammaNode->AddExitVar({ o0, o1 });
301 substitutionMap.
insert(oldLoopVar.output, output);
305 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
306 oldLoopVar.output->divert_users(&substitutionMap.
lookup(*oldLoopVar.output));
314 bool unswitchedLoop =
false;
315 for (
auto & node : region.
Nodes())
320 for (
auto & subregion : structuralNode->Subregions())
323 if (
const auto thetaNode =
dynamic_cast<rvsdg::ThetaNode *
>(structuralNode))
341 rvsdg::RvsdgModule & rvsdgModule,
342 util::StatisticsCollector & statisticsCollector)
344 auto statistics = Statistics::Create(rvsdgModule.SourceFilePath().value());
346 statistics->start(rvsdgModule.Rvsdg());
347 HandleRegion(rvsdgModule.Rvsdg().GetRootRegion());
348 statistics->end(rvsdgModule.Rvsdg());
350 statisticsCollector.CollectDemandedStatistics(std::move(statistics));
359 loopUnswitching.
Run(rvsdgModule, statisticsCollector);
~Statistics() override=default
Statistics(const util::FilePath &sourceFile)
void end(const rvsdg::Graph &graph) noexcept
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void start(const rvsdg::Graph &graph) noexcept
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static rvsdg::GammaNode * IsUnswitchable(const rvsdg::ThetaNode &thetaNode)
static void HandleRegion(rvsdg::Region ®ion)
static void SinkNodesIntoGamma(rvsdg::GammaNode &gammaNode, const rvsdg::ThetaNode &thetaNode)
static void CreateAndRun(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector)
static void CopyPredicateNodes(rvsdg::Region &target, rvsdg::SubstitutionMap &substitutionMap, const std::vector< std::vector< rvsdg::Node * >> &nodes)
static std::vector< std::vector< rvsdg::Node * > > CollectPredicateNodes(const rvsdg::ThetaNode &thetaNode, const rvsdg::GammaNode &gammaNode)
~LoopUnswitching() noexcept override
static bool UnswitchLoop(rvsdg::ThetaNode &thetaNode)
static size_t sinkDependentNodesIntoGamma(rvsdg::GammaNode &gammaNode)
Conditional operator / pattern matching.
EntryVar AddEntryVar(rvsdg::Output *origin)
Routes a variable into the gamma branches.
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
ExitVar AddExitVar(std::vector< rvsdg::Output * > values)
Routes per-branch result of gamma to output.
rvsdg::Region * region() const noexcept
Represent acyclic RVSDG subgraphs.
rvsdg::StructuralNode * node() const noexcept
void prune(bool recursive)
NodeRange Nodes() noexcept
void insert(const Output *original, Output *substitute)
Output & lookup(const Output &original) const
RegionResult * predicate() const noexcept
LoopVar MapPreLoopVar(const rvsdg::Output &argument) const
Maps variable at start of loop iteration to full varibale description.
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
rvsdg::Region * subregion() const noexcept
static ThetaNode * create(rvsdg::Region *parent)
util::Timer & GetTimer(const std::string &name)
util::Timer & AddTimer(std::string name)
void AddMeasurement(std::string name, T value)
Global memory state passed between functions.
void pullin_top(rvsdg::GammaNode *gamma)
std::unordered_map< const Node *, size_t > computeDepthMap(const Region ®ion)
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
size_t ninputs(const rvsdg::Region *region) noexcept
static const char * NumRvsdgNodesBefore
static const char * NumRvsdgNodesAfter
static const char * Timer
static const char * NumRvsdgInputsAfter
static const char * NumRvsdgInputsBefore