mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 02:38:07 +08:00
[flang] Register and lower SECNDS (stubbed implementation) (#151878)
This patch registers and lowers the GNU extension intrinsic `SECNDS` in Flang. - Registration and lowering are wired through the intrinsic infrastructure. - genSecnds() currently emits a TODO fatal error, marking it as unimplemented. - Includes an XFAIL test to exercise the lowering path and reflect current status. Fixes https://github.com/llvm/llvm-project/issues/58728 --- CC @eugeneepshteyn @klausler --------- Co-authored-by: Eugene Epshteyn <eepshteyn@nvidia.com>
This commit is contained in:
@@ -1123,6 +1123,33 @@ program rename_proc
|
||||
end program rename_proc
|
||||
```
|
||||
|
||||
### Non-Standard Intrinsics: SECNDS
|
||||
#### Description
|
||||
`SECNDS(refTime)` returns the number of seconds since midnight minus a user-supplied reference time `refTime`. If the difference is negative (i.e., the current time is past midnight and refTime was from the previous day), the result wraps around midnight to yield a positive value.
|
||||
|
||||
#### Usage and Info
|
||||
- **Standard:** GNU extension
|
||||
- **Class:** function
|
||||
- **Syntax:** result = `SECNDS(refTime)`
|
||||
- **Arguments:**
|
||||
|
||||
| ARGUMENT | INTENT | TYPE | KIND | Description |
|
||||
|-----------|--------|---------------|-------------------------|------------------------------------------|
|
||||
| `refTime` | `IN` | `REAL, scalar`| REAL(KIND=4), required | Reference time in seconds since midnight |
|
||||
|
||||
- **Return Value:** REAL(KIND=4), scalar — seconds elapsed since `refTime`.
|
||||
- **Purity:** Impure. SECNDS references the system clock and may not be invoked from a PURE procedure.
|
||||
|
||||
#### Example
|
||||
```Fortran
|
||||
PROGRAM example_secnds
|
||||
REAL :: refTime, elapsed
|
||||
refTime = SECNDS(0.0)
|
||||
elapsed = SECNDS(refTime)
|
||||
PRINT *, "Elapsed seconds:", elapsed
|
||||
END PROGRAM example_secnds
|
||||
```
|
||||
|
||||
### Non-standard Intrinsics: SECOND
|
||||
This intrinsic is an alias for `CPU_TIME`: supporting both a subroutine and a
|
||||
function form.
|
||||
|
||||
@@ -407,6 +407,8 @@ struct IntrinsicLibrary {
|
||||
llvm::ArrayRef<fir::ExtendedValue>);
|
||||
mlir::Value genScale(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
||||
fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
||||
fir::ExtendedValue genSecnds(mlir::Type resultType,
|
||||
llvm::ArrayRef<fir::ExtendedValue> args);
|
||||
fir::ExtendedValue genSecond(std::optional<mlir::Type>,
|
||||
mlir::ArrayRef<fir::ExtendedValue>);
|
||||
fir::ExtendedValue genSelectedCharKind(mlir::Type,
|
||||
|
||||
@@ -70,6 +70,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);
|
||||
|
||||
mlir::Value genSecnds(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value refTime);
|
||||
|
||||
/// generate time runtime call
|
||||
mlir::Value genTime(fir::FirOpBuilder &builder, mlir::Location loc);
|
||||
|
||||
|
||||
@@ -921,6 +921,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
|
||||
{"back", AnyLogical, Rank::elemental, Optionality::optional},
|
||||
DefaultingKIND},
|
||||
KINDInt},
|
||||
{"secnds",
|
||||
{{"refTime", TypePattern{RealType, KindCode::exactKind, 4},
|
||||
Rank::scalar}},
|
||||
TypePattern{RealType, KindCode::exactKind, 4}, Rank::scalar},
|
||||
{"second", {}, DefaultReal, Rank::scalar},
|
||||
{"selected_char_kind", {{"name", DefaultChar, Rank::scalar}}, DefaultInt,
|
||||
Rank::scalar, IntrinsicClass::transformationalFunction},
|
||||
|
||||
@@ -869,6 +869,10 @@ static constexpr IntrinsicHandler handlers[]{
|
||||
{"back", asValue, handleDynamicOptional},
|
||||
{"kind", asValue}}},
|
||||
/*isElemental=*/true},
|
||||
{"secnds",
|
||||
&I::genSecnds,
|
||||
{{{"refTime", asAddr}}},
|
||||
/*isElemental=*/false},
|
||||
{"second",
|
||||
&I::genSecond,
|
||||
{{{"time", asAddr}}},
|
||||
@@ -7864,6 +7868,22 @@ IntrinsicLibrary::genScan(mlir::Type resultType,
|
||||
return readAndAddCleanUp(resultMutableBox, resultType, "SCAN");
|
||||
}
|
||||
|
||||
// SECNDS
|
||||
fir::ExtendedValue
|
||||
IntrinsicLibrary::genSecnds(mlir::Type resultType,
|
||||
llvm::ArrayRef<fir::ExtendedValue> args) {
|
||||
assert(args.size() == 1 && "SECNDS expects one argument");
|
||||
|
||||
mlir::Value refTime = fir::getBase(args[0]);
|
||||
|
||||
if (!refTime)
|
||||
fir::emitFatalError(loc, "expected REFERENCE TIME parameter");
|
||||
|
||||
mlir::Value result = fir::runtime::genSecnds(builder, loc, refTime);
|
||||
|
||||
return builder.createConvert(loc, resultType, result);
|
||||
}
|
||||
|
||||
// SECOND
|
||||
fir::ExtendedValue
|
||||
IntrinsicLibrary::genSecond(std::optional<mlir::Type> resultType,
|
||||
|
||||
@@ -276,6 +276,23 @@ void fir::runtime::genRename(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
fir::CallOp::create(builder, loc, runtimeFunc, args);
|
||||
}
|
||||
|
||||
mlir::Value fir::runtime::genSecnds(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value refTime) {
|
||||
auto runtimeFunc =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(Secnds)>(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);
|
||||
}
|
||||
|
||||
/// generate runtime call to time intrinsic
|
||||
mlir::Value fir::runtime::genTime(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc) {
|
||||
|
||||
23
flang/test/Lower/Intrinsics/secnds.f90
Normal file
23
flang/test/Lower/Intrinsics/secnds.f90
Normal file
@@ -0,0 +1,23 @@
|
||||
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
|
||||
|
||||
! CHECK-LABEL: func.func @_QPuse_secnds(
|
||||
! CHECK-SAME: %arg0: !fir.ref<f32>
|
||||
function use_secnds(refTime) result(elapsed)
|
||||
real :: refTime, elapsed
|
||||
elapsed = secnds(refTime)
|
||||
end function
|
||||
|
||||
! File/line operands (don’t match the actual path/number)
|
||||
! CHECK: %[[STRADDR:.*]] = fir.address_of(
|
||||
! CHECK: %[[LINE:.*]] = arith.constant {{.*}} : i32
|
||||
! CHECK: %[[FNAME8:.*]] = fir.convert %[[STRADDR]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
|
||||
|
||||
! Important: pass refTime by address and return a value f32
|
||||
! CHECK: %[[CALL:.*]] = fir.call @{{.*}}Secnds(%arg0, %[[FNAME8]], %[[LINE]]) {{.*}} : (!fir.ref<f32>, !fir.ref<i8>, i32) -> f32
|
||||
|
||||
! Guard against illegal value ->ref conversion of result
|
||||
! CHECK-NOT: fir.convert {{.*}} : (f32) -> !fir.ref<f32>
|
||||
|
||||
! Function returns an f32 value
|
||||
! CHECK: return {{.*}} : f32
|
||||
|
||||
Reference in New Issue
Block a user