diff options
author | Brian Gesiak <modocache@gmail.com> | 2018-06-23 18:57:26 +0000 |
---|---|---|
committer | Brian Gesiak <modocache@gmail.com> | 2018-06-23 18:57:26 +0000 |
commit | 12728474b387b4866245203c092fa45bafed8fe3 (patch) | |
tree | 9734c2e6b977635684a5c7cbf0da5527ec3380dd /clang/lib/CodeGen | |
parent | f4c82cffc6882715045d97f72d989703b643f4ad (diff) | |
download | bcm5719-llvm-12728474b387b4866245203c092fa45bafed8fe3.tar.gz bcm5719-llvm-12728474b387b4866245203c092fa45bafed8fe3.zip |
[Coroutines] Less IR for noexcept await_resume
Summary:
In his review of https://reviews.llvm.org/D45860, @GorNishanov suggested
avoiding generating additional exception-handling IR in the case that
the resume function was marked as 'noexcept', and exceptions could not
occur. This implements that suggestion.
Test Plan: `check-clang`
Reviewers: GorNishanov, EricWF
Reviewed By: GorNishanov
Subscribers: cfe-commits, GorNishanov
Differential Revision: https://reviews.llvm.org/D47673
llvm-svn: 335422
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCoroutine.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index bd1689688fb..4f525c8aac8 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -130,6 +130,16 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { return Prefix; } +static bool memberCallExpressionCanThrow(const Expr *E) { + if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E)) + if (const auto *Proto = + CE->getMethodDecl()->getType()->getAs<FunctionProtoType>()) + if (isNoexceptExceptionSpec(Proto->getExceptionSpecType()) && + Proto->canThrow() == CT_Cannot) + return false; + return true; +} + // Emit suspend expression which roughly looks like: // // auto && x = CommonExpr(); @@ -217,8 +227,12 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co // Emit await_resume expression. CGF.EmitBlock(ReadyBlock); + + // Exception handling requires additional IR. If the 'await_resume' function + // is marked as 'noexcept', we avoid generating this additional IR. CXXTryStmt *TryStmt = nullptr; - if (Coro.ExceptionHandler && Kind == AwaitKind::Init) { + if (Coro.ExceptionHandler && Kind == AwaitKind::Init && + memberCallExpressionCanThrow(S.getResumeExpr())) { Coro.ResumeEHVar = CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh")); Builder.CreateFlagStore(true, Coro.ResumeEHVar); @@ -625,12 +639,20 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; if (CurCoro.Data->ExceptionHandler) { - BasicBlock *BodyBB = createBasicBlock("coro.resumed.body"); - BasicBlock *ContBB = createBasicBlock("coro.resumed.cont"); - Value *SkipBody = - Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar, "coro.resumed.eh"); - Builder.CreateCondBr(SkipBody, ContBB, BodyBB); - EmitBlock(BodyBB); + // If we generated IR to record whether an exception was thrown from + // 'await_resume', then use that IR to determine whether the coroutine + // body should be skipped. + // If we didn't generate the IR (perhaps because 'await_resume' was marked + // as 'noexcept'), then we skip this check. + BasicBlock *ContBB = nullptr; + if (CurCoro.Data->ResumeEHVar) { + BasicBlock *BodyBB = createBasicBlock("coro.resumed.body"); + ContBB = createBasicBlock("coro.resumed.cont"); + Value *SkipBody = Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar, + "coro.resumed.eh"); + Builder.CreateCondBr(SkipBody, ContBB, BodyBB); + EmitBlock(BodyBB); + } auto Loc = S.getLocStart(); CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, @@ -642,7 +664,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock()); ExitCXXTryStmt(*TryStmt); - EmitBlock(ContBB); + if (ContBB) + EmitBlock(ContBB); } else { emitBodyAndFallthrough(*this, S, S.getBody()); |