xref: /llvm-project/llvm/test/Transforms/ExpandVariadics/pass-byval-byref.ll (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
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
5
6; CHECK: @sink
7declare void @sink(...)
8
9
10define void @pass_byval(ptr byval(i32) %b) {
11; OPT-LABEL: @pass_byval(
12; OPT-NEXT:  entry:
13; OPT-NEXT:    tail call void (...) @sink(ptr byval(i32) [[B:%.*]])
14; OPT-NEXT:    ret void
15;
16; ABI-LABEL: @pass_byval(
17; ABI-NEXT:  entry:
18; ABI-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[PASS_BYVAL_VARARG:%.*]], align 16
19; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[VARARG_BUFFER]])
20; ABI-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[PASS_BYVAL_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
21; ABI-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[TMP0]], ptr [[B:%.*]], i64 4, i1 false)
22; ABI-NEXT:    call void @sink(ptr [[VARARG_BUFFER]])
23; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[VARARG_BUFFER]])
24; ABI-NEXT:    ret void
25;
26entry:
27  tail call void (...) @sink(ptr byval(i32) %b)
28  ret void
29}
30
31%struct.libcS = type { i8, i16, i32, i32, float, double }
32
33define void @i32_libcS_byval(i32 %x, ptr noundef byval(%struct.libcS) align 8 %y) {
34; OPT-LABEL: @i32_libcS_byval(
35; OPT-NEXT:  entry:
36; OPT-NEXT:    tail call void (...) @sink(i32 [[X:%.*]], ptr byval([[STRUCT_LIBCS:%.*]]) align 8 [[Y:%.*]])
37; OPT-NEXT:    ret void
38;
39; ABI-LABEL: @i32_libcS_byval(
40; ABI-NEXT:  entry:
41; ABI-NEXT:    [[INDIRECTALLOCA:%.*]] = alloca [[STRUCT_LIBCS:%.*]], align 8
42; ABI-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_LIBCS_BYVAL_VARARG:%.*]], align 16
43; ABI-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[INDIRECTALLOCA]], ptr [[Y:%.*]], i64 24, i1 false)
44; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[VARARG_BUFFER]])
45; ABI-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[I32_LIBCS_BYVAL_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
46; ABI-NEXT:    store i32 [[X:%.*]], ptr [[TMP0]], align 4
47; ABI-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw [[I32_LIBCS_BYVAL_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 1
48; ABI-NEXT:    store ptr [[INDIRECTALLOCA]], ptr [[TMP1]], align 4
49; ABI-NEXT:    call void @sink(ptr [[VARARG_BUFFER]])
50; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[VARARG_BUFFER]])
51; ABI-NEXT:    ret void
52;
53entry:
54  tail call void (...) @sink(i32 %x, ptr byval(%struct.libcS) align 8 %y)
55  ret void
56}
57
58define void @libcS_i32_byval(ptr byval(%struct.libcS) align 8 %x, i32 %y) {
59; OPT-LABEL: @libcS_i32_byval(
60; OPT-NEXT:  entry:
61; OPT-NEXT:    tail call void (...) @sink(ptr byval([[STRUCT_LIBCS:%.*]]) align 8 [[X:%.*]], i32 [[Y:%.*]])
62; OPT-NEXT:    ret void
63;
64; ABI-LABEL: @libcS_i32_byval(
65; ABI-NEXT:  entry:
66; ABI-NEXT:    [[INDIRECTALLOCA:%.*]] = alloca [[STRUCT_LIBCS:%.*]], align 8
67; ABI-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[LIBCS_I32_BYVAL_VARARG:%.*]], align 16
68; ABI-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[INDIRECTALLOCA]], ptr [[X:%.*]], i64 24, i1 false)
69; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[VARARG_BUFFER]])
70; ABI-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[LIBCS_I32_BYVAL_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
71; ABI-NEXT:    store ptr [[INDIRECTALLOCA]], ptr [[TMP0]], align 4
72; ABI-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw [[LIBCS_I32_BYVAL_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 1
73; ABI-NEXT:    store i32 [[Y:%.*]], ptr [[TMP1]], align 4
74; ABI-NEXT:    call void @sink(ptr [[VARARG_BUFFER]])
75; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[VARARG_BUFFER]])
76; ABI-NEXT:    ret void
77;
78entry:
79  tail call void (...) @sink(ptr byval(%struct.libcS) align 8 %x, i32 %y)
80  ret void
81}
82
83
84define void @pass_byref(ptr byref(i32) %b) {
85; OPT-LABEL: @pass_byref(
86; OPT-NEXT:  entry:
87; OPT-NEXT:    tail call void (...) @sink(ptr byref(i32) [[B:%.*]])
88; OPT-NEXT:    ret void
89;
90; ABI-LABEL: @pass_byref(
91; ABI-NEXT:  entry:
92; ABI-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[PASS_BYREF_VARARG:%.*]], align 16
93; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[VARARG_BUFFER]])
94; ABI-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[PASS_BYREF_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
95; ABI-NEXT:    store ptr [[B:%.*]], ptr [[TMP0]], align 4
96; ABI-NEXT:    call void @sink(ptr [[VARARG_BUFFER]])
97; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr [[VARARG_BUFFER]])
98; ABI-NEXT:    ret void
99;
100entry:
101  tail call void (...) @sink(ptr byref(i32) %b)
102  ret void
103}
104
105define void @i32_libcS_byref(i32 %x, ptr noundef byref(%struct.libcS) align 8 %y) {
106; OPT-LABEL: @i32_libcS_byref(
107; OPT-NEXT:  entry:
108; OPT-NEXT:    tail call void (...) @sink(i32 [[X:%.*]], ptr byref([[STRUCT_LIBCS:%.*]]) align 8 [[Y:%.*]])
109; OPT-NEXT:    ret void
110;
111; ABI-LABEL: @i32_libcS_byref(
112; ABI-NEXT:  entry:
113; ABI-NEXT:    [[INDIRECTALLOCA:%.*]] = alloca [[STRUCT_LIBCS:%.*]], align 8
114; ABI-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_LIBCS_BYREF_VARARG:%.*]], align 16
115; ABI-NEXT:    store ptr [[Y:%.*]], ptr [[INDIRECTALLOCA]], align 4
116; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[VARARG_BUFFER]])
117; ABI-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[I32_LIBCS_BYREF_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
118; ABI-NEXT:    store i32 [[X:%.*]], ptr [[TMP0]], align 4
119; ABI-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw [[I32_LIBCS_BYREF_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 1
120; ABI-NEXT:    store ptr [[INDIRECTALLOCA]], ptr [[TMP1]], align 4
121; ABI-NEXT:    call void @sink(ptr [[VARARG_BUFFER]])
122; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[VARARG_BUFFER]])
123; ABI-NEXT:    ret void
124;
125entry:
126  tail call void (...) @sink(i32 %x, ptr byref(%struct.libcS) align 8 %y)
127  ret void
128}
129
130define void @libcS_i32_byref(ptr byref(%struct.libcS) align 8 %x, i32 %y) {
131; OPT-LABEL: @libcS_i32_byref(
132; OPT-NEXT:  entry:
133; OPT-NEXT:    tail call void (...) @sink(ptr byref([[STRUCT_LIBCS:%.*]]) align 8 [[X:%.*]], i32 [[Y:%.*]])
134; OPT-NEXT:    ret void
135;
136; ABI-LABEL: @libcS_i32_byref(
137; ABI-NEXT:  entry:
138; ABI-NEXT:    [[INDIRECTALLOCA:%.*]] = alloca [[STRUCT_LIBCS:%.*]], align 8
139; ABI-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[LIBCS_I32_BYREF_VARARG:%.*]], align 16
140; ABI-NEXT:    store ptr [[X:%.*]], ptr [[INDIRECTALLOCA]], align 4
141; ABI-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[VARARG_BUFFER]])
142; ABI-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[LIBCS_I32_BYREF_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
143; ABI-NEXT:    store ptr [[INDIRECTALLOCA]], ptr [[TMP0]], align 4
144; ABI-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw [[LIBCS_I32_BYREF_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 1
145; ABI-NEXT:    store i32 [[Y:%.*]], ptr [[TMP1]], align 4
146; ABI-NEXT:    call void @sink(ptr [[VARARG_BUFFER]])
147; ABI-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[VARARG_BUFFER]])
148; ABI-NEXT:    ret void
149;
150entry:
151  tail call void (...) @sink(ptr byref(%struct.libcS) align 8 %x, i32 %y)
152  ret void
153}
154