• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=32-ALL,32-GOOD-RA
3; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=32-ALL,32-FAST-RA
4
5; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=64-ALL,64-GOOD-RA
6; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=64-ALL,64-FAST-RA
7; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf %s -o - | FileCheck %s --check-prefixes=64-ALL,64-GOOD-RA-SAHF
8; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mattr=+sahf -pre-RA-sched=fast %s -o - | FileCheck %s --check-prefixes=64-ALL,64-FAST-RA-SAHF
9; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs -mcpu=corei7 %s -o - | FileCheck %s --check-prefixes=64-ALL,64-GOOD-RA-SAHF
10
11declare i32 @foo()
12declare i32 @bar(i64)
13
14; In the following case when using fast scheduling we get a long chain of
15; EFLAGS save/restore due to a sequence of:
16; cmpxchg8b (implicit-def eflags)
17; eax = copy eflags
18; adjcallstackdown32
19; ...
20; use of eax
21; During PEI the adjcallstackdown32 is replaced with the subl which
22; clobbers eflags, effectively interfering in the liveness interval. However,
23; we then promote these copies into independent conditions in GPRs that avoids
24; repeated saving and restoring logic and can be trivially managed by the
25; register allocator.
26define i64 @test_intervening_call(i64* %foo, i64 %bar, i64 %baz) nounwind {
27; 32-GOOD-RA-LABEL: test_intervening_call:
28; 32-GOOD-RA:       # %bb.0: # %entry
29; 32-GOOD-RA-NEXT:    pushl %ebx
30; 32-GOOD-RA-NEXT:    pushl %esi
31; 32-GOOD-RA-NEXT:    pushl %eax
32; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %eax
33; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %edx
34; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %ebx
35; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %ecx
36; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %esi
37; 32-GOOD-RA-NEXT:    lock cmpxchg8b (%esi)
38; 32-GOOD-RA-NEXT:    setne %bl
39; 32-GOOD-RA-NEXT:    subl $8, %esp
40; 32-GOOD-RA-NEXT:    pushl %edx
41; 32-GOOD-RA-NEXT:    pushl %eax
42; 32-GOOD-RA-NEXT:    calll bar
43; 32-GOOD-RA-NEXT:    addl $16, %esp
44; 32-GOOD-RA-NEXT:    testb %bl, %bl
45; 32-GOOD-RA-NEXT:    jne .LBB0_3
46; 32-GOOD-RA-NEXT:  # %bb.1: # %t
47; 32-GOOD-RA-NEXT:    movl $42, %eax
48; 32-GOOD-RA-NEXT:    jmp .LBB0_2
49; 32-GOOD-RA-NEXT:  .LBB0_3: # %f
50; 32-GOOD-RA-NEXT:    xorl %eax, %eax
51; 32-GOOD-RA-NEXT:  .LBB0_2: # %t
52; 32-GOOD-RA-NEXT:    xorl %edx, %edx
53; 32-GOOD-RA-NEXT:    addl $4, %esp
54; 32-GOOD-RA-NEXT:    popl %esi
55; 32-GOOD-RA-NEXT:    popl %ebx
56; 32-GOOD-RA-NEXT:    retl
57;
58; 32-FAST-RA-LABEL: test_intervening_call:
59; 32-FAST-RA:       # %bb.0: # %entry
60; 32-FAST-RA-NEXT:    pushl %ebx
61; 32-FAST-RA-NEXT:    pushl %esi
62; 32-FAST-RA-NEXT:    pushl %eax
63; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %esi
64; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %ebx
65; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %ecx
66; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %eax
67; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %edx
68; 32-FAST-RA-NEXT:    lock cmpxchg8b (%esi)
69; 32-FAST-RA-NEXT:    setne %bl
70; 32-FAST-RA-NEXT:    subl $8, %esp
71; 32-FAST-RA-NEXT:    pushl %edx
72; 32-FAST-RA-NEXT:    pushl %eax
73; 32-FAST-RA-NEXT:    calll bar
74; 32-FAST-RA-NEXT:    addl $16, %esp
75; 32-FAST-RA-NEXT:    testb %bl, %bl
76; 32-FAST-RA-NEXT:    jne .LBB0_3
77; 32-FAST-RA-NEXT:  # %bb.1: # %t
78; 32-FAST-RA-NEXT:    movl $42, %eax
79; 32-FAST-RA-NEXT:    jmp .LBB0_2
80; 32-FAST-RA-NEXT:  .LBB0_3: # %f
81; 32-FAST-RA-NEXT:    xorl %eax, %eax
82; 32-FAST-RA-NEXT:  .LBB0_2: # %t
83; 32-FAST-RA-NEXT:    xorl %edx, %edx
84; 32-FAST-RA-NEXT:    addl $4, %esp
85; 32-FAST-RA-NEXT:    popl %esi
86; 32-FAST-RA-NEXT:    popl %ebx
87; 32-FAST-RA-NEXT:    retl
88;
89; 64-ALL-LABEL: test_intervening_call:
90; 64-ALL:       # %bb.0: # %entry
91; 64-ALL-NEXT:    pushq %rbx
92; 64-ALL-NEXT:    movq %rsi, %rax
93; 64-ALL-NEXT:    lock cmpxchgq %rdx, (%rdi)
94; 64-ALL-NEXT:    setne %bl
95; 64-ALL-NEXT:    movq %rax, %rdi
96; 64-ALL-NEXT:    callq bar
97; 64-ALL-NEXT:    testb %bl, %bl
98; 64-ALL-NEXT:    jne .LBB0_2
99; 64-ALL-NEXT:  # %bb.1: # %t
100; 64-ALL-NEXT:    movl $42, %eax
101; 64-ALL-NEXT:    popq %rbx
102; 64-ALL-NEXT:    retq
103; 64-ALL-NEXT:  .LBB0_2: # %f
104; 64-ALL-NEXT:    xorl %eax, %eax
105; 64-ALL-NEXT:    popq %rbx
106; 64-ALL-NEXT:    retq
107entry:
108  %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
109  %v = extractvalue { i64, i1 } %cx, 0
110  %p = extractvalue { i64, i1 } %cx, 1
111  call i32 @bar(i64 %v)
112  br i1 %p, label %t, label %f
113
114t:
115  ret i64 42
116
117f:
118  ret i64 0
119}
120
121; Interesting in producing a clobber without any function calls.
122define i32 @test_control_flow(i32* %p, i32 %i, i32 %j) nounwind {
123; 32-ALL-LABEL: test_control_flow:
124; 32-ALL:       # %bb.0: # %entry
125; 32-ALL-NEXT:    movl {{[0-9]+}}(%esp), %eax
126; 32-ALL-NEXT:    cmpl {{[0-9]+}}(%esp), %eax
127; 32-ALL-NEXT:    jle .LBB1_6
128; 32-ALL-NEXT:  # %bb.1: # %loop_start
129; 32-ALL-NEXT:    movl {{[0-9]+}}(%esp), %ecx
130; 32-ALL-NEXT:    .p2align 4, 0x90
131; 32-ALL-NEXT:  .LBB1_2: # %while.condthread-pre-split.i
132; 32-ALL-NEXT:    # =>This Loop Header: Depth=1
133; 32-ALL-NEXT:    # Child Loop BB1_3 Depth 2
134; 32-ALL-NEXT:    movl (%ecx), %edx
135; 32-ALL-NEXT:    .p2align 4, 0x90
136; 32-ALL-NEXT:  .LBB1_3: # %while.cond.i
137; 32-ALL-NEXT:    # Parent Loop BB1_2 Depth=1
138; 32-ALL-NEXT:    # => This Inner Loop Header: Depth=2
139; 32-ALL-NEXT:    movl %edx, %eax
140; 32-ALL-NEXT:    xorl %edx, %edx
141; 32-ALL-NEXT:    testl %eax, %eax
142; 32-ALL-NEXT:    je .LBB1_3
143; 32-ALL-NEXT:  # %bb.4: # %while.body.i
144; 32-ALL-NEXT:    # in Loop: Header=BB1_2 Depth=1
145; 32-ALL-NEXT:    lock cmpxchgl %eax, (%ecx)
146; 32-ALL-NEXT:    jne .LBB1_2
147; 32-ALL-NEXT:  # %bb.5:
148; 32-ALL-NEXT:    xorl %eax, %eax
149; 32-ALL-NEXT:  .LBB1_6: # %cond.end
150; 32-ALL-NEXT:    retl
151;
152; 64-ALL-LABEL: test_control_flow:
153; 64-ALL:       # %bb.0: # %entry
154; 64-ALL-NEXT:    cmpl %edx, %esi
155; 64-ALL-NEXT:    jle .LBB1_5
156; 64-ALL-NEXT:    .p2align 4, 0x90
157; 64-ALL-NEXT:  .LBB1_1: # %while.condthread-pre-split.i
158; 64-ALL-NEXT:    # =>This Loop Header: Depth=1
159; 64-ALL-NEXT:    # Child Loop BB1_2 Depth 2
160; 64-ALL-NEXT:    movl (%rdi), %ecx
161; 64-ALL-NEXT:    .p2align 4, 0x90
162; 64-ALL-NEXT:  .LBB1_2: # %while.cond.i
163; 64-ALL-NEXT:    # Parent Loop BB1_1 Depth=1
164; 64-ALL-NEXT:    # => This Inner Loop Header: Depth=2
165; 64-ALL-NEXT:    movl %ecx, %eax
166; 64-ALL-NEXT:    xorl %ecx, %ecx
167; 64-ALL-NEXT:    testl %eax, %eax
168; 64-ALL-NEXT:    je .LBB1_2
169; 64-ALL-NEXT:  # %bb.3: # %while.body.i
170; 64-ALL-NEXT:    # in Loop: Header=BB1_1 Depth=1
171; 64-ALL-NEXT:    lock cmpxchgl %eax, (%rdi)
172; 64-ALL-NEXT:    jne .LBB1_1
173; 64-ALL-NEXT:  # %bb.4:
174; 64-ALL-NEXT:    xorl %esi, %esi
175; 64-ALL-NEXT:  .LBB1_5: # %cond.end
176; 64-ALL-NEXT:    movl %esi, %eax
177; 64-ALL-NEXT:    retq
178entry:
179  %cmp = icmp sgt i32 %i, %j
180  br i1 %cmp, label %loop_start, label %cond.end
181
182loop_start:
183  br label %while.condthread-pre-split.i
184
185while.condthread-pre-split.i:
186  %.pr.i = load i32, i32* %p, align 4
187  br label %while.cond.i
188
189while.cond.i:
190  %0 = phi i32 [ %.pr.i, %while.condthread-pre-split.i ], [ 0, %while.cond.i ]
191  %tobool.i = icmp eq i32 %0, 0
192  br i1 %tobool.i, label %while.cond.i, label %while.body.i
193
194while.body.i:
195  %.lcssa = phi i32 [ %0, %while.cond.i ]
196  %1 = cmpxchg i32* %p, i32 %.lcssa, i32 %.lcssa seq_cst seq_cst
197  %2 = extractvalue { i32, i1 } %1, 1
198  br i1 %2, label %cond.end.loopexit, label %while.condthread-pre-split.i
199
200cond.end.loopexit:
201  br label %cond.end
202
203cond.end:
204  %cond = phi i32 [ %i, %entry ], [ 0, %cond.end.loopexit ]
205  ret i32 %cond
206}
207
208; This one is an interesting case because CMOV doesn't have a chain
209; operand. Naive attempts to limit cmpxchg EFLAGS use are likely to fail here.
210define i32 @test_feed_cmov(i32* %addr, i32 %desired, i32 %new) nounwind {
211; 32-GOOD-RA-LABEL: test_feed_cmov:
212; 32-GOOD-RA:       # %bb.0: # %entry
213; 32-GOOD-RA-NEXT:    pushl %ebx
214; 32-GOOD-RA-NEXT:    pushl %esi
215; 32-GOOD-RA-NEXT:    pushl %eax
216; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %eax
217; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %esi
218; 32-GOOD-RA-NEXT:    movl {{[0-9]+}}(%esp), %ecx
219; 32-GOOD-RA-NEXT:    lock cmpxchgl %esi, (%ecx)
220; 32-GOOD-RA-NEXT:    sete %bl
221; 32-GOOD-RA-NEXT:    calll foo
222; 32-GOOD-RA-NEXT:    testb %bl, %bl
223; 32-GOOD-RA-NEXT:    jne .LBB2_2
224; 32-GOOD-RA-NEXT:  # %bb.1: # %entry
225; 32-GOOD-RA-NEXT:    movl %eax, %esi
226; 32-GOOD-RA-NEXT:  .LBB2_2: # %entry
227; 32-GOOD-RA-NEXT:    movl %esi, %eax
228; 32-GOOD-RA-NEXT:    addl $4, %esp
229; 32-GOOD-RA-NEXT:    popl %esi
230; 32-GOOD-RA-NEXT:    popl %ebx
231; 32-GOOD-RA-NEXT:    retl
232;
233; 32-FAST-RA-LABEL: test_feed_cmov:
234; 32-FAST-RA:       # %bb.0: # %entry
235; 32-FAST-RA-NEXT:    pushl %ebx
236; 32-FAST-RA-NEXT:    pushl %esi
237; 32-FAST-RA-NEXT:    pushl %eax
238; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %ecx
239; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %esi
240; 32-FAST-RA-NEXT:    movl {{[0-9]+}}(%esp), %eax
241; 32-FAST-RA-NEXT:    lock cmpxchgl %esi, (%ecx)
242; 32-FAST-RA-NEXT:    sete %bl
243; 32-FAST-RA-NEXT:    calll foo
244; 32-FAST-RA-NEXT:    testb %bl, %bl
245; 32-FAST-RA-NEXT:    jne .LBB2_2
246; 32-FAST-RA-NEXT:  # %bb.1: # %entry
247; 32-FAST-RA-NEXT:    movl %eax, %esi
248; 32-FAST-RA-NEXT:  .LBB2_2: # %entry
249; 32-FAST-RA-NEXT:    movl %esi, %eax
250; 32-FAST-RA-NEXT:    addl $4, %esp
251; 32-FAST-RA-NEXT:    popl %esi
252; 32-FAST-RA-NEXT:    popl %ebx
253; 32-FAST-RA-NEXT:    retl
254;
255; 64-ALL-LABEL: test_feed_cmov:
256; 64-ALL:       # %bb.0: # %entry
257; 64-ALL-NEXT:    pushq %rbp
258; 64-ALL-NEXT:    pushq %rbx
259; 64-ALL-NEXT:    pushq %rax
260; 64-ALL-NEXT:    movl %edx, %ebx
261; 64-ALL-NEXT:    movl %esi, %eax
262; 64-ALL-NEXT:    lock cmpxchgl %edx, (%rdi)
263; 64-ALL-NEXT:    sete %bpl
264; 64-ALL-NEXT:    callq foo
265; 64-ALL-NEXT:    testb %bpl, %bpl
266; 64-ALL-NEXT:    cmovnel %ebx, %eax
267; 64-ALL-NEXT:    addq $8, %rsp
268; 64-ALL-NEXT:    popq %rbx
269; 64-ALL-NEXT:    popq %rbp
270; 64-ALL-NEXT:    retq
271entry:
272  %res = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
273  %success = extractvalue { i32, i1 } %res, 1
274
275  %rhs = call i32 @foo()
276
277  %ret = select i1 %success, i32 %new, i32 %rhs
278  ret i32 %ret
279}
280