427 lines · c
1// RUN: %clang_cc1 -target-feature +altivec -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s2 3// Test homogeneous float aggregate passing and returning.4 5struct f1 { float f[1]; };6struct f2 { float f[2]; };7struct f3 { float f[3]; };8struct f4 { float f[4]; };9struct f5 { float f[5]; };10struct f6 { float f[6]; };11struct f7 { float f[7]; };12struct f8 { float f[8]; };13struct f9 { float f[9]; };14 15struct fab { float a; float b; };16struct fabc { float a; float b; float c; };17 18struct f2a2b { float a[2]; float b[2]; };19 20// CHECK: define{{.*}} [1 x float] @func_f1(float inreg %x.coerce)21struct f1 func_f1(struct f1 x) { return x; }22 23// CHECK: define{{.*}} [2 x float] @func_f2([2 x float] %x.coerce)24struct f2 func_f2(struct f2 x) { return x; }25 26// CHECK: define{{.*}} [3 x float] @func_f3([3 x float] %x.coerce)27struct f3 func_f3(struct f3 x) { return x; }28 29// CHECK: define{{.*}} [4 x float] @func_f4([4 x float] %x.coerce)30struct f4 func_f4(struct f4 x) { return x; }31 32// CHECK: define{{.*}} [5 x float] @func_f5([5 x float] %x.coerce)33struct f5 func_f5(struct f5 x) { return x; }34 35// CHECK: define{{.*}} [6 x float] @func_f6([6 x float] %x.coerce)36struct f6 func_f6(struct f6 x) { return x; }37 38// CHECK: define{{.*}} [7 x float] @func_f7([7 x float] %x.coerce)39struct f7 func_f7(struct f7 x) { return x; }40 41// CHECK: define{{.*}} [8 x float] @func_f8([8 x float] %x.coerce)42struct f8 func_f8(struct f8 x) { return x; }43 44// CHECK: define{{.*}} void @func_f9(ptr dead_on_unwind noalias writable sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce)45struct f9 func_f9(struct f9 x) { return x; }46 47// CHECK: define{{.*}} [2 x float] @func_fab([2 x float] %x.coerce)48struct fab func_fab(struct fab x) { return x; }49 50// CHECK: define{{.*}} [3 x float] @func_fabc([3 x float] %x.coerce)51struct fabc func_fabc(struct fabc x) { return x; }52 53// CHECK: define{{.*}} [4 x float] @func_f2a2b([4 x float] %x.coerce)54struct f2a2b func_f2a2b(struct f2a2b x) { return x; }55 56// CHECK-LABEL: @call_f157// CHECK: %[[TMP:[^ ]+]] = load float, ptr @global_f1, align 458// CHECK: call [1 x float] @func_f1(float inreg %[[TMP]])59struct f1 global_f1;60void call_f1(void) { global_f1 = func_f1(global_f1); }61 62// CHECK-LABEL: @call_f263// CHECK: %[[TMP:[^ ]+]] = load [2 x float], ptr @global_f2, align 464// CHECK: call [2 x float] @func_f2([2 x float] %[[TMP]])65struct f2 global_f2;66void call_f2(void) { global_f2 = func_f2(global_f2); }67 68// CHECK-LABEL: @call_f369// CHECK: %[[TMP:[^ ]+]] = load [3 x float], ptr @global_f3, align 470// CHECK: call [3 x float] @func_f3([3 x float] %[[TMP]])71struct f3 global_f3;72void call_f3(void) { global_f3 = func_f3(global_f3); }73 74// CHECK-LABEL: @call_f475// CHECK: %[[TMP:[^ ]+]] = load [4 x float], ptr @global_f4, align 476// CHECK: call [4 x float] @func_f4([4 x float] %[[TMP]])77struct f4 global_f4;78void call_f4(void) { global_f4 = func_f4(global_f4); }79 80// CHECK-LABEL: @call_f581// CHECK: %[[TMP:[^ ]+]] = load [5 x float], ptr @global_f5, align 482// CHECK: call [5 x float] @func_f5([5 x float] %[[TMP]])83struct f5 global_f5;84void call_f5(void) { global_f5 = func_f5(global_f5); }85 86// CHECK-LABEL: @call_f687// CHECK: %[[TMP:[^ ]+]] = load [6 x float], ptr @global_f6, align 488// CHECK: call [6 x float] @func_f6([6 x float] %[[TMP]])89struct f6 global_f6;90void call_f6(void) { global_f6 = func_f6(global_f6); }91 92// CHECK-LABEL: @call_f793// CHECK: %[[TMP:[^ ]+]] = load [7 x float], ptr @global_f7, align 494// CHECK: call [7 x float] @func_f7([7 x float] %[[TMP]])95struct f7 global_f7;96void call_f7(void) { global_f7 = func_f7(global_f7); }97 98// CHECK-LABEL: @call_f899// CHECK: %[[TMP:[^ ]+]] = load [8 x float], ptr @global_f8, align 4100// CHECK: call [8 x float] @func_f8([8 x float] %[[TMP]])101struct f8 global_f8;102void call_f8(void) { global_f8 = func_f8(global_f8); }103 104// CHECK-LABEL: @call_f9105// CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64]106// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f9, i64 36, i1 false)107// CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], ptr %[[TMP1]]108// CHECK: call void @func_f9(ptr dead_on_unwind writable sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]])109struct f9 global_f9;110void call_f9(void) { global_f9 = func_f9(global_f9); }111 112// CHECK-LABEL: @call_fab113// CHECK: %[[TMP:[^ ]+]] = load [2 x float], ptr @global_fab114// CHECK: call [2 x float] @func_fab([2 x float] %[[TMP]])115struct fab global_fab;116void call_fab(void) { global_fab = func_fab(global_fab); }117 118// CHECK-LABEL: @call_fabc119// CHECK: %[[TMP:[^ ]+]] = load [3 x float], ptr @global_fabc120// CHECK: call [3 x float] @func_fabc([3 x float] %[[TMP]])121struct fabc global_fabc;122void call_fabc(void) { global_fabc = func_fabc(global_fabc); }123 124 125// Test homogeneous vector aggregate passing and returning.126 127struct v1 { vector int v[1]; };128struct v2 { vector int v[2]; };129struct v3 { vector int v[3]; };130struct v4 { vector int v[4]; };131struct v5 { vector int v[5]; };132struct v6 { vector int v[6]; };133struct v7 { vector int v[7]; };134struct v8 { vector int v[8]; };135struct v9 { vector int v[9]; };136 137struct vab { vector int a; vector int b; };138struct vabc { vector int a; vector int b; vector int c; };139 140// CHECK: define{{.*}} [1 x <4 x i32>] @func_v1(<4 x i32> inreg %x.coerce)141struct v1 func_v1(struct v1 x) { return x; }142 143// CHECK: define{{.*}} [2 x <4 x i32>] @func_v2([2 x <4 x i32>] %x.coerce)144struct v2 func_v2(struct v2 x) { return x; }145 146// CHECK: define{{.*}} [3 x <4 x i32>] @func_v3([3 x <4 x i32>] %x.coerce)147struct v3 func_v3(struct v3 x) { return x; }148 149// CHECK: define{{.*}} [4 x <4 x i32>] @func_v4([4 x <4 x i32>] %x.coerce)150struct v4 func_v4(struct v4 x) { return x; }151 152// CHECK: define{{.*}} [5 x <4 x i32>] @func_v5([5 x <4 x i32>] %x.coerce)153struct v5 func_v5(struct v5 x) { return x; }154 155// CHECK: define{{.*}} [6 x <4 x i32>] @func_v6([6 x <4 x i32>] %x.coerce)156struct v6 func_v6(struct v6 x) { return x; }157 158// CHECK: define{{.*}} [7 x <4 x i32>] @func_v7([7 x <4 x i32>] %x.coerce)159struct v7 func_v7(struct v7 x) { return x; }160 161// CHECK: define{{.*}} [8 x <4 x i32>] @func_v8([8 x <4 x i32>] %x.coerce)162struct v8 func_v8(struct v8 x) { return x; }163 164// CHECK: define{{.*}} void @func_v9(ptr dead_on_unwind noalias writable sret(%struct.v9) align 16 %agg.result, ptr noundef byval(%struct.v9) align 16 %x)165struct v9 func_v9(struct v9 x) { return x; }166 167// CHECK: define{{.*}} [2 x <4 x i32>] @func_vab([2 x <4 x i32>] %x.coerce)168struct vab func_vab(struct vab x) { return x; }169 170// CHECK: define{{.*}} [3 x <4 x i32>] @func_vabc([3 x <4 x i32>] %x.coerce)171struct vabc func_vabc(struct vabc x) { return x; }172 173// CHECK-LABEL: @call_v1174// CHECK: %[[TMP:[^ ]+]] = load <4 x i32>, ptr @global_v1, align 1175// CHECK: call [1 x <4 x i32>] @func_v1(<4 x i32> inreg %[[TMP]])176struct v1 global_v1;177void call_v1(void) { global_v1 = func_v1(global_v1); }178 179// CHECK-LABEL: @call_v2180// CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x i32>], ptr @global_v2, align 1181// CHECK: call [2 x <4 x i32>] @func_v2([2 x <4 x i32>] %[[TMP]])182struct v2 global_v2;183void call_v2(void) { global_v2 = func_v2(global_v2); }184 185// CHECK-LABEL: @call_v3186// CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x i32>], ptr @global_v3, align 1187// CHECK: call [3 x <4 x i32>] @func_v3([3 x <4 x i32>] %[[TMP]])188struct v3 global_v3;189void call_v3(void) { global_v3 = func_v3(global_v3); }190 191// CHECK-LABEL: @call_v4192// CHECK: %[[TMP:[^ ]+]] = load [4 x <4 x i32>], ptr @global_v4, align 1193// CHECK: call [4 x <4 x i32>] @func_v4([4 x <4 x i32>] %[[TMP]])194struct v4 global_v4;195void call_v4(void) { global_v4 = func_v4(global_v4); }196 197// CHECK-LABEL: @call_v5198// CHECK: %[[TMP:[^ ]+]] = load [5 x <4 x i32>], ptr @global_v5, align 1199// CHECK: call [5 x <4 x i32>] @func_v5([5 x <4 x i32>] %[[TMP]])200struct v5 global_v5;201void call_v5(void) { global_v5 = func_v5(global_v5); }202 203// CHECK-LABEL: @call_v6204// CHECK: %[[TMP:[^ ]+]] = load [6 x <4 x i32>], ptr @global_v6, align 1205// CHECK: call [6 x <4 x i32>] @func_v6([6 x <4 x i32>] %[[TMP]])206struct v6 global_v6;207void call_v6(void) { global_v6 = func_v6(global_v6); }208 209// CHECK-LABEL: @call_v7210// CHECK: %[[TMP:[^ ]+]] = load [7 x <4 x i32>], ptr @global_v7, align 1211// CHECK: call [7 x <4 x i32>] @func_v7([7 x <4 x i32>] %[[TMP]])212struct v7 global_v7;213void call_v7(void) { global_v7 = func_v7(global_v7); }214 215// CHECK-LABEL: @call_v8216// CHECK: %[[TMP:[^ ]+]] = load [8 x <4 x i32>], ptr @global_v8, align 1217// CHECK: call [8 x <4 x i32>] @func_v8([8 x <4 x i32>] %[[TMP]])218struct v8 global_v8;219void call_v8(void) { global_v8 = func_v8(global_v8); }220 221// CHECK-LABEL: @call_v9222// CHECK: call void @func_v9(ptr dead_on_unwind writable sret(%struct.v9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v9) align 16 @global_v9)223struct v9 global_v9;224void call_v9(void) { global_v9 = func_v9(global_v9); }225 226// CHECK-LABEL: @call_vab227// CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x i32>], ptr @global_vab228// CHECK: call [2 x <4 x i32>] @func_vab([2 x <4 x i32>] %[[TMP]])229struct vab global_vab;230void call_vab(void) { global_vab = func_vab(global_vab); }231 232// CHECK-LABEL: @call_vabc233// CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x i32>], ptr @global_vabc234// CHECK: call [3 x <4 x i32>] @func_vabc([3 x <4 x i32>] %[[TMP]])235struct vabc global_vabc;236void call_vabc(void) { global_vabc = func_vabc(global_vabc); }237 238 239// As clang extension, non-power-of-two vectors may also be part of240// homogeneous aggregates.241 242typedef float float3 __attribute__((vector_size (12)));243 244struct v3f1 { float3 v[1]; };245struct v3f2 { float3 v[2]; };246struct v3f3 { float3 v[3]; };247struct v3f4 { float3 v[4]; };248struct v3f5 { float3 v[5]; };249struct v3f6 { float3 v[6]; };250struct v3f7 { float3 v[7]; };251struct v3f8 { float3 v[8]; };252struct v3f9 { float3 v[9]; };253 254struct v3fab { float3 a; float3 b; };255struct v3fabc { float3 a; float3 b; float3 c; };256 257// CHECK: define{{.*}} [1 x <4 x float>] @func_v3f1(<3 x float> inreg %x.coerce)258struct v3f1 func_v3f1(struct v3f1 x) { return x; }259 260// CHECK: define{{.*}} [2 x <4 x float>] @func_v3f2([2 x <4 x float>] %x.coerce)261struct v3f2 func_v3f2(struct v3f2 x) { return x; }262 263// CHECK: define{{.*}} [3 x <4 x float>] @func_v3f3([3 x <4 x float>] %x.coerce)264struct v3f3 func_v3f3(struct v3f3 x) { return x; }265 266// CHECK: define{{.*}} [4 x <4 x float>] @func_v3f4([4 x <4 x float>] %x.coerce)267struct v3f4 func_v3f4(struct v3f4 x) { return x; }268 269// CHECK: define{{.*}} [5 x <4 x float>] @func_v3f5([5 x <4 x float>] %x.coerce)270struct v3f5 func_v3f5(struct v3f5 x) { return x; }271 272// CHECK: define{{.*}} [6 x <4 x float>] @func_v3f6([6 x <4 x float>] %x.coerce)273struct v3f6 func_v3f6(struct v3f6 x) { return x; }274 275// CHECK: define{{.*}} [7 x <4 x float>] @func_v3f7([7 x <4 x float>] %x.coerce)276struct v3f7 func_v3f7(struct v3f7 x) { return x; }277 278// CHECK: define{{.*}} [8 x <4 x float>] @func_v3f8([8 x <4 x float>] %x.coerce)279struct v3f8 func_v3f8(struct v3f8 x) { return x; }280 281// CHECK: define{{.*}} void @func_v3f9(ptr dead_on_unwind noalias writable sret(%struct.v3f9) align 16 %agg.result, ptr noundef byval(%struct.v3f9) align 16 %x)282struct v3f9 func_v3f9(struct v3f9 x) { return x; }283 284// CHECK: define{{.*}} [2 x <4 x float>] @func_v3fab([2 x <4 x float>] %x.coerce)285struct v3fab func_v3fab(struct v3fab x) { return x; }286 287// CHECK: define{{.*}} [3 x <4 x float>] @func_v3fabc([3 x <4 x float>] %x.coerce)288struct v3fabc func_v3fabc(struct v3fabc x) { return x; }289 290// CHECK-LABEL: @call_v3f1291// CHECK: %[[TMP:[^ ]+]] = load <3 x float>, ptr @global_v3f1, align 1292// CHECK: call [1 x <4 x float>] @func_v3f1(<3 x float> inreg %[[TMP]])293struct v3f1 global_v3f1;294void call_v3f1(void) { global_v3f1 = func_v3f1(global_v3f1); }295 296// CHECK-LABEL: @call_v3f2297// CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x float>], ptr @global_v3f2, align 16298// CHECK: call [2 x <4 x float>] @func_v3f2([2 x <4 x float>] %[[TMP]])299struct v3f2 global_v3f2;300void call_v3f2(void) { global_v3f2 = func_v3f2(global_v3f2); }301 302// CHECK-LABEL: @call_v3f3303// CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x float>], ptr @global_v3f3, align 16304// CHECK: call [3 x <4 x float>] @func_v3f3([3 x <4 x float>] %[[TMP]])305struct v3f3 global_v3f3;306void call_v3f3(void) { global_v3f3 = func_v3f3(global_v3f3); }307 308// CHECK-LABEL: @call_v3f4309// CHECK: %[[TMP:[^ ]+]] = load [4 x <4 x float>], ptr @global_v3f4, align 16310// CHECK: call [4 x <4 x float>] @func_v3f4([4 x <4 x float>] %[[TMP]])311struct v3f4 global_v3f4;312void call_v3f4(void) { global_v3f4 = func_v3f4(global_v3f4); }313 314// CHECK-LABEL: @call_v3f5315// CHECK: %[[TMP:[^ ]+]] = load [5 x <4 x float>], ptr @global_v3f5, align 16316// CHECK: call [5 x <4 x float>] @func_v3f5([5 x <4 x float>] %[[TMP]])317struct v3f5 global_v3f5;318void call_v3f5(void) { global_v3f5 = func_v3f5(global_v3f5); }319 320// CHECK-LABEL: @call_v3f6321// CHECK: %[[TMP:[^ ]+]] = load [6 x <4 x float>], ptr @global_v3f6, align 16322// CHECK: call [6 x <4 x float>] @func_v3f6([6 x <4 x float>] %[[TMP]])323struct v3f6 global_v3f6;324void call_v3f6(void) { global_v3f6 = func_v3f6(global_v3f6); }325 326// CHECK-LABEL: @call_v3f7327// CHECK: %[[TMP:[^ ]+]] = load [7 x <4 x float>], ptr @global_v3f7, align 16328// CHECK: call [7 x <4 x float>] @func_v3f7([7 x <4 x float>] %[[TMP]])329struct v3f7 global_v3f7;330void call_v3f7(void) { global_v3f7 = func_v3f7(global_v3f7); }331 332// CHECK-LABEL: @call_v3f8333// CHECK: %[[TMP:[^ ]+]] = load [8 x <4 x float>], ptr @global_v3f8, align 16334// CHECK: call [8 x <4 x float>] @func_v3f8([8 x <4 x float>] %[[TMP]])335struct v3f8 global_v3f8;336void call_v3f8(void) { global_v3f8 = func_v3f8(global_v3f8); }337 338// CHECK-LABEL: @call_v3f9339// CHECK: call void @func_v3f9(ptr dead_on_unwind writable sret(%struct.v3f9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v3f9) align 16 @global_v3f9)340struct v3f9 global_v3f9;341void call_v3f9(void) { global_v3f9 = func_v3f9(global_v3f9); }342 343// CHECK-LABEL: @call_v3fab344// CHECK: %[[TMP:[^ ]+]] = load [2 x <4 x float>], ptr @global_v3fab, align 16345// CHECK: call [2 x <4 x float>] @func_v3fab([2 x <4 x float>] %[[TMP]])346struct v3fab global_v3fab;347void call_v3fab(void) { global_v3fab = func_v3fab(global_v3fab); }348 349// CHECK-LABEL: @call_v3fabc350// CHECK: %[[TMP:[^ ]+]] = load [3 x <4 x float>], ptr @global_v3fabc, align 16351// CHECK: call [3 x <4 x float>] @func_v3fabc([3 x <4 x float>] %[[TMP]])352struct v3fabc global_v3fabc;353void call_v3fabc(void) { global_v3fabc = func_v3fabc(global_v3fabc); }354 355 356// Test returning small aggregates.357 358struct s1 { char c[1]; };359struct s2 { char c[2]; };360struct s3 { char c[3]; };361struct s4 { char c[4]; };362struct s5 { char c[5]; };363struct s6 { char c[6]; };364struct s7 { char c[7]; };365struct s8 { char c[8]; };366struct s9 { char c[9]; };367struct s16 { char c[16]; };368struct s17 { char c[17]; };369 370// CHECK: define{{.*}} i8 @ret_s1()371struct s1 ret_s1(void) {372 return (struct s1) { 17 };373}374 375// CHECK: define{{.*}} i16 @ret_s2()376struct s2 ret_s2(void) {377 return (struct s2) { 17, 18 };378}379 380// CHECK: define{{.*}} i24 @ret_s3()381struct s3 ret_s3(void) {382 return (struct s3) { 17, 18, 19 };383}384 385// CHECK: define{{.*}} i32 @ret_s4()386struct s4 ret_s4(void) {387 return (struct s4) { 17, 18, 19, 20 };388}389 390// CHECK: define{{.*}} i40 @ret_s5()391struct s5 ret_s5(void) {392 return (struct s5) { 17, 18, 19, 20, 21 };393}394 395// CHECK: define{{.*}} i48 @ret_s6()396struct s6 ret_s6(void) {397 return (struct s6) { 17, 18, 19, 20, 21, 22 };398}399 400// CHECK: define{{.*}} i56 @ret_s7()401struct s7 ret_s7(void) {402 return (struct s7) { 17, 18, 19, 20, 21, 22, 23 };403}404 405// CHECK: define{{.*}} i64 @ret_s8()406struct s8 ret_s8(void) {407 return (struct s8) { 17, 18, 19, 20, 21, 22, 23, 24 };408}409 410// CHECK: define{{.*}} { i64, i64 } @ret_s9()411struct s9 ret_s9(void) {412 return (struct s9) { 17, 18, 19, 20, 21, 22, 23, 24, 25 };413}414 415// CHECK: define{{.*}} { i64, i64 } @ret_s16()416struct s16 ret_s16(void) {417 return (struct s16) { 17, 18, 19, 20, 21, 22, 23, 24,418 25, 26, 27, 28, 29, 30, 31, 32 };419}420 421// CHECK: define{{.*}} void @ret_s17(ptr422struct s17 ret_s17(void) {423 return (struct s17) { 17, 18, 19, 20, 21, 22, 23, 24,424 25, 26, 27, 28, 29, 30, 31, 32, 33 };425}426 427