[flang-commits] [flang] a1918fd - [flang] Lower random_[init|number|seed] intrinsics

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Tue Mar 15 14:32:03 PDT 2022


Author: Valentin Clement
Date: 2022-03-15T22:31:56+01:00
New Revision: a1918fdf080900333be9eae264eba7cc6608eecc

URL: https://github.com/llvm/llvm-project/commit/a1918fdf080900333be9eae264eba7cc6608eecc
DIFF: https://github.com/llvm/llvm-project/commit/a1918fdf080900333be9eae264eba7cc6608eecc.diff

LOG: [flang] Lower random_[init|number|seed] intrinsics

Thsi patch add the infrastructure to lower the random related
intrinsics:

- `random_init`
- `random_number`
- `random_seed`

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: PeteSteinfeld, schweitz

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

Co-authored-by: V Donaldson <vdonaldson at nvidia.com>
Co-authored-by: Jean Perier <jperier at nvidia.com>

Added: 
    flang/test/Lower/random.f90

Modified: 
    flang/include/flang/Lower/Runtime.h
    flang/lib/Lower/IntrinsicCall.cpp
    flang/lib/Lower/Runtime.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h
index 11aa5bb1c2875..0f6f1e684b0ca 100644
--- a/flang/include/flang/Lower/Runtime.h
+++ b/flang/include/flang/Lower/Runtime.h
@@ -63,6 +63,12 @@ void genPauseStatement(AbstractConverter &, const parser::PauseStmt &);
 mlir::Value genAssociated(fir::FirOpBuilder &, mlir::Location,
                           mlir::Value pointer, mlir::Value target);
 
+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, int argIndex,
+                   mlir::Value argBox);
+
 } // namespace lower
 } // namespace Fortran
 

diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index adb4a324e8248..929d280872571 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -455,6 +455,9 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genMaxval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genMinloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genMinval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
+  void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
+  void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genUbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -463,7 +466,9 @@ struct IntrinsicLibrary {
   /// generate the related code.
   using ElementalGenerator = decltype(&IntrinsicLibrary::genAbs);
   using ExtendedGenerator = decltype(&IntrinsicLibrary::genSum);
-  using Generator = std::variant<ElementalGenerator, ExtendedGenerator>;
+  using SubroutineGenerator = decltype(&IntrinsicLibrary::genRandomInit);
+  using Generator =
+      std::variant<ElementalGenerator, ExtendedGenerator, SubroutineGenerator>;
 
   template <typename GeneratorType>
   fir::ExtendedValue
@@ -491,6 +496,8 @@ struct IntrinsicLibrary {
   mlir::Value invokeGenerator(ExtendedGenerator generator,
                               mlir::Type resultType,
                               llvm::ArrayRef<mlir::Value> args);
+  mlir::Value invokeGenerator(SubroutineGenerator generator,
+                              llvm::ArrayRef<mlir::Value> args);
 
   /// Add clean-up for \p temp to the current statement context;
   void addCleanUpForTemp(mlir::Location loc, mlir::Value temp);
@@ -614,6 +621,17 @@ static constexpr IntrinsicHandler handlers[]{
      {{{"array", asBox},
        {"dim", asValue},
        {"mask", asBox, handleDynamicOptional}}},
+    {"random_init",
+     &I::genRandomInit,
+     {{{"repeatable", asValue}, {"image_distinct", asValue}}},
+     /*isElemental=*/false},
+    {"random_number",
+     &I::genRandomNumber,
+     {{{"harvest", asBox}}},
+     /*isElemental=*/false},
+    {"random_seed",
+     &I::genRandomSeed,
+     {{{"size", asBox}, {"put", asBox}, {"get", asBox}}},
      /*isElemental=*/false},
     {"sum",
      &I::genSum,
@@ -1051,6 +1069,21 @@ IntrinsicLibrary::genElementalCall<IntrinsicLibrary::ExtendedGenerator>(
   return std::invoke(generator, *this, resultType, args);
 }
 
+template <>
+fir::ExtendedValue
+IntrinsicLibrary::genElementalCall<IntrinsicLibrary::SubroutineGenerator>(
+    SubroutineGenerator generator, llvm::StringRef name, mlir::Type resultType,
+    llvm::ArrayRef<fir::ExtendedValue> args, bool outline) {
+  for (const fir::ExtendedValue &arg : args)
+    if (!arg.getUnboxed() && !arg.getCharBox())
+      // fir::emitFatalError(loc, "nonscalar intrinsic argument");
+      crashOnMissingIntrinsic(loc, name);
+  if (outline)
+    return outlineInExtendedWrapper(generator, name, resultType, args);
+  std::invoke(generator, *this, args);
+  return mlir::Value();
+}
+
 static fir::ExtendedValue
 invokeHandler(IntrinsicLibrary::ElementalGenerator generator,
               const IntrinsicHandler &handler,
@@ -1078,6 +1111,22 @@ invokeHandler(IntrinsicLibrary::ExtendedGenerator generator,
   return std::invoke(generator, lib, *resultType, args);
 }
 
+static fir::ExtendedValue
+invokeHandler(IntrinsicLibrary::SubroutineGenerator generator,
+              const IntrinsicHandler &handler,
+              llvm::Optional<mlir::Type> resultType,
+              llvm::ArrayRef<fir::ExtendedValue> args, bool outline,
+              IntrinsicLibrary &lib) {
+  if (handler.isElemental)
+    return lib.genElementalCall(generator, handler.name, mlir::Type{}, args,
+                                outline);
+  if (outline)
+    return lib.outlineInExtendedWrapper(generator, handler.name, resultType,
+                                        args);
+  std::invoke(generator, lib, args);
+  return mlir::Value{};
+}
+
 fir::ExtendedValue
 IntrinsicLibrary::genIntrinsicCall(llvm::StringRef name,
                                    llvm::Optional<mlir::Type> resultType,
@@ -1145,6 +1194,16 @@ IntrinsicLibrary::invokeGenerator(ExtendedGenerator generator,
   return toValue(extendedResult, builder, loc);
 }
 
+mlir::Value
+IntrinsicLibrary::invokeGenerator(SubroutineGenerator generator,
+                                  llvm::ArrayRef<mlir::Value> args) {
+  llvm::SmallVector<fir::ExtendedValue> extendedArgs;
+  for (mlir::Value arg : args)
+    extendedArgs.emplace_back(toExtendedValue(arg, builder, loc));
+  std::invoke(generator, *this, extendedArgs);
+  return {};
+}
+
 template <typename GeneratorType>
 mlir::FuncOp IntrinsicLibrary::getWrapper(GeneratorType generator,
                                           llvm::StringRef name,
@@ -1184,12 +1243,17 @@ mlir::FuncOp IntrinsicLibrary::getWrapper(GeneratorType generator,
 
     IntrinsicLibrary localLib{*localBuilder, localLoc};
 
-    assert(funcType.getNumResults() == 1 &&
-           "expect one result for intrinsic function wrapper type");
-    mlir::Type resultType = funcType.getResult(0);
-    auto result =
-        localLib.invokeGenerator(generator, resultType, localArguments);
-    localBuilder->create<mlir::func::ReturnOp>(localLoc, result);
+    if constexpr (std::is_same_v<GeneratorType, SubroutineGenerator>) {
+      localLib.invokeGenerator(generator, localArguments);
+      localBuilder->create<mlir::func::ReturnOp>(localLoc);
+    } else {
+      assert(funcType.getNumResults() == 1 &&
+             "expect one result for intrinsic function wrapper type");
+      mlir::Type resultType = funcType.getResult(0);
+      auto result =
+          localLib.invokeGenerator(generator, resultType, localArguments);
+      localBuilder->create<mlir::func::ReturnOp>(localLoc, result);
+    }
   } else {
     // Wrapper was already built, ensure it has the sought type
     assert(function.getType() == funcType &&
@@ -1737,6 +1801,31 @@ IntrinsicLibrary::genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue> args) {
   return fir::MutableBoxValue(boxStorage, mold->nonDeferredLenParams(), {});
 }
 
+// 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]));
+}
+
+// RANDOM_NUMBER
+void IntrinsicLibrary::genRandomNumber(
+    llvm::ArrayRef<fir::ExtendedValue> args) {
+  assert(args.size() == 1);
+  Fortran::lower::genRandomNumber(builder, loc, fir::getBase(args[0]));
+}
+
+// RANDOM_SEED
+void IntrinsicLibrary::genRandomSeed(llvm::ArrayRef<fir::ExtendedValue> args) {
+  assert(args.size() == 3);
+  for (int i = 0; i < 3; ++i)
+    if (isPresent(args[i])) {
+      Fortran::lower::genRandomSeed(builder, loc, i, fir::getBase(args[i]));
+      return;
+    }
+  Fortran::lower::genRandomSeed(builder, loc, -1, mlir::Value{});
+}
+
 // SUM
 fir::ExtendedValue
 IntrinsicLibrary::genSum(mlir::Type resultType,

diff  --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
index a246633e450e4..ea42c91378679 100644
--- a/flang/lib/Lower/Runtime.cpp
+++ b/flang/lib/Lower/Runtime.cpp
@@ -14,6 +14,7 @@
 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Runtime/pointer.h"
+#include "flang/Runtime/random.h"
 #include "flang/Runtime/stop.h"
 #include "flang/Semantics/tools.h"
 #include "llvm/Support/Debug.h"
@@ -125,3 +126,59 @@ mlir::Value Fortran::lower::genAssociated(fir::FirOpBuilder &builder,
       builder, loc, func.getType(), pointer, target);
   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
 }
+
+void Fortran::lower::genRandomInit(fir::FirOpBuilder &builder,
+                                   mlir::Location loc, mlir::Value repeatable,
+                                   mlir::Value imageDistinct) {
+  mlir::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(RandomInit)>(loc, builder);
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, func.getType(), repeatable, imageDistinct);
+  builder.create<fir::CallOp>(loc, func, args);
+}
+
+void Fortran::lower::genRandomNumber(fir::FirOpBuilder &builder,
+                                     mlir::Location loc, mlir::Value harvest) {
+  mlir::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder);
+  mlir::FunctionType funcTy = func.getType();
+  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, int argIndex,
+                                   mlir::Value argBox) {
+  mlir::FuncOp func;
+  // argIndex is the nth (0-origin) argument in declaration order,
+  // or -1 if no argument is present.
+  switch (argIndex) {
+  case -1:
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedDefaultPut)>(loc,
+                                                                       builder);
+    builder.create<fir::CallOp>(loc, func);
+    return;
+  case 0:
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedSize)>(loc, builder);
+    break;
+  case 1:
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedPut)>(loc, builder);
+    break;
+  case 2:
+    func = fir::runtime::getRuntimeFunc<mkRTKey(RandomSeedGet)>(loc, builder);
+    break;
+  default:
+    llvm::report_fatal_error("invalid RANDOM_SEED argument index");
+  }
+  mlir::FunctionType funcTy = func.getType();
+  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, argBox, sourceFile, sourceLine);
+  builder.create<fir::CallOp>(loc, func, args);
+}

diff  --git a/flang/test/Lower/random.f90 b/flang/test/Lower/random.f90
new file mode 100644
index 0000000000000..0f6c38e84759d
--- /dev/null
+++ b/flang/test/Lower/random.f90
@@ -0,0 +1,41 @@
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPrandom_test
+subroutine random_test
+    ! CHECK-DAG: [[ss:%[0-9]+]] = fir.alloca {{.*}}random_testEss
+    ! CHECK-DAG: [[vv:%[0-9]+]] = fir.alloca {{.*}}random_testEvv
+    integer ss, vv(40)
+    ! CHECK-DAG: [[rr:%[0-9]+]] = fir.alloca {{.*}}random_testErr
+    ! CHECK-DAG: [[aa:%[0-9]+]] = fir.alloca {{.*}}random_testEaa
+    real rr, aa(5)
+    ! CHECK: fir.call @_FortranARandomInit(%true{{.*}}, %false{{.*}}) : (i1, i1) -> none
+    call random_init(.true., .false.)
+    ! CHECK: [[box:%[0-9]+]] = fir.embox [[ss]]
+    ! CHECK: [[argbox:%[0-9]+]] = fir.convert [[box]]
+    ! CHECK: fir.call @_FortranARandomSeedSize([[argbox]]
+    call random_seed(size=ss)
+    print*, 'size: ', ss
+    ! CHECK: fir.call @_FortranARandomSeedDefaultPut() : () -> none
+    call random_seed()
+    ! CHECK: [[box:%[0-9]+]] = fir.embox [[rr]]
+    ! CHECK: [[argbox:%[0-9]+]] = fir.convert [[box]]
+    ! CHECK: fir.call @_FortranARandomNumber([[argbox]]
+    call random_number(rr)
+    print*, rr
+    ! CHECK: [[box:%[0-9]+]] = fir.embox [[vv]]
+    ! CHECK: [[argbox:%[0-9]+]] = fir.convert [[box]]
+    ! CHECK: fir.call @_FortranARandomSeedGet([[argbox]]
+    call random_seed(get=vv)
+  ! print*, 'get:  ', vv(1:ss)
+    ! CHECK: [[box:%[0-9]+]] = fir.embox [[vv]]
+    ! CHECK: [[argbox:%[0-9]+]] = fir.convert [[box]]
+    ! CHECK: fir.call @_FortranARandomSeedPut([[argbox]]
+    call random_seed(put=vv)
+    print*, 'put:  ', vv(1:ss)
+    ! CHECK: [[box:%[0-9]+]] = fir.embox [[aa]]
+    ! CHECK: [[argbox:%[0-9]+]] = fir.convert [[box]]
+    ! CHECK: fir.call @_FortranARandomNumber([[argbox]]
+    call random_number(aa)
+    print*, aa
+  end
+  
\ No newline at end of file


        


More information about the flang-commits mailing list