[flang-commits] [flang] [flang] Reclassify MVBITS, SPLIT, and TOKENIZE as SIMPLE (PR #205024)
via flang-commits
flang-commits at lists.llvm.org
Sun Jun 21 19:36:20 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Šárka Holendová (mlir-maiden)
<details>
<summary>Changes</summary>
F2023 makes MVBITS a simple elemental subroutine and SPLIT/TOKENIZE simple subroutines.
This change:
- adds `simpleSubroutine` and `simpleElementalSubroutine` to `IntrinsicClass`,
- reclassifies the MVBITS, SPLIT, and TOKENIZE intrinsic table entries,
- propagates `SIMPLE` through intrinsic resolution and procedure characteristics.
MOVE_ALLOC is not included in this change.
---
Full diff: https://github.com/llvm/llvm-project/pull/205024.diff
4 Files Affected:
- (modified) flang/include/flang/Evaluate/intrinsics.h (+2-1)
- (modified) flang/lib/Evaluate/intrinsics.cpp (+11-7)
- (modified) flang/lib/Semantics/resolve-names.cpp (+7)
- (added) flang/test/Semantics/simple-intrinsics.f90 (+49)
``````````diff
diff --git a/flang/include/flang/Evaluate/intrinsics.h b/flang/include/flang/Evaluate/intrinsics.h
index 0d6c513606c19..dfc44d1e45da9 100644
--- a/flang/include/flang/Evaluate/intrinsics.h
+++ b/flang/include/flang/Evaluate/intrinsics.h
@@ -63,7 +63,8 @@ struct SpecificIntrinsicFunctionInterface : public characteristics::Procedure {
// Generic intrinsic classes from table 16.1
ENUM_CLASS(IntrinsicClass, atomicSubroutine, collectiveSubroutine,
elementalFunction, elementalSubroutine, inquiryFunction, pureSubroutine,
- impureFunction, impureSubroutine, transformationalFunction, noClass)
+ simpleSubroutine, simpleElementalSubroutine, impureFunction,
+ impureSubroutine, transformationalFunction, noClass)
class IntrinsicProcTable {
private:
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index bc0026746c05c..356e08a512951 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -1708,7 +1708,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
{"to", SameIntOrUnsigned, Rank::elemental, Optionality::required,
common::Intent::Out},
{"topos", AnyInt}},
- {}, Rank::elemental, IntrinsicClass::elementalSubroutine},
+ {}, Rank::elemental, IntrinsicClass::simpleElementalSubroutine},
{"random_init",
{{"repeatable", AnyLogical, Rank::scalar},
{"image_distinct", AnyLogical, Rank::scalar}},
@@ -1770,7 +1770,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
common::Intent::InOut},
{"back", AnyLogical, Rank::scalar, Optionality::optional,
common::Intent::In}},
- {}, Rank::elemental, IntrinsicClass::pureSubroutine},
+ {}, Rank::elemental, IntrinsicClass::simpleSubroutine},
{"tokenize",
{{"string", SameCharNoLen, Rank::scalar, Optionality::required,
common::Intent::In},
@@ -1780,7 +1780,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
common::Intent::Out},
{"separator", SameCharNoLen, Rank::vector, Optionality::optional,
common::Intent::Out}},
- {}, Rank::elemental, IntrinsicClass::pureSubroutine},
+ {}, Rank::elemental, IntrinsicClass::simpleSubroutine},
{"tokenize",
{{"string", SameCharNoLen, Rank::scalar, Optionality::required,
common::Intent::In},
@@ -1790,7 +1790,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
common::Intent::Out},
{"last", AnyInt, Rank::vector, Optionality::required,
common::Intent::Out}},
- {}, Rank::elemental, IntrinsicClass::pureSubroutine},
+ {}, Rank::elemental, IntrinsicClass::simpleSubroutine},
{"unlink",
{{"path", DefaultChar, Rank::scalar, Optionality::required,
common::Intent::In},
@@ -2876,10 +2876,14 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (elementalRank > 0) {
attrs.set(characteristics::Procedure::Attr::Elemental);
}
- // TODO: Mark intrinsic procedures that are SIMPLE per F2023
if (call.isSubroutineCall) {
- if (intrinsicClass == IntrinsicClass::pureSubroutine /* MOVE_ALLOC */ ||
- intrinsicClass == IntrinsicClass::elementalSubroutine /* MVBITS */) {
+ if (intrinsicClass == IntrinsicClass::pureSubroutine /* MOVE_ALLOC */) {
+ // TODO: set Attr::Simple for MOVE_ALLOC when FROM is not a coarray
+ // (F2023)
+ attrs.set(characteristics::Procedure::Attr::Pure);
+ } else if (intrinsicClass == IntrinsicClass::simpleSubroutine ||
+ intrinsicClass == IntrinsicClass::simpleElementalSubroutine) {
+ attrs.set(characteristics::Procedure::Attr::Simple);
attrs.set(characteristics::Procedure::Attr::Pure);
}
return SpecificCall{
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 6d2d0bf24b194..f7cff0b3af046 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -3471,6 +3471,13 @@ void ScopeHandler::AcquireIntrinsicProcedureFlags(Symbol &symbol) {
SetExplicitAttr(symbol, Attr::ELEMENTAL);
SetExplicitAttr(symbol, Attr::PURE);
break;
+ case evaluate::IntrinsicClass::simpleElementalSubroutine:
+ SetExplicitAttr(symbol, Attr::ELEMENTAL);
+ SetExplicitAttr(symbol, Attr::SIMPLE);
+ break;
+ case evaluate::IntrinsicClass::simpleSubroutine:
+ SetExplicitAttr(symbol, Attr::SIMPLE);
+ break;
case evaluate::IntrinsicClass::impureSubroutine:
break;
default:
diff --git a/flang/test/Semantics/simple-intrinsics.f90 b/flang/test/Semantics/simple-intrinsics.f90
new file mode 100644
index 0000000000000..c5f02017f130e
--- /dev/null
+++ b/flang/test/Semantics/simple-intrinsics.f90
@@ -0,0 +1,49 @@
+! RUN: %python %S/test_symbols.py %s %flang_fc1
+! Fortran 2023 classifies MVBITS, SPLIT, and TOKENIZE as SIMPLE
+! intrinsic subroutines. Verify that their symbols resolve with the
+! SIMPLE attribute. MVBITS is also ELEMENTAL.
+
+!DEF: /expect_simple_intrinsics (Subroutine) Subprogram
+!DEF: /expect_simple_intrinsics/string INTENT(IN) ObjectEntity CHARACTER(*,1)
+!DEF: /expect_simple_intrinsics/set INTENT(IN) ObjectEntity CHARACTER(*,1)
+!DEF: /expect_simple_intrinsics/from INTENT(IN) ObjectEntity INTEGER(4)
+!DEF: /expect_simple_intrinsics/to INTENT(INOUT) ObjectEntity INTEGER(4)
+subroutine expect_simple_intrinsics (string, set, from, to)
+ !REF: /expect_simple_intrinsics/string
+ !REF: /expect_simple_intrinsics/set
+ character(len=*), intent(in) :: string, set
+ !REF: /expect_simple_intrinsics/from
+ integer, intent(in) :: from
+ !REF: /expect_simple_intrinsics/to
+ integer, intent(inout) :: to
+ !DEF: /expect_simple_intrinsics/pos ObjectEntity INTEGER(4)
+ integer pos
+ !DEF: /expect_simple_intrinsics/tokens ALLOCATABLE ObjectEntity CHARACTER(:,1)
+ character(len=:), allocatable :: tokens(:)
+ !DEF: /expect_simple_intrinsics/first ALLOCATABLE ObjectEntity INTEGER(4)
+ !DEF: /expect_simple_intrinsics/last ALLOCATABLE ObjectEntity INTEGER(4)
+ integer, allocatable :: first(:), last(:)
+ !REF: /expect_simple_intrinsics/pos
+ pos = 1
+ !DEF: /expect_simple_intrinsics/split INTRINSIC, SIMPLE (Subroutine) ProcEntity
+ !REF: /expect_simple_intrinsics/string
+ !REF: /expect_simple_intrinsics/set
+ !REF: /expect_simple_intrinsics/pos
+ call split(string, set, pos)
+ !DEF: /expect_simple_intrinsics/tokenize INTRINSIC, SIMPLE (Subroutine) ProcEntity
+ !REF: /expect_simple_intrinsics/string
+ !REF: /expect_simple_intrinsics/set
+ !REF: /expect_simple_intrinsics/tokens
+ call tokenize(string, set, tokens)
+ !REF: /expect_simple_intrinsics/tokenize
+ !REF: /expect_simple_intrinsics/string
+ !REF: /expect_simple_intrinsics/set
+ !REF: /expect_simple_intrinsics/first
+ !REF: /expect_simple_intrinsics/last
+ call tokenize(string, set, first, last)
+ !DEF: /expect_simple_intrinsics/mvbits ELEMENTAL, INTRINSIC, SIMPLE (Subroutine) ProcEntity
+ !REF: /expect_simple_intrinsics/from
+ !REF: /expect_simple_intrinsics/to
+ call mvbits(from, 0, 1, to, 2)
+end subroutine
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/205024
More information about the flang-commits
mailing list