1; RUN: llc < %s -march=arm64 -mcpu=cyclone -enable-misched=false | FileCheck %s 2target triple = "arm64-apple-ios7.0.0" 3 4; rdar://13625505 5; Here we have 9 fixed integer arguments the 9th argument in on stack, the 6; varargs start right after at 8-byte alignment. 7define void @fn9(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8, i32 %a9, ...) nounwind noinline ssp { 8; CHECK-LABEL: fn9: 9; 9th fixed argument 10; CHECK: ldr {{w[0-9]+}}, [sp, #64] 11; CHECK: add [[ARGS:x[0-9]+]], sp, #72 12; CHECK: add {{x[0-9]+}}, [[ARGS]], #8 13; First vararg 14; CHECK: ldr {{w[0-9]+}}, [sp, #72] 15; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #8 16; Second vararg 17; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}] 18; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #8 19; Third vararg 20; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}] 21 %1 = alloca i32, align 4 22 %2 = alloca i32, align 4 23 %3 = alloca i32, align 4 24 %4 = alloca i32, align 4 25 %5 = alloca i32, align 4 26 %6 = alloca i32, align 4 27 %7 = alloca i32, align 4 28 %8 = alloca i32, align 4 29 %9 = alloca i32, align 4 30 %args = alloca i8*, align 8 31 %a10 = alloca i32, align 4 32 %a11 = alloca i32, align 4 33 %a12 = alloca i32, align 4 34 store i32 %a1, i32* %1, align 4 35 store i32 %a2, i32* %2, align 4 36 store i32 %a3, i32* %3, align 4 37 store i32 %a4, i32* %4, align 4 38 store i32 %a5, i32* %5, align 4 39 store i32 %a6, i32* %6, align 4 40 store i32 %a7, i32* %7, align 4 41 store i32 %a8, i32* %8, align 4 42 store i32 %a9, i32* %9, align 4 43 %10 = bitcast i8** %args to i8* 44 call void @llvm.va_start(i8* %10) 45 %11 = va_arg i8** %args, i32 46 store i32 %11, i32* %a10, align 4 47 %12 = va_arg i8** %args, i32 48 store i32 %12, i32* %a11, align 4 49 %13 = va_arg i8** %args, i32 50 store i32 %13, i32* %a12, align 4 51 ret void 52} 53 54declare void @llvm.va_start(i8*) nounwind 55 56define i32 @main() nounwind ssp { 57; CHECK-LABEL: main: 58; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16] 59; CHECK: str {{x[0-9]+}}, [sp, #8] 60; CHECK: str {{w[0-9]+}}, [sp] 61 %a1 = alloca i32, align 4 62 %a2 = alloca i32, align 4 63 %a3 = alloca i32, align 4 64 %a4 = alloca i32, align 4 65 %a5 = alloca i32, align 4 66 %a6 = alloca i32, align 4 67 %a7 = alloca i32, align 4 68 %a8 = alloca i32, align 4 69 %a9 = alloca i32, align 4 70 %a10 = alloca i32, align 4 71 %a11 = alloca i32, align 4 72 %a12 = alloca i32, align 4 73 store i32 1, i32* %a1, align 4 74 store i32 2, i32* %a2, align 4 75 store i32 3, i32* %a3, align 4 76 store i32 4, i32* %a4, align 4 77 store i32 5, i32* %a5, align 4 78 store i32 6, i32* %a6, align 4 79 store i32 7, i32* %a7, align 4 80 store i32 8, i32* %a8, align 4 81 store i32 9, i32* %a9, align 4 82 store i32 10, i32* %a10, align 4 83 store i32 11, i32* %a11, align 4 84 store i32 12, i32* %a12, align 4 85 %1 = load i32, i32* %a1, align 4 86 %2 = load i32, i32* %a2, align 4 87 %3 = load i32, i32* %a3, align 4 88 %4 = load i32, i32* %a4, align 4 89 %5 = load i32, i32* %a5, align 4 90 %6 = load i32, i32* %a6, align 4 91 %7 = load i32, i32* %a7, align 4 92 %8 = load i32, i32* %a8, align 4 93 %9 = load i32, i32* %a9, align 4 94 %10 = load i32, i32* %a10, align 4 95 %11 = load i32, i32* %a11, align 4 96 %12 = load i32, i32* %a12, align 4 97 call void (i32, i32, i32, i32, i32, i32, i32, i32, i32, ...) @fn9(i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12) 98 ret i32 0 99} 100 101;rdar://13668483 102@.str = private unnamed_addr constant [4 x i8] c"fmt\00", align 1 103define void @foo(i8* %fmt, ...) nounwind { 104entry: 105; CHECK-LABEL: foo: 106; CHECK: orr {{x[0-9]+}}, {{x[0-9]+}}, #0x8 107; CHECK: ldr {{w[0-9]+}}, [sp, #48] 108; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #15 109; CHECK: and x[[ADDR:[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0 110; CHECK: ldr {{q[0-9]+}}, [x[[ADDR]]] 111 %fmt.addr = alloca i8*, align 8 112 %args = alloca i8*, align 8 113 %vc = alloca i32, align 4 114 %vv = alloca <4 x i32>, align 16 115 store i8* %fmt, i8** %fmt.addr, align 8 116 %args1 = bitcast i8** %args to i8* 117 call void @llvm.va_start(i8* %args1) 118 %0 = va_arg i8** %args, i32 119 store i32 %0, i32* %vc, align 4 120 %1 = va_arg i8** %args, <4 x i32> 121 store <4 x i32> %1, <4 x i32>* %vv, align 16 122 ret void 123} 124 125define void @bar(i32 %x, <4 x i32> %y) nounwind { 126entry: 127; CHECK-LABEL: bar: 128; CHECK: stp {{q[0-9]+}}, {{q[0-9]+}}, [sp, #16] 129; CHECK: str {{x[0-9]+}}, [sp] 130 %x.addr = alloca i32, align 4 131 %y.addr = alloca <4 x i32>, align 16 132 store i32 %x, i32* %x.addr, align 4 133 store <4 x i32> %y, <4 x i32>* %y.addr, align 16 134 %0 = load i32, i32* %x.addr, align 4 135 %1 = load <4 x i32>, <4 x i32>* %y.addr, align 16 136 call void (i8*, ...) @foo(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %0, <4 x i32> %1) 137 ret void 138} 139 140; rdar://13668927 141; When passing 16-byte aligned small structs as vararg, make sure the caller 142; side is 16-byte aligned on stack. 143%struct.s41 = type { i32, i16, i32, i16 } 144define void @foo2(i8* %fmt, ...) nounwind { 145entry: 146; CHECK-LABEL: foo2: 147; CHECK: orr {{x[0-9]+}}, {{x[0-9]+}}, #0x8 148; CHECK: ldr {{w[0-9]+}}, [sp, #48] 149; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #15 150; CHECK: and x[[ADDR:[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0 151; CHECK: ldr {{q[0-9]+}}, [x[[ADDR]]] 152 %fmt.addr = alloca i8*, align 8 153 %args = alloca i8*, align 8 154 %vc = alloca i32, align 4 155 %vs = alloca %struct.s41, align 16 156 store i8* %fmt, i8** %fmt.addr, align 8 157 %args1 = bitcast i8** %args to i8* 158 call void @llvm.va_start(i8* %args1) 159 %0 = va_arg i8** %args, i32 160 store i32 %0, i32* %vc, align 4 161 %ap.cur = load i8*, i8** %args 162 %1 = getelementptr i8, i8* %ap.cur, i32 15 163 %2 = ptrtoint i8* %1 to i64 164 %3 = and i64 %2, -16 165 %ap.align = inttoptr i64 %3 to i8* 166 %ap.next = getelementptr i8, i8* %ap.align, i32 16 167 store i8* %ap.next, i8** %args 168 %4 = bitcast i8* %ap.align to %struct.s41* 169 %5 = bitcast %struct.s41* %vs to i8* 170 %6 = bitcast %struct.s41* %4 to i8* 171 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %6, i64 16, i32 16, i1 false) 172 ret void 173} 174declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind 175 176define void @bar2(i32 %x, i128 %s41.coerce) nounwind { 177entry: 178; CHECK-LABEL: bar2: 179; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16] 180; CHECK: str {{x[0-9]+}}, [sp] 181 %x.addr = alloca i32, align 4 182 %s41 = alloca %struct.s41, align 16 183 store i32 %x, i32* %x.addr, align 4 184 %0 = bitcast %struct.s41* %s41 to i128* 185 store i128 %s41.coerce, i128* %0, align 1 186 %1 = load i32, i32* %x.addr, align 4 187 %2 = bitcast %struct.s41* %s41 to i128* 188 %3 = load i128, i128* %2, align 1 189 call void (i8*, ...) @foo2(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1, i128 %3) 190 ret void 191} 192