1 // RUN: %clang_cc1 -target-feature +altivec -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
2
3 #include <stdarg.h>
4
5 struct test1 { int x; int y; };
6 struct test2 { int x; int y; } __attribute__((aligned (16)));
7 struct test3 { int x; int y; } __attribute__((aligned (32)));
8 struct test4 { int x; int y; int z; };
9 struct test5 { int x[17]; };
10 struct test6 { int x[17]; } __attribute__((aligned (16)));
11 struct test7 { int x[17]; } __attribute__((aligned (32)));
12 struct test8 { char x; };
13 struct test9 { _Complex char x; };
14
15 // CHECK: define{{.*}} void @test1(i32 noundef signext %x, i64 %y.coerce)
test1(int x,struct test1 y)16 void test1 (int x, struct test1 y)
17 {
18 }
19
20 // CHECK: define{{.*}} void @test2(i32 noundef signext %x, [1 x i128] %y.coerce)
test2(int x,struct test2 y)21 void test2 (int x, struct test2 y)
22 {
23 }
24
25 // CHECK: define{{.*}} void @test3(i32 noundef signext %x, [2 x i128] %y.coerce)
test3(int x,struct test3 y)26 void test3 (int x, struct test3 y)
27 {
28 }
29
30 // CHECK: define{{.*}} void @test4(i32 noundef signext %x, [2 x i64] %y.coerce)
test4(int x,struct test4 y)31 void test4 (int x, struct test4 y)
32 {
33 }
34
35 // CHECK: define{{.*}} void @test5(i32 noundef signext %x, ptr noundef byval(%struct.test5) align 8 %y)
test5(int x,struct test5 y)36 void test5 (int x, struct test5 y)
37 {
38 }
39
40 // CHECK: define{{.*}} void @test6(i32 noundef signext %x, ptr noundef byval(%struct.test6) align 16 %y)
test6(int x,struct test6 y)41 void test6 (int x, struct test6 y)
42 {
43 }
44
45 // This case requires run-time realignment of the incoming struct
46 // CHECK-LABEL: define{{.*}} void @test7(i32 noundef signext %x, ptr noundef byval(%struct.test7) align 16 %0)
47 // CHECK: %y = alloca %struct.test7, align 32
48 // CHECK: call void @llvm.memcpy.p0.p0.i64
test7(int x,struct test7 y)49 void test7 (int x, struct test7 y)
50 {
51 }
52
53 // CHECK: define{{.*}} void @test8(i32 noundef signext %x, i8 %y.coerce)
test8(int x,struct test8 y)54 void test8 (int x, struct test8 y)
55 {
56 }
57
58 // CHECK: define{{.*}} void @test9(i32 noundef signext %x, i16 %y.coerce)
test9(int x,struct test9 y)59 void test9 (int x, struct test9 y)
60 {
61 }
62
63 // CHECK: define{{.*}} void @test1va(ptr dead_on_unwind noalias writable sret(%struct.test1) align 4 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
64 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
65 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
66 // CHECK: store ptr %[[NEXT]], ptr %ap
67 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[AGG_RESULT]], ptr align 8 %[[CUR]], i64 8, i1 false)
test1va(int x,...)68 struct test1 test1va (int x, ...)
69 {
70 struct test1 y;
71 va_list ap;
72 va_start(ap, x);
73 y = va_arg (ap, struct test1);
74 va_end(ap);
75 return y;
76 }
77
78 // CHECK: define{{.*}} void @test2va(ptr dead_on_unwind noalias writable sret(%struct.test2) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
79 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
80 // CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
81 // CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
82 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGN]], i64 16
83 // CHECK: store ptr %[[NEXT]], ptr %ap
84 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[AGG_RESULT]], ptr align 16 %[[ALIGN]], i64 16, i1 false)
test2va(int x,...)85 struct test2 test2va (int x, ...)
86 {
87 struct test2 y;
88 va_list ap;
89 va_start(ap, x);
90 y = va_arg (ap, struct test2);
91 va_end(ap);
92 return y;
93 }
94
95 // CHECK: define{{.*}} void @test3va(ptr dead_on_unwind noalias writable sret(%struct.test3) align 32 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
96 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
97 // CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
98 // CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
99 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGN]], i64 32
100 // CHECK: store ptr %[[NEXT]], ptr %ap
101 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 32 %[[AGG_RESULT]], ptr align 16 %[[ALIGN]], i64 32, i1 false)
test3va(int x,...)102 struct test3 test3va (int x, ...)
103 {
104 struct test3 y;
105 va_list ap;
106 va_start(ap, x);
107 y = va_arg (ap, struct test3);
108 va_end(ap);
109 return y;
110 }
111
112 // CHECK: define{{.*}} void @test4va(ptr dead_on_unwind noalias writable sret(%struct.test4) align 4 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
113 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
114 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16
115 // CHECK: store ptr %[[NEXT]], ptr %ap
116 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[AGG_RESULT]], ptr align 8 %[[CUR]], i64 12, i1 false)
test4va(int x,...)117 struct test4 test4va (int x, ...)
118 {
119 struct test4 y;
120 va_list ap;
121 va_start(ap, x);
122 y = va_arg (ap, struct test4);
123 va_end(ap);
124 return y;
125 }
126
127 // CHECK: define{{.*}} void @test8va(ptr dead_on_unwind noalias writable sret(%struct.test8) align 1 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
128 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
129 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
130 // CHECK: store ptr %[[NEXT]], ptr %ap
131 // CHECK: [[T0:%.*]] = getelementptr inbounds i8, ptr %[[CUR]], i64 7
132 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[AGG_RESULT]], ptr align 1 [[T0]], i64 1, i1 false)
test8va(int x,...)133 struct test8 test8va (int x, ...)
134 {
135 struct test8 y;
136 va_list ap;
137 va_start(ap, x);
138 y = va_arg (ap, struct test8);
139 va_end(ap);
140 return y;
141 }
142
143 // CHECK: define{{.*}} void @test9va(ptr dead_on_unwind noalias writable sret(%struct.test9) align 1 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
144 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
145 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
146 // CHECK: store ptr %[[NEXT]], ptr %ap
147 // CHECK: [[T0:%.*]] = getelementptr inbounds i8, ptr %[[CUR]], i64 6
148 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[AGG_RESULT]], ptr align 2 [[T0]], i64 2, i1 false)
test9va(int x,...)149 struct test9 test9va (int x, ...)
150 {
151 struct test9 y;
152 va_list ap;
153 va_start(ap, x);
154 y = va_arg (ap, struct test9);
155 va_end(ap);
156 return y;
157 }
158
159 // CHECK: define{{.*}} void @testva_longdouble(ptr dead_on_unwind noalias writable sret(%struct.test_longdouble) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
160 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
161 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16
162 // CHECK: store ptr %[[NEXT]], ptr %ap
163 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[AGG_RESULT]], ptr align 8 %[[CUR]], i64 16, i1 false)
164 struct test_longdouble { long double x; };
testva_longdouble(int x,...)165 struct test_longdouble testva_longdouble (int x, ...)
166 {
167 struct test_longdouble y;
168 va_list ap;
169 va_start(ap, x);
170 y = va_arg (ap, struct test_longdouble);
171 va_end(ap);
172 return y;
173 }
174
175 // CHECK: define{{.*}} void @testva_vector(ptr dead_on_unwind noalias writable sret(%struct.test_vector) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...)
176 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
177 // CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15
178 // CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)
179 // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGN]], i64 16
180 // CHECK: store ptr %[[NEXT]], ptr %ap
181 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[AGG_RESULT]], ptr align 16 %[[ALIGN]], i64 16, i1 false)
182 struct test_vector { vector int x; };
testva_vector(int x,...)183 struct test_vector testva_vector (int x, ...)
184 {
185 struct test_vector y;
186 va_list ap;
187 va_start(ap, x);
188 y = va_arg (ap, struct test_vector);
189 va_end(ap);
190 return y;
191 }
192
193