Skip to content

Commit b64c26f

Browse files
authored
[flang][runtime] Implement SLEEP intrinsic (#79074)
This intrinsic is a gnu extension. See https://gcc.gnu.org/onlinedocs/gfortran/SLEEP.html This intrinsic is used in minighost: https://github.com/Mantevo/miniGhost/blob/c2102b521568a74862fa5abb074b1fc8041fc222/ref/MG_UTILS.F#L606
1 parent 1bc1dcf commit b64c26f

File tree

9 files changed

+72
-2
lines changed

9 files changed

+72
-2
lines changed

flang/docs/Intrinsics.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ This phase currently supports all the intrinsic procedures listed above but the
757757
| Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE |
758758
| Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY|
759759
| Non-standard intrinsic functions | AND, OR, XOR, SHIFT, ZEXT, IZEXT, COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR, IARG, IARGC, NARGS, GETPID, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC |
760-
| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SYSTEM_CLOCK |
760+
| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SLEEP, SYSTEM_CLOCK |
761761
| Atomic intrinsic subroutines | ATOMIC_ADD |
762762
| Collective intrinsic subroutines | CO_REDUCE |
763763
| Library subroutines | FDATE, GETLOG |
@@ -908,4 +908,3 @@ used in constant expressions have currently no folding support at all.
908908
- If a condition occurs that would assign a nonzero value to `CMDSTAT` but the `CMDSTAT` variable is not present, error termination is initiated.
909909
- On POSIX-compatible systems, the child process (async process) will be terminated with no effect on the parent process (continues).
910910
- On Windows, error termination is not initiated.
911-

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ struct IntrinsicLibrary {
339339
fir::ExtendedValue genStorageSize(mlir::Type,
340340
llvm::ArrayRef<fir::ExtendedValue>);
341341
fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
342+
void genSleep(llvm::ArrayRef<fir::ExtendedValue>);
342343
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
343344
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
344345
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ void genTransferSize(fir::FirOpBuilder &builder, mlir::Location loc,
6464
/// all intrinsic arguments are optional and may appear here as mlir::Value{}
6565
void genSystemClock(fir::FirOpBuilder &, mlir::Location, mlir::Value count,
6666
mlir::Value rate, mlir::Value max);
67+
68+
/// generate sleep runtime call
69+
void genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
70+
mlir::Value seconds);
6771
} // namespace runtime
6872
} // namespace fir
6973

flang/include/flang/Runtime/extensions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#ifndef FORTRAN_RUNTIME_EXTENSIONS_H_
1313
#define FORTRAN_RUNTIME_EXTENSIONS_H_
1414

15+
#include "flang/Runtime/entry-names.h"
16+
1517
#define FORTRAN_PROCEDURE_NAME(name) name##_
1618

1719
#include <cstddef>
@@ -35,5 +37,8 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
3537
// GNU extension subroutine GETLOG(C).
3638
void FORTRAN_PROCEDURE_NAME(getlog)(char *name, std::int64_t length);
3739

40+
// GNU extension subroutine SLEEP(SECONDS)
41+
void RTNAME(Sleep)(std::int64_t seconds);
42+
3843
} // extern "C"
3944
#endif // FORTRAN_RUNTIME_EXTENSIONS_H_

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,10 @@ static const IntrinsicInterface intrinsicSubroutine[]{
14011401
{"count_max", AnyInt, Rank::scalar, Optionality::optional,
14021402
common::Intent::Out}},
14031403
{}, Rank::elemental, IntrinsicClass::impureSubroutine},
1404+
{"sleep",
1405+
{{"seconds", AnyInt, Rank::scalar, Optionality::required,
1406+
common::Intent::In}},
1407+
{}, Rank::elemental, IntrinsicClass::impureSubroutine},
14041408
};
14051409

14061410
// TODO: Intrinsic subroutine EVENT_QUERY

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ static constexpr IntrinsicHandler handlers[]{
556556
{"dim", asAddr, handleDynamicOptional},
557557
{"kind", asValue}}},
558558
/*isElemental=*/false},
559+
{"sleep", &I::genSleep, {{{"seconds", asValue}}}, /*isElemental=*/false},
559560
{"spacing", &I::genSpacing},
560561
{"spread",
561562
&I::genSpread,
@@ -5924,6 +5925,12 @@ void IntrinsicLibrary::genSystemClock(llvm::ArrayRef<fir::ExtendedValue> args) {
59245925
fir::getBase(args[1]), fir::getBase(args[2]));
59255926
}
59265927

