[flang][NFC] Move runtime helpers used by intrinsics to lib/Optimizer 3/6
authorTom Eccles <tom.eccles@arm.com>
Wed, 1 Feb 2023 15:14:11 +0000 (15:14 +0000)
committerTom Eccles <tom.eccles@arm.com>
Mon, 6 Feb 2023 10:33:20 +0000 (10:33 +0000)
This will allow IntrinsicCall to be moved into lib/Optimizer later.

Differential Revision: https://reviews.llvm.org/D143081

flang/include/flang/Lower/Runtime.h
flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h [new file with mode: 0644]
flang/lib/Lower/IntrinsicCall.cpp
flang/lib/Lower/Runtime.cpp
flang/lib/Optimizer/Builder/CMakeLists.txt
flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp [new file with mode: 0644]

index 0c2a5fd..e4f8954 100644 (file)
@@ -63,42 +63,11 @@ void genSyncTeamStatement(AbstractConverter &, const parser::SyncTeamStmt &);
 void genUnlockStatement(AbstractConverter &, const parser::UnlockStmt &);
 void genPauseStatement(AbstractConverter &, const parser::PauseStmt &);
 
-mlir::Value genAssociated(fir::FirOpBuilder &, mlir::Location,
-                          mlir::Value pointer, mlir::Value target);
-
 void genPointerAssociate(fir::FirOpBuilder &, mlir::Location,
                          mlir::Value pointer, mlir::Value target);
 void genPointerAssociateRemapping(fir::FirOpBuilder &, mlir::Location,
                                   mlir::Value pointer, mlir::Value target,
                                   mlir::Value bounds);
-
-mlir::Value genCpuTime(fir::FirOpBuilder &, mlir::Location);
-void genDateAndTime(fir::FirOpBuilder &, mlir::Location,
-                    std::optional<fir::CharBoxValue> date,
-                    std::optional<fir::CharBoxValue> time,
-                    std::optional<fir::CharBoxValue> zone, mlir::Value values);
-
-void genRandomInit(fir::FirOpBuilder &, mlir::Location, mlir::Value repeatable,
-                   mlir::Value imageDistinct);
-void genRandomNumber(fir::FirOpBuilder &, mlir::Location, mlir::Value harvest);
-void genRandomSeed(fir::FirOpBuilder &, mlir::Location, mlir::Value size,
-                   mlir::Value put, mlir::Value get);
-
-/// generate runtime call to transfer intrinsic with no size argument
-void genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
-                 mlir::Value resultBox, mlir::Value sourceBox,
-                 mlir::Value moldBox);
-
-/// generate runtime call to transfer intrinsic with size argument
-void genTransferSize(fir::FirOpBuilder &builder, mlir::Location loc,
-                     mlir::Value resultBox, mlir::Value sourceBox,
-                     mlir::Value moldBox, mlir::Value size);
-
-/// 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/include/flang/Optimizer/Builder/Runtime/Intrinsics.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
new file mode 100644 (file)
index 0000000..9a37c15
--- /dev/null
@@ -0,0 +1,70 @@
+// Builder/Runtime/Intrinsics.h  Fortran runtime codegen interface -*- C++ -*-//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Builder routines for constructing the FIR dialect of MLIR. As FIR is a
+// dialect of MLIR, it makes extensive use of MLIR interfaces and MLIR's coding
+// style (https://mlir.llvm.org/getting_started/DeveloperGuide/) is used in this
+// module.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_LOWER_RUNTIME_H
+#define FORTRAN_LOWER_RUNTIME_H
+
+#include <optional>
+
+namespace mlir {
+class Location;
+class Value;
+} // namespace mlir
+
+namespace fir {
+class CharBoxValue;
+class FirOpBuilder;
+
+namespace runtime {
+
+mlir::Value genAssociated(fir::FirOpBuilder &, mlir::Location,
+                          mlir::Value pointer, mlir::Value target);
+
+void genPointerAssociate(fir::FirOpBuilder &, mlir::Location,
+                         mlir::Value pointer, mlir::Value target);
+void genPointerAssociateRemapping(fir::FirOpBuilder &, mlir::Location,
+                                  mlir::Value pointer, mlir::Value target,
+                                  mlir::Value bounds);
+
+mlir::Value genCpuTime(fir::FirOpBuilder &, mlir::Location);
+void genDateAndTime(fir::FirOpBuilder &, mlir::Location,
+                    std::optional<fir::CharBoxValue> date,
+                    std::optional<fir::CharBoxValue> time,
+                    std::optional<fir::CharBoxValue> zone, mlir::Value values);
+
+void genRandomInit(fir::FirOpBuilder &, mlir::Location, mlir::Value repeatable,
+                   mlir::Value imageDistinct);
+void genRandomNumber(fir::FirOpBuilder &, mlir::Location, mlir::Value harvest);
+void genRandomSeed(fir::FirOpBuilder &, mlir::Location, mlir::Value size,
+                   mlir::Value put, mlir::Value get);
+
+/// generate runtime call to transfer intrinsic with no size argument
+void genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
+                 mlir::Value resultBox, mlir::Value sourceBox,
+                 mlir::Value moldBox);
+
+/// generate runtime call to transfer intrinsic with size argument
+void genTransferSize(fir::FirOpBuilder &builder, mlir::Location loc,
+                     mlir::Value resultBox, mlir::Value sourceBox,
+                     mlir::Value moldBox, mlir::Value size);
+
+/// 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 runtime
+} // namespace fir
+
+#endif // FORTRAN_LOWER_RUNTIME_H
index 39199da..790d610 100644 (file)
@@ -16,7 +16,6 @@
 #include "flang/Lower/IntrinsicCall.h"
 #include "flang/Common/static-multimap-view.h"
 #include "flang/Lower/Mangler.h"
