From: Alexey Bataev Date: Tue, 16 Jun 2015 13:14:42 +0000 (+0000) Subject: [OPENMP] Support lastprivate clause in omp simd directive. X-Git-Tag: llvmorg-3.7.0-rc1~2291 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fc087ecc051e52229cc0af176436005d97152ef3;p=platform%2Fupstream%2Fllvm.git [OPENMP] Support lastprivate clause in omp simd directive. Added codegen for lastprivate clauses within simd loop-based directives. llvm-svn: 239813 --- diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index a6da3891af59..907fe93efc46 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -316,26 +316,32 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal( // ... // orig_varn = private_orig_varn; // } - auto *ThenBB = createBasicBlock(".omp.lastprivate.then"); - auto *DoneBB = createBasicBlock(".omp.lastprivate.done"); - Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB); - EmitBlock(ThenBB); + llvm::BasicBlock *ThenBB = nullptr; + llvm::BasicBlock *DoneBB = nullptr; + if (IsLastIterCond) { + ThenBB = createBasicBlock(".omp.lastprivate.then"); + DoneBB = createBasicBlock(".omp.lastprivate.done"); + Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB); + EmitBlock(ThenBB); + } llvm::DenseMap LoopCountersAndUpdates; const Expr *LastIterVal = nullptr; const Expr *IVExpr = nullptr; const Expr *IncExpr = nullptr; if (auto *LoopDirective = dyn_cast(&D)) { - LastIterVal = - cast(cast(LoopDirective->getUpperBoundVariable()) - ->getDecl()) - ->getAnyInitializer(); - IVExpr = LoopDirective->getIterationVariable(); - IncExpr = LoopDirective->getInc(); - auto IUpdate = LoopDirective->updates().begin(); - for (auto *E : LoopDirective->counters()) { - auto *D = cast(E)->getDecl()->getCanonicalDecl(); - LoopCountersAndUpdates[D] = *IUpdate; - ++IUpdate; + if (isOpenMPWorksharingDirective(D.getDirectiveKind())) { + LastIterVal = cast(cast( + LoopDirective->getUpperBoundVariable()) + ->getDecl()) + ->getAnyInitializer(); + IVExpr = LoopDirective->getIterationVariable(); + IncExpr = LoopDirective->getInc(); + auto IUpdate = LoopDirective->updates().begin(); + for (auto *E : LoopDirective->counters()) { + auto *D = cast(E)->getDecl()->getCanonicalDecl(); + LoopCountersAndUpdates[D] = *IUpdate; + ++IUpdate; + } } } { @@ -355,7 +361,7 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal( // directive, update its value before copyin back to original // variable. if (auto *UpExpr = LoopCountersAndUpdates.lookup(CanonicalVD)) { - if (FirstLCV) { + if (FirstLCV && LastIterVal) { EmitAnyExprToMem(LastIterVal, EmitLValue(IVExpr).getAddress(), IVExpr->getType().getQualifiers(), /*IsInitializer=*/false); @@ -379,7 +385,9 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal( } } } - EmitBlock(DoneBB, /*IsFinished=*/true); + if (IsLastIterCond) { + EmitBlock(DoneBB, /*IsFinished=*/true); + } } void CodeGenFunction::EmitOMPReductionClauseInit( @@ -793,11 +801,13 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { } } + bool HasLastprivateClause; { OMPPrivateScope LoopScope(CGF); EmitPrivateLoopCounters(CGF, LoopScope, S.counters()); EmitPrivateLinearVars(CGF, S, LoopScope); CGF.EmitOMPPrivateClause(S, LoopScope); + HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); (void)LoopScope.Privatize(); CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), @@ -806,6 +816,10 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { CGF.EmitStopPoint(&S); }, [](CodeGenFunction &) {}); + // Emit final copy of the lastprivate variables at the end of loops. + if (HasLastprivateClause) { + CGF.EmitOMPLastprivateClauseFinal(S); + } } CGF.EmitOMPSimdFinal(S); // Emit: if (PreCond) - end. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index b3c31f61d1a3..fddecbc93948 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2130,9 +2130,9 @@ public: /// \param D Directive that has at least one 'lastprivate' directives. /// \param IsLastIterCond Boolean condition that must be set to 'i1 true' if /// it is the last iteration of the loop code in associated directive, or to - /// 'i1 false' otherwise. + /// 'i1 false' otherwise. If this item is nullptr, no final check is required. void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, - llvm::Value *IsLastIterCond); + llvm::Value *IsLastIterCond = nullptr); /// \brief Emit initial code for reduction variables. Creates reduction copies /// and initializes them with the values according to OpenMP standard. /// diff --git a/clang/test/OpenMP/simd_codegen.cpp b/clang/test/OpenMP/simd_codegen.cpp index 6b3170d5dfd2..0a5b38a0ce32 100644 --- a/clang/test/OpenMP/simd_codegen.cpp +++ b/clang/test/OpenMP/simd_codegen.cpp @@ -182,6 +182,8 @@ void simple(float *a, float *b, float *c, float *d) { } int A; + // CHECK: store i32 -1, i32* [[A:%.+]], + A = -1; #pragma omp simd lastprivate(A) // Clause 'lastprivate' implementation is not completed yet. // Test checks that one iteration is separated in presence of lastprivate. @@ -198,13 +200,18 @@ void simple(float *a, float *b, float *c, float *d) { // CHECK: [[IV7_0:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] // CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV7_0]], 3 // CHECK-NEXT: [[LC_IT_2:%.+]] = add nsw i64 -10, [[LC_IT_1]] -// CHECK-NEXT: store i64 [[LC_IT_2]], i64* {{.+}}, !llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] +// CHECK-NEXT: store i64 [[LC_IT_2]], i64* [[LC:%[^,]+]],{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] +// CHECK-NEXT: [[LC_VAL:%.+]] = load i64, i64* [[LC]]{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] +// CHECK-NEXT: [[CONV:%.+]] = trunc i64 [[LC_VAL]] to i32 +// CHECK-NEXT: store i32 [[CONV]], i32* [[A_PRIV:%[^,]+]],{{.+}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] A = i; // CHECK: [[IV7_2:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] // CHECK-NEXT: [[ADD7_2:%.+]] = add nsw i64 [[IV7_2]], 1 // CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]] } // CHECK: [[SIMPLE_LOOP7_END]] +// CHECK-NEXT: [[A_PRIV_VAL:%.+]] = load i32, i32* [[A_PRIV]], +// CHECK-NEXT: store i32 [[A_PRIV_VAL]], i32* [[A]], // CHECK-NEXT: ret void }