[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 01:51:02 PDT 2026


https://github.com/NimishMishra created https://github.com/llvm/llvm-project/pull/185377

TIMEF is an Intel intrinsic that returns the number of seconds since the first time it is called, or zero. This PR adds support for the same. 

Link to Intel's documentation: https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2025-3/timef.html

>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/2] [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/2] 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



More information about the flang-commits mailing list