xref: /llvm-project/clang/test/CodeGenCXX/inline-then-fold-variadics.cpp (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
18516f54eSJon Chesterfield // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
28516f54eSJon Chesterfield // REQUIRES: webassembly-registered-target
38516f54eSJon Chesterfield 
48516f54eSJon Chesterfield // Simple calls to known variadic functions that are completely elided when
58516f54eSJon Chesterfield // optimisations are on This is a functional check that the expand-variadic pass
68516f54eSJon Chesterfield // is consistent with clang's va_arg handling
78516f54eSJon Chesterfield 
88516f54eSJon Chesterfield // When expand-variadics is added to the default pipeline, clang -O1 will
98516f54eSJon Chesterfield // suffice here -Wno-varargs avoids warning second argument to 'va_start' is not
108516f54eSJon Chesterfield // the last named parameter
118516f54eSJon Chesterfield 
128516f54eSJon Chesterfield // 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
138516f54eSJon Chesterfield 
148516f54eSJon Chesterfield #include <stdarg.h>
158516f54eSJon Chesterfield #include <stdint.h>
168516f54eSJon Chesterfield 
178516f54eSJon Chesterfield template <typename X, typename Y> static X first(...) {
188516f54eSJon Chesterfield   va_list va;
198516f54eSJon Chesterfield   __builtin_va_start(va, 0);
208516f54eSJon Chesterfield   X r = va_arg(va, X);
218516f54eSJon Chesterfield   va_end(va);
228516f54eSJon Chesterfield   return r;
238516f54eSJon Chesterfield }
248516f54eSJon Chesterfield 
258516f54eSJon Chesterfield template <typename X, typename Y> static Y second(...) {
268516f54eSJon Chesterfield   va_list va;
278516f54eSJon Chesterfield   __builtin_va_start(va, 0);
288516f54eSJon Chesterfield   va_arg(va, X);
298516f54eSJon Chesterfield   Y r = va_arg(va, Y);
308516f54eSJon Chesterfield   va_end(va);
318516f54eSJon Chesterfield   return r;
328516f54eSJon Chesterfield }
338516f54eSJon Chesterfield 
348516f54eSJon Chesterfield extern "C" {
358516f54eSJon Chesterfield 
368516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_pair_i32
37a79ae862SNikita Popov // CHECK-SAME: (i32 noundef returned [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
388516f54eSJon Chesterfield // CHECK-NEXT:  entry:
398516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[X]]
408516f54eSJon Chesterfield //
418516f54eSJon Chesterfield int first_pair_i32(int x, int y) { return first<int, int>(x, y); }
428516f54eSJon Chesterfield 
438516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_pair_i32
44a79ae862SNikita Popov // CHECK-SAME: (i32 noundef [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
458516f54eSJon Chesterfield // CHECK-NEXT:  entry:
468516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[Y]]
478516f54eSJon Chesterfield //
488516f54eSJon Chesterfield int second_pair_i32(int x, int y) { return second<int, int>(x, y); }
498516f54eSJon Chesterfield 
508516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_pair_f64
51a79ae862SNikita Popov // CHECK-SAME: (double noundef returned [[X:%.*]], double noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
528516f54eSJon Chesterfield // CHECK-NEXT:  entry:
538516f54eSJon Chesterfield // CHECK-NEXT:    ret double [[X]]
548516f54eSJon Chesterfield //
558516f54eSJon Chesterfield double first_pair_f64(double x, double y) {
568516f54eSJon Chesterfield   return first<double, double>(x, y);
578516f54eSJon Chesterfield }
588516f54eSJon Chesterfield 
598516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_pair_f64
60a79ae862SNikita Popov // CHECK-SAME: (double noundef [[X:%.*]], double noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
618516f54eSJon Chesterfield // CHECK-NEXT:  entry:
628516f54eSJon Chesterfield // CHECK-NEXT:    ret double [[Y]]
638516f54eSJon Chesterfield //
648516f54eSJon Chesterfield double second_pair_f64(double x, double y) {
658516f54eSJon Chesterfield   return second<double, double>(x, y);
668516f54eSJon Chesterfield }
678516f54eSJon Chesterfield }
688516f54eSJon Chesterfield 
698516f54eSJon Chesterfield extern "C" {
708516f54eSJon Chesterfield 
718516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_i32_f64
72a79ae862SNikita Popov // CHECK-SAME: (i32 noundef returned [[X:%.*]], double noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
738516f54eSJon Chesterfield // CHECK-NEXT:  entry:
748516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[X]]
758516f54eSJon Chesterfield //
768516f54eSJon Chesterfield int first_i32_f64(int x, double y) { return first<int, double>(x, y); }
778516f54eSJon Chesterfield 
788516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_i32_f64
79a79ae862SNikita Popov // CHECK-SAME: (i32 noundef [[X:%.*]], double noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
808516f54eSJon Chesterfield // CHECK-NEXT:  entry:
818516f54eSJon Chesterfield // CHECK-NEXT:    ret double [[Y]]
828516f54eSJon Chesterfield //
838516f54eSJon Chesterfield double second_i32_f64(int x, double y) { return second<int, double>(x, y); }
848516f54eSJon Chesterfield 
858516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_f64_i32
86a79ae862SNikita Popov // CHECK-SAME: (double noundef returned [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
878516f54eSJon Chesterfield // CHECK-NEXT:  entry:
888516f54eSJon Chesterfield // CHECK-NEXT:    ret double [[X]]
898516f54eSJon Chesterfield //
908516f54eSJon Chesterfield double first_f64_i32(double x, int y) { return first<double, int>(x, y); }
918516f54eSJon Chesterfield 
928516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_f64_i32
93a79ae862SNikita Popov // CHECK-SAME: (double noundef [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
948516f54eSJon Chesterfield // CHECK-NEXT:  entry:
958516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[Y]]
968516f54eSJon Chesterfield //
978516f54eSJon Chesterfield int second_f64_i32(double x, int y) { return second<double, int>(x, y); }
988516f54eSJon Chesterfield }
998516f54eSJon Chesterfield 
1008516f54eSJon Chesterfield extern "C" {
1018516f54eSJon Chesterfield typedef uint64_t ulong2 __attribute__((__vector_size__(16), __aligned__(16)));
1028516f54eSJon Chesterfield 
1038516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_i32_ulong2
104*29441e4fSNikita Popov // CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
1058516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1068516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[X]]
1078516f54eSJon Chesterfield //
1088516f54eSJon Chesterfield int first_i32_ulong2(int x, ulong2 *y) { return first<int, ulong2>(x, *y); }
1098516f54eSJon Chesterfield 
1108516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_i32_ulong2
111*29441e4fSNikita Popov // CHECK-SAME: (i32 noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
1128516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1138516f54eSJon Chesterfield // CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[Y]], align 16, !tbaa [[TBAA2:![0-9]+]]
1148516f54eSJon Chesterfield // CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
1158516f54eSJon Chesterfield // CHECK-NEXT:    ret void
1168516f54eSJon Chesterfield //
1178516f54eSJon Chesterfield void second_i32_ulong2(int x, ulong2 *y, ulong2 *r) {
1188516f54eSJon Chesterfield   *r = second<int, ulong2>(x, *y);
1198516f54eSJon Chesterfield }
1208516f54eSJon Chesterfield 
1218516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_ulong2_i32
122*29441e4fSNikita Popov // CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
1238516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1248516f54eSJon Chesterfield // CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[X]], align 16, !tbaa [[TBAA2]]
1258516f54eSJon Chesterfield // CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
1268516f54eSJon Chesterfield // CHECK-NEXT:    ret void
1278516f54eSJon Chesterfield //
1288516f54eSJon Chesterfield void first_ulong2_i32(ulong2 *x, int y, ulong2 *r) {
1298516f54eSJon Chesterfield   *r = first<ulong2, int>(*x, y);
1308516f54eSJon Chesterfield }
1318516f54eSJon Chesterfield 
1328516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_ulong2_i32
133*29441e4fSNikita Popov // CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
1348516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1358516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[Y]]
1368516f54eSJon Chesterfield //
1378516f54eSJon Chesterfield int second_ulong2_i32(ulong2 *x, int y) { return second<ulong2, int>(*x, y); }
1388516f54eSJon Chesterfield }
1398516f54eSJon Chesterfield 
1408516f54eSJon Chesterfield // ascending alignment
1418516f54eSJon Chesterfield typedef struct {
1428516f54eSJon Chesterfield   char c;
1438516f54eSJon Chesterfield   short s;
1448516f54eSJon Chesterfield   int i;
1458516f54eSJon Chesterfield   long l;
1468516f54eSJon Chesterfield   float f;
1478516f54eSJon Chesterfield   double d;
1488516f54eSJon Chesterfield } asc;
1498516f54eSJon Chesterfield 
1508516f54eSJon Chesterfield extern "C" {
1518516f54eSJon Chesterfield 
1528516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_i32_asc
153*29441e4fSNikita Popov // CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
1548516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1558516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[X]]
1568516f54eSJon Chesterfield //
1578516f54eSJon Chesterfield int first_i32_asc(int x, asc *y) { return first<int, asc>(x, *y); }
1588516f54eSJon Chesterfield 
1598516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_i32_asc
160*29441e4fSNikita Popov // CHECK-SAME: (i32 noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
1618516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1628516f54eSJon Chesterfield // 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)
1638516f54eSJon Chesterfield // CHECK-NEXT:    ret void
1648516f54eSJon Chesterfield //
1658516f54eSJon Chesterfield void second_i32_asc(int x, asc *y, asc *r) { *r = second<int, asc>(x, *y); }
1668516f54eSJon Chesterfield 
1678516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@first_asc_i32
168*29441e4fSNikita Popov // CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
1698516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1708516f54eSJon Chesterfield // 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)
1718516f54eSJon Chesterfield // CHECK-NEXT:    ret void
1728516f54eSJon Chesterfield //
1738516f54eSJon Chesterfield void first_asc_i32(asc *x, int y, asc *r) { *r = first<asc, int>(*x, y); }
1748516f54eSJon Chesterfield 
1758516f54eSJon Chesterfield // CHECK-LABEL: define {{[^@]+}}@second_asc_i32
176*29441e4fSNikita Popov // CHECK-SAME: (ptr noundef readonly captures(none) [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
1778516f54eSJon Chesterfield // CHECK-NEXT:  entry:
1788516f54eSJon Chesterfield // CHECK-NEXT:    ret i32 [[Y]]
1798516f54eSJon Chesterfield //
1808516f54eSJon Chesterfield int second_asc_i32(asc *x, int y) { return second<asc, int>(*x, y); }
1818516f54eSJon Chesterfield }
182