c294dee40135a63db5f3864d836794daa6974a42
[oota-llvm.git] / test / CodeGen / X86 / cmpxchg-clobber-flags.ll
1 ; RUN: llc -mtriple=i386-linux-gnu %s -o - | FileCheck %s -check-prefix=i386
2 ; RUN: llc -mtriple=i386-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=i386f
3
4 ; RUN: llc -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s -check-prefix=x8664
5 ; RUN: llc -mtriple=x86_64-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664
6 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s -check-prefix=x8664-sahf
7 ; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664-sahf
8 ; RUN: llc -mtriple=x86_64-linux-gnu -mcpu=corei7 %s -o - | FileCheck %s -check-prefix=x8664-sahf
9
10 ; FIXME: X86InstrInfo::copyPhysReg had code which figured out whether AX was
11 ;        live or not to avoid save / restore when it's not needed. See FIXME in
12 ;        that function for more details on which the code is currently
13 ;        disabled. The extra push/pop are marked below and can be removed once
14 ;        the issue is fixed.
15 ;        -verify-machineinstrs should also be added back in the RUN lines above.
16
17 declare i32 @foo()
18 declare i32 @bar(i64)
19
20 define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) {
21 ; i386-LABEL: test_intervening_call:
22 ; i386: cmpxchg8b
23 ; i386-NEXT: pushl %eax
24 ; i386-NEXT: seto %al
25 ; i386-NEXT: lahf
26 ; i386-NEXT: movl %eax, [[FLAGS:%.*]]
27 ; i386-NEXT: popl %eax
28 ; i386-NEXT: movl %edx, 4(%esp)
29 ; i386-NEXT: movl %eax, (%esp)
30 ; i386-NEXT: calll bar
31 ; ** FIXME Next line isn't actually necessary. **
32 ; i386-NEXT: pushl %eax
33 ; i386-NEXT: movl [[FLAGS]], %eax
34 ; i386-NEXT: addb $127, %al
35 ; i386-NEXT: sahf
36 ; ** FIXME Next line isn't actually necessary. **
37 ; i386-NEXT: popl %eax
38 ; i386-NEXT: jne
39
40 ; i386f-LABEL: test_intervening_call:
41 ; i386f: cmpxchg8b
42 ; i386f-NEXT: movl %eax, (%esp)
43 ; i386f-NEXT: movl %edx, 4(%esp)
44 ; ** FIXME Next line isn't actually necessary. **
45 ; i386f-NEXT: pushl %eax
46 ; i386f-NEXT: seto %al
47 ; i386f-NEXT: lahf
48 ; i386f-NEXT: movl %eax, [[FLAGS:%.*]]
49 ; ** FIXME Next line isn't actually necessary. **
50 ; i386f-NEXT: popl %eax
51 ; i386f-NEXT: calll bar
52 ; ** FIXME Next line isn't actually necessary. **
53 ; i386f-NEXT: pushl %eax
54 ; i386f-NEXT: movl [[FLAGS]], %eax
55 ; i386f-NEXT: addb $127, %al
56 ; i386f-NEXT: sahf
57 ; ** FIXME Next line isn't actually necessary. **
58 ; i386f-NEXT: popl %eax
59 ; i386f-NEXT: jne
60
61 ; x8664-LABEL: test_intervening_call:
62 ; x8664: cmpxchgq
63 ; x8664: pushfq
64 ; x8664-NEXT: popq [[FLAGS:%.*]]
65 ; x8664-NEXT: movq %rax, %rdi
66 ; x8664-NEXT: callq bar
67 ; x8664-NEXT: pushq [[FLAGS]]
68 ; x8664-NEXT: popfq
69 ; x8664-NEXT: jne
70
71 ; x8664-sahf-LABEL: test_intervening_call:
72 ; x8664-sahf: cmpxchgq
73 ; x8664-sahf: pushq %rax
74 ; x8664-sahf-NEXT: seto %al
75 ; x8664-sahf-NEXT: lahf
76 ; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]]
77 ; x8664-sahf-NEXT: popq %rax
78 ; x8664-sahf-NEXT: movq %rax, %rdi
79 ; x8664-sahf-NEXT: callq bar
80 ; ** FIXME Next line isn't actually necessary. **
81 ; x8664-sahf-NEXT: pushq %rax
82 ; x8664-sahf-NEXT: movq [[FLAGS]], %rax
83 ; x8664-sahf-NEXT: addb $127, %al
84 ; x8664-sahf-NEXT: sahf
85 ; ** FIXME Next line isn't actually necessary. **
86 ; x8664-sahf-NEXT: popq %rax
87 ; x8664-sahf-NEXT: jne
88
89   %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
90   %v = extractvalue { i64, i1 } %cx, 0
91   %p = extractvalue { i64, i1 } %cx, 1
92   call i32 @bar(i64 %v)
93   br i1 %p, label %t, label %f
94
95 t:
96   ret i64 42
97
98 f:
99   ret i64 0
100 }
101
102 ; Interesting in producing a clobber without any function calls.
103 define i32 @test_control_flow(i32* %p, i32 %i, i32 %j) {
104 ; i386-LABEL: test_control_flow:
105 ; i386: cmpxchg
106 ; i386-NEXT: jne
107
108 ; i386f-LABEL: test_control_flow:
109 ; i386f: cmpxchg
110 ; i386f-NEXT: jne
111
112 ; x8664-LABEL: test_control_flow:
113 ; x8664: cmpxchg
114 ; x8664-NEXT: jne
115
116 ; x8664-sahf-LABEL: test_control_flow:
117 ; x8664-sahf: cmpxchg
118 ; x8664-sahf-NEXT: jne
119
120 entry:
121   %cmp = icmp sgt i32 %i, %j
122   br i1 %cmp, label %loop_start, label %cond.end
123
124 loop_start:
125   br label %while.condthread-pre-split.i
126
127 while.condthread-pre-split.i:
128   %.pr.i = load i32, i32* %p, align 4
129   br label %while.cond.i
130
131 while.cond.i:
132   %0 = phi i32 [ %.pr.i, %while.condthread-pre-split.i ], [ 0, %while.cond.i ]
133   %tobool.i = icmp eq i32 %0, 0
134   br i1 %tobool.i, label %while.cond.i, label %while.body.i
135
136 while.body.i:
137   %.lcssa = phi i32 [ %0, %while.cond.i ]
138   %1 = cmpxchg i32* %p, i32 %.lcssa, i32 %.lcssa seq_cst seq_cst
139   %2 = extractvalue { i32, i1 } %1, 1
140   br i1 %2, label %cond.end.loopexit, label %while.condthread-pre-split.i
141
142 cond.end.loopexit:
143   br label %cond.end
144
145 cond.end:
146   %cond = phi i32 [ %i, %entry ], [ 0, %cond.end.loopexit ]
147   ret i32 %cond
148 }
149
150 ; This one is an interesting case because CMOV doesn't have a chain
151 ; operand. Naive attempts to limit cmpxchg EFLAGS use are likely to fail here.
152 define i32 @test_feed_cmov(i32* %addr, i32 %desired, i32 %new) {
153 ; i386-LABEL: test_feed_cmov:
154 ; i386: cmpxchgl
155 ; ** FIXME Next line isn't actually necessary. **
156 ; i386-NEXT: pushl %eax
157 ; i386-NEXT: seto %al
158 ; i386-NEXT: lahf
159 ; i386-NEXT: movl %eax, [[FLAGS:%.*]]
160 ; ** FIXME Next line isn't actually necessary. **
161 ; i386-NEXT: popl %eax
162 ; i386-NEXT: calll foo
163 ; i386-NEXT: pushl %eax
164 ; i386-NEXT: movl [[FLAGS]], %eax
165 ; i386-NEXT: addb $127, %al
166 ; i386-NEXT: sahf
167 ; i386-NEXT: popl %eax
168
169 ; i386f-LABEL: test_feed_cmov:
170 ; i386f: cmpxchgl
171 ; ** FIXME Next line isn't actually necessary. **
172 ; i386f-NEXT: pushl %eax
173 ; i386f-NEXT: seto %al
174 ; i386f-NEXT: lahf
175 ; i386f-NEXT: movl %eax, [[FLAGS:%.*]]
176 ; ** FIXME Next line isn't actually necessary. **
177 ; i386f-NEXT: popl %eax
178 ; i386f-NEXT: calll foo
179 ; i386f-NEXT: pushl %eax
180 ; i386f-NEXT: movl [[FLAGS]], %eax
181 ; i386f-NEXT: addb $127, %al
182 ; i386f-NEXT: sahf
183 ; i386f-NEXT: popl %eax
184
185 ; x8664-LABEL: test_feed_cmov:
186 ; x8664: cmpxchg
187 ; x8664: pushfq
188 ; x8664-NEXT: popq [[FLAGS:%.*]]
189 ; x8664-NEXT: callq foo
190 ; x8664-NEXT: pushq [[FLAGS]]
191 ; x8664-NEXT: popfq
192
193 ; x8664-sahf-LABEL: test_feed_cmov:
194 ; x8664-sahf: cmpxchgl
195 ; ** FIXME Next line isn't actually necessary. **
196 ; x8664-sahf: pushq %rax
197 ; x8664-sahf: seto %al
198 ; x8664-sahf-NEXT: lahf
199 ; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]]
200 ; ** FIXME Next line isn't actually necessary. **
201 ; x8664-sahf-NEXT: popq %rax
202 ; x8664-sahf-NEXT: callq foo
203 ; x8664-sahf-NEXT: pushq %rax
204 ; x8664-sahf-NEXT: movq [[FLAGS]], %rax
205 ; x8664-sahf-NEXT: addb $127, %al
206 ; x8664-sahf-NEXT: sahf
207 ; x8664-sahf-NEXT: popq %rax
208
209   %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
210   %success = extractvalue { i32, i1 } %res, 1
211
212   %rhs = call i32 @foo()
213
214   %ret = select i1 %success, i32 %new, i32 %rhs
215   ret i32 %ret
216 }