[flang] [llvm] [flang/flang-rt] Adding support of RAND, IRAND and SRAND intrinsics (PR #166780)
Jean-Didier PAILLEUX via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 20 00:13:18 PST 2025
https://github.com/JDPailleux updated https://github.com/llvm/llvm-project/pull/166780
>From 81fee7c4bf21fb12993f3a5bd14901d502fc9321 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Thu, 6 Nov 2025 13:56:32 +0100
Subject: [PATCH 1/5] [flang/flang-rt] Adding support of RAND, IRAND and SRAND
intrinsics
---
flang-rt/lib/runtime/extensions.cpp | 23 +++++++++++++
flang/docs/Intrinsics.md | 43 ++++++++++++++++++++++++
flang/include/flang/Runtime/extensions.h | 9 +++++
flang/test/Lower/Intrinsics/rand.f90 | 41 ++++++++++++++++++++++
4 files changed, 116 insertions(+)
create mode 100644 flang/test/Lower/Intrinsics/rand.f90
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 19e75143705ab..366406d2a71e4 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -398,6 +398,29 @@ std::int64_t RTNAME(time)() { return time(nullptr); }
// MCLOCK: returns accumulated CPU time in ticks
std::int32_t FORTRAN_PROCEDURE_NAME(mclock)() { return std::clock(); }
+// IRAND(I)
+int FORTRAN_PROCEDURE_NAME(irand)(int i) {
+ switch (i) {
+ case 0:
+ break;
+ case 1:
+ FORTRAN_PROCEDURE_NAME(srand)(0);
+ break;
+ default:
+ FORTRAN_PROCEDURE_NAME(srand)(i);
+ break;
+ }
+ return rand();
+}
+
+// RAND(I)
+float FORTRAN_PROCEDURE_NAME(rand)(int i) {
+ return (float)(FORTRAN_PROCEDURE_NAME(irand)(i));
+}
+
+// SRAND(SEED)
+void FORTRAN_PROCEDURE_NAME(srand)(int seed) { srand(seed); }
+
// Extension procedures related to I/O
namespace io {
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index bfda5f3253a68..af20892edd201 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -1379,3 +1379,46 @@ This is prefixed by `STRING`, a colon and a space.
- **Standard:** GNU extension
- **Class:** subroutine
- **Syntax:** `CALL PERROR(STRING)`
+
+
+### Non-Standard Intrinsics: SRAND
+
+#### Description
+`SAND` reinitializes the pseudo-random number generator called by `RAND` and `IRAND`.
+The new seed used by the generator is specified by the required argument `SEED`.
+
+#### Usage and Info
+
+- **Standard:** GNU extension
+- **Class:** Subroutine
+- **Syntax:** `CALL SRAND(SEED)`
+
+### Non-Standard Intrinsics: IRAND
+
+#### Description
+`IRAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
+If `FLAG` is 0, the next number in the current sequence is returned;
+If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
+If `FLAG` has any other value, it is used as a new seed with `SRAND`.
+The return value is of `INTEGER` type of kind 4.
+
+#### Usage and Info
+
+- **Standard:** GNU extension
+- **Class:** function
+- **Syntax:** `RESULT = IRAND(I)`
+
+### Non-Standard Intrinsics: RAND
+
+#### Description
+`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
+If `FLAG` is 0, the next number in the current sequence is returned;
+If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
+If `FLAG` has any other value, it is used as a new seed with `SRAND`.
+The return value is of `REAL` type with the default kind.
+
+#### Usage and Info
+
+- **Standard:** GNU extension
+- **Class:** function
+- **Syntax:** `RESULT = RAND(I)`
diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h
index 9fd3e118a0f22..73a458b26e2d7 100644
--- a/flang/include/flang/Runtime/extensions.h
+++ b/flang/include/flang/Runtime/extensions.h
@@ -101,5 +101,14 @@ int FORTRAN_PROCEDURE_NAME(mclock)();
float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime);
float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line);
+// GNU extension function IRAND(I)
+int FORTRAN_PROCEDURE_NAME(irand)(int i = 0);
+
+// GNU extension function RAND(I)
+float FORTRAN_PROCEDURE_NAME(rand)(int i = 0);
+
+// GNU extension subroutine SRAND(SEED)
+void FORTRAN_PROCEDURE_NAME(srand)(int seed);
+
} // extern "C"
#endif // FORTRAN_RUNTIME_EXTENSIONS_H_
diff --git a/flang/test/Lower/Intrinsics/rand.f90 b/flang/test/Lower/Intrinsics/rand.f90
new file mode 100644
index 0000000000000..488242fb9180d
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/rand.f90
@@ -0,0 +1,41 @@
+! RUN: bbc -emit-hlfir %s -o - | FileCheck --check-prefixes=CHECK %s
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck --check-prefixes=CHECK %s
+
+! CHECK-LABEL: func @_QPtest_srand(
+subroutine test_srand()
+ integer :: seed = 0
+ call srand(seed)
+ ! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFtest_srandEseed) : !fir.ref<i32>
+ ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_srandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ ! CHECK: fir.call @_QPsrand(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> ()
+ ! CHECK: return
+end subroutine test_srand
+
+! CHECK-LABEL: func @_QPtest_irand(
+subroutine test_irand()
+ integer :: seed = 0
+ integer :: result
+ result = irand(seed)
+ ! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "result", uniq_name = "_QFtest_irandEresult"}
+ ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_irandEresult"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_irandEseed) : !fir.ref<i32>
+ ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_irandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ ! CHECK: %[[VAL_4:.*]] = fir.call @_QPirand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> i32
+ ! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : i32, !fir.ref<i32>
+ ! CHECK: return
+end subroutine test_irand
+
+! CHECK-LABEL: func @_QPtest_rand(
+subroutine test_rand()
+ integer :: seed = 0
+ real :: result
+ result = rand(seed)
+ ! CHECK: %[[VAL_0:.*]] = fir.alloca f32 {bindc_name = "result", uniq_name = "_QFtest_randEresult"}
+ ! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_randEresult"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+ ! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_randEseed) : !fir.ref<i32>
+ ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_randEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ ! CHECK: %[[VAL_4:.*]] = fir.call @_QPrand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> f32
+ ! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : f32, !fir.ref<f32>
+ ! CHECK: return
+end subroutine test_rand
+
>From 6e20512e304209e10607f32d493af3a3cd7cfe60 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Fri, 14 Nov 2025 16:42:41 +0100
Subject: [PATCH 2/5] Update Intrinsics.md
---
flang/docs/Intrinsics.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index af20892edd201..0457b7b0c0c58 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -1384,7 +1384,7 @@ This is prefixed by `STRING`, a colon and a space.
### Non-Standard Intrinsics: SRAND
#### Description
-`SAND` reinitializes the pseudo-random number generator called by `RAND` and `IRAND`.
+`SRAND` reinitializes the pseudo-random number generator called by `RAND` and `IRAND`.
The new seed used by the generator is specified by the required argument `SEED`.
#### Usage and Info
>From f19acea17629b16428be4ede53d123b57d388f66 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Mon, 17 Nov 2025 08:04:32 +0100
Subject: [PATCH 3/5] Update Intrinsics.md
---
flang/docs/Intrinsics.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index 0457b7b0c0c58..2b0a3cb410f71 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -1396,7 +1396,7 @@ The new seed used by the generator is specified by the required argument `SEED`.
### Non-Standard Intrinsics: IRAND
#### Description
-`IRAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
+`IRAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and a system-dependent limit.
If `FLAG` is 0, the next number in the current sequence is returned;
If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
If `FLAG` has any other value, it is used as a new seed with `SRAND`.
@@ -1411,7 +1411,7 @@ The return value is of `INTEGER` type of kind 4.
### Non-Standard Intrinsics: RAND
#### Description
-`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
+`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and a system-dependent limit.
If `FLAG` is 0, the next number in the current sequence is returned;
If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
If `FLAG` has any other value, it is used as a new seed with `SRAND`.
>From ec9a76e1389092a79b58a26029be8b05f9862661 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Thu, 20 Nov 2025 08:01:55 +0100
Subject: [PATCH 4/5] Update IRAND and RAND to use the equivalent
implementation of the GNU extension
---
flang-rt/lib/runtime/extensions.cpp | 50 ++++++++++++++++---
flang/docs/Intrinsics.md | 2 +-
.../flang/Optimizer/Builder/IntrinsicCall.h | 4 ++
.../Optimizer/Builder/Runtime/Intrinsics.h | 5 ++
flang/include/flang/Runtime/extensions.h | 6 +--
flang/lib/Evaluate/intrinsics.cpp | 8 +++
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 35 +++++++++++++
.../Optimizer/Builder/Runtime/Intrinsics.cpp | 20 ++++++++
flang/test/Lower/Intrinsics/rand.f90 | 4 +-
9 files changed, 120 insertions(+), 14 deletions(-)
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 366406d2a71e4..0fb6688a8b812 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -12,6 +12,7 @@
#include "flang/Runtime/extensions.h"
#include "unit.h"
#include "flang-rt/runtime/descriptor.h"
+#include "flang-rt/runtime/lock.h"
#include "flang-rt/runtime/terminator.h"
#include "flang-rt/runtime/tools.h"
#include "flang/Runtime/command.h"
@@ -23,6 +24,7 @@
#include <cstdio>
#include <cstring>
#include <ctime>
+#include <limits>
#include <signal.h>
#include <stdlib.h>
#include <thread>
@@ -60,6 +62,12 @@ inline void CtimeBuffer(char *buffer, size_t bufsize, const time_t cur_time,
namespace Fortran::runtime {
+#define GFC_RAND_A 16807
+#define GFC_RAND_M 2147483647
+#define GFC_RAND_M1 (GFC_RAND_M - 1)
+static unsigned rand_seed = 1;
+static Lock rand_seed_lock;
+
// 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) {
@@ -398,28 +406,54 @@ std::int64_t RTNAME(time)() { return time(nullptr); }
// MCLOCK: returns accumulated CPU time in ticks
std::int32_t FORTRAN_PROCEDURE_NAME(mclock)() { return std::clock(); }
+static void _internal_srand(int seed) { rand_seed = seed ? seed : 123459876; }
+
// IRAND(I)
-int FORTRAN_PROCEDURE_NAME(irand)(int i) {
- switch (i) {
+int RTNAME(Irand)(int *i) {
+ int j;
+ if (i)
+ j = *i;
+ else
+ j = 0;
+
+ rand_seed_lock.Take();
+ switch (j) {
case 0:
break;
case 1:
- FORTRAN_PROCEDURE_NAME(srand)(0);
+ _internal_srand(0);
break;
default:
- FORTRAN_PROCEDURE_NAME(srand)(i);
+ _internal_srand(j);
break;
}
- return rand();
+
+ rand_seed = GFC_RAND_A * rand_seed % GFC_RAND_M;
+ j = (int)rand_seed;
+ rand_seed_lock.Drop();
+ return j;
}
// RAND(I)
-float FORTRAN_PROCEDURE_NAME(rand)(int i) {
- return (float)(FORTRAN_PROCEDURE_NAME(irand)(i));
+float RTNAME(Rand)(int *i) {
+ unsigned mask;
+ auto radix = std::numeric_limits<float>::radix;
+ auto digits = std::numeric_limits<float>::digits;
+ if (radix == 2)
+ mask = ~(unsigned)0u << (32 - digits + 1);
+ else if (radix == 16)
+ mask = ~(unsigned)0u << ((8 - digits) * 4 + 1);
+ else
+ std::fprintf(stderr, "Radix unknown value");
+ return ((unsigned)(RTNAME(Irand)(i) - 1) & mask) * (float)0x1.p-31f;
}
// SRAND(SEED)
-void FORTRAN_PROCEDURE_NAME(srand)(int seed) { srand(seed); }
+void FORTRAN_PROCEDURE_NAME(srand)(int *seed) {
+ rand_seed_lock.Take();
+ _internal_srand(*seed);
+ rand_seed_lock.Drop();
+}
// Extension procedures related to I/O
diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index 2b0a3cb410f71..eb4741f955eac 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -1411,7 +1411,7 @@ The return value is of `INTEGER` type of kind 4.
### Non-Standard Intrinsics: RAND
#### Description
-`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and a system-dependent limit.
+`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
If `FLAG` is 0, the next number in the current sequence is returned;
If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
If `FLAG` has any other value, it is used as a new seed with `SRAND`.
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index 01d27fd5fc399..82cddaaf36517 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -328,6 +328,8 @@ struct IntrinsicLibrary {
fir::ExtendedValue genIndex(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+ fir::ExtendedValue genIrand(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genIsContiguous(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
template <Fortran::runtime::io::Iostat value>
@@ -375,6 +377,8 @@ struct IntrinsicLibrary {
fir::ExtendedValue genProduct(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genPutenv(std::optional<mlir::Type>,
llvm::ArrayRef<fir::ExtendedValue>);
+ fir::ExtendedValue genRand(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue>);
void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
index 7a97172cfbb9a..af00128d7d4b2 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Intrinsics.h
@@ -109,6 +109,11 @@ void genSleep(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value genChdir(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value name);
+mlir::Value genIrand(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value i);
+mlir::Value genRand(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value i);
+
} // namespace runtime
} // namespace fir
diff --git a/flang/include/flang/Runtime/extensions.h b/flang/include/flang/Runtime/extensions.h
index 73a458b26e2d7..35f9131fddede 100644
--- a/flang/include/flang/Runtime/extensions.h
+++ b/flang/include/flang/Runtime/extensions.h
@@ -102,13 +102,13 @@ float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime);
float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line);
// GNU extension function IRAND(I)
-int FORTRAN_PROCEDURE_NAME(irand)(int i = 0);
+int RTNAME(Irand)(int *i);
// GNU extension function RAND(I)
-float FORTRAN_PROCEDURE_NAME(rand)(int i = 0);
+float RTNAME(Rand)(int *i);
// GNU extension subroutine SRAND(SEED)
-void FORTRAN_PROCEDURE_NAME(srand)(int seed);
+void FORTRAN_PROCEDURE_NAME(srand)(int *seed);
} // extern "C"
#endif // FORTRAN_RUNTIME_EXTENSIONS_H_
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 1de5e6b53ba71..e541a139a0648 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -654,6 +654,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{{"i", OperandUnsigned}, {"j", OperandUnsigned, Rank::elementalOrBOZ}},
OperandUnsigned},
{"ior", {{"i", BOZ}, {"j", SameIntOrUnsigned}}, SameIntOrUnsigned},
+ {"irand",
+ {{"i", TypePattern{IntType, KindCode::exactKind, 4}, Rank::scalar,
+ Optionality::optional}},
+ TypePattern{IntType, KindCode::exactKind, 4}, Rank::scalar},
{"ishft", {{"i", SameIntOrUnsigned}, {"shift", AnyInt}}, SameIntOrUnsigned},
{"ishftc",
{{"i", SameIntOrUnsigned}, {"shift", AnyInt},
@@ -872,6 +876,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
common::Intent::In,
{ArgFlag::canBeMoldNull, ArgFlag::onlyConstantInquiry}}},
DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction},
+ {"rand",
+ {{"i", TypePattern{IntType, KindCode::exactKind, 4}, Rank::scalar,
+ Optionality::optional}},
+ TypePattern{RealType, KindCode::exactKind, 4}, Rank::scalar},
{"range",
{{"x", AnyNumeric, Rank::anyOrAssumedRank, Optionality::required,
common::Intent::In,
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 3eb60448fae38..8e71da73a7dbe 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -486,6 +486,10 @@ static constexpr IntrinsicHandler handlers[]{
{"dim", asValue},
{"mask", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
+ {"irand",
+ &I::genIrand,
+ {{{"i", asAddr, handleDynamicOptional}}},
+ /*isElemental=*/false},
{"is_contiguous",
&I::genIsContiguous,
{{{"array", asBox}}},
@@ -612,6 +616,10 @@ static constexpr IntrinsicHandler handlers[]{
&I::genPutenv,
{{{"str", asAddr}, {"status", asAddr, handleDynamicOptional}}},
/*isElemental=*/false},
+ {"rand",
+ &I::genRand,
+ {{{"i", asAddr, handleDynamicOptional}}},
+ /*isElemental=*/false},
{"random_init",
&I::genRandomInit,
{{{"repeatable", asValue}, {"image_distinct", asValue}}},
@@ -6098,6 +6106,20 @@ IntrinsicLibrary::genIparity(mlir::Type resultType,
"IPARITY", resultType, args);
}
+// IRAND
+fir::ExtendedValue
+IntrinsicLibrary::genIrand(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue> args) {
+ assert(args.size() == 1);
+ mlir::Value i =
+ isStaticallyPresent(args[0])
+ ? fir::getBase(args[0])
+ : fir::AbsentOp::create(builder, loc,
+ builder.getRefType(builder.getI32Type()))
+ .getResult();
+ return fir::runtime::genIrand(builder, loc, i);
+}
+
// IS_CONTIGUOUS
fir::ExtendedValue
IntrinsicLibrary::genIsContiguous(mlir::Type resultType,
@@ -7132,6 +7154,19 @@ IntrinsicLibrary::genPutenv(std::optional<mlir::Type> resultType,
return {};
}
+// RAND
+fir::ExtendedValue
+IntrinsicLibrary::genRand(mlir::Type, llvm::ArrayRef<fir::ExtendedValue> args) {
+ assert(args.size() == 1);
+ mlir::Value i =
+ isStaticallyPresent(args[0])
+ ? fir::getBase(args[0])
+ : fir::AbsentOp::create(builder, loc,
+ builder.getRefType(builder.getI32Type()))
+ .getResult();
+ return fir::runtime::genRand(builder, loc, i);
+}
+
// RANDOM_INIT
void IntrinsicLibrary::genRandomInit(llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 2);
diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
index 110b1b20898c7..96b8f3f64b83b 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp
@@ -461,3 +461,23 @@ mlir::Value fir::runtime::genChdir(fir::FirOpBuilder &builder,
fir::runtime::createArguments(builder, loc, func.getFunctionType(), name);
return fir::CallOp::create(builder, loc, func, args).getResult(0);
}
+
+mlir::Value fir::runtime::genIrand(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value i) {
+ auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Irand)>(loc, builder);
+ mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType();
+
+ llvm::SmallVector<mlir::Value> args =
+ fir::runtime::createArguments(builder, loc, runtimeFuncTy, i);
+ return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0);
+}
+
+mlir::Value fir::runtime::genRand(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value i) {
+ auto runtimeFunc = fir::runtime::getRuntimeFunc<mkRTKey(Rand)>(loc, builder);
+ mlir::FunctionType runtimeFuncTy = runtimeFunc.getFunctionType();
+
+ llvm::SmallVector<mlir::Value> args =
+ fir::runtime::createArguments(builder, loc, runtimeFuncTy, i);
+ return fir::CallOp::create(builder, loc, runtimeFunc, args).getResult(0);
+}
diff --git a/flang/test/Lower/Intrinsics/rand.f90 b/flang/test/Lower/Intrinsics/rand.f90
index 488242fb9180d..4f0f17c53c5b9 100644
--- a/flang/test/Lower/Intrinsics/rand.f90
+++ b/flang/test/Lower/Intrinsics/rand.f90
@@ -20,7 +20,7 @@ subroutine test_irand()
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_irandEresult"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_irandEseed) : !fir.ref<i32>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_irandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
- ! CHECK: %[[VAL_4:.*]] = fir.call @_QPirand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> i32
+ ! CHECK: %[[VAL_4:.*]] = fir.call @_FortranAIrand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> i32
! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : i32, !fir.ref<i32>
! CHECK: return
end subroutine test_irand
@@ -34,7 +34,7 @@ subroutine test_rand()
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_randEresult"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_randEseed) : !fir.ref<i32>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_randEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
- ! CHECK: %[[VAL_4:.*]] = fir.call @_QPrand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> f32
+ ! CHECK: %[[VAL_4:.*]] = fir.call @_FortranARand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> f32
! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : f32, !fir.ref<f32>
! CHECK: return
end subroutine test_rand
>From 992160c33cadb9789218391a0af7ec94bc4fbefc Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Thu, 20 Nov 2025 09:12:59 +0100
Subject: [PATCH 5/5] Initialize mask
---
flang-rt/lib/runtime/extensions.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 0fb6688a8b812..301025d6c1a87 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -436,7 +436,7 @@ int RTNAME(Irand)(int *i) {
// RAND(I)
float RTNAME(Rand)(int *i) {
- unsigned mask;
+ unsigned mask = 0;
auto radix = std::numeric_limits<float>::radix;
auto digits = std::numeric_limits<float>::digits;
if (radix == 2)
More information about the llvm-commits
mailing list