1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
2 // REQUIRES: webassembly-registered-target
4 // Simple calls to known variadic functions that are completely elided when
5 // optimisations are on This is a functional check that the expand-variadic pass
6 // is consistent with clang's va_arg handling
8 // When expand-variadics is added to the default pipeline, clang -O1 will
9 // suffice here -Wno-varargs avoids warning second argument to 'va_start' is not
10 // the last named parameter
12 // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -Wno-varargs -O1 -emit-llvm -o - | opt - -S --passes='module(expand-variadics,default<O1>)' --expand-variadics-override=optimize -o - | FileCheck %s
17 template <typename X
, typename Y
> static X
first(...) {
19 __builtin_va_start(va
, 0);
25 template <typename X
, typename Y
> static Y
second(...) {
27 __builtin_va_start(va
, 0);
36 // CHECK-LABEL: define {{[^@]+}}@first_pair_i32
37 // CHECK-SAME: (i32 noundef returned [[X:%.*]], i32 noundef [[Y:%.*]])
39 // CHECK-NEXT: ret i32 [[X]]
41 int first_pair_i32(int x
, int y
) { return first
<int, int>(x
, y
); }
43 // CHECK-LABEL: define {{[^@]+}}@second_pair_i32
44 // CHECK-SAME: (i32 noundef [[X:%.*]], i32 noundef returned [[Y:%.*]])
46 // CHECK-NEXT: ret i32 [[Y]]
48 int second_pair_i32(int x
, int y
) { return second
<int, int>(x
, y
); }
50 // CHECK-LABEL: define {{[^@]+}}@first_pair_f64
51 // CHECK-SAME: (double noundef returned [[X:%.*]], double noundef [[Y:%.*]])
53 // CHECK-NEXT: ret double [[X]]
55 double first_pair_f64(double x
, double y
) {
56 return first
<double, double>(x
, y
);
59 // CHECK-LABEL: define {{[^@]+}}@second_pair_f64
60 // CHECK-SAME: (double noundef [[X:%.*]], double noundef returned [[Y:%.*]])
62 // CHECK-NEXT: ret double [[Y]]
64 double second_pair_f64(double x
, double y
) {
65 return second
<double, double>(x
, y
);
71 // CHECK-LABEL: define {{[^@]+}}@first_i32_f64
72 // CHECK-SAME: (i32 noundef returned [[X:%.*]], double noundef [[Y:%.*]])
74 // CHECK-NEXT: ret i32 [[X]]
76 int first_i32_f64(int x
, double y
) { return first
<int, double>(x
, y
); }
78 // CHECK-LABEL: define {{[^@]+}}@second_i32_f64
79 // CHECK-SAME: (i32 noundef [[X:%.*]], double noundef returned [[Y:%.*]])
81 // CHECK-NEXT: ret double [[Y]]
83 double second_i32_f64(int x
, double y
) { return second
<int, double>(x
, y
); }
85 // CHECK-LABEL: define {{[^@]+}}@first_f64_i32
86 // CHECK-SAME: (double noundef returned [[X:%.*]], i32 noundef [[Y:%.*]])
88 // CHECK-NEXT: ret double [[X]]
90 double first_f64_i32(double x
, int y
) { return first
<double, int>(x
, y
); }
92 // CHECK-LABEL: define {{[^@]+}}@second_f64_i32
93 // CHECK-SAME: (double noundef [[X:%.*]], i32 noundef returned [[Y:%.*]])
95 // CHECK-NEXT: ret i32 [[Y]]
97 int second_f64_i32(double x
, int y
) { return second
<double, int>(x
, y
); }
101 typedef uint64_t ulong2
__attribute__((__vector_size__(16), __aligned__(16)));
103 // CHECK-LABEL: define {{[^@]+}}@first_i32_ulong2
104 // CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]])
105 // CHECK-NEXT: entry:
106 // CHECK-NEXT: ret i32 [[X]]
108 int first_i32_ulong2(int x
, ulong2
*y
) { return first
<int, ulong2
>(x
, *y
); }
110 // CHECK-LABEL: define {{[^@]+}}@second_i32_ulong2
111 // CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
112 // CHECK-NEXT: entry:
113 // CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[Y]], align 16, !tbaa [[TBAA2:![0-9]+]]
114 // CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
115 // CHECK-NEXT: ret void
117 void second_i32_ulong2(int x
, ulong2
*y
, ulong2
*r
) {
118 *r
= second
<int, ulong2
>(x
, *y
);
121 // CHECK-LABEL: define {{[^@]+}}@first_ulong2_i32
122 // CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
123 // CHECK-NEXT: entry:
124 // CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[X]], align 16, !tbaa [[TBAA2]]
125 // CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
126 // CHECK-NEXT: ret void
128 void first_ulong2_i32(ulong2
*x
, int y
, ulong2
*r
) {
129 *r
= first
<ulong2
, int>(*x
, y
);
132 // CHECK-LABEL: define {{[^@]+}}@second_ulong2_i32
133 // CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef returned [[Y:%.*]])
134 // CHECK-NEXT: entry:
135 // CHECK-NEXT: ret i32 [[Y]]
137 int second_ulong2_i32(ulong2
*x
, int y
) { return second
<ulong2
, int>(*x
, y
); }
140 // ascending alignment
152 // CHECK-LABEL: define {{[^@]+}}@first_i32_asc
153 // CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]])
154 // CHECK-NEXT: entry:
155 // CHECK-NEXT: ret i32 [[X]]
157 int first_i32_asc(int x
, asc
*y
) { return first
<int, asc
>(x
, *y
); }
159 // CHECK-LABEL: define {{[^@]+}}@second_i32_asc
160 // CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
161 // CHECK-NEXT: entry:
162 // CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[Y]], i32 24, i1 false)
163 // CHECK-NEXT: ret void
165 void second_i32_asc(int x
, asc
*y
, asc
*r
) { *r
= second
<int, asc
>(x
, *y
); }
167 // CHECK-LABEL: define {{[^@]+}}@first_asc_i32
168 // CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
169 // CHECK-NEXT: entry:
170 // CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[X]], i32 24, i1 false)
171 // CHECK-NEXT: ret void
173 void first_asc_i32(asc
*x
, int y
, asc
*r
) { *r
= first
<asc
, int>(*x
, y
); }
175 // CHECK-LABEL: define {{[^@]+}}@second_asc_i32
176 // CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef returned [[Y:%.*]])
177 // CHECK-NEXT: entry:
178 // CHECK-NEXT: ret i32 [[Y]]
180 int second_asc_i32(asc
*x
, int y
) { return second
<asc
, int>(*x
, y
); }