From cfbb666593fffb644c3ab48f0e7576a8c9fb2a1a Mon Sep 17 00:00:00 2001 From: "Walter J.T.V" <81811777+eZWALT@users.noreply.github.com> Date: Wed, 1 May 2024 22:41:16 +0200 Subject: [PATCH] [CIR][OpenMP] Taskwait, Taskyield and Barrier implementation (#555) This PR is the final fix for issue #499. --- clang/lib/CIR/CodeGen/CIRGenFunction.h | 5 ++ clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp | 53 +++++++++++++ clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h | 36 +++++++++ clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 9 ++- clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp | 76 +++++++++++++++++++ .../CodeGen/UnimplementedFeatureGuarding.h | 1 + clang/test/CIR/CodeGen/OpenMP/barrier.cpp | 8 ++ .../{openmp.cpp => OpenMP/parallel.cpp} | 0 clang/test/CIR/CodeGen/OpenMP/taskwait.cpp | 9 +++ clang/test/CIR/CodeGen/OpenMP/taskyield.cpp | 8 ++ clang/test/CIR/Lowering/OpenMP/barrier.cir | 15 ++++ .../{openmp.cir => OpenMP/parallel.cir} | 0 clang/test/CIR/Lowering/OpenMP/taskwait.cir | 14 ++++ clang/test/CIR/Lowering/OpenMP/taskyield.cir | 14 ++++ 14 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 clang/test/CIR/CodeGen/OpenMP/barrier.cpp rename clang/test/CIR/CodeGen/{openmp.cpp => OpenMP/parallel.cpp} (100%) create mode 100644 clang/test/CIR/CodeGen/OpenMP/taskwait.cpp create mode 100644 clang/test/CIR/CodeGen/OpenMP/taskyield.cpp create mode 100644 clang/test/CIR/Lowering/OpenMP/barrier.cir rename clang/test/CIR/Lowering/{openmp.cir => OpenMP/parallel.cir} (100%) create mode 100644 clang/test/CIR/Lowering/OpenMP/taskwait.cir create mode 100644 clang/test/CIR/Lowering/OpenMP/taskyield.cir diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 22b863ba0d7c..63450258ad99 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -30,6 +30,7 @@ #include "mlir/IR/TypeRange.h" #include "mlir/IR/Value.h" +#include "mlir/Support/LogicalResult.h" namespace clang { class Expr; @@ -993,6 +994,10 @@ class CIRGenFunction : public CIRGenTypeCache { // OpenMP gen functions: mlir::LogicalResult buildOMPParallelDirective(const OMPParallelDirective &S); + mlir::LogicalResult buildOMPTaskwaitDirective(const OMPTaskwaitDirective &S); + mlir::LogicalResult + buildOMPTaskyieldDirective(const OMPTaskyieldDirective &S); + mlir::LogicalResult buildOMPBarrierDirective(const OMPBarrierDirective &S); LValue buildOpaqueValueLValue(const OpaqueValueExpr *e); diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp index 2060ce8e2d31..a42d84b12cb0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp @@ -52,3 +52,56 @@ bool CIRGenOpenMPRuntime::emitTargetGlobal(clang::GlobalDecl &GD) { assert(!UnimplementedFeature::openMPRuntime()); return false; } + +void CIRGenOpenMPRuntime::emitTaskWaitCall(CIRGenBuilderTy &builder, + CIRGenFunction &CGF, + mlir::Location Loc, + const OMPTaskDataTy &Data) { + + if (!CGF.HaveInsertPoint()) + return; + + if (CGF.CGM.getLangOpts().OpenMPIRBuilder && Data.Dependences.empty()) { + // TODO: Need to support taskwait with dependences in the OpenMPIRBuilder. + // TODO(cir): This could change in the near future when OpenMP 5.0 gets + // supported by MLIR + llvm_unreachable("NYI"); + // builder.create(Loc); + } else { + llvm_unreachable("NYI"); + } + assert(!UnimplementedFeature::openMPRegionInfo()); +} + +void CIRGenOpenMPRuntime::emitBarrierCall(CIRGenBuilderTy &builder, + CIRGenFunction &CGF, + mlir::Location Loc) { + + assert(!UnimplementedFeature::openMPRegionInfo()); + + if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { + builder.create(Loc); + return; + } + + if (!CGF.HaveInsertPoint()) + return; + + llvm_unreachable("NYI"); +} + +void CIRGenOpenMPRuntime::emitTaskyieldCall(CIRGenBuilderTy &builder, + CIRGenFunction &CGF, + mlir::Location Loc) { + + if (!CGF.HaveInsertPoint()) + return; + + if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { + builder.create(Loc); + } else { + llvm_unreachable("NYI"); + } + + assert(!UnimplementedFeature::openMPRegionInfo()); +} diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h index c4a53db44c92..a27b04a4866b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h +++ b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h @@ -13,9 +13,21 @@ #ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENOPENMPRUNTIME_H #define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENOPENMPRUNTIME_H +#include "CIRGenBuilder.h" #include "CIRGenValue.h" + +#include "clang/AST/Redeclarable.h" +#include "clang/Basic/OpenMPKinds.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "llvm/Support/ErrorHandling.h" + +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/Dialect.h" +#include "mlir/IR/Location.h" + +#include "UnimplementedFeatureGuarding.h" + namespace clang { class Decl; class Expr; @@ -27,6 +39,20 @@ namespace cir { class CIRGenModule; class CIRGenFunction; +struct OMPTaskDataTy final { + struct DependData { + clang::OpenMPDependClauseKind DepKind = clang::OMPC_DEPEND_unknown; + const clang::Expr *IteratorExpr = nullptr; + llvm::SmallVector DepExprs; + explicit DependData() = default; + DependData(clang::OpenMPDependClauseKind DepKind, + const clang::Expr *IteratorExpr) + : DepKind(DepKind), IteratorExpr(IteratorExpr) {} + }; + llvm::SmallVector Dependences; + bool HasNowaitClause = false; +}; + class CIRGenOpenMPRuntime { public: explicit CIRGenOpenMPRuntime(CIRGenModule &CGM); @@ -69,6 +95,16 @@ class CIRGenOpenMPRuntime { /// \param GD Global to scan. virtual bool emitTargetGlobal(clang::GlobalDecl &D); + /// Emit code for 'taskwait' directive + virtual void emitTaskWaitCall(CIRGenBuilderTy &builder, CIRGenFunction &CGF, + mlir::Location Loc, const OMPTaskDataTy &Data); + + virtual void emitBarrierCall(CIRGenBuilderTy &builder, CIRGenFunction &CGF, + mlir::Location Loc); + + virtual void emitTaskyieldCall(CIRGenBuilderTy &builder, CIRGenFunction &CGF, + mlir::Location Loc); + protected: CIRGenModule &CGM; }; diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 981804892ebb..b83b8795f841 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -180,6 +180,12 @@ mlir::LogicalResult CIRGenFunction::buildStmt(const Stmt *S, // OMP directives: case Stmt::OMPParallelDirectiveClass: return buildOMPParallelDirective(cast(*S)); + case Stmt::OMPTaskwaitDirectiveClass: + return buildOMPTaskwaitDirective(cast(*S)); + case Stmt::OMPTaskyieldDirectiveClass: + return buildOMPTaskyieldDirective(cast(*S)); + case Stmt::OMPBarrierDirectiveClass: + return buildOMPBarrierDirective(cast(*S)); // Unsupported AST nodes: case Stmt::CapturedStmtClass: case Stmt::ObjCAtTryStmtClass: @@ -205,9 +211,6 @@ mlir::LogicalResult CIRGenFunction::buildStmt(const Stmt *S, case Stmt::OMPParallelMasterDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPTaskDirectiveClass: - case Stmt::OMPTaskyieldDirectiveClass: - case Stmt::OMPBarrierDirectiveClass: - case Stmt::OMPTaskwaitDirectiveClass: case Stmt::OMPTaskgroupDirectiveClass: case Stmt::OMPFlushDirectiveClass: case Stmt::OMPDepobjDirectiveClass: diff --git a/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp b/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp index 3874ef3dcee6..0c996156f71e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp @@ -9,15 +9,63 @@ // This contains code to emit OpenMP Stmt nodes as MLIR code. // //===----------------------------------------------------------------------===// +#include "clang/AST/ASTFwd.h" +#include "clang/AST/StmtIterator.h" +#include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/OpenMPKinds.h" #include "CIRGenFunction.h" #include "CIRGenOpenMPRuntime.h" + +#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributeInterfaces.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Location.h" +#include "mlir/IR/Value.h" +#include "mlir/Support/LogicalResult.h" using namespace cir; using namespace clang; using namespace mlir::omp; +static void buildDependences(const OMPExecutableDirective &S, + OMPTaskDataTy &Data) { + + // First look for 'omp_all_memory' and add this first. + bool OmpAllMemory = false; + if (llvm::any_of( + S.getClausesOfKind(), [](const OMPDependClause *C) { + return C->getDependencyKind() == OMPC_DEPEND_outallmemory || + C->getDependencyKind() == OMPC_DEPEND_inoutallmemory; + })) { + OmpAllMemory = true; + // Since both OMPC_DEPEND_outallmemory and OMPC_DEPEND_inoutallmemory are + // equivalent to the runtime, always use OMPC_DEPEND_outallmemory to + // simplify. + OMPTaskDataTy::DependData &DD = + Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory, + /*IteratorExpr=*/nullptr); + // Add a nullptr Expr to simplify the codegen in emitDependData. + DD.DepExprs.push_back(nullptr); + } + // Add remaining dependences skipping any 'out' or 'inout' if they are + // overridden by 'omp_all_memory'. + for (const auto *C : S.getClausesOfKind()) { + OpenMPDependClauseKind Kind = C->getDependencyKind(); + if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory) + continue; + if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout)) + continue; + OMPTaskDataTy::DependData &DD = + Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier()); + DD.DepExprs.append(C->varlist_begin(), C->varlist_end()); + } +} + mlir::LogicalResult CIRGenFunction::buildOMPParallelDirective(const OMPParallelDirective &S) { mlir::LogicalResult res = mlir::success(); @@ -43,3 +91,31 @@ CIRGenFunction::buildOMPParallelDirective(const OMPParallelDirective &S) { builder.create(getLoc(S.getSourceRange().getEnd())); return res; } + +mlir::LogicalResult +CIRGenFunction::buildOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { + mlir::LogicalResult res = mlir::success(); + OMPTaskDataTy Data; + buildDependences(S, Data); + Data.HasNowaitClause = S.hasClausesOfKind(); + CGM.getOpenMPRuntime().emitTaskWaitCall(builder, *this, + getLoc(S.getSourceRange()), Data); + return res; +} +mlir::LogicalResult +CIRGenFunction::buildOMPTaskyieldDirective(const OMPTaskyieldDirective &S) { + mlir::LogicalResult res = mlir::success(); + // Creation of an omp.taskyield operation + CGM.getOpenMPRuntime().emitTaskyieldCall(builder, *this, + getLoc(S.getSourceRange())); + return res; +} + +mlir::LogicalResult +CIRGenFunction::buildOMPBarrierDirective(const OMPBarrierDirective &S) { + mlir::LogicalResult res = mlir::success(); + // Creation of an omp.barrier operation + CGM.getOpenMPRuntime().emitBarrierCall(builder, *this, + getLoc(S.getSourceRange())); + return res; +} \ No newline at end of file diff --git a/clang/lib/CIR/CodeGen/UnimplementedFeatureGuarding.h b/clang/lib/CIR/CodeGen/UnimplementedFeatureGuarding.h index e93a564ce076..bde8defb1147 100644 --- a/clang/lib/CIR/CodeGen/UnimplementedFeatureGuarding.h +++ b/clang/lib/CIR/CodeGen/UnimplementedFeatureGuarding.h @@ -135,6 +135,7 @@ struct UnimplementedFeature { static bool CUDA() { return false; } static bool openMP() { return false; } static bool openMPRuntime() { return false; } + static bool openMPRegionInfo() { return false; } static bool openMPTarget() { return false; } static bool isVarArg() { return false; } static bool setNonGC() { return false; } diff --git a/clang/test/CIR/CodeGen/OpenMP/barrier.cpp b/clang/test/CIR/CodeGen/OpenMP/barrier.cpp new file mode 100644 index 000000000000..b93016a3f1e4 --- /dev/null +++ b/clang/test/CIR/CodeGen/OpenMP/barrier.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fopenmp-enable-irbuilder -fopenmp -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +// CHECK: cir.func +void omp_barrier_1(){ +// CHECK: omp.barrier + #pragma omp barrier +} \ No newline at end of file diff --git a/clang/test/CIR/CodeGen/openmp.cpp b/clang/test/CIR/CodeGen/OpenMP/parallel.cpp similarity index 100% rename from clang/test/CIR/CodeGen/openmp.cpp rename to clang/test/CIR/CodeGen/OpenMP/parallel.cpp diff --git a/clang/test/CIR/CodeGen/OpenMP/taskwait.cpp b/clang/test/CIR/CodeGen/OpenMP/taskwait.cpp new file mode 100644 index 000000000000..448679622a7c --- /dev/null +++ b/clang/test/CIR/CodeGen/OpenMP/taskwait.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fopenmp-enable-irbuilder -fopenmp -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s +// XFAIL: * + +// CHECK: cir.func +void omp_taskwait_1(){ +// CHECK: omp.taskwait + #pragma omp taskwait +} diff --git a/clang/test/CIR/CodeGen/OpenMP/taskyield.cpp b/clang/test/CIR/CodeGen/OpenMP/taskyield.cpp new file mode 100644 index 000000000000..aa2903c07f74 --- /dev/null +++ b/clang/test/CIR/CodeGen/OpenMP/taskyield.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fopenmp-enable-irbuilder -fopenmp -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +// CHECK: cir.func +void omp_taskyield_1(){ +// CHECK: omp.taskyield + #pragma omp taskyield +} \ No newline at end of file diff --git a/clang/test/CIR/Lowering/OpenMP/barrier.cir b/clang/test/CIR/Lowering/OpenMP/barrier.cir new file mode 100644 index 000000000000..52fee8fff6c1 --- /dev/null +++ b/clang/test/CIR/Lowering/OpenMP/barrier.cir @@ -0,0 +1,15 @@ + +// RUN: cir-translate %s -cir-to-llvmir | FileCheck %s + + +module { + cir.func @omp_barrier_1() { + omp.barrier + cir.return + } +} + +// CHECK: define void @omp_barrier_1() +// CHECK: call i32 @__kmpc_global_thread_num(ptr {{.*}}) +// CHECK: call void @__kmpc_barrier(ptr {{.*}}, i32 {{.*}}) +// CHECK: ret void diff --git a/clang/test/CIR/Lowering/openmp.cir b/clang/test/CIR/Lowering/OpenMP/parallel.cir similarity index 100% rename from clang/test/CIR/Lowering/openmp.cir rename to clang/test/CIR/Lowering/OpenMP/parallel.cir diff --git a/clang/test/CIR/Lowering/OpenMP/taskwait.cir b/clang/test/CIR/Lowering/OpenMP/taskwait.cir new file mode 100644 index 000000000000..336bbda4f1bf --- /dev/null +++ b/clang/test/CIR/Lowering/OpenMP/taskwait.cir @@ -0,0 +1,14 @@ +// RUN: cir-translate %s -cir-to-llvmir | FileCheck %s + + +module { + cir.func @omp_taskwait_1() { + omp.taskwait + cir.return + } +} + +// CHECK: define void @omp_taskwait_1() +// CHECK: call i32 @__kmpc_global_thread_num(ptr {{.*}}) +// CHECK: call i32 @__kmpc_omp_taskwait(ptr {{.*}}, i32 {{.*}}) +// CHECK: ret void \ No newline at end of file diff --git a/clang/test/CIR/Lowering/OpenMP/taskyield.cir b/clang/test/CIR/Lowering/OpenMP/taskyield.cir new file mode 100644 index 000000000000..5104e9c31be1 --- /dev/null +++ b/clang/test/CIR/Lowering/OpenMP/taskyield.cir @@ -0,0 +1,14 @@ +// RUN: cir-translate %s -cir-to-llvmir | FileCheck %s + + +module { + cir.func @omp_taskyield_1() { + omp.taskyield + cir.return + } +} + +// CHECK: define void @omp_taskyield_1() +// CHECK: call i32 @__kmpc_global_thread_num(ptr {{.*}}) +// CHECK: call i32 @__kmpc_omp_taskyield(ptr {{.*}}, i32 {{.*}}, i32 {{.*}}) +// CHECK: ret void \ No newline at end of file