167 lines · c
1// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-LE %s2// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-BE %s3 4// Test float returns and params.5 6// CHECK: define{{.*}} float @func_p1(float noundef %x)7float func_p1(float x) { return x; }8 9// CHECK: define{{.*}} double @func_p2(double noundef %x)10double func_p2(double x) { return x; }11 12// CHECK: define{{.*}} ppc_fp128 @func_p3(ppc_fp128 noundef %x)13long double func_p3(long double x) { return x; }14 15// Test homogeneous float aggregate passing and returning.16 17struct f1 { float f[1]; };18struct f2 { float f[2]; };19struct f3 { float f[3]; };20struct f4 { float f[4]; };21struct f5 { float f[5]; };22struct f6 { float f[6]; };23struct f7 { float f[7]; };24struct f8 { float f[8]; };25struct f9 { float f[9]; };26 27struct fab { float a; float b; };28struct fabc { float a; float b; float c; };29 30struct f2a2b { float a[2]; float b[2]; };31 32// CHECK-LE: define{{.*}} i32 @func_f1(float inreg %x.coerce)33// CHECK-BE: define{{.*}} void @func_f1(ptr dead_on_unwind noalias writable sret(%struct.f1) align 4 %agg.result, float inreg %x.coerce)34struct f1 func_f1(struct f1 x) { return x; }35 36// CHECK-LE: define{{.*}} i64 @func_f2(i64 %x.coerce)37// CHECK-BE: define{{.*}} void @func_f2(ptr dead_on_unwind noalias writable sret(%struct.f2) align 4 %agg.result, i64 %x.coerce)38struct f2 func_f2(struct f2 x) { return x; }39 40// CHECK-LE: define{{.*}} { i64, i64 } @func_f3([2 x i64] %x.coerce)41// CHECK-BE: define{{.*}} void @func_f3(ptr dead_on_unwind noalias writable sret(%struct.f3) align 4 %agg.result, [2 x i64] %x.coerce)42struct f3 func_f3(struct f3 x) { return x; }43 44// CHECK-LE: define{{.*}} { i64, i64 } @func_f4([2 x i64] %x.coerce)45// CHECK-BE: define{{.*}} void @func_f4(ptr dead_on_unwind noalias writable sret(%struct.f4) align 4 %agg.result, [2 x i64] %x.coerce)46struct f4 func_f4(struct f4 x) { return x; }47 48// CHECK: define{{.*}} void @func_f5(ptr dead_on_unwind noalias writable sret(%struct.f5) align 4 %agg.result, [3 x i64] %x.coerce)49struct f5 func_f5(struct f5 x) { return x; }50 51// CHECK: define{{.*}} void @func_f6(ptr dead_on_unwind noalias writable sret(%struct.f6) align 4 %agg.result, [3 x i64] %x.coerce)52struct f6 func_f6(struct f6 x) { return x; }53 54// CHECK: define{{.*}} void @func_f7(ptr dead_on_unwind noalias writable sret(%struct.f7) align 4 %agg.result, [4 x i64] %x.coerce)55struct f7 func_f7(struct f7 x) { return x; }56 57// CHECK: define{{.*}} void @func_f8(ptr dead_on_unwind noalias writable sret(%struct.f8) align 4 %agg.result, [4 x i64] %x.coerce)58struct f8 func_f8(struct f8 x) { return x; }59 60// CHECK: define{{.*}} void @func_f9(ptr dead_on_unwind noalias writable sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce)61struct f9 func_f9(struct f9 x) { return x; }62 63// CHECK-LE: define{{.*}} i64 @func_fab(i64 %x.coerce)64// CHECK-BE: define{{.*}} void @func_fab(ptr dead_on_unwind noalias writable sret(%struct.fab) align 4 %agg.result, i64 %x.coerce)65struct fab func_fab(struct fab x) { return x; }66 67// CHECK-LE: define{{.*}} { i64, i64 } @func_fabc([2 x i64] %x.coerce)68// CHECK-BE: define{{.*}} void @func_fabc(ptr dead_on_unwind noalias writable sret(%struct.fabc) align 4 %agg.result, [2 x i64] %x.coerce)69struct fabc func_fabc(struct fabc x) { return x; }70 71// CHECK-LE: define{{.*}} { i64, i64 } @func_f2a2b([2 x i64] %x.coerce)72// CHECK-BE: define{{.*}} void @func_f2a2b(ptr dead_on_unwind noalias writable sret(%struct.f2a2b) align 4 %agg.result, [2 x i64] %x.coerce)73struct f2a2b func_f2a2b(struct f2a2b x) { return x; }74 75// CHECK-LABEL: @call_f176// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f1, align 477// CHECK: %[[TMP:[^ ]+]] = load float, ptr @global_f1, align 478// CHECK-LE: call i32 @func_f1(float inreg %[[TMP]])79// CHECK-BE: call void @func_f1(ptr dead_on_unwind writable sret(%struct.f1) align 4 %[[TMP0]], float inreg %[[TMP]])80struct f1 global_f1;81void call_f1(void) { global_f1 = func_f1(global_f1); }82 83// CHECK-LABEL: @call_f284// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f2, align 485// CHECK: %[[TMP:[^ ]+]] = load i64, ptr @global_f2, align 486// CHECK-LE: call i64 @func_f2(i64 %[[TMP]])87// CHECK-BE: call void @func_f2(ptr dead_on_unwind writable sret(%struct.f2) align 4 %[[TMP0]], i64 %[[TMP]])88struct f2 global_f2;89void call_f2(void) { global_f2 = func_f2(global_f2); }90 91// CHECK-LABEL: @call_f392// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f3, align 493// CHECK: %[[TMP1:[^ ]+]] = alloca [2 x i64]94// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f3, i64 12, i1 false)95// CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], ptr %[[TMP1]]96// CHECK-LE: call { i64, i64 } @func_f3([2 x i64] %[[TMP3]])97// CHECK-BE: call void @func_f3(ptr dead_on_unwind writable sret(%struct.f3) align 4 %[[TMP0]], [2 x i64] %[[TMP3]])98struct f3 global_f3;99void call_f3(void) { global_f3 = func_f3(global_f3); }100 101// CHECK-LABEL: @call_f4102// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f4, align 4103// CHECK: %[[TMP:[^ ]+]] = load [2 x i64], ptr @global_f4, align 4104// CHECK-LE: call { i64, i64 } @func_f4([2 x i64] %[[TMP]])105// CHECK-BE: call void @func_f4(ptr dead_on_unwind writable sret(%struct.f4) align 4 %[[TMP0]], [2 x i64] %[[TMP]])106struct f4 global_f4;107void call_f4(void) { global_f4 = func_f4(global_f4); }108 109// CHECK-LABEL: @call_f5110// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f5, align 4111// CHECK: %[[TMP1:[^ ]+]] = alloca [3 x i64]112// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f5, i64 20, i1 false)113// CHECK: %[[TMP3:[^ ]+]] = load [3 x i64], ptr %[[TMP1]]114// CHECK: call void @func_f5(ptr dead_on_unwind writable sret(%struct.f5) align 4 %[[TMP0]], [3 x i64] %[[TMP3]])115struct f5 global_f5;116void call_f5(void) { global_f5 = func_f5(global_f5); }117 118// CHECK-LABEL: @call_f6119// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f6, align 4120// CHECK: %[[TMP:[^ ]+]] = load [3 x i64], ptr @global_f6, align 4121// CHECK: call void @func_f6(ptr dead_on_unwind writable sret(%struct.f6) align 4 %[[TMP0]], [3 x i64] %[[TMP]])122struct f6 global_f6;123void call_f6(void) { global_f6 = func_f6(global_f6); }124 125// CHECK-LABEL: @call_f7126// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f7, align 4127// CHECK: %[[TMP1:[^ ]+]] = alloca [4 x i64], align 8128// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f7, i64 28, i1 false)129// CHECK: %[[TMP3:[^ ]+]] = load [4 x i64], ptr %[[TMP1]], align 8130// CHECK: call void @func_f7(ptr dead_on_unwind writable sret(%struct.f7) align 4 %[[TMP0]], [4 x i64] %[[TMP3]])131struct f7 global_f7;132void call_f7(void) { global_f7 = func_f7(global_f7); }133 134// CHECK-LABEL: @call_f8135// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f8, align 4136// CHECK: %[[TMP:[^ ]+]] = load [4 x i64], ptr @global_f8, align 4137// CHECK: call void @func_f8(ptr dead_on_unwind writable sret(%struct.f8) align 4 %[[TMP0]], [4 x i64] %[[TMP]])138struct f8 global_f8;139void call_f8(void) { global_f8 = func_f8(global_f8); }140 141// CHECK-LABEL: @call_f9142// CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64]143// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f9, i64 36, i1 false)144// CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], ptr %[[TMP1]]145// CHECK: call void @func_f9(ptr dead_on_unwind writable sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]])146struct f9 global_f9;147void call_f9(void) { global_f9 = func_f9(global_f9); }148 149// CHECK-LABEL: @call_fab150// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.fab, align 4151// CHECK: %[[TMP:[^ ]+]] = load i64, ptr @global_fab, align 4152// CHECK-LE: %call = call i64 @func_fab(i64 %[[TMP]])153// CHECK-BE: call void @func_fab(ptr dead_on_unwind writable sret(%struct.fab) align 4 %[[TMP0]], i64 %[[TMP]])154struct fab global_fab;155void call_fab(void) { global_fab = func_fab(global_fab); }156 157// CHECK-LABEL: @call_fabc158// CHECK-BE: %[[TMPX:[^ ]+]] = alloca %struct.fabc, align 4159// CHECK: %[[TMP0:[^ ]+]] = alloca [2 x i64], align 8160// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP0]], ptr align 4 @global_fabc, i64 12, i1 false)161// CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], ptr %[[TMP0]], align 8162// CHECK-LE: %call = call { i64, i64 } @func_fabc([2 x i64] %[[TMP3]])163// CHECK-BE: call void @func_fabc(ptr dead_on_unwind writable sret(%struct.fabc) align 4 %[[TMPX]], [2 x i64] %[[TMP3]])164struct fabc global_fabc;165void call_fabc(void) { global_fabc = func_fabc(global_fabc); }166 167