Skip to content

Commit

Permalink
[OPENMP]Fix PR48571: critical/master in outlined contexts cause crash.
Browse files Browse the repository at this point in the history
If emit inlined region for master/critical directives, no need to clear
lambda/block context data, otherwise the variables cannot be found and
it causes a crash at compile time.

Differential Revision: https://reviews.llvm.org/D99280

(cherry picked from commit 7654bb6)
  • Loading branch information
alexey-bataev authored and tstellar committed Jun 14, 2021
1 parent ce77909 commit 7cc5b15
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 12 deletions.
32 changes: 20 additions & 12 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Expand Up @@ -409,23 +409,27 @@ class InlinedOpenMPRegionRAII {
llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
FieldDecl *LambdaThisCaptureField = nullptr;
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
bool NoInheritance = false;

public:
/// Constructs region for combined constructs.
/// \param CodeGen Code generation sequence for combined directives. Includes
/// a list of functions used for code generation of implicitly inlined
/// regions.
InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
OpenMPDirectiveKind Kind, bool HasCancel)
: CGF(CGF) {
OpenMPDirectiveKind Kind, bool HasCancel,
bool NoInheritance = true)
: CGF(CGF), NoInheritance(NoInheritance) {
// 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;
BlockInfo = CGF.BlockInfo;
CGF.BlockInfo = nullptr;
if (NoInheritance) {
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
LambdaThisCaptureField = CGF.LambdaThisCaptureField;
CGF.LambdaThisCaptureField = nullptr;
BlockInfo = CGF.BlockInfo;
CGF.BlockInfo = nullptr;
}
}

~InlinedOpenMPRegionRAII() {
Expand All @@ -434,9 +438,11 @@ class InlinedOpenMPRegionRAII {
cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
delete CGF.CapturedStmtInfo;
CGF.CapturedStmtInfo = OldCSI;
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
CGF.LambdaThisCaptureField = LambdaThisCaptureField;
CGF.BlockInfo = BlockInfo;
if (NoInheritance) {
std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
CGF.LambdaThisCaptureField = LambdaThisCaptureField;
CGF.BlockInfo = BlockInfo;
}
}
};

Expand Down Expand Up @@ -3853,7 +3859,7 @@ static void emitPrivatesInit(CodeGenFunction &CGF,
// Processing for implicitly captured variables.
InlinedOpenMPRegionRAII Region(
CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown,
/*HasCancel=*/false);
/*HasCancel=*/false, /*NoInheritance=*/true);
SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
}
if (Type->isArrayType()) {
Expand Down Expand Up @@ -6214,7 +6220,9 @@ void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
bool HasCancel) {
if (!CGF.HaveInsertPoint())
return;
InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
InnerKind != OMPD_critical &&
InnerKind != OMPD_master);
CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}

Expand Down
25 changes: 25 additions & 0 deletions clang/test/OpenMP/critical_codegen.cpp
Expand Up @@ -68,6 +68,31 @@ int main() {
return a;
}

// ALL-LABEL: lambda_critical
// TERM_DEBUG-LABEL: lambda_critical
void lambda_critical(int a, int b) {
auto l = [=]() {
#pragma omp critical
{
// ALL: call void @__kmpc_critical(
int c = a + b;
}
};

l();

auto l1 = [=]() {
#pragma omp parallel
#pragma omp critical
{
// ALL: call void @__kmpc_critical(
int c = a + b;
}
};

l1();
}

struct S {
int a;
};
Expand Down
35 changes: 35 additions & 0 deletions clang/test/OpenMP/master_codegen.cpp
Expand Up @@ -55,6 +55,41 @@ int main() {
return a;
}

// ALL-LABEL: lambda_master
// TERM_DEBUG-LABEL: lambda_master
void lambda_master(int a, int b) {
auto l = [=]() {
#pragma omp master
{
// ALL: call i32 @__kmpc_master(
int c = a + b;
}
};

l();

auto l1 = [=]() {
#pragma omp parallel
#pragma omp master
{
// ALL: call i32 @__kmpc_master(
int c = a + b;
}
};

l1();

auto l2 = [=]() {
#pragma omp parallel master
{
// ALL: call i32 @__kmpc_master(
int c = a + b;
}
};

l2();
}

// ALL-LABEL: parallel_master
// TERM_DEBUG-LABEL: parallel_master
void parallel_master() {
Expand Down

0 comments on commit 7cc5b15

Please sign in to comment.