Skip to content

Commit 230f63f

Browse files
committed
Revert "[Flang][runtime] Distinguish CPU time and elapsed time for cpu_time and system_clock (llvm#96652)"
This reverts commit 7359edb.
1 parent 7359edb commit 230f63f

File tree

2 files changed

+51
-64
lines changed

2 files changed

+51
-64
lines changed

flang/runtime/time-intrinsic.cpp

Lines changed: 51 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,20 @@ template <typename Unused = void> double GetCpuTime(fallback_implementation) {
6464
// clock_gettime is implemented in the pthread library for MinGW.
6565
// Using it here would mean that all programs that link libFortranRuntime are
6666
// required to also link to pthread. Instead, don't use the function.
67-
#undef CLOCKID_CPU_TIME
68-
#undef CLOCKID_ELAPSED_TIME
69-
#else
70-
// Determine what clock to use for CPU time.
71-
#if defined CLOCK_PROCESS_CPUTIME_ID
72-
#define CLOCKID_CPU_TIME CLOCK_PROCESS_CPUTIME_ID
67+
#undef CLOCKID
68+
#elif defined CLOCK_PROCESS_CPUTIME_ID
69+
#define CLOCKID CLOCK_PROCESS_CPUTIME_ID
7370
#elif defined CLOCK_THREAD_CPUTIME_ID
74-
#define CLOCKID_CPU_TIME CLOCK_THREAD_CPUTIME_ID
75-
#else
76-
#undef CLOCKID_CPU_TIME
77-
#endif
78-
79-
// Determine what clock to use for elapsed time.
80-
#if defined CLOCK_MONOTONIC
81-
#define CLOCKID_ELAPSED_TIME CLOCK_MONOTONIC
71+
#define CLOCKID CLOCK_THREAD_CPUTIME_ID
72+
#elif defined CLOCK_MONOTONIC
73+
#define CLOCKID CLOCK_MONOTONIC
8274
#elif defined CLOCK_REALTIME
83-
#define CLOCKID_ELAPSED_TIME CLOCK_REALTIME
75+
#define CLOCKID CLOCK_REALTIME
8476
#else
85-
#undef CLOCKID_ELAPSED_TIME
86-
#endif
77+
#undef CLOCKID
8778
#endif
8879

89-
#ifdef CLOCKID_CPU_TIME
80+
#ifdef CLOCKID
9081
// POSIX implementation using clock_gettime. This is only enabled where
9182
// clock_gettime is available.
9283
template <typename T = int, typename U = struct timespec>
@@ -95,26 +86,17 @@ double GetCpuTime(preferred_implementation,
9586
T ClockId = 0, U *Timespec = nullptr,
9687
decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) {
9788
struct timespec tspec;
98-
if (clock_gettime(CLOCKID_CPU_TIME, &tspec) == 0) {
89+
if (clock_gettime(CLOCKID, &tspec) == 0) {
9990
return tspec.tv_nsec * 1.0e-9 + tspec.tv_sec;
10091
}
10192
// Return some negative value to represent failure.
10293
return -1.0;
10394
}
104-
#endif // CLOCKID_CPU_TIME
95+
#endif
10596

10697
using count_t = std::int64_t;
10798
using unsigned_count_t = std::uint64_t;
10899

109-
// POSIX implementation using clock_gettime where available. The clock_gettime
110-
// result is in nanoseconds, which is converted as necessary to
111-
// - deciseconds for kind 1
112-
// - milliseconds for kinds 2, 4
113-
// - nanoseconds for kinds 8, 16
114-
constexpr unsigned_count_t DS_PER_SEC{10u};
115-
constexpr unsigned_count_t MS_PER_SEC{1'000u};
116-
constexpr unsigned_count_t NS_PER_SEC{1'000'000'000u};
117-
118100
// Computes HUGE(INT(0,kind)) as an unsigned integer value.
119101
static constexpr inline unsigned_count_t GetHUGE(int kind) {
120102
if (kind > 8) {
@@ -123,65 +105,72 @@ static constexpr inline unsigned_count_t GetHUGE(int kind) {
123105
return (unsigned_count_t{1} << ((8 * kind) - 1)) - 1;
124106
}
125107

126-
// Function converts a std::timespec_t into the desired count to
127-
// be returned by the timing functions in accordance with the requested
128-
// kind at the call site.
129-
count_t ConvertTimeSpecToCount(int kind, const std::timespec &tspec) {
130-
const unsigned_count_t huge{GetHUGE(kind)};
131-
unsigned_count_t sec{static_cast<unsigned_count_t>(tspec.tv_sec)};
132-
unsigned_count_t nsec{static_cast<unsigned_count_t>(tspec.tv_nsec)};
133-
if (kind >= 8) {
134-
return (sec * NS_PER_SEC + nsec) % (huge + 1);
135-
} else if (kind >= 2) {
136-
return (sec * MS_PER_SEC + (nsec / (NS_PER_SEC / MS_PER_SEC))) % (huge + 1);
137-
} else { // kind == 1
138-
return (sec * DS_PER_SEC + (nsec / (NS_PER_SEC / DS_PER_SEC))) % (huge + 1);
139-
}
140-
}
141-
142-
// This is the fallback implementation, which should work everywhere.
108+
// This is the fallback implementation, which should work everywhere. Note that
109+
// in general we can't recover after std::clock has reached its maximum value.
143110
template <typename Unused = void>
144111
count_t GetSystemClockCount(int kind, fallback_implementation) {
145-
std::timespec tspec;
146-
147-
if (std::timespec_get(&tspec, TIME_UTC) < 0) {
112+
std::clock_t timestamp{std::clock()};
113+
if (timestamp == static_cast<std::clock_t>(-1)) {
148114
// Return -HUGE(COUNT) to represent failure.
149115
return -static_cast<count_t>(GetHUGE(kind));
150116
}
151-
152-
// Compute the timestamp as seconds plus nanoseconds in accordance
153-
// with the requested kind at the call site.
154-
return ConvertTimeSpecToCount(kind, tspec);
117+
// Convert the timestamp to std::uint64_t with wrap-around. The timestamp is
118+
// most likely a floating-point value (since C'11), so compute the modulus
119+
// carefully when one is required.
120+
constexpr auto maxUnsignedCount{std::numeric_limits<unsigned_count_t>::max()};
121+
if constexpr (std::numeric_limits<std::clock_t>::max() > maxUnsignedCount) {
122+
timestamp -= maxUnsignedCount * std::floor(timestamp / maxUnsignedCount);
123+
}
124+
unsigned_count_t unsignedCount{static_cast<unsigned_count_t>(timestamp)};
125+
// Return the modulus of the unsigned integral count with HUGE(COUNT)+1.
126+
// The result is a signed integer but never negative.
127+
return static_cast<count_t>(unsignedCount % (GetHUGE(kind) + 1));
155128
}
156129

157130
template <typename Unused = void>
158131
count_t GetSystemClockCountRate(int kind, fallback_implementation) {
159-
return kind >= 8 ? NS_PER_SEC : kind >= 2 ? MS_PER_SEC : DS_PER_SEC;
132+
return CLOCKS_PER_SEC;
160133
}
161134

162135
template <typename Unused = void>
163136
count_t GetSystemClockCountMax(int kind, fallback_implementation) {
137+
constexpr auto max_clock_t{std::numeric_limits<std::clock_t>::max()};
164138
unsigned_count_t maxCount{GetHUGE(kind)};
165-
return maxCount;
139+
return max_clock_t <= maxCount ? static_cast<count_t>(max_clock_t)
140+
: static_cast<count_t>(maxCount);
166141
}
167142

168-
#ifdef CLOCKID_ELAPSED_TIME
143+
// POSIX implementation using clock_gettime where available. The clock_gettime
144+
// result is in nanoseconds, which is converted as necessary to
145+
// - deciseconds for kind 1
146+
// - milliseconds for kinds 2, 4
147+
// - nanoseconds for kinds 8, 16
148+
constexpr unsigned_count_t DS_PER_SEC{10u};
149+
constexpr unsigned_count_t MS_PER_SEC{1'000u};
150+
constexpr unsigned_count_t NS_PER_SEC{1'000'000'000u};
151+
152+
#ifdef CLOCKID
169153
template <typename T = int, typename U = struct timespec>
170154
count_t GetSystemClockCount(int kind, preferred_implementation,
171155
// We need some dummy parameters to pass to decltype(clock_gettime).
172156
T ClockId = 0, U *Timespec = nullptr,
173157
decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) {
174158
struct timespec tspec;
175159
const unsigned_count_t huge{GetHUGE(kind)};
176-
if (clock_gettime(CLOCKID_ELAPSED_TIME, &tspec) != 0) {
160+
if (clock_gettime(CLOCKID, &tspec) != 0) {
177161
return -huge; // failure
178162
}
179-
180-
// Compute the timestamp as seconds plus nanoseconds in accordance
181-
// with the requested kind at the call site.
182-
return ConvertTimeSpecToCount(kind, tspec);
163+
unsigned_count_t sec{static_cast<unsigned_count_t>(tspec.tv_sec)};
164+
unsigned_count_t nsec{static_cast<unsigned_count_t>(tspec.tv_nsec)};
165+
if (kind >= 8) {
166+
return (sec * NS_PER_SEC + nsec) % (huge + 1);
167+
} else if (kind >= 2) {
168+
return (sec * MS_PER_SEC + (nsec / (NS_PER_SEC / MS_PER_SEC))) % (huge + 1);
169+
} else { // kind == 1
170+
return (sec * DS_PER_SEC + (nsec / (NS_PER_SEC / DS_PER_SEC))) % (huge + 1);
171+
}
183172
}
184-
#endif // CLOCKID_ELAPSED_TIME
173+
#endif
185174

186175
template <typename T = int, typename U = struct timespec>
187176
count_t GetSystemClockCountRate(int kind, preferred_implementation,

flang/test/Runtime/no-cpp-dep.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,12 @@ int32_t RTNAME(ArgumentCount)();
3030
int32_t RTNAME(GetCommandArgument)(int32_t, const struct Descriptor *,
3131
const struct Descriptor *, const struct Descriptor *);
3232
int32_t RTNAME(GetEnvVariable)();
33-
int64_t RTNAME(SystemClockCount)(int kind);
3433

3534
int main() {
3635
double x = RTNAME(CpuTime)();
3736
RTNAME(ProgramStart)(0, 0, 0, 0);
3837
int32_t c = RTNAME(ArgumentCount)();
3938
int32_t v = RTNAME(GetCommandArgument)(0, 0, 0, 0);
4039
int32_t e = RTNAME(GetEnvVariable)("FOO", 0, 0);
41-
int64_t t = RTNAME(SystemClockCount)(8);
4240
return x + c + v + e;
4341
}

0 commit comments

Comments
 (0)