24 return IsOrContains<PointerType>(
type) || is<rvsdg::FunctionType>(
type);
30 std::ostringstream str;
37 str <<
"Solver=Naive_";
41 str <<
"Solver=Worklist_";
62 auto result = str.str();
63 result.erase(result.size() - 1, 1);
67 std::vector<Andersen::Configuration>
70 std::vector<Configuration> configs;
73 config.EnablePreferImplicitPointees(
false);
74 configs.push_back(config);
75 config.EnablePreferImplicitPointees(
true);
76 configs.push_back(config);
80 config.EnableDifferencePropagation(
false);
81 PickPreferImplicitPointees(config);
82 config.EnableDifferencePropagation(
true);
83 PickPreferImplicitPointees(config);
87 config.EnableLazyCycleDetection(
false);
88 PickDifferencePropagation(config);
89 config.EnableLazyCycleDetection(
true);
90 PickDifferencePropagation(config);
94 config.EnableHybridCycleDetection(
false);
95 PickLazyCycleDetection(config);
97 if (config.IsOfflineVariableSubstitutionEnabled())
99 config.EnableHybridCycleDetection(
true);
100 PickLazyCycleDetection(config);
105 config.EnableOnlineCycleDetection(
false);
106 PickHybridCycleDetection(config);
107 config.EnableOnlineCycleDetection(
true);
109 PickDifferencePropagation(config);
114 config.SetWorklistSolverPolicy(Policy::LeastRecentlyFired);
115 PickOnlineCycleDetection(config);
116 config.SetWorklistSolverPolicy(Policy::TwoPhaseLeastRecentlyFired);
117 PickOnlineCycleDetection(config);
118 config.SetWorklistSolverPolicy(Policy::LastInFirstOut);
119 PickOnlineCycleDetection(config);
120 config.SetWorklistSolverPolicy(Policy::FirstInFirstOut);
121 PickOnlineCycleDetection(config);
122 config.SetWorklistSolverPolicy(Policy::TopologicalSort);
123 PickDifferencePropagation(config);
127 config.EnableOfflineConstraintNormalization(
false);
128 configs.push_back(config);
129 config.EnableOfflineConstraintNormalization(
true);
130 configs.push_back(config);
134 config.SetSolver(Solver::Worklist);
135 PickWorklistPolicy(config);
136 config.SetSolver(Solver::Naive);
137 PickOfflineNormalization(config);
139 auto PickOfflineVariableSubstitution = [&](
Configuration config)
141 config.EnableOfflineVariableSubstitution(
false);
143 config.EnableOfflineVariableSubstitution(
true);
148 PickOfflineVariableSubstitution(NaiveSolverConfiguration());
158 static constexpr
const char * NumPointerObjects_ =
"#PointerObjects";
159 static constexpr
const char * NumMemoryPointerObjects_ =
"#MemoryPointerObjects";
160 static constexpr
const char * NumMemoryPointerObjectsCanPoint_ =
"#MemoryPointerObjectsCanPoint";
161 static constexpr
const char * NumRegisterPointerObjects_ =
"#RegisterPointerObjects";
163 static constexpr
const char * NumRegistersMappedToPointerObject_ =
164 "#RegistersMappedToPointerObject";
165 static constexpr
const char * NumAllocaPointerObjects =
"#AllocaPointerObjects";
166 static constexpr
const char * NumMallocPointerObjects =
"#MallocPointerObjects";
167 static constexpr
const char * NumGlobalPointerObjects =
"#GlobalPointerObjects";
168 static constexpr
const char * NumFunctionPointerObjects =
"#FunctionPointerObjects";
169 static constexpr
const char * NumImportPointerObjects =
"#ImportPointerObjects";
171 static constexpr
const char * NumBaseConstraints_ =
"#BaseConstraints";
172 static constexpr
const char * NumSupersetConstraints_ =
"#SupersetConstraints";
173 static constexpr
const char * NumStoreConstraints_ =
"#StoreConstraints";
174 static constexpr
const char * NumLoadConstraints_ =
"#LoadConstraints";
175 static constexpr
const char * NumFunctionCallConstraints_ =
"#FunctionCallConstraints";
176 static constexpr
const char * NumScalarFlagConstraints_ =
"#ScalarFlagConstraints";
177 static constexpr
const char * NumOtherFlagConstraints_ =
"#OtherFlagConstraints";
179 static constexpr
const char * Configuration_ =
"Configuration";
182 static constexpr
const char * NumUnificationsOvs_ =
"#Unifications(OVS)";
183 static constexpr
const char * NumConstraintsRemovedOfflineNorm_ =
184 "#ConstraintsRemoved(OfflineNorm)";
187 static constexpr
const char * NumNaiveSolverIterations_ =
"#NaiveSolverIterations";
189 static constexpr
const char * WorklistPolicy_ =
"WorklistPolicy";
190 static constexpr
const char * NumWorklistSolverWorkItemsPopped_ =
191 "#WorklistSolverWorkItemsPopped";
192 static constexpr
const char * NumWorklistSolverWorkItemsNewPointees_ =
193 "#WorklistSolverWorkItemsNewPointees";
194 static constexpr
const char * NumTopologicalWorklistSweeps_ =
"#TopologicalWorklistSweeps";
197 static constexpr
const char * NumOnlineCyclesDetected_ =
"#OnlineCyclesDetected";
198 static constexpr
const char * NumOnlineCycleUnifications_ =
"#OnlineCycleUnifications";
200 static constexpr
const char * NumHybridCycleUnifications_ =
"#HybridCycleUnifications";
202 static constexpr
const char * NumLazyCycleDetectionAttempts_ =
"#LazyCycleDetectionAttempts";
203 static constexpr
const char * NumLazyCyclesDetected_ =
"#LazyCyclesDetected";
204 static constexpr
const char * NumLazyCycleUnifications_ =
"#LazyCycleUnifications";
206 static constexpr
const char * NumPIPExplicitPointeesRemoved_ =
"#PIPExplicitPointeesRemoved";
211 static constexpr
const char * NumSetInsertionAttempts_ =
"#PointsToSetInsertionAttempts";
214 static constexpr
const char * NumExplicitPointeesRemoved_ =
"#ExplicitPointeesRemoved";
218 static constexpr
const char * NumUnificationRoots_ =
"#UnificationRoots";
220 static constexpr
const char * NumCanPointsEscaped_ =
"#CanPointsEscaped";
222 static constexpr
const char * NumCantPointsEscaped_ =
"#CantPointsEscaped";
225 static constexpr
const char * NumExplicitPointees_ =
"#ExplicitPointees";
228 static constexpr
const char * NumExplicitPointsToRelations_ =
"#ExplicitPointsToRelations";
231 static constexpr
const char * NumPointsToExternalFlags_ =
"#PointsToExternalFlags";
233 static constexpr
const char * NumPointsToExternalRelations_ =
"#PointsToExternalRelations";
237 static constexpr
const char * NumExplicitPointsToRelationsAmongPrecise_ =
238 "#ExplicitPointsToRelationsAmongPrecise";
241 static constexpr
const char * NumPointeesEscapingFlags_ =
"#PointeesEscapingFlags";
243 static constexpr
const char * NumPointeesEscapingRelations_ =
"#PointeesEscapingRelations";
247 static constexpr
const char * NumPointsToRelations_ =
"#PointsToRelations";
250 static constexpr
const char * NumDoubledUpPointees_ =
"#DoubledUpPointees";
252 static constexpr
const char * NumDoubledUpPointsToRelations_ =
"#DoubledUpPointsToRelations";
255 static constexpr
const char * NumCantPointUnifications_ =
"#CantPointUnifications";
257 static constexpr
const char * NumCantPointExplicitPointees_ =
"#CantPointExplicitPointees";
259 static constexpr
const char * AnalysisTimer_ =
"AnalysisTimer";
260 static constexpr
const char * SetAndConstraintBuildingTimer_ =
"SetAndConstraintBuildingTimer";
261 static constexpr
const char * OfflineVariableSubstitutionTimer_ =
"OVSTimer";
262 static constexpr
const char * OfflineConstraintNormalizationTimer_ =
"OfflineNormTimer";
263 static constexpr
const char * ConstraintSolvingNaiveTimer_ =
"ConstraintSolvingNaiveTimer";
264 static constexpr
const char * ConstraintSolvingWorklistTimer_ =
"ConstraintSolvingWorklistTimer";
265 static constexpr
const char * PointsToGraphConstructionTimer_ =
"PointsToGraphConstructionTimer";
266 static constexpr
const char * PointsToGraphConstructionExternalToEscapedTimer_ =
267 "PointsToGraphConstructionExternalToEscapedTimer";
279 AddMeasurement(Label::NumRvsdgNodes,
rvsdg::nnodes(&graph.GetRootRegion()));
280 AddTimer(AnalysisTimer_).start();
286 AddTimer(SetAndConstraintBuildingTimer_).start();
294 GetTimer(SetAndConstraintBuildingTimer_).stop();
297 AddMeasurement(NumPointerObjects_, set.NumPointerObjects());
298 AddMeasurement(NumMemoryPointerObjects_, set.NumMemoryPointerObjects());
299 AddMeasurement(NumMemoryPointerObjectsCanPoint_, set.NumMemoryPointerObjectsCanPoint());
300 AddMeasurement(NumRegisterPointerObjects_, set.NumRegisterPointerObjects());
301 AddMeasurement(NumRegistersMappedToPointerObject_, set.GetRegisterMap().size());
304 NumAllocaPointerObjects,
307 NumMallocPointerObjects,
310 NumGlobalPointerObjects,
313 NumFunctionPointerObjects,
316 NumImportPointerObjects,
320 size_t numSupersetConstraints = 0;
321 size_t numStoreConstraints = 0;
322 size_t numLoadConstraints = 0;
323 size_t numFunctionCallConstraints = 0;
324 for (
const auto & constraint : constraints.GetConstraints())
326 numSupersetConstraints += std::holds_alternative<SupersetConstraint>(constraint);
327 numStoreConstraints += std::holds_alternative<StoreConstraint>(constraint);
328 numLoadConstraints += std::holds_alternative<LoadConstraint>(constraint);
329 numFunctionCallConstraints += std::holds_alternative<FunctionCallConstraint>(constraint);
331 AddMeasurement(NumBaseConstraints_, constraints.NumBaseConstraints());
332 AddMeasurement(NumSupersetConstraints_, numSupersetConstraints);
333 AddMeasurement(NumStoreConstraints_, numStoreConstraints);
334 AddMeasurement(NumLoadConstraints_, numLoadConstraints);
335 AddMeasurement(NumFunctionCallConstraints_, numFunctionCallConstraints);
336 const auto [scalarFlags, otherFlags] = constraints.NumFlagConstraints();
337 AddMeasurement(NumScalarFlagConstraints_, scalarFlags);
338 AddMeasurement(NumOtherFlagConstraints_, otherFlags);
344 AddTimer(OfflineVariableSubstitutionTimer_).start();
350 GetTimer(OfflineVariableSubstitutionTimer_).stop();
351 AddMeasurement(NumUnificationsOvs_, numUnifications);
357 AddTimer(OfflineConstraintNormalizationTimer_).start();
363 GetTimer(OfflineConstraintNormalizationTimer_).stop();
364 AddMeasurement(NumConstraintsRemovedOfflineNorm_, numConstraintsRemoved);
370 AddTimer(ConstraintSolvingNaiveTimer_).start();
376 GetTimer(ConstraintSolvingNaiveTimer_).stop();
377 AddMeasurement(NumNaiveSolverIterations_, numIterations);
383 AddTimer(ConstraintSolvingWorklistTimer_).start();
390 GetTimer(ConstraintSolvingWorklistTimer_).stop();
398 AddMeasurement(NumWorklistSolverWorkItemsPopped_, statistics.NumWorkItemsPopped);
399 AddMeasurement(NumWorklistSolverWorkItemsNewPointees_, statistics.NumWorkItemNewPointees);
401 if (statistics.NumTopologicalWorklistSweeps)
402 AddMeasurement(NumTopologicalWorklistSweeps_, *statistics.NumTopologicalWorklistSweeps);
404 if (statistics.NumOnlineCyclesDetected)
405 AddMeasurement(NumOnlineCyclesDetected_, *statistics.NumOnlineCyclesDetected);
407 if (statistics.NumOnlineCycleUnifications)
408 AddMeasurement(NumOnlineCycleUnifications_, *statistics.NumOnlineCycleUnifications);
410 if (statistics.NumHybridCycleUnifications)
411 AddMeasurement(NumHybridCycleUnifications_, *statistics.NumHybridCycleUnifications);
413 if (statistics.NumLazyCyclesDetectionAttempts)
414 AddMeasurement(NumLazyCycleDetectionAttempts_, *statistics.NumLazyCyclesDetectionAttempts);
416 if (statistics.NumLazyCyclesDetected)
417 AddMeasurement(NumLazyCyclesDetected_, *statistics.NumLazyCyclesDetected);
419 if (statistics.NumLazyCycleUnifications)
420 AddMeasurement(NumLazyCycleUnifications_, *statistics.NumLazyCycleUnifications);
422 if (statistics.NumPipExplicitPointeesRemoved)
423 AddMeasurement(NumPIPExplicitPointeesRemoved_, *statistics.NumPipExplicitPointeesRemoved);
429 AddMeasurement(Configuration_, config.
ToString());
438 size_t numUnificationRoots = 0;
440 size_t numCanPointEscaped = 0;
441 size_t numCantPointEscaped = 0;
443 size_t numExplicitPointees = 0;
444 size_t numExplicitPointsToRelations = 0;
445 size_t numExplicitPointeeRelationsAmongPrecise = 0;
447 size_t numPointsToExternalFlags = 0;
448 size_t numPointsToExternalRelations = 0;
449 size_t numPointeesEscapingFlags = 0;
450 size_t numPointeesEscapingRelations = 0;
452 size_t numDoubledUpPointees = 0;
453 size_t numDoubledUpPointsToRelations = 0;
462 numCanPointEscaped++;
464 numCantPointEscaped++;
471 numExplicitPointsToRelations += pointees.
Size();
476 numPointsToExternalRelations++;
477 for (
auto pointee : pointees.Items())
480 numDoubledUpPointsToRelations++;
487 numExplicitPointeeRelationsAmongPrecise += pointees.Size();
499 numUnificationRoots++;
501 numPointsToExternalFlags++;
503 numPointeesEscapingFlags++;
505 numExplicitPointees += pointees.Size();
509 for (
auto pointee : pointees.Items())
511 numDoubledUpPointees++;
515 size_t numCantPointUnifications = 0;
516 size_t numCantPointExplicitPointees = 0;
521 if (unificationHasCanPoint[i])
523 numCantPointUnifications++;
527 AddMeasurement(NumUnificationRoots_, numUnificationRoots);
528 AddMeasurement(NumCanPointsEscaped_, numCanPointEscaped);
529 AddMeasurement(NumCantPointsEscaped_, numCantPointEscaped);
531 AddMeasurement(NumExplicitPointees_, numExplicitPointees);
532 AddMeasurement(NumExplicitPointsToRelations_, numExplicitPointsToRelations);
534 NumExplicitPointsToRelationsAmongPrecise_,
535 numExplicitPointeeRelationsAmongPrecise);
537 AddMeasurement(NumPointsToExternalFlags_, numPointsToExternalFlags);
538 AddMeasurement(NumPointsToExternalRelations_, numPointsToExternalRelations);
539 AddMeasurement(NumPointeesEscapingFlags_, numPointeesEscapingFlags);
540 AddMeasurement(NumPointeesEscapingRelations_, numPointeesEscapingRelations);
544 size_t numPointsToRelations =
545 numExplicitPointsToRelations - numDoubledUpPointsToRelations
546 + numPointsToExternalRelations * (numCanPointEscaped + numCantPointEscaped);
548 AddMeasurement(NumPointsToRelations_, numPointsToRelations);
550 AddMeasurement(NumDoubledUpPointees_, numDoubledUpPointees);
551 AddMeasurement(NumDoubledUpPointsToRelations_, numDoubledUpPointsToRelations);
553 AddMeasurement(NumCantPointUnifications_, numCantPointUnifications);
554 AddMeasurement(NumCantPointExplicitPointees_, numCantPointExplicitPointees);
560 AddTimer(PointsToGraphConstructionTimer_).start();
566 AddTimer(PointsToGraphConstructionExternalToEscapedTimer_).start();
572 GetTimer(PointsToGraphConstructionExternalToEscapedTimer_).stop();
578 GetTimer(PointsToGraphConstructionTimer_).stop();
579 AddMeasurement(Label::NumPointsToGraphNodes, pointsToGraph.
numNodes());
580 AddMeasurement(Label::NumPointsToGraphAllocaNodes, pointsToGraph.
numAllocaNodes());
581 AddMeasurement(Label::NumPointsToGraphDeltaNodes, pointsToGraph.
numDeltaNodes());
582 AddMeasurement(Label::NumPointsToGraphImportNodes, pointsToGraph.
numImportNodes());
583 AddMeasurement(Label::NumPointsToGraphLambdaNodes, pointsToGraph.
numLambdaNodes());
584 AddMeasurement(Label::NumPointsToGraphMallocNodes, pointsToGraph.
numMallocNodes());
585 AddMeasurement(Label::NumPointsToGraphMemoryNodes, pointsToGraph.
numMemoryNodes());
586 AddMeasurement(Label::NumPointsToGraphRegisterNodes, pointsToGraph.
numRegisterNodes());
588 Label::NumPointsToGraphExternallyAvailableNodes,
592 Label::NumPointsToGraphNodesTargetsAllExternallyAvailable,
594 auto [numExplicitEdges, numEdges] = pointsToGraph.
numEdges();
595 AddMeasurement(Label::NumPointsToGraphExplicitEdges, numExplicitEdges);
596 AddMeasurement(Label::NumPointsToGraphEdges, numEdges);
602 GetTimer(AnalysisTimer_).stop();
605 static std::unique_ptr<Statistics>
608 return std::make_unique<Statistics>(sourceFile);
647 AnalyzeBitcast(node);
651 AnalyzeBits2ptr(node);
655 AnalyzePtrToInt(node);
659 AnalyzeConstantPointerNull(node);
671 AnalyzeConstantArray(node);
675 AnalyzeConstantStruct(node);
679 AnalyzeConstantAggregateZero(node);
683 AnalyzeExtractValue(node);
691 AnalyzePointerToFunction(node);
695 AnalyzeFunctionToPointer(node);
699 AnalyzeIOBarrier(node);
712 for (size_t n = 0; n < node.ninputs(); n++)
713 JLM_ASSERT(!IsOrContainsPointerType(*node.input(n)->Type()));
720 const auto allocaOp = util::assertedCast<const AllocaOperation>(&node.
GetOperation());
722 const auto & outputRegister = *node.
output(0);
723 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
726 const auto allocaPO =
Set_->CreateAllocaMemoryObject(node, canPoint);
727 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, allocaPO);
736 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
739 const auto mallocPO =
Set_->CreateMallocMemoryObject(node,
true);
740 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, mallocPO);
751 const auto addressRegisterPO =
Set_->GetRegisterPointerObject(addressRegister);
755 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
760 Set_->MarkAsLoadingAsScalar(addressRegisterPO);
770 const auto addressRegisterPO =
Set_->GetRegisterPointerObject(addressRegister);
775 const auto valueRegisterPO =
Set_->GetRegisterPointerObject(valueRegister);
780 Set_->MarkAsStoringAsScalar(addressRegisterPO);
791 const auto callTargetPO =
Set_->GetRegisterPointerObject(callTarget);
794 for (
size_t n = 0; n < callNode.
noutputs(); n++)
796 const auto & outputRegister = *callNode.
output(n);
798 (void)
Set_->CreateRegisterPointerObject(outputRegister);
814 const auto & baseRegister = *node.
input(0)->
origin();
815 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
817 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
818 const auto & outputRegister = *node.
output(0);
819 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
827 const auto & inputRegister = *node.
input(0)->
origin();
828 const auto & outputRegister = *node.
output(0);
837 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
838 Set_->MapRegisterToExistingPointerObject(outputRegister, inputRegisterPO);
845 const auto & output = *node.
output(0);
851 const auto outputPO =
Set_->CreateRegisterPointerObject(output);
859 const auto & inputRegister = *node.
input(0)->
origin();
860 JLM_ASSERT(is<PointerType>(inputRegister.Type()));
863 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
864 Constraints_->AddRegisterContentEscapedConstraint(inputRegisterPO);
871 const auto & output = *node.
output(0);
876 (void)
Set_->CreateRegisterPointerObject(output);
883 const auto & output = *node.
output(0);
890 (void)
Set_->CreateRegisterPointerObject(output);
898 auto & dstAddressRegister = *node.
input(0)->
origin();
899 auto & srcAddressRegister = *node.
input(1)->
origin();
900 JLM_ASSERT(is<PointerType>(dstAddressRegister.Type()));
901 JLM_ASSERT(is<PointerType>(srcAddressRegister.Type()));
903 const auto dstAddressRegisterPO =
Set_->GetRegisterPointerObject(dstAddressRegister);
904 const auto srcAddressRegisterPO =
Set_->GetRegisterPointerObject(srcAddressRegister);
907 const auto dummyPO =
Set_->CreateDummyRegisterPointerObject();
924 auto & outputRegister = *node.
output(0);
925 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
927 for (
size_t n = 0; n < node.
ninputs(); n++)
929 const auto & inputRegister = *node.
input(n)->
origin();
932 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
946 auto & outputRegister = *node.
output(0);
947 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
949 for (
size_t n = 0; n < node.
ninputs(); n++)
951 const auto & inputRegister = *node.
input(n)->
origin();
955 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
964 auto & output = *node.
output(0);
971 (void)
Set_->CreateRegisterPointerObject(output);
979 const auto & result = *node.
output(0);
983 const auto & inputRegister = *node.
input(0)->
origin();
984 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
986 Set_->MapRegisterToExistingPointerObject(result, inputRegisterPO);
999 for (
size_t i = 0; i < node.
ninputs(); i++)
1004 const auto & inputRegister = *node.
input(i)->
origin();
1005 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1006 Constraints_->AddRegisterContentEscapedConstraint(inputRegisterPO);
1017 const auto & baseRegister = *node.
input(0)->
origin();
1018 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
1020 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
1021 const auto & outputRegister = *node.
output(0);
1022 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
1032 const auto & baseRegister = *node.
input(0)->
origin();
1033 JLM_ASSERT(is<rvsdg::FunctionType>(baseRegister.Type()));
1035 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
1036 const auto & outputRegister = *node.
output(0);
1037 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
1045 const auto operation = util::assertedCast<const IOBarrierOperation>(&node.
GetOperation());
1049 const auto & inputRegister = *node.
input(0)->
origin();
1050 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1051 const auto & outputRegister = *node.
output(0);
1052 Set_->MapRegisterToExistingPointerObject(outputRegister, inputRegisterPO);
1091 auto & inputRegister = *cv.input->origin();
1092 auto & argumentRegister = *cv.inner;
1093 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1094 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1101 (void)
Set_->CreateRegisterPointerObject(*argument);
1107 const auto lambdaPO =
Set_->CreateFunctionMemoryObject(lambda);
1110 const auto & lambdaOutput = *lambda.
output();
1111 const auto lambdaOutputPO =
Set_->CreateRegisterPointerObject(lambdaOutput);
1112 Constraints_->AddPointerPointeeConstraint(lambdaOutputPO, lambdaPO);
1124 auto & inputRegister = *cv.input->origin();
1125 auto & argumentRegister = *cv.inner;
1126 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1127 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1139 const auto globalPO =
Set_->CreateGlobalMemoryObject(delta, canPoint);
1144 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(resultRegister);
1149 auto & outputRegister = delta.
output();
1150 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
1151 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, globalPO);
1163 auto & inputRegister = *var.input->origin();
1164 auto & argumentRegister = *var.inner;
1165 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1166 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1175 auto & argumentRegister = *var.recref;
1176 (void)
Set_->CreateRegisterPointerObject(argumentRegister);
1188 auto & argumentRegister = *var.recref;
1189 auto & resultRegister = *var.result->origin();
1190 const auto argumentRegisterPO =
Set_->GetRegisterPointerObject(argumentRegister);
1191 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(resultRegister);
1195 auto & outputRegister = *var.output;
1196 Set_->MapRegisterToExistingPointerObject(outputRegister, resultRegisterPO);
1209 auto & inputRegister = *ev.input->origin();
1210 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1212 for (
auto & argument : ev.branchArgument)
1213 Set_->MapRegisterToExistingPointerObject(*argument, inputRegisterPO);
1226 auto & outputRegister = ex.output;
1227 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(*outputRegister);
1229 for (
auto result : ex.branchResult)
1231 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(*result->origin());
1247 auto & inputReg = *loopVar.input->origin();
1248 auto & innerArgumentReg = *loopVar.pre;
1249 const auto inputRegPO =
Set_->GetRegisterPointerObject(inputReg);
1250 const auto innerArgumentRegPO =
Set_->CreateRegisterPointerObject(innerArgumentReg);
1265 auto & innerArgumentReg = *loopVar.pre;
1266 auto & innerResultReg = *loopVar.post->origin();
1267 auto & outputReg = *loopVar.output;
1269 const auto innerArgumentRegPO =
Set_->GetRegisterPointerObject(innerArgumentReg);
1270 const auto innerResultRegPO =
Set_->GetRegisterPointerObject(innerResultReg);
1276 Set_->MapRegisterToExistingPointerObject(outputReg, innerResultRegPO);
1284 for (
size_t i = 0; i < region.
narguments(); i++)
1296 for (
const auto node : traverser)
1306 for (
size_t i = 0; i < node->noutputs(); i++)
1321 for (
size_t n = 0; n < rootRegion.narguments(); n++)
1323 auto & argument = *util::assertedCast<LlvmGraphImport>(rootRegion.argument(n));
1335 const auto importObjectPO =
Set_->CreateImportMemoryObject(argument, canPoint);
1338 const auto importRegisterPO =
Set_->CreateRegisterPointerObject(argument);
1339 Constraints_->AddPointerPointeeConstraint(importRegisterPO, importObjectPO);
1345 for (
size_t n = 0; n < rootRegion.nresults(); n++)
1347 auto & escapedRegister = *rootRegion.result(n)->origin();
1351 const auto escapedRegisterPO =
Set_->GetRegisterPointerObject(escapedRegister);
1352 Constraints_->AddRegisterContentEscapedConstraint(escapedRegisterPO);
1371 Set_ = std::make_unique<PointerObjectSet>();
1425 std::unique_ptr<PointsToGraph>
1431 statistics->StartAndersenStatistics(module.
Rvsdg());
1434 size_t testAllConfigsIterations = 0;
1436 testAllConfigsIterations = std::stoi(testAllConfigsString);
1437 std::optional<size_t> useExactConfig;
1439 useExactConfig = std::stoi(useExactConfigString);
1448 std::pair<std::unique_ptr<PointerObjectSet>, std::unique_ptr<PointerObjectConstraintSet>> copy;
1449 if (testAllConfigsIterations || doubleCheck)
1457 if (useExactConfig.has_value())
1460 config = allConfigs.at(*useExactConfig);
1464 statistics->AddStatisticsFromSolution(*
Set_);
1469 graph.AppendToLabel(
"After Solving with " + config.ToString());
1475 statistics->StopAndersenStatistics();
1479 if (testAllConfigsIterations || doubleCheck)
1482 std::cerr <<
"Double checking Andersen analysis using naive solving" << std::endl;
1485 std::vector<Configuration> configs;
1486 if (testAllConfigsIterations)
1493 const auto iterations = std::max<size_t>(testAllConfigsIterations, 1);
1495 for (
size_t i = 0; i < iterations; i++)
1497 for (
const auto & config : configs)
1500 auto workingCopy = copy.second->Clone();
1504 solvingStats->AddStatisticsFromSolution(*workingCopy.first);
1508 if (doubleCheck && i == 0)
1510 if (workingCopy.first->HasIdenticalSolAs(*
Set_))
1513 <<
" did not produce the same solution as the config " << config.ToString()
1515 JLM_UNREACHABLE(
"Andersen solver double checking uncovered differences!");
1527 std::unique_ptr<PointsToGraph>
1531 return Analyze(module, statisticsCollector);
1534 std::unique_ptr<PointsToGraph>
1544 std::unordered_map<PointerObjectIndex, PointsToGraph::NodeIndex> memoryNodeMapping;
1546 for (
auto [allocaNode, pointerObjectIndex] : set.
GetAllocaMap())
1548 memoryNodeMapping[pointerObjectIndex] =
1549 pointsToGraph->addNodeForAlloca(*allocaNode, set.
HasEscaped(pointerObjectIndex));
1552 for (
auto [deltaNode, pointerObjectIndex] : set.
GetGlobalMap())
1554 memoryNodeMapping[pointerObjectIndex] =
1555 pointsToGraph->addNodeForDelta(*deltaNode, set.
HasEscaped(pointerObjectIndex));
1558 for (
auto [
import, pointerObjectIndex] : set.
GetImportMap())
1560 memoryNodeMapping[pointerObjectIndex] =
1561 pointsToGraph->addNodeForImport(*
import, set.
HasEscaped(pointerObjectIndex));
1564 for (
auto [lambdaNode, pointerObjectIndex] : set.
GetFunctionMap())
1566 memoryNodeMapping[pointerObjectIndex] =
1567 pointsToGraph->addNodeForLambda(*lambdaNode, set.
HasEscaped(pointerObjectIndex));
1570 for (
auto [mallocNode, pointerObjectIndex] : set.
GetMallocMap())
1572 memoryNodeMapping[pointerObjectIndex] =
1573 pointsToGraph->addNodeForMalloc(*mallocNode, set.
HasEscaped(pointerObjectIndex));
1590 pointsToGraph->markAsTargetsAllExternallyAvailable(ptgNode);
1596 pointsToGraph->addTarget(ptgNode, memoryNodeMapping[targetIdx]);
1603 std::unordered_map<PointerObjectIndex, util::HashSet<const rvsdg::Output *>> outputsInRegister;
1607 outputsInRegister[root].insert(outputNode);
1611 for (
auto & [registerIdx, outputNodes] : outputsInRegister)
1613 const auto ptgNode = pointsToGraph->addNodeForRegisters();
1614 for (
auto outputNode : outputNodes.Items())
1615 pointsToGraph->mapRegisterToNode(*outputNode, ptgNode);
1616 applyPointsToSet(ptgNode, registerIdx);
1620 for (
auto [pointerObjectSetIndex, ptgNode] : memoryNodeMapping)
1622 applyPointsToSet(ptgNode, pointerObjectSetIndex);
1626 return pointsToGraph;
1629 std::unique_ptr<PointsToGraph>
static rvsdg::Input & GetFunctionInput(const rvsdg::Node &node) noexcept
ConstantPointerNullOperation class.
Get address of compiled function object.
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & LoadedValueOutput(const rvsdg::Node &node)
static rvsdg::Output & addressOutput(const rvsdg::Node &node)
Interpret pointer as callable function.
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
UndefValueOperation class.
bool EnableOfflineConstraintNormalization_
bool EnableHybridCycleDetection_
bool IsOfflineVariableSubstitutionEnabled() const noexcept
bool IsLazyCycleDetectionEnabled() const noexcept
bool EnableOnlineCycleDetection_
PointerObjectConstraintSet::WorklistSolverPolicy GetWorklistSoliverPolicy() const noexcept
std::string ToString() const
bool EnableDifferencePropagation_
bool IsHybridCycleDetectionEnabled() const noexcept
bool IsPreferImplicitPointeesEnabled() const noexcept
bool IsDifferencePropagationEnabled() const noexcept
static Configuration NaiveSolverConfiguration() noexcept
PointerObjectConstraintSet::WorklistSolverPolicy WorklistSolverPolicy_
bool IsOnlineCycleDetectionEnabled() const noexcept
static std::vector< Configuration > GetAllConfigurations()
bool EnablePreferImplicitPointees_
bool EnableLazyCycleDetection_
bool IsOfflineConstraintNormalizationEnabled() const noexcept
Solver GetSolver() const noexcept
bool EnableOfflineVariableSubstitution_
void StartPointsToGraphConstructionStatistics()
void StartConstraintSolvingNaiveStatistics() noexcept
Statistics(const util::FilePath &sourceFile)
void StopAndersenStatistics() noexcept
void StartSetAndConstraintBuildingStatistics() noexcept
void StartConstraintSolvingWorklistStatistics() noexcept
void StartOfflineConstraintNormalization() noexcept
void StopOfflineVariableSubstitution(size_t numUnifications) noexcept
~Statistics() override=default
void StartOfflineVariableSubstitution() noexcept
void AddStatisticsFromSolution(const PointerObjectSet &set)
void StopPointsToGraphConstructionStatistics(const PointsToGraph &pointsToGraph)
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void StopSetAndConstraintBuildingStatistics(const PointerObjectSet &set, const PointerObjectConstraintSet &constraints) noexcept
void StopOfflineConstraintNormalization(size_t numConstraintsRemoved) noexcept
void StartAndersenStatistics(const rvsdg::Graph &graph) noexcept
void StopConstraintSolvingNaiveStatistics(size_t numIterations) noexcept
void AddStatisticFromConfiguration(const Configuration &config)
void StopExternalToAllEscapedStatistics()
void StartExternalToAllEscapedStatistics()
void StopConstraintSolvingWorklistStatistics(PointerObjectConstraintSet::WorklistStatistics &statistics) noexcept
void AnalyzeIOBarrier(const rvsdg::SimpleNode &node)
const Configuration & GetConfiguration() const
static void SolveConstraints(PointerObjectConstraintSet &constraints, const Configuration &config, Statistics &statistics)
void AnalyzeConstantPointerNull(const rvsdg::SimpleNode &node)
void SetConfiguration(Configuration config)
void AnalyzeValist(const rvsdg::SimpleNode &node)
void AnalyzePointerToFunction(const rvsdg::SimpleNode &node)
void AnalyzeStore(const rvsdg::SimpleNode &node)
static const char *const ENV_USE_EXACT_CONFIG
std::unique_ptr< PointerObjectSet > Set_
void AnalyzeUndef(const rvsdg::SimpleNode &node)
static std::unique_ptr< PointsToGraph > ConstructPointsToGraphFromPointerObjectSet(const PointerObjectSet &set, Statistics &statistics)
static const char *const ENV_DOUBLE_CHECK
void AnalyzeRegion(rvsdg::Region ®ion)
void AnalyzeGep(const rvsdg::SimpleNode &node)
~Andersen() noexcept override
void AnalyzeRvsdg(const rvsdg::Graph &graph)
void AnalyzeAlloca(const rvsdg::SimpleNode &node)
void AnalyzeModule(const rvsdg::RvsdgModule &module, Statistics &statistics)
void AnalyzePtrToInt(const rvsdg::SimpleNode &node)
std::unique_ptr< PointsToGraph > Analyze(const rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
void AnalyzeExtractValue(const rvsdg::SimpleNode &node)
void AnalyzeConstantArray(const rvsdg::SimpleNode &node)
void AnalyzeConstantAggregateZero(const rvsdg::SimpleNode &node)
void AnalyzeBitcast(const rvsdg::SimpleNode &node)
void AnalyzePhi(const rvsdg::PhiNode &node)
static const char *const ENV_DUMP_SUBSET_GRAPH
void AnalyzeMemcpy(const rvsdg::SimpleNode &node)
void AnalyzeCall(const rvsdg::SimpleNode &callNode)
void AnalyzeConstantStruct(const rvsdg::SimpleNode &node)
std::unique_ptr< PointerObjectConstraintSet > Constraints_
void AnalyzeTheta(const rvsdg::ThetaNode &node)
void AnalyzeMalloc(const rvsdg::SimpleNode &node)
void AnalyzeLambda(const rvsdg::LambdaNode &node)
void AnalyzeBits2ptr(const rvsdg::SimpleNode &node)
void AnalyzeLoad(const rvsdg::SimpleNode &node)
void AnalyzeSimpleNode(const rvsdg::SimpleNode &node)
void AnalyzeFunctionToPointer(const rvsdg::SimpleNode &node)
void AnalyzeGamma(const rvsdg::GammaNode &node)
void AnalyzeStructuralNode(const rvsdg::StructuralNode &node)
static const char *const ENV_TEST_ALL_CONFIGS
void AnalyzeDelta(const rvsdg::DeltaNode &node)
size_t NormalizeConstraints()
size_t PerformOfflineVariableSubstitution(bool storeRefCycleUnificationRoot)
WorklistStatistics SolveUsingWorklist(WorklistSolverPolicy policy, bool enableOnlineCycleDetection, bool enableHybridCycleDetection, bool enableLazyCycleDetection, bool enableDifferencePropagation, bool enablePreferImplicitPropation)
static const char * WorklistSolverPolicyToString(WorklistSolverPolicy policy)
const util::BijectiveMap< const rvsdg::LambdaNode *, PointerObjectIndex > & GetFunctionMap() const noexcept
size_t GetNumSetInsertionAttempts() const noexcept
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetMallocMap() const noexcept
size_t GetNumExplicitPointeesRemoved() const noexcept
const util::HashSet< PointerObjectIndex > & GetPointsToSet(PointerObjectIndex index) const
bool HasPointeesEscaping(PointerObjectIndex index) const noexcept
bool CanPoint(PointerObjectIndex index) const noexcept
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetAllocaMap() const noexcept
bool IsPointingToExternal(PointerObjectIndex index) const noexcept
bool HasEscaped(PointerObjectIndex index) const noexcept
const std::unordered_map< const LlvmGraphImport *, PointerObjectIndex > & GetImportMap() const noexcept
const std::unordered_map< const rvsdg::DeltaNode *, PointerObjectIndex > & GetGlobalMap() const noexcept
PointerObjectIndex GetUnificationRoot(PointerObjectIndex index) const noexcept
bool IsUnificationRoot(PointerObjectIndex index) const noexcept
size_t NumPointerObjects() const noexcept
const std::unordered_map< const rvsdg::Output *, PointerObjectIndex > & GetRegisterMap() const noexcept
size_t numLambdaNodes() const noexcept
size_t numNodesTargetingAllExternallyAvailable() const noexcept
size_t numNodes() const noexcept
size_t numMemoryNodes() const noexcept
size_t numRegisterNodes() const noexcept
size_t numMallocNodes() const noexcept
static std::unique_ptr< PointsToGraph > create()
size_t numExternallyAvailableNodes() const noexcept
size_t numDeltaNodes() const noexcept
size_t numAllocaNodes() const noexcept
size_t numImportNodes() const noexcept
std::pair< size_t, size_t > numEdges() const noexcept
rvsdg::Input & result() const noexcept
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
rvsdg::Region * subregion() const noexcept
rvsdg::Output & output() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Conditional operator / pattern matching.
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
Region & GetRootRegion() const noexcept
std::vector< rvsdg::Output * > GetFunctionArguments() const
rvsdg::Region * subregion() const noexcept
rvsdg::Output * output() const noexcept
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
size_t ninputs() const noexcept
size_t noutputs() 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
std::vector< FixVar > GetFixVars() const noexcept
Gets all fixpoint variables.
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Represent acyclic RVSDG subgraphs.
RegionArgument * argument(size_t index) const noexcept
size_t narguments() const noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
size_t nsubregions() const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
rvsdg::Region * subregion() const noexcept
std::size_t Size() const noexcept
IteratorRange< ItemConstIterator > Items() const noexcept
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
void outputAllGraphs(std::ostream &out, OutputFormat format)
#define JLM_UNREACHABLE(msg)
bool IsOrContainsPointerType(const rvsdg::Type &type)
uint32_t PointerObjectIndex
bool IsAggregateType(const jlm::rvsdg::Type &type)
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
static std::string type(const Node *n)
size_t nnodes(const jlm::rvsdg::Region *region) noexcept