Allow SymbolUserOpInterface operators to be used in RemoveDeadValues Pass (#117405)
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / ProgressMeter.h
blobc09b9e96045178c24d8573e066dca32520862e4b
1 //===-- ProgressMeter.h -----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_PROGRESSMETER_H
10 #define LLVM_TOOLS_LLVM_EXEGESIS_PROGRESSMETER_H
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include <cassert>
15 #include <chrono>
16 #include <cmath>
17 #include <optional>
18 #include <type_traits>
20 namespace llvm {
21 namespace exegesis {
23 /// Represents `\sum_{i=1..accumulated}{step_i} / accumulated`,
24 /// where `step_i` is the value passed to the `i`-th call to `step()`,
25 /// and `accumulated` is the total number of calls to `step()`.
26 template <typename NumTy, typename DenTy = int> class SimpleMovingAverage {
27 NumTy Accumulated = NumTy(0);
28 DenTy Steps = 0;
30 public:
31 SimpleMovingAverage() = default;
33 SimpleMovingAverage(const SimpleMovingAverage &) = delete;
34 SimpleMovingAverage(SimpleMovingAverage &&) = delete;
35 SimpleMovingAverage &operator=(const SimpleMovingAverage &) = delete;
36 SimpleMovingAverage &operator=(SimpleMovingAverage &&) = delete;
38 inline void step(NumTy Quantity) {
39 Accumulated += Quantity;
40 ++Steps;
43 inline NumTy getAccumulated() const { return Accumulated; }
45 inline DenTy getNumSteps() const { return Steps; }
47 template <typename AvgTy = NumTy>
48 inline std::optional<AvgTy> getAverage() const {
49 if (Steps == 0)
50 return std::nullopt;
51 return AvgTy(Accumulated) / Steps;
55 template <typename ClockTypeTy = std::chrono::steady_clock,
56 typename = std::enable_if_t<ClockTypeTy::is_steady>>
57 class ProgressMeter {
58 public:
59 using ClockType = ClockTypeTy;
60 using TimePointType = std::chrono::time_point<ClockType>;
61 using DurationType = std::chrono::duration<typename ClockType::rep,
62 typename ClockType::period>;
63 using CompetionPercentage = int;
64 using Sec = std::chrono::duration<double, std::chrono::seconds::period>;
66 private:
67 raw_ostream &Out;
68 const int NumStepsTotal;
69 SimpleMovingAverage<DurationType> ElapsedTotal;
71 public:
72 friend class ProgressMeterStep;
73 class ProgressMeterStep {
74 ProgressMeter *P;
75 const TimePointType Begin;
77 public:
78 inline ProgressMeterStep(ProgressMeter *P_)
79 : P(P_), Begin(P ? ProgressMeter<ClockType>::ClockType::now()
80 : TimePointType()) {}
82 inline ~ProgressMeterStep() {
83 if (!P)
84 return;
85 const TimePointType End = ProgressMeter<ClockType>::ClockType::now();
86 P->step(End - Begin);
89 ProgressMeterStep(const ProgressMeterStep &) = delete;
90 ProgressMeterStep(ProgressMeterStep &&) = delete;
91 ProgressMeterStep &operator=(const ProgressMeterStep &) = delete;
92 ProgressMeterStep &operator=(ProgressMeterStep &&) = delete;
95 ProgressMeter(int NumStepsTotal_, raw_ostream &out_ = errs())
96 : Out(out_), NumStepsTotal(NumStepsTotal_) {
97 assert(NumStepsTotal > 0 && "No steps are planned?");
100 ProgressMeter(const ProgressMeter &) = delete;
101 ProgressMeter(ProgressMeter &&) = delete;
102 ProgressMeter &operator=(const ProgressMeter &) = delete;
103 ProgressMeter &operator=(ProgressMeter &&) = delete;
105 private:
106 void step(DurationType Elapsed) {
107 assert((ElapsedTotal.getNumSteps() < NumStepsTotal) && "Step overflow!");
108 assert(Elapsed.count() >= 0 && "Negative time drift detected.");
110 auto [OldProgress, OldEta] = eta();
111 ElapsedTotal.step(Elapsed);
112 auto [NewProgress, NewEta] = eta();
114 if (NewProgress < OldProgress + 1)
115 return;
117 Out << format("Processing... %*d%%", 3, NewProgress);
118 if (NewEta) {
119 int SecondsTotal = std::ceil(NewEta->count());
120 int Seconds = SecondsTotal % 60;
121 int MinutesTotal = SecondsTotal / 60;
123 Out << format(", ETA %02d:%02d", MinutesTotal, Seconds);
125 Out << "\n";
126 Out.flush();
129 inline std::pair<CompetionPercentage, std::optional<Sec>> eta() const {
130 CompetionPercentage Progress =
131 (100 * ElapsedTotal.getNumSteps()) / NumStepsTotal;
133 std::optional<Sec> ETA;
134 if (std::optional<Sec> AverageStepDuration =
135 ElapsedTotal.template getAverage<Sec>())
136 ETA = (NumStepsTotal - ElapsedTotal.getNumSteps()) * *AverageStepDuration;
138 return {Progress, ETA};
142 } // namespace exegesis
143 } // namespace llvm
145 #endif