[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / ExpandVariadics / expand-va-intrinsic-split-simple.ll
blob96cc826aef4ec26452b1efc4bab2c792992fd162
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature
2 ; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=optimize < %s | FileCheck %s --check-prefixes=OPT
3 ; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s --check-prefixes=ABI
4 ; REQUIRES: webassembly-registered-target
6 ; Examples are variadic functions that return the first or the second of an int and a double
7 ; Split the functions into an internal equivalent that takes a va_list and a ABI preserving wrapper
9 define i32 @variadic_int_double_get_firstz(...) {
10 ; OPT-LABEL: define {{[^@]+}}@variadic_int_double_get_firstz(...) {
11 ; OPT-NEXT:  entry:
12 ; OPT-NEXT:    %va_start = alloca ptr, align 4
13 ; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
14 ; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
15 ; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
16 ; OPT-NEXT:    %1 = call i32 @variadic_int_double_get_firstz.valist(ptr %0)
17 ; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
18 ; OPT-NEXT:    ret i32 %1
20 ; ABI-LABEL: define {{[^@]+}}@variadic_int_double_get_firstz(ptr %varargs) {
21 ; ABI-NEXT:  entry:
22 ; ABI-NEXT:    %va = alloca ptr, align 4
23 ; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
24 ; ABI-NEXT:    %argp.cur = load ptr, ptr %va, align 4
25 ; ABI-NEXT:    %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
26 ; ABI-NEXT:    store ptr %argp.next, ptr %va, align 4
27 ; ABI-NEXT:    %0 = load i32, ptr %argp.cur, align 4
28 ; ABI-NEXT:    ret i32 %0
30 entry:
31   %va = alloca ptr, align 4
32   call void @llvm.va_start.p0(ptr nonnull %va)
33   %argp.cur = load ptr, ptr %va, align 4
34   %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
35   store ptr %argp.next, ptr %va, align 4
36   %0 = load i32, ptr %argp.cur, align 4
37   call void @llvm.va_end.p0(ptr %va)
38   ret i32 %0
41 ; CHECK-LABEL: define i32 @variadic_int_double_get_firstz(...) {
42 ; CHECK-NEXT:  entry:
43 ; CHECK-NEXT:    %va_list = alloca ptr, align 4
44 ; CHECK-NEXT:    call void @llvm.va_start.p0(ptr %va_list)
45 ; CHECK-NEXT:    %0 = tail call i32 @variadic_int_double_get_firstz.valist(ptr %va_list)
46 ; CHECK-NEXT:    ret i32 %0
47 ; CHECK-NEXT:  }
49 ; CHECK-LABEL: define internal i32 @variadic_int_double_get_firstz.valist(ptr noalias %varargs) {
50 ; CHECK-NEXT:  entry:
51 ; CHECK-NEXT:   %va = alloca ptr, align 4
52 ; CHECK-NEXT:   store ptr %varargs, ptr %va, align 4
53 ; CHECK-NEXT:   %argp.cur = load ptr, ptr %va, align 4
54 ; CHECK-NEXT:   %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
55 ; CHECK-NEXT:   store ptr %argp.next, ptr %va, align 4
56 ; CHECK-NEXT:   %0 = load i32, ptr %argp.cur, align 4
57 ; CHECK-NEXT:   ret i32 %0
58 ; CHECK-NEXT:  }
60 define double @variadic_int_double_get_secondz(...) {
61 ; OPT-LABEL: define {{[^@]+}}@variadic_int_double_get_secondz(...) {
62 ; OPT-NEXT:  entry:
63 ; OPT-NEXT:    %va_start = alloca ptr, align 4
64 ; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
65 ; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
66 ; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
67 ; OPT-NEXT:    %1 = call double @variadic_int_double_get_secondz.valist(ptr %0)
68 ; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
69 ; OPT-NEXT:    ret double %1
71 ; ABI-LABEL: define {{[^@]+}}@variadic_int_double_get_secondz(ptr %varargs) {
72 ; ABI-NEXT:  entry:
73 ; ABI-NEXT:    %va = alloca ptr, align 4
74 ; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
75 ; ABI-NEXT:    %argp.cur = load ptr, ptr %va, align 4
76 ; ABI-NEXT:    %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
77 ; ABI-NEXT:    %argp.next2 = getelementptr inbounds i8, ptr %argp.cur, i32 12
78 ; ABI-NEXT:    store ptr %argp.next2, ptr %va, align 4
79 ; ABI-NEXT:    %0 = load double, ptr %argp.next, align 4
80 ; ABI-NEXT:    ret double %0
82 entry:
83   %va = alloca ptr, align 4
84   call void @llvm.va_start.p0(ptr nonnull %va)
85   %argp.cur = load ptr, ptr %va, align 4
86   %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
87   %argp.next2 = getelementptr inbounds i8, ptr %argp.cur, i32 12
88   store ptr %argp.next2, ptr %va, align 4
89   %0 = load double, ptr %argp.next, align 4
90   call void @llvm.va_end.p0(ptr %va)
91   ret double %0
94 ; CHECK-LABEL: define double @variadic_int_double_get_secondz(...) {
95 ; CHECK-NEXT:  entry:
96 ; CHECK-NEXT:    %va_list = alloca ptr, align 4
97 ; CHECK-NEXT:    call void @llvm.va_start.p0(ptr %va_list)
98 ; CHECK-NEXT:    %0 = tail call double @variadic_int_double_get_secondz.valist(ptr %va_list)
99 ; CHECK-NEXT:    ret double %0
100 ; CHECK-NEXT:  }
102 ; CHECK-LABEL: define internal double @variadic_int_double_get_secondz.valist(ptr noalias %varargs) {
103 ; CHECK-NEXT:  entry:
104 ; CHECK-NEXT:    %va = alloca ptr, align 4
105 ; CHECK-NEXT:    store ptr %varargs, ptr %va, align 4
106 ; CHECK-NEXT:    %argp.cur = load ptr, ptr %va, align 4
107 ; CHECK-NEXT:    %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
108 ; CHECK-NEXT:    %argp.next2 = getelementptr inbounds i8, ptr %argp.cur, i32 12
109 ; CHECK-NEXT:    store ptr %argp.next2, ptr %va, align 4
110 ; CHECK-NEXT:    %0 = load double, ptr %argp.next, align 4
111 ; CHECK-NEXT:    ret double %0
112 ; CHECK-NEXT:  }
115 ; CHECK-LABEL: @variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
116 ; CHECK-NEXT:  entry:
117 ; CHECK-NEXT:    %vararg_buffer = alloca %variadic_can_get_firstIidEEbT_T0_.vararg, align 16
118 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr %vararg_buffer)
119 ; CHECK-NEXT:    %0 = getelementptr inbounds %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
120 ; CHECK-NEXT:    store i32 %x, ptr %0, align 4
121 ; CHECK-NEXT:    %1 = getelementptr inbounds %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 1
122 ; CHECK-NEXT:    store double %y, ptr %1, align 4
123 ; CHECK-NEXT:    %call = call i32 @variadic_int_double_get_firstz.valist(ptr %vararg_buffer)
124 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr %vararg_buffer)
125 ; CHECK-NEXT:    %cmp.i = icmp eq i32 %call, %x
126 ; CHECK-NEXT:    ret i1 %cmp.i
127 ; CHECK-NEXT:  }
129 define zeroext i1 @variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
130 ; OPT-LABEL: define {{[^@]+}}@variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
131 ; OPT-NEXT:  entry:
132 ; OPT-NEXT:    %vararg_buffer = alloca %variadic_can_get_firstIidEEbT_T0_.vararg, align 16
133 ; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
134 ; OPT-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
135 ; OPT-NEXT:    store i32 %x, ptr %0, align 4
136 ; OPT-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
137 ; OPT-NEXT:    store double %y, ptr %1, align 8
138 ; OPT-NEXT:    %call = call i32 @variadic_int_double_get_firstz.valist(ptr %vararg_buffer)
139 ; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
140 ; OPT-NEXT:    %cmp.i = icmp eq i32 %call, %x
141 ; OPT-NEXT:    ret i1 %cmp.i
143 ; ABI-LABEL: define {{[^@]+}}@variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
144 ; ABI-NEXT:  entry:
145 ; ABI-NEXT:    %vararg_buffer = alloca %variadic_can_get_firstIidEEbT_T0_.vararg, align 16
146 ; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
147 ; ABI-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
148 ; ABI-NEXT:    store i32 %x, ptr %0, align 4
149 ; ABI-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
150 ; ABI-NEXT:    store double %y, ptr %1, align 8
151 ; ABI-NEXT:    %call = call i32 @variadic_int_double_get_firstz(ptr %vararg_buffer)
152 ; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
153 ; ABI-NEXT:    %cmp.i = icmp eq i32 %call, %x
154 ; ABI-NEXT:    ret i1 %cmp.i
156 entry:
157   %call = call i32 (...) @variadic_int_double_get_firstz(i32 %x, double %y)
158   %cmp.i = icmp eq i32 %call, %x
159   ret i1 %cmp.i
162 ; CHECK-LABEL: @variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
163 ; CHECK-NEXT:  entry:
164 ; CHECK-NEXT:    %vararg_buffer = alloca %variadic_can_get_secondIidEEbT_T0_.vararg, align 16
165 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr %vararg_buffer)
166 ; CHECK-NEXT:    %0 = getelementptr inbounds %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
167 ; CHECK-NEXT:    store i32 %x, ptr %0, align 4
168 ; CHECK-NEXT:    %1 = getelementptr inbounds %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 1
169 ; CHECK-NEXT:    store double %y, ptr %1, align 4
170 ; CHECK-NEXT:    %call = call double @variadic_int_double_get_secondz.valist(ptr %vararg_buffer)
171 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr %vararg_buffer)
172 ; CHECK-NEXT:    %cmp.i = fcmp oeq double %call, %y
173 ; CHECK-NEXT:    ret i1 %cmp.i
174 ; CHECK-NEXT:  }
176 define zeroext i1 @variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
177 ; OPT-LABEL: define {{[^@]+}}@variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
178 ; OPT-NEXT:  entry:
179 ; OPT-NEXT:    %vararg_buffer = alloca %variadic_can_get_secondIidEEbT_T0_.vararg, align 16
180 ; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
181 ; OPT-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
182 ; OPT-NEXT:    store i32 %x, ptr %0, align 4
183 ; OPT-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
184 ; OPT-NEXT:    store double %y, ptr %1, align 8
185 ; OPT-NEXT:    %call = call double @variadic_int_double_get_secondz.valist(ptr %vararg_buffer)
186 ; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
187 ; OPT-NEXT:    %cmp.i = fcmp oeq double %call, %y
188 ; OPT-NEXT:    ret i1 %cmp.i
190 ; ABI-LABEL: define {{[^@]+}}@variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
191 ; ABI-NEXT:  entry:
192 ; ABI-NEXT:    %vararg_buffer = alloca %variadic_can_get_secondIidEEbT_T0_.vararg, align 16
193 ; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
194 ; ABI-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
195 ; ABI-NEXT:    store i32 %x, ptr %0, align 4
196 ; ABI-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
197 ; ABI-NEXT:    store double %y, ptr %1, align 8
198 ; ABI-NEXT:    %call = call double @variadic_int_double_get_secondz(ptr %vararg_buffer)
199 ; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
200 ; ABI-NEXT:    %cmp.i = fcmp oeq double %call, %y
201 ; ABI-NEXT:    ret i1 %cmp.i
203 entry:
204   %call = call double (...) @variadic_int_double_get_secondz(i32 %x, double %y)
205   %cmp.i = fcmp oeq double %call, %y
206   ret i1 %cmp.i
209 ; Declaration unchanged
210 ; CHECK: declare void @variadic_without_callers(...)
211 declare void @variadic_without_callers(...)
213 declare void @llvm.va_start.p0(ptr)
214 declare void @llvm.va_end.p0(ptr)