Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions llvm/lib/Transforms/Coroutines/CoroSplit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,7 @@ static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape,
}

/// Returns all debug records in F.
static SmallVector<DbgVariableRecord *>
collectDbgVariableRecords(Function &F) {
static SmallVector<DbgVariableRecord *> collectDbgVariableRecords(Function &F) {
SmallVector<DbgVariableRecord *> DbgVariableRecords;
for (auto &I : instructions(F)) {
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
Expand Down Expand Up @@ -933,15 +932,19 @@ void coro::BaseCloner::create() {
auto NewAttrs = AttributeList();

switch (Shape.ABI) {
case coro::ABI::Switch:
case coro::ABI::Switch: {
// Bootstrap attributes by copying function attributes from the
// original function. This should include optimization settings and so on.
NewAttrs = NewAttrs.addFnAttributes(
Context, AttrBuilder(Context, OrigAttrs.getFnAttrs()));
AttrBuilder Builder(Context, OrigAttrs.getFnAttrs());
// Remove all the memory attribute, as copying too strict attributes caused
// UB.
Builder.removeAttribute(Attribute::AttrKind::Memory);
NewAttrs = NewAttrs.addFnAttributes(Context, std::move(Builder));

addFramePointerAttrs(NewAttrs, Context, 0, Shape.FrameSize,
Shape.FrameAlign, /*NoAlias=*/false);
break;
}
case coro::ABI::Async: {
auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
Expand Down
40 changes: 40 additions & 0 deletions llvm/test/Transforms/Coroutines/coro-split-func-attrs.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
; RUN: opt %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

; Verify that memory attributes are not copied blindly to generated functions.

declare ptr @aligned_alloc(i64, i64)
declare void @free(ptr %mem)

define ptr @f(i32 %a, i32 %b) presplitcoroutine memory(none) "keep" {
entry:
%promise = alloca i32
%id = call token @llvm.coro.id(i32 0, ptr %promise, ptr null, ptr null)
%size = call i64 @llvm.coro.size.i64()
%align = call i64 @llvm.coro.align.i64()
%alloc = call ptr @aligned_alloc(i64 %size, i64 %align)
%hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
%s0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %s0, label %suspend [i8 0, label %one_block
i8 1, label %cleanup]
one_block:
%c = add nuw i32 %a, %b
store i32 %c, ptr %promise
%s1 = call i8 @llvm.coro.suspend(token none, i1 true)
switch i8 %s1, label %suspend [i8 0, label %trap
i8 1, label %cleanup]
cleanup:
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
%unused = call i1 @llvm.coro.end(ptr %hdl, i1 false, token none)
ret ptr %hdl
trap:
call void @llvm.trap()
unreachable
}

; CHECK: @f.resume({{.*}}) #[[RESUME_ATTRS:[[:alnum:]]+]]
; CHECK: @f.destroy({{.*}}) #[[RESUME_ATTRS]]
; CHECK: @f.cleanup({{.*}}) #[[RESUME_ATTRS]]
; CHECK: attributes #[[RESUME_ATTRS]] = { "keep" }