32 return IsOrContains<PointerType>(type) || is<rvsdg::FunctionType>(type);
38 std::ostringstream str;
45 str <<
"Solver=Naive_";
49 str <<
"Solver=Worklist_";
70 auto result = str.str();
71 result.erase(result.size() - 1, 1);
75 std::vector<Andersen::Configuration>
78 std::vector<Configuration> configs;
81 config.EnablePreferImplicitPointees(
false);
82 configs.push_back(config);
83 config.EnablePreferImplicitPointees(
true);
84 configs.push_back(config);
88 config.EnableDifferencePropagation(
false);
89 PickPreferImplicitPointees(config);
90 config.EnableDifferencePropagation(
true);
91 PickPreferImplicitPointees(config);
95 config.EnableLazyCycleDetection(
false);
96 PickDifferencePropagation(config);
97 config.EnableLazyCycleDetection(
true);
98 PickDifferencePropagation(config);
102 config.EnableHybridCycleDetection(
false);
103 PickLazyCycleDetection(config);
105 if (config.IsOfflineVariableSubstitutionEnabled())
107 config.EnableHybridCycleDetection(
true);
108 PickLazyCycleDetection(config);
113 config.EnableOnlineCycleDetection(
false);
114 PickHybridCycleDetection(config);
115 config.EnableOnlineCycleDetection(
true);
117 PickDifferencePropagation(config);
122 config.SetWorklistSolverPolicy(Policy::LeastRecentlyFired);
123 PickOnlineCycleDetection(config);
124 config.SetWorklistSolverPolicy(Policy::TwoPhaseLeastRecentlyFired);
125 PickOnlineCycleDetection(config);
126 config.SetWorklistSolverPolicy(Policy::LastInFirstOut);
127 PickOnlineCycleDetection(config);
128 config.SetWorklistSolverPolicy(Policy::FirstInFirstOut);
129 PickOnlineCycleDetection(config);
130 config.SetWorklistSolverPolicy(Policy::TopologicalSort);
131 PickDifferencePropagation(config);
135 config.EnableOfflineConstraintNormalization(
false);
136 configs.push_back(config);
137 config.EnableOfflineConstraintNormalization(
true);
138 configs.push_back(config);
142 config.SetSolver(Solver::Worklist);
143 PickWorklistPolicy(config);
144 config.SetSolver(Solver::Naive);
145 PickOfflineNormalization(config);
147 auto PickOfflineVariableSubstitution = [&](
Configuration config)
149 config.EnableOfflineVariableSubstitution(
false);
151 config.EnableOfflineVariableSubstitution(
true);
156 PickOfflineVariableSubstitution(NaiveSolverConfiguration());
166 static constexpr
const char * NumPointerObjects_ =
"#PointerObjects";
167 static constexpr
const char * NumMemoryPointerObjects_ =
"#MemoryPointerObjects";
168 static constexpr
const char * NumMemoryPointerObjectsCanPoint_ =
"#MemoryPointerObjectsCanPoint";
169 static constexpr
const char * NumRegisterPointerObjects_ =
"#RegisterPointerObjects";
171 static constexpr
const char * NumRegistersMappedToPointerObject_ =
172 "#RegistersMappedToPointerObject";
173 static constexpr
const char * NumAllocaPointerObjects =
"#AllocaPointerObjects";
174 static constexpr
const char * NumMallocPointerObjects =
"#MallocPointerObjects";
175 static constexpr
const char * NumGlobalPointerObjects =
"#GlobalPointerObjects";
176 static constexpr
const char * NumFunctionPointerObjects =
"#FunctionPointerObjects";
177 static constexpr
const char * NumImportPointerObjects =
"#ImportPointerObjects";
179 static constexpr
const char * NumBaseConstraints_ =
"#BaseConstraints";
180 static constexpr
const char * NumSupersetConstraints_ =
"#SupersetConstraints";
181 static constexpr
const char * NumStoreConstraints_ =
"#StoreConstraints";
182 static constexpr
const char * NumLoadConstraints_ =
"#LoadConstraints";
183 static constexpr
const char * NumFunctionCallConstraints_ =
"#FunctionCallConstraints";
184 static constexpr
const char * NumScalarFlagConstraints_ =
"#ScalarFlagConstraints";
185 static constexpr
const char * NumOtherFlagConstraints_ =
"#OtherFlagConstraints";
187 static constexpr
const char * Configuration_ =
"Configuration";
190 static constexpr
const char * NumUnificationsOvs_ =
"#Unifications(OVS)";
191 static constexpr
const char * NumConstraintsRemovedOfflineNorm_ =
192 "#ConstraintsRemoved(OfflineNorm)";
195 static constexpr
const char * NumNaiveSolverIterations_ =
"#NaiveSolverIterations";
197 static constexpr
const char * WorklistPolicy_ =
"WorklistPolicy";
198 static constexpr
const char * NumWorklistSolverWorkItemsPopped_ =
199 "#WorklistSolverWorkItemsPopped";
200 static constexpr
const char * NumWorklistSolverWorkItemsNewPointees_ =
201 "#WorklistSolverWorkItemsNewPointees";
202 static constexpr
const char * NumTopologicalWorklistSweeps_ =
"#TopologicalWorklistSweeps";
205 static constexpr
const char * NumOnlineCyclesDetected_ =
"#OnlineCyclesDetected";
206 static constexpr
const char * NumOnlineCycleUnifications_ =
"#OnlineCycleUnifications";
208 static constexpr
const char * NumHybridCycleUnifications_ =
"#HybridCycleUnifications";
210 static constexpr
const char * NumLazyCycleDetectionAttempts_ =
"#LazyCycleDetectionAttempts";
211 static constexpr
const char * NumLazyCyclesDetected_ =
"#LazyCyclesDetected";
212 static constexpr
const char * NumLazyCycleUnifications_ =
"#LazyCycleUnifications";
214 static constexpr
const char * NumPIPExplicitPointeesRemoved_ =
"#PIPExplicitPointeesRemoved";
219 static constexpr
const char * NumSetInsertionAttempts_ =
"#PointsToSetInsertionAttempts";
222 static constexpr
const char * NumExplicitPointeesRemoved_ =
"#ExplicitPointeesRemoved";
226 static constexpr
const char * NumUnificationRoots_ =
"#UnificationRoots";
228 static constexpr
const char * NumCanPointsEscaped_ =
"#CanPointsEscaped";
230 static constexpr
const char * NumCantPointsEscaped_ =
"#CantPointsEscaped";
233 static constexpr
const char * NumExplicitPointees_ =
"#ExplicitPointees";
236 static constexpr
const char * NumExplicitPointsToRelations_ =
"#ExplicitPointsToRelations";
239 static constexpr
const char * NumPointsToExternalFlags_ =
"#PointsToExternalFlags";
241 static constexpr
const char * NumPointsToExternalRelations_ =
"#PointsToExternalRelations";
245 static constexpr
const char * NumExplicitPointsToRelationsAmongPrecise_ =
246 "#ExplicitPointsToRelationsAmongPrecise";
249 static constexpr
const char * NumPointeesEscapingFlags_ =
"#PointeesEscapingFlags";
251 static constexpr
const char * NumPointeesEscapingRelations_ =
"#PointeesEscapingRelations";
255 static constexpr
const char * NumPointsToRelations_ =
"#PointsToRelations";
258 static constexpr
const char * NumDoubledUpPointees_ =
"#DoubledUpPointees";
260 static constexpr
const char * NumDoubledUpPointsToRelations_ =
"#DoubledUpPointsToRelations";
263 static constexpr
const char * NumCantPointUnifications_ =
"#CantPointUnifications";
265 static constexpr
const char * NumCantPointExplicitPointees_ =
"#CantPointExplicitPointees";
267 static constexpr
const char * AnalysisTimer_ =
"AnalysisTimer";
268 static constexpr
const char * SetAndConstraintBuildingTimer_ =
"SetAndConstraintBuildingTimer";
269 static constexpr
const char * OfflineVariableSubstitutionTimer_ =
"OVSTimer";
270 static constexpr
const char * OfflineConstraintNormalizationTimer_ =
"OfflineNormTimer";
271 static constexpr
const char * ConstraintSolvingNaiveTimer_ =
"ConstraintSolvingNaiveTimer";
272 static constexpr
const char * ConstraintSolvingWorklistTimer_ =
"ConstraintSolvingWorklistTimer";
273 static constexpr
const char * PointsToGraphConstructionTimer_ =
"PointsToGraphConstructionTimer";
274 static constexpr
const char * PointsToGraphConstructionExternalToEscapedTimer_ =
275 "PointsToGraphConstructionExternalToEscapedTimer";
287 AddMeasurement(Label::NumRvsdgNodes,
rvsdg::nnodes(&graph.GetRootRegion()));
288 AddTimer(AnalysisTimer_).start();
294 AddTimer(SetAndConstraintBuildingTimer_).start();
302 GetTimer(SetAndConstraintBuildingTimer_).stop();
305 AddMeasurement(NumPointerObjects_, set.NumPointerObjects());
306 AddMeasurement(NumMemoryPointerObjects_, set.NumMemoryPointerObjects());
307 AddMeasurement(NumMemoryPointerObjectsCanPoint_, set.NumMemoryPointerObjectsCanPoint());
308 AddMeasurement(NumRegisterPointerObjects_, set.NumRegisterPointerObjects());
309 AddMeasurement(NumRegistersMappedToPointerObject_, set.GetRegisterMap().size());
312 NumAllocaPointerObjects,
315 NumMallocPointerObjects,
318 NumGlobalPointerObjects,
321 NumFunctionPointerObjects,
324 NumImportPointerObjects,
328 size_t numSupersetConstraints = 0;
329 size_t numStoreConstraints = 0;
330 size_t numLoadConstraints = 0;
331 size_t numFunctionCallConstraints = 0;
332 for (
const auto & constraint : constraints.GetConstraints())
334 numSupersetConstraints += std::holds_alternative<SupersetConstraint>(constraint);
335 numStoreConstraints += std::holds_alternative<StoreConstraint>(constraint);
336 numLoadConstraints += std::holds_alternative<LoadConstraint>(constraint);
337 numFunctionCallConstraints += std::holds_alternative<FunctionCallConstraint>(constraint);
339 AddMeasurement(NumBaseConstraints_, constraints.NumBaseConstraints());
340 AddMeasurement(NumSupersetConstraints_, numSupersetConstraints);
341 AddMeasurement(NumStoreConstraints_, numStoreConstraints);
342 AddMeasurement(NumLoadConstraints_, numLoadConstraints);
343 AddMeasurement(NumFunctionCallConstraints_, numFunctionCallConstraints);
344 const auto [scalarFlags, otherFlags] = constraints.NumFlagConstraints();
345 AddMeasurement(NumScalarFlagConstraints_, scalarFlags);
346 AddMeasurement(NumOtherFlagConstraints_, otherFlags);
352 AddTimer(OfflineVariableSubstitutionTimer_).start();
358 GetTimer(OfflineVariableSubstitutionTimer_).stop();
359 AddMeasurement(NumUnificationsOvs_, numUnifications);
365 AddTimer(OfflineConstraintNormalizationTimer_).start();
371 GetTimer(OfflineConstraintNormalizationTimer_).stop();
372 AddMeasurement(NumConstraintsRemovedOfflineNorm_, numConstraintsRemoved);
378 AddTimer(ConstraintSolvingNaiveTimer_).start();
384 GetTimer(ConstraintSolvingNaiveTimer_).stop();
385 AddMeasurement(NumNaiveSolverIterations_, numIterations);
391 AddTimer(ConstraintSolvingWorklistTimer_).start();
398 GetTimer(ConstraintSolvingWorklistTimer_).stop();
406 AddMeasurement(NumWorklistSolverWorkItemsPopped_, statistics.NumWorkItemsPopped);
407 AddMeasurement(NumWorklistSolverWorkItemsNewPointees_, statistics.NumWorkItemNewPointees);
409 if (statistics.NumTopologicalWorklistSweeps)
410 AddMeasurement(NumTopologicalWorklistSweeps_, *statistics.NumTopologicalWorklistSweeps);
412 if (statistics.NumOnlineCyclesDetected)
413 AddMeasurement(NumOnlineCyclesDetected_, *statistics.NumOnlineCyclesDetected);
415 if (statistics.NumOnlineCycleUnifications)
416 AddMeasurement(NumOnlineCycleUnifications_, *statistics.NumOnlineCycleUnifications);
418 if (statistics.NumHybridCycleUnifications)
419 AddMeasurement(NumHybridCycleUnifications_, *statistics.NumHybridCycleUnifications);
421 if (statistics.NumLazyCyclesDetectionAttempts)
422 AddMeasurement(NumLazyCycleDetectionAttempts_, *statistics.NumLazyCyclesDetectionAttempts);
424 if (statistics.NumLazyCyclesDetected)
425 AddMeasurement(NumLazyCyclesDetected_, *statistics.NumLazyCyclesDetected);
427 if (statistics.NumLazyCycleUnifications)
428 AddMeasurement(NumLazyCycleUnifications_, *statistics.NumLazyCycleUnifications);
430 if (statistics.NumPipExplicitPointeesRemoved)
431 AddMeasurement(NumPIPExplicitPointeesRemoved_, *statistics.NumPipExplicitPointeesRemoved);
437 AddMeasurement(Configuration_, config.
ToString());
446 size_t numUnificationRoots = 0;
448 size_t numCanPointEscaped = 0;
449 size_t numCantPointEscaped = 0;
451 size_t numExplicitPointees = 0;
452 size_t numExplicitPointsToRelations = 0;
453 size_t numExplicitPointeeRelationsAmongPrecise = 0;
455 size_t numPointsToExternalFlags = 0;
456 size_t numPointsToExternalRelations = 0;
457 size_t numPointeesEscapingFlags = 0;
458 size_t numPointeesEscapingRelations = 0;
460 size_t numDoubledUpPointees = 0;
461 size_t numDoubledUpPointsToRelations = 0;
470 numCanPointEscaped++;
472 numCantPointEscaped++;
479 numExplicitPointsToRelations += pointees.
Size();
484 numPointsToExternalRelations++;
485 for (
auto pointee : pointees.Items())
488 numDoubledUpPointsToRelations++;
495 numExplicitPointeeRelationsAmongPrecise += pointees.Size();
507 numUnificationRoots++;
509 numPointsToExternalFlags++;
511 numPointeesEscapingFlags++;
513 numExplicitPointees += pointees.Size();
517 for (
auto pointee : pointees.Items())
519 numDoubledUpPointees++;
523 size_t numCantPointUnifications = 0;
524 size_t numCantPointExplicitPointees = 0;
529 if (unificationHasCanPoint[i])
531 numCantPointUnifications++;
535 AddMeasurement(NumUnificationRoots_, numUnificationRoots);
536 AddMeasurement(NumCanPointsEscaped_, numCanPointEscaped);
537 AddMeasurement(NumCantPointsEscaped_, numCantPointEscaped);
539 AddMeasurement(NumExplicitPointees_, numExplicitPointees);
540 AddMeasurement(NumExplicitPointsToRelations_, numExplicitPointsToRelations);
542 NumExplicitPointsToRelationsAmongPrecise_,
543 numExplicitPointeeRelationsAmongPrecise);
545 AddMeasurement(NumPointsToExternalFlags_, numPointsToExternalFlags);
546 AddMeasurement(NumPointsToExternalRelations_, numPointsToExternalRelations);
547 AddMeasurement(NumPointeesEscapingFlags_, numPointeesEscapingFlags);
548 AddMeasurement(NumPointeesEscapingRelations_, numPointeesEscapingRelations);
552 size_t numPointsToRelations =
553 numExplicitPointsToRelations - numDoubledUpPointsToRelations
554 + numPointsToExternalRelations * (numCanPointEscaped + numCantPointEscaped);
556 AddMeasurement(NumPointsToRelations_, numPointsToRelations);
558 AddMeasurement(NumDoubledUpPointees_, numDoubledUpPointees);
559 AddMeasurement(NumDoubledUpPointsToRelations_, numDoubledUpPointsToRelations);
561 AddMeasurement(NumCantPointUnifications_, numCantPointUnifications);
562 AddMeasurement(NumCantPointExplicitPointees_, numCantPointExplicitPointees);
568 AddTimer(PointsToGraphConstructionTimer_).start();
574 AddTimer(PointsToGraphConstructionExternalToEscapedTimer_).start();
580 GetTimer(PointsToGraphConstructionExternalToEscapedTimer_).stop();
586 GetTimer(PointsToGraphConstructionTimer_).stop();
587 AddMeasurement(Label::NumPointsToGraphNodes, pointsToGraph.
numNodes());
588 AddMeasurement(Label::NumPointsToGraphAllocaNodes, pointsToGraph.
numAllocaNodes());
589 AddMeasurement(Label::NumPointsToGraphDeltaNodes, pointsToGraph.
numDeltaNodes());
590 AddMeasurement(Label::NumPointsToGraphImportNodes, pointsToGraph.
numImportNodes());
591 AddMeasurement(Label::NumPointsToGraphLambdaNodes, pointsToGraph.
numLambdaNodes());
592 AddMeasurement(Label::NumPointsToGraphMallocNodes, pointsToGraph.
numMallocNodes());
593 AddMeasurement(Label::NumPointsToGraphMemoryNodes, pointsToGraph.
numMemoryNodes());
594 AddMeasurement(Label::NumPointsToGraphRegisterNodes, pointsToGraph.
numRegisterNodes());
596 Label::NumPointsToGraphExternallyAvailableNodes,
600 Label::NumPointsToGraphNodesTargetsAllExternallyAvailable,
602 auto [numExplicitEdges, numEdges] = pointsToGraph.
numEdges();
603 AddMeasurement(Label::NumPointsToGraphExplicitEdges, numExplicitEdges);
604 AddMeasurement(Label::NumPointsToGraphEdges, numEdges);
610 GetTimer(AnalysisTimer_).stop();
613 static std::unique_ptr<Statistics>
616 return std::make_unique<Statistics>(sourceFile);
655 AnalyzeBitcast(node);
659 AnalyzeBits2ptr(node);
663 AnalyzePtrToInt(node);
667 AnalyzeConstantPointerNull(node);
691 AnalyzeConstantArray(node);
695 AnalyzeConstantStruct(node);
699 AnalyzeConstantAggregateZero(node);
703 AnalyzeInsertValue(node);
707 AnalyzeExtractValue(node);
715 AnalyzePointerToFunction(node);
719 AnalyzeFunctionToPointer(node);
723 AnalyzeIOBarrier(node);
736 for (size_t n = 0; n < node.ninputs(); n++)
737 JLM_ASSERT(!IsOrContainsPointerType(*node.input(n)->Type()));
744 const auto allocaOp = util::assertedCast<const AllocaOperation>(&node.
GetOperation());
746 const auto & outputRegister = *node.
output(0);
747 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
750 const auto allocaPO =
Set_->CreateAllocaMemoryObject(node, canPoint);
751 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, allocaPO);
760 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
763 const auto mallocPO =
Set_->CreateMallocMemoryObject(node,
true);
764 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, mallocPO);
775 const auto addressRegisterPO =
Set_->GetRegisterPointerObject(addressRegister);
779 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
784 Set_->MarkAsLoadingAsScalar(addressRegisterPO);
794 const auto addressRegisterPO =
Set_->GetRegisterPointerObject(addressRegister);
799 const auto valueRegisterPO =
Set_->GetRegisterPointerObject(valueRegister);
804 Set_->MarkAsStoringAsScalar(addressRegisterPO);
815 const auto callTargetPO =
Set_->GetRegisterPointerObject(callTarget);
818 for (
size_t n = 0; n < callNode.
noutputs(); n++)
820 const auto & outputRegister = *callNode.
output(n);
822 (void)
Set_->CreateRegisterPointerObject(outputRegister);
838 const auto & baseRegister = *node.
input(0)->
origin();
839 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
841 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
842 const auto & outputRegister = *node.
output(0);
843 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
851 const auto & inputRegister = *node.
input(0)->
origin();
852 const auto & outputRegister = *node.
output(0);
861 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
862 Set_->MapRegisterToExistingPointerObject(outputRegister, inputRegisterPO);
869 const auto & output = *node.
output(0);
875 const auto outputPO =
Set_->CreateRegisterPointerObject(output);
883 const auto & inputRegister = *node.
input(0)->
origin();
884 JLM_ASSERT(is<PointerType>(inputRegister.Type()));
887 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
888 Constraints_->AddRegisterContentEscapedConstraint(inputRegisterPO);
895 const auto & output = *node.
output(0);
900 (void)
Set_->CreateRegisterPointerObject(output);
907 const auto & output = *node.
output(0);
914 (void)
Set_->CreateRegisterPointerObject(output);
921 const auto & output = *node.
output(0);
928 (void)
Set_->CreateRegisterPointerObject(output);
935 const auto & output = *node.
output(0);
944 auto operandPO =
Set_->GetRegisterPointerObject(operand);
945 Set_->MapRegisterToExistingPointerObject(output, operandPO);
953 auto & dstAddressRegister = *node.
input(0)->
origin();
954 auto & srcAddressRegister = *node.
input(1)->
origin();
955 JLM_ASSERT(is<PointerType>(dstAddressRegister.Type()));
956 JLM_ASSERT(is<PointerType>(srcAddressRegister.Type()));
958 const auto dstAddressRegisterPO =
Set_->GetRegisterPointerObject(dstAddressRegister);
959 const auto srcAddressRegisterPO =
Set_->GetRegisterPointerObject(srcAddressRegister);
962 const auto dummyPO =
Set_->CreateDummyRegisterPointerObject();
976 JLM_ASSERT(is<PointerType>(dstAddressRegister.Type()));
978 const auto dstAddressRegisterPO =
Set_->GetRegisterPointerObject(dstAddressRegister);
980 Set_->MarkAsStoringAsScalar(dstAddressRegisterPO);
992 auto & outputRegister = *node.
output(0);
993 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
995 for (
size_t n = 0; n < node.
ninputs(); n++)
997 const auto & inputRegister = *node.
input(n)->
origin();
1000 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1014 auto & outputRegister = *node.
output(0);
1015 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
1017 for (
size_t n = 0; n < node.
ninputs(); n++)
1019 const auto & inputRegister = *node.
input(n)->
origin();
1023 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1032 auto & output = *node.
output(0);
1039 (void)
Set_->CreateRegisterPointerObject(output);
1054 const auto & result = *node.
output(0);
1058 const auto & inputRegister = *node.
input(0)->
origin();
1059 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1067 const auto elementPO =
Set_->GetRegisterPointerObject(element);
1068 const auto resultPO =
Set_->CreateRegisterPointerObject(result);
1075 Set_->MapRegisterToExistingPointerObject(result, inputRegisterPO);
1084 const auto & result = *node.
output(0);
1088 const auto & inputRegister = *node.
input(0)->
origin();
1089 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1091 Set_->MapRegisterToExistingPointerObject(result, inputRegisterPO);
1104 for (
size_t i = 0; i < node.
ninputs(); i++)
1109 const auto & inputRegister = *node.
input(i)->
origin();
1110 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1111 Constraints_->AddRegisterContentEscapedConstraint(inputRegisterPO);
1122 const auto & baseRegister = *node.
input(0)->
origin();
1123 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
1125 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
1126 const auto & outputRegister = *node.
output(0);
1127 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
1137 const auto & baseRegister = *node.
input(0)->
origin();
1138 JLM_ASSERT(is<rvsdg::FunctionType>(baseRegister.Type()));
1140 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
1141 const auto & outputRegister = *node.
output(0);
1142 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
1150 const auto operation = util::assertedCast<const IOBarrierOperation>(&node.
GetOperation());
1154 const auto & inputRegister = *node.
input(0)->
origin();
1155 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1156 const auto & outputRegister = *node.
output(0);
1157 Set_->MapRegisterToExistingPointerObject(outputRegister, inputRegisterPO);
1196 auto & inputRegister = *cv.input->origin();
1197 auto & argumentRegister = *cv.inner;
1198 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1199 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1206 (void)
Set_->CreateRegisterPointerObject(*argument);
1212 const auto lambdaPO =
Set_->CreateFunctionMemoryObject(lambda);
1215 const auto & lambdaOutput = *lambda.
output();
1216 const auto lambdaOutputPO =
Set_->CreateRegisterPointerObject(lambdaOutput);
1217 Constraints_->AddPointerPointeeConstraint(lambdaOutputPO, lambdaPO);
1229 auto & inputRegister = *cv.input->origin();
1230 auto & argumentRegister = *cv.inner;
1231 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1232 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1244 const auto globalPO =
Set_->CreateGlobalMemoryObject(delta, canPoint);
1249 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(resultRegister);
1254 auto & outputRegister = delta.
output();
1255 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
1256 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, globalPO);
1268 auto & inputRegister = *var.input->origin();
1269 auto & argumentRegister = *var.inner;
1270 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1271 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1280 auto & argumentRegister = *var.recref;
1281 (void)
Set_->CreateRegisterPointerObject(argumentRegister);
1293 auto & argumentRegister = *var.recref;
1294 auto & resultRegister = *var.result->origin();
1295 const auto argumentRegisterPO =
Set_->GetRegisterPointerObject(argumentRegister);
1296 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(resultRegister);
1300 auto & outputRegister = *var.output;
1301 Set_->MapRegisterToExistingPointerObject(outputRegister, resultRegisterPO);
1314 auto & inputRegister = *ev.input->origin();
1315 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1317 for (
auto & argument : ev.branchArgument)
1318 Set_->MapRegisterToExistingPointerObject(*argument, inputRegisterPO);
1331 auto & outputRegister = ex.output;
1332 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(*outputRegister);
1334 for (
auto result : ex.branchResult)
1336 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(*result->origin());
1352 auto & inputReg = *loopVar.input->origin();
1353 auto & innerArgumentReg = *loopVar.pre;
1354 const auto inputRegPO =
Set_->GetRegisterPointerObject(inputReg);
1355 const auto innerArgumentRegPO =
Set_->CreateRegisterPointerObject(innerArgumentReg);
1370 auto & innerArgumentReg = *loopVar.pre;
1371 auto & innerResultReg = *loopVar.post->origin();
1372 auto & outputReg = *loopVar.output;
1374 const auto innerArgumentRegPO =
Set_->GetRegisterPointerObject(innerArgumentReg);
1375 const auto innerResultRegPO =
Set_->GetRegisterPointerObject(innerResultReg);
1381 Set_->MapRegisterToExistingPointerObject(outputReg, innerResultRegPO);
1389 for (
size_t i = 0; i < region.
narguments(); i++)
1401 for (
const auto node : traverser)
1411 for (
size_t i = 0; i < node->noutputs(); i++)
1426 for (
size_t n = 0; n < rootRegion.narguments(); n++)
1428 auto & argument = *util::assertedCast<LlvmGraphImport>(rootRegion.argument(n));
1440 const auto importObjectPO =
Set_->CreateImportMemoryObject(argument, canPoint);
1443 const auto importRegisterPO =
Set_->CreateRegisterPointerObject(argument);
1444 Constraints_->AddPointerPointeeConstraint(importRegisterPO, importObjectPO);
1450 for (
size_t n = 0; n < rootRegion.nresults(); n++)
1452 auto & escapedRegister = *rootRegion.result(n)->origin();
1456 const auto escapedRegisterPO =
Set_->GetRegisterPointerObject(escapedRegister);
1457 Constraints_->AddRegisterContentEscapedConstraint(escapedRegisterPO);
1476 Set_ = std::make_unique<PointerObjectSet>();
1530 std::unique_ptr<PointsToGraph>
1536 statistics->StartAndersenStatistics(module.
Rvsdg());
1539 size_t testAllConfigsIterations = 0;
1541 testAllConfigsIterations = std::stoi(testAllConfigsString);
1542 std::optional<size_t> useExactConfig;
1544 useExactConfig = std::stoi(useExactConfigString);
1553 std::pair<std::unique_ptr<PointerObjectSet>, std::unique_ptr<PointerObjectConstraintSet>> copy;
1554 if (testAllConfigsIterations || doubleCheck)
1562 if (useExactConfig.has_value())
1565 config = allConfigs.at(*useExactConfig);
1569 statistics->AddStatisticsFromSolution(*
Set_);
1574 graph.AppendToLabel(
"After Solving with " + config.ToString());
1580 statistics->StopAndersenStatistics();
1584 if (testAllConfigsIterations || doubleCheck)
1587 std::cerr <<
"Double checking Andersen analysis using naive solving" << std::endl;
1590 std::vector<Configuration> configs;
1591 if (testAllConfigsIterations)
1598 const auto iterations = std::max<size_t>(testAllConfigsIterations, 1);
1600 for (
size_t i = 0; i < iterations; i++)
1602 for (
const auto & config : configs)
1605 auto workingCopy = copy.second->Clone();
1609 solvingStats->AddStatisticsFromSolution(*workingCopy.first);
1613 if (doubleCheck && i == 0)
1615 if (workingCopy.first->HasIdenticalSolAs(*
Set_))
1618 <<
" did not produce the same solution as the config " << config.ToString()
1620 JLM_UNREACHABLE(
"Andersen solver double checking uncovered differences!");
1632 std::unique_ptr<PointsToGraph>
1639 std::unique_ptr<PointsToGraph>
1649 std::unordered_map<PointerObjectIndex, PointsToGraph::NodeIndex> memoryNodeMapping;
1651 for (
auto [allocaNode, pointerObjectIndex] : set.
GetAllocaMap())
1653 memoryNodeMapping[pointerObjectIndex] =
1654 pointsToGraph->addNodeForAlloca(*allocaNode, set.
HasEscaped(pointerObjectIndex));
1657 for (
auto [deltaNode, pointerObjectIndex] : set.
GetGlobalMap())
1659 memoryNodeMapping[pointerObjectIndex] =
1660 pointsToGraph->addNodeForDelta(*deltaNode, set.
HasEscaped(pointerObjectIndex));
1663 for (
auto [
import, pointerObjectIndex] : set.
GetImportMap())
1665 memoryNodeMapping[pointerObjectIndex] =
1666 pointsToGraph->addNodeForImport(*
import, set.
HasEscaped(pointerObjectIndex));
1669 for (
auto [lambdaNode, pointerObjectIndex] : set.
GetFunctionMap())
1671 memoryNodeMapping[pointerObjectIndex] =
1672 pointsToGraph->addNodeForLambda(*lambdaNode, set.
HasEscaped(pointerObjectIndex));
1675 for (
auto [mallocNode, pointerObjectIndex] : set.
GetMallocMap())
1677 memoryNodeMapping[pointerObjectIndex] =
1678 pointsToGraph->addNodeForMalloc(*mallocNode, set.
HasEscaped(pointerObjectIndex));
1695 pointsToGraph->markAsTargetsAllExternallyAvailable(ptgNode);
1701 pointsToGraph->addTarget(ptgNode, memoryNodeMapping[targetIdx]);
1708 std::unordered_map<PointerObjectIndex, util::HashSet<const rvsdg::Output *>> outputsInRegister;
1712 outputsInRegister[root].insert(outputNode);
1716 for (
auto & [registerIdx, outputNodes] : outputsInRegister)
1718 const auto ptgNode = pointsToGraph->addNodeForRegisters();
1719 for (
auto outputNode : outputNodes.Items())
1720 pointsToGraph->mapRegisterToNode(*outputNode, ptgNode);
1721 applyPointsToSet(ptgNode, registerIdx);
1725 for (
auto [pointerObjectSetIndex, ptgNode] : memoryNodeMapping)
1727 applyPointsToSet(ptgNode, pointerObjectSetIndex);
1731 return pointsToGraph;
1734 std::unique_ptr<PointsToGraph>
static jlm::util::StatisticsCollector statisticsCollector
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)
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
Interpret pointer as callable function.
PoisonValueOperation class.
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 AnalyzePoison(const rvsdg::SimpleNode &node)
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)
void AnalyzeMemset(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 AnalyzeInsertValue(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 AnalyzeFreeze(const rvsdg::SimpleNode &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.
size_t nnodes(const jlm::rvsdg::Region *region) noexcept