[Mlir-commits] [flang] [mlir] [flang][OpenMP] Support for "omp assumes absent" (PR #236693)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Oct 29 01:47:21 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-flang-openmp

Author: SunilKuravinakop

<details>
<summary>Changes</summary>

Support for "absent" clause in "assumes" directive.

---

Patch is 28.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/236693.diff


14 Files Affected:

- (modified) flang/docs/OpenMPSupport.md (+1-1) 
- (modified) flang/include/flang/Semantics/scope.h (+9) 
- (modified) flang/lib/Lower/Bridge.cpp (+29-12) 
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+2-1) 
- (modified) flang/lib/Semantics/mod-file.cpp (+9) 
- (modified) flang/lib/Semantics/resolve-directives.cpp (+12-5) 
- (modified) flang/lib/Semantics/resolve-names.cpp (+8) 
- (modified) flang/test/Lower/OpenMP/Todo/assumes.f90 (+13-7) 
- (renamed) flang/test/Lower/OpenMP/assumption-submodule.f90 (+11-1) 
- (modified) flang/test/Lower/OpenMP/assumption.f90 (+150-10) 
- (modified) flang/test/Parser/OpenMP/assumption.f90 (+21) 
- (modified) flang/test/Semantics/OpenMP/declarative-directive01.f90 (+31) 
- (modified) mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir (+2-2) 
- (modified) mlir/test/Target/LLVMIR/llvmir.mlir (+2-2) 


