1 ; RUN: llc < %s -march=arm64 -mcpu=cyclone -enable-misched=false | FileCheck %s 2 ; RUN: llc < %s -O0 | FileCheck -check-prefix=FAST %s 3 target triple = "arm64-apple-darwin" 4 5 ; rdar://12648441 6 ; Generated from arm64-arguments.c with -O2. 7 ; Test passing structs with size < 8, < 16 and > 16 8 ; with alignment of 16 and without 9 10 ; Structs with size < 8 11 %struct.s38 = type { i32, i16 } 12 ; With alignment of 16, the size will be padded to multiple of 16 bytes. 13 %struct.s39 = type { i32, i16, [10 x i8] } 14 ; Structs with size < 16 15 %struct.s40 = type { i32, i16, i32, i16 } 16 %struct.s41 = type { i32, i16, i32, i16 } 17 ; Structs with size > 16 18 %struct.s42 = type { i32, i16, i32, i16, i32, i16 } 19 %struct.s43 = type { i32, i16, i32, i16, i32, i16, [10 x i8] } 20 21 @g38 = common global %struct.s38 zeroinitializer, align 4 22 @g38_2 = common global %struct.s38 zeroinitializer, align 4 23 @g39 = common global %struct.s39 zeroinitializer, align 16 24 @g39_2 = common global %struct.s39 zeroinitializer, align 16 25 @g40 = common global %struct.s40 zeroinitializer, align 4 26 @g40_2 = common global %struct.s40 zeroinitializer, align 4 27 @g41 = common global %struct.s41 zeroinitializer, align 16 28 @g41_2 = common global %struct.s41 zeroinitializer, align 16 29 @g42 = common global %struct.s42 zeroinitializer, align 4 30 @g42_2 = common global %struct.s42 zeroinitializer, align 4 31 @g43 = common global %struct.s43 zeroinitializer, align 16 32 @g43_2 = common global %struct.s43 zeroinitializer, align 16 33 34 ; structs with size < 8 bytes, passed via i64 in x1 and x2 35 define i32 @f38(i32 %i, i64 %s1.coerce, i64 %s2.coerce) #0 { 36 entry: 37 ; CHECK-LABEL: f38 38 ; CHECK: add w[[A:[0-9]+]], w1, w0 39 ; CHECK: add {{w[0-9]+}}, w[[A]], w2 40 %s1.sroa.0.0.extract.trunc = trunc i64 %s1.coerce to i32 41 %s1.sroa.1.4.extract.shift = lshr i64 %s1.coerce, 32 42 %s2.sroa.0.0.extract.trunc = trunc i64 %s2.coerce to i32 43 %s2.sroa.1.4.extract.shift = lshr i64 %s2.coerce, 32 44 %sext8 = shl nuw nsw i64 %s1.sroa.1.4.extract.shift, 16 45 %sext = trunc i64 %sext8 to i32 46 %conv = ashr exact i32 %sext, 16 47 %sext1011 = shl nuw nsw i64 %s2.sroa.1.4.extract.shift, 16 48 %sext10 = trunc i64 %sext1011 to i32 49 %conv6 = ashr exact i32 %sext10, 16 50 %add = add i32 %s1.sroa.0.0.extract.trunc, %i 51 %add3 = add i32 %add, %s2.sroa.0.0.extract.trunc 52 %add4 = add i32 %add3, %conv 53 %add7 = add i32 %add4, %conv6 54 ret i32 %add7 55 } 56 57 define i32 @caller38() #1 { 58 entry: 59 ; CHECK-LABEL: caller38 60 ; CHECK: ldr x1, 61 ; CHECK: ldr x2, 62 %0 = load i64, i64* bitcast (%struct.s38* @g38 to i64*), align 4 63 %1 = load i64, i64* bitcast (%struct.s38* @g38_2 to i64*), align 4 64 %call = tail call i32 @f38(i32 3, i64 %0, i64 %1) #5 65 ret i32 %call 66 } 67 68 declare i32 @f38_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 69 i32 %i7, i32 %i8, i32 %i9, i64 %s1.coerce, i64 %s2.coerce) #0 70 71 ; structs with size < 8 bytes, passed on stack at [sp+8] and [sp+16] 72 ; i9 at [sp] 73 define i32 @caller38_stack() #1 { 74 entry: 75 ; CHECK-LABEL: caller38_stack 76 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #8] 77 ; CHECK: movz w[[C:[0-9]+]], #0x9 78 ; CHECK: str w[[C]], [sp] 79 %0 = load i64, i64* bitcast (%struct.s38* @g38 to i64*), align 4 80 %1 = load i64, i64* bitcast (%struct.s38* @g38_2 to i64*), align 4 81 %call = tail call i32 @f38_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, 82 i32 7, i32 8, i32 9, i64 %0, i64 %1) #5 83 ret i32 %call 84 } 85 86 ; structs with size < 8 bytes, alignment of 16 87 ; passed via i128 in x1 and x3 88 define i32 @f39(i32 %i, i128 %s1.coerce, i128 %s2.coerce) #0 { 89 entry: 90 ; CHECK-LABEL: f39 91 ; CHECK: add w[[A:[0-9]+]], w1, w0 92 ; CHECK: add {{w[0-9]+}}, w[[A]], w3 93 %s1.sroa.0.0.extract.trunc = trunc i128 %s1.coerce to i32 94 %s1.sroa.1.4.extract.shift = lshr i128 %s1.coerce, 32 95 %s2.sroa.0.0.extract.trunc = trunc i128 %s2.coerce to i32 96 %s2.sroa.1.4.extract.shift = lshr i128 %s2.coerce, 32 97 %sext8 = shl nuw nsw i128 %s1.sroa.1.4.extract.shift, 16 98 %sext = trunc i128 %sext8 to i32 99 %conv = ashr exact i32 %sext, 16 100 %sext1011 = shl nuw nsw i128 %s2.sroa.1.4.extract.shift, 16 101 %sext10 = trunc i128 %sext1011 to i32 102 %conv6 = ashr exact i32 %sext10, 16 103 %add = add i32 %s1.sroa.0.0.extract.trunc, %i 104 %add3 = add i32 %add, %s2.sroa.0.0.extract.trunc 105 %add4 = add i32 %add3, %conv 106 %add7 = add i32 %add4, %conv6 107 ret i32 %add7 108 } 109 110 define i32 @caller39() #1 { 111 entry: 112 ; CHECK-LABEL: caller39 113 ; CHECK: ldp x1, x2, 114 ; CHECK: ldp x3, x4, 115 %0 = load i128, i128* bitcast (%struct.s39* @g39 to i128*), align 16 116 %1 = load i128, i128* bitcast (%struct.s39* @g39_2 to i128*), align 16 117 %call = tail call i32 @f39(i32 3, i128 %0, i128 %1) #5 118 ret i32 %call 119 } 120 121 declare i32 @f39_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 122 i32 %i7, i32 %i8, i32 %i9, i128 %s1.coerce, i128 %s2.coerce) #0 123 124 ; structs with size < 8 bytes, alignment 16 125 ; passed on stack at [sp+16] and [sp+32] 126 define i32 @caller39_stack() #1 { 127 entry: 128 ; CHECK-LABEL: caller39_stack 129 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #32] 130 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16] 131 ; CHECK: movz w[[C:[0-9]+]], #0x9 132 ; CHECK: str w[[C]], [sp] 133 %0 = load i128, i128* bitcast (%struct.s39* @g39 to i128*), align 16 134 %1 = load i128, i128* bitcast (%struct.s39* @g39_2 to i128*), align 16 135 %call = tail call i32 @f39_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, 136 i32 7, i32 8, i32 9, i128 %0, i128 %1) #5 137 ret i32 %call 138 } 139 140 ; structs with size < 16 bytes 141 ; passed via i128 in x1 and x3 142 define i32 @f40(i32 %i, [2 x i64] %s1.coerce, [2 x i64] %s2.coerce) #0 { 143 entry: 144 ; CHECK-LABEL: f40 145 ; CHECK: add w[[A:[0-9]+]], w1, w0 146 ; CHECK: add {{w[0-9]+}}, w[[A]], w3 147 %s1.coerce.fca.0.extract = extractvalue [2 x i64] %s1.coerce, 0 148 %s2.coerce.fca.0.extract = extractvalue [2 x i64] %s2.coerce, 0 149 %s1.sroa.0.0.extract.trunc = trunc i64 %s1.coerce.fca.0.extract to i32 150 %s2.sroa.0.0.extract.trunc = trunc i64 %s2.coerce.fca.0.extract to i32 151 %s1.sroa.0.4.extract.shift = lshr i64 %s1.coerce.fca.0.extract, 32 152 %sext8 = shl nuw nsw i64 %s1.sroa.0.4.extract.shift, 16 153 %sext = trunc i64 %sext8 to i32 154 %conv = ashr exact i32 %sext, 16 155 %s2.sroa.0.4.extract.shift = lshr i64 %s2.coerce.fca.0.extract, 32 156 %sext1011 = shl nuw nsw i64 %s2.sroa.0.4.extract.shift, 16 157 %sext10 = trunc i64 %sext1011 to i32 158 %conv6 = ashr exact i32 %sext10, 16 159 %add = add i32 %s1.sroa.0.0.extract.trunc, %i 160 %add3 = add i32 %add, %s2.sroa.0.0.extract.trunc 161 %add4 = add i32 %add3, %conv 162 %add7 = add i32 %add4, %conv6 163 ret i32 %add7 164 } 165 166 define i32 @caller40() #1 { 167 entry: 168 ; CHECK-LABEL: caller40 169 ; CHECK: ldp x1, x2, 170 ; CHECK: ldp x3, x4, 171 %0 = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40 to [2 x i64]*), align 4 172 %1 = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40_2 to [2 x i64]*), align 4 173 %call = tail call i32 @f40(i32 3, [2 x i64] %0, [2 x i64] %1) #5 174 ret i32 %call 175 } 176 177 declare i32 @f40_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 178 i32 %i7, i32 %i8, i32 %i9, [2 x i64] %s1.coerce, [2 x i64] %s2.coerce) #0 179 180 ; structs with size < 16 bytes 181 ; passed on stack at [sp+8] and [sp+24] 182 define i32 @caller40_stack() #1 { 183 entry: 184 ; CHECK-LABEL: caller40_stack 185 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #24] 186 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #8] 187 ; CHECK: movz w[[C:[0-9]+]], #0x9 188 ; CHECK: str w[[C]], [sp] 189 %0 = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40 to [2 x i64]*), align 4 190 %1 = load [2 x i64], [2 x i64]* bitcast (%struct.s40* @g40_2 to [2 x i64]*), align 4 191 %call = tail call i32 @f40_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, 192 i32 7, i32 8, i32 9, [2 x i64] %0, [2 x i64] %1) #5 193 ret i32 %call 194 } 195 196 ; structs with size < 16 bytes, alignment of 16 197 ; passed via i128 in x1 and x3 198 define i32 @f41(i32 %i, i128 %s1.coerce, i128 %s2.coerce) #0 { 199 entry: 200 ; CHECK-LABEL: f41 201 ; CHECK: add w[[A:[0-9]+]], w1, w0 202 ; CHECK: add {{w[0-9]+}}, w[[A]], w3 203 %s1.sroa.0.0.extract.trunc = trunc i128 %s1.coerce to i32 204 %s1.sroa.1.4.extract.shift = lshr i128 %s1.coerce, 32 205 %s2.sroa.0.0.extract.trunc = trunc i128 %s2.coerce to i32 206 %s2.sroa.1.4.extract.shift = lshr i128 %s2.coerce, 32 207 %sext8 = shl nuw nsw i128 %s1.sroa.1.4.extract.shift, 16 208 %sext = trunc i128 %sext8 to i32 209 %conv = ashr exact i32 %sext, 16 210 %sext1011 = shl nuw nsw i128 %s2.sroa.1.4.extract.shift, 16 211 %sext10 = trunc i128 %sext1011 to i32 212 %conv6 = ashr exact i32 %sext10, 16 213 %add = add i32 %s1.sroa.0.0.extract.trunc, %i 214 %add3 = add i32 %add, %s2.sroa.0.0.extract.trunc 215 %add4 = add i32 %add3, %conv 216 %add7 = add i32 %add4, %conv6 217 ret i32 %add7 218 } 219 220 define i32 @caller41() #1 { 221 entry: 222 ; CHECK-LABEL: caller41 223 ; CHECK: ldp x1, x2, 224 ; CHECK: ldp x3, x4, 225 %0 = load i128, i128* bitcast (%struct.s41* @g41 to i128*), align 16 226 %1 = load i128, i128* bitcast (%struct.s41* @g41_2 to i128*), align 16 227 %call = tail call i32 @f41(i32 3, i128 %0, i128 %1) #5 228 ret i32 %call 229 } 230 231 declare i32 @f41_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 232 i32 %i7, i32 %i8, i32 %i9, i128 %s1.coerce, i128 %s2.coerce) #0 233 234 ; structs with size < 16 bytes, alignment of 16 235 ; passed on stack at [sp+16] and [sp+32] 236 define i32 @caller41_stack() #1 { 237 entry: 238 ; CHECK-LABEL: caller41_stack 239 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #32] 240 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16] 241 ; CHECK: movz w[[C:[0-9]+]], #0x9 242 ; CHECK: str w[[C]], [sp] 243 %0 = load i128, i128* bitcast (%struct.s41* @g41 to i128*), align 16 244 %1 = load i128, i128* bitcast (%struct.s41* @g41_2 to i128*), align 16 245 %call = tail call i32 @f41_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, 246 i32 7, i32 8, i32 9, i128 %0, i128 %1) #5 247 ret i32 %call 248 } 249 250 ; structs with size of 22 bytes, passed indirectly in x1 and x2 251 define i32 @f42(i32 %i, %struct.s42* nocapture %s1, %struct.s42* nocapture %s2) #2 { 252 entry: 253 ; CHECK-LABEL: f42 254 ; CHECK: ldr w[[A:[0-9]+]], [x1] 255 ; CHECK: ldr w[[B:[0-9]+]], [x2] 256 ; CHECK: add w[[C:[0-9]+]], w[[A]], w0 257 ; CHECK: add {{w[0-9]+}}, w[[C]], w[[B]] 258 ; FAST: f42 259 ; FAST: ldr w[[A:[0-9]+]], [x1] 260 ; FAST: ldr w[[B:[0-9]+]], [x2] 261 ; FAST: add w[[C:[0-9]+]], w[[A]], w0 262 ; FAST: add {{w[0-9]+}}, w[[C]], w[[B]] 263 %i1 = getelementptr inbounds %struct.s42, %struct.s42* %s1, i64 0, i32 0 264 %0 = load i32, i32* %i1, align 4, !tbaa !0 265 %i2 = getelementptr inbounds %struct.s42, %struct.s42* %s2, i64 0, i32 0 266 %1 = load i32, i32* %i2, align 4, !tbaa !0 267 %s = getelementptr inbounds %struct.s42, %struct.s42* %s1, i64 0, i32 1 268 %2 = load i16, i16* %s, align 2, !tbaa !3 269 %conv = sext i16 %2 to i32 270 %s5 = getelementptr inbounds %struct.s42, %struct.s42* %s2, i64 0, i32 1 271 %3 = load i16, i16* %s5, align 2, !tbaa !3 272 %conv6 = sext i16 %3 to i32 273 %add = add i32 %0, %i 274 %add3 = add i32 %add, %1 275 %add4 = add i32 %add3, %conv 276 %add7 = add i32 %add4, %conv6 277 ret i32 %add7 278 } 279 280 ; For s1, we allocate a 22-byte space, pass its address via x1 281 define i32 @caller42() #3 { 282 entry: 283 ; CHECK-LABEL: caller42 284 ; CHECK: str {{x[0-9]+}}, [sp, #48] 285 ; CHECK: str {{q[0-9]+}}, [sp, #32] 286 ; CHECK: str {{x[0-9]+}}, [sp, #16] 287 ; CHECK: str {{q[0-9]+}}, [sp] 288 ; CHECK: add x1, sp, #32 289 ; CHECK: mov x2, sp 290 ; Space for s1 is allocated at sp+32 291 ; Space for s2 is allocated at sp 292 293 ; FAST-LABEL: caller42 294 ; FAST: sub sp, sp, #96 295 ; Space for s1 is allocated at fp-24 = sp+72 296 ; Space for s2 is allocated at sp+48 297 ; FAST: sub x[[A:[0-9]+]], x29, #24 298 ; FAST: add x[[A:[0-9]+]], sp, #48 299 ; Call memcpy with size = 24 (0x18) 300 ; FAST: orr {{x[0-9]+}}, xzr, #0x18 301 %tmp = alloca %struct.s42, align 4 302 %tmp1 = alloca %struct.s42, align 4 303 %0 = bitcast %struct.s42* %tmp to i8* 304 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%struct.s42* @g42 to i8*), i64 24, i32 4, i1 false), !tbaa.struct !4 305 %1 = bitcast %struct.s42* %tmp1 to i8* 306 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast (%struct.s42* @g42_2 to i8*), i64 24, i32 4, i1 false), !tbaa.struct !4 307 %call = call i32 @f42(i32 3, %struct.s42* %tmp, %struct.s42* %tmp1) #5 308 ret i32 %call 309 } 310 311 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) #4 312 313 declare i32 @f42_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 314 i32 %i7, i32 %i8, i32 %i9, %struct.s42* nocapture %s1, 315 %struct.s42* nocapture %s2) #2 316 317 define i32 @caller42_stack() #3 { 318 entry: 319 ; CHECK-LABEL: caller42_stack 320 ; CHECK: mov x29, sp 321 ; CHECK: sub sp, sp, #96 322 ; CHECK: stur {{x[0-9]+}}, [x29, #-16] 323 ; CHECK: stur {{q[0-9]+}}, [x29, #-32] 324 ; CHECK: str {{x[0-9]+}}, [sp, #48] 325 ; CHECK: str {{q[0-9]+}}, [sp, #32] 326 ; Space for s1 is allocated at x29-32 = sp+64 327 ; Space for s2 is allocated at sp+32 328 ; CHECK: add x[[B:[0-9]+]], sp, #32 329 ; CHECK: str x[[B]], [sp, #16] 330 ; CHECK: sub x[[A:[0-9]+]], x29, #32 331 ; Address of s1 is passed on stack at sp+8 332 ; CHECK: str x[[A]], [sp, #8] 333 ; CHECK: movz w[[C:[0-9]+]], #0x9 334 ; CHECK: str w[[C]], [sp] 335 336 ; FAST-LABEL: caller42_stack 337 ; Space for s1 is allocated at fp-24 338 ; Space for s2 is allocated at fp-48 339 ; FAST: sub x[[A:[0-9]+]], x29, #24 340 ; FAST: sub x[[B:[0-9]+]], x29, #48 341 ; Call memcpy with size = 24 (0x18) 342 ; FAST: orr {{x[0-9]+}}, xzr, #0x18 343 ; FAST: str {{w[0-9]+}}, [sp] 344 ; Address of s1 is passed on stack at sp+8 345 ; FAST: str {{x[0-9]+}}, [sp, #8] 346 ; FAST: str {{x[0-9]+}}, [sp, #16] 347 %tmp = alloca %struct.s42, align 4 348 %tmp1 = alloca %struct.s42, align 4 349 %0 = bitcast %struct.s42* %tmp to i8* 350 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%struct.s42* @g42 to i8*), i64 24, i32 4, i1 false), !tbaa.struct !4 351 %1 = bitcast %struct.s42* %tmp1 to i8* 352 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast (%struct.s42* @g42_2 to i8*), i64 24, i32 4, i1 false), !tbaa.struct !4 353 %call = call i32 @f42_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, 354 i32 8, i32 9, %struct.s42* %tmp, %struct.s42* %tmp1) #5 355 ret i32 %call 356 } 357 358 ; structs with size of 22 bytes, alignment of 16 359 ; passed indirectly in x1 and x2 360 define i32 @f43(i32 %i, %struct.s43* nocapture %s1, %struct.s43* nocapture %s2) #2 { 361 entry: 362 ; CHECK-LABEL: f43 363 ; CHECK: ldr w[[A:[0-9]+]], [x1] 364 ; CHECK: ldr w[[B:[0-9]+]], [x2] 365 ; CHECK: add w[[C:[0-9]+]], w[[A]], w0 366 ; CHECK: add {{w[0-9]+}}, w[[C]], w[[B]] 367 ; FAST-LABEL: f43 368 ; FAST: ldr w[[A:[0-9]+]], [x1] 369 ; FAST: ldr w[[B:[0-9]+]], [x2] 370 ; FAST: add w[[C:[0-9]+]], w[[A]], w0 371 ; FAST: add {{w[0-9]+}}, w[[C]], w[[B]] 372 %i1 = getelementptr inbounds %struct.s43, %struct.s43* %s1, i64 0, i32 0 373 %0 = load i32, i32* %i1, align 4, !tbaa !0 374 %i2 = getelementptr inbounds %struct.s43, %struct.s43* %s2, i64 0, i32 0 375 %1 = load i32, i32* %i2, align 4, !tbaa !0 376 %s = getelementptr inbounds %struct.s43, %struct.s43* %s1, i64 0, i32 1 377 %2 = load i16, i16* %s, align 2, !tbaa !3 378 %conv = sext i16 %2 to i32 379 %s5 = getelementptr inbounds %struct.s43, %struct.s43* %s2, i64 0, i32 1 380 %3 = load i16, i16* %s5, align 2, !tbaa !3 381 %conv6 = sext i16 %3 to i32 382 %add = add i32 %0, %i 383 %add3 = add i32 %add, %1 384 %add4 = add i32 %add3, %conv 385 %add7 = add i32 %add4, %conv6 386 ret i32 %add7 387 } 388 389 define i32 @caller43() #3 { 390 entry: 391 ; CHECK-LABEL: caller43 392 ; CHECK: str {{q[0-9]+}}, [sp, #48] 393 ; CHECK: str {{q[0-9]+}}, [sp, #32] 394 ; CHECK: str {{q[0-9]+}}, [sp, #16] 395 ; CHECK: str {{q[0-9]+}}, [sp] 396 ; CHECK: add x1, sp, #32 397 ; CHECK: mov x2, sp 398 ; Space for s1 is allocated at sp+32 399 ; Space for s2 is allocated at sp 400 401 ; FAST-LABEL: caller43 402 ; FAST: mov x29, sp 403 ; Space for s1 is allocated at sp+32 404 ; Space for s2 is allocated at sp 405 ; FAST: add x1, sp, #32 406 ; FAST: mov x2, sp 407 ; FAST: str {{x[0-9]+}}, [sp, #32] 408 ; FAST: str {{x[0-9]+}}, [sp, #40] 409 ; FAST: str {{x[0-9]+}}, [sp, #48] 410 ; FAST: str {{x[0-9]+}}, [sp, #56] 411 ; FAST: str {{x[0-9]+}}, [sp] 412 ; FAST: str {{x[0-9]+}}, [sp, #8] 413 ; FAST: str {{x[0-9]+}}, [sp, #16] 414 ; FAST: str {{x[0-9]+}}, [sp, #24] 415 %tmp = alloca %struct.s43, align 16 416 %tmp1 = alloca %struct.s43, align 16 417 %0 = bitcast %struct.s43* %tmp to i8* 418 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%struct.s43* @g43 to i8*), i64 32, i32 16, i1 false), !tbaa.struct !4 419 %1 = bitcast %struct.s43* %tmp1 to i8* 420 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast (%struct.s43* @g43_2 to i8*), i64 32, i32 16, i1 false), !tbaa.struct !4 421 %call = call i32 @f43(i32 3, %struct.s43* %tmp, %struct.s43* %tmp1) #5 422 ret i32 %call 423 } 424 425 declare i32 @f43_stack(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 426 i32 %i7, i32 %i8, i32 %i9, %struct.s43* nocapture %s1, 427 %struct.s43* nocapture %s2) #2 428 429 define i32 @caller43_stack() #3 { 430 entry: 431 ; CHECK-LABEL: caller43_stack 432 ; CHECK: mov x29, sp 433 ; CHECK: sub sp, sp, #96 434 ; CHECK: stur {{q[0-9]+}}, [x29, #-16] 435 ; CHECK: stur {{q[0-9]+}}, [x29, #-32] 436 ; CHECK: str {{q[0-9]+}}, [sp, #48] 437 ; CHECK: str {{q[0-9]+}}, [sp, #32] 438 ; Space for s1 is allocated at x29-32 = sp+64 439 ; Space for s2 is allocated at sp+32 440 ; CHECK: add x[[B:[0-9]+]], sp, #32 441 ; CHECK: str x[[B]], [sp, #16] 442 ; CHECK: sub x[[A:[0-9]+]], x29, #32 443 ; Address of s1 is passed on stack at sp+8 444 ; CHECK: str x[[A]], [sp, #8] 445 ; CHECK: movz w[[C:[0-9]+]], #0x9 446 ; CHECK: str w[[C]], [sp] 447 448 ; FAST-LABEL: caller43_stack 449 ; FAST: sub sp, sp, #96 450 ; Space for s1 is allocated at fp-32 = sp+64 451 ; Space for s2 is allocated at sp+32 452 ; FAST: sub x[[A:[0-9]+]], x29, #32 453 ; FAST: add x[[B:[0-9]+]], sp, #32 454 ; FAST: stur {{x[0-9]+}}, [x29, #-32] 455 ; FAST: stur {{x[0-9]+}}, [x29, #-24] 456 ; FAST: stur {{x[0-9]+}}, [x29, #-16] 457 ; FAST: stur {{x[0-9]+}}, [x29, #-8] 458 ; FAST: str {{x[0-9]+}}, [sp, #32] 459 ; FAST: str {{x[0-9]+}}, [sp, #40] 460 ; FAST: str {{x[0-9]+}}, [sp, #48] 461 ; FAST: str {{x[0-9]+}}, [sp, #56] 462 ; FAST: str {{w[0-9]+}}, [sp] 463 ; Address of s1 is passed on stack at sp+8 464 ; FAST: str {{x[0-9]+}}, [sp, #8] 465 ; FAST: str {{x[0-9]+}}, [sp, #16] 466 %tmp = alloca %struct.s43, align 16 467 %tmp1 = alloca %struct.s43, align 16 468 %0 = bitcast %struct.s43* %tmp to i8* 469 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%struct.s43* @g43 to i8*), i64 32, i32 16, i1 false), !tbaa.struct !4 470 %1 = bitcast %struct.s43* %tmp1 to i8* 471 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast (%struct.s43* @g43_2 to i8*), i64 32, i32 16, i1 false), !tbaa.struct !4 472 %call = call i32 @f43_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, 473 i32 8, i32 9, %struct.s43* %tmp, %struct.s43* %tmp1) #5 474 ret i32 %call 475 } 476 477 ; rdar://13668927 478 ; Check that we don't split an i128. 479 declare i32 @callee_i128_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, 480 i32 %i6, i32 %i7, i128 %s1, i32 %i8) 481 482 define i32 @i128_split() { 483 entry: 484 ; CHECK-LABEL: i128_split 485 ; "i128 %0" should be on stack at [sp]. 486 ; "i32 8" should be on stack at [sp, #16]. 487 ; CHECK: str {{w[0-9]+}}, [sp, #16] 488 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp] 489 ; FAST-LABEL: i128_split 490 ; FAST: sub sp, sp 491 ; FAST: mov x[[ADDR:[0-9]+]], sp 492 ; FAST: str {{w[0-9]+}}, [x[[ADDR]], #16] 493 ; Load/Store opt is disabled with -O0, so the i128 is split. 494 ; FAST: str {{x[0-9]+}}, [x[[ADDR]], #8] 495 ; FAST: str {{x[0-9]+}}, [x[[ADDR]]] 496 %0 = load i128, i128* bitcast (%struct.s41* @g41 to i128*), align 16 497 %call = tail call i32 @callee_i128_split(i32 1, i32 2, i32 3, i32 4, i32 5, 498 i32 6, i32 7, i128 %0, i32 8) #5 499 ret i32 %call 500 } 501 502 declare i32 @callee_i64(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, 503 i32 %i6, i32 %i7, i64 %s1, i32 %i8) 504 505 define i32 @i64_split() { 506 entry: 507 ; CHECK-LABEL: i64_split 508 ; "i64 %0" should be in register x7. 509 ; "i32 8" should be on stack at [sp]. 510 ; CHECK: ldr x7, [{{x[0-9]+}}] 511 ; CHECK: str {{w[0-9]+}}, [sp, #-16]! 512 ; FAST-LABEL: i64_split 513 ; FAST: ldr x7, [{{x[0-9]+}}] 514 ; FAST: mov x[[R0:[0-9]+]], sp 515 ; FAST: orr w[[R1:[0-9]+]], wzr, #0x8 516 ; FAST: str w[[R1]], {{\[}}x[[R0]]{{\]}} 517 %0 = load i64, i64* bitcast (%struct.s41* @g41 to i64*), align 16 518 %call = tail call i32 @callee_i64(i32 1, i32 2, i32 3, i32 4, i32 5, 519 i32 6, i32 7, i64 %0, i32 8) #5 520 ret i32 %call 521 } 522 523 attributes #0 = { noinline nounwind readnone "fp-contract-model"="standard" "relocation-model"="pic" "ssp-buffers-size"="8" } 524 attributes #1 = { nounwind readonly "fp-contract-model"="standard" "relocation-model"="pic" "ssp-buffers-size"="8" } 525 attributes #2 = { noinline nounwind readonly "fp-contract-model"="standard" "relocation-model"="pic" "ssp-buffers-size"="8" } 526 attributes #3 = { nounwind "fp-contract-model"="standard" "relocation-model"="pic" "ssp-buffers-size"="8" } 527 attributes #4 = { nounwind } 528 attributes #5 = { nobuiltin } 529 530 !0 = !{!"int", !1} 531 !1 = !{!"omnipotent char", !2} 532 !2 = !{!"Simple C/C++ TBAA"} 533 !3 = !{!"short", !1} 534 !4 = !{i64 0, i64 4, !0, i64 4, i64 2, !3, i64 8, i64 4, !0, i64 12, i64 2, !3, i64 16, i64 4, !0, i64 20, i64 2, !3} 535