1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-pc-win32              | FileCheck %s
3; RUN: llc < %s -mtriple=x86_64-pc-win32 -mattr=+sahf | FileCheck %s
4
5define i32 @f1(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) "frame-pointer"="all" {
6; CHECK-LABEL: f1:
7; CHECK:       # %bb.0:
8; CHECK-NEXT:    pushq %rbp
9; CHECK-NEXT:    .seh_pushreg %rbp
10; CHECK-NEXT:    movq %rsp, %rbp
11; CHECK-NEXT:    .seh_setframe %rbp, 0
12; CHECK-NEXT:    .seh_endprologue
13; CHECK-NEXT:    movl 48(%rbp), %eax
14; CHECK-NEXT:    popq %rbp
15; CHECK-NEXT:    retq
16; CHECK-NEXT:    .seh_endproc
17  ret i32 %p5
18}
19
20define void @f2(i32 %p, ...) "frame-pointer"="all" {
21; CHECK-LABEL: f2:
22; CHECK:       # %bb.0:
23; CHECK-NEXT:    pushq %rbp
24; CHECK-NEXT:    .seh_pushreg %rbp
25; CHECK-NEXT:    pushq %rax
26; CHECK-NEXT:    .seh_stackalloc 8
27; CHECK-NEXT:    movq %rsp, %rbp
28; CHECK-NEXT:    .seh_setframe %rbp, 0
29; CHECK-NEXT:    .seh_endprologue
30; CHECK-NEXT:    movq %rdx, 32(%rbp)
31; CHECK-NEXT:    movq %r8, 40(%rbp)
32; CHECK-NEXT:    movq %r9, 48(%rbp)
33; CHECK-NEXT:    leaq 32(%rbp), %rax
34; CHECK-NEXT:    movq %rax, (%rbp)
35; CHECK-NEXT:    addq $8, %rsp
36; CHECK-NEXT:    popq %rbp
37; CHECK-NEXT:    retq
38; CHECK-NEXT:    .seh_endproc
39  %ap = alloca i8, align 8
40  call void @llvm.va_start(i8* %ap)
41  ret void
42}
43
44define i8* @f3() "frame-pointer"="all" {
45; CHECK-LABEL: f3:
46; CHECK:       # %bb.0:
47; CHECK-NEXT:    pushq %rbp
48; CHECK-NEXT:    .seh_pushreg %rbp
49; CHECK-NEXT:    movq %rsp, %rbp
50; CHECK-NEXT:    .seh_setframe %rbp, 0
51; CHECK-NEXT:    .seh_endprologue
52; CHECK-NEXT:    movq 8(%rbp), %rax
53; CHECK-NEXT:    popq %rbp
54; CHECK-NEXT:    retq
55; CHECK-NEXT:    .seh_endproc
56  %ra = call i8* @llvm.returnaddress(i32 0)
57  ret i8* %ra
58}
59
60define i8* @f4() "frame-pointer"="all" {
61; CHECK-LABEL: f4:
62; CHECK:       # %bb.0:
63; CHECK-NEXT:    pushq %rbp
64; CHECK-NEXT:    .seh_pushreg %rbp
65; CHECK-NEXT:    subq $304, %rsp # imm = 0x130
66; CHECK-NEXT:    .seh_stackalloc 304
67; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rbp
68; CHECK-NEXT:    .seh_setframe %rbp, 128
69; CHECK-NEXT:    .seh_endprologue
70; CHECK-NEXT:    movq 184(%rbp), %rax
71; CHECK-NEXT:    addq $304, %rsp # imm = 0x130
72; CHECK-NEXT:    popq %rbp
73; CHECK-NEXT:    retq
74; CHECK-NEXT:    .seh_endproc
75  alloca [300 x i8]
76  %ra = call i8* @llvm.returnaddress(i32 0)
77  ret i8* %ra
78}
79
80declare void @external(i8*)
81
82define void @f5() "frame-pointer"="all" {
83; CHECK-LABEL: f5:
84; CHECK:       # %bb.0:
85; CHECK-NEXT:    pushq %rbp
86; CHECK-NEXT:    .seh_pushreg %rbp
87; CHECK-NEXT:    subq $336, %rsp # imm = 0x150
88; CHECK-NEXT:    .seh_stackalloc 336
89; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rbp
90; CHECK-NEXT:    .seh_setframe %rbp, 128
91; CHECK-NEXT:    .seh_endprologue
92; CHECK-NEXT:    leaq -92(%rbp), %rcx
93; CHECK-NEXT:    callq external
94; CHECK-NEXT:    nop
95; CHECK-NEXT:    addq $336, %rsp # imm = 0x150
96; CHECK-NEXT:    popq %rbp
97; CHECK-NEXT:    retq
98; CHECK-NEXT:    .seh_endproc
99  %a = alloca [300 x i8]
100  %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
101  call void @external(i8* %gep)
102  ret void
103}
104
105define void @f6(i32 %p, ...) "frame-pointer"="all" {
106; CHECK-LABEL: f6:
107; CHECK:       # %bb.0:
108; CHECK-NEXT:    pushq %rbp
109; CHECK-NEXT:    .seh_pushreg %rbp
110; CHECK-NEXT:    subq $336, %rsp # imm = 0x150
111; CHECK-NEXT:    .seh_stackalloc 336
112; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rbp
113; CHECK-NEXT:    .seh_setframe %rbp, 128
114; CHECK-NEXT:    .seh_endprologue
115; CHECK-NEXT:    leaq -92(%rbp), %rcx
116; CHECK-NEXT:    callq external
117; CHECK-NEXT:    nop
118; CHECK-NEXT:    addq $336, %rsp # imm = 0x150
119; CHECK-NEXT:    popq %rbp
120; CHECK-NEXT:    retq
121; CHECK-NEXT:    .seh_endproc
122  %a = alloca [300 x i8]
123  %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
124  call void @external(i8* %gep)
125  ret void
126}
127
128define i32 @f7(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "frame-pointer"="all" {
129; CHECK-LABEL: f7:
130; CHECK:       # %bb.0:
131; CHECK-NEXT:    pushq %rbp
132; CHECK-NEXT:    .seh_pushreg %rbp
133; CHECK-NEXT:    subq $304, %rsp # imm = 0x130
134; CHECK-NEXT:    .seh_stackalloc 304
135; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rbp
136; CHECK-NEXT:    .seh_setframe %rbp, 128
137; CHECK-NEXT:    .seh_endprologue
138; CHECK-NEXT:    andq $-64, %rsp
139; CHECK-NEXT:    movl 224(%rbp), %eax
140; CHECK-NEXT:    leaq 176(%rbp), %rsp
141; CHECK-NEXT:    popq %rbp
142; CHECK-NEXT:    retq
143; CHECK-NEXT:    .seh_endproc
144  alloca [300 x i8], align 64
145  ret i32 %e
146}
147
148define i32 @f8(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "frame-pointer"="all" {
149; CHECK-LABEL: f8:
150; CHECK:       # %bb.0:
151; CHECK-NEXT:    pushq %rbp
152; CHECK-NEXT:    .seh_pushreg %rbp
153; CHECK-NEXT:    pushq %rsi
154; CHECK-NEXT:    .seh_pushreg %rsi
155; CHECK-NEXT:    pushq %rbx
156; CHECK-NEXT:    .seh_pushreg %rbx
157; CHECK-NEXT:    subq $352, %rsp # imm = 0x160
158; CHECK-NEXT:    .seh_stackalloc 352
159; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rbp
160; CHECK-NEXT:    .seh_setframe %rbp, 128
161; CHECK-NEXT:    .seh_endprologue
162; CHECK-NEXT:    andq $-64, %rsp
163; CHECK-NEXT:    movq %rsp, %rbx
164; CHECK-NEXT:    movl 288(%rbp), %esi
165; CHECK-NEXT:    movl %ecx, %eax
166; CHECK-NEXT:    leaq 15(,%rax,4), %rax
167; CHECK-NEXT:    andq $-16, %rax
168; CHECK-NEXT:    callq __chkstk
169; CHECK-NEXT:    subq %rax, %rsp
170; CHECK-NEXT:    subq $32, %rsp
171; CHECK-NEXT:    movq %rbx, %rcx
172; CHECK-NEXT:    callq external
173; CHECK-NEXT:    addq $32, %rsp
174; CHECK-NEXT:    movl %esi, %eax
175; CHECK-NEXT:    leaq 224(%rbp), %rsp
176; CHECK-NEXT:    popq %rbx
177; CHECK-NEXT:    popq %rsi
178; CHECK-NEXT:    popq %rbp
179; CHECK-NEXT:    retq
180; CHECK-NEXT:    .seh_endproc
181  %alloca = alloca [300 x i8], align 64
182  alloca i32, i32 %a
183  %gep = getelementptr [300 x i8], [300 x i8]* %alloca, i32 0, i32 0
184  call void @external(i8* %gep)
185  ret i32 %e
186}
187
188define i64 @f9() {
189; CHECK-LABEL: f9:
190; CHECK:       # %bb.0: # %entry
191; CHECK-NEXT:    pushq %rbp
192; CHECK-NEXT:    .seh_pushreg %rbp
193; CHECK-NEXT:    movq %rsp, %rbp
194; CHECK-NEXT:    .seh_setframe %rbp, 0
195; CHECK-NEXT:    .seh_endprologue
196; CHECK-NEXT:    pushfq
197; CHECK-NEXT:    popq %rax
198; CHECK-NEXT:    popq %rbp
199; CHECK-NEXT:    retq
200; CHECK-NEXT:    .seh_endproc
201entry:
202  %call = call i64 @llvm.x86.flags.read.u64()
203  ret i64 %call
204}
205
206declare i64 @dummy()
207
208define i64 @f10(i64* %foo, i64 %bar, i64 %baz) {
209; CHECK-LABEL: f10:
210; CHECK:       # %bb.0:
211; CHECK-NEXT:    pushq %rsi
212; CHECK-NEXT:    .seh_pushreg %rsi
213; CHECK-NEXT:    pushq %rbx
214; CHECK-NEXT:    .seh_pushreg %rbx
215; CHECK-NEXT:    subq $40, %rsp
216; CHECK-NEXT:    .seh_stackalloc 40
217; CHECK-NEXT:    .seh_endprologue
218; CHECK-NEXT:    movq %rdx, %rsi
219; CHECK-NEXT:    movq %rdx, %rax
220; CHECK-NEXT:    lock cmpxchgq %r8, (%rcx)
221; CHECK-NEXT:    sete %bl
222; CHECK-NEXT:    callq dummy
223; CHECK-NEXT:    testb %bl, %bl
224; CHECK-NEXT:    cmoveq %rsi, %rax
225; CHECK-NEXT:    addq $40, %rsp
226; CHECK-NEXT:    popq %rbx
227; CHECK-NEXT:    popq %rsi
228; CHECK-NEXT:    retq
229; CHECK-NEXT:    .seh_endproc
230  %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
231  %v = extractvalue { i64, i1 } %cx, 0
232  %p = extractvalue { i64, i1 } %cx, 1
233  %call = call i64 @dummy()
234  %sel = select i1 %p, i64 %call, i64 %bar
235  ret i64 %sel
236}
237
238define i8* @f11() "frame-pointer"="all" {
239; CHECK-LABEL: f11:
240; CHECK:       # %bb.0:
241; CHECK-NEXT:    pushq %rbp
242; CHECK-NEXT:    .seh_pushreg %rbp
243; CHECK-NEXT:    movq %rsp, %rbp
244; CHECK-NEXT:    .seh_setframe %rbp, 0
245; CHECK-NEXT:    .seh_endprologue
246; CHECK-NEXT:    leaq 8(%rbp), %rax
247; CHECK-NEXT:    popq %rbp
248; CHECK-NEXT:    retq
249; CHECK-NEXT:    .seh_endproc
250  %aora = call i8* @llvm.addressofreturnaddress()
251  ret i8* %aora
252}
253
254define i8* @f12() {
255; CHECK-LABEL: f12:
256; CHECK:       # %bb.0:
257; CHECK-NEXT:    movq %rsp, %rax
258; CHECK-NEXT:    retq
259  %aora = call i8* @llvm.addressofreturnaddress()
260  ret i8* %aora
261}
262
263declare i8* @llvm.returnaddress(i32) nounwind readnone
264declare i8* @llvm.addressofreturnaddress() nounwind readnone
265declare i64 @llvm.x86.flags.read.u64()
266declare void @llvm.va_start(i8*) nounwind
267