-#include "flang/Lower/Runtime.h"
 #include "flang/Lower/Support/Utils.h"
 #include "flang/Optimizer/Builder/BoxValue.h"
 #include "flang/Optimizer/Builder/Character.h"
@@ -28,6 +27,7 @@
 #include "flang/Optimizer/Builder/Runtime/Command.h"
 #include "flang/Optimizer/Builder/Runtime/Derived.h"
 #include "flang/Optimizer/Builder/Runtime/Inquiry.h"
+#include "flang/Optimizer/Builder/Runtime/Intrinsics.h"
 #include "flang/Optimizer/Builder/Runtime/Numeric.h"
 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
 #include "flang/Optimizer/Builder/Runtime/Reduction.h"
@@ -2272,7 +2272,7 @@ IntrinsicLibrary::genAssociated(mlir::Type resultType,
   mlir::Value pointerBoxRef =
       fir::factory::getMutableIRBox(builder, loc, *pointer);
   auto pointerBox = builder.create<fir::LoadOp>(loc, pointerBoxRef);
-  return Fortran::lower::genAssociated(builder, loc, pointerBox, targetBox);
+  return fir::runtime::genAssociated(builder, loc, pointerBox, targetBox);
 }
 
 // BESSEL_JN
@@ -2763,7 +2763,7 @@ void IntrinsicLibrary::genCpuTime(llvm::ArrayRef<fir::ExtendedValue> args) {
   assert(args.size() == 1);
   const mlir::Value *arg = args[0].getUnboxed();
   assert(arg && "nonscalar cpu_time argument");
-  mlir::Value res1 = Fortran::lower::genCpuTime(builder, loc);
+  mlir::Value res1 = fir::runtime::genCpuTime(builder, loc);
   mlir::Value res2 =
       builder.createConvert(loc, fir::dyn_cast_ptrEleTy(arg->getType()), res1);
   builder.create<fir::StoreOp>(loc, res2, *arg);
@@ -2823,8 +2823,8 @@ void IntrinsicLibrary::genDateAndTime(llvm::ArrayRef<fir::ExtendedValue> args) {
     values = builder.create<fir::AbsentOp>(
         loc, fir::BoxType::get(builder.getNoneType()));
 
-  Fortran::lower::genDateAndTime(builder, loc, charArgs[0], charArgs[1],
-                                 charArgs[2], values);
+  fir::runtime::genDateAndTime(builder, loc, charArgs[0], charArgs[1],
+                               charArgs[2], values);
 }
 
 // DIM
@@ -4189,15 +4189,15 @@ IntrinsicLibrary::genProduct(mlir::Type resultType,
 // RANDOM_INIT
 void IntrinsicLibrary::genRandomInit(llvm::ArrayRef<fir::ExtendedValue> args) {
   assert(args.size() == 2);
-  Fortran::lower::genRandomInit(builder, loc, fir::getBase(args[0]),
-                                fir::getBase(args[1]));
+  fir::runtime::genRandomInit(builder, loc, fir::getBase(args[0]),
+                              fir::getBase(args[1]));
 }
 
 // RANDOM_NUMBER
 void IntrinsicLibrary::genRandomNumber(
     llvm::ArrayRef<fir::ExtendedValue> args) {
   assert(args.size() == 1);
-  Fortran::lower::genRandomNumber(builder, loc, fir::getBase(args[0]));
+  fir::runtime::genRandomNumber(builder, loc, fir::getBase(args[0]));
 }
 
 // RANDOM_SEED
@@ -4212,7 +4212,7 @@ void IntrinsicLibrary::genRandomSeed(llvm::ArrayRef<fir::ExtendedValue> args) {
   mlir::Value size = getDesc(0);
   mlir::Value put = getDesc(1);
   mlir::Value get = getDesc(2);
-  Fortran::lower::genRandomSeed(builder, loc, size, put, get);
+  fir::runtime::genRandomSeed(builder, loc, size, put, get);
 }
 
 // REDUCE
@@ -4850,8 +4850,8 @@ IntrinsicLibrary::genSum(mlir::Type resultType,
 // SYSTEM_CLOCK
 void IntrinsicLibrary::genSystemClock(llvm::ArrayRef<fir::ExtendedValue> args) {
   assert(args.size() == 3);
-  Fortran::lower::genSystemClock(builder, loc, fir::getBase(args[0]),
-                                 fir::getBase(args[1]), fir::getBase(args[2]));
+  fir::runtime::genSystemClock(builder, loc, fir::getBase(args[0]),
+                               fir::getBase(args[1]), fir::getBase(args[2]));
 }
 
 // TRANSFER
@@ -4883,18 +4883,18 @@ IntrinsicLibrary::genTransfer(mlir::Type resultType,
     mlir::Value resultIrBox =
         fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
 
-    Fortran::lower::genTransfer(builder, loc, resultIrBox, source, mold);
+    fir::runtime::genTransfer(builder, loc, resultIrBox, source, mold);
   } else {
     // The result is a rank one array in this case.
     mlir::Value resultIrBox =
         fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
 
     if (absentSize) {
-      Fortran::lower::genTransfer(builder, loc, resultIrBox, source, mold);
+      fir::runtime::genTransfer(builder, loc, resultIrBox, source, mold);
     } else {
       mlir::Value sizeArg = fir::getBase(args[2]);
-      Fortran::lower::genTransferSize(builder, loc, resultIrBox, source, mold,
-                                      sizeArg);
+      fir::runtime::genTransferSize(builder, loc, resultIrBox, source, mold,
+                                    sizeArg);
     }
   }
   return readAndAddCleanUp(resultMutableBox, resultType, "TRANSFER");
index e68b131..d490264 100644 (file)
@@ -177,18 +177,6 @@ void Fortran::lower::genPauseStatement(
   builder.create<fir::CallOp>(loc, callee, std::nullopt);
 }
 
-mlir::Value Fortran::lower::genAssociated(fir::FirOpBuilder &builder,
-                                          mlir::Location loc,
-                                          mlir::Value pointer,
-                                          mlir::Value target) {
-  mlir::func::FuncOp func =
-      fir::runtime::getRuntimeFunc<mkRTKey(PointerIsAssociatedWith)>(loc,
-                                                                     builder);
-  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-      builder, loc, func.getFunctionType(), pointer, target);
-  return builder.create<fir::CallOp>(loc, func, args).getResult(0);
-}
-
 void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder,
                                          mlir::Location loc,
                                          mlir::Value pointer,
@@ -217,203 +205,3 @@ void Fortran::lower::genPointerAssociateRemapping(fir::FirOpBuilder &builder,
       sourceLine);
   builder.create<fir::CallOp>(loc, func, args).getResult(0);
 }
-
-mlir::Value Fortran::lower::genCpuTime(fir::FirOpBuilder &builder,
-                                       mlir::Location loc) {
-  mlir::func::FuncOp func =
-      fir::runtime::getRuntimeFunc<mkRTKey(CpuTime)>(loc, builder);
-  return builder.create<fir::CallOp>(loc, func, std::nullopt).getResult(0);
-}
-
-void Fortran::lower::genDateAndTime(fir::FirOpBuilder &builder,
-                                    mlir::Location loc,
-                                    std::optional<fir::CharBoxValue> date,
-                                    std::optional<fir::CharBoxValue> time,
-                                    std::optional<fir::CharBoxValue> zone,
-                                    mlir::Value values) {
-  mlir::func::FuncOp callee =
-      fir::runtime::getRuntimeFunc<mkRTKey(DateAndTime)>(loc, builder);
-  mlir::FunctionType funcTy = callee.getFunctionType();
-  mlir::Type idxTy = builder.getIndexType();
-  mlir::Value zero;
-  auto splitArg = [&](std::optional<fir::CharBoxValue> arg, mlir::Value &buffer,
-                      mlir::Value &len) {
-    if (arg) {
-      buffer = arg->getBuffer();
-      len = arg->getLen();
-    } else {
-      if (!zero)
-        zero = builder.createIntegerConstant(loc, idxTy, 0);
-      buffer = zero;
-      len = zero;
-    }
-  };
-  mlir::Value dateBuffer;
-  mlir::Value dateLen;
-  splitArg(date, dateBuffer, dateLen);
-  mlir::Value timeBuffer;
-  mlir::Value timeLen;
-  splitArg(time, timeBuffer, timeLen);
-  mlir::Value zoneBuffer;
-  mlir::Value zoneLen;
-  splitArg(zone, zoneBuffer, zoneLen);
-
-  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
-  mlir::Value sourceLine =
-      fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7));
-
-  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-      builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen,
-      zoneBuffer, zoneLen, sourceFile, sourceLine, values);
-  builder.create<fir::CallOp>(loc, callee, args);
-}
-
-void Fortran::lower::genRandomInit(fir::FirOpBuilder &builder,
-                                   mlir::Location loc, mlir::Value repeatable,
-                                   mlir::Value imageDistinct) {
-  mlir::func::FuncOp func =
-      fir::runtime::getRuntimeFunc<mkRTKey(RandomInit)>(loc, builder);
-  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-      builder, loc, func.getFunctionType(), repeatable, imageDistinct);
-  builder.create<fir::CallOp>(loc, func, args);
-}
-
-void Fortran::lower::genRandomNumber(fir::FirOpBuilder &builder,
-                                     mlir::Location loc, mlir::Value harvest) {
-  mlir::func::FuncOp func =
-      fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder);
-  mlir::FunctionType funcTy = func.getFunctionType();
-  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
-  mlir::Value sourceLine =
-      fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
-  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-      builder, loc, funcTy, harvest, sourceFile, sourceLine);
-  builder.create<fir::CallOp>(loc, func, args);
-}
-
-void Fortran::lower::genRandomSeed(fir::FirOpBuilder &builder,
-                                   mlir::Location loc, mlir::Value size,
-                                   mlir::Value put, mlir::Value get) {
-  bool sizeIsPresent =
-      !mlir::isa_and_nonnull<fir::AbsentOp>(size.getDefiningOp());
-  bool putIsPresent =
-      !mlir::isa_and_nonnull<fir::AbsentOp>(put.getDefiningOp());
-  bool getIsPresent =
-      !mlir::isa_and_nonnull<fir::AbsentOp>(get.getDefiningOp());
-  mlir::func::FuncOp func;
-  int staticArgCount = sizeIsPresent + putIsPresent + getIsPresent;
-  if (staticArgCount == 0) {
-    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedDefaultPut)>(loc,
-                                                                       builder);
-    builder.create<fir::CallOp>(loc, func);
-    return;
-  }
-  mlir::FunctionType funcTy;
-  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
-  mlir::Value sourceLine;
-  mlir::Value argBox;
-  llvm::SmallVector<mlir::Value> args;
-  if (staticArgCount > 1) {
-    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeed)>(loc, builder);
-    funcTy = func.getFunctionType();
-    sourceLine =
-        fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4));
-    args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get,
-                                         sourceFile, sourceLine);
-    builder.create<fir::CallOp>(loc, func, args);
-    return;
-  }
-  if (sizeIsPresent) {
-    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedSize)>(loc, builder);
-    argBox = size;
-  } else if (putIsPresent) {
-    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedPut)>(loc, builder);
-    argBox = put;
-  } else {
-    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedGet)>(loc, builder);
-    argBox = get;
-  }
-  funcTy = func.getFunctionType();
-  sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
-  args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile,
-                                       sourceLine);
-  builder.create<fir::CallOp>(loc, func, args);
-}
-
-/// generate runtime call to transfer intrinsic with no size argument
-void Fortran::lower::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
-                                 mlir::Value resultBox, mlir::Value sourceBox,
-                                 mlir::Value moldBox) {
-
-  mlir::func::FuncOp func =
-      fir::runtime::getRuntimeFunc<mkRTKey(Transfer)>(loc, builder);
-  mlir::FunctionType fTy = func.getFunctionType();
-  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
-  mlir::Value sourceLine =
-      fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
-  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-      builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine);
-  builder.create<fir::CallOp>(loc, func, args);
-}
-
-/// generate runtime call to transfer intrinsic with size argument
-void Fortran::lower::genTransferSize(fir::FirOpBuilder &builder,
-                                     mlir::Location loc, mlir::Value resultBox,
-                                     mlir::Value sourceBox, mlir::Value moldBox,
-                                     mlir::Value size) {
-  mlir::func::FuncOp func =
-      fir::runtime::getRuntimeFunc<mkRTKey(TransferSize)>(loc, builder);
-  mlir::FunctionType fTy = func.getFunctionType();
-  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
-  mlir::Value sourceLine =
-      fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
-  llvm::SmallVector<mlir::Value> args =
-      fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
-                                    moldBox, sourceFile, sourceLine, size);
-  builder.create<fir::CallOp>(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::func::FuncOp func, mlir::Value arg) {
-    mlir::Type type = arg.getType();
-    fir::IfOp ifOp{};
-    const bool isOptionalArg =
-        fir::valueHasFirAttribute(arg, fir::getOptionalAttrName());
-    if (type.dyn_cast<fir::PointerType>() || type.dyn_cast<fir::HeapType>()) {
-      // Check for a disassociated pointer or an unallocated allocatable.
-      assert(!isOptionalArg && "invalid optional argument");
-      ifOp = builder.create<fir::IfOp>(loc, builder.genIsNotNullAddr(loc, arg),
-                                       /*withElseRegion=*/false);
-    } else if (isOptionalArg) {
-      ifOp = builder.create<fir::IfOp>(
-          loc, builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), arg),
-          /*withElseRegion=*/false);
-    }
-    if (ifOp)
-      builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
-    mlir::Type kindTy = func.getFunctionType().getInput(0);
-    int integerKind = 8;
-    if (auto intType = fir::unwrapRefType(type).dyn_cast<mlir::IntegerType>())
-      integerKind = intType.getWidth() / 8;
-    mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind);
-    mlir::Value res =
-        builder.create<fir::CallOp>(loc, func, mlir::ValueRange{kind})
-            .getResult(0);
-    mlir::Value castRes =
-        builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res);
-    builder.create<fir::StoreOp>(loc, castRes, arg);
-    if (ifOp)
-      builder.setInsertionPointAfter(ifOp);
-  };
-  using fir::runtime::getRuntimeFunc;
-  if (count)
-    makeCall(getRuntimeFunc<mkRTKey(SystemClockCount)>(loc, builder), count);
-  if (rate)
-    makeCall(getRuntimeFunc<mkRTKey(SystemClockCountRate)>(loc, builder), rate);
-  if (max)
-    makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
-}
index b429d66..d8f40af 100644 (file)
@@ -16,6 +16,7 @@ add_flang_library(FIRBuilder
   Runtime/Derived.cpp
   Runtime/EnvironmentDefaults.cpp
   Runtime/Inquiry.cpp
+  Runtime/Intrinsics.cpp
   Runtime/Numeric.cpp
   Runtime/Ragged.cpp
   Runtime/Reduction.cpp
diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
new file mode 100644 (file)
index 0000000..72fb630
--- /dev/null
@@ -0,0 +1,238 @@
+//===-- Intrinsics.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/Runtime/Intrinsics.h"
+#include "flang/Optimizer/Builder/BoxValue.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Parser/parse-tree.h"
+#include "flang/Runtime/misc-intrinsic.h"
+#include "flang/Runtime/pointer.h"
+#include "flang/Runtime/random.h"
+#include "flang/Runtime/stop.h"
+#include "flang/Runtime/time-intrinsic.h"
+#include "flang/Semantics/tools.h"
+#include "llvm/Support/Debug.h"
+#include <optional>
+
+#define DEBUG_TYPE "flang-lower-runtime"
+
+using namespace Fortran::runtime;
+
+mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder,
+                                        mlir::Location loc, mlir::Value pointer,
+                                        mlir::Value target) {
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(PointerIsAssociatedWith)>(loc,
+                                                                     builder);
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, func.getFunctionType(), pointer, target);
+  return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+mlir::Value fir::runtime::genCpuTime(fir::FirOpBuilder &builder,
+                                     mlir::Location loc) {
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(CpuTime)>(loc, builder);
+  return builder.create<fir::CallOp>(loc, func, std::nullopt).getResult(0);
+}
+
+void fir::runtime::genDateAndTime(fir::FirOpBuilder &builder,
+                                  mlir::Location loc,
+                                  std::optional<fir::CharBoxValue> date,
+                                  std::optional<fir::CharBoxValue> time,
+                                  std::optional<fir::CharBoxValue> zone,
+                                  mlir::Value values) {
+  mlir::func::FuncOp callee =
+      fir::runtime::getRuntimeFunc<mkRTKey(DateAndTime)>(loc, builder);
+  mlir::FunctionType funcTy = callee.getFunctionType();
+  mlir::Type idxTy = builder.getIndexType();
+  mlir::Value zero;
+  auto splitArg = [&](std::optional<fir::CharBoxValue> arg, mlir::Value &buffer,
+                      mlir::Value &len) {
+    if (arg) {
+      buffer = arg->getBuffer();
+      len = arg->getLen();
+    } else {
+      if (!zero)
+        zero = builder.createIntegerConstant(loc, idxTy, 0);
+      buffer = zero;
+      len = zero;
+    }
+  };
+  mlir::Value dateBuffer;
+  mlir::Value dateLen;
+  splitArg(date, dateBuffer, dateLen);
+  mlir::Value timeBuffer;
+  mlir::Value timeLen;
+  splitArg(time, timeBuffer, timeLen);
+  mlir::Value zoneBuffer;
+  mlir::Value zoneLen;
+  splitArg(zone, zoneBuffer, zoneLen);
+
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine =
+      fir::factory::locationToLineNo(builder, loc, funcTy.getInput(7));
+
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, funcTy, dateBuffer, dateLen, timeBuffer, timeLen,
+      zoneBuffer, zoneLen, sourceFile, sourceLine, values);
+  builder.create<fir::CallOp>(loc, callee, args);
+}
+
+void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc,
+                                 mlir::Value repeatable,
+                                 mlir::Value imageDistinct) {
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(RandomInit)>(loc, builder);
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, func.getFunctionType(), repeatable, imageDistinct);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder,
+                                   mlir::Location loc, mlir::Value harvest) {
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder);
+  mlir::FunctionType funcTy = func.getFunctionType();
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine =
+      fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, funcTy, harvest, sourceFile, sourceLine);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+void fir::runtime::genRandomSeed(fir::FirOpBuilder &builder, mlir::Location loc,
+                                 mlir::Value size, mlir::Value put,
+                                 mlir::Value get) {
+  bool sizeIsPresent =
+      !mlir::isa_and_nonnull<fir::AbsentOp>(size.getDefiningOp());
+  bool putIsPresent =
+      !mlir::isa_and_nonnull<fir::AbsentOp>(put.getDefiningOp());
+  bool getIsPresent =
+      !mlir::isa_and_nonnull<fir::AbsentOp>(get.getDefiningOp());
+  mlir::func::FuncOp func;
+  int staticArgCount = sizeIsPresent + putIsPresent + getIsPresent;
+  if (staticArgCount == 0) {
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedDefaultPut)>(loc,
+                                                                       builder);
+    builder.create<fir::CallOp>(loc, func);
+    return;
+  }
+  mlir::FunctionType funcTy;
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine;
+  mlir::Value argBox;
+  llvm::SmallVector<mlir::Value> args;
+  if (staticArgCount > 1) {
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeed)>(loc, builder);
+    funcTy = func.getFunctionType();
+    sourceLine =
+        fir::factory::locationToLineNo(builder, loc, funcTy.getInput(4));
+    args = fir::runtime::createArguments(builder, loc, funcTy, size, put, get,
+                                         sourceFile, sourceLine);
+    builder.create<fir::CallOp>(loc, func, args);
+    return;
+  }
+  if (sizeIsPresent) {
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedSize)>(loc, builder);
+    argBox = size;
+  } else if (putIsPresent) {
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedPut)>(loc, builder);
+    argBox = put;
+  } else {
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedGet)>(loc, builder);
+    argBox = get;
+  }
+  funcTy = func.getFunctionType();
+  sourceLine = fir::factory::locationToLineNo(builder, loc, funcTy.getInput(2));
+  args = fir::runtime::createArguments(builder, loc, funcTy, argBox, sourceFile,
+                                       sourceLine);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+/// generate runtime call to transfer intrinsic with no size argument
+void fir::runtime::genTransfer(fir::FirOpBuilder &builder, mlir::Location loc,
+                               mlir::Value resultBox, mlir::Value sourceBox,
+                               mlir::Value moldBox) {
+
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(Transfer)>(loc, builder);
+  mlir::FunctionType fTy = func.getFunctionType();
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine =
+      fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, fTy, resultBox, sourceBox, moldBox, sourceFile, sourceLine);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+/// generate runtime call to transfer intrinsic with size argument
+void fir::runtime::genTransferSize(fir::FirOpBuilder &builder,
+                                   mlir::Location loc, mlir::Value resultBox,
+                                   mlir::Value sourceBox, mlir::Value moldBox,
+                                   mlir::Value size) {
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(TransferSize)>(loc, builder);
+  mlir::FunctionType fTy = func.getFunctionType();
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine =
+      fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
+  llvm::SmallVector<mlir::Value> args =
+      fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
+                                    moldBox, sourceFile, sourceLine, size);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+/// generate system_clock runtime call/s
+/// all intrinsic arguments are optional and may appear here as mlir::Value{}
+void fir::runtime::genSystemClock(fir::FirOpBuilder &builder,
+                                  mlir::Location loc, mlir::Value count,
+                                  mlir::Value rate, mlir::Value max) {
+  auto makeCall = [&](mlir::func::FuncOp func, mlir::Value arg) {
+    mlir::Type type = arg.getType();
+    fir::IfOp ifOp{};
+    const bool isOptionalArg =
+        fir::valueHasFirAttribute(arg, fir::getOptionalAttrName());
+    if (type.dyn_cast<fir::PointerType>() || type.dyn_cast<fir::HeapType>()) {
+      // Check for a disassociated pointer or an unallocated allocatable.
+      assert(!isOptionalArg && "invalid optional argument");
+      ifOp = builder.create<fir::IfOp>(loc, builder.genIsNotNullAddr(loc, arg),
+                                       /*withElseRegion=*/false);
+    } else if (isOptionalArg) {
+      ifOp = builder.create<fir::IfOp>(
+          loc, builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), arg),
+          /*withElseRegion=*/false);
+    }
+    if (ifOp)
+      builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
+    mlir::Type kindTy = func.getFunctionType().getInput(0);
+    int integerKind = 8;
+    if (auto intType = fir::unwrapRefType(type).dyn_cast<mlir::IntegerType>())
+      integerKind = intType.getWidth() / 8;
+    mlir::Value kind = builder.createIntegerConstant(loc, kindTy, integerKind);
+    mlir::Value res =
+        builder.create<fir::CallOp>(loc, func, mlir::ValueRange{kind})
+            .getResult(0);
+    mlir::Value castRes =
+        builder.createConvert(loc, fir::dyn_cast_ptrEleTy(type), res);
+    builder.create<fir::StoreOp>(loc, castRes, arg);
+    if (ifOp)
+      builder.setInsertionPointAfter(ifOp);
+  };
+  using fir::runtime::getRuntimeFunc;
+  if (count)
+    makeCall(getRuntimeFunc<mkRTKey(SystemClockCount)>(loc, builder), count);
+  if (rate)
+    makeCall(getRuntimeFunc<mkRTKey(SystemClockCountRate)>(loc, builder), rate);
+  if (max)
+    makeCall(getRuntimeFunc<mkRTKey(SystemClockCountMax)>(loc, builder), max);
+}