Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion flang-rt/lib/runtime/extensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ inline void CtimeBuffer(char *buffer, size_t bufsize, const time_t cur_time,

namespace Fortran::runtime {

// Common implementation that could be used for either SECNDS() or SECNDSD(),
// Common implementation that could be used for either SECNDS() or DSECNDS(),
// which are defined for float or double.
template <typename T> T SecndsImpl(T *refTime) {
static_assert(std::is_same<T, float>::value || std::is_same<T, double>::value,
Expand Down Expand Up @@ -381,6 +381,17 @@ float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line) {
return FORTRAN_PROCEDURE_NAME(secnds)(refTime);
}

// PGI extension function DSECNDS(refTime)
double FORTRAN_PROCEDURE_NAME(dsecnds)(double *refTime) {
return SecndsImpl(refTime);
}

double RTNAME(Dsecnds)(double *refTime, const char *sourceFile, int line) {
Terminator terminator{sourceFile, line};
RUNTIME_CHECK(terminator, refTime != nullptr);
return FORTRAN_PROCEDURE_NAME(dsecnds)(refTime);
}

// GNU extension function TIME()
std::int64_t RTNAME(time)() { return time(nullptr); }

Expand Down
26 changes: 26 additions & 0 deletions flang/docs/Intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,32 @@ PROGRAM example_secnds
PRINT *, "Elapsed seconds:", elapsed
END PROGRAM example_secnds
```
### Non-Standard Intrinsics: DSECNDS
#### Description
`DSECNDS(refTime)` is the double precision variant of `SECNDS`. It returns the number of seconds
since midnight minus a user-supplied reference time `refTime`. Uses `REAL(KIND=8)` for higher precision.

#### Usage and Info
- **Standard:** PGI extension
- **Class:** function
- **Syntax:** result = `DSECNDS(refTime)`
- **Arguments:**

| ARGUMENT | INTENT | TYPE | KIND | Description |
|-----------|--------|---------------|-------------------------|------------------------------------------|
| `refTime` | `IN` | `REAL, scalar`| REAL(KIND=8), required | Reference time in seconds since midnight |

- **Return Value:** REAL(KIND=8), scalar — seconds elapsed since `refTime`.
- **Purity:** Impure

#### Example
```fortran
PROGRAM example_dsecnds
DOUBLE PRECISION :: refTime
refTime = 0.0D0
PRINT '(F24.15)', DSECNDS(refTime)
END PROGRAM example_dsecnds
```

### Non-standard Intrinsics: SECOND
This intrinsic is an alias for `CPU_TIME`: supporting both a subroutine and a
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ struct IntrinsicLibrary {
mlir::Value genCosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genCospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genDsecnds(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args);
mlir::Value genDim(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genDotProduct(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ void genDateAndTime(fir::FirOpBuilder &, mlir::Location,
std::optional<fir::CharBoxValue> date,
std::optional<fir::CharBoxValue> time,
std::optional<fir::CharBoxValue> zone, mlir::Value values);

mlir::Value genDsecnds(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value refTime);

void genEtime(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value values, mlir::Value time);

Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Runtime/extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ typedef std::uint32_t gid_t;

extern "C" {

// PGI extension function DSECNDS(refTime)
double FORTRAN_PROCEDURE_NAME(dsecnds)(double *refTime);
double RTNAME(Dsecnds)(double *refTime, const char *sourceFile, int line);

// CALL FLUSH(n) antedates the Fortran 2003 FLUSH statement.
void FORTRAN_PROCEDURE_NAME(flush)(const int &unit);

Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Evaluate/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"vector_b", AnyNumeric, Rank::vector}},
ResultNumeric, Rank::scalar, IntrinsicClass::transformationalFunction},
{"dprod", {{"x", DefaultReal}, {"y", DefaultReal}}, DoublePrecision},
{"dsecnds",
{{"refTime", TypePattern{RealType, KindCode::exactKind, 8},
Rank::scalar}},
TypePattern{RealType, KindCode::exactKind, 8}, Rank::scalar},
{"dshiftl",
{{"i", SameIntOrUnsigned},
{"j", SameIntOrUnsigned, Rank::elementalOrBOZ}, {"shift", AnyInt}},
Expand Down
21 changes: 21 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,10 @@ static constexpr IntrinsicHandler handlers[]{
{{{"vector_a", asBox}, {"vector_b", asBox}}},
/*isElemental=*/false},
{"dprod", &I::genDprod},
{"dsecnds",
&I::genDsecnds,
{{{"refTime", asAddr}}},
/*isElemental=*/false},
{"dshiftl", &I::genDshiftl},
{"dshiftr", &I::genDshiftr},
{"eoshift",
Expand Down Expand Up @@ -3941,6 +3945,23 @@ mlir::Value IntrinsicLibrary::genDprod(mlir::Type resultType,
return mlir::arith::MulFOp::create(builder, loc, a, b);
}

// DSECNDS
// Double precision variant of SECNDS (PGI extension)
fir::ExtendedValue
IntrinsicLibrary::genDsecnds(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 1 && "DSECNDS expects one argument");

mlir::Value refTime = fir::getBase(args[0]);

if (!refTime)
fir::emitFatalError(loc, "expected REFERENCE TIME parameter");

mlir::Value result = fir::runtime::genDsecnds(builder, loc, refTime);

return builder.createConvert(loc, resultType, result);
}

// DSHIFTL
mlir::Value IntrinsicLibrary::genDshiftl(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
Expand Down
17 changes: 17 additions & 0 deletions flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder,
fir::CallOp::create(builder, loc, callee, args);
}

mlir::Value fir::runtime::genDsecnds(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value refTime) {
auto runtimeFunc =
fir::runtime::getRuntimeFunc<mkRTKey(Dsecnds)>(loc, builder);

mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType();

mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(2));

llvm::SmallVector<mlir::Value> args = {refTime, sourceFile, sourceLine};
args = fir::runtime::createArguments(builder, loc, runtimeFuncTy, args);

return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0);
}

void fir::runtime::genEtime(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value values, mlir::Value time) {
auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Etime)>(loc, builder);
Expand Down
22 changes: 22 additions & 0 deletions flang/test/Lower/Intrinsics/dsecnds.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s

! CHECK-LABEL: func.func @_QPuse_dsecnds(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f64>
function use_dsecnds(refTime) result(elapsed)
double precision :: refTime, elapsed
elapsed = dsecnds(refTime)
end function

! Verify filename and line operands are passed into runtime call
! CHECK: %[[STRADDR:.*]] = fir.address_of(
! CHECK: %[[LINE:.*]] = arith.constant {{.*}} : i32
! CHECK: %[[FNAME8:.*]] = fir.convert %[[STRADDR]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>

! Call the runtime DSECNDS with (refTime, file, line)
! CHECK: %[[CALL:.*]] = fir.call @_FortranADsecnds(%{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<f64>, !fir.ref<i8>, i32) -> f64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't want to use these definitions, then perhaps don't define them above?


! Guard: no illegal ref conversion
! CHECK-NOT: fir.convert {{.*}} : (f64) -> !fir.ref<f64>

! Function returns f64
! CHECK: return {{.*}} : f64
Loading