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