Jlm
Loading...
Searching...
No Matches
MemoryStateEncoder.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Nico Reißmann <nico.reissmann@gmail.com>
3 * Copyright 2025 Håvard Krogstie <krogstie.havard@gmail.com>
4 * See COPYING for terms of redistribution.
5 */
6
19#include <jlm/rvsdg/gamma.hpp>
21#include <jlm/rvsdg/theta.hpp>
23#include <jlm/util/common.hpp>
25
26#include <unordered_map>
27
28namespace jlm::llvm::aa
29{
30
35{
36 // The number of entities that have been counted
37 uint64_t NumEntities = 0;
38
39 // Count of total memory states, separated by Ref/Mod/ModRef
40 uint64_t NumRefOnly = 0;
41 uint64_t NumModOnly = 0;
42 uint64_t NumModRef = 0;
43
44 // Count of total memory states, separated by MemoryNode type
45 uint64_t NumAllocas = 0;
46 uint64_t NumMallocs = 0;
47 uint64_t NumDeltas = 0;
48 uint64_t NumImports = 0;
49 uint64_t NumLambdas = 0;
50 uint64_t NumExternalNode = 0;
51
52 // Count of the total memory states, how many are not externally available
53 uint64_t NumNonEscaped = 0;
54
55 // Remember the single entity with the highest number of memory states
57 // Do the same, but only include non-escaped MemoryNodes
59
60 void
62 uint64_t numRefOnly,
63 uint64_t numModOnly,
64 uint64_t numModRef,
65 uint64_t numAllocas,
66 uint64_t numMallocs,
67 uint64_t numDeltas,
68 uint64_t numImports,
69 uint64_t numLambdas,
70 uint64_t numExternalNode,
71 uint64_t numNonEscaped)
72 {
74
75 NumRefOnly += numRefOnly;
76 NumModOnly += numModOnly;
77 NumModRef += numModRef;
78
79 NumAllocas += numAllocas;
80 NumMallocs += numMallocs;
81 NumDeltas += numDeltas;
82 NumImports += numImports;
83 NumLambdas += numLambdas;
84 NumExternalNode += numExternalNode;
85
86 const uint64_t totalMemoryStates = numRefOnly + numModOnly + numModRef;
87 if (totalMemoryStates > MaxMemoryStateEntity)
88 MaxMemoryStateEntity = totalMemoryStates;
89
90 NumNonEscaped += numNonEscaped;
91 if (numNonEscaped > MaxNonEscapedMemoryStateEntity)
92 MaxNonEscapedMemoryStateEntity = numNonEscaped;
93 }
94
95 void
96 CountEntity(const PointsToGraph & pointsToGraph, const ModRefSet & memoryNodes)
97 {
98 uint64_t numRefOnly = 0;
99 uint64_t numModOnly = 0;
100 uint64_t numModRef = 0;
101
102 uint64_t numAllocas = 0;
103 uint64_t numMallocs = 0;
104 uint64_t numDeltas = 0;
105 uint64_t numImports = 0;
106 uint64_t numLambdas = 0;
107 uint64_t numExternalNode = 0;
108
109 uint64_t numNonEscaped = 0;
110
111 for (const auto [memoryNode, modRefEffect] : memoryNodes.getModRefNodes())
112 {
113 switch (modRefEffect)
114 {
116 numRefOnly++;
117 break;
119 numModOnly++;
120 break;
122 numModRef++;
123 break;
124 default:
125 JLM_UNREACHABLE("Unknown ModRefEffect");
126 }
127
128 if (!pointsToGraph.isExternallyAvailable(memoryNode))
129 numNonEscaped++;
130
131 const auto kind = pointsToGraph.getNodeKind(memoryNode);
132 switch (kind)
133 {
135 numAllocas++;
136 break;
138 numDeltas++;
139 break;
141 numLambdas++;
142 break;
144 numImports++;
145 break;
147 numMallocs++;
148 break;
150 numExternalNode++;
151 break;
152 default:
153 throw std::logic_error("Unknown MemoryNode kind");
154 }
155 }
156
158 numRefOnly,
159 numModOnly,
160 numModRef,
161 numAllocas,
162 numMallocs,
163 numDeltas,
164 numImports,
165 numLambdas,
166 numExternalNode,
167 numNonEscaped);
168 }
169};
170
175{
176 // Prefixes for statistics that count ModRef vs RefOnly
177 static constexpr auto NumTotalRefOnlyStates_ = "#TotalRefOnlyState";
178 static constexpr auto NumTotalModOnlyStates_ = "#TotalModOnlyState";
179 static constexpr auto NumTotalModRefStates_ = "#TotalModRefState";
180 // These are prefixes for statistics that count MemoryNode types
181 static constexpr auto NumTotalAllocaState_ = "#TotalAllocaState";
182 static constexpr auto NumTotalMallocState_ = "#TotalMallocState";
183 static constexpr auto NumTotalDeltaState_ = "#TotalDeltaState";
184 static constexpr auto NumTotalImportState_ = "#TotalImportState";
185 static constexpr auto NumTotalLambdaState_ = "#TotalLambdaState";
186 static constexpr auto NumTotalExternalNodeState_ = "#TotalExternalNodeState";
187 // Among all the MemoryNodes counted above, how many of them are not externally available
188 static constexpr auto NumTotalNonEscapedState_ = "#TotalNonEscapedState";
189 // Maximums in a single counted entity
190 static constexpr auto NumMaxMemoryState_ = "#MaxMemoryState";
191 static constexpr auto NumMaxNonEscapedMemoryState_ = "#MaxNonEscapedMemoryState";
192
193 // The number of regions that are inside lambda nodes (including the lambda subregion itself)
194 static constexpr auto NumIntraProceduralRegions_ = "#IntraProceduralRegions";
195 // Suffix used when counting region state arguments (or LambdaEntrySplit for lambda subregions)
196 static constexpr auto RegionArgumentStateSuffix_ = "Arguments";
197
198 // Counting both volatile and non-volatile loads
199 static constexpr auto NumLoadOperations_ = "#LoadOperations";
200 // Suffix used when counting memory states routed through loads
201 static constexpr auto LoadStateSuffix_ = "sThroughLoad";
202
203 // Counting both volatile and non-volatile stores
204 static constexpr auto NumStoreOperations_ = "#StoreOperations";
205 // Suffix used when counting memory states routed through stores
206 static constexpr auto StoreStateSuffix_ = "sThroughStore";
207
208 // Counting call entry merges
209 static constexpr auto NumCallEntryMergeOperations_ = "#CallEntryMergeOperations";
210 // Suffix used when counting memory states routed into call entry merges
211 static constexpr auto CallEntryMergeStateSuffix_ = "sIntoCallEntryMerge";
212
213public:
214 ~EncodingStatistics() override = default;
215
216 explicit EncodingStatistics(const util::FilePath & sourceFile)
218 {}
219
220 void
221 Start(const rvsdg::Graph & graph)
222 {
223 AddMeasurement(Label::NumRvsdgNodesBefore, rvsdg::nnodes(&graph.GetRootRegion()));
224 AddTimer(Label::Timer).start();
225 }
226
227 void
229 {
230 GetTimer(Label::Timer).stop();
231 }
232
233 void
239
240 void
246
247 void
253
254 void
260
261 static std::unique_ptr<EncodingStatistics>
262 Create(const util::FilePath & sourceFile)
263 {
264 return std::make_unique<EncodingStatistics>(sourceFile);
265 }
266
267private:
268 void
286};
287
290class StateMap final
291{
292public:
297 {
298 friend StateMap;
299
301 : MemoryNode_(memoryNode),
302 State_(&state)
303 {
304 JLM_ASSERT(is<MemoryStateType>(state.Type()));
305 }
306
307 public:
308 [[nodiscard]] PointsToGraph::NodeIndex
309 MemoryNode() const noexcept
310 {
311 return MemoryNode_;
312 }
313
314 [[nodiscard]] rvsdg::Output &
315 State() const noexcept
316 {
317 return *State_;
318 }
319
320 void
321 ReplaceState(rvsdg::Output & state) noexcept
322 {
323 JLM_ASSERT(State_->region() == state.region());
324 JLM_ASSERT(is<MemoryStateType>(state.Type()));
325
326 State_ = &state;
327 }
328
329 static void
331 const std::vector<MemoryNodeStatePair *> & memoryNodeStatePairs,
332 const std::vector<rvsdg::Output *> & states)
333 {
334 JLM_ASSERT(memoryNodeStatePairs.size() == states.size());
335 for (size_t n = 0; n < memoryNodeStatePairs.size(); n++)
336 memoryNodeStatePairs[n]->ReplaceState(*states[n]);
337 }
338
339 static void
341 const std::vector<MemoryNodeStatePair *> & memoryNodeStatePairs,
343 {
344 auto it = states.begin();
345 for (auto memoryNodeStatePair : memoryNodeStatePairs)
346 {
347 memoryNodeStatePair->ReplaceState(*it);
348 it++;
349 }
350 JLM_ASSERT(it.GetOutput() == nullptr);
351 }
352
353 static std::vector<rvsdg::Output *>
354 States(const std::vector<MemoryNodeStatePair *> & memoryNodeStatePairs)
355 {
356 std::vector<rvsdg::Output *> states;
357 for (auto & memoryNodeStatePair : memoryNodeStatePairs)
358 states.push_back(memoryNodeStatePair->State_);
359
360 return states;
361 }
362
363 private:
366 };
367
368 StateMap() = default;
369
370 StateMap(const StateMap &) = delete;
371
372 StateMap(StateMap &&) = delete;
373
374 StateMap &
375 operator=(const StateMap &) = delete;
376
377 StateMap &
378 operator=(StateMap &&) = delete;
379
382 {
383 if (const auto it = states_.find(memoryNode); it != states_.end())
384 return &it->second;
385
386 return nullptr;
387 }
388
389 const MemoryNodeStatePair *
390 TryGetState(PointsToGraph::NodeIndex memoryNode) const noexcept
391 {
392 return const_cast<StateMap *>(this)->TryGetState(memoryNode);
393 }
394
395 bool
396 HasState(PointsToGraph::NodeIndex memoryNode) const noexcept
397 {
398 return TryGetState(memoryNode) != nullptr;
399 }
400
401 MemoryNodeStatePair *
403 {
404 if (const auto statePair = TryGetState(memoryNode))
405 return statePair;
406 throw std::logic_error("Memory node does not have a state.");
407 }
408
409 std::vector<MemoryNodeStatePair *>
410 GetStates(const ModRefSet & modRefSet)
411 {
412 std::vector<MemoryNodeStatePair *> memoryNodeStatePairs;
413 for (const auto [memoryNode, modRefEffect] : modRefSet.getModRefNodes())
414 {
415 JLM_ASSERT(modRefEffect != ModRefEffect::NoEffect);
416 memoryNodeStatePairs.push_back(GetState(memoryNode));
417 }
418
419 return memoryNodeStatePairs;
420 }
421
429 std::vector<MemoryNodeStatePair *>
430 GetExistingStates(const ModRefSet & modRefSet)
431 {
432 std::vector<MemoryNodeStatePair *> memoryNodeStatePairs;
433 for (auto & [memoryNode, _] : modRefSet.getModRefNodes())
434 {
435 if (const auto statePair = TryGetState(memoryNode))
436 memoryNodeStatePairs.push_back(statePair);
437 }
438
439 return memoryNodeStatePairs;
440 }
441
449 MemoryNodeStatePair *
451 {
452 auto [it, added] = states_.insert({ memoryNode, { memoryNode, state } });
453 if (!added)
454 throw std::logic_error("Memory node already has a state.");
455 return &it->second;
456 }
457
458 static std::unique_ptr<StateMap>
460 {
461 return std::make_unique<StateMap>();
462 }
463
464private:
465 // std::unordered_map guarantees pointers to keys and values remain valid even when
466 // new pairs are added to the container.
467 std::unordered_map<PointsToGraph::NodeIndex, MemoryNodeStatePair> states_;
468};
469
473{
474public:
476 {
477 // Ensure that a PopRegion() was invoked for each invocation of a PushRegion().
478 JLM_ASSERT(StateMaps_.empty());
479 }
480
481 explicit RegionalizedStateMap(const ModRefSummary & modRefSummary)
482 : ModRefSummary_(modRefSummary)
483 {}
484
486
488
491
494
497 {
498 return GetStateMap(*state.region()).InsertState(memoryNode, state);
499 }
500
502 TryGetState(const rvsdg::Region & region, PointsToGraph::NodeIndex memoryNode) const
503 {
504 return GetStateMap(region).TryGetState(memoryNode);
505 }
506
507 bool
508 HasState(const rvsdg::Region & region, PointsToGraph::NodeIndex memoryNode) const
509 {
510 return GetStateMap(region).HasState(memoryNode);
511 }
512
515 {
516 return GetStateMap(region).GetState(memoryNode);
517 }
518
519 std::vector<StateMap::MemoryNodeStatePair *>
520 GetStates(const rvsdg::Region & region, const ModRefSet & modRefSet)
521 {
522 return GetStateMap(region).GetStates(modRefSet);
523 }
524
535 std::vector<StateMap::MemoryNodeStatePair *>
536 GetExistingStates(const rvsdg::Region & region, const ModRefSet & modRefSet) const
537 {
538 return GetStateMap(region).GetExistingStates(modRefSet);
539 }
540
541 std::vector<StateMap::MemoryNodeStatePair *>
543 {
544 return GetExistingStates(*node.region(), GetSimpleNodeModRef(node));
545 }
546
547 const ModRefSet &
549 {
551 }
552
553 void
554 PushRegion(const rvsdg::Region & region)
555 {
556 JLM_ASSERT(StateMaps_.find(&region) == StateMaps_.end());
557 StateMaps_[&region] = StateMap::Create();
558 }
559
560 void
561 PopRegion(const rvsdg::Region & region)
562 {
563 JLM_ASSERT(StateMaps_.find(&region) != StateMaps_.end());
564 StateMaps_.erase(&region);
565 }
566
567private:
568 StateMap &
569 GetStateMap(const rvsdg::Region & region) const noexcept
570 {
571 JLM_ASSERT(StateMaps_.find(&region) != StateMaps_.end());
572 return *StateMaps_.at(&region);
573 }
574
576
577 std::unordered_map<const rvsdg::Region *, std::unique_ptr<StateMap>> StateMaps_;
578};
579
583{
584public:
585 explicit Context(const ModRefSummary & modRefSummary)
586 : RegionalizedStateMap_(modRefSummary),
587 ModRefSummary_(modRefSummary)
588 {}
589
590 Context(const Context &) = delete;
591
592 Context(Context &&) = delete;
593
594 Context &
595 operator=(const Context &) = delete;
596
597 Context &
598 operator=(Context &&) = delete;
599
602 {
604 }
605
606 const ModRefSummary &
607 GetModRefSummary() const noexcept
608 {
609 return ModRefSummary_;
610 }
611
617
620 {
621 return LoadCounter_;
622 }
623
626 {
627 return StoreCounter_;
628 }
629
635
636 static std::unique_ptr<MemoryStateEncoder::Context>
637 Create(const ModRefSummary & modRefSummary)
638 {
639 return std::make_unique<Context>(modRefSummary);
640 }
641
642private:
645
646 // Counters used for producing statistics about memory states
651};
652
653static std::vector<MemoryNodeId>
654GetMemoryNodeIds(const ModRefSet & modRefSet)
655{
656 std::vector<MemoryNodeId> memoryNodeIds;
657 for (const auto [memoryNode, _] : modRefSet.getModRefNodes())
658 {
659 memoryNodeIds.push_back(memoryNode);
660 }
661
662 return memoryNodeIds;
663}
664
665MemoryStateEncoder::~MemoryStateEncoder() noexcept = default;
666
667MemoryStateEncoder::MemoryStateEncoder() = default;
668
669void
671 rvsdg::RvsdgModule & rvsdgModule,
672 const ModRefSummary & modRefSummary,
673 util::StatisticsCollector & statisticsCollector)
674{
675 Context_ = Context::Create(modRefSummary);
676 auto statistics = EncodingStatistics::Create(rvsdgModule.SourceFilePath().value());
677
678 statistics->Start(rvsdgModule.Rvsdg());
679 EncodeRegion(rvsdgModule.Rvsdg().GetRootRegion());
680 statistics->Stop();
681
682 statistics->AddIntraProceduralRegionMemoryStateCounts(
683 Context_->GetInterProceduralRegionCounter());
684 statistics->AddLoadMemoryStateCounts(Context_->GetLoadCounter());
685 statistics->AddStoreMemoryStateCounts(Context_->GetStoreCounter());
686 statistics->AddCallEntryMergeStateCounts(Context_->GetCallEntryMergeCounter());
687
688 statisticsCollector.CollectDemandedStatistics(std::move(statistics));
689
690 // Discard internal state to free up memory after we are done with the encoding
691 Context_.reset();
692
693 // Remove all nodes that became dead throughout the encoding.
694 DeadNodeElimination deadNodeElimination;
695 deadNodeElimination.Run(rvsdgModule, statisticsCollector);
696}
697
698void
700{
701 using namespace jlm::rvsdg;
702
703 TopDownTraverser traverser(&region);
704 for (const auto node : traverser)
705 {
706 MatchTypeOrFail(
707 *node,
708 [&](SimpleNode & simpleNode)
709 {
710 EncodeSimpleNode(simpleNode);
711 },
712 [&](StructuralNode & structuralNode)
713 {
714 EncodeStructuralNode(structuralNode);
715 });
716 }
717}
718
719void
721{
722 if (auto lambdaNode = dynamic_cast<const rvsdg::LambdaNode *>(&structuralNode))
723 {
724 EncodeLambda(*lambdaNode);
725 }
726 else if (auto deltaNode = dynamic_cast<const rvsdg::DeltaNode *>(&structuralNode))
727 {
728 EncodeDelta(*deltaNode);
729 }
730 else if (auto phiNode = dynamic_cast<const rvsdg::PhiNode *>(&structuralNode))
731 {
732 EncodePhi(*phiNode);
733 }
734 else if (auto gammaNode = dynamic_cast<rvsdg::GammaNode *>(&structuralNode))
735 {
736 EncodeGamma(*gammaNode);
737 }
738 else if (auto thetaNode = dynamic_cast<rvsdg::ThetaNode *>(&structuralNode))
739 {
740 EncodeTheta(*thetaNode);
741 }
742 else
743 {
744 JLM_UNREACHABLE("Unhandled node type.");
745 }
746}
747
748void
750{
751 MatchTypeWithDefault(
752 simpleNode.GetOperation(),
753 [&](const AllocaOperation &)
754 {
755 EncodeAlloca(simpleNode);
756 },
757 [&](const MallocOperation &)
758 {
759 EncodeMalloc(simpleNode);
760 },
761 [&](const LoadOperation &)
762 {
763 EncodeLoad(simpleNode);
764 },
765 [&](const StoreOperation &)
766 {
767 EncodeStore(simpleNode);
768 },
769 [&](const CallOperation &)
770 {
771 EncodeCall(simpleNode);
772 },
773 [&](const FreeOperation &)
774 {
775 EncodeFree(simpleNode);
776 },
777 [&](const MemCpyOperation &)
778 {
779 EncodeMemcpy(simpleNode);
780 },
781 [&](const MemSetOperation &)
782 {
783 EncodeMemset(simpleNode);
784 },
785 [&](const MemMoveOperation &)
786 {
787 EncodeMemmove(simpleNode);
788 },
789 [&](const MemoryStateOperation &)
790 {
791 // Nothing needs to be done
792 },
793 [&]()
794 {
795 // Ensure we took care of all memory state consuming/producing nodes
796 JLM_ASSERT(!hasMemoryState(simpleNode));
797 });
798}
799
800void
802{
803 JLM_ASSERT(is<AllocaOperation>(allocaNode.GetOperation()));
804
805 auto & stateMap = Context_->GetRegionalizedStateMap();
806 auto & allocaMemoryNodes = stateMap.GetSimpleNodeModRef(allocaNode).getModRefNodes();
807 // It is possible for read-only allocas to not have any associated memory nodes
808 if (allocaMemoryNodes.size() == 0)
809 return;
810 // An alloca can have at most one associated memory node
811 JLM_ASSERT(allocaMemoryNodes.size() == 1);
812 auto allocaMemoryNode = allocaMemoryNodes.begin()->first;
813 auto & allocaNodeStateOutput = *allocaNode.output(1);
814
815 // If a state representing the alloca already exists in the region,
816 // merge it with the state created by the alloca using a MemoryStateJoin node.
817 if (const auto statePair = stateMap.TryGetState(*allocaNode.region(), allocaMemoryNode))
818 {
819 auto & joinNode =
820 MemoryStateJoinOperation::CreateNode({ &allocaNodeStateOutput, &statePair->State() });
821 auto & joinOutput = *joinNode.output(0);
822 statePair->ReplaceState(joinOutput);
823 }
824 else
825 {
826 stateMap.InsertState(allocaMemoryNode, allocaNodeStateOutput);
827 }
828}
829
830void
832{
833 JLM_ASSERT(is<MallocOperation>(mallocNode.GetOperation()));
834 auto & stateMap = Context_->GetRegionalizedStateMap();
835 auto & mallocMemoryNodes = stateMap.GetSimpleNodeModRef(mallocNode).getModRefNodes();
836 // It is possible for read-only mallocs to not have any associated memory nodes
837 if (mallocMemoryNodes.size() == 0)
838 return;
839 // A malloc can have at most one associated memory node
840 JLM_ASSERT(mallocMemoryNodes.size() == 1);
841 auto mallocMemoryNode = mallocMemoryNodes.begin()->first;
842
843 auto & mallocNodeStateOutput = MallocOperation::memoryStateOutput(mallocNode);
844
845 // We use a static heap model. This means that multiple invocations of an malloc
846 // at runtime can refer to the same abstract memory location. We therefore need to
847 // merge the previous and the current state to ensure that the previous state
848 // is not just simply replaced and therefore "lost".
849 if (const auto statePair = stateMap.TryGetState(*mallocNode.region(), mallocMemoryNode))
850 {
851 auto & joinNode =
852 MemoryStateJoinOperation::CreateNode({ &mallocNodeStateOutput, &statePair->State() });
853 auto & joinOutput = *joinNode.output(0);
854 statePair->ReplaceState(joinOutput);
855 }
856 else
857 {
858 stateMap.InsertState(mallocMemoryNode, mallocNodeStateOutput);
859 }
860}
861
862void
864{
865 JLM_ASSERT(is<LoadOperation>(node.GetOperation()));
866 auto & stateMap = Context_->GetRegionalizedStateMap();
867
868 const auto & modRefSet = stateMap.GetSimpleNodeModRef(node);
869 Context_->GetLoadCounter().CountEntity(
870 Context_->GetModRefSummary().GetPointsToGraph(),
871 modRefSet);
872
873 const auto memoryNodeStatePairs = stateMap.GetExistingStates(*node.region(), modRefSet);
874 const auto memoryStates = StateMap::MemoryNodeStatePair::States(memoryNodeStatePairs);
875
876 const auto & newLoadNode = ReplaceLoadNode(node, memoryStates);
877
879 memoryNodeStatePairs,
881}
882
883void
885{
886 auto & stateMap = Context_->GetRegionalizedStateMap();
887
888 const auto & modRefSet = stateMap.GetSimpleNodeModRef(node);
889 Context_->GetStoreCounter().CountEntity(
890 Context_->GetModRefSummary().GetPointsToGraph(),
891 modRefSet);
892
893 const auto memoryNodeStatePairs = stateMap.GetExistingStates(*node.region(), modRefSet);
894 const auto memoryStates = StateMap::MemoryNodeStatePair::States(memoryNodeStatePairs);
895
896 const auto & newStoreNode = ReplaceStoreNode(node, memoryStates);
897
899 memoryNodeStatePairs,
901}
902
903void
905{
906 JLM_ASSERT(is<FreeOperation>(freeNode.GetOperation()));
907 auto & stateMap = Context_->GetRegionalizedStateMap();
908
909 auto address = freeNode.input(0)->origin();
910 auto ioState = freeNode.input(freeNode.ninputs() - 1)->origin();
911 auto memoryNodeStatePairs = stateMap.GetExistingStates(freeNode);
912 auto inStates = StateMap::MemoryNodeStatePair::States(memoryNodeStatePairs);
913
914 auto outputs = FreeOperation::Create(address, inStates, ioState);
915
916 // Redirect IO state edge
917 freeNode.output(freeNode.noutputs() - 1)->divert_users(outputs.back());
918
920 memoryNodeStatePairs,
921 { outputs.begin(), std::prev(outputs.end()) });
922}
923
924void
926{
927 const auto region = callNode.region();
928 auto & regionalizedStateMap = Context_->GetRegionalizedStateMap();
929
930 const auto & memoryNodes = regionalizedStateMap.GetSimpleNodeModRef(callNode);
931 Context_->GetCallEntryMergeCounter().CountEntity(
932 Context_->GetModRefSummary().GetPointsToGraph(),
933 memoryNodes);
934
935 const auto statePairs = regionalizedStateMap.GetExistingStates(*region, memoryNodes);
936
937 std::vector<rvsdg::Output *> inputStates;
938 std::vector<MemoryNodeId> memoryNodeIds;
939 for (auto statePair : statePairs)
940 {
941 inputStates.emplace_back(&statePair->State());
942 memoryNodeIds.push_back(statePair->MemoryNode());
943 }
944
945 auto & entryMergeNode =
946 CallEntryMemoryStateMergeOperation::CreateNode(*region, inputStates, memoryNodeIds);
947 CallOperation::GetMemoryStateInput(callNode).divert_to(entryMergeNode.output(0));
948
951 memoryNodeIds);
952
954}
955
956void
958{
959 JLM_ASSERT(is<MemCpyOperation>(memcpyNode.GetOperation()));
960 auto & stateMap = Context_->GetRegionalizedStateMap();
961
962 auto memoryNodeStatePairs = stateMap.GetExistingStates(memcpyNode);
963 auto memoryStateOperands = StateMap::MemoryNodeStatePair::States(memoryNodeStatePairs);
964
965 auto memoryStateResults = ReplaceMemcpyNode(memcpyNode, memoryStateOperands);
966
967 StateMap::MemoryNodeStatePair::ReplaceStates(memoryNodeStatePairs, memoryStateResults);
968}
969
970void
972{
973 JLM_ASSERT(is<MemSetOperation>(memsetNode.GetOperation()));
974 auto & stateMap = Context_->GetRegionalizedStateMap();
975
976 auto memoryNodeStatePairs = stateMap.GetExistingStates(memsetNode);
977 auto memoryStateOperands = StateMap::MemoryNodeStatePair::States(memoryNodeStatePairs);
978
979 auto memoryStateResults = ReplaceMemsetNode(memsetNode, memoryStateOperands);
980
981 StateMap::MemoryNodeStatePair::ReplaceStates(memoryNodeStatePairs, memoryStateResults);
982}
983
984void
986{
987 JLM_ASSERT(is<MemMoveOperation>(memmoveNode.GetOperation()));
988 auto & stateMap = Context_->GetRegionalizedStateMap();
989
990 auto memoryNodeStatePairs = stateMap.GetExistingStates(memmoveNode);
991 auto memoryStateOperands = StateMap::MemoryNodeStatePair::States(memoryNodeStatePairs);
992
993 auto memoryStateResults = ReplaceMemmoveNode(memmoveNode, memoryStateOperands);
994
995 StateMap::MemoryNodeStatePair::ReplaceStates(memoryNodeStatePairs, memoryStateResults);
996}
997
998void
1000{
1001 EncodeLambdaEntry(lambdaNode);
1002 EncodeRegion(*lambdaNode.subregion());
1003 EncodeLambdaExit(lambdaNode);
1004}
1005
1006void
1008{
1009 auto & memoryStateArgument = GetMemoryStateRegionArgument(lambdaNode);
1010
1011 const auto & modRefSet = Context_->GetModRefSummary().GetLambdaEntryModRef(lambdaNode);
1012 Context_->GetInterProceduralRegionCounter().CountEntity(
1013 Context_->GetModRefSummary().GetPointsToGraph(),
1014 modRefSet);
1015
1016 const auto memoryNodeIds = GetMemoryNodeIds(modRefSet);
1017 auto & stateMap = Context_->GetRegionalizedStateMap();
1018
1019 stateMap.PushRegion(*lambdaNode.subregion());
1020 auto & lambdaEntrySplitNode =
1021 LambdaEntryMemoryStateSplitOperation::CreateNode(memoryStateArgument, memoryNodeIds);
1022 const auto states = rvsdg::outputs(&lambdaEntrySplitNode);
1023
1024 size_t n = 0;
1025 for (const auto [memoryNode, _] : modRefSet.getModRefNodes())
1026 stateMap.InsertState(memoryNode, *states[n++]);
1027
1028 if (!states.empty())
1029 {
1030 // This additional MemoryStateMergeOperation node makes all other nodes in the function that
1031 // consume the memory state dependent on this node and therefore transitively on the
1032 // LambdaEntryMemoryStateSplitOperation. This ensures that the
1033 // LambdaEntryMemoryStateSplitOperation is always visited before all other memory state
1034 // consuming nodes:
1035 //
1036 // ... := LAMBDA[f]
1037 // [..., a1, ...]
1038 // o1, ..., ox := LambdaEntryMemoryStateSplit a1
1039 // oy = MemoryStateMerge o1, ..., ox
1040 // ....
1041 //
1042 // No other memory state consuming node aside from the LambdaEntryMemoryStateSplitOperation
1043 // should now consume a1.
1044 auto state = MemoryStateMergeOperation::Create(states);
1045 memoryStateArgument.divertUsersWhere(
1046 *state,
1047 [&lambdaEntrySplitNode](const rvsdg::Input & user)
1048 {
1049 return rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(user) != &lambdaEntrySplitNode;
1050 });
1051 }
1052}
1053
1054void
1056{
1057 const auto & modRefSet = Context_->GetModRefSummary().GetLambdaExitModRef(lambdaNode);
1058 auto & stateMap = Context_->GetRegionalizedStateMap();
1059 auto & memoryStateResult = GetMemoryStateRegionResult(lambdaNode);
1060
1061 std::vector<rvsdg::Output *> states;
1062 std::vector<MemoryNodeId> memoryNodeIds;
1063 auto & subregion = *lambdaNode.subregion();
1064 const auto memoryNodeStatePairs = stateMap.GetStates(subregion, modRefSet);
1065 for (const auto memoryNodeStatePair : memoryNodeStatePairs)
1066 {
1067 states.push_back(&memoryNodeStatePair->State());
1068 memoryNodeIds.push_back(memoryNodeStatePair->MemoryNode());
1069 }
1070
1071 const auto mergedState =
1072 LambdaExitMemoryStateMergeOperation::CreateNode(subregion, states, memoryNodeIds).output(0);
1073 memoryStateResult.divert_to(mergedState);
1074
1075 stateMap.PopRegion(*lambdaNode.subregion());
1076}
1077
1078void
1080{
1081 EncodeRegion(*phiNode.subregion());
1082}
1083
1084void
1086{
1087 // Nothing needs to be done
1088}
1089
1090void
1092{
1093 for (auto & subregion : gammaNode.Subregions())
1094 Context_->GetRegionalizedStateMap().PushRegion(subregion);
1095
1096 EncodeGammaEntry(gammaNode);
1097
1098 for (auto & subregion : gammaNode.Subregions())
1099 EncodeRegion(subregion);
1100
1101 EncodeGammaExit(gammaNode);
1102
1103 for (auto & subregion : gammaNode.Subregions())
1104 Context_->GetRegionalizedStateMap().PopRegion(subregion);
1105}
1106
1107void
1109{
1110 auto region = gammaNode.region();
1111 auto & stateMap = Context_->GetRegionalizedStateMap();
1112 auto & modRefSet = Context_->GetModRefSummary().GetGammaEntryModRef(gammaNode);
1113
1114 // Count the memory state arguments once per subregion
1115 for ([[maybe_unused]] auto & subregion : gammaNode.Subregions())
1116 Context_->GetInterProceduralRegionCounter().CountEntity(
1117 Context_->GetModRefSummary().GetPointsToGraph(),
1118 modRefSet);
1119
1120 auto memoryNodeStatePairs = stateMap.GetExistingStates(*region, modRefSet);
1121 for (auto & memoryNodeStatePair : memoryNodeStatePairs)
1122 {
1123 auto gammaInput = gammaNode.AddEntryVar(&memoryNodeStatePair->State());
1124 for (auto & argument : gammaInput.branchArgument)
1125 stateMap.InsertState(memoryNodeStatePair->MemoryNode(), *argument);
1126 }
1127}
1128
1129void
1131{
1132 auto & stateMap = Context_->GetRegionalizedStateMap();
1133 auto & modRefSet = Context_->GetModRefSummary().GetGammaExitModRef(gammaNode);
1134 auto memoryNodeStatePairs = stateMap.GetExistingStates(*gammaNode.region(), modRefSet);
1135
1136 for (auto & memoryNodeStatePair : memoryNodeStatePairs)
1137 {
1138 std::vector<rvsdg::Output *> states;
1139
1140 for (auto & subregion : gammaNode.Subregions())
1141 {
1142 auto & state = stateMap.GetState(subregion, memoryNodeStatePair->MemoryNode())->State();
1143 states.push_back(&state);
1144 }
1145
1146 auto state = gammaNode.AddExitVar(states).output;
1147 memoryNodeStatePair->ReplaceState(*state);
1148 }
1149}
1150
1151void
1153{
1154 Context_->GetRegionalizedStateMap().PushRegion(*thetaNode.subregion());
1155
1156 auto thetaStateOutputs = EncodeThetaEntry(thetaNode);
1157 EncodeRegion(*thetaNode.subregion());
1158 EncodeThetaExit(thetaNode, thetaStateOutputs);
1159
1160 Context_->GetRegionalizedStateMap().PopRegion(*thetaNode.subregion());
1161}
1162
1163std::vector<rvsdg::Output *>
1165{
1166 auto region = thetaNode.region();
1167 auto & stateMap = Context_->GetRegionalizedStateMap();
1168 const auto & memoryNodes = Context_->GetModRefSummary().GetThetaModRef(thetaNode);
1169 Context_->GetInterProceduralRegionCounter().CountEntity(
1170 Context_->GetModRefSummary().GetPointsToGraph(),
1171 memoryNodes);
1172
1173 std::vector<rvsdg::Output *> thetaStateOutputs;
1174 auto memoryNodeStatePairs = stateMap.GetExistingStates(*region, memoryNodes);
1175 for (auto & memoryNodeStatePair : memoryNodeStatePairs)
1176 {
1177 auto loopvar = thetaNode.AddLoopVar(&memoryNodeStatePair->State());
1178 stateMap.InsertState(memoryNodeStatePair->MemoryNode(), *loopvar.pre);
1179 thetaStateOutputs.push_back(loopvar.output);
1180 }
1181
1182 return thetaStateOutputs;
1183}
1184
1185void
1187 rvsdg::ThetaNode & thetaNode,
1188 const std::vector<rvsdg::Output *> & thetaStateOutputs)
1189{
1190 auto subregion = thetaNode.subregion();
1191 auto & stateMap = Context_->GetRegionalizedStateMap();
1192 const auto & memoryNodes = Context_->GetModRefSummary().GetThetaModRef(thetaNode);
1193 auto memoryNodeStatePairs = stateMap.GetExistingStates(*thetaNode.region(), memoryNodes);
1194
1195 JLM_ASSERT(memoryNodeStatePairs.size() == thetaStateOutputs.size());
1196 for (size_t n = 0; n < thetaStateOutputs.size(); n++)
1197 {
1198 auto thetaStateOutput = thetaStateOutputs[n];
1199 auto & memoryNodeStatePair = memoryNodeStatePairs[n];
1200 auto memoryNode = memoryNodeStatePair->MemoryNode();
1201 auto loopvar = thetaNode.MapOutputLoopVar(*thetaStateOutput);
1202 JLM_ASSERT(loopvar.input->origin() == &memoryNodeStatePair->State());
1203
1204 auto & subregionState = stateMap.GetState(*subregion, memoryNode)->State();
1205 loopvar.post->divert_to(&subregionState);
1206 memoryNodeStatePair->ReplaceState(*thetaStateOutput);
1207 }
1208}
1209
1212 const rvsdg::SimpleNode & node,
1213 const std::vector<rvsdg::Output *> & memoryStates)
1214{
1215 JLM_ASSERT(is<LoadOperation>(node.GetOperation()));
1216
1217 if (const auto loadVolatileOperation =
1218 dynamic_cast<const LoadVolatileOperation *>(&node.GetOperation()))
1219 {
1220 auto & newLoadNode = LoadVolatileOperation::CreateNode(
1221 *LoadOperation::AddressInput(node).origin(),
1223 memoryStates,
1224 loadVolatileOperation->GetLoadedType(),
1225 loadVolatileOperation->GetAlignment());
1226 auto & oldLoadedValueOutput = LoadOperation::LoadedValueOutput(node);
1227 auto & newLoadedValueOutput = LoadOperation::LoadedValueOutput(newLoadNode);
1228 auto & oldIOStateOutput = LoadVolatileOperation::IOStateOutput(node);
1229 auto & newIOStateOutput = LoadVolatileOperation::IOStateOutput(newLoadNode);
1230 oldLoadedValueOutput.divert_users(&newLoadedValueOutput);
1231 oldIOStateOutput.divert_users(&newIOStateOutput);
1232 return newLoadNode;
1233 }
1234
1235 if (const auto loadNonVolatileOperation =
1236 dynamic_cast<const LoadNonVolatileOperation *>(&node.GetOperation()))
1237 {
1238 auto & newLoadNode = LoadNonVolatileOperation::CreateNode(
1239 *LoadOperation::AddressInput(node).origin(),
1240 memoryStates,
1241 loadNonVolatileOperation->GetLoadedType(),
1242 loadNonVolatileOperation->GetAlignment());
1243 auto & oldLoadedValueOutput = LoadOperation::LoadedValueOutput(node);
1244 auto & newLoadedValueOutput = LoadNonVolatileOperation::LoadedValueOutput(newLoadNode);
1245 oldLoadedValueOutput.divert_users(&newLoadedValueOutput);
1246 return newLoadNode;
1247 }
1248
1249 JLM_UNREACHABLE("Unhandled load node type.");
1250}
1251
1254 const rvsdg::SimpleNode & node,
1255 const std::vector<rvsdg::Output *> & memoryStates)
1256{
1257 if (const auto oldStoreVolatileOperation =
1258 dynamic_cast<const StoreVolatileOperation *>(&node.GetOperation()))
1259 {
1260 auto & newStoreNode = StoreVolatileOperation::CreateNode(
1261 *StoreOperation::AddressInput(node).origin(),
1262 *StoreOperation::StoredValueInput(node).origin(),
1264 memoryStates,
1265 oldStoreVolatileOperation->GetAlignment());
1266 auto & oldIOStateOutput = StoreVolatileOperation::IOStateOutput(node);
1267 auto & newIOStateOutput = StoreVolatileOperation::IOStateOutput(newStoreNode);
1268 oldIOStateOutput.divert_users(&newIOStateOutput);
1269 return newStoreNode;
1270 }
1271
1272 if (const auto oldStoreNonVolatileOperation =
1273 dynamic_cast<const StoreNonVolatileOperation *>(&node.GetOperation()))
1274 {
1276 *StoreOperation::AddressInput(node).origin(),
1277 *StoreOperation::StoredValueInput(node).origin(),
1278 memoryStates,
1279 oldStoreNonVolatileOperation->GetAlignment());
1280 }
1281
1282 JLM_UNREACHABLE("Unhandled store node type.");
1283}
1284
1285std::vector<rvsdg::Output *>
1287 const rvsdg::SimpleNode & memcpyNode,
1288 const std::vector<rvsdg::Output *> & memoryStates)
1289{
1290 JLM_ASSERT(is<MemCpyOperation>(memcpyNode.GetOperation()));
1291
1292 auto destination = memcpyNode.input(0)->origin();
1293 auto source = memcpyNode.input(1)->origin();
1294 auto length = memcpyNode.input(2)->origin();
1295
1296 if (is<MemCpyVolatileOperation>(memcpyNode.GetOperation()))
1297 {
1298 auto & ioState = *memcpyNode.input(3)->origin();
1299 auto & newMemcpyNode =
1300 MemCpyVolatileOperation::CreateNode(*destination, *source, *length, ioState, memoryStates);
1301 auto results = rvsdg::outputs(&newMemcpyNode);
1302
1303 // Redirect I/O state
1304 memcpyNode.output(0)->divert_users(results[0]);
1305
1306 // Skip I/O state and only return memory states
1307 return { std::next(results.begin()), results.end() };
1308 }
1309 if (is<MemCpyNonVolatileOperation>(memcpyNode.GetOperation()))
1310 {
1311 return MemCpyNonVolatileOperation::create(destination, source, length, memoryStates);
1312 }
1313
1314 throw std::logic_error("Unhandled memcpy operation type.");
1315}
1316
1317std::vector<rvsdg::Output *>
1319 const rvsdg::SimpleNode & memsetNode,
1320 const std::vector<rvsdg::Output *> & memoryStates)
1321{
1322 JLM_ASSERT(is<MemSetOperation>(memsetNode.GetOperation()));
1323
1324 auto destination = MemSetOperation::destinationInput(memsetNode).origin();
1325 auto value = MemSetOperation::valueInput(memsetNode).origin();
1326 auto length = MemSetOperation::lengthInput(memsetNode).origin();
1327
1328 if (is<MemSetNonVolatileOperation>(memsetNode.GetOperation()))
1329 {
1330 return outputs(
1331 &MemSetNonVolatileOperation::createNode(*destination, *value, *length, memoryStates));
1332 }
1333
1334 throw std::logic_error("Unhandled memset operation type.");
1335}
1336
1337std::vector<rvsdg::Output *>
1339 const rvsdg::SimpleNode & memmoveNode,
1340 const std::vector<rvsdg::Output *> & memoryStates)
1341{
1342 JLM_ASSERT(is<MemMoveOperation>(memmoveNode.GetOperation()));
1343
1344 auto & destOperand = *memmoveNode.input(0)->origin();
1345 auto & srcOperand = *memmoveNode.input(1)->origin();
1346 auto & lengthOperand = *memmoveNode.input(2)->origin();
1347
1348 if (is<MemMoveNonVolatileOperation>(memmoveNode.GetOperation()))
1349 {
1351 destOperand,
1352 srcOperand,
1353 lengthOperand,
1354 memoryStates));
1355 }
1356
1357 throw std::logic_error("Unhandled memmove operation type.");
1358}
1359
1360}
static jlm::util::StatisticsCollector statisticsCollector
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
Call operation class.
Definition call.hpp:251
static rvsdg::Output & GetMemoryStateOutput(const rvsdg::Node &node) noexcept
Definition call.hpp:369
static rvsdg::Input & GetMemoryStateInput(const rvsdg::Node &node) noexcept
Definition call.hpp:357
Dead Node Elimination Optimization.
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *pointer, const std::vector< const Variable * > &memoryStates, const Variable *iOState)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands, const std::vector< MemoryNodeId > &memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< LoadNonVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
Definition Load.hpp:469
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
Definition Load.hpp:116
static rvsdg::Output & LoadedValueOutput(const rvsdg::Node &node)
Definition Load.hpp:84
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
Definition Load.hpp:75
static rvsdg::Input & IOStateInput(const rvsdg::Node &node) noexcept
Definition Load.hpp:225
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< LoadVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
Definition Load.cpp:430
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node)
Definition Load.hpp:234
static rvsdg::Output & memoryStateOutput(const rvsdg::Node &node)
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *destination, const Variable *source, const Variable *length, const std::vector< const Variable * > &memoryStates)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &destination, rvsdg::Output &source, rvsdg::Output &length, rvsdg::Output &ioState, const std::vector< rvsdg::Output * > &memoryStates)
static rvsdg::SimpleNode & createNode(rvsdg::Output &dest, rvsdg::Output &src, rvsdg::Output &length, const std::vector< rvsdg::Output * > &memoryStates)
static rvsdg::SimpleNode & createNode(rvsdg::Output &destination, rvsdg::Output &value, rvsdg::Output &length, const std::vector< rvsdg::Output * > &memoryStates)
static rvsdg::Input & valueInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & lengthInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static rvsdg::SimpleNode & CreateNode(const std::vector< rvsdg::Output * > &operands)
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &value, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
Definition Store.hpp:344
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
Definition Store.hpp:84
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
Definition Store.hpp:75
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
Definition Store.hpp:93
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node) noexcept
Definition Store.hpp:451
static rvsdg::Input & IOStateInput(const rvsdg::Node &node) noexcept
Definition Store.hpp:442
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< StoreVolatileOperation > storeOperation, const std::vector< rvsdg::Output * > &operands)
Definition Store.hpp:474
Statistics class for memory state encoder encoding.
void AddStoreMemoryStateCounts(const MemoryStateTypeCounter &counter)
static constexpr auto NumIntraProceduralRegions_
void AddCallEntryMergeStateCounts(const MemoryStateTypeCounter &counter)
void AddLoadMemoryStateCounts(const MemoryStateTypeCounter &counter)
static constexpr auto NumCallEntryMergeOperations_
static constexpr auto RegionArgumentStateSuffix_
static constexpr auto NumTotalNonEscapedState_
void AddMemoryStateTypeCounter(const std::string &suffix, const MemoryStateTypeCounter &counter)
void AddIntraProceduralRegionMemoryStateCounts(const MemoryStateTypeCounter &counter)
static constexpr auto CallEntryMergeStateSuffix_
EncodingStatistics(const util::FilePath &sourceFile)
static constexpr auto NumMaxNonEscapedMemoryState_
static constexpr auto NumTotalExternalNodeState_
~EncodingStatistics() override=default
static std::unique_ptr< EncodingStatistics > Create(const util::FilePath &sourceFile)
void Start(const rvsdg::Graph &graph)
Context for the memory state encoder.
Context(const ModRefSummary &modRefSummary)
static std::unique_ptr< MemoryStateEncoder::Context > Create(const ModRefSummary &modRefSummary)
Context & operator=(const Context &)=delete
RegionalizedStateMap & GetRegionalizedStateMap() noexcept
Context & operator=(Context &&)=delete
const ModRefSummary & GetModRefSummary() const noexcept
MemoryStateTypeCounter & GetInterProceduralRegionCounter()
static std::vector< rvsdg::Output * > ReplaceMemcpyNode(const rvsdg::SimpleNode &memcpyNode, const std::vector< rvsdg::Output * > &memoryStates)
void EncodeMalloc(const rvsdg::SimpleNode &mallocNode)
void EncodeCall(const rvsdg::SimpleNode &callNode)
void EncodeLambdaEntry(const rvsdg::LambdaNode &lambdaNode)
void EncodeAlloca(const rvsdg::SimpleNode &allocaNode)
static rvsdg::SimpleNode & ReplaceStoreNode(const rvsdg::SimpleNode &node, const std::vector< rvsdg::Output * > &memoryStates)
void EncodeStructuralNode(rvsdg::StructuralNode &structuralNode)
void EncodeDelta(const rvsdg::DeltaNode &deltaNode)
void EncodeLambda(const rvsdg::LambdaNode &lambda)
void EncodeLoad(const rvsdg::SimpleNode &node)
void EncodeGammaExit(rvsdg::GammaNode &gammaNode)
void EncodeStore(const rvsdg::SimpleNode &node)
std::unique_ptr< Context > Context_
void EncodeGammaEntry(rvsdg::GammaNode &gammaNode)
static std::vector< rvsdg::Output * > ReplaceMemmoveNode(const rvsdg::SimpleNode &memmoveNode, const std::vector< rvsdg::Output * > &memoryStates)
void EncodeRegion(rvsdg::Region &region)
static rvsdg::SimpleNode & ReplaceLoadNode(const rvsdg::SimpleNode &node, const std::vector< rvsdg::Output * > &memoryStates)
void EncodeMemmove(const rvsdg::SimpleNode &memmoveNode)
void EncodeSimpleNode(const rvsdg::SimpleNode &simpleNode)
std::vector< rvsdg::Output * > EncodeThetaEntry(rvsdg::ThetaNode &thetaNode)
void EncodePhi(const rvsdg::PhiNode &phiNode)
static std::vector< rvsdg::Output * > ReplaceMemsetNode(const rvsdg::SimpleNode &memsetNode, const std::vector< rvsdg::Output * > &memoryStates)
void EncodeMemcpy(const rvsdg::SimpleNode &memcpyNode)
void EncodeGamma(rvsdg::GammaNode &gammaNode)
void EncodeFree(const rvsdg::SimpleNode &freeNode)
void EncodeMemset(const rvsdg::SimpleNode &memsetNode)
void EncodeLambdaExit(const rvsdg::LambdaNode &lambdaNode)
void EncodeThetaExit(rvsdg::ThetaNode &thetaNode, const std::vector< rvsdg::Output * > &thetaStateOutputs)
void EncodeTheta(rvsdg::ThetaNode &thetaNode)
const std::unordered_map< PointsToGraph::NodeIndex, ModRefEffect > & getModRefNodes() const
virtual const ModRefSet & GetSimpleNodeModRef(const rvsdg::SimpleNode &node) const =0
bool isExternallyAvailable(NodeIndex index) const
NodeKind getNodeKind(NodeIndex index) const
Hash map for mapping Rvsdg regions to StateMap class instances.
std::unordered_map< const rvsdg::Region *, std::unique_ptr< StateMap > > StateMaps_
std::vector< StateMap::MemoryNodeStatePair * > GetExistingStates(const rvsdg::Region &region, const ModRefSet &modRefSet) const
StateMap::MemoryNodeStatePair * TryGetState(const rvsdg::Region &region, PointsToGraph::NodeIndex memoryNode) const
void PushRegion(const rvsdg::Region &region)
StateMap::MemoryNodeStatePair * GetState(const rvsdg::Region &region, PointsToGraph::NodeIndex memoryNode)
std::vector< StateMap::MemoryNodeStatePair * > GetStates(const rvsdg::Region &region, const ModRefSet &modRefSet)
RegionalizedStateMap & operator=(const RegionalizedStateMap &)=delete
const ModRefSet & GetSimpleNodeModRef(const rvsdg::SimpleNode &node) const
bool HasState(const rvsdg::Region &region, PointsToGraph::NodeIndex memoryNode) const
std::vector< StateMap::MemoryNodeStatePair * > GetExistingStates(const rvsdg::SimpleNode &node) const
RegionalizedStateMap & operator=(RegionalizedStateMap &&)=delete
RegionalizedStateMap(RegionalizedStateMap &&)=delete
RegionalizedStateMap(const ModRefSummary &modRefSummary)
StateMap & GetStateMap(const rvsdg::Region &region) const noexcept
RegionalizedStateMap(const RegionalizedStateMap &)=delete
StateMap::MemoryNodeStatePair * InsertState(PointsToGraph::NodeIndex memoryNode, rvsdg::Output &state)
void PopRegion(const rvsdg::Region &region)
static std::vector< rvsdg::Output * > States(const std::vector< MemoryNodeStatePair * > &memoryNodeStatePairs)
static void ReplaceStates(const std::vector< MemoryNodeStatePair * > &memoryNodeStatePairs, const rvsdg::Node::OutputIteratorRange &states)
static void ReplaceStates(const std::vector< MemoryNodeStatePair * > &memoryNodeStatePairs, const std::vector< rvsdg::Output * > &states)
void ReplaceState(rvsdg::Output &state) noexcept
MemoryNodeStatePair(PointsToGraph::NodeIndex memoryNode, rvsdg::Output &state)
PointsToGraph::NodeIndex MemoryNode() const noexcept
Hash map for mapping points-to graph memory nodes to RVSDG memory states.
std::unordered_map< PointsToGraph::NodeIndex, MemoryNodeStatePair > states_
StateMap & operator=(const StateMap &)=delete
MemoryNodeStatePair * GetState(PointsToGraph::NodeIndex memoryNode)
std::vector< MemoryNodeStatePair * > GetExistingStates(const ModRefSet &modRefSet)
StateMap & operator=(StateMap &&)=delete
std::vector< MemoryNodeStatePair * > GetStates(const ModRefSet &modRefSet)
StateMap(const StateMap &)=delete
const MemoryNodeStatePair * TryGetState(PointsToGraph::NodeIndex memoryNode) const noexcept
static std::unique_ptr< StateMap > Create()
bool HasState(PointsToGraph::NodeIndex memoryNode) const noexcept
MemoryNodeStatePair * TryGetState(PointsToGraph::NodeIndex memoryNode) noexcept
MemoryNodeStatePair * InsertState(PointsToGraph::NodeIndex memoryNode, rvsdg::Output &state)
StateMap(StateMap &&)=delete
Conditional operator / pattern matching.
Definition gamma.hpp:99
EntryVar AddEntryVar(rvsdg::Output *origin)
Routes a variable into the gamma branches.
Definition gamma.cpp:260
ExitVar AddExitVar(const std::vector< rvsdg::Output * > &values)
Routes per-branch result of gamma to output.
Definition gamma.cpp:362
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
void divert_to(Output *new_origin)
Definition node.cpp:64
Output * origin() const noexcept
Definition node.hpp:58
rvsdg::Region * subregion() const noexcept
Definition lambda.hpp:138
rvsdg::Region * region() const noexcept
Definition node.hpp:761
size_t ninputs() const noexcept
Definition node.hpp:609
size_t noutputs() const noexcept
Definition node.hpp:644
rvsdg::Region * region() const noexcept
Definition node.cpp:151
void divert_users(jlm::rvsdg::Output *new_origin)
Definition node.hpp:301
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
A phi node represents the fixpoint of mutually recursive definitions.
Definition Phi.hpp:46
rvsdg::Region * subregion() const noexcept
Definition Phi.hpp:320
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
SubregionIteratorRange Subregions()
LoopVar MapOutputLoopVar(const rvsdg::Output &output) const
Maps variable at exit to full varibale description.
Definition theta.cpp:166
rvsdg::Region * subregion() const noexcept
Definition theta.hpp:79
LoopVar AddLoopVar(rvsdg::Output *origin)
Creates a new loop-carried variable.
Definition theta.cpp:49
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
Statistics Interface.
util::Timer & GetTimer(const std::string &name)
Statistics(const Statistics::Id &statisticsId, util::FilePath sourceFile)
util::Timer & AddTimer(std::string name)
void AddMeasurement(std::string name, T value)
void start() noexcept
Definition time.hpp:54
void stop() noexcept
Definition time.hpp:67
#define JLM_ASSERT(x)
Definition common.hpp:16
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
static std::vector< MemoryNodeId > GetMemoryNodeIds(const ModRefSet &modRefSet)
rvsdg::Input & GetMemoryStateRegionResult(const rvsdg::LambdaNode &lambdaNode) noexcept
rvsdg::Output & GetMemoryStateRegionArgument(const rvsdg::LambdaNode &lambdaNode) noexcept
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition node.hpp:1058
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
Definition region.cpp:808
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
Helper struct for counting up MemoryNodes, among some set of entities that use them.
void CountEntity(const PointsToGraph &pointsToGraph, const ModRefSet &memoryNodes)
void CountEntity(uint64_t numRefOnly, uint64_t numModOnly, uint64_t numModRef, uint64_t numAllocas, uint64_t numMallocs, uint64_t numDeltas, uint64_t numImports, uint64_t numLambdas, uint64_t numExternalNode, uint64_t numNonEscaped)
rvsdg::Output * output
Output of gamma.
Definition gamma.hpp:154