45 static std::unique_ptr<Statistics>
48 return std::make_unique<Statistics>(sourceFile);
95 for (
auto phiLambdaNode : phiLambdaNodes)
108 simpleNode.GetOperation(),
127 JLM_ASSERT(isGammaNode || isThetaNode || isLambdaNode);
131 for (
auto & node : region.
Nodes())
159 simpleNode.GetOperation(),
162 if (configuration_.enableCallOutputRedirection)
163 redirectCallOutputs(simpleNode);
167 if (configuration_.enableLoadMemoryStateRedirection)
168 redirectLoadMemoryStates(simpleNode);
179 const auto isGammaNode = !!
dynamic_cast<rvsdg::GammaNode *
>(&structuralNode);
180 const auto isThetaNode = !!
dynamic_cast<rvsdg::ThetaNode *
>(&structuralNode);
183 for (
auto & subregion : structuralNode.
Subregions())
196 exitVar.output->divert_users(*invariantOrigin);
204 for (
const auto & loopVar : thetaNode.
GetLoopVars())
208 if (rvsdg::is<IOStateType>(loopVar.input->Type()))
212 loopVar.output->divert_users(loopVar.input->origin());
220 if (!correlationOpt.has_value())
224 auto & correlation = correlationOpt.value();
227 if (!subregionRolesOpt.has_value())
232 auto roles = *subregionRolesOpt;
233 auto & gammaNode = correlation->gammaNode();
238 if (rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(entryVarArgument))
240 auto roleVar = gammaNode.MapBranchArgument(entryVarArgument);
241 if (
auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
257 auto & loopVarPostOperand = *loopVar.
post->
origin();
258 if (rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(loopVarPostOperand) != &gammaNode)
264 auto [branchResult, _] = gammaNode.MapOutputExitVar(loopVarPostOperand);
269 auto & entryVarArgument = *branchResult[roles.repetitionSubregion->index()]->origin();
270 divertLoopVar(loopVar, entryVarArgument);
275 auto & entryVarArgument = *branchResult[roles.exitSubregion->index()]->origin();
276 divertLoopVar(loopVar, entryVarArgument);
287 auto callType = callTypeClassifier->GetCallType();
296 rvsdg::AssertGetOwnerNode<rvsdg::LambdaNode>(callTypeClassifier->GetLambdaOutput());
307 const auto results = lambdaNode.GetFunctionResults();
309 for (
size_t n = 0; n < callNode.
noutputs(); n++)
311 const auto callOutput = callNode.
output(n);
313 auto & lambdaResult = *results[n];
314 auto origin = lambdaResult.origin();
315 if (rvsdg::TryGetRegionParentNode<rvsdg::LambdaNode>(*origin) == &lambdaNode)
317 if (
auto ctxvar = lambdaNode.MapBinderContextVar(*origin))
340 if (callExitSplit ==
nullptr || callEntryMerge ==
nullptr || lambdaEntrySplit ==
nullptr
341 || lambdaExitMerge ==
nullptr)
344 const auto callExitSplitOp =
345 *util::assertedCast<const CallExitMemoryStateSplitOperation>(&callExitSplit->GetOperation());
346 for (
const auto memoryNodeId : callExitSplitOp.getMemoryNodeIds())
369 if (result ==
nullptr)
373 if (argument ==
nullptr)
379 if (result !=
nullptr && argument !=
nullptr)
382 if (result->origin() != argument)
397 output->divert_users(input->origin());
409 memoryStateOutput.divert_users(memoryStateInput.origin());
static jlm::util::StatisticsCollector statisticsCollector
static rvsdg::Input * tryMapMemoryNodeIdToInput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
static rvsdg::Output * tryMapMemoryNodeIdToOutput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
static rvsdg::Input * Argument(const rvsdg::Node &node, const size_t n)
static rvsdg::SimpleNode * tryGetMemoryStateExitSplit(const rvsdg::Node &callNode) noexcept
static std::unique_ptr< CallTypeClassifier > ClassifyCall(const rvsdg::SimpleNode &callNode)
Classifies a call node.
static size_t NumArguments(const rvsdg::Node &node) noexcept
static rvsdg::SimpleNode * tryGetMemoryStateEntryMerge(const rvsdg::Node &callNode) noexcept
Get address of compiled function object.
~Statistics() override=default
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
Statistics(const util::FilePath &sourceFile)
Invariant Value Redirection.
~InvariantValueRedirection() override
static void redirectGammaOutputs(rvsdg::GammaNode &gammaNode)
void redirectInRootRegion(rvsdg::Graph &rvsdg)
Configuration configuration_
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static void redirectLoadMemoryStates(rvsdg::SimpleNode &loadNode)
void redirectInSubregions(rvsdg::StructuralNode &structuralNode)
static void redirectCallOutputs(rvsdg::SimpleNode &callNode)
static void createAndRun(rvsdg::RvsdgModule &rvsdgModule, Configuration configuration)
static void redirectThetaOutputs(rvsdg::ThetaNode &thetaNode)
static void redirectThetaGammaOutputs(rvsdg::ThetaNode &thetaNode)
void redirectInRegion(rvsdg::Region ®ion)
static rvsdg::Output * tryMapMemoryNodeIdToOutput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
static rvsdg::Input * tryMapMemoryNodeIdToInput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
static rvsdg::Output & LoadedValueOutput(const rvsdg::Node &node)
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
Interpret pointer as callable function.
static constexpr NodeIndex externalMemoryNode
Conditional operator / pattern matching.
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
Region & GetRootRegion() const noexcept
rvsdg::Region * subregion() const noexcept
size_t noutputs() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
bool IsDead() const noexcept
A phi node represents the fixpoint of mutually recursive definitions.
static std::vector< rvsdg::LambdaNode * > ExtractLambdaNodes(const PhiNode &phiNode)
Represent acyclic RVSDG subgraphs.
rvsdg::StructuralNode * node() const noexcept
void prune(bool recursive)
NodeRange Nodes() noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
NodeOutput * output(size_t index) const noexcept
SubregionIteratorRange Subregions()
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
util::Timer & GetTimer(const std::string &name)
util::Timer & AddTimer(std::string name)
Global memory state passed between functions.
rvsdg::SimpleNode * tryGetMemoryStateEntrySplit(const rvsdg::LambdaNode &lambdaNode) noexcept
std::optional< std::unique_ptr< ThetaGammaPredicateCorrelation > > computeThetaGammaPredicateCorrelation(rvsdg::ThetaNode &thetaNode)
std::optional< GammaSubregionRoles > determineGammaSubregionRoles(const ThetaGammaPredicateCorrelation &correlation)
rvsdg::SimpleNode * tryGetMemoryStateExitMerge(const rvsdg::LambdaNode &lambdaNode) noexcept
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
static bool ThetaLoopVarIsInvariant(const ThetaNode::LoopVar &loopVar) noexcept
void MatchType(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
std::optional< rvsdg::Output * > GetGammaInvariantOrigin(const GammaNode &gamma, const GammaNode::ExitVar &exitvar)
Determines whether a gamma exit var is path-invariant.
bool enableGammaOutputRedirection
bool enableThetaGammaCorrelationRedirection
bool enableThetaOutputRedirection
Description of a loop-carried variable.
rvsdg::Output * pre
Variable before iteration (input argument to subregion).
rvsdg::Output * output
Variable at loop exit (output of theta).
rvsdg::Input * post
Variable after iteration (output result from subregion).
static const char * Timer