diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 45 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 53 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 105 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 13 |
6 files changed, 227 insertions, 12 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index a48f4a3e152..5ea75ea4655 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1291,27 +1291,56 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPSharedClause(N); } -OMPLinearClause *OMPLinearClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL, Expr *Step) { +void OMPLinearClause::setInits(ArrayRef<Expr *> IL) { + assert(IL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(IL.begin(), IL.end(), varlist_end()); +} + +void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) { + assert(UL.size() == varlist_size() && + "Number of updates is not the same as the preallocated buffer"); + std::copy(UL.begin(), UL.end(), getInits().end()); +} + +void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) { + assert(FL.size() == varlist_size() && + "Number of final updates is not the same as the preallocated buffer"); + std::copy(FL.begin(), FL.end(), getUpdates().end()); +} + +OMPLinearClause * +OMPLinearClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, + ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) { + // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions + // (Step and CalcStep). void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * (VL.size() + 1)); + (4 * VL.size() + 2) * sizeof(Expr *)); OMPLinearClause *Clause = new (Mem) OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setInits(IL); + // Fill update and final expressions with zeroes, they are provided later, + // after the directive construction. + std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(), + nullptr); + std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(), + nullptr); Clause->setStep(Step); + Clause->setCalcStep(CalcStep); return Clause; } OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, unsigned NumVars) { + // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions + // (Step and CalcStep). void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * (NumVars + 1)); + (4 * NumVars + 2) * sizeof(Expr *)); return new (Mem) OMPLinearClause(NumVars); } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index d1f25d63b3f..900ff3abe3a 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -359,7 +359,17 @@ void OMPClauseProfiler::VisitOMPReductionClause( } void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); + for (auto *E : C->inits()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->updates()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->finals()) { + Profiler->VisitStmt(E); + } Profiler->VisitStmt(C->getStep()); + Profiler->VisitStmt(C->getCalcStep()); } void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) { VisitOMPClauseList(C); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index a7615ce10a2..42e6a841cdf 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -266,6 +266,13 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S, for (auto I : S.updates()) { EmitIgnoredExpr(I); } + // Update the linear variables. + for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) { + for (auto U : C->updates()) { + EmitIgnoredExpr(U); + } + } + // On a continue in the body, jump to the end. auto Continue = getJumpDestInCurrentScope("omp.body.continue"); BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue)); @@ -336,6 +343,12 @@ void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &S) { } ++IC; } + // Emit the final values of the linear variables. + for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) { + for (auto F : C->finals()) { + EmitIgnoredExpr(F); + } + } } static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM, @@ -381,6 +394,25 @@ static void EmitPrivateLoopCounters(CodeGenFunction &CGF, } } +static void +EmitPrivateLinearVars(CodeGenFunction &CGF, const OMPExecutableDirective &D, + CodeGenFunction::OMPPrivateScope &PrivateScope) { + for (auto Clause : OMPExecutableDirective::linear_filter(D.clauses())) { + for (auto *E : Clause->varlists()) { + auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); + bool IsRegistered = PrivateScope.addPrivate(VD, [&]()->llvm::Value * { + // Emit var without initialization. + auto VarEmission = CGF.EmitAutoVarAlloca(*VD); + CGF.EmitAutoVarCleanups(VarEmission); + return VarEmission.getAllocatedAddress(); + }); + assert(IsRegistered && "linear var already registered as private"); + // Silence the warning about unused variable. + (void)IsRegistered; + } + } +} + void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { // Pragma 'simd' code depends on presence of 'lastprivate'. // If present, we have to separate last iteration of the loop: @@ -428,6 +460,14 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { InlinedOpenMPRegionScopeRAII Region(*this, S); + // Emit inits for the linear variables. + for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) { + for (auto Init : C->inits()) { + auto *D = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl()); + EmitVarDecl(*D); + } + } + // Emit the loop iteration variable. const Expr *IVExpr = S.getIterationVariable(); const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); @@ -443,6 +483,17 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { EmitIgnoredExpr(S.getCalcLastIteration()); } + // Emit the linear steps for the linear clauses. + // If a step is not constant, it is pre-calculated before the loop. + for (auto C : OMPExecutableDirective::linear_filter(S.clauses())) { + if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep())) + if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) { + EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl())); + // Emit calculation of the linear step. + EmitIgnoredExpr(CS); + } + } + if (SeparateIter) { // Emit: if (LastIteration > 0) - begin. RegionCounter Cnt = getPGORegionCounter(&S); @@ -455,6 +506,7 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { { OMPPrivateScope LoopScope(*this); EmitPrivateLoopCounters(*this, LoopScope, S.counters()); + EmitPrivateLinearVars(*this, S, LoopScope); EmitOMPPrivateClause(S, LoopScope); (void)LoopScope.Privatize(); EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), @@ -473,6 +525,7 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { { OMPPrivateScope LoopScope(*this); EmitPrivateLoopCounters(*this, LoopScope, S.counters()); + EmitPrivateLinearVars(*this, S, LoopScope); EmitOMPPrivateClause(S, LoopScope); (void)LoopScope.Privatize(); EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 70423994289..81d04a8c2f6 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -622,6 +622,10 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { PopExpressionEvaluationContext(); } +static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, + Expr *NumIterations, Sema &SemaRef, + Scope *S); + namespace { class VarDeclFilterCCC : public CorrectionCandidateCallback { @@ -2915,6 +2919,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // Save results Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); + Built.NumIterations = NumIterations.get(); Built.CalcLastIteration = CalcLastIteration.get(); Built.PreCond = PreCond.get(); Built.Cond = Cond.get(); @@ -2958,6 +2963,16 @@ StmtResult Sema::ActOnOpenMPSimdDirective( assert((CurContext->isDependentContext() || B.builtAll()) && "omp simd loop exprs were not built"); + if (!CurContext->isDependentContext()) { + // Finalize the clauses that need pre-built expressions for CodeGen. + for (auto C : Clauses) { + if (auto LC = dyn_cast<OMPLinearClause>(C)) + if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), + B.NumIterations, *this, CurScope)) + return StmtError(); + } + } + getCurFunction()->setHasBranchProtectedScope(); return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -5231,11 +5246,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, SourceLocation ColonLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> Inits; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP linear clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + Inits.push_back(nullptr); continue; } @@ -5277,6 +5294,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, if (QType->isDependentType() || QType->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + Inits.push_back(nullptr); continue; } @@ -5322,14 +5340,27 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, continue; } + // Build var to save initial value. + VarDecl *Init = BuildVarDecl(*this, ELoc, DE->getType(), ".linear.start"); + AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(), + /*DirectInit*/ false, /*TypeMayContainAuto*/ false); + CurContext->addDecl(Init); + Init->setIsUsed(); + auto InitRef = DeclRefExpr::Create( + Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), + /*TemplateKWLoc*/ SourceLocation(), Init, + /*isEnclosingLocal*/ false, DE->getLocStart(), DE->getType(), + /*VK*/ VK_LValue); DSAStack->addDSA(VD, DE, OMPC_linear); Vars.push_back(DE); + Inits.push_back(InitRef); } if (Vars.empty()) return nullptr; Expr *StepExpr = Step; + Expr *CalcStepExpr = nullptr; if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && !Step->isInstantiationDependent() && !Step->containsUnexpandedParameterPack()) { @@ -5339,17 +5370,85 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, return nullptr; StepExpr = Val.get(); + // Build var to save the step value. + VarDecl *SaveVar = + BuildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step"); + CurContext->addDecl(SaveVar); + SaveVar->setIsUsed(); + ExprResult SaveRef = + BuildDeclRefExpr(SaveVar, StepExpr->getType(), VK_LValue, StepLoc); + ExprResult CalcStep = + BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); + // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). llvm::APSInt Result; - if (StepExpr->isIntegerConstantExpr(Result, Context) && - !Result.isNegative() && !Result.isStrictlyPositive()) + bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); + if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] << (Vars.size() > 1); + if (!IsConstant && CalcStep.isUsable()) { + // Calculate the step beforehand instead of doing this on each iteration. + // (This is not used if the number of iterations may be kfold-ed). + CalcStepExpr = CalcStep.get(); + } } return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc, - Vars, StepExpr); + Vars, Inits, StepExpr, CalcStepExpr); +} + +static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, + Expr *NumIterations, Sema &SemaRef, + Scope *S) { + // Walk the vars and build update/final expressions for the CodeGen. + SmallVector<Expr *, 8> Updates; + SmallVector<Expr *, 8> Finals; + Expr *Step = Clause.getStep(); + Expr *CalcStep = Clause.getCalcStep(); + // OpenMP [2.14.3.7, linear clause] + // If linear-step is not specified it is assumed to be 1. + if (Step == nullptr) + Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); + else if (CalcStep) + Step = cast<BinaryOperator>(CalcStep)->getLHS(); + bool HasErrors = false; + auto CurInit = Clause.inits().begin(); + for (auto &RefExpr : Clause.varlists()) { + Expr *InitExpr = *CurInit; + + // Build privatized reference to the current linear var. + auto DE = cast<DeclRefExpr>(RefExpr); + auto PrivateRef = DeclRefExpr::Create( + SemaRef.Context, /*QualifierLoc*/ DE->getQualifierLoc(), + /*TemplateKWLoc*/ SourceLocation(), DE->getDecl(), + /* RefersToEnclosingVariableOrCapture */ true, DE->getLocStart(), + DE->getType(), /*VK*/ VK_LValue); + + // Build update: Var = InitExpr + IV * Step + ExprResult Update = + BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef, + InitExpr, IV, Step, /* Subtract */ false); + Update = SemaRef.ActOnFinishFullExpr(Update.get()); + + // Build final: Var = InitExpr + NumIterations * Step + ExprResult Final = + BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), RefExpr, InitExpr, + NumIterations, Step, /* Subtract */ false); + Final = SemaRef.ActOnFinishFullExpr(Final.get()); + if (!Update.isUsable() || !Final.isUsable()) { + Updates.push_back(nullptr); + Finals.push_back(nullptr); + HasErrors = true; + } else { + Updates.push_back(Update.get()); + Finals.push_back(Final.get()); + } + ++CurInit; + } + Clause.setUpdates(Updates); + Clause.setFinals(Finals); + return HasErrors; } OMPClause *Sema::ActOnOpenMPAlignedClause( diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 0f0c7ea9703..eec0fe43b28 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1928,7 +1928,20 @@ void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setInits(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setUpdates(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setFinals(Vars); C->setStep(Reader->Reader.ReadSubExpr()); + C->setCalcStep(Reader->Reader.ReadSubExpr()); } void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index e8769c08d68..3f568a6365c 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1820,9 +1820,20 @@ void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); - for (auto *VE : C->varlists()) + for (auto *VE : C->varlists()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->inits()) { Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->updates()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->finals()) { + Writer->Writer.AddStmt(VE); + } Writer->Writer.AddStmt(C->getStep()); + Writer->Writer.AddStmt(C->getCalcStep()); } void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) { |