From a5bc5221e0a14d9024f59303030c4bca2e8968a9 Mon Sep 17 00:00:00 2001 From: Andre Kuhlenschmidt Date: Tue, 1 Apr 2025 09:21:12 -0700 Subject: [PATCH 1/3] initial commit --- flang-rt/lib/runtime/extensions.cpp | 3 +++ flang/docs/Intrinsics.md | 21 +++++++++++++++++++ .../flang/Optimizer/Builder/IntrinsicCall.h | 1 + .../Optimizer/Builder/Runtime/Intrinsics.h | 3 +++ flang/include/flang/Runtime/extensions.h | 3 +++ flang/lib/Evaluate/intrinsics.cpp | 2 ++ flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 9 ++++++++ .../Optimizer/Builder/Runtime/Intrinsics.cpp | 7 +++++++ flang/test/Lower/Intrinsics/time.f90 | 17 +++++++++++++++ 9 files changed, 66 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 618e184e28519..a73279e445797 100644 --- a/flang-rt/lib/runtime/extensions.cpp +++ b/flang-rt/lib/runtime/extensions.cpp @@ -272,5 +272,8 @@ void FORTRAN_PROCEDURE_NAME(qsort)(int *array, int *len, int *isize, // PERROR(STRING) void RTNAME(Perror)(const char *str) { perror(str); } +// 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 e885ceca25aad..8b675c33b09d1 100644 --- a/flang/docs/Intrinsics.md +++ b/flang/docs/Intrinsics.md @@ -1091,6 +1091,27 @@ 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). + +#### 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: UNLINK #### Description diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index a4268e74d9a67..29cde05480173 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -429,6 +429,7 @@ struct IntrinsicLibrary { mlir::ArrayRef args); void genSystemClock(llvm::ArrayRef); mlir::Value genTand(mlir::Type, llvm::ArrayRef); + mlir::Value genTime(mlir::Type, llvm::ArrayRef); mlir::Value genTrailz(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genTransfer(mlir::Type, llvm::ArrayRef); 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 57de3f8f05948..47ef4c12ef73a 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 0eb8419491a61..e4f82b7fddb02 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -977,6 +977,8 @@ 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 ad2324d5b5edc..d8ee84db6030d 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -921,6 +921,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, @@ -8428,6 +8429,14 @@ void IntrinsicLibrary::genThreadFenceSystem( builder.create(loc, funcOp, noArgs); } +// TIME +mlir::Value IntrinsicLibrary::genTime(mlir::Type resultType, + llvm::ArrayRef 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..3d818b1228ff3 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(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(loc, builder); + return builder.create(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..eac492572ef89 --- /dev/null +++ b/flang/test/Lower/Intrinsics/time.f90 @@ -0,0 +1,17 @@ +!RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s + +!CHECK-LABEL: func.func @_QPtime_test() -> i64 +function time_test() + Integer(kind=8) :: time_test + + + !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{{.*}} + !CHECK: %[[call_result:.*]] = fir.call @_FortranAtime() + !CHECK-SAME: -> i64 + + !CHECK-DAG: hlfir.assign %[[call_result]] to %[[func_result_decl]]#[[func_result]] : i64, !fir.ref + !CHECK-DAG: %[[load_result:.*]] = fir.load %[[func_result_decl]]#[[func_result]] : !fir.ref + !CHECK: return %[[load_result]] : i64 + time_test = time() +end function time_test From c523af419b437ef336fb4d1f4ff5bbc265f9a19b Mon Sep 17 00:00:00 2001 From: Andre Kuhlenschmidt Date: Tue, 1 Apr 2025 12:07:02 -0700 Subject: [PATCH 2/3] run clang-format --- flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 3d818b1228ff3..3aad0625042a2 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -253,8 +253,8 @@ void fir::runtime::genRename(fir::FirOpBuilder &builder, mlir::Location loc, } /// generate runtime call to time intrinsic -mlir::Value fir::runtime::genTime( - fir::FirOpBuilder &builder, mlir::Location loc) { +mlir::Value fir::runtime::genTime(fir::FirOpBuilder &builder, + mlir::Location loc) { auto func = fir::runtime::getRuntimeFunc(loc, builder); return builder.create(loc, func, std::nullopt).getResult(0); } From 4f930b763133989919cddf55a0528555718fcae4 Mon Sep 17 00:00:00 2001 From: Andre Kuhlenschmidt Date: Tue, 1 Apr 2025 12:09:53 -0700 Subject: [PATCH 3/3] back out formatting change --- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index d8ee84db6030d..2df9349269a69 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -769,7 +769,7 @@ static constexpr IntrinsicHandler handlers[]{ {"perror", &I::genPerror, {{{"string", asBox}}}, - /*isElemental=*/false}, + /*isElemental*/ false}, {"popcnt", &I::genPopcnt}, {"poppar", &I::genPoppar}, {"present",