[Mlir-commits] [mlir] [MLIR][OpenMP] Add missing OpenMP to LLVM conversion patterns (PR #104440)

Sergio Afonso llvmlistbot at llvm.org
Wed Aug 21 07:58:03 PDT 2024


https://github.com/skatrak updated https://github.com/llvm/llvm-project/pull/104440

>From 82fd9d7226a0b118706df03b0667548e4e2f61b7 Mon Sep 17 00:00:00 2001
From: Sergio Afonso <safonsof at amd.com>
Date: Thu, 15 Aug 2024 15:03:11 +0100
Subject: [PATCH] [MLIR][OpenMP] Add missing OpenMP to LLVM conversion patterns

This patch adds conversion patterns to LLVM for the following OpenMP dialect
operations:
  - `omp.critical.declare`
  - `omp.cancel`
  - `omp.cancellation_point`
  - `omp.distribute`
  - `omp.teams`
  - `omp.ordered`
  - `omp.taskloop`

Also, arbitrary sorting of operations when passing them as template argument
lists when configuring that pass is replaced by alphabetical sorting.
---
 .../Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp  | 69 ++++++++------
 .../OpenMPToLLVM/convert-to-llvmir.mlir       | 94 +++++++++++++++++++
 2 files changed, 132 insertions(+), 31 deletions(-)

diff --git a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
index f6a6d1d7228a06..d6b4ec8584b082 100644
--- a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
+++ b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
@@ -223,22 +223,21 @@ void MultiRegionOpConversion<omp::PrivateClauseOp>::forwardOpAttrs(
 void mlir::configureOpenMPToLLVMConversionLegality(
     ConversionTarget &target, LLVMTypeConverter &typeConverter) {
   target.addDynamicallyLegalOp<
-      mlir::omp::AtomicReadOp, mlir::omp::AtomicWriteOp, mlir::omp::FlushOp,
-      mlir::omp::ThreadprivateOp, mlir::omp::YieldOp,
-      mlir::omp::TargetEnterDataOp, mlir::omp::TargetExitDataOp,
-      mlir::omp::TargetUpdateOp, mlir::omp::MapBoundsOp, mlir::omp::MapInfoOp>(
-      [&](Operation *op) {
-        return typeConverter.isLegal(op->getOperandTypes()) &&
-               typeConverter.isLegal(op->getResultTypes());
-      });
+      omp::AtomicReadOp, omp::AtomicWriteOp, omp::CancellationPointOp,
+      omp::CancelOp, omp::CriticalDeclareOp, omp::FlushOp, omp::MapBoundsOp,
+      omp::MapInfoOp, omp::OrderedOp, omp::TargetEnterDataOp,
+      omp::TargetExitDataOp, omp::TargetUpdateOp, omp::ThreadprivateOp,
+      omp::YieldOp>([&](Operation *op) {
+    return typeConverter.isLegal(op->getOperandTypes()) &&
+           typeConverter.isLegal(op->getResultTypes());
+  });
   target.addDynamicallyLegalOp<
-      mlir::omp::AtomicUpdateOp, mlir::omp::CriticalOp, mlir::omp::TargetOp,
-      mlir::omp::TargetDataOp, mlir::omp::LoopNestOp,
-      mlir::omp::OrderedRegionOp, mlir::omp::ParallelOp, mlir::omp::WsloopOp,
-      mlir::omp::SimdOp, mlir::omp::MasterOp, mlir::omp::SectionOp,
-      mlir::omp::SectionsOp, mlir::omp::SingleOp, mlir::omp::TaskgroupOp,
-      mlir::omp::TaskOp, mlir::omp::DeclareReductionOp,
-      mlir::omp::PrivateClauseOp>([&](Operation *op) {
+      omp::AtomicUpdateOp, omp::CriticalOp, omp::DeclareReductionOp,
+      omp::DistributeOp, omp::LoopNestOp, omp::MasterOp, omp::OrderedRegionOp,
+      omp::ParallelOp, omp::PrivateClauseOp, omp::SectionOp, omp::SectionsOp,
+      omp::SimdOp, omp::SingleOp, omp::TargetDataOp, omp::TargetOp,
+      omp::TaskgroupOp, omp::TaskloopOp, omp::TaskOp, omp::TeamsOp,
+      omp::WsloopOp>([&](Operation *op) {
     return std::all_of(op->getRegions().begin(), op->getRegions().end(),
                        [&](Region &region) {
                          return typeConverter.isLegal(&region);
@@ -260,23 +259,31 @@ void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter,
       AtomicReadOpConversion, MapInfoOpConversion,
       MultiRegionOpConversion<omp::DeclareReductionOp>,
       MultiRegionOpConversion<omp::PrivateClauseOp>,
-      RegionOpConversion<omp::CriticalOp>, RegionOpConversion<omp::LoopNestOp>,
-      RegionOpConversion<omp::MasterOp>,
-      RegionOpConversion<omp::OrderedRegionOp>,
-      RegionOpConversion<omp::ParallelOp>, RegionOpConversion<omp::WsloopOp>,
-      RegionOpConversion<omp::SectionsOp>, RegionOpConversion<omp::SectionOp>,
-      RegionOpConversion<omp::SimdOp>, RegionOpConversion<omp::SingleOp>,
-      RegionOpConversion<omp::TaskgroupOp>, RegionOpConversion<omp::TaskOp>,
-      RegionOpConversion<omp::TargetDataOp>, RegionOpConversion<omp::TargetOp>,
-      RegionLessOpWithVarOperandsConversion<omp::AtomicWriteOp>,
-      RegionOpWithVarOperandsConversion<omp::AtomicUpdateOp>,
-      RegionLessOpWithVarOperandsConversion<omp::FlushOp>,
-      RegionLessOpWithVarOperandsConversion<omp::ThreadprivateOp>,
-      RegionLessOpConversion<omp::YieldOp>,
+      RegionLessOpConversion<omp::CancellationPointOp>,
+      RegionLessOpConversion<omp::CancelOp>,
+      RegionLessOpConversion<omp::CriticalDeclareOp>,
+      RegionLessOpConversion<omp::OrderedOp>,
       RegionLessOpConversion<omp::TargetEnterDataOp>,
       RegionLessOpConversion<omp::TargetExitDataOp>,
       RegionLessOpConversion<omp::TargetUpdateOp>,
-      RegionLessOpWithVarOperandsConversion<omp::MapBoundsOp>>(converter);
+      RegionLessOpConversion<omp::YieldOp>,
+      RegionLessOpWithVarOperandsConversion<omp::AtomicWriteOp>,
+      RegionLessOpWithVarOperandsConversion<omp::FlushOp>,
+      RegionLessOpWithVarOperandsConversion<omp::MapBoundsOp>,
+      RegionLessOpWithVarOperandsConversion<omp::ThreadprivateOp>,
+      RegionOpConversion<omp::AtomicCaptureOp>,
+      RegionOpConversion<omp::CriticalOp>,
+      RegionOpConversion<omp::DistributeOp>,
+      RegionOpConversion<omp::LoopNestOp>, RegionOpConversion<omp::MaskedOp>,
+      RegionOpConversion<omp::MasterOp>,
+      RegionOpConversion<omp::OrderedRegionOp>,
+      RegionOpConversion<omp::ParallelOp>, RegionOpConversion<omp::SectionOp>,
+      RegionOpConversion<omp::SectionsOp>, RegionOpConversion<omp::SimdOp>,
+      RegionOpConversion<omp::SingleOp>, RegionOpConversion<omp::TargetDataOp>,
+      RegionOpConversion<omp::TargetOp>, RegionOpConversion<omp::TaskgroupOp>,
+      RegionOpConversion<omp::TaskloopOp>, RegionOpConversion<omp::TaskOp>,
+      RegionOpConversion<omp::TeamsOp>, RegionOpConversion<omp::WsloopOp>,
+      RegionOpWithVarOperandsConversion<omp::AtomicUpdateOp>>(converter);
 }
 
 namespace {
@@ -301,8 +308,8 @@ void ConvertOpenMPToLLVMPass::runOnOperation() {
   populateOpenMPToLLVMConversionPatterns(converter, patterns);
 
   LLVMConversionTarget target(getContext());
-  target.addLegalOp<omp::TerminatorOp, omp::TaskyieldOp, omp::FlushOp,
-                    omp::BarrierOp, omp::TaskwaitOp>();
+  target.addLegalOp<omp::BarrierOp, omp::FlushOp, omp::TaskwaitOp,
+                    omp::TaskyieldOp, omp::TerminatorOp>();
   configureOpenMPToLLVMConversionLegality(target, converter);
   if (failed(applyPartialConversion(module, target, std::move(patterns))))
     signalPassFailure();
diff --git a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
index d81487daf34f68..5afdbaa2a56af3 100644
--- a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
+++ b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
@@ -18,6 +18,20 @@ func.func @critical_block_arg() {
 
 // -----
 
+// CHECK: omp.critical.declare @[[MUTEX:.*]] hint(contended, speculative)
+omp.critical.declare @mutex hint(contended, speculative)
+
+// CHECK: llvm.func @critical_declare
+func.func @critical_declare() {
+  // CHECK: omp.critical(@[[MUTEX]])
+  omp.critical(@mutex) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
 // CHECK-LABEL: llvm.func @master_block_arg
 func.func @master_block_arg() {
   // CHECK: omp.master
@@ -523,3 +537,83 @@ omp.private {type = firstprivate} @y.privatizer : index alloc {
   // CHECK: omp.yield(%arg0 : i64)
   omp.yield(%arg0 : index)
 }
+
+// -----
+
+// CHECK-LABEL: llvm.func @omp_cancel_cancellation_point()
+func.func @omp_cancel_cancellation_point() -> () {
+  omp.parallel {
+    // CHECK: omp.cancel cancellation_construct_type(parallel)
+    omp.cancel cancellation_construct_type(parallel)
+    // CHECK: omp.cancellation_point cancellation_construct_type(parallel)
+    omp.cancellation_point cancellation_construct_type(parallel)
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+// CHECK-LABEL: llvm.func @omp_distribute(
+// CHECK-SAME:  %[[ARG0:.*]]: i64)
+func.func @omp_distribute(%arg0 : index) -> () {
+  // CHECK: omp.distribute dist_schedule_static dist_schedule_chunk_size(%[[ARG0]] : i64) {
+  omp.distribute dist_schedule_static dist_schedule_chunk_size(%arg0 : index) {
+    omp.loop_nest (%iv) : index = (%arg0) to (%arg0) step (%arg0) {
+      omp.yield
+    }
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+// CHECK-LABEL: llvm.func @omp_teams(
+// CHECK-SAME:  %[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr, %[[ARG2:.*]]: i64)
+func.func @omp_teams(%arg0 : memref<i32>) -> () {
+  // CHECK: omp.teams allocate(%{{.*}} : !llvm.struct<(ptr, ptr, i64)> -> %{{.*}} : !llvm.struct<(ptr, ptr, i64)>)
+  omp.teams allocate(%arg0 : memref<i32> -> %arg0 : memref<i32>) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+// CHECK-LABEL: llvm.func @omp_ordered(
+// CHECK-SAME:  %[[ARG0:.*]]: i64)
+func.func @omp_ordered(%arg0 : index) -> () {
+  omp.wsloop ordered(1) {
+    omp.loop_nest (%iv) : index = (%arg0) to (%arg0) step (%arg0) {
+      // CHECK: omp.ordered depend_vec(%[[ARG0]] : i64) {doacross_num_loops = 1 : i64}
+      omp.ordered depend_vec(%arg0 : index) {doacross_num_loops = 1 : i64}
+      omp.yield
+    }
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+// CHECK-LABEL: @omp_taskloop(
+// CHECK-SAME:  %[[ARG0:.*]]: i64, %[[ARG1:.*]]: !llvm.ptr, %[[ARG2:.*]]: !llvm.ptr, %[[ARG3:.*]]: i64)
+func.func @omp_taskloop(%arg0: index, %arg1 : memref<i32>) {
+  // CHECK: omp.parallel {
+  omp.parallel {
+    // CHECK: omp.taskloop allocate(%{{.*}} : !llvm.struct<(ptr, ptr, i64)> -> %{{.*}} : !llvm.struct<(ptr, ptr, i64)>) {
+    omp.taskloop allocate(%arg1 : memref<i32> -> %arg1 : memref<i32>) {
+      // CHECK: omp.loop_nest (%[[IV:.*]]) : i64 = (%[[ARG0]]) to (%[[ARG0]]) step (%[[ARG0]]) {
+      omp.loop_nest (%iv) : index = (%arg0) to (%arg0) step (%arg0) {
+        // CHECK-DAG: %[[CAST_IV:.*]] = builtin.unrealized_conversion_cast %[[IV]] : i64 to index
+        // CHECK: "test.payload"(%[[CAST_IV]]) : (index) -> ()
+        "test.payload"(%iv) : (index) -> ()
+        omp.yield
+      }
+      omp.terminator
+    }
+    omp.terminator
+  }
+  return
+}



More information about the Mlir-commits mailing list