/// In this example directive '#pragma omp target' has clause 'device'
/// with single expression 'a'.
///
-class OMPDeviceClause : public OMPClause {
+class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
///
- OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc)
- : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Device(E) {}
+ OMPDeviceClause(Expr *E, Stmt *HelperE, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), Device(E) {
+ setPreInitStmt(HelperE);
+ }
/// \brief Build an empty clause.
///
OMPDeviceClause()
- : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Device(nullptr) {}
+ : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
+ OMPClauseWithPreInit(this), LParenLoc(SourceLocation()),
+ Device(nullptr) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ TRY_TO(VisitOMPClauseWithPreInit(C));
TRY_TO(TraverseStmt(C->getDevice()));
return true;
}
return static_cast<const OMPNumTeamsClause *>(C);
case OMPC_thread_limit:
return static_cast<const OMPThreadLimitClause *>(C);
+ case OMPC_device:
+ return static_cast<const OMPDeviceClause *>(C);
case OMPC_default:
case OMPC_proc_bind:
case OMPC_final:
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
- case OMPC_device:
case OMPC_threads:
case OMPC_simd:
case OMPC_map:
void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
const OMPTargetTeamsDistributeDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_target_teams_distribute,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
const OMPTargetTeamsDistributeParallelForDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_target_teams_distribute_parallel_for,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_target_teams_distribute_parallel_for_simd,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective(
const OMPTargetTeamsDistributeSimdDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
CGM.getOpenMPRuntime().emitInlinedDirective(
*this, OMPD_target_teams_distribute_simd,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
SourceLocation LParenLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Device;
+ Stmt *HelperValStmt = nullptr;
// OpenMP [2.9.1, Restrictions]
// The device expression must evaluate to a non-negative integer value.
/*StrictlyPositive=*/false))
return nullptr;
- return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ if (isOpenMPTargetExecutionDirective(DKind) &&
+ !CurContext->isDependentContext()) {
+ llvm::MapVector<Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(Context, Captures);
+ }
+
+ return new (Context)
+ OMPDeviceClause(ValExpr, HelperValStmt, StartLoc, LParenLoc, EndLoc);
}
static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
}
void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setDevice(Reader->Record.readSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation());
}
}
void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ VisitOMPClauseWithPreInit(C);
Record.AddStmt(C->getDevice());
Record.AddSourceLocation(C->getLParenLoc());
}
double cn[5][n];
TT<long long, char> d;
- // CHECK: [[RET:%.+]] = call i32 @__tgt_target(i32 -1, i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i32* null)
+ // CHECK: [[ADD:%.+]] = add nsw i32
+ // CHECK: store i32 [[ADD]], i32* [[CAPTURE:%.+]],
+ // CHECK: [[LD:%.+]] = load i32, i32* [[CAPTURE]],
+ // CHECK: [[RET:%.+]] = call i32 @__tgt_target(i32 [[LD]], i8* @{{[^,]+}}, i32 0, i8** null, i8** null, i[[SZ]]* null, i32* null)
// CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0
// CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:[^,]+]], label %[[END:[^,]+]]
// CHECK: [[FAIL]]
// CHECK: call void [[HVT0:@.+]]()
// CHECK-NEXT: br label %[[END]]
// CHECK: [[END]]
- #pragma omp target
+ #pragma omp target device(global + a)
{
}