Skip to content

Commit

Permalink
Revert "[Coro] [async] Disable inlining in async coroutine splitting (l…
Browse files Browse the repository at this point in the history
…lvm#80904)"

This reverts commit b1ac052.

This commit breaks coroutine splitting for non-swift calling convention
functions. In this example:

```ll
; ModuleID = 'repro.ll'
source_filename = "stdlib/test/runtime/test_llcl.mojo"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = internal constant { i32, i32 } { i32 trunc (i64 sub (i64 ptrtoint (ptr @craSH to i64), i64 ptrtoint (ptr getelementptr inbounds ({ i32, i32 }, ptr @0, i32 0, i32 1) to i64)) to i32), i32 64 }

define dso_local void @af_suspend_fn(ptr %0, i64 %1, ptr %2) #0 {
  ret void
}

define dso_local void @craSH(ptr %0) #0 {
  %2 = call token @llvm.coro.id.async(i32 64, i32 8, i32 0, ptr @0)
  %3 = call ptr @llvm.coro.begin(token %2, ptr null)
  %4 = getelementptr inbounds { ptr, { ptr, ptr }, i64, { ptr, i1 }, i64, i64 }, ptr poison, i32 0, i32 0
  %5 = call ptr @llvm.coro.async.resume()
  store ptr %5, ptr %4, align 8
  %6 = call { ptr, ptr, ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0p0p0s(i32 0, ptr %5, ptr @ctxt_proj_fn, ptr @af_suspend_fn, ptr poison, i64 -1, ptr poison)
  ret void
}

define dso_local ptr @ctxt_proj_fn(ptr %0) #0 {
  ret ptr %0
}

; Function Attrs: nomerge nounwind
declare { ptr, ptr, ptr } @llvm.coro.suspend.async.sl_p0p0p0s(i32, ptr, ptr, ...) #1

; Function Attrs: nounwind
declare token @llvm.coro.id.async(i32, i32, i32, ptr) rust-lang#2

; Function Attrs: nounwind
declare ptr @llvm.coro.begin(token, ptr writeonly) rust-lang#2

; Function Attrs: nomerge nounwind
declare ptr @llvm.coro.async.resume() #1

attributes #0 = { "target-features"="+adx,+aes,+avx,+avx2,+bmi,+bmi2,+clflushopt,+clwb,+clzero,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+mwaitx,+pclmul,+pku,+popcnt,+prfchw,+rdpid,+rdpru,+rdrnd,+rdseed,+sahf,+sha,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+sse4a,+ssse3,+vaes,+vpclmulqdq,+wbnoinvd,+x87,+xsave,+xsavec,+xsaveopt,+xsaves" }
attributes #1 = { nomerge nounwind }
attributes rust-lang#2 = { nounwind }
```

This verifier crashes after the `coro-split` pass with

