mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 05:36:06 +00:00
[OPENMP] Fix for codegen of captured variables in inlined directives.
Currently there is a problem with codegen of inlined directives inside lambdas, it may cause a crash during codegen because of incorrect capturing of variables. Patch fixes this problem. llvm-svn: 267677
This commit is contained in:
parent
a2d72377a1
commit
4ba78a46ff
@ -384,6 +384,8 @@ private:
|
||||
/// \brief RAII for emitting code of OpenMP constructs.
|
||||
class InlinedOpenMPRegionRAII {
|
||||
CodeGenFunction &CGF;
|
||||
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
|
||||
FieldDecl *LambdaThisCaptureField = nullptr;
|
||||
|
||||
public:
|
||||
/// \brief Constructs region for combined constructs.
|
||||
@ -396,6 +398,9 @@ public:
|
||||
// Start emission for the construct.
|
||||
CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
|
||||
CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
|
||||
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
|
||||
LambdaThisCaptureField = CGF.LambdaThisCaptureField;
|
||||
CGF.LambdaThisCaptureField = nullptr;
|
||||
}
|
||||
|
||||
~InlinedOpenMPRegionRAII() {
|
||||
@ -404,6 +409,8 @@ public:
|
||||
cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
|
||||
delete CGF.CapturedStmtInfo;
|
||||
CGF.CapturedStmtInfo = OldCSI;
|
||||
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
|
||||
CGF.LambdaThisCaptureField = LambdaThisCaptureField;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ using namespace CodeGen;
|
||||
namespace {
|
||||
/// Lexical scope for OpenMP executable constructs, that handles correct codegen
|
||||
/// for captured expressions.
|
||||
class OMPLexicalScope : public CodeGenFunction::LexicalScope {
|
||||
class OMPLexicalScope final : public CodeGenFunction::LexicalScope {
|
||||
void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
|
||||
for (const auto *C : S.clauses()) {
|
||||
if (auto *CPI = OMPClauseWithPreInit::get(C)) {
|
||||
@ -44,11 +44,40 @@ class OMPLexicalScope : public CodeGenFunction::LexicalScope {
|
||||
}
|
||||
}
|
||||
}
|
||||
CodeGenFunction::OMPPrivateScope InlinedShareds;
|
||||
|
||||
static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
|
||||
return CGF.LambdaCaptureFields.lookup(VD) ||
|
||||
(CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
|
||||
(CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl));
|
||||
}
|
||||
|
||||
public:
|
||||
OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
|
||||
: CodeGenFunction::LexicalScope(CGF, S.getSourceRange()) {
|
||||
OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S,
|
||||
bool AsInlined = false)
|
||||
: CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
|
||||
InlinedShareds(CGF) {
|
||||
emitPreInitStmt(CGF, S);
|
||||
if (AsInlined) {
|
||||
if (S.hasAssociatedStmt()) {
|
||||
auto *CS = cast<CapturedStmt>(S.getAssociatedStmt());
|
||||
for (auto &C : CS->captures()) {
|
||||
if (C.capturesVariable() || C.capturesVariableByCopy()) {
|
||||
auto *VD = C.getCapturedVar();
|
||||
DeclRefExpr DRE(const_cast<VarDecl *>(VD),
|
||||
isCapturedVar(CGF, VD) ||
|
||||
(CGF.CapturedStmtInfo &&
|
||||
InlinedShareds.isGlobalVarCaptured(VD)),
|
||||
VD->getType().getNonReferenceType(), VK_LValue,
|
||||
SourceLocation());
|
||||
InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
|
||||
return CGF.EmitLValue(&DRE).getAddress();
|
||||
});
|
||||
}
|
||||
}
|
||||
(void)InlinedShareds.Privatize();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1601,7 +1630,7 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
|
||||
CGF.EmitBlock(ContBlock, true);
|
||||
}
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
|
||||
}
|
||||
|
||||
@ -1995,7 +2024,7 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
|
||||
HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
|
||||
};
|
||||
{
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
|
||||
S.hasCancel());
|
||||
}
|
||||
@ -2013,7 +2042,7 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
|
||||
HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
|
||||
};
|
||||
{
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
|
||||
}
|
||||
|
||||
@ -2167,7 +2196,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
|
||||
|
||||
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
|
||||
{
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
EmitSections(S);
|
||||
}
|
||||
// Emit an implicit barrier at the end.
|
||||
@ -2181,7 +2210,7 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
|
||||
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
|
||||
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
|
||||
S.hasCancel());
|
||||
}
|
||||
@ -2213,7 +2242,7 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
|
||||
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
||||
};
|
||||
{
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
|
||||
CopyprivateVars, DestExprs,
|
||||
SrcExprs, AssignmentOps);
|
||||
@ -2232,7 +2261,7 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
|
||||
Action.Enter(CGF);
|
||||
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
|
||||
}
|
||||
|
||||
@ -2244,7 +2273,7 @@ void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
|
||||
Expr *Hint = nullptr;
|
||||
if (auto *HintClause = S.getSingleClause<OMPHintClause>())
|
||||
Hint = HintClause->getHint();
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitCriticalRegion(*this,
|
||||
S.getDirectiveName().getAsString(),
|
||||
CodeGen, S.getLocStart(), Hint);
|
||||
@ -2438,7 +2467,7 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
|
||||
Action.Enter(CGF);
|
||||
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart());
|
||||
}
|
||||
|
||||
@ -2573,7 +2602,7 @@ void CodeGenFunction::EmitOMPDistributeDirective(
|
||||
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
|
||||
CGF.EmitOMPDistributeLoop(S);
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen,
|
||||
false);
|
||||
}
|
||||
@ -2606,7 +2635,7 @@ void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
|
||||
cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
||||
}
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart(), !C);
|
||||
}
|
||||
|
||||
@ -3064,7 +3093,7 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
|
||||
S.getV(), S.getExpr(), S.getUpdateExpr(),
|
||||
S.isXLHSInRHSPart(), S.getLocStart());
|
||||
};
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
|
||||
}
|
||||
|
||||
@ -3213,7 +3242,7 @@ CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
|
||||
void CodeGenFunction::EmitOMPTargetDataDirective(
|
||||
const OMPTargetDataDirective &S) {
|
||||
// emit the code inside the construct for now
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(
|
||||
*this, OMPD_target_data, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
|
||||
CGF.EmitStmt(
|
||||
@ -3376,7 +3405,7 @@ void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
|
||||
void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
|
||||
const OMPTaskLoopSimdDirective &S) {
|
||||
// emit the code inside the construct for now
|
||||
OMPLexicalScope Scope(*this, S);
|
||||
OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
|
||||
CGM.getOpenMPRuntime().emitInlinedDirective(
|
||||
*this, OMPD_taskloop_simd, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
|
||||
OMPLoopScope PreInitScope(CGF, S);
|
||||
|
@ -641,6 +641,11 @@ public:
|
||||
ForceCleanup();
|
||||
}
|
||||
|
||||
/// Checks if the global variable is captured in current function.
|
||||
bool isGlobalVarCaptured(const VarDecl *VD) const {
|
||||
return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Copy all the entries in the source map over the corresponding
|
||||
/// entries in the destination, which must exist.
|
||||
|
@ -64,6 +64,8 @@ void critical_ref(S &s) {
|
||||
// CHECK: [[S_REF:%.+]] = load %struct.S*, %struct.S** [[S_ADDR]],
|
||||
// CHECK: [[S_A_REF:%.+]] = getelementptr inbounds %struct.S, %struct.S* [[S_REF]], i32 0, i32 0
|
||||
++s.a;
|
||||
// CHECK: [[S_REF:%.+]] = load %struct.S*, %struct.S** [[S_ADDR]],
|
||||
// CHECK: store %struct.S* [[S_REF]], %struct.S** [[S_ADDR:%.+]],
|
||||
// CHECK: call void @__kmpc_critical(
|
||||
#pragma omp critical
|
||||
// CHECK: [[S_REF:%.+]] = load %struct.S*, %struct.S** [[S_ADDR]],
|
||||
|
@ -959,6 +959,8 @@ int main() {
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]],
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
@ -993,6 +995,8 @@ int main() {
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]],
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*
|
||||
// CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], i32 0, i32 0
|
||||
|
@ -759,6 +759,8 @@ int main() {
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]],
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
@ -793,6 +795,8 @@ int main() {
|
||||
|
||||
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]],
|
||||
// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],
|
||||
// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*
|
||||
// CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], i32 0, i32 0
|
||||
|
@ -494,8 +494,10 @@ void linear(float *a) {
|
||||
|
||||
#pragma omp simd linear(k : 3)
|
||||
// CHECK: store i64* [[VAL_ADDR]], i64** [[K_ADDR]],
|
||||
// CHECK: [[VAL_REF:%.+]] = load i64*, i64** [[K_ADDR]],
|
||||
// CHECK: store i64* [[VAL_REF]], i64** [[K_ADDR_REF:%.+]],
|
||||
// CHECK: store i32 0, i32* [[OMP_IV:%[^,]+]]
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR]],
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR_REF]],
|
||||
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_REF]]
|
||||
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
|
||||
|
||||
@ -528,7 +530,7 @@ void linear(float *a) {
|
||||
// CHECK: [[SIMPLE_LOOP_END]]
|
||||
//
|
||||
// Update linear vars after loop, as the loop was operating on a private version.
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR]],
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR_REF]],
|
||||
// CHECK: store i64* [[K_REF]], i64** [[K_PRIV_REF:%.+]],
|
||||
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
|
||||
// CHECK-NEXT: [[LIN_ADD2:%.+]] = add nsw i64 [[LIN0_2]], 27
|
||||
@ -537,8 +539,10 @@ void linear(float *a) {
|
||||
//
|
||||
|
||||
#pragma omp simd linear(val(k) : 3)
|
||||
// CHECK: [[VAL_REF:%.+]] = load i64*, i64** [[K_ADDR]],
|
||||
// CHECK: store i64* [[VAL_REF]], i64** [[K_ADDR_REF:%.+]],
|
||||
// CHECK: store i32 0, i32* [[OMP_IV:%[^,]+]]
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR]],
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR_REF]],
|
||||
// CHECK: [[K0LOAD:%.+]] = load i64, i64* [[K_REF]]
|
||||
// CHECK-NEXT: store i64 [[K0LOAD]], i64* [[LIN0:%[^,]+]]
|
||||
|
||||
@ -571,7 +575,7 @@ void linear(float *a) {
|
||||
// CHECK: [[SIMPLE_LOOP_END]]
|
||||
//
|
||||
// Update linear vars after loop, as the loop was operating on a private version.
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR]],
|
||||
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR_REF]],
|
||||
// CHECK: store i64* [[K_REF]], i64** [[K_PRIV_REF:%.+]],
|
||||
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
|
||||
// CHECK-NEXT: [[LIN_ADD2:%.+]] = add nsw i64 [[LIN0_2]], 27
|
||||
|
Loading…
x
Reference in New Issue
Block a user