[flang-commits] [flang] [llvm] [flang/flang-rt] Adding support of RAND, IRAND and SRAND intrinsics (PR #166780)

via flang-commits flang-commits at lists.llvm.org
Thu Nov 6 06:41:45 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Jean-Didier PAILLEUX (JDPailleux)

<details>
<summary>Changes</summary>

This PR adds support of [RAND](https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gfortran/RAND.html), [IRAND](https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gfortran/IRAND.html) and [SRAND](https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gfortran/SRAND.html) intrinsics in Flang, which are part of the GNU extension.
These intrinsics are used in the following benchmark:  [floatingspeed](https://github.com/ahbarnett/floatingspeed/)

---
Full diff: https://github.com/llvm/llvm-project/pull/166780.diff


4 Files Affected:

- (modified) flang-rt/lib/runtime/extensions.cpp (+23) 
- (modified) flang/docs/Intrinsics.md (+43) 
- (modified) flang/include/flang/Runtime/extensions.h (+9) 
- (added) flang/test/Lower/Intrinsics/rand.f90 (+41) 


``````````diff
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
+

``````````

</details>


https://github.com/llvm/llvm-project/pull/166780


More information about the flang-commits mailing list