xref: /llvm-project/llvm/test/Transforms/GlobalOpt/preallocated.ll (revision 25bc999d1fb2efccc3ece398550af738aea7d310)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2; RUN: opt < %s -passes=globalopt -S | FileCheck %s
3
4declare token @llvm.call.preallocated.setup(i32)
5declare ptr @llvm.call.preallocated.arg(token, i32)
6declare i32 @__CxxFrameHandler3(...)
7
8; Don't touch functions with any musttail calls
9define internal i32 @preallocated_musttail(ptr preallocated(i32) %p) {
10; CHECK-LABEL: define {{[^@]+}}@preallocated_musttail
11; CHECK-SAME: (ptr preallocated(i32) [[P:%.*]]) unnamed_addr {
12; CHECK-NEXT:    [[RV:%.*]] = load i32, ptr [[P]], align 4
13; CHECK-NEXT:    ret i32 [[RV]]
14;
15  %rv = load i32, ptr %p
16  ret i32 %rv
17}
18
19define i32 @call_preallocated_musttail(ptr preallocated(i32) %a) {
20; CHECK-LABEL: define {{[^@]+}}@call_preallocated_musttail
21; CHECK-SAME: (ptr preallocated(i32) [[A:%.*]]) local_unnamed_addr {
22; CHECK-NEXT:    [[R:%.*]] = musttail call i32 @preallocated_musttail(ptr preallocated(i32) [[A]])
23; CHECK-NEXT:    ret i32 [[R]]
24;
25  %r = musttail call i32 @preallocated_musttail(ptr preallocated(i32) %a)
26  ret i32 %r
27}
28
29define i32 @call_preallocated_musttail_without_musttail() {
30; CHECK-LABEL: define {{[^@]+}}@call_preallocated_musttail_without_musttail() local_unnamed_addr {
31; CHECK-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1)
32; CHECK-NEXT:    [[N:%.*]] = call ptr @llvm.call.preallocated.arg(token [[C]], i32 0) #[[ATTR1:[0-9]+]]
33; CHECK-NEXT:    [[R:%.*]] = call i32 @preallocated_musttail(ptr preallocated(i32) [[N]]) [ "preallocated"(token [[C]]) ]
34; CHECK-NEXT:    ret i32 [[R]]
35;
36  %c = call token @llvm.call.preallocated.setup(i32 1)
37  %N = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32)
38  %r = call i32 @preallocated_musttail(ptr preallocated(i32) %N) ["preallocated"(token %c)]
39  ret i32 %r
40}
41
42; Check that only one alloca per preallocated arg
43define internal i32 @preallocated(ptr preallocated(i32) %a) {
44; CHECK-LABEL: define {{[^@]+}}@preallocated
45; CHECK-SAME: (ptr [[A:%.*]]) unnamed_addr {
46; CHECK-NEXT:    [[RV:%.*]] = load i32, ptr [[A]], align 4
47; CHECK-NEXT:    ret i32 [[RV]]
48;
49  %rv = load i32, ptr %a
50  ret i32 %rv
51}
52
53declare void @foo(ptr)
54
55define i32 @call_preallocated_multiple_args() {
56; CHECK-LABEL: define {{[^@]+}}@call_preallocated_multiple_args() local_unnamed_addr {
57; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.stacksave.p0()
58; CHECK-NEXT:    [[PAARG:%.*]] = alloca i32, align 4
59; CHECK-NEXT:    call void @foo(ptr [[PAARG]])
60; CHECK-NEXT:    call void @foo(ptr [[PAARG]])
61; CHECK-NEXT:    call void @foo(ptr [[PAARG]])
62; CHECK-NEXT:    [[R:%.*]] = call fastcc i32 @preallocated(ptr [[PAARG]])
63; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[TMP1]])
64; CHECK-NEXT:    ret i32 [[R]]
65;
66  %c = call token @llvm.call.preallocated.setup(i32 1)
67  %a1 = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32)
68  call void @foo(ptr %a1)
69  %a2 = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32)
70  call void @foo(ptr %a2)
71  %a3 = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32)
72  call void @foo(ptr %a3)
73  %r = call i32 @preallocated(ptr preallocated(i32) %a3) ["preallocated"(token %c)]
74  ret i32 %r
75}
76
77; Don't touch functions with any invokes
78define internal i32 @preallocated_invoke(ptr preallocated(i32) %p) {
79; CHECK-LABEL: define {{[^@]+}}@preallocated_invoke
80; CHECK-SAME: (ptr preallocated(i32) [[P:%.*]]) unnamed_addr {
81; CHECK-NEXT:    [[RV:%.*]] = load i32, ptr [[P]], align 4
82; CHECK-NEXT:    ret i32 [[RV]]
83;
84  %rv = load i32, ptr %p
85  ret i32 %rv
86}
87
88define i32 @call_preallocated_invoke() personality ptr @__CxxFrameHandler3 {
89; CHECK-LABEL: define {{[^@]+}}@call_preallocated_invoke() local_unnamed_addr personality ptr @__CxxFrameHandler3 {
90; CHECK-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1)
91; CHECK-NEXT:    [[A:%.*]] = call ptr @llvm.call.preallocated.arg(token [[C]], i32 0) #[[ATTR1]]
92; CHECK-NEXT:    [[R:%.*]] = invoke i32 @preallocated_invoke(ptr preallocated(i32) [[A]]) [ "preallocated"(token [[C]]) ]
93; CHECK-NEXT:    to label [[CONTA:%.*]] unwind label [[CONTB:%.*]]
94; CHECK:       conta:
95; CHECK-NEXT:    ret i32 [[R]]
96; CHECK:       contb:
97; CHECK-NEXT:    [[S:%.*]] = catchswitch within none [label %catch] unwind to caller
98; CHECK:       catch:
99; CHECK-NEXT:    [[P:%.*]] = catchpad within [[S]] []
100; CHECK-NEXT:    catchret from [[P]] to label [[CONT:%.*]]
101; CHECK:       cont:
102; CHECK-NEXT:    ret i32 42
103;
104  %c = call token @llvm.call.preallocated.setup(i32 1)
105  %a = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32)
106  %r = invoke i32 @preallocated_invoke(ptr preallocated(i32) %a) ["preallocated"(token %c)]
107  to label %conta unwind label %contb
108conta:
109  ret i32 %r
110contb:
111  %s = catchswitch within none [label %catch] unwind to caller
112catch:
113  %p = catchpad within %s []
114  catchret from %p to label %cont
115cont:
116  ret i32 42
117}
118