```
cannot guarantee tail call due to mismatched parameter counts
  musttail call void @af_suspend_fn(ptr poison, i64 -1, ptr poison)
LLVM ERROR: Broken function
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: opt ../../../reduced.ll -O0
 #0 0x00007f1d89645c0e __interceptor_backtrace.part.0 /build/gcc-11-XeT9lY/gcc-11-11.4.0/build/x86_64-linux-gnu/libsanitizer/asan/../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4193:28
 #1 0x0000556d94d254f7 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:22
 rust-lang#2 0x0000556d94d19a2f llvm::sys::RunSignalHandlers() /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Support/Signals.cpp:105:20
 rust-lang#3 0x0000556d94d1aa42 SignalHandler(int) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Support/Unix/Signals.inc:371:36
 rust-lang#4 0x00007f1d88e42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 rust-lang#5 0x00007f1d88e969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 rust-lang#6 0x00007f1d88e969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 rust-lang#7 0x00007f1d88e969fc pthread_kill ./nptl/pthread_kill.c:89:10
 rust-lang#8 0x00007f1d88e42476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 rust-lang#9 0x00007f1d88e287f3 abort ./stdlib/abort.c:81:7
 rust-lang#10 0x0000556d8944be01 std::vector<llvm::json::Value, std::allocator<llvm::json::Value>>::size() const /usr/include/c++/11/bits/stl_vector.h:919:40
 rust-lang#11 0x0000556d8944be01 bool std::operator==<llvm::json::Value, std::allocator<llvm::json::Value>>(std::vector<llvm::json::Value, std::allocator<llvm::json::Value>> const&, std::vector<llvm::json::Value, std::allocator<llvm::json::Value>> const&) /usr/include/c++/11/bits/stl_vector.h:1893:23
 rust-lang#12 0x0000556d8944be01 llvm::json::operator==(llvm::json::Array const&, llvm::json::Array const&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/Support/JSON.h:572:69
 rust-lang#13 0x0000556d8944be01 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Support/JSON.cpp:204:28
 rust-lang#14 0x0000556d949ed2bd llvm::report_fatal_error(char const*, bool) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Support/ErrorHandling.cpp:82:70
 rust-lang#15 0x0000556d8e37e876 llvm::SmallVectorBase<unsigned int>::size() const /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallVector.h:91:32
 rust-lang#16 0x0000556d8e37e876 llvm::SmallVectorTemplateCommon<llvm::DiagnosticInfoOptimizationBase::Argument, void>::end() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallVector.h:282:41
 rust-lang#17 0x0000556d8e37e876 llvm::SmallVector<llvm::DiagnosticInfoOptimizationBase::Argument, 4u>::~SmallVector() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallVector.h:1215:24
 rust-lang#18 0x0000556d8e37e876 llvm::DiagnosticInfoOptimizationBase::~DiagnosticInfoOptimizationBase() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/DiagnosticInfo.h:413:7
 rust-lang#19 0x0000556d8e37e876 llvm::DiagnosticInfoIROptimization::~DiagnosticInfoIROptimization() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/DiagnosticInfo.h:622:7
 rust-lang#20 0x0000556d8e37e876 llvm::OptimizationRemark::~OptimizationRemark() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/DiagnosticInfo.h:689:7
 rust-lang#21 0x0000556d8e37e876 operator() /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Transforms/Coroutines/CoroSplit.cpp:2213:14
 rust-lang#22 0x0000556d8e37e876 emit<llvm::CoroSplitPass::run(llvm::LazyCallGraph::SCC&, llvm::CGSCCAnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&)::<lambda()> > /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h:83:12
 rust-lang#23 0x0000556d8e37e876 llvm::CoroSplitPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Transforms/Coroutines/CoroSplit.cpp:2212:13
 rust-lang#24 0x0000556d8c36ecb1 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CoroSplitPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:3
 rust-lang#25 0x0000556d91c1a84f llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:90:12
 rust-lang#26 0x0000556d8c3690d1 llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:3
 rust-lang#27 0x0000556d91c2162d llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:278:18
 rust-lang#28 0x0000556d8c369035 llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:3
 rust-lang#29 0x0000556d9457abc5 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/PassManager.h:247:20
 rust-lang#30 0x0000556d8e30979e llvm::CoroConditionalWrapper::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/ubuntu/modular/third-party/llvm-project/llvm/lib/Transforms/Coroutines/CoroConditionalWrapper.cpp:19:74
 rust-lang#31 0x0000556d8c365755 llvm::detail::PassModel<llvm::Module, llvm::CoroConditionalWrapper, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:3
 rust-lang#32 0x0000556d9457abc5 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/PassManager.h:247:20
 rust-lang#33 0x0000556d89818556 llvm::SmallPtrSetImplBase::isSmall() const /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:196:33
 rust-lang#34 0x0000556d89818556 llvm::SmallPtrSetImplBase::~SmallPtrSetImplBase() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:84:17
 rust-lang#35 0x0000556d89818556 llvm::SmallPtrSetImpl<llvm::AnalysisKey*>::~SmallPtrSetImpl() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:321:7
 rust-lang#36 0x0000556d89818556 llvm::SmallPtrSet<llvm::AnalysisKey*, 2u>::~SmallPtrSet() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/ADT/SmallPtrSet.h:427:7
 rust-lang#37 0x0000556d89818556 llvm::PreservedAnalyses::~PreservedAnalyses() /home/ubuntu/modular/third-party/llvm-project/llvm/include/llvm/IR/Analysis.h:109:7
 rust-lang#38 0x0000556d89818556 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) /home/ubuntu/modular/third-party/llvm-project/llvm/tools/opt/NewPMDriver.cpp:532:10
 rust-lang#39 0x0000556d897e3939 optMain /home/ubuntu/modular/third-party/llvm-project/llvm/tools/opt/optdriver.cpp:737:27
 rust-lang#40 0x0000556d89455461 main /home/ubuntu/modular/third-party/llvm-project/llvm/tools/opt/opt.cpp:25:33
 rust-lang#41 0x00007f1d88e29d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
 rust-lang#42 0x00007f1d88e29e40 call_init ./csu/../csu/libc-start.c:128:20
 rust-lang#43 0x00007f1d88e29e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
 rust-lang#44 0x0000556d897b6335 _start (/home/ubuntu/modular/.derived/third-party/llvm-project/build-relwithdebinfo-asan/bin/opt+0x150c335)
Aborted (core dumped)
  • Loading branch information
Mogball committed Feb 21, 2024
1 parent 2cd59bd commit 2e29c91
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 262 deletions.
81 changes: 47 additions & 34 deletions llvm/lib/Transforms/Coroutines/CoroSplit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ class CoroCloner {
/// Create a cloner for a switch lowering.
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
Kind FKind)
: OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape),
FKind(FKind), Builder(OrigF.getContext()) {
: OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape), FKind(FKind),
Builder(OrigF.getContext()) {
assert(Shape.ABI == coro::ABI::Switch);
}

Expand Down Expand Up @@ -170,8 +170,7 @@ class CoroCloner {
static void maybeFreeRetconStorage(IRBuilder<> &Builder,
const coro::Shape &Shape, Value *FramePtr,
CallGraph *CG) {
assert(Shape.ABI == coro::ABI::Retcon ||
Shape.ABI == coro::ABI::RetconOnce);
assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce);
if (Shape.RetconLowering.IsFrameInlineInStorage)
return;

Expand Down Expand Up @@ -208,12 +207,17 @@ static bool replaceCoroEndAsync(AnyCoroEndInst *End) {
// Insert the return instruction.
Builder.SetInsertPoint(End);
Builder.CreateRetVoid();
InlineFunctionInfo FnInfo;

// Remove the rest of the block, by splitting it into an unreachable block.
auto *BB = End->getParent();
BB->splitBasicBlock(End);
BB->getTerminator()->eraseFromParent();

auto InlineRes = InlineFunction(*MustTailCall, FnInfo);
assert(InlineRes.isSuccess() && "Expected inlining to succeed");
(void)InlineRes;

// We have cleaned up the coro.end block above.
return false;
}
Expand Down Expand Up @@ -264,7 +268,7 @@ static void replaceFallthroughCoroEnd(AnyCoroEndInst *End,

if (auto *RetStructTy = dyn_cast<StructType>(RetTy)) {
assert(RetStructTy->getNumElements() == NumReturns &&
"numbers of returns should match resume function singature");
"numbers of returns should match resume function singature");
Value *ReturnValue = UndefValue::get(RetStructTy);
unsigned Idx = 0;
for (Value *RetValEl : CoroResults->return_values())
Expand All @@ -277,7 +281,8 @@ static void replaceFallthroughCoroEnd(AnyCoroEndInst *End,
assert(NumReturns == 1);
Builder.CreateRet(*CoroResults->retval_begin());
}
CoroResults->replaceAllUsesWith(ConstantTokenNone::get(CoroResults->getContext()));
CoroResults->replaceAllUsesWith(
ConstantTokenNone::get(CoroResults->getContext()));
CoroResults->eraseFromParent();
break;
}
Expand All @@ -291,7 +296,7 @@ static void replaceFallthroughCoroEnd(AnyCoroEndInst *End,
auto RetTy = Shape.getResumeFunctionType()->getReturnType();
auto RetStructTy = dyn_cast<StructType>(RetTy);
PointerType *ContinuationTy =
cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) : RetTy);
cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) : RetTy);

Value *ReturnValue = ConstantPointerNull::get(ContinuationTy);
if (RetStructTy) {
Expand Down Expand Up @@ -480,11 +485,12 @@ void CoroCloner::replaceRetconOrAsyncSuspendUses() {
Shape.ABI == coro::ABI::Async);

auto NewS = VMap[ActiveSuspend];
if (NewS->use_empty()) return;
if (NewS->use_empty())
return;

// Copy out all the continuation arguments after the buffer pointer into
// an easily-indexed data structure for convenience.
SmallVector<Value*, 8> Args;
SmallVector<Value *, 8> Args;
// The async ABI includes all arguments -- including the first argument.
bool IsAsyncABI = Shape.ABI == coro::ABI::Async;
for (auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
Expand All @@ -511,7 +517,8 @@ void CoroCloner::replaceRetconOrAsyncSuspendUses() {
}

// If we have no remaining uses, we're done.
if (NewS->use_empty()) return;
if (NewS->use_empty())
return;

// Otherwise, we need to create an aggregate.
Value *Agg = PoisonValue::get(NewS->getType());
Expand Down Expand Up @@ -549,7 +556,8 @@ void CoroCloner::replaceCoroSuspends() {

for (AnyCoroSuspendInst *CS : Shape.CoroSuspends) {
// The active suspend was handled earlier.
if (CS == ActiveSuspend) continue;
if (CS == ActiveSuspend)
continue;

auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
MappedCS->replaceAllUsesWith(SuspendResult);
Expand Down Expand Up @@ -707,7 +715,7 @@ void CoroCloner::replaceEntryBlock() {
// In switch-lowering, we built a resume-entry block in the original
// function. Make the entry block branch to this.
auto *SwitchBB =
cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
Builder.CreateBr(SwitchBB);
break;
}
Expand Down Expand Up @@ -1055,7 +1063,7 @@ void CoroCloner::create() {
// to suppress deallocation code.
if (Shape.ABI == coro::ABI::Switch)
coro::replaceCoroFree(cast<CoroIdInst>(VMap[Shape.CoroBegin->getId()]),
/*Elide=*/ FKind == CoroCloner::Kind::SwitchCleanup);
/*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup);
}

static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) {
Expand Down Expand Up @@ -1842,8 +1850,13 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape,
SmallVector<Value *, 8> Args(Suspend->args());
auto FnArgs = ArrayRef<Value *>(Args).drop_front(
CoroSuspendAsyncInst::MustTailCallFuncArg + 1);
coro::createMustTailCall(Suspend->getDebugLoc(), Fn, TTI, FnArgs, Builder);
auto *TailCall = coro::createMustTailCall(Suspend->getDebugLoc(), Fn, TTI,
FnArgs, Builder);
Builder.CreateRetVoid();
InlineFunctionInfo FnInfo;
auto InlineRes = InlineFunction(*TailCall, FnInfo);
assert(InlineRes.isSuccess() && "Expected inlining to succeed");
(void)InlineRes;

// Replace the lvm.coro.async.resume intrisic call.
replaceAsyncResumeFunction(Suspend, Continuation);
Expand All @@ -1860,8 +1873,7 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape,

static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
SmallVectorImpl<Function *> &Clones) {
assert(Shape.ABI == coro::ABI::Retcon ||
Shape.ABI == coro::ABI::RetconOnce);
assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce);
assert(Clones.empty());

// Reset various things that the optimizer might have decided it
Expand All @@ -1887,7 +1899,7 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
// FIXME: pass the required alignment
RawFramePtr = Shape.emitAlloc(Builder, Builder.getInt64(Size), nullptr);
RawFramePtr =
Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());
Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());

// Stash the allocated frame pointer in the continuation storage.
Builder.CreateStore(RawFramePtr, Id->getStorage());
Expand Down Expand Up @@ -1927,8 +1939,8 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
// Create the unified return block.
if (!ReturnBB) {
// Place it before the first suspend.
ReturnBB = BasicBlock::Create(F.getContext(), "coro.return", &F,
NewSuspendBB);
ReturnBB =
BasicBlock::Create(F.getContext(), "coro.return", &F, NewSuspendBB);
Shape.RetconLowering.ReturnBlock = ReturnBB;

IRBuilder<> Builder(ReturnBB);
Expand All @@ -1942,8 +1954,8 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,

// Next, all the directly-yielded values.
for (auto *ResultTy : Shape.getRetconResultTypes())
ReturnPHIs.push_back(Builder.CreatePHI(ResultTy,
Shape.CoroSuspends.size()));
ReturnPHIs.push_back(
Builder.CreatePHI(ResultTy, Shape.CoroSuspends.size()));

// Build the return value.
auto RetTy = F.getReturnType();
Expand All @@ -1952,9 +1964,9 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
// We can't rely on the types matching up because that type would
// have to be infinite.
auto CastedContinuationTy =
(ReturnPHIs.size() == 1 ? RetTy : RetTy->getStructElementType(0));
(ReturnPHIs.size() == 1 ? RetTy : RetTy->getStructElementType(0));
auto *CastedContinuation =
Builder.CreateBitCast(ReturnPHIs[0], CastedContinuationTy);
Builder.CreateBitCast(ReturnPHIs[0], CastedContinuationTy);

Value *RetV;
if (ReturnPHIs.size() == 1) {
Expand Down Expand Up @@ -1988,17 +2000,18 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
}

namespace {
class PrettyStackTraceFunction : public PrettyStackTraceEntry {
Function &F;
public:
PrettyStackTraceFunction(Function &F) : F(F) {}
void print(raw_ostream &OS) const override {
OS << "While splitting coroutine ";
F.printAsOperand(OS, /*print type*/ false, F.getParent());
OS << "\n";
}
};
}
class PrettyStackTraceFunction : public PrettyStackTraceEntry {
Function &F;

public:
PrettyStackTraceFunction(Function &F) : F(F) {}
void print(raw_ostream &OS) const override {
OS << "While splitting coroutine ";
F.printAsOperand(OS, /*print type*/ false, F.getParent());
OS << "\n";
}
};
} // namespace

static coro::Shape
splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ declare void @my_other_async_function(ptr %async.ctxt)
i32 128 ; Initial async context size without space for frame
}>

define swifttailcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline {
tail call swifttailcc void %fnPtr(ptr %async.ctxt)
define swiftcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
tail call swiftcc void %fnPtr(ptr %async.ctxt)
ret void
}

Expand All @@ -37,12 +37,12 @@ entry:

; The address of alloca escapes but the analysis based on lifetimes fails to see
; that it can't localize this alloca.
; CHECK: define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) {
; CHECK: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) {
; CHECK: entry:
; CHECK-NOT: ret
; CHECK-NOT: [[ESCAPED_ADDR:%.*]] = alloca i64, align 8
; CHECK: ret
define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) {
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) {
entry:
%escaped_addr = alloca i64

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ declare void @my_other_async_function(ptr %async.ctxt)
i32 128 ; Initial async context size without space for frame
}>

define swifttailcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline {
tail call swifttailcc void %fnPtr(ptr %async.ctxt)
define swiftcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
tail call swiftcc void %fnPtr(ptr %async.ctxt)
ret void
}

Expand All @@ -36,7 +36,7 @@ entry:
ret ptr %resume_ctxt
}

define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) {
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) {
entry:
%escaped_addr = alloca i64

Expand Down
10 changes: 5 additions & 5 deletions llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ declare swiftcc void @asyncReturn(ptr)
declare swiftcc void @asyncSuspend(ptr)
declare {ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)

define swifttailcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline {
musttail call swifttailcc void %fnPtr(ptr %async.ctxt)
define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
tail call swiftcc void %fnPtr(ptr %async.ctxt)
ret void
}

define ptr @__swift_async_resume_project_context(ptr %ctxt) alwaysinline {
define ptr @__swift_async_resume_project_context(ptr %ctxt) {
entry:
%resume_ctxt = load ptr, ptr %ctxt, align 8
ret ptr %resume_ctxt
}


; CHECK: %my_async_function.Frame = type { i64, [48 x i8], i64, i64, [16 x i8], ptr, i64, ptr }
; CHECK: define swifttailcc void @my_async_function
; CHECK: define swiftcc void @my_async_function
; CHECK: [[T0:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr %async.ctx.frameptr, i32 0, i32 3
; CHECK: [[T1:%.*]] = ptrtoint ptr [[T0]] to i64
; CHECK: [[T2:%.*]] = add i64 [[T1]], 31
Expand All @@ -60,7 +60,7 @@ entry:
; CHECK: store i64 2, ptr [[T4]]
; CHECK: store i64 3, ptr [[T9]]

define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine {
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine {
entry:
%tmp = alloca i64, align 8
%tmp2 = alloca i64, align 16
Expand Down
Loading

0 comments on commit 2e29c91

Please sign in to comment.