llvm.org GIT mirror llvm / 93684e3
[NFC][llvm-exegesis] Refactor Analysis::SchedClassCluster::measurementsMatch() Summary: The diff looks scary but it really isn't: 1. I moved the check for the number of measurements into `SchedClassClusterCentroid::validate()` 2. While there, added a check that we can only have a single inverse throughput measurement. I missed that when adding it initially. 3. In `Analysis::SchedClassCluster::measurementsMatch()` is called with the current LLVM values from schedule class and the values from Centroid. 3.1. The values from centroid we can already get from `SchedClassClusterCentroid::getAsPoint()`. This isn't 100% a NFC, because previously for inverse throughput we used `min()`. I have asked whether i have done that correctly in https://reviews.llvm.org/D57647?id=184939#inline-510384 but did not hear back. I think `avg()` should be used too, thus it is a fix. 3.2. Finally, refactor the computation of the LLVM-specified values into `Analysis::SchedClassCluster::getSchedClassPoint()` I will need that function for [[ https://bugs.llvm.org/show_bug.cgi?id=41275 | PR41275 ]] Reviewers: courbet, gchatelet Reviewed By: courbet Subscribers: tschuett, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59951 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357245 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Lebedev 1 year, 8 months ago
4 changed file(s) with 91 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
459459 return 0;
460460 }
461461
462 bool Analysis::SchedClassCluster::measurementsMatch(
463 const llvm::MCSubtargetInfo &STI, const ResolvedSchedClass &RSC,
464 const InstructionBenchmarkClustering &Clustering,
465 const double AnalysisInconsistencyEpsilonSquared_) const {
466 ArrayRef Representative = Centroid.getStats();
462 std::vector Analysis::SchedClassCluster::getSchedClassPoint(
463 InstructionBenchmark::ModeE Mode, const llvm::MCSubtargetInfo &STI,
464 const ResolvedSchedClass &RSC,
465 ArrayRef Representative) const {
467466 const size_t NumMeasurements = Representative.size();
468 std::vector ClusterCenterPoint(NumMeasurements);
467
469468 std::vector SchedClassPoint(NumMeasurements);
470 // Latency case.
471 assert(!Clustering.getPoints().empty());
472 const InstructionBenchmark::ModeE Mode = Clustering.getPoints()[0].Mode;
469
473470 if (Mode == InstructionBenchmark::Latency) {
474 if (NumMeasurements != 1) {
475 llvm::errs()
476 << "invalid number of measurements in latency mode: expected 1, got "
477 << NumMeasurements << "\n";
478 return false;
479 }
471 assert(NumMeasurements == 1 && "Latency is a single measure.");
472 BenchmarkMeasure &LatencyMeasure = SchedClassPoint[0];
473
480474 // Find the latency.
481 SchedClassPoint[0].PerInstructionValue = 0.0;
475 LatencyMeasure.PerInstructionValue = 0.0;
476
482477 for (unsigned I = 0; I < RSC.SCDesc->NumWriteLatencyEntries; ++I) {
483478 const llvm::MCWriteLatencyEntry *const WLE =
484479 STI.getWriteLatencyEntry(RSC.SCDesc, I);
485 SchedClassPoint[0].PerInstructionValue =
486 std::max(SchedClassPoint[0].PerInstructionValue, WLE->Cycles);
487 }
488 ClusterCenterPoint[0].PerInstructionValue = Representative[0].avg();
480 LatencyMeasure.PerInstructionValue =
481 std::max(LatencyMeasure.PerInstructionValue, WLE->Cycles);
482 }
489483 } else if (Mode == InstructionBenchmark::Uops) {
490 for (int I = 0, E = Representative.size(); I < E; ++I) {
491 const auto Key = Representative[I].key();
484 for (const auto &I : llvm::zip(SchedClassPoint, Representative)) {
485 BenchmarkMeasure &Measure = std::get<0>(I);
486 const PerInstructionStats &Stats = std::get<1>(I);
487
488 StringRef Key = Stats.key();
492489 uint16_t ProcResIdx = findProcResIdx(STI, Key);
493490 if (ProcResIdx > 0) {
494491 // Find the pressure on ProcResIdx `Key`.
498495 [ProcResIdx](const std::pair &WPR) {
499496 return WPR.first == ProcResIdx;
500497 });
501 SchedClassPoint[I].PerInstructionValue =
498 Measure.PerInstructionValue =
502499 ProcResPressureIt == RSC.IdealizedProcResPressure.end()
503500 ? 0.0
504501 : ProcResPressureIt->second;
505502 } else if (Key == "NumMicroOps") {
506 SchedClassPoint[I].PerInstructionValue = RSC.SCDesc->NumMicroOps;
503 Measure.PerInstructionValue = RSC.SCDesc->NumMicroOps;
507504 } else {
508505 llvm::errs() << "expected `key` to be either a ProcResIdx or a ProcRes "
509506 "name, got "
510507 << Key << "\n";
511 return false;
508 return {};
512509 }
513 ClusterCenterPoint[I].PerInstructionValue = Representative[I].avg();
514510 }
515511 } else if (Mode == InstructionBenchmark::InverseThroughput) {
516 for (int I = 0, E = Representative.size(); I < E; ++I) {
517 SchedClassPoint[I].PerInstructionValue =
518 MCSchedModel::getReciprocalThroughput(STI, *RSC.SCDesc);
519 ClusterCenterPoint[I].PerInstructionValue = Representative[I].min();
520 }
512 assert(NumMeasurements == 1 && "Inverse Throughput is a single measure.");
513 BenchmarkMeasure &RThroughputMeasure = SchedClassPoint[0];
514
515 RThroughputMeasure.PerInstructionValue =
516 MCSchedModel::getReciprocalThroughput(STI, *RSC.SCDesc);
521517 } else {
522518 llvm_unreachable("unimplemented measurement matching mode");
519 }
520
521 return SchedClassPoint;
522 }
523
524 bool Analysis::SchedClassCluster::measurementsMatch(
525 const llvm::MCSubtargetInfo &STI, const ResolvedSchedClass &RSC,
526 const InstructionBenchmarkClustering &Clustering,
527 const double AnalysisInconsistencyEpsilonSquared_) const {
528 assert(!Clustering.getPoints().empty());
529 const InstructionBenchmark::ModeE Mode = Clustering.getPoints()[0].Mode;
530
531 if (!Centroid.validate(Mode))
523532 return false;
524 }
533
534 const std::vector ClusterCenterPoint =
535 Centroid.getAsPoint();
536
537 const std::vector SchedClassPoint =
538 getSchedClassPoint(Mode, STI, RSC, Centroid.getStats());
539 if (SchedClassPoint.empty())
540 return false; // In Uops mode validate() may not be enough.
541
542 assert(ClusterCenterPoint.size() == SchedClassPoint.size() &&
543 "Expected measured/sched data dimensions to match.");
544
525545 return Clustering.isNeighbour(ClusterCenterPoint, SchedClassPoint,
526546 AnalysisInconsistencyEpsilonSquared_);
527547 }
7878 // Return the cluster centroid.
7979 const SchedClassClusterCentroid &getCentroid() const { return Centroid; }
8080
81 std::vector
82 getSchedClassPoint(InstructionBenchmark::ModeE Mode,
83 const llvm::MCSubtargetInfo &STI,
84 const ResolvedSchedClass &SC,
85 ArrayRef Representative) const;
86
8187 // Returns true if the cluster representative measurements match that of SC.
8288 bool
8389 measurementsMatch(const llvm::MCSubtargetInfo &STI,
362362 return ClusterCenterPoint;
363363 }
364364
365 bool SchedClassClusterCentroid::validate(
366 InstructionBenchmark::ModeE Mode) const {
367 size_t NumMeasurements = Representative.size();
368 switch (Mode) {
369 case InstructionBenchmark::Latency:
370 if (NumMeasurements != 1) {
371 llvm::errs()
372 << "invalid number of measurements in latency mode: expected 1, got "
373 << NumMeasurements << "\n";
374 return false;
375 }
376 break;
377 case InstructionBenchmark::Uops:
378 // Can have many measurements.
379 break;
380 case InstructionBenchmark::InverseThroughput:
381 if (NumMeasurements != 1) {
382 llvm::errs() << "invalid number of measurements in inverse throughput "
383 "mode: expected 1, got "
384 << NumMeasurements << "\n";
385 return false;
386 }
387 break;
388 default:
389 llvm_unreachable("unimplemented measurement matching mode");
390 return false;
391 }
392
393 return true; // All good.
394 }
395
365396 } // namespace exegesis
366397 } // namespace llvm
155155
156156 void addPoint(ArrayRef Point);
157157
158 bool validate(InstructionBenchmark::ModeE Mode) const;
159
158160 private:
159161 // Measurement stats for the points in the SchedClassCluster.
160162 std::vector Representative;