[X86, Win64] Use a frame pointer if pushf is emitted
[oota-llvm.git] / test / CodeGen / X86 / win64_frame.ll
1 ; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefix=CHECK --check-prefix=PUSHF
2 ; RUN: llc < %s -mtriple=x86_64-pc-win32 -mattr=+sahf | FileCheck %s --check-prefix=SAHF
3
4 define i32 @f1(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) "no-frame-pointer-elim"="true" {
5   ; CHECK-LABEL: f1:
6   ; CHECK:       movl    48(%rbp), %eax
7   ret i32 %p5
8 }
9
10 define void @f2(i32 %p, ...) "no-frame-pointer-elim"="true" {
11   ; CHECK-LABEL: f2:
12   ; CHECK:      .seh_stackalloc 8
13   ; CHECK:      movq    %rsp, %rbp
14   ; CHECK:      .seh_setframe 5, 0
15   ; CHECK:      movq    %rdx, 32(%rbp)
16   ; CHECK:      leaq    32(%rbp), %rax
17   %ap = alloca i8, align 8
18   call void @llvm.va_start(i8* %ap)
19   ret void
20 }
21
22 define i8* @f3() "no-frame-pointer-elim"="true" {
23   ; CHECK-LABEL: f3:
24   ; CHECK:      movq    %rsp, %rbp
25   ; CHECK:      .seh_setframe 5, 0
26   ; CHECK:      movq    8(%rbp), %rax
27   %ra = call i8* @llvm.returnaddress(i32 0)
28   ret i8* %ra
29 }
30
31 define i8* @f4() "no-frame-pointer-elim"="true" {
32   ; CHECK-LABEL: f4:
33   ; CHECK:      pushq   %rbp
34   ; CHECK:      .seh_pushreg 5
35   ; CHECK:      subq    $304, %rsp
36   ; CHECK:      .seh_stackalloc 304
37   ; CHECK:      leaq    128(%rsp), %rbp
38   ; CHECK:      .seh_setframe 5, 128
39   ; CHECK:      .seh_endprologue
40   ; CHECK:      movq    184(%rbp), %rax
41   alloca [300 x i8]
42   %ra = call i8* @llvm.returnaddress(i32 0)
43   ret i8* %ra
44 }
45
46 declare void @external(i8*)
47
48 define void @f5() "no-frame-pointer-elim"="true" {
49   ; CHECK-LABEL: f5:
50   ; CHECK:      subq    $336, %rsp
51   ; CHECK:      .seh_stackalloc 336
52   ; CHECK:      leaq    128(%rsp), %rbp
53   ; CHECK:      .seh_setframe 5, 128
54   ; CHECK:      leaq    -92(%rbp), %rcx
55   ; CHECK:      callq   external
56   %a = alloca [300 x i8]
57   %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
58   call void @external(i8* %gep)
59   ret void
60 }
61
62 define void @f6(i32 %p, ...) "no-frame-pointer-elim"="true" {
63   ; CHECK-LABEL: f6:
64   ; CHECK:      subq    $336, %rsp
65   ; CHECK:      .seh_stackalloc 336
66   ; CHECK:      leaq    128(%rsp), %rbp
67   ; CHECK:      .seh_setframe 5, 128
68   ; CHECK:      leaq    -92(%rbp), %rcx
69   ; CHECK:      callq   external
70   %a = alloca [300 x i8]
71   %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
72   call void @external(i8* %gep)
73   ret void
74 }
75
76 define i32 @f7(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "no-frame-pointer-elim"="true" {
77   ; CHECK-LABEL: f7:
78   ; CHECK:      pushq   %rbp
79   ; CHECK:      .seh_pushreg 5
80   ; CHECK:      subq    $304, %rsp
81   ; CHECK:      .seh_stackalloc 304
82   ; CHECK:      leaq    128(%rsp), %rbp
83   ; CHECK:      .seh_setframe 5, 128
84   ; CHECK:      andq    $-64, %rsp
85   ; CHECK:      movl    224(%rbp), %eax
86   ; CHECK:      leaq    176(%rbp), %rsp
87   alloca [300 x i8], align 64
88   ret i32 %e
89 }
90
91 define i32 @f8(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "no-frame-pointer-elim"="true" {
92   ; CHECK-LABEL: f8:
93   ; CHECK:        subq    $352, %rsp
94   ; CHECK:        .seh_stackalloc 352
95   ; CHECK:        leaq    128(%rsp), %rbp
96   ; CHECK:        .seh_setframe 5, 128
97
98   %alloca = alloca [300 x i8], align 64
99   ; CHECK:        andq    $-64, %rsp
100   ; CHECK:        movq    %rsp, %rbx
101
102   alloca i32, i32 %a
103   ; CHECK:        movl    %ecx, %eax
104   ; CHECK:        leaq    15(,%rax,4), %rcx
105   ; CHECK:        movabsq $34359738352, %rax
106   ; CHECK:        andq    %rcx, %rax
107   ; CHECK:        callq   __chkstk
108   ; CHECK:        subq    %rax, %rsp
109
110   %gep = getelementptr [300 x i8], [300 x i8]* %alloca, i32 0, i32 0
111   call void @external(i8* %gep)
112   ; CHECK:        subq    $32, %rsp
113   ; CHECK:        leaq    (%rbx), %rcx
114   ; CHECK:        callq   external
115   ; CHECK:        addq    $32, %rsp
116
117   ret i32 %e
118   ; CHECK:        movl    %esi, %eax
119   ; CHECK:        leaq    224(%rbp), %rsp
120 }
121
122 define i64 @f9() {
123 entry:
124   ; CHECK-LABEL: f9:
125   ; CHECK:      pushq   %rbp
126   ; CHECK:      .seh_pushreg 5
127   ; CHECK-NEXT: movq    %rsp, %rbp
128   ; CHECK:      .seh_setframe 5, 0
129   ; CHECK:      .seh_endprologue
130
131   %call = call i64 asm sideeffect "pushf\0A\09popq $0\0A", "=r,~{dirflag},~{fpsr},~{flags}"()
132   ; CHECK-NEXT: #APP
133   ; CHECK-NEXT: pushfq
134   ; CHECK-NEXT: popq    %rax
135   ; CHECK:      #NO_APP
136
137   ret i64 %call
138   ; CHECK-NEXT: popq    %rbp
139   ; CHECK-NEXT: retq
140 }
141
142 declare i64 @dummy()
143
144 define i64 @f10(i64* %foo, i64 %bar, i64 %baz) {
145   ; CHECK-LABEL: f10:
146   ; CHECK:      pushq   %rbp
147   ; CHECK:      .seh_pushreg 5
148   ; CHECK:      pushq   %rsi
149   ; CHECK:      .seh_pushreg 6
150   ; CHECK:      pushq   %rdi
151   ; CHECK:      .seh_pushreg 7
152   ; CHECK:      subq    $32, %rsp
153   ; CHECK:      .seh_stackalloc 32
154   ; CHECK:      leaq    32(%rsp), %rbp
155   ; CHECK:      .seh_setframe 5, 32
156   ; CHECK:      .seh_endprologue
157
158   %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
159   ; PUSHF:      lock cmpxchgq
160   ; PUSHF-NEXT: pushfq
161   ; PUSHF-NEXT: popq %[[REG:.*]]
162   ; SAHF:       lock cmpxchgq
163   ; SAHF-NEXT:  seto    %al
164   ; SAHF-NEXT:  lahf
165
166   %v = extractvalue { i64, i1 } %cx, 0
167   %p = extractvalue { i64, i1 } %cx, 1
168
169   %call = call i64 @dummy()
170   ; PUSHF:      callq dummy
171   ; PUSHF-NEXT: pushq %[[REG]]
172   ; PUSHF-NEXT: popfq
173   ; SAHF:       callq dummy
174   ; SAHF-NEXT:  pushq
175   ; SAHF:       addb $127, %al
176   ; SAHF-NEXT:  sahf
177   ; SAHF-NEXT:  popq
178
179   %sel = select i1 %p, i64 %call, i64 %bar
180   ; CHECK-NEXT: cmovneq
181
182   ret i64 %sel
183   ; CHECK-NEXT: addq    $32, %rsp
184   ; CHECK-NEXT: popq    %rdi
185   ; CHECK-NEXT: popq    %rsi
186   ; CHECK-NEXT: popq    %rbp
187 }
188
189 declare i8* @llvm.returnaddress(i32) nounwind readnone
190
191 declare void @llvm.va_start(i8*) nounwind