Mercurial > hg > CbC > CbC_llvm
view flang/runtime/time-intrinsic.cpp @ 223:5f17cb93ff66 llvm-original
LLVM13 (2021/7/18)
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 18 Jul 2021 22:43:00 +0900 |
parents | |
children | c4bab56944e8 |
line wrap: on
line source
//===-- runtime/time-intrinsic.cpp ----------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // Implements time-related intrinsic subroutines. #include "time-intrinsic.h" #include <ctime> // CPU_TIME (Fortran 2018 16.9.57) // We can use std::clock() from the <ctime> header as a fallback implementation // that should be available everywhere. This may not provide the best resolution // and is particularly troublesome on (some?) POSIX systems where CLOCKS_PER_SEC // is defined as 10^6 regardless of the actual precision of std::clock(). // Therefore, we will usually prefer platform-specific alternatives when they // are available. // // We can use SFINAE to choose a platform-specific alternative. To do so, we // introduce a helper function template, whose overload set will contain only // implementations relying on interfaces which are actually available. Each // overload will have a dummy parameter whose type indicates whether or not it // should be preferred. Any other parameters required for SFINAE should have // default values provided. namespace { // Types for the dummy parameter indicating the priority of a given overload. // We will invoke our helper with an integer literal argument, so the overload // with the highest priority should have the type int. using fallback_implementation = double; using preferred_implementation = int; // This is the fallback implementation, which should work everywhere. template <typename Unused = void> double getCpuTime(fallback_implementation) { std::clock_t timestamp{std::clock()}; if (timestamp != std::clock_t{-1}) { return static_cast<double>(timestamp) / CLOCKS_PER_SEC; } // Return some negative value to represent failure. return -1.0; } // POSIX implementation using clock_gettime. This is only enabled if // clock_gettime is available. template <typename T = int, typename U = struct timespec> double getCpuTime(preferred_implementation, // We need some dummy parameters to pass to decltype(clock_gettime). T ClockId = 0, U *Timespec = nullptr, decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) { #if defined CLOCK_THREAD_CPUTIME_ID #define CLOCKID CLOCK_THREAD_CPUTIME_ID #elif defined CLOCK_PROCESS_CPUTIME_ID #define CLOCKID CLOCK_PROCESS_CPUTIME_ID #elif defined CLOCK_MONOTONIC #define CLOCKID CLOCK_MONOTONIC #else #define CLOCKID CLOCK_REALTIME #endif struct timespec tspec; if (clock_gettime(CLOCKID, &tspec) == 0) { return tspec.tv_nsec * 1.0e-9 + tspec.tv_sec; } // Return some negative value to represent failure. return -1.0; } } // anonymous namespace namespace Fortran::runtime { extern "C" { double RTNAME(CpuTime)() { return getCpuTime(0); } } // extern "C" } // namespace Fortran::runtime