193 lines · c
1// RUN: %clang_cc1 -target-feature +altivec -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s2 3#include <stdarg.h>4 5struct test1 { int x; int y; };6struct test2 { int x; int y; } __attribute__((aligned (16)));7struct test3 { int x; int y; } __attribute__((aligned (32)));8struct test4 { int x; int y; int z; };9struct test5 { int x[17]; };10struct test6 { int x[17]; } __attribute__((aligned (16)));11struct test7 { int x[17]; } __attribute__((aligned (32)));12struct test8 { char x; };13struct test9 { _Complex char x; };14 15// CHECK: define{{.*}} void @test1(i32 noundef signext %x, i64 %y.coerce)16void test1 (int x, struct test1 y)17{18}19 20// CHECK: define{{.*}} void @test2(i32 noundef signext %x, [1 x i128] %y.coerce)21void test2 (int x, struct test2 y)22{23}24 25// CHECK: define{{.*}} void @test3(i32 noundef signext %x, [2 x i128] %y.coerce)26void test3 (int x, struct test3 y)27{28}29 30// CHECK: define{{.*}} void @test4(i32 noundef signext %x, [2 x i64] %y.coerce)31void 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)36void 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)41void test6 (int x, struct test6 y)42{43}44 45// This case requires run-time realignment of the incoming struct46// CHECK-LABEL: define{{.*}} void @test7(i32 noundef signext %x, ptr noundef byval(%struct.test7) align 16 %0)47// CHECK: %y = alloca %struct.test7, align 3248// CHECK: call void @llvm.memcpy.p0.p0.i6449void test7 (int x, struct test7 y)50{51}52 53// CHECK: define{{.*}} void @test8(i32 noundef signext %x, i8 %y.coerce)54void test8 (int x, struct test8 y)55{56}57 58// CHECK: define{{.*}} void @test9(i32 noundef signext %x, i16 %y.coerce)59void 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 %ap65// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 866// CHECK: store ptr %[[NEXT]], ptr %ap67// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[AGG_RESULT]], ptr align 8 %[[CUR]], i64 8, i1 false)68struct 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 %ap80// CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 1581// CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)82// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGN]], i64 1683// CHECK: store ptr %[[NEXT]], ptr %ap84// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[AGG_RESULT]], ptr align 16 %[[ALIGN]], i64 16, i1 false)85struct 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 %ap97// CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 1598// CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)99// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGN]], i64 32100// CHECK: store ptr %[[NEXT]], ptr %ap101// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 32 %[[AGG_RESULT]], ptr align 16 %[[ALIGN]], i64 32, i1 false)102struct 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 %ap114// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16115// CHECK: store ptr %[[NEXT]], ptr %ap116// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[AGG_RESULT]], ptr align 8 %[[CUR]], i64 12, i1 false)117struct 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 %ap129// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8130// CHECK: store ptr %[[NEXT]], ptr %ap131// CHECK: [[T0:%.*]] = getelementptr inbounds i8, ptr %[[CUR]], i64 7132// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[AGG_RESULT]], ptr align 1 [[T0]], i64 1, i1 false)133struct 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 %ap145// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8146// CHECK: store ptr %[[NEXT]], ptr %ap147// CHECK: [[T0:%.*]] = getelementptr inbounds i8, ptr %[[CUR]], i64 6148// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[AGG_RESULT]], ptr align 2 [[T0]], i64 2, i1 false)149struct 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 %ap161// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16162// CHECK: store ptr %[[NEXT]], ptr %ap163// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[AGG_RESULT]], ptr align 8 %[[CUR]], i64 16, i1 false)164struct test_longdouble { long double x; };165struct 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 %ap177// CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15178// CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16)179// CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGN]], i64 16180// CHECK: store ptr %[[NEXT]], ptr %ap181// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[AGG_RESULT]], ptr align 16 %[[ALIGN]], i64 16, i1 false)182struct test_vector { vector int x; };183struct 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