diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1482,10 +1482,9 @@ virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef NumIterations); - /// Emit code for doacross ordered directive with 'depend' clause. - /// \param C 'depend' clause with 'sink|source' dependency kind. - virtual void emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C); + /// Emit code for doacross ordered directive with 'doacross | depend' clause. + /// \param C 'doacross | depend' clause with 'sink|source' dependence type. + virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPClause *C); /// Translates the native parameter of outlined function if this is required /// for target. @@ -2235,10 +2234,9 @@ void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef NumIterations) override; - /// Emit code for doacross ordered directive with 'depend' clause. - /// \param C 'depend' clause with 'sink|source' dependency kind. - void emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C) override; + /// Emit code for doacross ordered directive with 'doacross | depend' clause. + /// \param C 'doacross | depend' clause with 'sink|source' dependence type. + void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPClause *C) override; /// Translates the native parameter of outlined function if this is required /// for target. diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11380,15 +11380,21 @@ } void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C) { + const OMPClause *CL) { + const OMPDependClause *DC = + isa(CL) ? dyn_cast(CL) : nullptr; + const OMPDoacrossClause *DoC = + isa(CL) ? dyn_cast(CL) : nullptr; QualType Int64Ty = CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); - llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); + llvm::APInt Size(/*numBits=*/32, + DoC ? DoC->getNumLoops() : DC->getNumLoops()); QualType ArrayTy = CGM.getContext().getConstantArrayType( Int64Ty, Size, nullptr, ArrayType::Normal, 0); Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); - for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { - const Expr *CounterVal = C->getLoopData(I); + for (unsigned I = 0, E = DoC ? DoC->getNumLoops() : DC->getNumLoops(); I < E; + ++I) { + const Expr *CounterVal = DoC ? DoC->getLoopData(I) : DC->getLoopData(I); assert(CounterVal); llvm::Value *CntVal = CGF.EmitScalarConversion( CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, @@ -11397,17 +11403,29 @@ /*Volatile=*/false, Int64Ty); } llvm::Value *Args[] = { - emitUpdateLocation(CGF, C->getBeginLoc()), - getThreadID(CGF, C->getBeginLoc()), + emitUpdateLocation(CGF, DoC ? DoC->getBeginLoc() : DC->getBeginLoc()), + getThreadID(CGF, DoC ? DoC->getBeginLoc() : DC->getBeginLoc()), CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; llvm::FunctionCallee RTLFn; - if (C->getDependencyKind() == OMPC_DEPEND_source) { - RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), - OMPRTL___kmpc_doacross_post); - } else { - assert(C->getDependencyKind() == OMPC_DEPEND_sink); - RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), - OMPRTL___kmpc_doacross_wait); + if (DoC) { + if (DoC->getDependenceType() == OMPC_DOACROSS_source) { + RTLFn = OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_doacross_post); + } else { + assert(DoC->getDependenceType() == OMPC_DOACROSS_sink); + RTLFn = OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_doacross_wait); + } + } + if (DC) { + if (DC->getDependencyKind() == OMPC_DEPEND_source) { + RTLFn = OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_doacross_post); + } else { + assert(DC->getDependencyKind() == OMPC_DEPEND_sink); + RTLFn = OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_doacross_wait); + } } CGF.EmitRuntimeCall(RTLFn, Args); } @@ -12394,7 +12412,7 @@ } void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, - const OMPDependClause *C) { + const OMPClause *C) { llvm_unreachable("Not supported in SIMD-only mode"); } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -5839,6 +5839,33 @@ return Fn; } +static void emitRestoreIP(CodeGenFunction &CGF, const OMPClause *C, + llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, + llvm::OpenMPIRBuilder &OMPBuilder) { + auto DOC = dyn_cast(C); + auto DC = dyn_cast(C); + + unsigned NumLoops = DC ? DC->getNumLoops() : DOC->getNumLoops(); + QualType Int64Ty = CGF.CGM.getContext().getIntTypeForBitwidth( + /*DestWidth=*/64, /*Signed=*/1); + llvm::SmallVector StoreValues; + for (unsigned I = 0; I < NumLoops; I++) { + const Expr *CounterVal = DC ? DC->getLoopData(I) : DOC->getLoopData(I); + assert(CounterVal); + llvm::Value *StoreValue = CGF.EmitScalarConversion( + CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, + CounterVal->getExprLoc()); + StoreValues.emplace_back(StoreValue); + } + bool IsDependSource = false; + if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) || + (DOC && DOC->getDependenceType() == OMPC_DOACROSS_source)) + IsDependSource = true; + CGF.Builder.restoreIP( + OMPBuilder.createOrderedDepend(CGF.Builder, AllocaIP, NumLoops, + StoreValues, ".cnt.addr", IsDependSource)); +} + void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) { if (CGM.getLangOpts().OpenMPIRBuilder) { llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); @@ -5850,26 +5877,16 @@ "No associated statement must be in ordered depend construct."); InsertPointTy AllocaIP(AllocaInsertPt->getParent(), AllocaInsertPt->getIterator()); - for (const auto *DC : S.getClausesOfKind()) { - unsigned NumLoops = DC->getNumLoops(); - QualType Int64Ty = CGM.getContext().getIntTypeForBitwidth( - /*DestWidth=*/64, /*Signed=*/1); - llvm::SmallVector StoreValues; - for (unsigned I = 0; I < NumLoops; I++) { - const Expr *CounterVal = DC->getLoopData(I); - assert(CounterVal); - llvm::Value *StoreValue = EmitScalarConversion( - EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, - CounterVal->getExprLoc()); - StoreValues.emplace_back(StoreValue); - } - bool IsDependSource = false; - if (DC->getDependencyKind() == OMPC_DEPEND_source) - IsDependSource = true; - Builder.restoreIP(OMPBuilder.createOrderedDepend( - Builder, AllocaIP, NumLoops, StoreValues, ".cnt.addr", - IsDependSource)); - } + for (const auto *DC : S.getClausesOfKind()) + emitRestoreIP(*this, dyn_cast(DC), AllocaIP, OMPBuilder); + } else if (S.hasClausesOfKind()) { + // The ordered directive with doacross clause. + assert(!S.hasAssociatedStmt() && + "No associated statement must be in ordered doacross construct."); + InsertPointTy AllocaIP(AllocaInsertPt->getParent(), + AllocaInsertPt->getIterator()); + for (const auto *DC : S.getClausesOfKind()) + emitRestoreIP(*this, dyn_cast(DC), AllocaIP, OMPBuilder); } else { // The ordered directive with threads or simd clause, or without clause. // Without clause, it behaves as if the threads clause is specified. @@ -5916,6 +5933,13 @@ CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC); return; } + if (S.hasClausesOfKind()) { + assert(!S.hasAssociatedStmt() && + "No associated statement must be in ordered doacross construct."); + for (const auto *DC : S.getClausesOfKind()) + CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC); + return; + } const auto *C = S.getSingleClause(); auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF, PrePostActionTy &Action) { diff --git a/clang/test/OpenMP/ordered_doacross_codegen.c b/clang/test/OpenMP/ordered_doacross_codegen.c --- a/clang/test/OpenMP/ordered_doacross_codegen.c +++ b/clang/test/OpenMP/ordered_doacross_codegen.c @@ -2,13 +2,21 @@ // RUN: %clang_cc1 -fopenmp -triple x86_64-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NORMAL +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-unknown -emit-llvm %s -o - -fopenmp-version=52 | FileCheck %s --check-prefixes=CHECK,CHECK-NORMAL // RUN: %clang_cc1 -verify -fopenmp -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IRBUILDER +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -fopenmp-version=52 -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IRBUILDER // RUN: %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IRBUILDER +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IRBUILDER + // RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics @@ -51,7 +59,11 @@ // CHECK-NORMAL-NEXT: call void @__kmpc_doacross_post(ptr [[IDENT]], i32 [[GTID]], ptr [[TMP]]) // CHECK-IRBUILDER-NEXT: [[GTID1:%.+]] = call i32 @__kmpc_global_thread_num(ptr [[IDENT:@.+]]) // CHECK-IRBUILDER-NEXT: call void @__kmpc_doacross_post(ptr [[IDENT]], i32 [[GTID1]], ptr [[TMP]]) +#if _OPENMP >= 202111 +#pragma omp ordered doacross(source:) +#else #pragma omp ordered depend(source) +#endif c[i] = c[i] + 1; foo(); // CHECK: call void @foo() @@ -66,7 +78,11 @@ // CHECK-NORMAL-NEXT: call void @__kmpc_doacross_wait(ptr [[IDENT]], i32 [[GTID]], ptr [[TMP]]) // CHECK-IRBUILDER-NEXT: [[GTID2:%.+]] = call i32 @__kmpc_global_thread_num(ptr [[IDENT:@.+]]) // CHECK-IRBUILDER-NEXT: call void @__kmpc_doacross_wait(ptr [[IDENT]], i32 [[GTID2]], ptr [[TMP]]) +#if _OPENMP >= 202111 +#pragma omp ordered doacross(sink : i - 2) +#else #pragma omp ordered depend(sink : i - 2) +#endif d[i] = a[i - 2]; } // CHECK: call void @__kmpc_for_static_fini(