48 static std::unique_ptr<Statistics>
51 return std::make_unique<Statistics>(sourceFile);
98 for (
auto phiLambdaNode : phiLambdaNodes)
111 simpleNode.GetOperation(),
130 JLM_ASSERT(isGammaNode || isThetaNode || isLambdaNode);
134 for (
auto & node : region.
Nodes())
165 simpleNode.GetOperation(),
168 if (configuration_.enableCallOutputRedirection)
169 redirectCallOutputs(simpleNode);
173 if (configuration_.enableLoadMemoryStateRedirection)
174 redirectLoadMemoryStates(simpleNode);
185 const auto isGammaNode = !!
dynamic_cast<rvsdg::GammaNode *
>(&structuralNode);
186 const auto isThetaNode = !!
dynamic_cast<rvsdg::ThetaNode *
>(&structuralNode);
189 for (
auto & subregion : structuralNode.
Subregions())
202 exitVar.output->divert_users(*invariantOrigin);
210 for (
auto [branchResult, gammaOutput] : gammaNode.
GetExitVars())
216 std::optional<IntegerValueRepresentation> intValueOpt;
217 std::optional<rvsdg::ControlValueRepresentation> ctlValueOpt;
218 for (
const auto result : branchResult)
224 simpleNode->GetOperation(),
227 if (!ctlValueOpt.has_value())
229 ctlValueOpt = ctlConstantOp.value();
233 if (ctlValueOpt != ctlConstantOp.
value())
244 if (!intValueOpt.has_value())
246 intValueOpt = intConstantOp.Representation();
250 if (intValueOpt != intConstantOp.Representation())
256 JLM_ASSERT(intValueOpt == intConstantOp.Representation());
274 ctlValueOpt = std::nullopt;
275 intValueOpt = std::nullopt;
282 ctlValueOpt = std::nullopt;
283 intValueOpt = std::nullopt;
290 if (ctlValueOpt.has_value())
292 auto & ctlConstantOutput =
294 gammaOutput->divert_users(&ctlConstantOutput);
299 if (intValueOpt.has_value())
301 auto & intConstantNode =
303 gammaOutput->divert_users(intConstantNode.output(0));
311 const auto owner = output.
GetOwner();
312 const auto ownerNode = std::get_if<rvsdg::Node *>(&owner);
327 for (
const auto & loopVar : thetaNode.
GetLoopVars())
336 loopVar.output->divert_users(loopVar.input->origin());
338 else if (
const auto constantNode =
getConstant(*loopVar.post->origin()))
340 auto copiedConstantNode = constantNode->copy(thetaNode.
region(), {});
341 loopVar.output->divert_users(copiedConstantNode->output(0));
350 if (!correlationOpt.has_value())
354 auto & correlation = correlationOpt.value();
357 if (!subregionRolesOpt.has_value())
362 auto roles = *subregionRolesOpt;
363 auto & gammaNode = correlation->gammaNode();
370 auto roleVar = gammaNode.MapBranchArgument(entryVarArgument);
371 if (
auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
387 auto & loopVarPostOperand = *loopVar.
post->
origin();
394 auto [branchResult, _] = gammaNode.MapOutputExitVar(loopVarPostOperand);
399 auto & entryVarArgument = *branchResult[roles.repetitionSubregion->index()]->origin();
400 divertLoopVar(loopVar, entryVarArgument);
405 auto & entryVarArgument = *branchResult[roles.exitSubregion->index()]->origin();
406 divertLoopVar(loopVar, entryVarArgument);
416 auto callTypeClassifier = CallOperation::ClassifyCall(callNode);
417 auto callType = callTypeClassifier->GetCallType();
422 if (callType != CallTypeClassifier::CallType::NonRecursiveDirectCall)
433 if (CallOperation::NumArguments(callNode) != lambdaNode.GetFunctionArguments().size())
437 const auto results = lambdaNode.GetFunctionResults();
439 for (
size_t n = 0; n < callNode.
noutputs(); n++)
441 const auto callOutput = callNode.
output(n);
443 auto & lambdaResult = *results[n];
444 auto origin = lambdaResult.origin();
447 if (
auto ctxvar = lambdaNode.MapBinderContextVar(*origin))
455 auto callOperand = CallOperation::Argument(callNode, origin->index())->origin();
464 const auto callExitSplit = CallOperation::tryGetMemoryStateExitSplit(callNode);
465 const auto callEntryMerge = CallOperation::tryGetMemoryStateEntryMerge(callNode);
470 if (callExitSplit ==
nullptr || callEntryMerge ==
nullptr || lambdaEntrySplit ==
nullptr
471 || lambdaExitMerge ==
nullptr)
474 const auto callExitSplitOp =
475 *util::assertedCast<const CallExitMemoryStateSplitOperation>(&callExitSplit->GetOperation());
476 for (
const auto memoryNodeId : callExitSplitOp.getMemoryNodeIds())
486 if (memoryNodeId == aa::PointsToGraph::externalMemoryNode)
490 auto result = LambdaExitMemoryStateMergeOperation::tryMapMemoryNodeIdToInput(
493 auto argument = LambdaEntryMemoryStateSplitOperation::tryMapMemoryNodeIdToOutput(
499 if (result ==
nullptr)
500 result = LambdaExitMemoryStateMergeOperation::tryMapMemoryNodeIdToInput(
502 aa::PointsToGraph::externalMemoryNode);
503 if (argument ==
nullptr)
504 argument = LambdaEntryMemoryStateSplitOperation::tryMapMemoryNodeIdToOutput(
506 aa::PointsToGraph::externalMemoryNode);
509 if (result !=
nullptr && argument !=
nullptr)
512 if (result->origin() != argument)
518 CallExitMemoryStateSplitOperation::tryMapMemoryNodeIdToOutput(*callExitSplit, memoryNodeId);
519 const auto input = CallEntryMemoryStateMergeOperation::tryMapMemoryNodeIdToInput(
527 output->divert_users(input->origin());
534 if (LoadOperation::LoadedValueOutput(loadNode).IsDead())
536 for (
auto & memoryStateOutput : LoadOperation::MemoryStateOutputs(loadNode))
538 auto & memoryStateInput = LoadOperation::MapMemoryStateOutputToInput(memoryStateOutput);
539 memoryStateOutput.divert_users(memoryStateInput.origin());
Get address of compiled function object.
static rvsdg::Node & Create(rvsdg::Region ®ion, IntegerValueRepresentation representation)
~Statistics() override=default
Statistics(const util::FilePath &sourceFile)
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
Invariant Value Redirection.
~InvariantValueRedirection() override
static void redirectGammaOutputConstants(rvsdg::GammaNode &gammaNode)
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.
void redirectInSubregions(rvsdg::StructuralNode &structuralNode)
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)
Interpret pointer as callable function.
UndefValueOperation class.
static Output & create(Region ®ion, ControlValueRepresentation value)
const ControlValueRepresentation & value() const noexcept
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
rvsdg::Region * region() const noexcept
size_t noutputs() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
std::variant< Node *, Region * > GetOwner() const noexcept
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.
void prune(bool recursive)
rvsdg::StructuralNode * node() const noexcept
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.
static rvsdg::Node * getConstant(const rvsdg::Output &output)
static util::StatisticsCollector statisticsCollector
rvsdg::SimpleNode * tryGetMemoryStateEntrySplit(const rvsdg::LambdaNode &lambdaNode) noexcept
rvsdg::Output & traceOutput(rvsdg::Output &output, bool mayEnterSubregions, const rvsdg::Region *withinRegion)
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 MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
static bool ThetaLoopVarIsInvariant(const ThetaNode::LoopVar &loopVar) noexcept
void MatchType(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
std::optional< rvsdg::Output * > GetGammaInvariantOrigin(const GammaNode &gamma, const GammaNode::ExitVar &exitvar)
Determines whether a gamma exit var is path-invariant.
detail::TopDownTraverserGeneric< false > TopDownTraverser
Traverser for visiting every node in a region in a top down order.
bool enableGammaOutputConstantRedirection
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).