Skip to content

Commit b11eece

Browse files
authored
[flang][intrinsics] Implement the time intrinsic (#133823)
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.
1 parent 996cf5d commit b11eece

File tree

9 files changed

+67
-1
lines changed

9 files changed

+67
-1
lines changed

flang-rt/lib/runtime/extensions.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,5 +272,8 @@ void FORTRAN_PROCEDURE_NAME(qsort)(int *array, int *len, int *isize,
272272
// PERROR(STRING)
273273
void RTNAME(Perror)(const char *str) { perror(str); }
274274

275+
// GNU extension function TIME()
276+
std::int64_t RTNAME(time)() { return time(nullptr); }
277+
275278
} // namespace Fortran::runtime
276279
} // extern "C"

flang/docs/Intrinsics.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,27 @@ end program rename_proc
10911091
This intrinsic is an alias for `CPU_TIME`: supporting both a subroutine and a
10921092
function form.
10931093

1094+
### Non-Standard Intrinsics: TIME
1095+
1096+
#### Description
1097+
`TIME()` returns the current time of the system as a INTEGER(8).
1098+
1099+
#### Usage and Info
1100+
1101+
- **Standard:** GNU extension
1102+
- **Class:** function
1103+
- **Syntax:** `RESULT = TIME()`
1104+
1105+
#### Example
1106+
```Fortran
1107+
PROGRAM example_time
1108+
print *, TIME()
1109+
print *, TIME()
1110+
call SLEEP(10)
1111+
print *, TIME()
1112+
END PROGRAM
1113+
```
1114+
10941115
### Non-Standard Intrinsics: UNLINK
10951116

10961117
#### Description

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ struct IntrinsicLibrary {
429429
mlir::ArrayRef<fir::ExtendedValue> args);
430430
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
431431
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
432+
mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
432433
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
433434
fir::ExtendedValue genTransfer(mlir::Type,
434435
llvm::ArrayRef<fir::ExtendedValue>);

flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ void genRandomSeed(fir::FirOpBuilder &, mlir::Location, mlir::Value size,
6565
void genRename(fir::FirOpBuilder &builder, mlir::Location loc,
6666
mlir::Value path1, mlir::Value path2, mlir::Value status);
6767

68+
/// generate time runtime call
69+
mlir::Value genTime(fir::FirOpBuilder &builder, mlir::Location loc);
70+
6871
/// generate runtime call to transfer intrinsic with no size argument
6972
void genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
7073
mlir::Value resultBox, mlir::Value sourceBox,

flang/include/flang/Runtime/extensions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ std::int64_t RTNAME(Signal)(std::int64_t number, void (*handler)(int));
6565
// GNU extension subroutine SLEEP(SECONDS)
6666
void RTNAME(Sleep)(std::int64_t seconds);
6767

68+
// GNU extension function TIME()
69+
std::int64_t RTNAME(time)();
70+
6871
// GNU extension function ACCESS(NAME, MODE)
6972
// TODO: not supported on Windows
7073
#ifndef _WIN32

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
977977
DefaultInt, Rank::vector, IntrinsicClass::transformationalFunction},
978978
{"this_image", {OptionalTEAM}, DefaultInt, Rank::scalar,
979979
IntrinsicClass::transformationalFunction},
980+
{"time", {}, TypePattern{IntType, KindCode::exactKind, 8}, Rank::scalar,
981+
IntrinsicClass::transformationalFunction},
980982
{"tiny",
981983
{{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required,
982984
common::Intent::In, {ArgFlag::canBeMoldNull}}},

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ static constexpr IntrinsicHandler handlers[]{
769769
{"perror",
770770
&I::genPerror,
771771
{{{"string", asBox}}},
772-
/*isElemental=*/false},
772+
/*isElemental*/ false},
773773
{"popcnt", &I::genPopcnt},
774774
{"poppar", &I::genPoppar},
775775
{"present",
@@ -921,6 +921,7 @@ static constexpr IntrinsicHandler handlers[]{
921921
{"threadfence", &I::genThreadFence, {}, /*isElemental=*/false},
922922
{"threadfence_block", &I::genThreadFenceBlock, {}, /*isElemental=*/false},
923923
{"threadfence_system", &I::genThreadFenceSystem, {}, /*isElemental=*/false},
924+
{"time", &I::genTime, {}, /*isElemental=*/false},
924925
{"trailz", &I::genTrailz},
925926
{"transfer",
926927
&I::genTransfer,
@@ -8428,6 +8429,14 @@ void IntrinsicLibrary::genThreadFenceSystem(
84288429
builder.create<fir::CallOp>(loc, funcOp, noArgs);
84298430
}
84308431

8432+
// TIME
8433+
mlir::Value IntrinsicLibrary::genTime(mlir::Type resultType,
8434+
llvm::ArrayRef<mlir::Value> args) {
8435+
assert(args.size() == 0);
8436+
return builder.createConvert(loc, resultType,
8437+
fir::runtime::genTime(builder, loc));
8438+
}
8439+
84318440
// TRIM
84328441
fir::ExtendedValue
84338442
IntrinsicLibrary::genTrim(mlir::Type resultType,

flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ void fir::runtime::genRename(fir::FirOpBuilder &builder, mlir::Location loc,
252252
builder.create<fir::CallOp>(loc, runtimeFunc, args);
253253
}
254254

255+
/// generate runtime call to time intrinsic
256+
mlir::Value fir::runtime::genTime(fir::FirOpBuilder &builder,
257+
mlir::Location loc) {
258+
auto func = fir::runtime::getRuntimeFunc<mkRTKey(time)>(loc, builder);
259+
return builder.create<fir::CallOp>(loc, func, std::nullopt).getResult(0);
260+
}
261+
255262
/// generate runtime call to transfer intrinsic with no size argument
256263
void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
257264
mlir::Value resultBox, mlir::Value sourceBox,

flang/test/Lower/Intrinsics/time.f90

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
!RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
2+
3+
!CHECK-LABEL: func.func @_QPtime_test() -> i64
4+
function time_test()
5+
Integer(kind=8) :: time_test
6+
7+
8+
!CHECK-DAG: %[[func_result:.*]] = fir.alloca i64 {bindc_name = "time_test", uniq_name = "_QFtime_testEtime_test"}
9+
!CHECK-DAG: %[[func_result_decl:.*]]:{{.*}} = hlfir.declare %[[func_result]] {uniq_name = "_QFtime_testEtime_test"} : {{.*}}fir.ref<i64>{{.*}}
10+
!CHECK: %[[call_result:.*]] = fir.call @_FortranAtime()
11+
!CHECK-SAME: -> i64
12+
13+
!CHECK-DAG: hlfir.assign %[[call_result]] to %[[func_result_decl]]#[[func_result]] : i64, !fir.ref<i64>
14+
!CHECK-DAG: %[[load_result:.*]] = fir.load %[[func_result_decl]]#[[func_result]] : !fir.ref<i64>
15+
!CHECK: return %[[load_result]] : i64
16+
time_test = time()
17+
end function time_test

0 commit comments

Comments
 (0)