• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -verify-machineinstrs -mtriple=i386-linux-gnu %s -o - | FileCheck %s -check-prefix=i386
2; RUN: llc -verify-machineinstrs -mtriple=i386-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=i386f
3
4; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s -check-prefix=x8664
5; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664
6; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu -mattr=+sahf %s -o - | FileCheck %s -check-prefix=x8664-sahf
7; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s -check-prefix=x8664-sahf
8; RUN: llc -verify-machineinstrs -mtriple=x86_64-linux-gnu -mcpu=corei7 %s -o - | FileCheck %s -check-prefix=x8664-sahf
9
10declare i32 @foo()
11declare i32 @bar(i64)
12
13define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) {
14; i386-LABEL: test_intervening_call:
15; i386: cmpxchg8b
16; i386-NEXT: pushl %eax
17; i386-NEXT: seto %al
18; i386-NEXT: lahf
19; i386-NEXT: movl %eax, [[FLAGS:%.*]]
20; i386-NEXT: popl %eax
21; i386-NEXT: movl %edx, 4(%esp)
22; i386-NEXT: movl %eax, (%esp)
23; i386-NEXT: calll bar
24; i386-NEXT: movl [[FLAGS]], %eax
25; i386-NEXT: addb $127, %al
26; i386-NEXT: sahf
27; i386-NEXT: jne
28
29; i386f-LABEL: test_intervening_call:
30; i386f: cmpxchg8b
31; i386f-NEXT: movl %eax, (%esp)
32; i386f-NEXT: movl %edx, 4(%esp)
33; i386f-NEXT: seto %al
34; i386f-NEXT: lahf
35; i386f-NEXT: movl %eax, [[FLAGS:%.*]]
36; i386f-NEXT: calll bar
37; i386f-NEXT: movl [[FLAGS]], %eax
38; i386f-NEXT: addb $127, %al
39; i386f-NEXT: sahf
40; i386f-NEXT: jne
41
42; x8664-LABEL: test_intervening_call:
43; x8664: cmpxchgq
44; x8664: pushfq
45; x8664-NEXT: popq [[FLAGS:%.*]]
46; x8664-NEXT: movq %rax, %rdi
47; x8664-NEXT: callq bar
48; x8664-NEXT: pushq [[FLAGS]]
49; x8664-NEXT: popfq
50; x8664-NEXT: jne
51
52; x8664-sahf-LABEL: test_intervening_call:
53; x8664-sahf: cmpxchgq
54; x8664-sahf: pushq %rax
55; x8664-sahf-NEXT: seto %al
56; x8664-sahf-NEXT: lahf
57; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]]
58; x8664-sahf-NEXT: popq %rax
59; x8664-sahf-NEXT: movq %rax, %rdi
60; x8664-sahf-NEXT: callq bar
61; x8664-sahf-NEXT: movq [[FLAGS]], %rax
62; x8664-sahf-NEXT: addb $127, %al
63; x8664-sahf-NEXT: sahf
64; x8664-sahf-NEXT: jne
65
66  %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
67  %v = extractvalue { i64, i1 } %cx, 0
68  %p = extractvalue { i64, i1 } %cx, 1
69  call i32 @bar(i64 %v)
70  br i1 %p, label %t, label %f
71
72t:
73  ret i64 42
74
75f:
76  ret i64 0
77}
78
79; Interesting in producing a clobber without any function calls.
80define i32 @test_control_flow(i32* %p, i32 %i, i32 %j) {
81; i386-LABEL: test_control_flow:
82; i386: cmpxchg
83; i386-NEXT: jne
84
85; i386f-LABEL: test_control_flow:
86; i386f: cmpxchg
87; i386f-NEXT: jne
88
89; x8664-LABEL: test_control_flow:
90; x8664: cmpxchg
91; x8664-NEXT: jne
92
93; x8664-sahf-LABEL: test_control_flow:
94; x8664-sahf: cmpxchg
95; x8664-sahf-NEXT: jne
96
97entry:
98  %cmp = icmp sgt i32 %i, %j
99  br i1 %cmp, label %loop_start, label %cond.end
100
101loop_start:
102  br label %while.condthread-pre-split.i
103
104while.condthread-pre-split.i:
105  %.pr.i = load i32, i32* %p, align 4
106  br label %while.cond.i
107
108while.cond.i:
109  %0 = phi i32 [ %.pr.i, %while.condthread-pre-split.i ], [ 0, %while.cond.i ]
110  %tobool.i = icmp eq i32 %0, 0
111  br i1 %tobool.i, label %while.cond.i, label %while.body.i
112
113while.body.i:
114  %.lcssa = phi i32 [ %0, %while.cond.i ]
115  %1 = cmpxchg i32* %p, i32 %.lcssa, i32 %.lcssa seq_cst seq_cst
116  %2 = extractvalue { i32, i1 } %1, 1
117  br i1 %2, label %cond.end.loopexit, label %while.condthread-pre-split.i
118
119cond.end.loopexit:
120  br label %cond.end
121
122cond.end:
123  %cond = phi i32 [ %i, %entry ], [ 0, %cond.end.loopexit ]
124  ret i32 %cond
125}
126
127; This one is an interesting case because CMOV doesn't have a chain
128; operand. Naive attempts to limit cmpxchg EFLAGS use are likely to fail here.
129define i32 @test_feed_cmov(i32* %addr, i32 %desired, i32 %new) {
130; i386-LABEL: test_feed_cmov:
131; i386: cmpxchgl
132; i386-NEXT: seto %al
133; i386-NEXT: lahf
134; i386-NEXT: movl %eax, [[FLAGS:%.*]]
135; i386-NEXT: calll foo
136; i386-NEXT: pushl %eax
137; i386-NEXT: movl [[FLAGS]], %eax
138; i386-NEXT: addb $127, %al
139; i386-NEXT: sahf
140; i386-NEXT: popl %eax
141
142; i386f-LABEL: test_feed_cmov:
143; i386f: cmpxchgl
144; i386f-NEXT: seto %al
145; i386f-NEXT: lahf
146; i386f-NEXT: movl %eax, [[FLAGS:%.*]]
147; i386f-NEXT: calll foo
148; i386f-NEXT: pushl %eax
149; i386f-NEXT: movl [[FLAGS]], %eax
150; i386f-NEXT: addb $127, %al
151; i386f-NEXT: sahf
152; i386f-NEXT: popl %eax
153
154; x8664-LABEL: test_feed_cmov:
155; x8664: cmpxchg
156; x8664: pushfq
157; x8664-NEXT: popq [[FLAGS:%.*]]
158; x8664-NEXT: callq foo
159; x8664-NEXT: pushq [[FLAGS]]
160; x8664-NEXT: popfq
161
162; x8664-sahf-LABEL: test_feed_cmov:
163; x8664-sahf: cmpxchgl
164; x8664-sahf: seto %al
165; x8664-sahf-NEXT: lahf
166; x8664-sahf-NEXT: movq %rax, [[FLAGS:%.*]]
167; x8664-sahf-NEXT: callq foo
168; x8664-sahf-NEXT: pushq %rax
169; x8664-sahf-NEXT: movq [[FLAGS]], %rax
170; x8664-sahf-NEXT: addb $127, %al
171; x8664-sahf-NEXT: sahf
172; x8664-sahf-NEXT: popq %rax
173
174  %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
175  %success = extractvalue { i32, i1 } %res, 1
176
177  %rhs = call i32 @foo()
178
179  %ret = select i1 %success, i32 %new, i32 %rhs
180  ret i32 %ret
181}
182