[flang-commits] [flang] [flang][OpenMP] Add lowering for assume and assumes directives (PR #205615)

via flang-commits flang-commits at lists.llvm.org
Tue Jun 30 05:02:46 PDT 2026


https://github.com/Ritanya-B-Bharadwaj updated https://github.com/llvm/llvm-project/pull/205615

>From f63249c16cf413ff9099f86107c2733a6a8bc77a Mon Sep 17 00:00:00 2001
From: Ritanya B Bharadwaj <ritanya.b.bharadwaj at gmail.com>
Date: Wed, 24 Jun 2026 12:45:59 -0500
Subject: [PATCH 1/2] Adding lowering support for assume and assumes

---
 flang/lib/Lower/OpenMP/OpenMP.cpp        | 33 +++++++++++++++---
 flang/test/Lower/OpenMP/Todo/assume.f90  | 10 ------
 flang/test/Lower/OpenMP/Todo/assumes.f90 |  6 ----
 flang/test/Lower/OpenMP/assumption.f90   | 44 ++++++++++++++++++++++++
 4 files changed, 72 insertions(+), 21 deletions(-)
 delete mode 100644 flang/test/Lower/OpenMP/Todo/assume.f90
 delete mode 100644 flang/test/Lower/OpenMP/Todo/assumes.f90
 create mode 100644 flang/test/Lower/OpenMP/assumption.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index facca9867e4bb..5f84b76cf89e2 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -49,6 +49,7 @@
 #include "flang/Support/OpenMP-utils.h"
 #include "flang/Utils/OpenMP.h"
 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 #include "mlir/Support/StateStack.h"
 #include "mlir/Transforms/RegionUtils.h"
@@ -4205,8 +4206,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
                    semantics::SemanticsContext &semaCtx,
                    lower::pft::Evaluation &eval,
                    const parser::OmpAssumesDirective &assumesConstruct) {
-  if (!semaCtx.langOptions().OpenMPSimd)
-    TODO(converter.getCurrentLocation(), "OpenMP ASSUMES declaration");
+  // Assumption clauses are hints with no representation in the OpenMP dialect,
+  // so this declarative directive is a no-op.
 }
 
 static void
@@ -5314,9 +5315,31 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
                    semantics::SemanticsContext &semaCtx,
                    lower::pft::Evaluation &eval,
                    const parser::OmpAssumeDirective &assumeConstruct) {
-  mlir::Location clauseLocation = converter.genLocation(assumeConstruct.source);
-  if (!semaCtx.langOptions().OpenMPSimd)
-    TODO(clauseLocation, "OpenMP ASSUME construct");
+  if (!semaCtx.langOptions().OpenMPSimd) {
+    fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+    lower::StatementContext stmtCtx;
+
+    const parser::OmpDirectiveSpecification &beginSpec =
+        assumeConstruct.BeginDir();
+    for (const parser::OmpClause &clause : beginSpec.Clauses().v) {
+      const auto *holds = std::get_if<parser::OmpClause::Holds>(&clause.u);
+      if (!holds)
+        continue;
+
+      mlir::Location clauseLoc = converter.genLocation(clause.source);
+      const parser::Expr &parserExpr = holds->v.v.value();
+      const semantics::SomeExpr *expr = semantics::GetExpr(semaCtx, parserExpr);
+      assert(expr && "Expecting analyzed expression for holds clause");
+
+      mlir::Value cond =
+          fir::getBase(converter.genExprValue(*expr, stmtCtx, &clauseLoc));
+      cond =
+          firOpBuilder.createConvert(clauseLoc, firOpBuilder.getI1Type(), cond);
+      mlir::LLVM::AssumeOp::create(firOpBuilder, clauseLoc, cond);
+    }
+    stmtCtx.finalizeAndPop();
+  }
+  genNestedEvaluations(converter, eval);
 }
 
 static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
