| //===--- PerfMonitor.h --- Monitor time spent in scops --------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef PERF_MONITOR_H |
| #define PERF_MONITOR_H |
| |
| #include "polly/CodeGen/IRBuilder.h" |
| |
| namespace polly { |
| |
| class PerfMonitor { |
| public: |
| /// Create a new performance monitor. |
| /// |
| /// @param S The scop for which to generate fine-grained performance |
| /// monitoring information. |
| /// @param M The module for which to generate the performance monitor. |
| PerfMonitor(const Scop &S, llvm::Module *M); |
| |
| /// Initialize the performance monitor. |
| /// |
| /// Ensure that all global variables, functions, and callbacks needed to |
| /// manage the performance monitor are initialized and registered. |
| void initialize(); |
| |
| /// Mark the beginning of a timing region. |
| /// |
| /// @param InsertBefore The instruction before which the timing region starts. |
| void insertRegionStart(llvm::Instruction *InsertBefore); |
| |
| /// Mark the end of a timing region. |
| /// |
| /// @param InsertBefore The instruction before which the timing region starts. |
| void insertRegionEnd(llvm::Instruction *InsertBefore); |
| |
| private: |
| llvm::Module *M; |
| PollyIRBuilder Builder; |
| |
| // The scop to profile against. |
| const Scop &S; |
| |
| /// Indicates if performance profiling is supported on this architecture. |
| bool Supported; |
| |
| /// The cycle counter at the beginning of the program execution. |
| llvm::Value *CyclesTotalStartPtr; |
| |
| /// The total number of cycles spent in the current scop S. |
| llvm::Value *CyclesInCurrentScopPtr; |
| |
| /// The total number of times the current scop S is executed. |
| llvm::Value *TripCountForCurrentScopPtr; |
| |
| /// The total number of cycles spent within scops. |
| llvm::Value *CyclesInScopsPtr; |
| |
| /// The value of the cycle counter at the beginning of the last scop. |
| llvm::Value *CyclesInScopStartPtr; |
| |
| /// A global variable, that keeps track if the performance monitor |
| /// initialization has already been run. |
| llvm::Value *AlreadyInitializedPtr; |
| |
| llvm::Function *insertInitFunction(llvm::Function *FinalReporting); |
| |
| /// Add Function @p to list of global constructors |
| /// |
| /// If no global constructors are available in this current module, insert |
| /// a new list of global constructors containing @p Fn as only global |
| /// constructor. Otherwise, append @p Fn to the list of global constructors. |
| /// |
| /// All functions listed as global constructors are executed before the |
| /// main() function is called. |
| /// |
| /// @param Fn Function to add to global constructors |
| void addToGlobalConstructors(llvm::Function *Fn); |
| |
| /// Add global variables to module. |
| /// |
| /// Insert a set of global variables that are used to track performance, |
| /// into the module (or obtain references to them if they already exist). |
| void addGlobalVariables(); |
| |
| /// Add per-scop tracking to module. |
| /// |
| /// Insert the global variable which is used to track the number of cycles |
| /// this scop runs. |
| void addScopCounter(); |
| |
| /// Get a reference to the intrinsic "{ i64, i32 } @llvm.x86.rdtscp()". |
| /// |
| /// The rdtscp function returns the current value of the processor's |
| /// time-stamp counter as well as the current CPU identifier. On modern x86 |
| /// systems, the returned value is independent of the dynamic clock frequency |
| /// and consistent across multiple cores. It can consequently be used to get |
| /// accurate and low-overhead timing information. Even though the counter is |
| /// wrapping, it can be reliably used even for measuring longer time |
| /// intervals, as on a 1 GHz processor the counter only wraps every 545 years. |
| /// |
| /// The RDTSCP instruction is "pseudo" serializing: |
| /// |
| /// "“The RDTSCP instruction waits until all previous instructions have been |
| /// executed before reading the counter. However, subsequent instructions may |
| /// begin execution before the read operation is performed.” |
| /// |
| /// To ensure that no later instructions are scheduled before the RDTSCP |
| /// instruction it is often recommended to schedule a cpuid call after the |
| /// RDTSCP instruction. We do not do this yet, trading some imprecision in |
| /// our timing for a reduced overhead in our timing. |
| /// |
| /// @returns A reference to the declaration of @llvm.x86.rdtscp. |
| llvm::Function *getRDTSCP(); |
| |
| /// Get a reference to "int atexit(void (*function)(void))" function. |
| /// |
| /// This function allows to register function pointers that must be executed |
| /// when the program is terminated. |
| /// |
| /// @returns A reference to @atexit(). |
| llvm::Function *getAtExit(); |
| |
| /// Create function "__polly_perf_final_reporting". |
| /// |
| /// This function finalizes the performance measurements and prints the |
| /// results to stdout. It is expected to be registered with 'atexit()'. |
| llvm::Function *insertFinalReporting(); |
| |
| /// Append Scop reporting data to "__polly_perf_final_reporting". |
| /// |
| /// This function appends the current scop (S)'s information to the final |
| /// printing function. |
| void AppendScopReporting(); |
| }; |
| } // namespace polly |
| |
| #endif |