From 5e2254881a7dbb0db56eb459af9f038bb7f80e26 Mon Sep 17 00:00:00 2001 From: TB Schardl Date: Tue, 30 Jun 2020 01:20:14 +0000 Subject: [PATCH] [Cilk] Emit a diagnostic message, rather than fail an assert, when codegen fails to emit a spawn. Addresses issue #5 --- clang/lib/CodeGen/CGCilk.cpp | 13 +++---------- clang/lib/CodeGen/CGExpr.cpp | 4 ++-- clang/lib/CodeGen/CGExprAgg.cpp | 12 ++++++------ clang/lib/CodeGen/CGExprComplex.cpp | 8 ++++---- clang/lib/CodeGen/CGExprScalar.cpp | 8 ++++---- clang/lib/CodeGen/CGStmt.cpp | 4 ++-- clang/lib/CodeGen/CodeGenFunction.h | 10 +++++++++- clang/test/Cilk/spawn-expr.c | 15 +++++++++++++++ 8 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 clang/test/Cilk/spawn-expr.c diff --git a/clang/lib/CodeGen/CGCilk.cpp b/clang/lib/CodeGen/CGCilk.cpp index 8bdd53804bfd..8f9ca9b2f671 100644 --- a/clang/lib/CodeGen/CGCilk.cpp +++ b/clang/lib/CodeGen/CGCilk.cpp @@ -192,7 +192,7 @@ void CodeGenFunction::DetachScope::StartDetach() { } void CodeGenFunction::DetachScope::CleanupDetach() { - if (DetachCleanedUp) + if (!DetachStarted || DetachCleanedUp) return; // Pop the sync region for the detached task. @@ -380,13 +380,6 @@ static const Stmt *IgnoreImplicitAndCleanups(const Stmt *S) { return Current; } -static void FailedSpawnWarning(CodeGenFunction &CGF, SourceLocation SLoc) { - DiagnosticsEngine &Diags = CGF.CGM.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning, - "Failed to produce spawn"); - Diags.Report(SLoc, DiagID); -} - void CodeGenFunction::EmitCilkSpawnStmt(const CilkSpawnStmt &S) { // Handle spawning of calls in a special manner, to evaluate // arguments before spawn. @@ -403,7 +396,7 @@ void CodeGenFunction::EmitCilkSpawnStmt(const CilkSpawnStmt &S) { // Finish the detach. if (IsSpawned) { if (!CurDetachScope->IsDetachStarted()) - FailedSpawnWarning(*this, S.getBeginLoc()); + FailedSpawnWarning(S.getBeginLoc()); IsSpawned = false; PopDetachScope(); } @@ -441,7 +434,7 @@ LValue CodeGenFunction::EmitCilkSpawnExprLValue(const CilkSpawnExpr *E) { // Finish the detach. if (IsSpawned) { if (!CurDetachScope->IsDetachStarted()) - FailedSpawnWarning(*this, E->getExprLoc()); + FailedSpawnWarning(E->getExprLoc()); IsSpawned = false; PopDetachScope(); } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1d36b2689c2e..39df2b7950b0 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4646,8 +4646,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { EmitStoreThroughLValue(RV, LV); // Finish the detach. - assert(CurDetachScope && CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce a detach."); + if (!(CurDetachScope && CurDetachScope->IsDetachStarted())) + FailedSpawnWarning(E->getRHS()->getExprLoc()); PopDetachScope(); IsSpawned = false; diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index cf85b4f47e7b..c501469c65d6 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -890,8 +890,8 @@ void AggExprEmitter::VisitCilkSpawnExpr(CilkSpawnExpr *E) { Visit(E->getSpawnedExpr()); // Pop the detach scope - assert(CGF.IsSpawned && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce a detach."); + if (!(CGF.IsSpawned && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(E->getExprLoc()); CGF.IsSpawned = false; CGF.PopDetachScope(); } @@ -1192,8 +1192,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { Visit(E->getRHS()); CGF.EmitAtomicStore(Dest.asRValue(), LHS, /*isInit*/ false); if (CGF.IsSpawned) { - assert(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce a detach."); + if (!(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(E->getRHS()->getExprLoc()); CGF.IsSpawned = false; CGF.PopDetachScope(); } @@ -1217,8 +1217,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { EmitFinalDestCopy(E->getType(), LHS); if (CGF.IsSpawned) { - assert(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce a detach."); + if (!(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(E->getRHS()->getExprLoc()); CGF.IsSpawned = false; CGF.PopDetachScope(); } diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 34e94d898c07..bf5bc9a16628 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -133,8 +133,8 @@ class ComplexExprEmitter CGF.PushDetachScope(); ComplexPairTy C = Visit(CSE->getSpawnedExpr()); if (DoSpawnedInit) { - assert(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce detach."); + if (!(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(CSE->getExprLoc()); LValue LV = LValueToSpawnInit; EmitStoreOfComplex(C, LV, /*init*/ true); @@ -1022,8 +1022,8 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E, EmitStoreOfComplex(Val, LHS, /*isInit*/ false); // Finish the detach. - assert(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce detach."); + if (!(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(E->getRHS()->getExprLoc()); CGF.IsSpawned = false; CGF.PopDetachScope(); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 1bdb6667592b..f69d7148ed95 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -464,9 +464,9 @@ class ScalarExprEmitter CGF.IsSpawned = true; CGF.PushDetachScope(); Value *V = Visit(CSE->getSpawnedExpr()); + if (!(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(CSE->getExprLoc()); if (DoSpawnedInit) { - assert(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce detach."); LValue LV = LValueToSpawnInit; CGF.EmitNullabilityCheck(LV, V, CSE->getExprLoc()); CGF.EmitStoreThroughLValue(RValue::get(V), LV, true); @@ -3974,8 +3974,8 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS); // Finish the detach. - assert(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce detach."); + if (!(CGF.CurDetachScope && CGF.CurDetachScope->IsDetachStarted())) + CGF.FailedSpawnWarning(E->getRHS()->getExprLoc()); CGF.IsSpawned = false; CGF.PopDetachScope(); diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 3000a584e7a3..fa4c91088186 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1145,9 +1145,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { CurDetachScope->CleanupDetach(); cleanupScope.ForceCleanup(); if (IsSpawned) { + if (!(CurDetachScope && CurDetachScope->IsDetachStarted())) + FailedSpawnWarning(RV->getExprLoc()); // Pop the detach scope - assert(IsSpawned && CurDetachScope->IsDetachStarted() && - "Processing _Cilk_spawn of expression did not produce a detach."); IsSpawned = false; PopDetachScope(); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 11d849b04e6f..eefcf828c1a5 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1382,6 +1382,14 @@ class CodeGenFunction : public CodeGenTypeCache { delete CurDetachScope; } + /// Produce a warning that we failed to emit a spawn. + void FailedSpawnWarning(SourceLocation SLoc) { + DiagnosticsEngine &Diags = CGM.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning, + "Failed to emit spawn"); + Diags.Report(SLoc, DiagID); + } + // RAII for automatically popping detach scopes at the end of code-generating // an expression. class DetachScopeRAII { @@ -1396,7 +1404,7 @@ class CodeGenFunction : public CodeGenTypeCache { return; CGF.PopDetachScope(); assert(CGF.CurDetachScope == StartingDetachScope && - "Unexpected detach scope after processing AtomicExpr"); + "Unexpected detach scope"); CGF.IsSpawned = false; } }; diff --git a/clang/test/Cilk/spawn-expr.c b/clang/test/Cilk/spawn-expr.c new file mode 100644 index 000000000000..96cffd89ff24 --- /dev/null +++ b/clang/test/Cilk/spawn-expr.c @@ -0,0 +1,15 @@ +// Check the spawning of builtins. +// +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -fopencilk -verify -ftapir=none -S -emit-llvm -o - | FileCheck %s + +int g(int); + +int f() { + int x = _Cilk_spawn 0; // expected-warning {{Failed to emit spawn}} + g(_Cilk_spawn 7); // expected-warning {{Failed to emit spawn}} + return _Cilk_spawn 1; // expected-warning {{no parallelism from a '_Cilk_spawn' in a return statement}} expected-warning {{Failed to emit spawn}} +} + +// CHECK-LABEL: define {{.*}}i32 @f( +// CHECK-NOT: detach +