45 static const bool ENABLE_PTGAA = std::getenv(
"JLM_ENABLE_SVF_PTGAA");
78 const size_t numTotalLoads,
79 const size_t numLoadsForwarded,
80 const size_t numNoAliasAnalysisQueries,
81 const size_t numMayAliasAnalysisQueries,
82 const size_t numMustAliasAnalysisQueries) noexcept
116 static std::unique_ptr<Statistics>
119 return std::make_unique<Statistics>(sourceFile);
148 operator()(
const std::pair<rvsdg::Output *, rvsdg::Region *> & value)
const
150 return std::hash<rvsdg::Output *>()(value.first) ^ std::hash<rvsdg::Region *>()(value.second);
154 std::unordered_map<std::pair<rvsdg::Output *, rvsdg::Region *>,
rvsdg::Output *, OutputRegionHash>
174 for (
auto & node : region.
Nodes())
187 context_->outputTracer.clearCache();
202 for (
auto node : traverser)
208 for (
auto & subregion : gammaNode.
Subregions())
210 traverseIntraProceduralRegion(subregion);
219 if (is<LoadNonVolatileOperation>(&simpleNode))
269 return kind == other.kind &&
node == other.node;
275 return !(*
this == other);
360 if (!lastStoredValue.isKnown())
370 if (!lastStoredValue.isKnown())
399 const auto response =
433 if (
auto node = rvsdg::TryGetOwnerNode<rvsdg::Node>(input))
438 if (!inserted && it->second != result)
445 const auto region = regionResult->region();
449 if (!inserted && it->second != result)
462 if (
auto [storeNode, storeOp] =
463 rvsdg::TryGetSimpleNodeAndOptionalOp<StoreOperation>(tracedOutput);
464 storeNode && storeOp)
473 switch (aliasReponse)
518 if (
auto [joinNode, joinOp] =
519 rvsdg::TryGetSimpleNodeAndOptionalOp<MemoryStateJoinOperation>(tracedOutput);
522 if (joinNode->ninputs() == 0)
525 for (
auto & input : joinNode->Inputs())
528 if (!result.isKnown())
535 return sharedLastStore;
539 if (
auto [allocaNode, allocaOp] =
540 rvsdg::TryGetSimpleNodeAndOptionalOp<AllocaOperation>(tracedOutput);
541 allocaNode && allocaOp)
547 if (
auto gammaNode = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(tracedOutput))
549 const auto exitVar = gammaNode->MapOutputExitVar(tracedOutput);
553 std::optional<StoreValueOrigin> commonStoreValueOrigin;
555 for (
auto branchResult : exitVar.branchResult)
561 if (!lastStoreNode.isKnown())
565 if (!commonStoreValueOrigin.has_value())
566 commonStoreValueOrigin = lastStoreNode;
567 else if (commonStoreValueOrigin.value() != lastStoreNode)
571 JLM_ASSERT(commonStoreValueOrigin.has_value());
572 if (commonStoreValueOrigin->isKnown())
573 return *commonStoreValueOrigin;
580 if (
auto thetaNode = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(tracedOutput))
582 const auto loopVar = thetaNode->MapOutputLoopVar(tracedOutput);
585 if (!lastStoreNode.isKnown())
591 && lastStoreNode.node == thetaNode)
597 if (lastStoreNode.node->region() == thetaNode->subregion())
601 return lastStoreNode;
605 if (
auto thetaNode = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(tracedOutput))
607 const auto loopVar = thetaNode->MapPreLoopVar(tracedOutput);
611 if (!inputLastStoreNode.isKnown())
641 throw std::logic_error(
"Unhandled alias analysis query response!");
689 JLM_ASSERT(is<LoadNonVolatileOperation>(&loadNode));
691 context_->statistics.startTracing();
702 context_->statistics.startForwarding();
704 context_->statistics.stopForwarding();
714 auto & loadNode = tracingInfo.
loadNode;
716 auto & loadRegion = *loadNode.region();
727 loadedValueOutput.divert_users(&storedValueOutput);
732 auto & memoryStateInput =
734 memoryStateOutput.divert_users(memoryStateInput.origin());
767 auto [it, inserted] = tracingInfo.
createdExitVars.emplace(gammaNode,
nullptr);
770 std::vector<rvsdg::Output *> lastStorePerSubregion;
771 for (
auto & subregion : gammaNode->Subregions())
775 lastStorePerSubregion.push_back(&storedValueOutput);
778 auto exitVar = gammaNode->AddExitVar(lastStorePerSubregion);
779 it->second = exitVar.output;
796 auto lastStoreInRegion = tracingInfo.
lastStoreInRegion.find(thetaNode->subregion());
798 JLM_ASSERT(lastStoreInRegion->second.isKnown());
818 JLM_ASSERT(lastStoreBeforeTheta->second.isKnown());
819 auto & outerRegion = *thetaNode->region();
831 auto loopVar = thetaNode->AddLoopVar(initialValue);
832 auto [it, inserted] = tracingInfo.
createdLoopVars.emplace(thetaNode, loopVar);
842 switch (storeValueOrigin.
kind)
869 post->divert_to(&origin);
876 if (output.
region() == ®ion)
880 JLM_UNREACHABLE(
"root region reached during attempt at routing output into region");
888 if (
auto it =
context_->routedOutputs.find({ &outerOutput, ®ion });
889 it !=
context_->routedOutputs.end())
893 auto entryVar = gammaNode->AddEntryVar(&outerOutput);
894 for (
auto branchArgument : entryVar.branchArgument)
896 context_->routedOutputs[{ &outerOutput, branchArgument->region() }] = branchArgument;
899 return *entryVar.branchArgument[region.
index()];
908 if (
auto it =
context_->routedOutputs.find({ &outerOutput, ®ion });
909 it !=
context_->routedOutputs.end())
913 auto loopVar = thetaNode->AddLoopVar(&outerOutput);
914 context_->routedOutputs[{ &outerOutput, ®ion }] = loopVar.pre;
918 JLM_UNREACHABLE(
"routeOutputToRegion reached unhandled structural node");
921 static std::unique_ptr<aa::AliasAnalysis>
924 auto localAA = std::make_unique<aa::LocalAliasAnalysis>();
929 localAA->setMaxTraceCollectionSize(1);
937 auto ptgAA = std::make_unique<aa::PointsToGraphAliasAnalysis>(std::move(ptg));
939 return std::make_unique<aa::ChainedAliasAnalysis>(std::move(localAA), std::move(ptgAA));
950 context_ = std::make_unique<Context>(*aliasAnalysis, *statistics);
952 statistics->StartStatistics();
954 auto & rvsdg = module.
Rvsdg();
957 statistics->StopStatistics(
960 context_->numNoAliasAnalysisQueries,
961 context_->numMayAliasAnalysisQueries,
962 context_->numMustAliasAnalysisQueries);
static jlm::util::StatisticsCollector statisticsCollector
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & LoadedValueOutput(const rvsdg::Node &node)
static size_t numMemoryStates(const rvsdg::SimpleNode &node) noexcept
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
static rvsdg::Node::InputIteratorRange MemoryStateInputs(const rvsdg::Node &node) noexcept
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
std::unordered_map< rvsdg::Input *, StoreValueOrigin > lastStoreBeforeInput
StoreValueOrigin getLastStoreBeforeInputInternal(rvsdg::Input &input)
void updateAliasAnalysisQueryCounters(aa::AliasAnalysis::AliasQueryResponse response)
aa::AliasAnalysis::AliasQueryResponse queryAliasAnalysis(rvsdg::SimpleNode &storeNode)
std::unordered_map< rvsdg::GammaNode *, rvsdg::Output * > createdExitVars
LoadTracingInfo(rvsdg::SimpleNode &loadNode, OutputTracer &tracer, aa::AliasAnalysis &aliasAnalysis)
rvsdg::SimpleNode & loadNode
std::unordered_map< rvsdg::SimpleNode *, StoreNodeInfo > storeNodeInfo
size_t numNoAliasAnalysisQueries
StoreValueOrigin getLastStoreBeforeInput(rvsdg::Input &input)
bool traceAllMemoryStateInputs()
std::unordered_map< rvsdg::ThetaNode *, rvsdg::ThetaNode::LoopVar > createdLoopVars
std::queue< rvsdg::Input * > unroutedLoopVarPosts
aa::AliasAnalysis & aliasAnalysis
std::unordered_map< rvsdg::Region *, StoreValueOrigin > lastStoreInRegion
size_t numMustAliasAnalysisQueries
std::shared_ptr< const rvsdg::Type > loadedType
size_t numMayAliasAnalysisQueries
rvsdg::Output * loadedAddress
std::unordered_map< rvsdg::Node *, StoreValueOrigin > lastStoreBeforeNode
util::HashSet< rvsdg::Input * > loopVarPostsToTrace
void setTraceThroughLoadedStates(bool traceThroughLoadedStates)
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
Store Value Forwarding Statistics class.
void stopTracing() noexcept
~Statistics() override=default
static constexpr auto ForwardingLabel_
static constexpr auto NumLoadsForwarded_
static constexpr auto numNoAliasAnalysisQueriesLabel_
void StartStatistics() noexcept
Statistics(const util::FilePath &sourceFile)
void startForwarding() noexcept
static constexpr auto numMayAliasAnalysisQueriesLabel_
void StopStatistics(const size_t numTotalLoads, const size_t numLoadsForwarded, const size_t numNoAliasAnalysisQueries, const size_t numMayAliasAnalysisQueries, const size_t numMustAliasAnalysisQueries) noexcept
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
static constexpr auto NumTotalLoads_
void stopForwarding() noexcept
static constexpr auto TracingLabel_
static constexpr auto numMustAliasAnalysisQueriesLabel_
void startTracing() noexcept
Store Value Forwarding Optimization.
~StoreValueForwarding() noexcept override
std::unique_ptr< Context > context_
void connectUnroutedLoopPosts(LoadTracingInfo &tracingInfo)
void processLoadNode(rvsdg::SimpleNode &loadNode)
rvsdg::Output & routeOutputToRegion(rvsdg::Output &output, rvsdg::Region ®ion)
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
rvsdg::Output & getStoredValueOrigin(StoreValueOrigin storeValueOrigin, rvsdg::Region &targetRegion, LoadTracingInfo &tracingInfo)
void traverseInterProceduralRegion(rvsdg::Region ®ion)
void traverseIntraProceduralRegion(rvsdg::Region ®ion)
void forwardStoredValues(LoadTracingInfo &tracingInfo)
static jlm::rvsdg::Output * Create(rvsdg::Region ®ion, std::shared_ptr< const jlm::rvsdg::Type > type)
virtual AliasQueryResponse Query(const rvsdg::Output &p1, size_t s1, const rvsdg::Output &p2, size_t s2)=0
std::unique_ptr< PointsToGraph > Analyze(const rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Conditional operator / pattern matching.
void setTraceThroughStructuralNodes(bool value) noexcept
Output & trace(Output &output)
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
A phi node represents the fixpoint of mutually recursive definitions.
rvsdg::Region * subregion() const noexcept
Represents the result of a region.
Represent acyclic RVSDG subgraphs.
rvsdg::StructuralNode * node() const noexcept
void prune(bool recursive)
size_t index() const noexcept
bool IsRootRegion() const noexcept
NodeRange Nodes() noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
SubregionIteratorRange Subregions()
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)
#define JLM_UNREACHABLE(msg)
Global memory state passed between functions.
static std::unique_ptr< aa::AliasAnalysis > createAliasAnalysis(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector)
rvsdg::Output & traceOutput(rvsdg::Output &output, const rvsdg::Region *withinRegion)
size_t GetTypeStoreSize(const rvsdg::Type &type)
static const bool ENABLE_PTGAA
static const bool ENABLE_AGGRESSIVE_LOCALAA
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
std::size_t operator()(const std::pair< rvsdg::Output *, rvsdg::Region * > &value) const
aa::AliasAnalysis & aliasAnalysis
size_t numMustAliasAnalysisQueries
size_t numMayAliasAnalysisQueries
Context(aa::AliasAnalysis &aliasAnalysis, Statistics &statistics) noexcept
size_t numNoAliasAnalysisQueries
std::unordered_map< std::pair< rvsdg::Output *, rvsdg::Region * >, rvsdg::Output *, OutputRegionHash > routedOutputs
OutputTracer outputTracer
static StoreValueOrigin createUninitialized()
static StoreValueOrigin createStoreNode(rvsdg::SimpleNode &storeNode)
bool operator!=(const StoreValueOrigin &other) const noexcept
static StoreValueOrigin createGammaNodeOutput(rvsdg::GammaNode &gammaNode)
static StoreValueOrigin createThetaNodePre(rvsdg::ThetaNode &thetaNode)
static StoreValueOrigin createThetaNodeOutput(rvsdg::ThetaNode &thetaNode)
bool operator==(const StoreValueOrigin &other) const noexcept
static StoreValueOrigin createUnknown()
static const char * Timer