xref: /llvm-project/llvm/test/Transforms/ExpandVariadics/expand-va-intrinsic-split-simple.ll (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
18516f54eSJon Chesterfield; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature
28516f54eSJon Chesterfield; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=optimize < %s | FileCheck %s --check-prefixes=OPT
38516f54eSJon Chesterfield; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s --check-prefixes=ABI
48516f54eSJon Chesterfield; REQUIRES: webassembly-registered-target
58516f54eSJon Chesterfield
68516f54eSJon Chesterfield; Examples are variadic functions that return the first or the second of an int and a double
78516f54eSJon Chesterfield; Split the functions into an internal equivalent that takes a va_list and a ABI preserving wrapper
88516f54eSJon Chesterfield
98516f54eSJon Chesterfielddefine i32 @variadic_int_double_get_firstz(...) {
108516f54eSJon Chesterfield; OPT-LABEL: define {{[^@]+}}@variadic_int_double_get_firstz(...) {
118516f54eSJon Chesterfield; OPT-NEXT:  entry:
128516f54eSJon Chesterfield; OPT-NEXT:    %va_start = alloca ptr, align 4
138516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
148516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
158516f54eSJon Chesterfield; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
168516f54eSJon Chesterfield; OPT-NEXT:    %1 = call i32 @variadic_int_double_get_firstz.valist(ptr %0)
178516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
188516f54eSJon Chesterfield; OPT-NEXT:    ret i32 %1
198516f54eSJon Chesterfield;
208516f54eSJon Chesterfield; ABI-LABEL: define {{[^@]+}}@variadic_int_double_get_firstz(ptr %varargs) {
218516f54eSJon Chesterfield; ABI-NEXT:  entry:
228516f54eSJon Chesterfield; ABI-NEXT:    %va = alloca ptr, align 4
238516f54eSJon Chesterfield; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
248516f54eSJon Chesterfield; ABI-NEXT:    %argp.cur = load ptr, ptr %va, align 4
258516f54eSJon Chesterfield; ABI-NEXT:    %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
268516f54eSJon Chesterfield; ABI-NEXT:    store ptr %argp.next, ptr %va, align 4
278516f54eSJon Chesterfield; ABI-NEXT:    %0 = load i32, ptr %argp.cur, align 4
288516f54eSJon Chesterfield; ABI-NEXT:    ret i32 %0
298516f54eSJon Chesterfield;
308516f54eSJon Chesterfieldentry:
318516f54eSJon Chesterfield  %va = alloca ptr, align 4
328516f54eSJon Chesterfield  call void @llvm.va_start.p0(ptr nonnull %va)
338516f54eSJon Chesterfield  %argp.cur = load ptr, ptr %va, align 4
348516f54eSJon Chesterfield  %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
358516f54eSJon Chesterfield  store ptr %argp.next, ptr %va, align 4
368516f54eSJon Chesterfield  %0 = load i32, ptr %argp.cur, align 4
378516f54eSJon Chesterfield  call void @llvm.va_end.p0(ptr %va)
388516f54eSJon Chesterfield  ret i32 %0
398516f54eSJon Chesterfield}
408516f54eSJon Chesterfield
418516f54eSJon Chesterfield; CHECK-LABEL: define i32 @variadic_int_double_get_firstz(...) {
428516f54eSJon Chesterfield; CHECK-NEXT:  entry:
438516f54eSJon Chesterfield; CHECK-NEXT:    %va_list = alloca ptr, align 4
448516f54eSJon Chesterfield; CHECK-NEXT:    call void @llvm.va_start.p0(ptr %va_list)
458516f54eSJon Chesterfield; CHECK-NEXT:    %0 = tail call i32 @variadic_int_double_get_firstz.valist(ptr %va_list)
468516f54eSJon Chesterfield; CHECK-NEXT:    ret i32 %0
478516f54eSJon Chesterfield; CHECK-NEXT:  }
488516f54eSJon Chesterfield
498516f54eSJon Chesterfield; CHECK-LABEL: define internal i32 @variadic_int_double_get_firstz.valist(ptr noalias %varargs) {
508516f54eSJon Chesterfield; CHECK-NEXT:  entry:
518516f54eSJon Chesterfield; CHECK-NEXT:   %va = alloca ptr, align 4
528516f54eSJon Chesterfield; CHECK-NEXT:   store ptr %varargs, ptr %va, align 4
538516f54eSJon Chesterfield; CHECK-NEXT:   %argp.cur = load ptr, ptr %va, align 4
548516f54eSJon Chesterfield; CHECK-NEXT:   %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
558516f54eSJon Chesterfield; CHECK-NEXT:   store ptr %argp.next, ptr %va, align 4
568516f54eSJon Chesterfield; CHECK-NEXT:   %0 = load i32, ptr %argp.cur, align 4
578516f54eSJon Chesterfield; CHECK-NEXT:   ret i32 %0
588516f54eSJon Chesterfield; CHECK-NEXT:  }
598516f54eSJon Chesterfield
608516f54eSJon Chesterfielddefine double @variadic_int_double_get_secondz(...) {
618516f54eSJon Chesterfield; OPT-LABEL: define {{[^@]+}}@variadic_int_double_get_secondz(...) {
628516f54eSJon Chesterfield; OPT-NEXT:  entry:
638516f54eSJon Chesterfield; OPT-NEXT:    %va_start = alloca ptr, align 4
648516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
658516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
668516f54eSJon Chesterfield; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
678516f54eSJon Chesterfield; OPT-NEXT:    %1 = call double @variadic_int_double_get_secondz.valist(ptr %0)
688516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
698516f54eSJon Chesterfield; OPT-NEXT:    ret double %1
708516f54eSJon Chesterfield;
718516f54eSJon Chesterfield; ABI-LABEL: define {{[^@]+}}@variadic_int_double_get_secondz(ptr %varargs) {
728516f54eSJon Chesterfield; ABI-NEXT:  entry:
738516f54eSJon Chesterfield; ABI-NEXT:    %va = alloca ptr, align 4
748516f54eSJon Chesterfield; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
758516f54eSJon Chesterfield; ABI-NEXT:    %argp.cur = load ptr, ptr %va, align 4
768516f54eSJon Chesterfield; ABI-NEXT:    %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
778516f54eSJon Chesterfield; ABI-NEXT:    %argp.next2 = getelementptr inbounds i8, ptr %argp.cur, i32 12
788516f54eSJon Chesterfield; ABI-NEXT:    store ptr %argp.next2, ptr %va, align 4
798516f54eSJon Chesterfield; ABI-NEXT:    %0 = load double, ptr %argp.next, align 4
808516f54eSJon Chesterfield; ABI-NEXT:    ret double %0
818516f54eSJon Chesterfield;
828516f54eSJon Chesterfieldentry:
838516f54eSJon Chesterfield  %va = alloca ptr, align 4
848516f54eSJon Chesterfield  call void @llvm.va_start.p0(ptr nonnull %va)
858516f54eSJon Chesterfield  %argp.cur = load ptr, ptr %va, align 4
868516f54eSJon Chesterfield  %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
878516f54eSJon Chesterfield  %argp.next2 = getelementptr inbounds i8, ptr %argp.cur, i32 12
888516f54eSJon Chesterfield  store ptr %argp.next2, ptr %va, align 4
898516f54eSJon Chesterfield  %0 = load double, ptr %argp.next, align 4
908516f54eSJon Chesterfield  call void @llvm.va_end.p0(ptr %va)
918516f54eSJon Chesterfield  ret double %0
928516f54eSJon Chesterfield}
938516f54eSJon Chesterfield
948516f54eSJon Chesterfield; CHECK-LABEL: define double @variadic_int_double_get_secondz(...) {
958516f54eSJon Chesterfield; CHECK-NEXT:  entry:
968516f54eSJon Chesterfield; CHECK-NEXT:    %va_list = alloca ptr, align 4
978516f54eSJon Chesterfield; CHECK-NEXT:    call void @llvm.va_start.p0(ptr %va_list)
988516f54eSJon Chesterfield; CHECK-NEXT:    %0 = tail call double @variadic_int_double_get_secondz.valist(ptr %va_list)
998516f54eSJon Chesterfield; CHECK-NEXT:    ret double %0
1008516f54eSJon Chesterfield; CHECK-NEXT:  }
1018516f54eSJon Chesterfield
1028516f54eSJon Chesterfield; CHECK-LABEL: define internal double @variadic_int_double_get_secondz.valist(ptr noalias %varargs) {
1038516f54eSJon Chesterfield; CHECK-NEXT:  entry:
1048516f54eSJon Chesterfield; CHECK-NEXT:    %va = alloca ptr, align 4
1058516f54eSJon Chesterfield; CHECK-NEXT:    store ptr %varargs, ptr %va, align 4
1068516f54eSJon Chesterfield; CHECK-NEXT:    %argp.cur = load ptr, ptr %va, align 4
1078516f54eSJon Chesterfield; CHECK-NEXT:    %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 4
1088516f54eSJon Chesterfield; CHECK-NEXT:    %argp.next2 = getelementptr inbounds i8, ptr %argp.cur, i32 12
1098516f54eSJon Chesterfield; CHECK-NEXT:    store ptr %argp.next2, ptr %va, align 4
1108516f54eSJon Chesterfield; CHECK-NEXT:    %0 = load double, ptr %argp.next, align 4
1118516f54eSJon Chesterfield; CHECK-NEXT:    ret double %0
1128516f54eSJon Chesterfield; CHECK-NEXT:  }
1138516f54eSJon Chesterfield
1148516f54eSJon Chesterfield
1158516f54eSJon Chesterfield; CHECK-LABEL: @variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
1168516f54eSJon Chesterfield; CHECK-NEXT:  entry:
1178516f54eSJon Chesterfield; CHECK-NEXT:    %vararg_buffer = alloca %variadic_can_get_firstIidEEbT_T0_.vararg, align 16
1188516f54eSJon Chesterfield; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr %vararg_buffer)
1198516f54eSJon Chesterfield; CHECK-NEXT:    %0 = getelementptr inbounds %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
1208516f54eSJon Chesterfield; CHECK-NEXT:    store i32 %x, ptr %0, align 4
1218516f54eSJon Chesterfield; CHECK-NEXT:    %1 = getelementptr inbounds %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 1
1228516f54eSJon Chesterfield; CHECK-NEXT:    store double %y, ptr %1, align 4
1238516f54eSJon Chesterfield; CHECK-NEXT:    %call = call i32 @variadic_int_double_get_firstz.valist(ptr %vararg_buffer)
1248516f54eSJon Chesterfield; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr %vararg_buffer)
1258516f54eSJon Chesterfield; CHECK-NEXT:    %cmp.i = icmp eq i32 %call, %x
1268516f54eSJon Chesterfield; CHECK-NEXT:    ret i1 %cmp.i
1278516f54eSJon Chesterfield; CHECK-NEXT:  }
1288516f54eSJon Chesterfield
1298516f54eSJon Chesterfielddefine zeroext i1 @variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
1308516f54eSJon Chesterfield; OPT-LABEL: define {{[^@]+}}@variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
1318516f54eSJon Chesterfield; OPT-NEXT:  entry:
1328516f54eSJon Chesterfield; OPT-NEXT:    %vararg_buffer = alloca %variadic_can_get_firstIidEEbT_T0_.vararg, align 16
1338516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
134*94473f4dSHari Limaye; OPT-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
1358516f54eSJon Chesterfield; OPT-NEXT:    store i32 %x, ptr %0, align 4
136*94473f4dSHari Limaye; OPT-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
1378516f54eSJon Chesterfield; OPT-NEXT:    store double %y, ptr %1, align 8
1388516f54eSJon Chesterfield; OPT-NEXT:    %call = call i32 @variadic_int_double_get_firstz.valist(ptr %vararg_buffer)
1398516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
1408516f54eSJon Chesterfield; OPT-NEXT:    %cmp.i = icmp eq i32 %call, %x
1418516f54eSJon Chesterfield; OPT-NEXT:    ret i1 %cmp.i
1428516f54eSJon Chesterfield;
1438516f54eSJon Chesterfield; ABI-LABEL: define {{[^@]+}}@variadic_can_get_firstIidEEbT_T0_(i32 %x, double %y) {
1448516f54eSJon Chesterfield; ABI-NEXT:  entry:
1458516f54eSJon Chesterfield; ABI-NEXT:    %vararg_buffer = alloca %variadic_can_get_firstIidEEbT_T0_.vararg, align 16
1468516f54eSJon Chesterfield; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
147*94473f4dSHari Limaye; ABI-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
1488516f54eSJon Chesterfield; ABI-NEXT:    store i32 %x, ptr %0, align 4
149*94473f4dSHari Limaye; ABI-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_firstIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
1508516f54eSJon Chesterfield; ABI-NEXT:    store double %y, ptr %1, align 8
1518516f54eSJon Chesterfield; ABI-NEXT:    %call = call i32 @variadic_int_double_get_firstz(ptr %vararg_buffer)
1528516f54eSJon Chesterfield; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
1538516f54eSJon Chesterfield; ABI-NEXT:    %cmp.i = icmp eq i32 %call, %x
1548516f54eSJon Chesterfield; ABI-NEXT:    ret i1 %cmp.i
1558516f54eSJon Chesterfield;
1568516f54eSJon Chesterfieldentry:
1578516f54eSJon Chesterfield  %call = call i32 (...) @variadic_int_double_get_firstz(i32 %x, double %y)
1588516f54eSJon Chesterfield  %cmp.i = icmp eq i32 %call, %x
1598516f54eSJon Chesterfield  ret i1 %cmp.i
1608516f54eSJon Chesterfield}
1618516f54eSJon Chesterfield
1628516f54eSJon Chesterfield; CHECK-LABEL: @variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
1638516f54eSJon Chesterfield; CHECK-NEXT:  entry:
1648516f54eSJon Chesterfield; CHECK-NEXT:    %vararg_buffer = alloca %variadic_can_get_secondIidEEbT_T0_.vararg, align 16
1658516f54eSJon Chesterfield; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr %vararg_buffer)
1668516f54eSJon Chesterfield; CHECK-NEXT:    %0 = getelementptr inbounds %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
1678516f54eSJon Chesterfield; CHECK-NEXT:    store i32 %x, ptr %0, align 4
1688516f54eSJon Chesterfield; CHECK-NEXT:    %1 = getelementptr inbounds %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 1
1698516f54eSJon Chesterfield; CHECK-NEXT:    store double %y, ptr %1, align 4
1708516f54eSJon Chesterfield; CHECK-NEXT:    %call = call double @variadic_int_double_get_secondz.valist(ptr %vararg_buffer)
1718516f54eSJon Chesterfield; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr %vararg_buffer)
1728516f54eSJon Chesterfield; CHECK-NEXT:    %cmp.i = fcmp oeq double %call, %y
1738516f54eSJon Chesterfield; CHECK-NEXT:    ret i1 %cmp.i
1748516f54eSJon Chesterfield; CHECK-NEXT:  }
1758516f54eSJon Chesterfield
1768516f54eSJon Chesterfielddefine zeroext i1 @variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
1778516f54eSJon Chesterfield; OPT-LABEL: define {{[^@]+}}@variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
1788516f54eSJon Chesterfield; OPT-NEXT:  entry:
1798516f54eSJon Chesterfield; OPT-NEXT:    %vararg_buffer = alloca %variadic_can_get_secondIidEEbT_T0_.vararg, align 16
1808516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
181*94473f4dSHari Limaye; OPT-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
1828516f54eSJon Chesterfield; OPT-NEXT:    store i32 %x, ptr %0, align 4
183*94473f4dSHari Limaye; OPT-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
1848516f54eSJon Chesterfield; OPT-NEXT:    store double %y, ptr %1, align 8
1858516f54eSJon Chesterfield; OPT-NEXT:    %call = call double @variadic_int_double_get_secondz.valist(ptr %vararg_buffer)
1868516f54eSJon Chesterfield; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
1878516f54eSJon Chesterfield; OPT-NEXT:    %cmp.i = fcmp oeq double %call, %y
1888516f54eSJon Chesterfield; OPT-NEXT:    ret i1 %cmp.i
1898516f54eSJon Chesterfield;
1908516f54eSJon Chesterfield; ABI-LABEL: define {{[^@]+}}@variadic_can_get_secondIidEEbT_T0_(i32 %x, double %y) {
1918516f54eSJon Chesterfield; ABI-NEXT:  entry:
1928516f54eSJon Chesterfield; ABI-NEXT:    %vararg_buffer = alloca %variadic_can_get_secondIidEEbT_T0_.vararg, align 16
1938516f54eSJon Chesterfield; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
194*94473f4dSHari Limaye; ABI-NEXT:    %0 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 0
1958516f54eSJon Chesterfield; ABI-NEXT:    store i32 %x, ptr %0, align 4
196*94473f4dSHari Limaye; ABI-NEXT:    %1 = getelementptr inbounds nuw %variadic_can_get_secondIidEEbT_T0_.vararg, ptr %vararg_buffer, i32 0, i32 2
1978516f54eSJon Chesterfield; ABI-NEXT:    store double %y, ptr %1, align 8
1988516f54eSJon Chesterfield; ABI-NEXT:    %call = call double @variadic_int_double_get_secondz(ptr %vararg_buffer)
1998516f54eSJon Chesterfield; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
2008516f54eSJon Chesterfield; ABI-NEXT:    %cmp.i = fcmp oeq double %call, %y
2018516f54eSJon Chesterfield; ABI-NEXT:    ret i1 %cmp.i
2028516f54eSJon Chesterfield;
2038516f54eSJon Chesterfieldentry:
2048516f54eSJon Chesterfield  %call = call double (...) @variadic_int_double_get_secondz(i32 %x, double %y)
2058516f54eSJon Chesterfield  %cmp.i = fcmp oeq double %call, %y
2068516f54eSJon Chesterfield  ret i1 %cmp.i
2078516f54eSJon Chesterfield}
2088516f54eSJon Chesterfield
2098516f54eSJon Chesterfield; Declaration unchanged
2108516f54eSJon Chesterfield; CHECK: declare void @variadic_without_callers(...)
2118516f54eSJon Chesterfielddeclare void @variadic_without_callers(...)
2128516f54eSJon Chesterfield
2138516f54eSJon Chesterfielddeclare void @llvm.va_start.p0(ptr)
2148516f54eSJon Chesterfielddeclare void @llvm.va_end.p0(ptr)
215