-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][intrinsics] Implement the time intrinsic #133823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
b4a1195
to
a56da1f
Compare
LGTM. You have some clang-format errors. |
6d8f2ea
to
4f930b7
Compare
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-fir-hlfir Author: Andre Kuhlenschmidt (akuhlens) ChangesThis PR implements the nonstandard intrinsic time. In addition to running the unit tests, I also double checked that the example code works by manually compiling and running it. Full diff: https://github.com/llvm/llvm-project/pull/133823.diff 9 Files Affected:
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<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 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..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",
@@ -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<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..3aad0625042a2 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..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<i64>{{.*}}
+ !CHECK: %[[call_result:.*]] = fir.call @_FortranAtime()
+ !CHECK-SAME: -> i64
+
+ !CHECK-DAG: hlfir.assign %[[call_result]] to %[[func_result_decl]]#[[func_result]] : i64, !fir.ref<i64>
+ !CHECK-DAG: %[[load_result:.*]] = fir.load %[[func_result_decl]]#[[func_result]] : !fir.ref<i64>
+ !CHECK: return %[[load_result]] : i64
+ time_test = time()
+end function time_test
|
This PR implements the nonstandard intrinsic time.
In addition to running the unit tests, I also double checked that the example code works by manually compiling and running it.