[flang] [llvm] [flang][intrinsics] Implement the time intrinsic (PR #133823)
Andre Kuhlenschmidt via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 31 16:20:59 PDT 2025
https://github.com/akuhlens created https://github.com/llvm/llvm-project/pull/133823
This PR implements the nonstandard intrinsic time.
>From 1dbdd5586c181704c4c2ed071ad4dfdcbf90fea2 Mon Sep 17 00:00:00 2001
From: Andre Kuhlenschmidt <akuhlenschmi at nvidia.com>
Date: Mon, 31 Mar 2025 11:21:42 -0700
Subject: [PATCH] initial commit
---
flang-rt/lib/runtime/extensions.cpp | 5 ++++
flang/docs/Intrinsics.md | 23 +++++++++++++++++++
.../flang/Optimizer/Builder/IntrinsicCall.h | 1 +
.../Optimizer/Builder/Runtime/Intrinsics.h | 3 +++
flang/include/flang/Runtime/extensions.h | 3 +++
flang/lib/Evaluate/intrinsics.cpp | 1 +
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 11 +++++++++
.../Optimizer/Builder/Runtime/Intrinsics.cpp | 7 ++++++
flang/test/Lower/Intrinsics/time.f90 | 20 ++++++++++++++++
9 files changed, 74 insertions(+)
create mode 100644 flang/test/Lower/Intrinsics/time.f90
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 7e9e512778a75..0a6ba6d38f828 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -268,5 +268,10 @@ void FORTRAN_PROCEDURE_NAME(qsort)(int *array, int *len, int *isize,
qsort(array, *len, *isize, compar);
}
+// GNU extension function TIME()
+std::int64_t RTNAME(time)() {
+ return time(nullptr);
+}
+
} // namespace Fortran::runtime
} // extern "C"
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index c5c45c2f87d35..38d4e3988a869 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -1085,6 +1085,29 @@ end program rename_proc
This intrinsic is an alias for `CPU_TIME`: supporting both a subroutine and a
function form.
+### Non-Standard Intrinsics: TIME
+
+#### Description
+`TIME()` returns the current time of the system as a INTEGER(8).
+
+FIXME: Add portability warning.
+
+#### Usage and Info
+
+- **Standard:** GNU extension
+- **Class:** function
+- **Syntax:** `RESULT = TIME()`
+
+#### Example
+```Fortran
+PROGRAM example_time
+ print *, TIME()
+ print *, TIME()
+ call SLEEP(10)
+ print *, TIME()
+END PROGRAM
+```
+
### Non-standard Intrinsics: LNBLNK
This intrinsic is an alias for `LEN_TRIM`, without the optional KIND argument.
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index cdbb78224e3b4..9aa4c3a6690b4 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -428,6 +428,7 @@ struct IntrinsicLibrary {
mlir::ArrayRef<fir::ExtendedValue> args);
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
+ mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genTransfer(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 51d2dc82f98ae..2e5adf6bd0ab7 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
@@ -65,6 +65,9 @@ void genRandomSeed(fir::FirOpBuilder &, mlir::Location, mlir::Value size,
void genRename(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value path1, mlir::Value path2, mlir::Value status);
+/// generate time runtime call
+mlir::Value genTime(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/extensions.h b/flang/include/flang/Runtime/extensions.h
index 4e96f253a6c2c..e2da65c98487f 100644
--- a/flang/include/flang/Runtime/extensions.h
+++ b/flang/include/flang/Runtime/extensions.h
@@ -65,6 +65,9 @@ std::int64_t RTNAME(Signal)(std::int64_t number, void (*handler)(int));
// GNU extension subroutine SLEEP(SECONDS)
void RTNAME(Sleep)(std::int64_t seconds);
+// GNU extension function TIME()
+std::int64_t RTNAME(time)();
+
// GNU extension function ACCESS(NAME, MODE)
// TODO: not supported on Windows
#ifndef _WIN32
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index ae77dc8d11f44..81852cfb4ff02 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -975,6 +975,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
DefaultInt, Rank::vector, IntrinsicClass::transformationalFunction},
{"this_image", {OptionalTEAM}, DefaultInt, Rank::scalar,
IntrinsicClass::transformationalFunction},
+ {"time", {}, TypePattern{IntType, KindCode::exactKind, 8}, Rank::scalar, IntrinsicClass::transformationalFunction},
{"tiny",
{{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required,
common::Intent::In, {ArgFlag::canBeMoldNull}}},
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index e1e2fa875bff3..d4f380379930b 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -904,6 +904,7 @@ static constexpr IntrinsicHandler handlers[]{
{"threadfence", &I::genThreadFence, {}, /*isElemental=*/false},
{"threadfence_block", &I::genThreadFenceBlock, {}, /*isElemental=*/false},
{"threadfence_system", &I::genThreadFenceSystem, {}, /*isElemental=*/false},
+ {"time", &I::genTime, {}, /*isElemental=*/false},
{"trailz", &I::genTrailz},
{"transfer",
&I::genTransfer,
@@ -8371,6 +8372,16 @@ void IntrinsicLibrary::genThreadFenceSystem(
builder.create<fir::CallOp>(loc, funcOp, noArgs);
}
+// TIME
+mlir::Value
+IntrinsicLibrary::genTime(mlir::Type resultType,
+ llvm::ArrayRef<mlir::Value> args) {
+ assert(args.size() == 0);
+ return builder.createConvert(loc, resultType,
+ fir::runtime::genTime(builder, loc));
+}
+
+
// TRIM
fir::ExtendedValue
IntrinsicLibrary::genTrim(mlir::Type resultType,
diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
index 2f46e7605fe91..183eb03768775 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
@@ -252,6 +252,13 @@ void fir::runtime::genRename(fir::FirOpBuilder &builder, mlir::Location loc,
builder.create<fir::CallOp>(loc, runtimeFunc, args);
}
+/// generate runtime call to time intrinsic
+mlir::Value fir::runtime::genTime(fir::FirOpBuilder &builder,
+ mlir::Location loc) {
+ auto func = fir::runtime::getRuntimeFunc<mkRTKey(time)>(loc, builder);
+ return builder.create<fir::CallOp>(loc, func, std::nullopt).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/time.f90 b/flang/test/Lower/Intrinsics/time.f90
new file mode 100644
index 0000000000000..950a801fc275b
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/time.f90
@@ -0,0 +1,20 @@
+!RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+
+!CHECK-LABEL: func.func @_QPhostnm_test
+!CHECK-SAME: %[[dummyHn:.*]]: !fir.boxchar<1> {fir.bindc_name = "hn"}) -> i32 {
+function time_test())
+ Integer, kind(8) :: time_test
+
+ ! Check that _FortranAHostnm is called with boxed char 255, some other char
+ ! string of variable length (source file path) and some integer (source line)
+ !CHECK-DAG: %[[func_result:.*]] = fir.alloca i64 {bindc_name = "time_test", uniq_name = "_QFtime_testEtime_test"}
+ !CHECK-DAG: %[[func_result_decl:.*]]:{{.*}} = hlfir.declare %[[func_result]] {uniq_name = "_QFtime_testEtime_test"} : {{.*}}fir.ref<i64>{{.*}}
+ !CHECK: %[[call_result:.*]] = fir.call @_FortranAtime()
+ !CHECK-SAME: -> i64
+
+ ! Check _FortranAHostnm result code handling
+ !CHECK-DAG: hlfir.assign %[[call_result]] to %[[func_result_decl]]{{.*}}i64{{.*}}
+ !CHECK-DAG: %[[load_result:.*]] = fir.load %[[func_result_decl]]{{.*}}i64{{.*}}
+ !CHECK: return %[[load_result]] : i64
+ time_test = time()
+end function time_test
More information about the llvm-commits
mailing list