``````````diff
diff --git a/flang/docs/OpenMPSupport.md b/flang/docs/OpenMPSupport.md
index 63c1c3b66ad0a2..fee2b324f51d3c 100644
--- a/flang/docs/OpenMPSupport.md
+++ b/flang/docs/OpenMPSupport.md
@@ -197,7 +197,7 @@ Parser/Semantics, MLIR, Lowering, or the OpenMPIRBuilder.
 | nothing directive | <span class="good">done</span> | | Parser and lowering coverage exists for standalone and metadirective-selected forms (`flang/test/Parser/OpenMP/nothing.f90`, `flang/test/Lower/OpenMP/nothing.f90`, `flang/test/Lower/OpenMP/metadirective-nothing.f90`). | [llvm/llvm-project#193664](https://github.com/llvm/llvm-project/pull/193664), [llvm/llvm-project#202679](https://github.com/llvm/llvm-project/pull/202679) |
 | tile and unroll constructs | <span class="part">partial</span> | | Semantics coverage exists across tile/unroll and loop-transformation tests (`flang/test/Semantics/OpenMP/tile01.f90`, `flang/test/Semantics/OpenMP/tile09.f90`, `flang/test/Semantics/OpenMP/loop-transformation-construct01.f90`), with additional lowering/transform completeness work ongoing. The `full` and `partial` clauses on `unroll` are lowered (`flang/test/Lower/OpenMP/unroll-full01.f90`, `flang/test/Lower/OpenMP/unroll-partial01.f90`). | [llvm/llvm-project#160298](https://github.com/llvm/llvm-project/pull/160298), [llvm/llvm-project#185296](https://github.com/llvm/llvm-project/pull/185296), [llvm/llvm-project#188025](https://github.com/llvm/llvm-project/pull/188025) |
 | scope construct | <span class="part">partial</span> | | Scope construct support is available, with follow-on completeness work still in progress for some combinations (see also OpenMP 5.2 scope-related rows). | [llvm/llvm-project#113700](https://github.com/llvm/llvm-project/pull/113700), [llvm/llvm-project#193098](https://github.com/llvm/llvm-project/pull/193098) |
-| assumes directives | <span class="part">partial</span> | | `no_openmp` is supported. For OpenMP 5.2 and earlier, module-level assumptions are preserved in module files for separately compiled submodules. Other clauses remain TODO-tracked (`flang/test/Lower/OpenMP/assumption.f90`, `flang/test/Lower/OpenMP/Todo/assumes.f90`). | [llvm/llvm-project#102008](https://github.com/llvm/llvm-project/pull/102008) |
+| assumes directives | <span class="part">partial</span> | | `no_openmp` and `absent` are supported. Other clauses remain TODO-tracked (`flang/test/Lower/OpenMP/assumption.f90`, `flang/test/Lower/OpenMP/Todo/assumes.f90`). | [llvm/llvm-project#102008](https://github.com/llvm/llvm-project/pull/102008) |
 | assume directive | <span class="none">unclaimed</span> | | Lowering still has explicit TODO (`flang/lib/Lower/OpenMP/OpenMP.cpp` TODO: `OpenMP ASSUME construct`; `flang/test/Lower/OpenMP/Todo/assume.f90`). | [llvm/llvm-project#102008](https://github.com/llvm/llvm-project/pull/102008) |
 | default(firstprivate) | <span class="good">done</span> | | Supported for `default(firstprivate)` clause forms, with semantics and lowering coverage (`flang/test/Semantics/OpenMP/default-clause.f90`, `flang/test/Lower/OpenMP/default-clause.f90`, `flang/test/Lower/OpenMP/default-clause-byref.f90`). | [D123930](https://reviews.llvm.org/D123930) |
 | default(private) | <span class="part">partial</span> | | Semantics/default-clause coverage exists (`flang/test/Semantics/OpenMP/default.f90`, `flang/test/Semantics/OpenMP/default02.f90`) with ongoing lowering completeness checks. | [llvm/llvm-project#107586](https://github.com/llvm/llvm-project/pull/107586) |
diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h
index c3cb663dea2366..0536ec028dd81e 100644
--- a/flang/include/flang/Semantics/scope.h
+++ b/flang/include/flang/Semantics/scope.h
@@ -16,6 +16,7 @@
 #include "flang/Parser/message.h"
 #include "flang/Parser/provenance.h"
 #include "flang/Support/Fortran.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 #include <list>
 #include <map>
 #include <optional>
@@ -275,6 +276,13 @@ class Scope {
   bool hasSAVE() const { return hasSAVE_; }
   void set_hasSAVE(bool yes = true) { hasSAVE_ = yes; }
 
+  const std::set<llvm::omp::Directive> &ompAssumesAbsent() const {
+    return ompAssumesAbsent_;
+  }
+  void add_ompAssumesAbsent(llvm::omp::Directive directive) {
+    ompAssumesAbsent_.insert(directive);
+  }
+
   // The range of the source of this and nested scopes.
   const parser::CharBlock &sourceRange() const { return sourceRange_; }
   void AddSourceRange(parser::CharBlock);
@@ -327,6 +335,7 @@ class Scope {
   std::optional<ImportKind> importKind_;
   std::set<SourceName> importNames_;
   UnorderedSymbolSet openACCMappedSymbols_;
+  std::set<llvm::omp::Directive> ompAssumesAbsent_;
   DerivedTypeSpec *derivedTypeSpec_{nullptr}; // dTS->scope() == this
   parser::Message::Reference instantiationContext_;
   bool hasSAVE_{false}; // scope has a bare SAVE statement
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index f7c3796c266d9a..05601f87449701 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -86,6 +86,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Target/TargetMachine.h"
 #include <optional>
+#include <set>
 
 #define DEBUG_TYPE "flang-lower-bridge"
 
@@ -6508,26 +6509,42 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
   void setOpenMPAssumptionAttributes(mlir::func::FuncOp func,
                                      const Fortran::semantics::Scope &scope) {
-    if (bridge.getSemanticsContext().langOptions().OpenMPSimd)
+    const auto &langOptions = bridge.getSemanticsContext().langOptions();
+    if (langOptions.OpenMPSimd)
       return;
     const auto *assumptionScopeEnd =
         &Fortran::semantics::omp::GetProgramUnit(scope).parent();
+    bool noOpenmp = false;
+    std::set<llvm::omp::Directive> absent;
     for (const auto *assumptionScope = &scope;
          !assumptionScope->IsGlobal() && assumptionScope != assumptionScopeEnd;
          assumptionScope = &assumptionScope->parent()) {
       if (const auto *symbol = assumptionScope->symbol();
-          !symbol ||
-          !symbol->test(Fortran::semantics::Symbol::Flag::OmpAssumesNoOpenmp))
-        continue;
-      llvm::SmallVector<mlir::Attribute> llvmAttrs;
-      if (auto existing =
-              func->getAttrOfType<mlir::ArrayAttr>("llvm.passthrough"))
-        llvm::append_range(llvmAttrs, existing);
-      llvmAttrs.push_back(
-          builder->getStrArrayAttr({llvm::AssumptionAttrKey, "omp_no_openmp"}));
-      func->setAttr("llvm.passthrough", builder->getArrayAttr(llvmAttrs));
-      break;
+          symbol &&
+          symbol->test(Fortran::semantics::Symbol::Flag::OmpAssumesNoOpenmp))
+        noOpenmp = true;
+      const auto &directives = assumptionScope->ompAssumesAbsent();
+      absent.insert(directives.begin(), directives.end());
     }
+    if (!noOpenmp && absent.empty())
+      return;
+    std::string assumptions = noOpenmp ? "omp_no_openmp" : "";
+    for (llvm::omp::Directive directive : absent) {
+      if (!assumptions.empty())
+        assumptions += ',';
+      assumptions += "absent(";
+      assumptions += llvm::omp::getOpenMPDirectiveName(
+                         directive, langOptions.getOpenMPVersion())
+                         .str();
+      assumptions += ')';
+    }
+    llvm::SmallVector<mlir::Attribute> llvmAttrs;
+    if (auto existing =
+            func->getAttrOfType<mlir::ArrayAttr>("llvm.passthrough"))
+      llvm::append_range(llvmAttrs, existing);
+    llvmAttrs.push_back(
+        builder->getStrArrayAttr({llvm::AssumptionAttrKey, assumptions}));
+    func->setAttr("llvm.passthrough", builder->getArrayAttr(llvmAttrs));
   }
 
   /// Start translation of a function.
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 3ce793989dee30..004f68418fd66a 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -5951,7 +5951,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
     return;
 
   for (const parser::OmpClause &clause : assumesConstruct.v.Clauses().v) {
-    if (!std::holds_alternative<parser::OmpClause::NoOpenmp>(clause.u))
+    if (!std::holds_alternative<parser::OmpClause::NoOpenmp>(clause.u) &&
+        !std::holds_alternative<parser::OmpClause::Absent>(clause.u))
       TODO(converter.genLocation(clause.source),
            "assumption clauses on the assumes directive");
   }
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index dae665eb67500e..b90a8f16bec535 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -473,6 +473,15 @@ void ModFileWriter::PutSymbols(
   if (scope.symbol()->test(Symbol::Flag::OmpAssumesNoOpenmp)) {
     decls_ << "!$omp assumes no_openmp\n";
   }
+  if (!scope.ompAssumesAbsent().empty()) {
+    decls_ << "!$omp assumes absent(";
+    llvm::interleaveComma(
+        scope.ompAssumesAbsent(), decls_, [&](llvm::omp::Directive directive) {
+          decls_ << llvm::omp::getOpenMPDirectiveName(
+              directive, context_.langOptions().getOpenMPVersion());
+        });
+    decls_ << ")\n";
+  }
   PutOpenMPDeclarativeDirectives(decls_, sorted, context_);
 
   for (const auto &set : scope.equivalenceSets()) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 9b15b979c0d1ae..6d90816c244585 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -501,11 +501,18 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
     if (x.moduleName.symbol) {
       Scope &thisScope{context_.FindScope(x.moduleName.source)};
       const auto version{context_.langOptions().getOpenMPVersion()};
-      if ((version == 51 || version == 52) &&
-          x.moduleName.symbol->test(Symbol::Flag::OmpAssumesNoOpenmp)) {
-        if (auto *symbol{const_cast<Symbol *>(
-                omp::GetProgramUnit(thisScope).symbol())}) {
-          symbol->set(Symbol::Flag::OmpAssumesNoOpenmp);
+      if (version == 51 || version == 52) {
+        Scope &programUnit{const_cast<Scope &>(omp::GetProgramUnit(thisScope))};
+        if (x.moduleName.symbol->test(Symbol::Flag::OmpAssumesNoOpenmp)) {
+          if (auto *symbol{const_cast<Symbol *>(programUnit.symbol())}) {
+            symbol->set(Symbol::Flag::OmpAssumesNoOpenmp);
+          }
+        }
+        if (const auto *moduleScope{x.moduleName.symbol->scope()}) {
+          for (llvm::omp::Directive directive :
+              moduleScope->ompAssumesAbsent()) {
+            programUnit.add_ompAssumesAbsent(directive);
+          }
         }
       }
       common::visit(
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 6dd69a7d210dbd..a0c1ebf4349eac 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1859,6 +1859,14 @@ class OmpVisitor : public virtual DeclarationVisitor {
         symbol->set(Symbol::Flag::OmpAssumesNoOpenmp);
       }
     }
+    for (const parser::OmpClause &clause : x.v.Clauses().v) {
+      if (const auto *absent{
+              std::get_if<parser::OmpClause::Absent>(&clause.u)}) {
+        for (llvm::omp::Directive directive : absent->v.v) {
+          currScope().add_ompAssumesAbsent(directive);
+        }
+      }
+    }
   }
 
   // Make sure that the following code is properly handled:
diff --git a/flang/test/Lower/OpenMP/Todo/assumes.f90 b/flang/test/Lower/OpenMP/Todo/assumes.f90
index 256307bb737f70..ff535cfe4177e5 100644
--- a/flang/test/Lower/OpenMP/Todo/assumes.f90
+++ b/flang/test/Lower/OpenMP/Todo/assumes.f90
@@ -3,7 +3,8 @@
 ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-openmp-first.f90 2>&1 | FileCheck %s
 ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-openmp-last.f90 2>&1 | FileCheck %s
 ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/no-openmp-routines.f90 2>&1 | FileCheck %s
-! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/absent.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/absent-first.f90 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/absent-last.f90 2>&1 | FileCheck %s
 ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/contains.f90 2>&1 | FileCheck %s
 ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %t/holds.f90 2>&1 | FileCheck %s
 
@@ -24,22 +25,27 @@ subroutine p
   !$omp assumes no_parallelism no_openmp
 end subroutine p
 
-!--- no-openmp-routines.f90
+!--- absent-first.f90
 subroutine p
-  !$omp assumes no_openmp no_openmp_routines
+  !$omp assumes absent(parallel) no_parallelism
 end subroutine p
 
-!--- absent.f90
+!--- absent-last.f90
+subroutine p
+  !$omp assumes no_parallelism absent(parallel)
+end subroutine p
+
+!--- no-openmp-routines.f90
 subroutine p
-  !$omp assumes no_openmp absent(parallel)
+  !$omp assumes no_openmp absent(parallel) no_openmp_routines
 end subroutine p
 
 !--- contains.f90
 subroutine p
-  !$omp assumes no_openmp contains(parallel)
+  !$omp assumes no_openmp absent(parallel) contains(task)
 end subroutine p
 
 !--- holds.f90
 subroutine p
-  !$omp assumes no_openmp holds(.true.)
+  !$omp assumes no_openmp absent(parallel) holds(.true.)
 end subroutine p
diff --git a/flang/test/Lower/OpenMP/assumption-noopenmp-submodule.f90 b/flang/test/Lower/OpenMP/assumption-submodule.f90
similarity index 68%
rename from flang/test/Lower/OpenMP/assumption-noopenmp-submodule.f90
rename to flang/test/Lower/OpenMP/assumption-submodule.f90
index 2d57eb312e9658..cdf810f028d050 100644
--- a/flang/test/Lower/OpenMP/assumption-noopenmp-submodule.f90
+++ b/flang/test/Lower/OpenMP/assumption-submodule.f90
@@ -17,8 +17,18 @@
   implicit none
 contains
   ! CHECK-LABEL: func.func @_QMuse_parentPimported_work()
-  ! CHECK5X-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+  ! CHECK5X-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp,absent(barrier),absent(parallel)"]]
   ! CHECK60-NOT: "omp_no_openmp"
   module procedure imported_work
   end procedure imported_work
 end submodule use_child_reload
+
+submodule (use_parent) absent_use_child_reload
+  use absent_reexport, only:
+contains
+  ! CHECK-LABEL: func.func @_QMuse_parentPabsent_imported_work()
+  ! CHECK5X-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "absent(barrier),absent(parallel),absent(target)"]]
+  ! CHECK60-NOT: llvm.passthrough
+  module procedure absent_imported_work
+  end procedure absent_imported_work
+end submodule absent_use_child_reload
diff --git a/flang/test/Lower/OpenMP/assumption.f90 b/flang/test/Lower/OpenMP/assumption.f90
index ca2e522a0b790d..b43022c6c983ff 100644
--- a/flang/test/Lower/OpenMP/assumption.f90
+++ b/flang/test/Lower/OpenMP/assumption.f90
@@ -1,13 +1,12 @@
 ! RUN: mkdir -p %t
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -module-dir %t -o - %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK5X,SCOPE,SCOPE5X
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -module-dir %t -o - %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK5X,SUBMODULE,SCOPE,SCOPE5X,ABSENT,ABSENT5X,RELOAD,RELOAD5X
 ! RUN: FileCheck %s --check-prefix=MODFILE --input-file=%t/assumes_module.mod
-! RUN: FileCheck %s --check-prefix=USE-MODFILE --input-file=%t/use_parent-use_child.mod
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -module-dir %t -o - %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK60,SCOPE,SCOPE60
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -module-dir %t -o - %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK60,SUBMODULE,SCOPE,SCOPE60,ABSENT,ABSENT60,RELOAD,RELOAD60
 ! RUN: %flang_fc1 -emit-hlfir -fopenmp-simd -fopenmp-version=51 -module-dir %t -o - %s | FileCheck %s --check-prefix=SIMD
 ! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=51 -module-dir %t %s | FileCheck %s --check-prefix=SYMBOLS
 
 ! SIMD: module
-! SIMD-NOT: "omp_no_openmp"
+! SIMD-NOT: "llvm.assume"
 
 ! SYMBOLS-DAG: assume_block (Subroutine): Subprogram
 ! SYMBOLS-DAG: assumes_module (OmpAssumesNoOpenmp): Module
@@ -21,7 +20,7 @@
 ! always lowered.
 
 ! CHECK-LABEL: func.func @_QPassume_block
-! CHECK-NOT: "omp_no_openmp"
+! CHECK-NOT: llvm.passthrough
 subroutine assume_block(x)
   integer :: x
   ! CHECK: %[[DECL:.*]]:2 = hlfir.declare
@@ -126,19 +125,29 @@ subroutine assumes_no_openmp_local
   call set_value(x)
 end subroutine assumes_no_openmp_local
 
+submodule (assumes_module) assumes_implementation
+contains
+  module procedure separate_work
+  end procedure separate_work
+end submodule assumes_implementation
+
 ! MODFILE: module assumes_module
 ! MODFILE: !$omp assumes no_openmp
 
+! SUBMODULE-LABEL: func.func @_QMassumes_modulePseparate_work()
+! SUBMODULE-NOT: "omp_no_openmp"
+! SUBMODULE: return
+
 module scoped_assumes
   implicit none
-  !$omp assumes no_openmp
+  !$omp assumes no_openmp absent(parallel, barrier)
   interface
     module subroutine independent_work() bind(C, name="independent_work")
     end subroutine independent_work
   end interface
 contains
   ! SCOPE-LABEL: func.func @_QMscoped_assumesPmodule_work()
-  ! SCOPE-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+  ! SCOPE-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp,absent(barrier),absent(parallel)"]]
   subroutine module_work()
   end subroutine module_work
 end module scoped_assumes
@@ -146,7 +155,7 @@ end module scoped_assumes
 submodule (scoped_assumes) scoped_implementation
 contains
   ! SCOPE-LABEL: func.func @independent_work()
-  ! SCOPE-NOT: "omp_no_openmp"
+  ! SCOPE-NOT: llvm.passthrough
   module procedure independent_work
     ! SCOPE: omp.parallel {
     !$omp parallel
@@ -167,17 +176,148 @@ module use_parent
   interface
     module subroutine imported_work()
     end subroutine imported_work
+    module subroutine absent_imported_work()
+    end subroutine absent_imported_work
   end interface
 end module use_parent
 
-! USE-MODFILE: !$omp assumes no_openmp
 submodule (use_parent) use_child
   use scoped_assumes, only:
   implicit none
 contains
   ! SCOPE-LABEL: func.func @_QMuse_parentPimported_work()
-  ! SCOPE5X-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp"]]
+  ! SCOPE5X-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp,absent(barrier),absent(parallel)"]]
   ! SCOPE60-NOT: "omp_no_openmp"
   module procedure imported_work
   end procedure imported_work
 end submodule use_child
+
+! ABSENT-LABEL: func.func @_QPassumes_absent
+! ABSENT-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "absent(barrier),absent(parallel)"]]
+subroutine assumes_absent(x)
+  implicit none
+  !$omp assumes absent(parallel, barrier)
+  integer :: x
+  ! ABSENT: hlfir.assign
+  x = 7
+end subroutine assumes_absent
+
+module absent_module
+  implicit none
+  !$omp assumes no_openmp absent(parallel, barrier)
+  interface
+    module subroutine separate_absent_work() bind(C, name="separate_absent_work")
+    end subroutine separate_absent_work
+  end interface
+contains
+  ! ABSENT-LABEL: func.func @_QMabsent_modulePmodule_work()
+  ! ABSENT-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp,absent(barrier),absent(parallel)"]]
+  subroutine module_work()
+  end subroutine module_work
+
+  ! ABSENT-LABEL: func.func @_QMabsent_modulePlocal_work()
+  ! ABSENT-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp,absent(barrier),absent(critical),absent(parallel)"]]
+  subroutine local_work()
+    !$omp assumes absent(critical)
+  end subroutine local_work
+end module absent_module
+
+! ABSENT-LABEL: func.func @_QPassumes_host()
+! ABSENT-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "absent(parallel)"]]
+subroutine assumes_host()
+  !$omp assumes absent(parallel)
+  call internal_work()
+contains
+  ! ABSENT-LABEL: func.func {{.*}}@_QFassumes_hostPinternal_work()
+  ! ABSENT-SAME: llvm.passthrough = {{\[\[}}"llvm.assume", "omp_no_openmp,absent(barrier),absent(parallel)"]]
+  subroutine internal_work()
+    !$omp assumes absent(parallel, barrier) no_openmp
+    !$omp assumes absent(barrier)
+  end subroutine internal_work
+end subroutine assumes_host
+
+! ABSENT-LABEL: func....
[truncated]

``````````

</details>


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


More information about the Mlir-commits mailing list