diff --git a/flang/test/Lower/OpenMP/Todo/assume.f90 b/flang/test/Lower/OpenMP/Todo/assume.f90
deleted file mode 100644
index 1216888efabd1..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/assume.f90
+++ /dev/null
@@ -1,10 +0,0 @@
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: OpenMP ASSUME construct
-program p
-  integer r
-  r = 1
-!$omp assume no_parallelism
-  print *,r
-!$omp end assume
-end program p
diff --git a/flang/test/Lower/OpenMP/Todo/assumes.f90 b/flang/test/Lower/OpenMP/Todo/assumes.f90
deleted file mode 100644
index ac26ed14ded3c..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/assumes.f90
+++ /dev/null
@@ -1,6 +0,0 @@
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: OpenMP ASSUMES declaration
-program p
-  !$omp assumes no_openmp
-end program p
diff --git a/flang/test/Lower/OpenMP/assumption.f90 b/flang/test/Lower/OpenMP/assumption.f90
new file mode 100644
index 0000000000000..65e6aa47881c9
--- /dev/null
+++ b/flang/test/Lower/OpenMP/assumption.f90
@@ -0,0 +1,44 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+
+! Lowering of the OpenMP ASSUME construct and ASSUMES directive. Most assumption
+! clauses are optimization hints with no representation in the OpenMP dialect, so
+! the ASSUME construct lowers its associated structured block and the ASSUMES
+! directive lowers as a no-op. The HOLDS clause asserts a scalar logical
+! expression, which is lowered to an `llvm.intr.assume` intrinsic.
+
+! CHECK-LABEL: func.func @_QPassumes_decl
+subroutine assumes_decl(x)
+  !$omp assumes no_openmp
+  integer :: x
+  ! CHECK: %[[DECL:.*]]:2 = hlfir.declare
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+  ! CHECK: hlfir.assign %[[C0]] to %[[DECL]]#0
+  x = 0
+end subroutine assumes_decl
+
+! CHECK-LABEL: func.func @_QPassume_construct
+subroutine assume_construct(x)
+  integer :: x
+  ! CHECK: %[[DECL:.*]]:2 = hlfir.declare
+  !$omp assume no_openmp
+  ! CHECK: %[[C1:.*]] = arith.constant 1 : i32
+  ! CHECK: hlfir.assign %[[C1]] to %[[DECL]]#0
+  x = 1
+  !$omp end assume
+end subroutine assume_construct
+
+! CHECK-LABEL: func.func @_QPassume_block
+subroutine assume_block(x)
+  integer :: x
+  ! CHECK: %[[DECL:.*]]:2 = hlfir.declare
+  !$omp assume holds(x > 0)
+  block
+    ! CHECK: %[[LOAD:.*]] = fir.load %[[DECL]]#0
+    ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+    ! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[LOAD]], %[[C0]] : i32
+    ! CHECK: llvm.intr.assume %[[CMP]] : i1
+    ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
+    ! CHECK: hlfir.assign %[[C2]] to %[[DECL]]#0
+    x = 2
+  end block
+end subroutine assume_block

>From a4fd5dfc0b47da53da17ce7c7625639d1378ab8e Mon Sep 17 00:00:00 2001
From: Ritanya B Bharadwaj <ritanya.b.bharadwaj at gmail.com>
Date: Tue, 30 Jun 2026 07:01:33 -0500
Subject: [PATCH 2/2] Changes based on review comments

---
 flang/lib/Lower/OpenMP/OpenMP.cpp        | 11 +++++----
 flang/test/Lower/OpenMP/Todo/assume.f90  | 10 ++++++++
 flang/test/Lower/OpenMP/Todo/assumes.f90 |  6 +++++
 flang/test/Lower/OpenMP/assumption.f90   | 29 +++---------------------
 4 files changed, 26 insertions(+), 30 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/Todo/assume.f90
 create mode 100644 flang/test/Lower/OpenMP/Todo/assumes.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 5f84b76cf89e2..822bf5b9db5f7 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -4208,6 +4208,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
                    const parser::OmpAssumesDirective &assumesConstruct) {
   // Assumption clauses are hints with no representation in the OpenMP dialect,
   // so this declarative directive is a no-op.
+  if (!semaCtx.langOptions().OpenMPSimd)
+    TODO(converter.getCurrentLocation(),
+         "assumption clauses on the assumes directive");
 }
 
 static void
