diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h index fa1bfaa8578c6..3eec7b4d016ff 100644 --- a/flang/include/flang/Lower/Runtime.h +++ b/flang/include/flang/Lower/Runtime.h @@ -81,6 +81,11 @@ void genRandomNumber(fir::FirOpBuilder &, mlir::Location, mlir::Value harvest); void genRandomSeed(fir::FirOpBuilder &, mlir::Location, int argIndex, mlir::Value argBox); +/// generate system_clock runtime call/s +/// all intrinsic arguments are optional and may appear here as mlir::Value{} +void genSystemClock(fir::FirOpBuilder &, mlir::Location, mlir::Value count, + mlir::Value rate, mlir::Value max); + } // namespace lower } // namespace Fortran diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp index 196ed24d1c257..3a5a6148bc288 100644 --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -462,6 +462,7 @@ struct IntrinsicLibrary { void genRandomSeed(llvm::ArrayRef); fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef); + void genSystemClock(llvm::ArrayRef); fir::ExtendedValue genUbound(mlir::Type, llvm::ArrayRef); /// Define the different FIR generators that can be mapped to intrinsic to @@ -652,6 +653,10 @@ static constexpr IntrinsicHandler handlers[]{ {"dim", asValue}, {"mask", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, + {"system_clock", + &I::genSystemClock, + {{{"count", asAddr}, {"count_rate", asAddr}, {"count_max", asAddr}}}, + /*isElemental=*/false}, {"ubound", &I::genUbound, {{{"array", asBox}, {"dim", asValue}, {"kind", asValue}}}, @@ -1875,6 +1880,13 @@ IntrinsicLibrary::genSum(mlir::Type resultType, builder, loc, stmtCtx, "unexpected result for Sum", args); } +// SYSTEM_CLOCK +void IntrinsicLibrary::genSystemClock(llvm::ArrayRef args) { + assert(args.size() == 3); + Fortran::lower::genSystemClock(builder, loc, fir::getBase(args[0]), + fir::getBase(args[1]), fir::getBase(args[2])); +} + // SIZE fir::ExtendedValue IntrinsicLibrary::genSize(mlir::Type resultType, diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp index a6507e15bbf20..8b97a5125c8ca 100644 --- a/flang/lib/Lower/Runtime.cpp +++ b/flang/lib/Lower/Runtime.cpp @@ -233,3 +233,31 @@ void Fortran::lower::genRandomSeed(fir::FirOpBuilder &builder, builder, loc, funcTy, argBox, sourceFile, sourceLine); builder.create(loc, func, args); } + +/// generate system_clock runtime call/s +/// all intrinsic arguments are optional and may appear here as mlir::Value{} +void Fortran::lower::genSystemClock(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value count, + mlir::Value rate, mlir::Value max) { + auto makeCall = [&](mlir::FuncOp func, mlir::Value arg) { + mlir::Type kindTy = func.getType().getInput(0); + int integerKind = 8; + if (auto intType = + fir::unwrapRefType(arg.getType()).dyn_cast()) + integerKind = intType.getWidth() / 8; + mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind); + mlir::Value res = + builder.create(loc, func, mlir::ValueRange{kind}) + .getResult(0); + mlir::Value castRes = + builder.createConvert(loc, fir::dyn_cast_ptrEleTy(arg.getType()), res); + builder.create(loc, castRes, arg); + }; + using fir::runtime::getRuntimeFunc; + if (count) + makeCall(getRuntimeFunc(loc, builder), count); + if (rate) + makeCall(getRuntimeFunc(loc, builder), rate); + if (max) + makeCall(getRuntimeFunc(loc, builder), max); +} diff --git a/flang/test/Lower/Intrinsics/system_clock.f90 b/flang/test/Lower/Intrinsics/system_clock.f90 new file mode 100644 index 0000000000000..8713acd05e8c3 --- /dev/null +++ b/flang/test/Lower/Intrinsics/system_clock.f90 @@ -0,0 +1,31 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: system_clock_test +subroutine system_clock_test() + integer(4) :: c + integer(8) :: m + real :: r + ! CHECK-DAG: %[[c:.*]] = fir.alloca i32 {bindc_name = "c" + ! CHECK-DAG: %[[m:.*]] = fir.alloca i64 {bindc_name = "m" + ! CHECK-DAG: %[[r:.*]] = fir.alloca f32 {bindc_name = "r" + ! CHECK: %[[c4:.*]] = arith.constant 4 : i32 + ! CHECK: %[[Count:.*]] = fir.call @_FortranASystemClockCount(%[[c4]]) : (i32) -> i64 + ! CHECK: %[[Count1:.*]] = fir.convert %[[Count]] : (i64) -> i32 + ! CHECK: fir.store %[[Count1]] to %[[c]] : !fir.ref + ! CHECK: %[[c8:.*]] = arith.constant 8 : i32 + ! CHECK: %[[Rate:.*]] = fir.call @_FortranASystemClockCountRate(%[[c8]]) : (i32) -> i64 + ! CHECK: %[[Rate1:.*]] = fir.convert %[[Rate]] : (i64) -> f32 + ! CHECK: fir.store %[[Rate1]] to %[[r]] : !fir.ref + ! CHECK: %[[c8_2:.*]] = arith.constant 8 : i32 + ! CHECK: %[[Max:.*]] = fir.call @_FortranASystemClockCountMax(%[[c8_2]]) : (i32) -> i64 + ! CHECK: fir.store %[[Max]] to %[[m]] : !fir.ref + call system_clock(c, r, m) +! print*, c, r, m + ! CHECK-NOT: fir.call + ! CHECK: %[[c8_3:.*]] = arith.constant 8 : i32 + ! CHECK: %[[Rate:.*]] = fir.call @_FortranASystemClockCountRate(%[[c8_3]]) : (i32) -> i64 + ! CHECK: fir.store %[[Rate]] to %[[m]] : !fir.ref + call system_clock(count_rate=m) + ! CHECK-NOT: fir.call +! print*, m +end subroutine