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 %s 2 // 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 %s 3 4 // Test float returns and params. 5 6 // CHECK: define{{.*}} float @func_p1(float noundef %x) 7 float func_p1(float x) { return x; } 8 9 // CHECK: define{{.*}} double @func_p2(double noundef %x) 10 double func_p2(double x) { return x; } 11 12 // CHECK: define{{.*}} ppc_fp128 @func_p3(ppc_fp128 noundef %x) 13 long double func_p3(long double x) { return x; } 14 15 // Test homogeneous float aggregate passing and returning. 16 17 struct f1 { float f[1]; }; 18 struct f2 { float f[2]; }; 19 struct f3 { float f[3]; }; 20 struct f4 { float f[4]; }; 21 struct f5 { float f[5]; }; 22 struct f6 { float f[6]; }; 23 struct f7 { float f[7]; }; 24 struct f8 { float f[8]; }; 25 struct f9 { float f[9]; }; 26 27 struct fab { float a; float b; }; 28 struct fabc { float a; float b; float c; }; 29 30 struct 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(%struct.f1* noalias sret(%struct.f1) align 4 %agg.result, float inreg %x.coerce) 34 struct 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(%struct.f2* noalias sret(%struct.f2) align 4 %agg.result, i64 %x.coerce) 38 struct 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(%struct.f3* noalias sret(%struct.f3) align 4 %agg.result, [2 x i64] %x.coerce) 42 struct 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(%struct.f4* noalias sret(%struct.f4) align 4 %agg.result, [2 x i64] %x.coerce) 46 struct f4 func_f4(struct f4 x) { return x; } 47 48 // CHECK: define{{.*}} void @func_f5(%struct.f5* noalias sret(%struct.f5) align 4 %agg.result, [3 x i64] %x.coerce) 49 struct f5 func_f5(struct f5 x) { return x; } 50 51 // CHECK: define{{.*}} void @func_f6(%struct.f6* noalias sret(%struct.f6) align 4 %agg.result, [3 x i64] %x.coerce) 52 struct f6 func_f6(struct f6 x) { return x; } 53 54 // CHECK: define{{.*}} void @func_f7(%struct.f7* noalias sret(%struct.f7) align 4 %agg.result, [4 x i64] %x.coerce) 55 struct f7 func_f7(struct f7 x) { return x; } 56 57 // CHECK: define{{.*}} void @func_f8(%struct.f8* noalias sret(%struct.f8) align 4 %agg.result, [4 x i64] %x.coerce) 58 struct f8 func_f8(struct f8 x) { return x; } 59 60 // CHECK: define{{.*}} void @func_f9(%struct.f9* noalias sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce) 61 struct 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(%struct.fab* noalias sret(%struct.fab) align 4 %agg.result, i64 %x.coerce) 65 struct 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(%struct.fabc* noalias sret(%struct.fabc) align 4 %agg.result, [2 x i64] %x.coerce) 69 struct 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(%struct.f2a2b* noalias sret(%struct.f2a2b) align 4 %agg.result, [2 x i64] %x.coerce) 73 struct f2a2b func_f2a2b(struct f2a2b x) { return x; } 74 75 // CHECK-LABEL: @call_f1 76 // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f1, align 4 77 // CHECK: %[[TMP:[^ ]+]] = load float, float* getelementptr inbounds (%struct.f1, %struct.f1* @global_f1, i32 0, i32 0, i32 0), align 4 78 // CHECK-LE: call i32 @func_f1(float inreg %[[TMP]]) 79 // CHECK-BE: call void @func_f1(%struct.f1* sret(%struct.f1) align 4 %[[TMP0]], float inreg %[[TMP]]) 80 struct f1 global_f1; 81 void call_f1(void) { global_f1 = func_f1(global_f1); } 82 83 // CHECK-LABEL: @call_f2 84 // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f2, align 4 85 // CHECK: %[[TMP:[^ ]+]] = load i64, i64* bitcast (%struct.f2* @global_f2 to i64*), align 4 86 // CHECK-LE: call i64 @func_f2(i64 %[[TMP]]) 87 // CHECK-BE: call void @func_f2(%struct.f2* sret(%struct.f2) align 4 %[[TMP0]], i64 %[[TMP]]) 88 struct f2 global_f2; 89 void call_f2(void) { global_f2 = func_f2(global_f2); } 90 91 // CHECK-LABEL: @call_f3 92 // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f3, align 4 93 // CHECK: %[[TMP1:[^ ]+]] = alloca [2 x i64] 94 // CHECK: %[[TMP2:[^ ]+]] = bitcast [2 x i64]* %[[TMP1]] to i8* 95 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f3* @global_f3 to i8*), i64 12, i1 false) 96 // CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], [2 x i64]* %[[TMP1]] 97 // CHECK-LE: call { i64, i64 } @func_f3([2 x i64] %[[TMP3]]) 98 // CHECK-BE: call void @func_f3(%struct.f3* sret(%struct.f3) align 4 %[[TMP0]], [2 x i64] %[[TMP3]]) 99 struct f3 global_f3; 100 void call_f3(void) { global_f3 = func_f3(global_f3); } 101 102 // CHECK-LABEL: @call_f4 103 // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f4, align 4 104 // CHECK: %[[TMP:[^ ]+]] = load [2 x i64], [2 x i64]* bitcast (%struct.f4* @global_f4 to [2 x i64]*), align 4 105 // CHECK-LE: call { i64, i64 } @func_f4([2 x i64] %[[TMP]]) 106 // CHECK-BE: call void @func_f4(%struct.f4* sret(%struct.f4) align 4 %[[TMP0]], [2 x i64] %[[TMP]]) 107 struct f4 global_f4; 108 void call_f4(void) { global_f4 = func_f4(global_f4); } 109 110 // CHECK-LABEL: @call_f5 111 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f5, align 4 112 // CHECK: %[[TMP1:[^ ]+]] = alloca [3 x i64] 113 // CHECK: %[[TMP2:[^ ]+]] = bitcast [3 x i64]* %[[TMP1]] to i8* 114 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f5* @global_f5 to i8*), i64 20, i1 false) 115 // CHECK: %[[TMP3:[^ ]+]] = load [3 x i64], [3 x i64]* %[[TMP1]] 116 // CHECK: call void @func_f5(%struct.f5* sret(%struct.f5) align 4 %[[TMP0]], [3 x i64] %[[TMP3]]) 117 struct f5 global_f5; 118 void call_f5(void) { global_f5 = func_f5(global_f5); } 119 120 // CHECK-LABEL: @call_f6 121 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f6, align 4 122 // CHECK: %[[TMP:[^ ]+]] = load [3 x i64], [3 x i64]* bitcast (%struct.f6* @global_f6 to [3 x i64]*), align 4 123 // CHECK: call void @func_f6(%struct.f6* sret(%struct.f6) align 4 %[[TMP0]], [3 x i64] %[[TMP]]) 124 struct f6 global_f6; 125 void call_f6(void) { global_f6 = func_f6(global_f6); } 126 127 // CHECK-LABEL: @call_f7 128 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f7, align 4 129 // CHECK: %[[TMP1:[^ ]+]] = alloca [4 x i64], align 8 130 // CHECK: %[[TMP2:[^ ]+]] = bitcast [4 x i64]* %[[TMP1]] to i8* 131 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f7* @global_f7 to i8*), i64 28, i1 false) 132 // CHECK: %[[TMP3:[^ ]+]] = load [4 x i64], [4 x i64]* %[[TMP1]], align 8 133 // CHECK: call void @func_f7(%struct.f7* sret(%struct.f7) align 4 %[[TMP0]], [4 x i64] %[[TMP3]]) 134 struct f7 global_f7; 135 void call_f7(void) { global_f7 = func_f7(global_f7); } 136 137 // CHECK-LABEL: @call_f8 138 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f8, align 4 139 // CHECK: %[[TMP:[^ ]+]] = load [4 x i64], [4 x i64]* bitcast (%struct.f8* @global_f8 to [4 x i64]*), align 4 140 // CHECK: call void @func_f8(%struct.f8* sret(%struct.f8) align 4 %[[TMP0]], [4 x i64] %[[TMP]]) 141 struct f8 global_f8; 142 void call_f8(void) { global_f8 = func_f8(global_f8); } 143 144 // CHECK-LABEL: @call_f9 145 // CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64] 146 // CHECK: %[[TMP2:[^ ]+]] = bitcast [5 x i64]* %[[TMP1]] to i8* 147 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.f9* @global_f9 to i8*), i64 36, i1 false) 148 // CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], [5 x i64]* %[[TMP1]] 149 // CHECK: call void @func_f9(%struct.f9* sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]]) 150 struct f9 global_f9; 151 void call_f9(void) { global_f9 = func_f9(global_f9); } 152 153 // CHECK-LABEL: @call_fab 154 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.fab, align 4 155 // CHECK: %[[TMP:[^ ]+]] = load i64, i64* bitcast (%struct.fab* @global_fab to i64*), align 4 156 // CHECK-LE: %call = call i64 @func_fab(i64 %[[TMP]]) 157 // CHECK-BE: call void @func_fab(%struct.fab* sret(%struct.fab) align 4 %[[TMP0]], i64 %[[TMP]]) 158 struct fab global_fab; 159 void call_fab(void) { global_fab = func_fab(global_fab); } 160 161 // CHECK-LABEL: @call_fabc 162 // CHECK-BE: %[[TMPX:[^ ]+]] = alloca %struct.fabc, align 4 163 // CHECK: %[[TMP0:[^ ]+]] = alloca [2 x i64], align 8 164 // CHECK: %[[TMP2:[^ ]+]] = bitcast [2 x i64]* %[[TMP0]] to i8* 165 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[TMP2]], i8* align 4 bitcast (%struct.fabc* @global_fabc to i8*), i64 12, i1 false) 166 // CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], [2 x i64]* %[[TMP0]], align 8 167 // CHECK-LE: %call = call { i64, i64 } @func_fabc([2 x i64] %[[TMP3]]) 168 // CHECK-BE: call void @func_fabc(%struct.fabc* sret(%struct.fabc) align 4 %[[TMPX]], [2 x i64] %[[TMP3]]) 169 struct fabc global_fabc; 170 void call_fabc(void) { global_fabc = func_fabc(global_fabc); } 171 172