summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAlexander Musman <alexander.musman@gmail.com>2015-01-22 08:49:35 +0000
committerAlexander Musman <alexander.musman@gmail.com>2015-01-22 08:49:35 +0000
commitdf7a8e2bc80d15de84f3be277ff3df25769ab84b (patch)
tree477e341acdd0356ec210998413b79c032e6429bf /clang/lib/CodeGen
parent3f68fae900fe9659085d9385210bbd588e54d03e (diff)
downloadbcm5719-llvm-df7a8e2bc80d15de84f3be277ff3df25769ab84b.tar.gz
bcm5719-llvm-df7a8e2bc80d15de84f3be277ff3df25769ab84b.zip
Support ‘omp for’ with static chunked schedule kind.
Differential Revision: http://reviews.llvm.org/D7006 llvm-svn: 226795
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp6
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.h6
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp92
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h6
4 files changed, 108 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 22ee00f2c7a..90bc5dbdb6d 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -848,6 +848,12 @@ bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
return Schedule == OMP_sch_static;
}
+bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
+ auto Schedule = getRuntimeSchedule(ScheduleKind, /* Chunked */ false);
+ assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
+ return Schedule != OMP_sch_static;
+}
+
void CGOpenMPRuntime::EmitOMPForInit(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPScheduleClauseKind ScheduleKind,
unsigned IVSize, bool IVSigned,
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index 6daf8179c14..5c40d530a10 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -320,6 +320,12 @@ public:
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
bool Chunked) const;
+ /// \brief Check if the specified \a ScheduleKind is dynamic.
+ /// This kind of worksharing directive is emitted without outer loop.
+ /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
+ ///
+ virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const;
+
/// \brief Call the appropriate runtime routine to initialize it before start
/// of loop.
///
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 101c3e717e8..60958d071c5 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -500,6 +500,89 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
}
+void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
+ const OMPLoopDirective &S,
+ OMPPrivateScope &LoopScope,
+ llvm::Value *LB, llvm::Value *UB,
+ llvm::Value *ST, llvm::Value *IL,
+ llvm::Value *Chunk) {
+ auto &RT = CGM.getOpenMPRuntime();
+ assert(!RT.isStaticNonchunked(ScheduleKind, /* Chunked */ Chunk != nullptr) &&
+ "static non-chunked schedule does not need outer loop");
+ if (RT.isDynamic(ScheduleKind)) {
+ ErrorUnsupported(&S, "OpenMP loop with dynamic schedule");
+ return;
+ }
+
+ // Emit outer loop.
+ //
+ // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
+ // When schedule(static, chunk_size) is specified, iterations are divided into
+ // chunks of size chunk_size, and the chunks are assigned to the threads in
+ // the team in a round-robin fashion in the order of the thread number.
+ //
+ // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
+ // while (idx <= UB) { BODY; ++idx; } // inner loop
+ // LB = LB + ST;
+ // UB = UB + ST;
+ // }
+ //
+ const Expr *IVExpr = S.getIterationVariable();
+ const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
+ const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
+
+ RT.EmitOMPForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned, IL,
+ LB, UB, ST, Chunk);
+ auto LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
+
+ // Start the loop with a block that tests the condition.
+ auto CondBlock = createBasicBlock("omp.dispatch.cond");
+ EmitBlock(CondBlock);
+ LoopStack.push(CondBlock);
+
+ llvm::Value *BoolCondVal = nullptr;
+ // UB = min(UB, GlobalUB)
+ EmitIgnoredExpr(S.getEnsureUpperBound());
+ // IV = LB
+ EmitIgnoredExpr(S.getInit());
+ // IV < UB
+ BoolCondVal = EvaluateExprAsBool(S.getCond(false));
+
+ // If there are any cleanups between here and the loop-exit scope,
+ // create a block to stage a loop exit along.
+ auto ExitBlock = LoopExit.getBlock();
+ if (LoopScope.requiresCleanups())
+ ExitBlock = createBasicBlock("omp.dispatch.cleanup");
+
+ auto LoopBody = createBasicBlock("omp.dispatch.body");
+ Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
+ if (ExitBlock != LoopExit.getBlock()) {
+ EmitBlock(ExitBlock);
+ EmitBranchThroughCleanup(LoopExit);
+ }
+ EmitBlock(LoopBody);
+
+ // Create a block for the increment.
+ auto Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
+
+ EmitOMPInnerLoop(S, LoopScope);
+
+ EmitBlock(Continue.getBlock());
+ BreakContinueStack.pop_back();
+ // Emit "LB = LB + Stride", "UB = UB + Stride".
+ EmitIgnoredExpr(S.getNextLowerBound());
+ EmitIgnoredExpr(S.getNextUpperBound());
+
+ EmitBranch(CondBlock);
+ LoopStack.pop();
+ // Emit the fall-through block.
+ EmitBlock(LoopExit.getBlock());
+
+ // Tell the runtime we are done.
+ RT.EmitOMPForFinish(*this, S.getLocStart(), ScheduleKind);
+}
+
/// \brief Emit a helper variable and return corresponding lvalue.
static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
const DeclRefExpr *Helper) {
@@ -581,8 +664,13 @@ void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
EmitOMPInnerLoop(S, LoopScope);
// Tell the runtime we are done.
RT.EmitOMPForFinish(*this, S.getLocStart(), ScheduleKind);
- } else
- ErrorUnsupported(&S, "OpenMP loop with requested schedule");
+ } else {
+ // Emit the outer loop, which requests its work chunk [LB..UB] from
+ // runtime and runs the inner loop to process it.
+ EmitOMPForOuterLoop(ScheduleKind, S, LoopScope, LB.getAddress(),
+ UB.getAddress(), ST.getAddress(), IL.getAddress(),
+ Chunk);
+ }
}
// We're now done with the loop, so jump to the continuation block.
EmitBranch(ContBlock);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 44e01c80df7..ea63c84d9fc 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -27,6 +27,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/ArrayRef.h"
@@ -2052,6 +2053,11 @@ private:
bool SeparateIter = false);
void EmitOMPSimdFinal(const OMPLoopDirective &S);
void EmitOMPWorksharingLoop(const OMPLoopDirective &S);
+ void EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
+ const OMPLoopDirective &S,
+ OMPPrivateScope &LoopScope, llvm::Value *LB,
+ llvm::Value *UB, llvm::Value *ST, llvm::Value *IL,
+ llvm::Value *Chunk);
public:
OpenPOWER on IntegriCloud