[flang-commits] [flang] [llvm] [flang][flang-rt] Add support for non-standard TIMEF intrinsic (PR #185377)
via flang-commits
flang-commits at lists.llvm.org
Mon Mar 9 03:43:40 PDT 2026
https://github.com/NimishMishra updated https://github.com/llvm/llvm-project/pull/185377
>From 22bf5067bd20110e3d09820d99453206cf731dd4 Mon Sep 17 00:00:00 2001
From: NimishMishra <neelam.nimish at gmail.com>
Date: Mon, 9 Mar 2026 12:37:26 +0530
Subject: [PATCH 1/3] [flang][flang-rt] Implement non-standard TIMEF intrinsic
---
flang-rt/lib/runtime/extensions.cpp | 13 +++++++++++++
flang-rt/unittests/Runtime/Time.cpp | 14 ++++++++++++++
.../flang/Optimizer/Builder/IntrinsicCall.h | 1 +
.../flang/Optimizer/Builder/Runtime/Intrinsics.h | 3 +++
flang/include/flang/Runtime/time-intrinsic.h | 3 +++
flang/lib/Evaluate/intrinsics.cpp | 1 +
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 8 ++++++++
.../lib/Optimizer/Builder/Runtime/Intrinsics.cpp | 8 ++++++++
flang/test/Lower/Intrinsics/timef.f90 | 15 +++++++++++++++
9 files changed, 66 insertions(+)
create mode 100644 flang/test/Lower/Intrinsics/timef.f90
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index b06b9eabe2c60..126cadadc1619 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -413,6 +413,19 @@ double RTNAME(Dsecnds)(double *refTime, const char *sourceFile, int line) {
// GNU extension function TIME()
std::int64_t RTNAME(time)() { return time(nullptr); }
+// Intel extension function TIMEF()
+// Returns number of seconds that have elapsed since the first time
+// TIMEF was called. For the first call, it returns 0.
+double RTNAME(Timef)() {
+ static double first = -1;
+ if(first < 0){
+ first = time(nullptr);
+ return 0;
+ }
+ else
+ return time(nullptr) - first;
+}
+
// MCLOCK: returns accumulated CPU time in ticks
std::int32_t FORTRAN_PROCEDURE_NAME(mclock)() { return std::clock(); }
diff --git a/flang-rt/unittests/Runtime/Time.cpp b/flang-rt/unittests/Runtime/Time.cpp
index 548c0834e34a3..be668e9a8f3c2 100644
--- a/flang-rt/unittests/Runtime/Time.cpp
+++ b/flang-rt/unittests/Runtime/Time.cpp
@@ -31,6 +31,20 @@ TEST(TimeIntrinsics, CpuTime) {
}
}
+TEST(TimeIntrinsics, Timef) {
+ // We can't really test that we get the "right" result for Timef, but we
+ // can have a smoke test to see that we get something reasonable on the
+ // platforms where we expect to support it.
+ double start{RTNAME(Timef)()};
+ ASSERT_GE(start, 0.0);
+
+ // Loop until we get a different value from Timef
+ for (double end = start; end == start; end = RTNAME(CpuTime)()) {
+ ASSERT_GE(end, 0.0);
+ ASSERT_GE(end, start);
+ }
+}
+
using count_t = std::int64_t;
TEST(TimeIntrinsics, SystemClock) {
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index 3ef4045518cc4..ac1fdd8f27db9 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -214,6 +214,7 @@ struct IntrinsicLibrary {
void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
fir::ExtendedValue genEtime(std::optional<mlir::Type>,
mlir::ArrayRef<fir::ExtendedValue> args);
+ mlir::Value genTimef(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genExtendsTypeOf(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
index 1f751827309a4..d6f0f5051e219 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
@@ -82,6 +82,9 @@ mlir::Value genSecnds(fir::FirOpBuilder &builder, mlir::Location loc,
/// generate time runtime call
mlir::Value genTime(fir::FirOpBuilder &builder, mlir::Location loc);
+/// generate timef runtime call
+mlir::Value genTimef(fir::FirOpBuilder &builder, mlir::Location loc);
+
/// generate runtime call to transfer intrinsic with no size argument
void genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value sourceBox,
diff --git a/flang/include/flang/Runtime/time-intrinsic.h b/flang/include/flang/Runtime/time-intrinsic.h
index 80490a17e4559..4df151451d735 100644
--- a/flang/include/flang/Runtime/time-intrinsic.h
+++ b/flang/include/flang/Runtime/time-intrinsic.h
@@ -26,6 +26,9 @@ extern "C" {
// real kind.
double RTNAME(CpuTime)();
+// Interface for Timef()
+double RTNAME(Timef)();
+
// Interface for the SYSTEM_CLOCK intrinsic. We break it up into 3 distinct
// function calls, one for each of SYSTEM_CLOCK's optional output arguments.
// Lowering converts the results to the types of the actual arguments,
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 2ae1c478489c4..2082d2dd58c16 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1030,6 +1030,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
IntrinsicClass::transformationalFunction},
{"time", {}, TypePattern{IntType, KindCode::exactKind, 8}, Rank::scalar,
IntrinsicClass::transformationalFunction},
+ {"timef", {}, TypePattern{RealType, KindCode::exactKind, 8}, Rank::scalar},
{"tiny",
{{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required,
common::Intent::In,
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 9036d65f138d3..79433c56a0ee0 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -797,6 +797,7 @@ static constexpr IntrinsicHandler handlers[]{
{"team", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"time", &I::genTime, {}, /*isElemental=*/false},
+ {"timef", &I::genTimef, {}, /*isElemental=*/false},
{"tokenize",
&I::genTokenize,
{{{"string", asAddr},
@@ -8255,6 +8256,13 @@ IntrinsicLibrary::genThisImage(mlir::Type resultType,
return builder.createConvert(loc, resultType, res);
}
+// TIMEF
+mlir::Value IntrinsicLibrary::genTimef(mlir::Type resultType,
+ llvm::ArrayRef<mlir::Value> args) {
+ assert(args.empty() && "timef does not accept any args");
+ return fir::runtime::genTimef(builder, loc);
+}
+
// TRAILZ
mlir::Value IntrinsicLibrary::genTrailz(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
index a5f16f89b260a..dc87638937d7a 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
@@ -327,6 +327,14 @@ mlir::Value fir::runtime::genTime(fir::FirOpBuilder &builder,
.getResult(0);
}
+/// generate runtime call to timef intrinsic
+mlir::Value fir::runtime::genTimef(fir::FirOpBuilder &builder,
+ mlir::Location loc) {
+ auto func = fir::runtime::getRuntimeFunc<mkRTKey(Timef)>(loc, builder);
+ return fir::CallOp::create(builder, loc, func, mlir::ValueRange{})
+ .getResult(0);
+}
+
/// generate runtime call to transfer intrinsic with no size argument
void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value sourceBox,
diff --git a/flang/test/Lower/Intrinsics/timef.f90 b/flang/test/Lower/Intrinsics/timef.f90
new file mode 100644
index 0000000000000..5ec4a71e49d29
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/timef.f90
@@ -0,0 +1,15 @@
+!RUN: bbc -emit-hlfir %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+
+subroutine test_timef(t)
+ real(8) :: t
+ t = timef()
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_timef(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f64> {fir.bindc_name = "t"}) {
+! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] arg {{[0-9]+}} {uniq_name = "_QFtest_timefEt"} : (!fir.ref<f64>, !fir.dscope) -> (!fir.ref<f64>, !fir.ref<f64>)
+! CHECK: %[[VAL_4:.*]] = fir.call @_FortranATimef() fastmath<contract> : () -> f64
+! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f64, !fir.ref<f64>
+! CHECK: return
+! CHECK: }
>From b0679b775022858d3ef95cf6ae80f60002379932 Mon Sep 17 00:00:00 2001
From: NimishMishra <neelam.nimish at gmail.com>
Date: Mon, 9 Mar 2026 13:45:30 +0530
Subject: [PATCH 2/3] Add documentation changes
---
flang-rt/lib/runtime/extensions.cpp | 15 +++++++--------
flang/docs/Intrinsics.md | 13 +++++++++++++
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 126cadadc1619..3ffeec511da31 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -414,16 +414,15 @@ double RTNAME(Dsecnds)(double *refTime, const char *sourceFile, int line) {
std::int64_t RTNAME(time)() { return time(nullptr); }
// Intel extension function TIMEF()
-// Returns number of seconds that have elapsed since the first time
+// Returns number of seconds that have elapsed since the first time
// TIMEF was called. For the first call, it returns 0.
double RTNAME(Timef)() {
- static double first = -1;
- if(first < 0){
- first = time(nullptr);
- return 0;
- }
- else
- return time(nullptr) - first;
+ static double first = -1;
+ if (first < 0) {
+ first = time(nullptr);
+ return 0;
+ } else
+ return time(nullptr) - first;
}
// MCLOCK: returns accumulated CPU time in ticks
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index 615d2746284ab..c6d2f92ef5d1a 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -1215,6 +1215,19 @@ PROGRAM example_time
END PROGRAM
```
+### Non-Standard Intrinsics: TIMEF
+
+#### Description
+`TIMEF` returns the number of seconds that have
+elapsed since the first time TIMEF was called.
+The first time it is called, TIMEF returns 0.
+
+#### Usage and Info
+
+- **Standard:** Intel extension
+- **Class:** function
+- **Syntax:** `RESULT = TIMEF()`
+
### Non-Standard Intrinsics: UNLINK
#### Description
>From 887c54b5df89647cb2dc6115a834d04ea5665866 Mon Sep 17 00:00:00 2001
From: NimishMishra <42909663+NimishMishra at users.noreply.github.com>
Date: Mon, 9 Mar 2026 03:43:31 -0700
Subject: [PATCH 3/3] Fix typo
---
flang-rt/unittests/Runtime/Time.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang-rt/unittests/Runtime/Time.cpp b/flang-rt/unittests/Runtime/Time.cpp
index be668e9a8f3c2..795c1ee1315b4 100644
--- a/flang-rt/unittests/Runtime/Time.cpp
+++ b/flang-rt/unittests/Runtime/Time.cpp
@@ -39,7 +39,7 @@ TEST(TimeIntrinsics, Timef) {
ASSERT_GE(start, 0.0);
// Loop until we get a different value from Timef
- for (double end = start; end == start; end = RTNAME(CpuTime)()) {
+ for (double end = start; end == start; end = RTNAME(Timef)()) {
ASSERT_GE(end, 0.0);
ASSERT_GE(end, start);
}
More information about the flang-commits
mailing list