5928+
// SLEEP
5929+
void IntrinsicLibrary::genSleep(llvm::ArrayRef<fir::ExtendedValue> args) {
5930+
assert(args.size() == 1 && "SLEEP has one compulsory argument");
5931+
fir::runtime::genSleep(builder, loc, fir::getBase(args[0]));
5932+
}
5933+
59275934
// TRANSFER
59285935
fir::ExtendedValue
59295936
IntrinsicLibrary::genTransfer(mlir::Type resultType,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
1313
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
1414
#include "flang/Parser/parse-tree.h"
15+
#include "flang/Runtime/extensions.h"
1516
#include "flang/Runtime/misc-intrinsic.h"
1617
#include "flang/Runtime/pointer.h"
1718
#include "flang/Runtime/random.h"
@@ -235,3 +236,12 @@ void fir::runtime::genSystemClock(fir::FirOpBuilder &builder,
235236
if (max)
236237
makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
237238
}
239+
240+
void fir::runtime::genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
241+
mlir::Value seconds) {
242+
mlir::Type int64 = builder.getIntegerType(64);
243+
seconds = builder.create<fir::ConvertOp>(loc, int64, seconds);
244+
mlir::func::FuncOp func{
245+
fir::runtime::getRuntimeFunc<mkRTKey(Sleep)>(loc, builder)};
246+
builder.create<fir::CallOp>(loc, func, seconds);
247+
}

flang/runtime/extensions.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#include "tools.h"
1515
#include "flang/Runtime/command.h"
1616
#include "flang/Runtime/descriptor.h"
17+
#include "flang/Runtime/entry-names.h"
1718
#include "flang/Runtime/io-api.h"
19+
#include <chrono>
1820
#include <ctime>
21+
#include <thread>
1922

2023
#ifdef _WIN32
2124
inline void CtimeBuffer(char *buffer, size_t bufsize, const time_t cur_time,
@@ -113,5 +116,15 @@ void FORTRAN_PROCEDURE_NAME(getlog)(char *arg, std::int64_t length) {
113116
#endif
114117
}
115118

119+
// CALL SLEEP(SECONDS)
120+
void RTNAME(Sleep)(std::int64_t seconds) {
121+
// ensure that conversion to unsigned makes sense,
122+
// sleep(0) is an immidiate return anyway
123+
if (seconds < 1) {
124+
return;
125+
}
126+
std::this_thread::sleep_for(std::chrono::seconds(seconds));
127+
}
128+
116129
} // namespace Fortran::runtime
117130
} // extern "C"

flang/test/Lower/Intrinsics/sleep.f90

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
2+
3+
subroutine test_sleep()
4+
! CHECK-LABEL: func.func @_QPtest_sleep() {
5+
6+
call sleep(1_2)
7+
! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i16
8+
! CHECK: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i16) -> i64
9+
! CHECK: %[[VAL_2:.*]] = fir.call @_FortranASleep(%[[VAL_1]]) fastmath<contract> : (i64) -> none
10+
11+
call sleep(1_4)
12+
! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32
13+
! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i32) -> i64
14+
! CHECK: %[[VAL_5:.*]] = fir.call @_FortranASleep(%[[VAL_4]]) fastmath<contract> : (i64) -> none
15+
16+
call sleep(1_8)
17+
! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i64
18+
! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> i64
19+
! CHECK: %[[VAL_8:.*]] = fir.call @_FortranASleep(%[[VAL_7]]) fastmath<contract> : (i64) -> none
20+
21+
call sleep(1_16)
22+
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i128
23+
! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i128) -> i64
24+
! CHECK: %[[VAL_11:.*]] = fir.call @_FortranASleep(%[[VAL_10]]) fastmath<contract> : (i64) -> none
25+
end
26+
! CHECK: return
27+
! CHECK: }

0 commit comments

Comments
 (0)