Skip to content

Commit 3748c05

Browse files
committed
add support function form of etime
1 parent 2356ea8 commit 3748c05

File tree

3 files changed

+120
-15
lines changed

3 files changed

+120
-15
lines changed

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,8 @@ struct IntrinsicLibrary {
222222
fir::ExtendedValue genEoshift(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
223223
void genExit(llvm::ArrayRef<fir::ExtendedValue>);
224224
void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
225-
void genEtime(mlir::ArrayRef<fir::ExtendedValue> args);
225+
fir::ExtendedValue genEtime(std::optional<mlir::Type>,
226+
mlir::ArrayRef<fir::ExtendedValue> args);
226227
mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
227228
fir::ExtendedValue genExtendsTypeOf(mlir::Type,
228229
llvm::ArrayRef<fir::ExtendedValue>);
@@ -399,8 +400,10 @@ struct IntrinsicLibrary {
399400
using ElementalGenerator = decltype(&IntrinsicLibrary::genAbs);
400401
using ExtendedGenerator = decltype(&IntrinsicLibrary::genLenTrim);
401402
using SubroutineGenerator = decltype(&IntrinsicLibrary::genDateAndTime);
402-
using Generator =
403-
std::variant<ElementalGenerator, ExtendedGenerator, SubroutineGenerator>;
403+
/// The generator for intrinsic that has both function and subroutine form.
404+
using DualGenerator = decltype(&IntrinsicLibrary::genEtime);
405+
using Generator = std::variant<ElementalGenerator, ExtendedGenerator,
406+
SubroutineGenerator, DualGenerator>;
404407

405408
/// All generators can be outlined. This will build a function named
406409
/// "fir."+ <generic name> + "." + <result type code> and generate the
@@ -441,6 +444,10 @@ struct IntrinsicLibrary {
441444
llvm::ArrayRef<mlir::Value> args);
442445
mlir::Value invokeGenerator(SubroutineGenerator generator,
443446
llvm::ArrayRef<mlir::Value> args);
447+
mlir::Value invokeGenerator(DualGenerator generator,
448+
llvm::ArrayRef<mlir::Value> args);
449+
mlir::Value invokeGenerator(DualGenerator generator, mlir::Type resultType,
450+
llvm::ArrayRef<mlir::Value> args);
444451

445452
/// Get pointer to unrestricted intrinsic. Generate the related unrestricted
446453
/// intrinsic if it is not defined yet.

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
454454
{"erf", {{"x", SameReal}}, SameReal},
455455
{"erfc", {{"x", SameReal}}, SameReal},
456456
{"erfc_scaled", {{"x", SameReal}}, SameReal},
457+
{"etime",
458+
{{"values", TypePattern{RealType, KindCode::exactKind, 4}, Rank::vector,
459+
Optionality::required, common::Intent::Out}},
460+
TypePattern{RealType, KindCode::exactKind, 4}},
457461
{"exp", {{"x", SameFloating}}, SameFloating},
458462
{"exp", {{"x", SameFloating}}, SameFloating},
459463
{"exponent", {{"x", AnyReal}}, DefaultInt},
@@ -973,6 +977,12 @@ static const std::pair<const char *, const char *> genericAlias[]{
973977
{"__builtin_ieee_selected_real_kind", "selected_real_kind"},
974978
};
975979

980+
// Collection for some intrinsics with function and subroutine form,
981+
// in order to pass
982+
static const std::string dualIntrinsic[]{
983+
{"etime"}
984+
};
985+
976986
// The following table contains the intrinsic functions listed in
977987
// Tables 16.2 and 16.3 in Fortran 2018. The "unrestricted" functions
978988
// in Table 16.2 can be used as actual arguments, PROCEDURE() interfaces,
@@ -2488,6 +2498,7 @@ class IntrinsicProcTable::Implementation {
24882498
bool IsIntrinsic(const std::string &) const;
24892499
bool IsIntrinsicFunction(const std::string &) const;
24902500
bool IsIntrinsicSubroutine(const std::string &) const;
2501+
bool IsDualIntrinsic(const std::string &) const;
24912502

24922503
IntrinsicClass GetIntrinsicClass(const std::string &) const;
24932504
std::string GetGenericIntrinsicName(const std::string &) const;
@@ -2549,6 +2560,13 @@ bool IntrinsicProcTable::Implementation::IsIntrinsic(
25492560
const std::string &name) const {
25502561
return IsIntrinsicFunction(name) || IsIntrinsicSubroutine(name);
25512562
}
2563+
bool IntrinsicProcTable::Implementation::IsDualIntrinsic(
2564+
const std::string &name) const {
2565+
return std::find_if(std::begin(dualIntrinsic), std::end(dualIntrinsic),
2566+
[&name](const std::string &dualName) {
2567+
return dualName == name;
2568+
}) != std::end(dualIntrinsic);
2569+
}
25522570

25532571
IntrinsicClass IntrinsicProcTable::Implementation::GetIntrinsicClass(
25542572
const std::string &name) const {
@@ -3080,7 +3098,7 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
30803098
return specificCall;
30813099
}
30823100
}
3083-
if (IsIntrinsicFunction(call.name)) {
3101+
if (IsIntrinsicFunction(call.name) && !IsDualIntrinsic(call.name)) {
30843102
context.messages().Say(
30853103
"Cannot use intrinsic function '%s' as a subroutine"_err_en_US,
30863104
call.name);
@@ -3215,7 +3233,7 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
32153233
}
32163234

32173235
if (specificBuffer.empty() && genericBuffer.empty() &&
3218-
IsIntrinsicSubroutine(call.name)) {
3236+
IsIntrinsicSubroutine(call.name) && IsDualIntrinsic(call.name)) {
32193237
context.messages().Say(
32203238
"Cannot use intrinsic subroutine '%s' as a function"_err_en_US,
32213239
call.name);

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "flang/Optimizer/Builder/Runtime/Stop.h"
3636
#include "flang/Optimizer/Builder/Runtime/Transformational.h"
3737
#include "flang/Optimizer/Builder/Todo.h"
38+
#include "flang/Optimizer/Dialect/FIROps.h"
3839
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
3940
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
4041
#include "flang/Optimizer/Support/FatalError.h"
@@ -49,6 +50,7 @@
4950
#include "llvm/Support/Debug.h"
5051
#include "llvm/Support/MathExtras.h"
5152
#include "llvm/Support/raw_ostream.h"
53+
#include <mlir/IR/Value.h>
5254
#include <optional>
5355

5456
#define DEBUG_TYPE "flang-lower-intrinsic"
@@ -1681,6 +1683,24 @@ IntrinsicLibrary::genElementalCall<IntrinsicLibrary::SubroutineGenerator>(
16811683
return mlir::Value();
16821684
}
16831685

1686+
template <>
1687+
fir::ExtendedValue
1688+
IntrinsicLibrary::genElementalCall<IntrinsicLibrary::DualGenerator>(
1689+
DualGenerator generator, llvm::StringRef name, mlir::Type resultType,
1690+
llvm::ArrayRef<fir::ExtendedValue> args, bool outline) {
1691+
assert(resultType.getImpl() && "expect elemental intrinsic to be functions");
1692+
1693+
for (const fir::ExtendedValue &arg : args)
1694+
if (!arg.getUnboxed() && !arg.getCharBox())
1695+
// fir::emitFatalError(loc, "nonscalar intrinsic argument");
1696+
crashOnMissingIntrinsic(loc, name);
1697+
if (outline)
1698+
return outlineInExtendedWrapper(generator, name, resultType, args);
1699+
1700+
return std::invoke(generator, *this, std::optional<mlir::Type>{resultType},
1701+
args);
1702+
}
1703+
16841704
static fir::ExtendedValue
16851705
invokeHandler(IntrinsicLibrary::ElementalGenerator generator,
16861706
const IntrinsicHandler &handler,
@@ -1724,6 +1744,22 @@ invokeHandler(IntrinsicLibrary::SubroutineGenerator generator,
17241744
return mlir::Value{};
17251745
}
17261746

1747+
static fir::ExtendedValue
1748+
invokeHandler(IntrinsicLibrary::DualGenerator generator,
1749+
const IntrinsicHandler &handler,
1750+
std::optional<mlir::Type> resultType,
1751+
llvm::ArrayRef<fir::ExtendedValue> args, bool outline,
1752+
IntrinsicLibrary &lib) {
1753+
if (handler.isElemental)
1754+
return lib.genElementalCall(generator, handler.name, mlir::Type{}, args,
1755+
outline);
1756+
if (outline)
1757+
return lib.outlineInExtendedWrapper(generator, handler.name, resultType,
1758+
args);
1759+
1760+
return std::invoke(generator, lib, resultType, args);
1761+
}
1762+
17271763
std::pair<fir::ExtendedValue, bool>
17281764
IntrinsicLibrary::genIntrinsicCall(llvm::StringRef specificName,
17291765
std::optional<mlir::Type> resultType,
@@ -1819,6 +1855,34 @@ IntrinsicLibrary::invokeGenerator(SubroutineGenerator generator,
18191855
return {};
18201856
}
18211857

1858+
mlir::Value
1859+
IntrinsicLibrary::invokeGenerator(DualGenerator generator,
1860+
llvm::ArrayRef<mlir::Value> args) {
1861+
llvm::SmallVector<fir::ExtendedValue> extendedArgs;
1862+
for (mlir::Value arg : args)
1863+
extendedArgs.emplace_back(toExtendedValue(arg, builder, loc));
1864+
std::invoke(generator, *this, std::optional<mlir::Type>{}, extendedArgs);
1865+
return {};
1866+
}
1867+
1868+
mlir::Value
1869+
IntrinsicLibrary::invokeGenerator(DualGenerator generator,
1870+
mlir::Type resultType,
1871+
llvm::ArrayRef<mlir::Value> args) {
1872+
llvm::SmallVector<fir::ExtendedValue> extendedArgs;
1873+
for (mlir::Value arg : args)
1874+
extendedArgs.emplace_back(toExtendedValue(arg, builder, loc));
1875+
1876+
if (resultType.getImpl() == nullptr) {
1877+
// TODO:
1878+
assert(false && "result type is null");
1879+
}
1880+
1881+
auto extendedResult = std::invoke(
1882+
generator, *this, std::optional<mlir::Type>{resultType}, extendedArgs);
1883+
return toValue(extendedResult, builder, loc);
1884+
}
1885+
18221886
//===----------------------------------------------------------------------===//
18231887
// Intrinsic Procedure Mangling
18241888
//===----------------------------------------------------------------------===//
@@ -3235,18 +3299,34 @@ void IntrinsicLibrary::genExecuteCommandLine(
32353299
}
32363300

32373301
// ETIME
3238-
void IntrinsicLibrary::genEtime(llvm::ArrayRef<fir::ExtendedValue> args) {
3239-
assert(args.size() == 2);
3302+
fir::ExtendedValue
3303+
IntrinsicLibrary::genEtime(std::optional<mlir::Type> resultType,
3304+
llvm::ArrayRef<fir::ExtendedValue> args) {
3305+
assert((args.size() == 2 && !resultType.has_value()) ||
3306+
(args.size() == 1 && resultType.has_value()));
32403307

32413308
mlir::Value values = fir::getBase(args[0]);
3242-
mlir::Value time = fir::getBase(args[1]);
3243-
3244-
if (!values)
3245-
fir::emitFatalError(loc, "expected VALUES parameter");
3246-
if (!time)
3247-
fir::emitFatalError(loc, "expected TIME parameter");
3248-
3249-
fir::runtime::genEtime(builder, loc, values, time);
3309+
if (resultType.has_value()) {
3310+
// function form
3311+
if (!values)
3312+
fir::emitFatalError(loc, "expected VALUES parameter");
3313+
3314+
auto timeAddr = builder.createTemporary(loc, *resultType);
3315+
auto timeBox = builder.createBox(loc, timeAddr);
3316+
fir::runtime::genEtime(builder, loc, values, timeBox);
3317+
return builder.create<fir::LoadOp>(loc, timeAddr);
3318+
} else {
3319+
// subroutine form
3320+
mlir::Value time = fir::getBase(args[1]);
3321+
if (!values)
3322+
fir::emitFatalError(loc, "expected VALUES parameter");
3323+
if (!time)
3324+
fir::emitFatalError(loc, "expected TIME parameter");
3325+
3326+
fir::runtime::genEtime(builder, loc, values, time);
3327+
return {};
3328+
}
3329+
return {};
32503330
}
32513331

32523332
// EXIT

0 commit comments

Comments
 (0)