https://github.com/pedropiin created https://github.com/llvm/llvm-project/pull/235537
## What Both `none` and `shared` `default` clause kinds need no additional code generation. Yet they are blocked by NYI. This PR implements a more flexible barrier, allowing the use of the `default` clause with two of its kinds. Additionally reordering the functions definitions in `CIRGenOpenMPClause.cpp` so that all methods are in alphabetic order. I'm going to address the `private` and `firstprivate` clause kinds on a next PR, tackling part of the privatization logic. Basing myself on the logic of my other related PRs #204999 and #202466 . ## Evidence `python3 build/bin/llvm-lit -sv clang/test/CIR/CodeGenOpenMP/parallel.c` ```llvm-lit: /home/pedro/dev/projects/llvm-project-fork/llvm/utils/lit/lit/llvm/config.py:572: note: using clang: /home/pedro/dev/projects/llvm-project-fork/build/bin/clang Testing Time: 0.04s Total Discovered Tests: 1 Passed: 1 (100.00%) ``` `python3 build/bin/llvm-lit -sv clang/test/CIR/CodeGenOpenMP/not-yet-implemented.c` ``` llvm-lit: /home/pedro/dev/projects/llvm-project-fork/llvm/utils/lit/lit/llvm/config.py:572: note: using clang: /home/pedro/dev/projects/llvm-project-fork/build/bin/clang Testing Time: 0.04s Total Discovered Tests: 1 Passed: 1 (100.00%) ``` >From d13a4d9443833980b3d029260954c0c8cc8766e7 Mon Sep 17 00:00:00 2001 From: pedropiin <[email protected]> Date: Sun, 25 Oct 2026 20:40:57 -0300 Subject: [PATCH] Implementing part of the lowering for the 'default' clause for the 'parallel' directive --- clang/lib/CIR/CodeGen/CIRGenOpenMPClause.cpp | 84 ++++++++++++------- clang/lib/CIR/CodeGen/CIRGenOpenMPClause.h | 2 + clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp | 8 +- .../CIR/CodeGenOpenMP/not-yet-implemented.c | 8 ++ clang/test/CIR/CodeGenOpenMP/parallel.c | 79 +++++++++++++++++ 5 files changed, 147 insertions(+), 34 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.cpp index 2e64632f037c53..94eea7d007217f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.cpp @@ -74,40 +74,26 @@ static mlir::Value emitMapInfoForVar(CIRGenFunction &cgf, /*partial_map=*/builder.getBoolAttr(false)); } -bool OpenMPClauseEmitter::emitProcBind( - mlir::omp::ProcBindClauseOps &result) const { - for (const OMPClause *clause : clauses) { - const auto *pbc = dyn_cast<OMPProcBindClause>(clause); - if (!pbc) - continue; - - llvm::omp::ProcBindKind kind = pbc->getProcBindKind(); - assert(kind != llvm::omp::ProcBindKind::OMP_PROC_BIND_unknown && - "unknown proc-bind kind"); - // The 'default' kind has no dialect counterpart; leave the attribute unset. - if (kind != llvm::omp::ProcBindKind::OMP_PROC_BIND_default) - result.procBindKind = mlir::omp::ClauseProcBindKindAttr::get( - builder.getContext(), mlir::omp::convertProcBindKind(kind)); - return true; - } - return false; -} - -bool OpenMPClauseEmitter::emitNumThreads( - mlir::omp::NumThreadsClauseOps &result) const { +bool OpenMPClauseEmitter::emitDefault() const { for (const OMPClause *clause : clauses) { - const auto *ntc = dyn_cast<OMPNumThreadsClause>(clause); - if (!ntc) + const auto *dc = dyn_cast<OMPDefaultClause>(clause); + if (!dc) continue; - for (const Expr *expr : ntc->getNumThreads()) { - mlir::Value numThreadsValue = cgf.emitScalarExpr(expr); - auto intType = builder.getIntegerType(32); - numThreadsValue = builder.createBuiltinIntCast(numThreadsValue, intType); - result.numThreadsVars.push_back(numThreadsValue); + switch (dc->getDefaultKind()) { + case llvm::omp::OMP_DEFAULT_none: + case llvm::omp::OMP_DEFAULT_shared: + return true; + case llvm::omp::OMP_DEFAULT_private: + case llvm::omp::OMP_DEFAULT_firstprivate: + case llvm::omp::OMP_DEFAULT_unknown: + const char *default_kind_name = clang::getOpenMPSimpleClauseTypeName( + llvm::omp::OMPC_default, static_cast<unsigned>(dc->getDefaultKind())); + cgm.errorNYI(dc->getBeginLoc(), + std::string("Lowering for the default clause with kind '") + + default_kind_name + ("' not yet implemented.")); + return false; } - - return true; } return false; } @@ -190,3 +176,41 @@ bool OpenMPClauseEmitter::emitMap( } return found; } + +bool OpenMPClauseEmitter::emitNumThreads( + mlir::omp::NumThreadsClauseOps &result) const { + for (const OMPClause *clause : clauses) { + const auto *ntc = dyn_cast<OMPNumThreadsClause>(clause); + if (!ntc) + continue; + + for (const Expr *expr : ntc->getNumThreads()) { + mlir::Value numThreadsValue = cgf.emitScalarExpr(expr); + auto intType = builder.getIntegerType(32); + numThreadsValue = builder.createBuiltinIntCast(numThreadsValue, intType); + result.numThreadsVars.push_back(numThreadsValue); + } + + return true; + } + return false; +} + +bool OpenMPClauseEmitter::emitProcBind( + mlir::omp::ProcBindClauseOps &result) const { + for (const OMPClause *clause : clauses) { + const auto *pbc = dyn_cast<OMPProcBindClause>(clause); + if (!pbc) + continue; + + llvm::omp::ProcBindKind kind = pbc->getProcBindKind(); + assert(kind != llvm::omp::ProcBindKind::OMP_PROC_BIND_unknown && + "unknown proc-bind kind"); + // The 'default' kind has no dialect counterpart; leave the attribute unset. + if (kind != llvm::omp::ProcBindKind::OMP_PROC_BIND_default) + result.procBindKind = mlir::omp::ClauseProcBindKindAttr::get( + builder.getContext(), mlir::omp::convertProcBindKind(kind)); + return true; + } + return false; +} diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.h b/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.h index a5dcbcb918c737..64930479071c74 100644 --- a/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.h +++ b/clang/lib/CIR/CodeGen/CIRGenOpenMPClause.h @@ -40,6 +40,8 @@ class OpenMPClauseEmitter { llvm::ArrayRef<const OMPClause *> clauses) : cgf(cgf), cgm(cgm), builder(builder), loc(loc), clauses(clauses) {} + bool emitDefault() const; + bool emitIf(mlir::omp::IfClauseOps &result, llvm::omp::Directive directiveName) const; diff --git a/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp b/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp index 9d937f5ed67f90..c20c9d945ee8e8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmtOpenMP.cpp @@ -57,15 +57,15 @@ emitParallelClauses(CIRGenFunction &cgf, CIRGenModule &cgm, llvm::ArrayRef<const OMPClause *> clauses, mlir::omp::ParallelOperands &clauseOps) { OpenMPClauseEmitter ce(cgf, cgm, builder, loc, clauses); + ce.emitDefault(); ce.emitIf(clauseOps, llvm::omp::Directive::OMPD_parallel); ce.emitNumThreads(clauseOps); ce.emitProcBind(clauseOps); return ce.emitNYI</*supported=*/OMPIfClause, OMPNumThreadsClause, - OMPProcBindClause>( + OMPProcBindClause, OMPDefaultClause>( /*nyi=*/OpenMPNYIClauseList<OMPAllocateClause, OMPCopyinClause, - OMPDefaultClause, OMPFirstprivateClause, - OMPPrivateClause, OMPReductionClause, - OMPSharedClause>{}, + OMPFirstprivateClause, OMPPrivateClause, + OMPReductionClause, OMPSharedClause>{}, llvm::omp::Directive::OMPD_parallel); } diff --git a/clang/test/CIR/CodeGenOpenMP/not-yet-implemented.c b/clang/test/CIR/CodeGenOpenMP/not-yet-implemented.c index c4a97e2b76d05b..93881db2a6390a 100644 --- a/clang/test/CIR/CodeGenOpenMP/not-yet-implemented.c +++ b/clang/test/CIR/CodeGenOpenMP/not-yet-implemented.c @@ -29,4 +29,12 @@ void do_things() { // expected-error@+1{{ClangIR code gen Not Yet Implemented: OpenMP synthesized 'firstprivate' clause from construct decomposition}} #pragma omp target { i = 1; } + + // expected-error@+1{{ClangIR code gen Not Yet Implemented: Lowering for the default clause with kind 'private' not yet implemented.}} +#pragma omp parallel default(private) + {} + + // expected-error@+1{{ClangIR code gen Not Yet Implemented: Lowering for the default clause with kind 'firstprivate' not yet implemented.}} +#pragma omp parallel default(firstprivate) + {} } diff --git a/clang/test/CIR/CodeGenOpenMP/parallel.c b/clang/test/CIR/CodeGenOpenMP/parallel.c index 6a9a349c59489f..caac29732eb3b0 100644 --- a/clang/test/CIR/CodeGenOpenMP/parallel.c +++ b/clang/test/CIR/CodeGenOpenMP/parallel.c @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -fopenmp -triple x86_64-linux-gnu -emit-cir -fclangir %s -o - | FileCheck %s +// CHECK: cir.global "private" constant cir_private @__const.default_parallel.arr {{.*}} !cir.array<!s32i x 1> align(4) + void before(int); void during(int); void after(int); @@ -53,6 +55,83 @@ void parallel_with_operations() { // CHECK-NEXT: omp.terminator // CHECK-NEXT: } } + +void default_parallel() { + // CHECK: cir.func {{.*}} @default_parallel + + int x = 0; + int y = 0; + int *p = &y; + int arr[1] = {0}; // Checked at the beginning of the file. + + // CHECK-NEXT: %[[X_ADDR:.*]] = cir.alloca "x" + // CHECK-NEXT: %[[Y_ADDR:.*]] = cir.alloca "y" + // CHECK-NEXT: %[[P_ADDR:.*]] = cir.alloca "p" + // CHECK-NEXT: %[[ARR_ADDR:.*]] = cir.alloca "arr" + +#pragma omp parallel default(none) + {} + // CHECK: omp.parallel { + // CHECK-NEXT: omp.terminator + // CHECK-NEXT: } + +#pragma omp parallel default(none) + { + int inside = 10; + } + // CHECK-NEXT: omp.parallel { + // CHECK-NEXT: %[[INSIDE_ADDR:.*]] = cir.alloca "inside" + // CHECK-NEXT: %[[TEN_ADDR:.*]] = cir.const #cir.int<10> + // CHECK-NEXT: cir.store align(4) %[[TEN_ADDR]], %[[INSIDE_ADDR]] + // CHECK-NEXT: omp.terminator + // CHECK-NEXT: } + +#pragma omp parallel default(shared) + {} + // CHECK-NEXT: omp.parallel { + // CHECK-NEXT: omp.terminator + // CHECK-NEXT: } + +#pragma omp parallel default(shared) + { + x += 5; + } + // CHECK-NEXT: omp.parallel { + // CHECK-NEXT: %[[FIVE_ADDR:.*]] = cir.const #cir.int<5> + // CHECK-NEXT: %[[PTR_X_ADDR:.*]] = cir.load align(4) %[[X_ADDR]] + // CHECK-NEXT: %[[INCREMENT_X_ADDR:.*]] = cir.add nsw %[[PTR_X_ADDR]], %[[FIVE_ADDR]] + // CHECK-NEXT: cir.store align(4) %[[INCREMENT_X_ADDR]], %[[X_ADDR]] + // CHECK-NEXT: omp.terminator + // CHECK-NEXT: } + +#pragma omp parallel default(shared) + { + arr[0] += x; + } + // CHECK-NEXT: omp.parallel { + // CHECK-NEXT: %[[PTR_X_ADDR:.*]] = cir.load align(4) %[[X_ADDR]] + // CHECK-NEXT: %[[ZERO_IDX_ADDR:.*]] = cir.const #cir.int<0> + // CHECK-NEXT: %[[ARR_ELEMENT_ADDR:.*]] = cir.get_element %[[ARR_ADDR]][%[[ZERO_IDX_ADDR]] : !s64i] + // CHECK-NEXT: %[[PTR_ARR_ELEMENT_ADDR:.*]] = cir.load align(4) %[[ARR_ELEMENT_ADDR]] + // CHECK-NEXT: %[[INCREMENT_ELEMENT_ADDR:.*]] = cir.add nsw %[[PTR_ARR_ELEMENT_ADDR]], %[[PTR_X_ADDR]] + // CHECK-NEXT: cir.store align(4) %[[INCREMENT_ELEMENT_ADDR]], %[[ARR_ELEMENT_ADDR]] + // CHECK-NEXT: omp.terminator + // CHECK-NEXT: } + +#pragma omp parallel default(shared) + { + *p += x; + } + // CHECK-NEXT: omp.parallel { + // CHECK-NEXT: %[[PTR_X_ADDR:.*]] = cir.load align(4) %[[X_ADDR]] + // CHECK-NEXT: %[[DEREF_P_ADDR:.*]] = cir.load deref align(8) %[[P_ADDR]] + // CHECK-NEXT: %[[LOAD_DEREF_P_ADDR:.*]] = cir.load align(4) %[[DEREF_P_ADDR]] + // CHECK-NEXT: %[[INCREMENT_P_ADDR:.*]] = cir.add nsw %[[LOAD_DEREF_P_ADDR]], %[[PTR_X_ADDR]] + // CHECK-NEXT: cir.store align(4) %[[INCREMENT_P_ADDR]], %[[DEREF_P_ADDR]] + // CHECK-NEXT: omp.terminator + // CHECK-NEXT: } +} + void proc_bind_parallel() { // CHECK: cir.func{{.*}}@proc_bind_parallel #pragma omp parallel proc_bind(master) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