@@ -5322,11 +5325,11 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
     const parser::OmpDirectiveSpecification &beginSpec =
         assumeConstruct.BeginDir();
     for (const parser::OmpClause &clause : beginSpec.Clauses().v) {
-      const auto *holds = std::get_if<parser::OmpClause::Holds>(&clause.u);
-      if (!holds)
-        continue;
-
       mlir::Location clauseLoc = converter.genLocation(clause.source);
+      const auto *holds = std::get_if<parser::OmpClause::Holds>(&clause.u);
+      if (!holds) {
+        TODO(clauseLoc, "assumption clause is not implemented yet");
+      }
       const parser::Expr &parserExpr = holds->v.v.value();
       const semantics::SomeExpr *expr = semantics::GetExpr(semaCtx, parserExpr);
       assert(expr && "Expecting analyzed expression for holds clause");
diff --git a/flang/test/Lower/OpenMP/Todo/assume.f90 b/flang/test/Lower/OpenMP/Todo/assume.f90
new file mode 100644
index 0000000000000..58c900c9212b9
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/assume.f90
@@ -0,0 +1,10 @@
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: assumption clause is not implemented yet
+program p
+  integer r
+  r = 1
+!$omp assume no_parallelism
+  print *,r
+!$omp end assume
+end program p
diff --git a/flang/test/Lower/OpenMP/Todo/assumes.f90 b/flang/test/Lower/OpenMP/Todo/assumes.f90
new file mode 100644
index 0000000000000..8ac080cd376be
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/assumes.f90
@@ -0,0 +1,6 @@
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: assumption clauses on the assumes directive
+program p
+  !$omp assumes no_openmp
+end program p
diff --git a/flang/test/Lower/OpenMP/assumption.f90 b/flang/test/Lower/OpenMP/assumption.f90
index 65e6aa47881c9..3cf51efd59dec 100644
--- a/flang/test/Lower/OpenMP/assumption.f90
+++ b/flang/test/Lower/OpenMP/assumption.f90
@@ -1,31 +1,8 @@
 ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s
 
-! Lowering of the OpenMP ASSUME construct and ASSUMES directive. Most assumption
-! clauses are optimization hints with no representation in the OpenMP dialect, so
-! the ASSUME construct lowers its associated structured block and the ASSUMES
-! directive lowers as a no-op. The HOLDS clause asserts a scalar logical
-! expression, which is lowered to an `llvm.intr.assume` intrinsic.
-
-! CHECK-LABEL: func.func @_QPassumes_decl
-subroutine assumes_decl(x)
-  !$omp assumes no_openmp
-  integer :: x
-  ! CHECK: %[[DECL:.*]]:2 = hlfir.declare
-  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-  ! CHECK: hlfir.assign %[[C0]] to %[[DECL]]#0
-  x = 0
-end subroutine assumes_decl
-
-! CHECK-LABEL: func.func @_QPassume_construct
-subroutine assume_construct(x)
-  integer :: x
-  ! CHECK: %[[DECL:.*]]:2 = hlfir.declare
-  !$omp assume no_openmp
-  ! CHECK: %[[C1:.*]] = arith.constant 1 : i32
-  ! CHECK: hlfir.assign %[[C1]] to %[[DECL]]#0
-  x = 1
-  !$omp end assume
-end subroutine assume_construct
+! Lowering of the OpenMP ASSUME construct. The HOLDS clause asserts a scalar
+! logical expression, which is lowered to an llvm.assume intrinsic. The block is
+! always lowered.
 
 ! CHECK-LABEL: func.func @_QPassume_block
 subroutine assume_block(x)



More information about the flang-commits mailing list