Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / Coroutines / coro-alloca-loop-carried-address.ll
blob412327a49dcf2b52c6ddb2389d81cda1ac60a74b
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
4 @escape_hatch0 = external global i64
5 @escape_hatch1 = external global i64
7 define void @foo() presplitcoroutine {
8 ; CHECK-LABEL: @foo(
9 ; CHECK-NEXT:  entry:
10 ; CHECK-NEXT:    [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @foo.resumers)
11 ; CHECK-NEXT:    [[ALLOC:%.*]] = call ptr @malloc(i64 40)
12 ; CHECK-NEXT:    [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
13 ; CHECK-NEXT:    store ptr @foo.resume, ptr [[VFRAME]], align 8
14 ; CHECK-NEXT:    [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
15 ; CHECK-NEXT:    store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
16 ; CHECK-NEXT:    [[STACKVAR0_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 2
17 ; CHECK-NEXT:    [[STACKVAR1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 3
18 ; CHECK-NEXT:    [[STACKVAR0_INT:%.*]] = ptrtoint ptr [[STACKVAR0_RELOAD_ADDR]] to i64
19 ; CHECK-NEXT:    store i64 [[STACKVAR0_INT]], ptr @escape_hatch0, align 4
20 ; CHECK-NEXT:    [[STACKVAR1_INT:%.*]] = ptrtoint ptr [[STACKVAR1_RELOAD_ADDR]] to i64
21 ; CHECK-NEXT:    store i64 [[STACKVAR1_INT]], ptr @escape_hatch1, align 4
22 ; CHECK-NEXT:    br label [[LOOP:%.*]]
23 ; CHECK:       loop:
24 ; CHECK-NEXT:    store i64 1234, ptr [[STACKVAR0_RELOAD_ADDR]], align 4
25 ; CHECK-NEXT:    call void @bar()
26 ; CHECK-NEXT:    [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 4
27 ; CHECK-NEXT:    store i1 false, ptr [[INDEX_ADDR1]], align 1
28 ; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[AFTERCOROEND:%.*]]
29 ; CHECK:       AfterCoroEnd:
30 ; CHECK-NEXT:    ret void
32 entry:
33   %stackvar0 = alloca i64
34   %stackvar1 = alloca i64
36   ; address of %stackvar escapes and may be relied upon even after
37   ; suspending/resuming the coroutine regardless of the lifetime markers.
38   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
39   %size = call i64 @llvm.coro.size.i64()
40   %alloc = call ptr @malloc(i64 %size)
41   %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
43   ; %stackvar0 must be rewritten to reference the coroutine Frame!
44   %stackvar0_int = ptrtoint ptr %stackvar0 to i64
45   store i64 %stackvar0_int, ptr @escape_hatch0
46   ; %stackvar1 must be rewritten to reference the coroutine Frame!
47   %stackvar1_int = ptrtoint ptr %stackvar1 to i64
48   store i64 %stackvar1_int, ptr @escape_hatch1
50   br label %loop
52 loop:
53   call void @llvm.lifetime.start(i64 8, ptr %stackvar0)
55   store i64 1234, ptr %stackvar0
57   ; Call could potentially change value in memory referenced by %stackvar0 /
58   ; %stackvar1 and rely on it staying the same across suspension.
59   call void @bar()
61   call void @llvm.lifetime.end(i64 8, ptr %stackvar0)
63   %save = call token @llvm.coro.save(ptr null)
64   %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
65   switch i8 %suspend, label %exit [
66   i8 0, label %loop
67   i8 1, label %exit
68   ]
70 exit:
71   call i1 @llvm.coro.end(ptr null, i1 false, token none)
72   ret void
75 declare void @bar()
76 declare ptr @malloc(i64)
78 declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
79 declare i64 @llvm.coro.size.i64()
80 declare ptr @llvm.coro.begin(token, ptr writeonly)
81 declare token @llvm.coro.save(ptr)
82 declare i8 @llvm.coro.suspend(token, i1)
83 declare i1 @llvm.coro.end(ptr, i1, token)
84 declare void @llvm.lifetime.start(i64, ptr nocapture)
85 declare void @llvm.lifetime.end(i64, ptr nocapture)