[llvm-dev] problem with moveSpillUsesAfterCoroBegin
Andrew Kelley via llvm-dev
llvm-dev at lists.llvm.org
Sun Feb 25 22:14:07 PST 2018
Here's what this function is supposed to do:
// Move early uses of spilled variable after CoroBegin.
// For example, if a parameter had address taken, we may end up with the
code
// like:
// define @f(i32 %n) {
// %n.addr = alloca i32
// store %n, %n.addr
// ...
// call @coro.begin
// we need to move the store after coro.begin
in the implementation it has:
// TODO: Make this more robust. Currently if we run into a situation
// where simple instruction move won't work we panic and
// report_fatal_error.
for (User *UI : I->users()) {
if (!DT.dominates(CoroBegin, cast<Instruction>(UI)))
report_fatal_error("cannot move instruction since its users are
not"
" dominated by CoroBegin");
}
here is what my frontend is currently generating (I'll paste the frontend
code for clarity and then the LLVM IR):
const std = @import("std");
export fn entry() void {
const p = (async(std.debug.global_allocator) amain()) catch unreachable;
cancel p;
}
async fn amain() error {
return error.Failure;
}
; Function Attrs: nobuiltin nounwind
define void @entry() #0 !dbg !220 {
Entry:
%0 = alloca { i16, i8* }, align 8
%1 = alloca { i16, i8* }, align 8
%p = alloca i8*, align 8
%2 = getelementptr inbounds { i16, i8* }, { i16, i8* }* %0, i32 0, i32 0,
!dbg !226
store i16 0, i16* %2, !dbg !226
%3 = call fastcc i8* @amain(%Allocator* getelementptr inbounds
(%FixedBufferAllocator, %FixedBufferAllocator* @global_fixed_allocator, i32
0, i32 0), i16* %2), !dbg !226
%4 = getelementptr inbounds { i16, i8* }, { i16, i8* }* %0, i32 0, i32 1,
!dbg !226
store i8* %3, i8** %4, !dbg !226
%5 = getelementptr inbounds { i16, i8* }, { i16, i8* }* %0, i32 0, i32 0,
!dbg !227
%6 = load i16, i16* %5, align 2, !dbg !227
%7 = icmp eq i16 %6, 0, !dbg !227
br i1 %7, label %UnwrapErrOk, label %UnwrapErrError, !dbg !227
UnwrapErrError: ; preds = %Entry
tail call fastcc void @__zig_fail_unwrap(%StackTrace* null, i16 %6), !dbg
!227
unreachable, !dbg !227
UnwrapErrOk: ; preds = %Entry
%8 = getelementptr inbounds { i16, i8* }, { i16, i8* }* %0, i32 0, i32 1,
!dbg !227
%9 = load i8*, i8** %8, align 8, !dbg !227
store i8* %9, i8** %p, align 8, !dbg !228
call void @llvm.dbg.declare(metadata i8** %p, metadata !224, metadata
!DIExpression()), !dbg !228
%10 = load i8*, i8** %p, align 8, !dbg !229
call void @llvm.coro.destroy(i8* %10), !dbg !231
ret void, !dbg !232
}
; Function Attrs: nobuiltin nounwind
define internal fastcc i8* @amain(%StackTrace* nonnull, %Allocator*, i16*)
unnamed_addr #0 !dbg !234 {
Entry:
%3 = alloca { i16, %"[]u8" }, align 8
%4 = alloca { i16, %"[]u8" }, align 8
%_anon = alloca %AsyncFramePromise, align 8
%5 = bitcast %AsyncFramePromise* %_anon to i8*, !dbg !245
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* bitcast
(%AsyncFramePromise* @16 to i8*), i64 24, i32 8, i1 false), !dbg !245
call void @llvm.dbg.declare(metadata %AsyncFramePromise* %_anon, metadata
!239, metadata !DIExpression()), !dbg !245
%6 = bitcast %AsyncFramePromise* %_anon to i8*, !dbg !245
%7 = call token @llvm.coro.id(i32 16, i8* %6, i8* null, i8* null), !dbg
!245
%8 = call i1 @llvm.coro.alloc(token %7), !dbg !245
br i1 %8, label %DynAlloc, label %CoroBegin, !dbg !245
DynAlloc: ; preds = %Entry
%9 = call i64 @llvm.coro.size.i64(), !dbg !245
%10 = getelementptr inbounds %Allocator, %Allocator* %1, i32 0, i32 0,
!dbg !245
%11 = load void ({ i16, %"[]u8" }*, %StackTrace*, %Allocator*, i64,
i29)*, void ({ i16, %"[]u8" }*, %StackTrace*, %Allocator*, i64, i29)** %10,
align 8, !dbg !245
call fastcc void %11({ i16, %"[]u8" }* %3, %StackTrace* %0, %Allocator*
%1, i64 %9, i29 16), !dbg !245
%12 = getelementptr inbounds { i16, %"[]u8" }, { i16, %"[]u8" }* %3, i32
0, i32 0, !dbg !245
%13 = load i16, i16* %12, align 2, !dbg !245
%14 = icmp ne i16 %13, 0, !dbg !245
br i1 %14, label %AllocError, label %AllocOk, !dbg !245
AllocError: ; preds = %DynAlloc
%15 = getelementptr inbounds { i16, %"[]u8" }, { i16, %"[]u8" }* %3, i32
0, i32 0, !dbg !245
%16 = load i16, i16* %15, align 2, !dbg !245
store i16 %16, i16* %2, !dbg !245
ret i8* null, !dbg !245
AllocOk: ; preds = %DynAlloc
%17 = getelementptr inbounds { i16, %"[]u8" }, { i16, %"[]u8" }* %3, i32
0, i32 1, !dbg !245
%18 = getelementptr inbounds %"[]u8", %"[]u8"* %17, i32 0, i32 0, !dbg
!245
%19 = load i8*, i8** %18, align 8, !dbg !245
br label %CoroBegin, !dbg !245
CoroBegin: ; preds = %AllocOk, %Entry
%20 = phi i8* [ null, %Entry ], [ %19, %AllocOk ], !dbg !245
%21 = phi %"[]u8"* [ undef, %Entry ], [ %17, %AllocOk ], !dbg !245
%22 = call i8* @llvm.coro.begin(token %7, i8* %20), !dbg !245
%23 = getelementptr inbounds %AsyncFramePromise, %AsyncFramePromise*
%_anon, i32 0, i32 0, !dbg !245
%24 = getelementptr inbounds %AsyncFramePromise, %AsyncFramePromise*
%_anon, i32 0, i32 1, !dbg !245
%25 = getelementptr inbounds %AsyncFramePromise, %AsyncFramePromise*
%_anon, i32 0, i32 2, !dbg !245
store i16* %24, i16** %25, align 8, !dbg !245
%26 = load i16*, i16** %25, align 8, !dbg !246
store i16 2, i16* %26, align 2, !dbg !246
%27 = load i8*, i8** %23, align 8, !dbg !246
%28 = icmp ne i8* %27, null, !dbg !246
br i1 %28, label %CoroNormalFinal, label %CoroEarlyFinal, !dbg !246
CoroEarlyFinal: ; preds = %CoroBegin
%29 = call i8 @llvm.coro.suspend(token none, i1 true), !dbg !245
switch i8 %29, label %Suspend [
i8 0, label %InvalidResume
i8 1, label %FinalCleanup
], !dbg !245
Suspend: ; preds = %CoroEarlyFinal
%30 = call i1 @llvm.coro.end(i8* null, i1 false), !dbg !245
ret i8* %22, !dbg !245
InvalidResume: ; preds = %CoroEarlyFinal
tail call fastcc void @panic(%"[]u8"* @20, %StackTrace* null), !dbg !245
unreachable, !dbg !245
CoroNormalFinal: ; preds = %CoroBegin
br label %CheckFree, !dbg !245
FinalCleanup: ; preds = %CoroEarlyFinal
%31 = load i16*, i16** %25, align 8, !dbg !245
%32 = bitcast i16* %31 to i8*, !dbg !245
%33 = bitcast i16* %24 to i8*, !dbg !245
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %32, i8* %33, i64 2, i32 2, i1
false), !dbg !245
br label %CheckFree, !dbg !245
CheckFree: ; preds = %FinalCleanup,
%CoroNormalFinal
%34 = phi i1 [ false, %FinalCleanup ], [ true, %CoroNormalFinal ], !dbg
!245
br i1 %8, label %DynFree, label %EndFree, !dbg !245
DynFree: ; preds = %CheckFree
%35 = getelementptr inbounds %Allocator, %Allocator* %1, i32 0, i32 2,
!dbg !245
%36 = load void (%Allocator*, %"[]u8"*)*, void (%Allocator*, %"[]u8"*)**
%35, align 8, !dbg !245
call fastcc void %36(%Allocator* %1, %"[]u8"* byval %21), !dbg !245
br label %EndFree, !dbg !245
EndFree: ; preds = %DynFree,
%CheckFree
br i1 %34, label %Resume, label %Return, !dbg !245
Resume: ; preds = %EndFree
%37 = load i8*, i8** %23, align 8, !dbg !245
%38 = load i8*, i8** %23, align 8, !dbg !245
call void @llvm.coro.resume(i8* %38), !dbg !245
br label %Return, !dbg !245
Return: ; preds = %Resume,
%EndFree
ret i8* undef, !dbg !245
}
This triggers:
"cannot move instruction since its users are not dominated by CoroBegin"
When I use gdb to print I->dump():
%8 = getelementptr inbounds %Allocator, %Allocator* %1, i32 0, i32 0,
!dbg !71
Much to my surprise, this is pointing to an instruction in the `entry`
function, not the `amain` coroutine function. Is this a bug?
Thanks for the help,
Andrew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180226/4fde8c27/attachment.html>
More information about the llvm-dev
mailing list