23 LoopUnswitchingDefaultHeuristic::~LoopUnswitchingDefaultHeuristic() noexcept = default;
29 const auto & thetaNode = correlation.thetaNode();
30 const auto & gammaNode = correlation.gammaNode();
34 if (node == &gammaNode)
37 if (rvsdg::is<rvsdg::StructuralOperation>(node))
44 std::shared_ptr<const LoopUnswitchingDefaultHeuristic>
48 return std::shared_ptr<const LoopUnswitchingDefaultHeuristic>(std::shared_ptr<void>(), &instance);
76 static std::unique_ptr<Statistics>
79 return std::make_unique<Statistics>(sourceFile);
86 auto [matchNode, matchOperation] =
87 rvsdg::TryGetSimpleNodeAndOptionalOp<rvsdg::MatchOperation>(*theta.
predicate()->
origin());
92 if (matchNode->output(0)->nusers() != 2)
96 for (
const auto & user : matchNode->output(0)->Users())
101 gammaNode = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(user);
110 const auto origin = loopVar.post->origin();
111 if (rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*origin))
115 else if (rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(*origin) == gammaNode)
135 for (
const auto & loopVar : thetaNode.
GetLoopVars())
137 if (rvsdg::TryGetOwnerNode<rvsdg::Node>(*loopVar.post->origin()) != &gammaNode)
139 auto [input, branchArgument] = gammaNode.
AddEntryVar(loopVar.post->origin());
141 auto [_, output] = gammaNode.
AddExitVar({ branchArgument[0], branchArgument[1] });
142 loopVar.post->divert_to(output);
149 std::vector<std::vector<rvsdg::Node *>>
158 std::vector<std::vector<rvsdg::Node *>> nodes;
161 if (&node == &gammaNode)
164 const auto depth = depthMap[&node];
165 if (depth >= nodes.size())
166 nodes.resize(depth + 1);
167 nodes[depth].push_back(&node);
177 const std::vector<std::vector<rvsdg::Node *>> & nodes)
179 for (
auto & sameDepthNodes : nodes)
181 for (
const auto & node : sameDepthNodes)
182 node->copy(&target, substitutionMap);
191 for (
const auto & loopVar : thetaNode.
GetLoopVars())
193 const auto node = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(*loopVar.post->origin());
194 if (node != &gammaNode)
220 auto & correlation = correlationOpt.value();
222 if (!
heuristic_->shouldUnswitchLoop(*correlation))
244 for (
const auto & oldLoopVar : oldThetaNode.
GetLoopVars())
245 stage1SMap.
insert(oldLoopVar.pre, oldLoopVar.input->origin());
253 &stage1SMap.
lookup(*oldGammaNode->predicate()->origin()),
254 oldGammaNode->nsubregions());
256 const auto [oldRepetitionSubregion, oldExitSubregion] =
258 const auto & newRepetitionSubregion = newGammaNode->subregion(oldRepetitionSubregion->index());
259 const auto repetitionSubregionIndex = oldRepetitionSubregion->index();
260 const auto exitSubregionIndex = oldExitSubregion->index();
264 std::unordered_map<rvsdg::Input *, rvsdg::Input *> oldGammaNewGammaInputMap;
265 std::unordered_map<rvsdg::Input *, rvsdg::Input *> oldGammaNewThetaInputMap;
266 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
268 auto & newOrigin = stage1SMap.
lookup(*oldInput->origin());
269 auto newEntryVar = newGammaNode->AddEntryVar(&newOrigin);
271 newThetaNode->AddLoopVar(newEntryVar.branchArgument[repetitionSubregionIndex]);
272 oldGammaNewGammaInputMap[oldInput] = newEntryVar.input;
273 oldGammaNewThetaInputMap[oldInput] = newLoopVar.input;
279 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
281 auto newLoopInput = oldGammaNewThetaInputMap[oldInput];
282 auto newLoopVar = newThetaNode->MapInputLoopVar(*newLoopInput);
283 stage3SMap.
insert(oldBranchArgument[repetitionSubregionIndex], newLoopVar.pre);
286 oldRepetitionSubregion->copy(newThetaNode->subregion(), stage3SMap);
294 auto oldExitVar = oldGammaNode->MapOutputExitVar(*oldLoopVar.post->origin());
295 auto oldOrigin = oldExitVar.branchResult[repetitionSubregionIndex]->origin();
296 auto & newOrigin = stage3SMap.
lookup(*oldOrigin);
297 stage4SMap.
insert(oldLoopVar.pre, &newOrigin);
306 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
308 auto newLoopVarInput = oldGammaNewThetaInputMap[oldInput];
309 auto newLoopVar = newThetaNode->MapInputLoopVar(*newLoopVarInput);
310 auto & newOrigin = stage4SMap.
lookup(*oldInput->origin());
311 newLoopVar.post->divert_to(&newOrigin);
315 std::unordered_map<rvsdg::Input *, rvsdg::Output *> oldGammaNewGammaOutputMap;
317 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
319 auto newGammaInput = oldGammaNewGammaInputMap[oldInput];
321 std::get<rvsdg::GammaNode::EntryVar>(newGammaNode->MapInput(*newGammaInput));
322 auto newLoopVarInput = oldGammaNewThetaInputMap[oldInput];
323 auto newLoopVar = newThetaNode->MapInputLoopVar(*newLoopVarInput);
325 std::vector<rvsdg::Output *> values(2);
326 values[exitSubregionIndex] = newEntryVar.branchArgument[exitSubregionIndex];
327 values[repetitionSubregionIndex] = newLoopVar.output;
328 auto newExitVar = newGammaNode->AddExitVar(values);
329 oldGammaNewGammaOutputMap[oldInput] = newExitVar.output;
336 for (
const auto & [oldInput, oldBranchArgument] : oldGammaNode->GetEntryVars())
338 auto newOrigin = oldGammaNewGammaOutputMap[oldInput];
339 stage7SMap.
insert(oldBranchArgument[exitSubregionIndex], newOrigin);
342 oldExitSubregion->copy(oldThetaNode.
region(), stage7SMap);
348 auto oldExitVar = oldGammaNode->MapOutputExitVar(*oldLoopVar.post->origin());
349 auto oldOrigin = oldExitVar.branchResult[exitSubregionIndex]->origin();
350 auto & newOrigin = stage7SMap.
lookup(*oldOrigin);
360 bool unswitchedLoop =
false;
361 for (
auto & node : region.
Nodes())
366 for (
auto & subregion : structuralNode->Subregions())
369 if (
const auto thetaNode =
dynamic_cast<rvsdg::ThetaNode *
>(structuralNode))
387 rvsdg::RvsdgModule & rvsdgModule,
390 auto statistics = Statistics::Create(rvsdgModule.SourceFilePath().value());
392 statistics->start(rvsdgModule.Rvsdg());
393 HandleRegion(rvsdgModule.Rvsdg().GetRootRegion());
394 statistics->end(rvsdgModule.Rvsdg());
403 std::shared_ptr<const LoopUnswitchingHeuristic> heuristic)
static jlm::util::StatisticsCollector statisticsCollector
static std::shared_ptr< const LoopUnswitchingDefaultHeuristic > create()
virtual ~LoopUnswitchingHeuristic() noexcept
~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 bool allLoopVarsAreRoutedThroughGamma(const rvsdg::ThetaNode &thetaNode, const rvsdg::GammaNode &gammaNode)
void HandleRegion(rvsdg::Region ®ion)
static void SinkNodesIntoGamma(rvsdg::GammaNode &gammaNode, const rvsdg::ThetaNode &thetaNode)
static void CreateAndRun(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector, std::shared_ptr< const LoopUnswitchingHeuristic > heuristic)
std::shared_ptr< const LoopUnswitchingHeuristic > heuristic_
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
bool UnswitchLoop(rvsdg::ThetaNode &thetaNode)
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(const std::vector< rvsdg::Output * > &values)
Routes per-branch result of gamma to output.
rvsdg::Region * region() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
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
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
rvsdg::Region * subregion() const noexcept
static ThetaNode * create(rvsdg::Region *parent)
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
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::optional< std::unique_ptr< ThetaGammaPredicateCorrelation > > computeThetaGammaPredicateCorrelation(rvsdg::ThetaNode &thetaNode)
std::optional< GammaSubregionRoles > determineGammaSubregionRoles(const ThetaGammaPredicateCorrelation &correlation)
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