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