[PATCH] D97915: [Coroutines] Handle overaligned frame allocation
Yuanfang Chen via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 29 11:53:43 PDT 2021
ychen added a comment.
For coroutine `f0` in `test/CodeGenCoroutines/coro-alloc.cpp`
The allocation looks like this:
; Function Attrs: noinline nounwind optnone mustprogress
define dso_local void @f0() #0 {
entry:
%0 = alloca %struct.global_new_delete_tag, align 1
%1 = alloca %struct.global_new_delete_tag, align 1
%__promise = alloca %"struct.std::experimental::coroutine_traits<void, global_new_delete_tag>::promise_type", align 1
%ref.tmp = alloca %struct.suspend_always, align 1
%undef.agg.tmp = alloca %struct.suspend_always, align 1
%agg.tmp = alloca %"struct.std::experimental::coroutine_handle", align 1
%agg.tmp2 = alloca %"struct.std::experimental::coroutine_handle.0", align 1
%undef.agg.tmp3 = alloca %"struct.std::experimental::coroutine_handle.0", align 1
%ref.tmp4 = alloca %struct.suspend_always, align 1
%undef.agg.tmp5 = alloca %struct.suspend_always, align 1
%agg.tmp7 = alloca %"struct.std::experimental::coroutine_handle", align 1
%agg.tmp8 = alloca %"struct.std::experimental::coroutine_handle.0", align 1
%undef.agg.tmp9 = alloca %"struct.std::experimental::coroutine_handle.0", align 1
%2 = bitcast %"struct.std::experimental::coroutine_traits<void, global_new_delete_tag>::promise_type"* %__promise to i8*
%3 = call token @llvm.coro.id(i32 16, i8* %2, i8* null, i8* null)
%4 = call i1 @llvm.coro.alloc(token %3)
br i1 %4, label %coro.alloc, label %coro.init
coro.alloc: ; preds = %entry
%5 = call i64 @llvm.coro.size.i64()
%6 = call i64 @llvm.coro.align.i64()
%7 = sub nsw i64 %6, 16
%8 = icmp sgt i64 %7, 0
%9 = select i1 %8, i64 %7, i64 0
%10 = add i64 %5, %9
%call = call noalias nonnull i8* @_Znwm(i64 %10) #11
br label %coro.check.align
coro.check.align: ; preds = %coro.alloc
%11 = call i64 @llvm.coro.align.i64()
%12 = icmp ugt i64 %11, 16
br i1 %12, label %coro.alloc.align, label %coro.init
coro.alloc.align: ; preds = %coro.check.align
%mask = sub i64 %11, 1
%intptr = ptrtoint i8* %call to i64
%over_boundary = add i64 %intptr, %mask
%inverted_mask = xor i64 %mask, -1
%aligned_intptr = and i64 %over_boundary, %inverted_mask
%diff = sub i64 %aligned_intptr, %intptr
%aligned_result = getelementptr inbounds i8, i8* %call, i64 %diff
call void @llvm.assume(i1 true) [ "align"(i8* %aligned_result, i64 %11) ]
%13 = call i32 @llvm.coro.raw.frame.ptr.offset.i32()
%14 = getelementptr inbounds i8, i8* %aligned_result, i32 %13
%15 = bitcast i8* %14 to i8**
store i8* %call, i8** %15, align 8
br label %coro.init
coro.init: ; preds = %coro.alloc.align, %coro.check.align, %entry
%16 = phi i8* [ null, %entry ], [ %call, %coro.check.align ], [ %aligned_result, %coro.alloc.align ]
%17 = call i8* @llvm.coro.begin(token %3, i8* %16)
call void @_ZNSt12experimental16coroutine_traitsIJv21global_new_delete_tagEE12promise_type17get_return_objectEv(%"struct.std::experimental::coroutine_traits<void, global_new_delete_tag>::promise_type"* nonnull dereferenceable(1) %__promise)
call void @_ZNSt12experimental16coroutine_traitsIJv21global_new_delete_tagEE12promise_type15initial_suspendEv(%"struct.std::experimental::coroutine_traits<void, global_new_delete_tag>::promise_type"* nonnull dereferenceable(1) %__promise)
%call1 = call zeroext i1 @_ZN14suspend_always11await_readyEv(%struct.suspend_always* nonnull dereferenceable(1) %ref.tmp) #2
br i1 %call1, label %init.ready, label %init.suspend
The deallocation looks like this:
cleanup: ; preds = %final.ready, %final.cleanup, %init.cleanup
%cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %init.cleanup ]
%22 = call i8* @llvm.coro.free(token %3, i8* %17)
%23 = icmp ne i8* %22, null
br i1 %23, label %coro.free, label %after.coro.free
coro.free: ; preds = %cleanup
%24 = call i64 @llvm.coro.align.i64()
%25 = icmp ugt i64 %24, 16
%26 = call i32 @llvm.coro.raw.frame.ptr.offset.i32()
%27 = getelementptr inbounds i8, i8* %22, i32 %26
%28 = bitcast i8* %27 to i8**
%29 = load i8*, i8** %28, align 8
%30 = select i1 %25, i8* %29, i8* %22
call void @_ZdlPv(i8* %30) #2
br label %after.coro.free
after.coro.free: ; preds = %cleanup, %coro.free
switch i32 %cleanup.dest.slot.0, label %unreachable [
i32 0, label %cleanup.cont
i32 2, label %coro.ret
]
cleanup.cont: ; preds = %after.coro.free
br label %coro.ret
coro.ret: ; preds = %cleanup.cont, %after.coro.free, %final.suspend, %init.suspend
%31 = call i1 @llvm.coro.end(i8* null, i1 false)
ret void
unreachable: ; preds = %after.coro.free
unreachable
}
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D97915/new/
https://reviews.llvm.org/D97915
More information about the llvm-commits
mailing list