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