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