-
Notifications
You must be signed in to change notification settings - Fork 14.5k
Open
Labels
Description
Compile following code
; opt -passes=licm t19.ll -S
define ptr @f(i32 %n) presplitcoroutine {
entry:
%pointer1 = alloca ptr
%pointer2 = alloca ptr
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call ptr @malloc(i32 %size)
%hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
br label %loop
loop:
%n.val = phi i32 [ %n, %entry ], [ %inc, %resume ]
%inc = add nsw i32 %n.val, 1
call void @print(i32 %n.val)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
i8 1, label %cleanup]
resume:
%fca.0 = insertvalue [2 x ptr] poison, ptr %pointer1, 0 // These 2 instructions
%fca.1 = insertvalue [2 x ptr] %fca.0, ptr %pointer2, 1 // should not be hoisted
call void @foo([2 x ptr] %fca.1)
br label %loop
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
}
declare void @free(ptr)
declare ptr @malloc(i32)
declare void @print(i32)
declare void @foo([2 x ptr])
I got
entry:
%pointer1 = alloca ptr, align 8
%pointer2 = alloca ptr, align 8
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call ptr @malloc(i32 %size)
%hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
%fca.0 = insertvalue [2 x ptr] poison, ptr %pointer1, 0 // %pointer1 and %pointer2 points to
%fca.1 = insertvalue [2 x ptr] %fca.0, ptr %pointer2, 1 // stack objects in ramp function
br label %loop
loop: ; preds = %resume, %entry
%n.val = phi i32 [ %n, %entry ], [ %inc, %resume ]
%inc = add nsw i32 %n.val, 1
call void @print(i32 %n.val)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend.loopexit [
i8 0, label %resume
i8 1, label %cleanup
]
resume: ; preds = %loop
call void @foo([2 x ptr] %fca.1) // This instruction is in the resume function, it can't access ramp function stack objects
br label %loop
cleanup: ; preds = %loop
...
In the original code, two pointers are passed to function foo, so they can be accessed by foo, all of the related instructions (construction of %fca.1 and function call) will be placed in resume function of a coroutine, so there is no problem.
After LICM, the construction of %fca.1 is hoisted out of the loop, and later these instructions will be placed into ramp function. The pointers contained in %fca.1 points to stack objects of ramp function. Later %fca.1 is passed to resume function through coroutine frame, and used by function foo, unfortunately the ramp function frame does not exist at this time, so the pointers passed to foo are invalid.