1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=-sse -verify-machineinstrs < %s | FileCheck %s --check-prefix=X86
3; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=-sse2 -verify-machineinstrs < %s | FileCheck %s --check-prefix=X86
4; RUN: llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=X64
5
6declare i32 @llvm.flt.rounds()
7
8define i32 @test_flt_rounds() nounwind {
9; X86-LABEL: test_flt_rounds:
10; X86:       # %bb.0:
11; X86-NEXT:    subl $2, %esp
12; X86-NEXT:    fnstcw (%esp)
13; X86-NEXT:    movzwl (%esp), %ecx
14; X86-NEXT:    shrl $9, %ecx
15; X86-NEXT:    andb $6, %cl
16; X86-NEXT:    movl $45, %eax
17; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
18; X86-NEXT:    shrl %cl, %eax
19; X86-NEXT:    andl $3, %eax
20; X86-NEXT:    addl $2, %esp
21; X86-NEXT:    retl
22;
23; X64-LABEL: test_flt_rounds:
24; X64:       # %bb.0:
25; X64-NEXT:    fnstcw -{{[0-9]+}}(%rsp)
26; X64-NEXT:    movzwl -{{[0-9]+}}(%rsp), %ecx
27; X64-NEXT:    shrl $9, %ecx
28; X64-NEXT:    andb $6, %cl
29; X64-NEXT:    movl $45, %eax
30; X64-NEXT:    # kill: def $cl killed $cl killed $ecx
31; X64-NEXT:    shrl %cl, %eax
32; X64-NEXT:    andl $3, %eax
33; X64-NEXT:    retq
34  %1 = call i32 @llvm.flt.rounds()
35  ret i32 %1
36}
37
38; Make sure we preserve order with fesetround.
39define i32 @multiple_flt_rounds() nounwind {
40; X86-LABEL: multiple_flt_rounds:
41; X86:       # %bb.0: # %entry
42; X86-NEXT:    pushl %ebx
43; X86-NEXT:    pushl %esi
44; X86-NEXT:    subl $20, %esp
45; X86-NEXT:    movl $1024, (%esp) # imm = 0x400
46; X86-NEXT:    calll fesetround
47; X86-NEXT:    fnstcw {{[0-9]+}}(%esp)
48; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
49; X86-NEXT:    shrl $9, %ecx
50; X86-NEXT:    andb $6, %cl
51; X86-NEXT:    movl $45, %esi
52; X86-NEXT:    movl $45, %eax
53; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
54; X86-NEXT:    shrl %cl, %eax
55; X86-NEXT:    andl $3, %eax
56; X86-NEXT:    xorl %ebx, %ebx
57; X86-NEXT:    cmpl $3, %eax
58; X86-NEXT:    setne %bl
59; X86-NEXT:    movl $0, (%esp)
60; X86-NEXT:    calll fesetround
61; X86-NEXT:    fnstcw {{[0-9]+}}(%esp)
62; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
63; X86-NEXT:    shrl $9, %ecx
64; X86-NEXT:    andb $6, %cl
65; X86-NEXT:    movl $45, %eax
66; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
67; X86-NEXT:    shrl %cl, %eax
68; X86-NEXT:    andl $3, %eax
69; X86-NEXT:    cmpl $1, %eax
70; X86-NEXT:    je .LBB1_2
71; X86-NEXT:  # %bb.1: # %entry
72; X86-NEXT:    incl %ebx
73; X86-NEXT:  .LBB1_2: # %entry
74; X86-NEXT:    movl $3072, (%esp) # imm = 0xC00
75; X86-NEXT:    calll fesetround
76; X86-NEXT:    fnstcw {{[0-9]+}}(%esp)
77; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
78; X86-NEXT:    shrl $9, %ecx
79; X86-NEXT:    andb $6, %cl
80; X86-NEXT:    movl $45, %eax
81; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
82; X86-NEXT:    shrl %cl, %eax
83; X86-NEXT:    andl $3, %eax
84; X86-NEXT:    cmpl $1, %eax
85; X86-NEXT:    sbbl $-1, %ebx
86; X86-NEXT:    movl $2048, (%esp) # imm = 0x800
87; X86-NEXT:    calll fesetround
88; X86-NEXT:    fnstcw {{[0-9]+}}(%esp)
89; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
90; X86-NEXT:    shrl $9, %ecx
91; X86-NEXT:    andb $6, %cl
92; X86-NEXT:    # kill: def $cl killed $cl killed $ecx
93; X86-NEXT:    shrl %cl, %esi
94; X86-NEXT:    andl $3, %esi
95; X86-NEXT:    xorl %ecx, %ecx
96; X86-NEXT:    cmpl $2, %esi
97; X86-NEXT:    setne %cl
98; X86-NEXT:    negl %ecx
99; X86-NEXT:    xorl %eax, %eax
100; X86-NEXT:    cmpl %ecx, %ebx
101; X86-NEXT:    setne %al
102; X86-NEXT:    addl $20, %esp
103; X86-NEXT:    popl %esi
104; X86-NEXT:    popl %ebx
105; X86-NEXT:    retl
106;
107; X64-LABEL: multiple_flt_rounds:
108; X64:       # %bb.0: # %entry
109; X64-NEXT:    pushq %rbp
110; X64-NEXT:    pushq %r14
111; X64-NEXT:    pushq %rbx
112; X64-NEXT:    subq $16, %rsp
113; X64-NEXT:    movl $1024, %edi # imm = 0x400
114; X64-NEXT:    callq fesetround
115; X64-NEXT:    fnstcw {{[0-9]+}}(%rsp)
116; X64-NEXT:    movzwl {{[0-9]+}}(%rsp), %ecx
117; X64-NEXT:    shrl $9, %ecx
118; X64-NEXT:    andb $6, %cl
119; X64-NEXT:    movl $45, %r14d
120; X64-NEXT:    movl $45, %eax
121; X64-NEXT:    # kill: def $cl killed $cl killed $ecx
122; X64-NEXT:    shrl %cl, %eax
123; X64-NEXT:    andl $3, %eax
124; X64-NEXT:    xorl %ebx, %ebx
125; X64-NEXT:    cmpl $3, %eax
126; X64-NEXT:    setne %bl
127; X64-NEXT:    xorl %edi, %edi
128; X64-NEXT:    callq fesetround
129; X64-NEXT:    fnstcw {{[0-9]+}}(%rsp)
130; X64-NEXT:    movzwl {{[0-9]+}}(%rsp), %ecx
131; X64-NEXT:    shrl $9, %ecx
132; X64-NEXT:    andb $6, %cl
133; X64-NEXT:    movl $45, %eax
134; X64-NEXT:    # kill: def $cl killed $cl killed $ecx
135; X64-NEXT:    shrl %cl, %eax
136; X64-NEXT:    andl $3, %eax
137; X64-NEXT:    leal 1(%rbx), %ebp
138; X64-NEXT:    cmpl $1, %eax
139; X64-NEXT:    cmovel %ebx, %ebp
140; X64-NEXT:    movl $3072, %edi # imm = 0xC00
141; X64-NEXT:    callq fesetround
142; X64-NEXT:    fnstcw {{[0-9]+}}(%rsp)
143; X64-NEXT:    movzwl {{[0-9]+}}(%rsp), %ecx
144; X64-NEXT:    shrl $9, %ecx
145; X64-NEXT:    andb $6, %cl
146; X64-NEXT:    movl $45, %eax
147; X64-NEXT:    # kill: def $cl killed $cl killed $ecx
148; X64-NEXT:    shrl %cl, %eax
149; X64-NEXT:    andl $3, %eax
150; X64-NEXT:    cmpl $1, %eax
151; X64-NEXT:    sbbl $-1, %ebp
152; X64-NEXT:    movl $2048, %edi # imm = 0x800
153; X64-NEXT:    callq fesetround
154; X64-NEXT:    fnstcw {{[0-9]+}}(%rsp)
155; X64-NEXT:    movzwl {{[0-9]+}}(%rsp), %ecx
156; X64-NEXT:    shrl $9, %ecx
157; X64-NEXT:    andb $6, %cl
158; X64-NEXT:    # kill: def $cl killed $cl killed $ecx
159; X64-NEXT:    shrl %cl, %r14d
160; X64-NEXT:    andl $3, %r14d
161; X64-NEXT:    xorl %ecx, %ecx
162; X64-NEXT:    cmpl $2, %r14d
163; X64-NEXT:    setne %cl
164; X64-NEXT:    negl %ecx
165; X64-NEXT:    xorl %eax, %eax
166; X64-NEXT:    cmpl %ecx, %ebp
167; X64-NEXT:    setne %al
168; X64-NEXT:    addq $16, %rsp
169; X64-NEXT:    popq %rbx
170; X64-NEXT:    popq %r14
171; X64-NEXT:    popq %rbp
172; X64-NEXT:    retq
173entry:
174  %call = tail call i32 @fesetround(i32 1024)
175  %0 = tail call i32 @llvm.flt.rounds()
176  %cmp = icmp ne i32 %0, 3
177  %spec.select = zext i1 %cmp to i32
178  %call1 = tail call i32 @fesetround(i32 0)
179  %1 = tail call i32 @llvm.flt.rounds()
180  %cmp2 = icmp eq i32 %1, 1
181  %inc4 = select i1 %cmp, i32 2, i32 1
182  %errs.1 = select i1 %cmp2, i32 %spec.select, i32 %inc4
183  %call6 = tail call i32 @fesetround(i32 3072)
184  %2 = tail call i32 @llvm.flt.rounds()
185  %cmp7 = icmp ne i32 %2, 0
186  %inc9 = zext i1 %cmp7 to i32
187  %spec.select22 = add nuw nsw i32 %errs.1, %inc9
188  %call11 = tail call i32 @fesetround(i32 2048)
189  %3 = tail call i32 @llvm.flt.rounds()
190  %cmp12 = icmp ne i32 %3, 2
191  %inc14.neg = sext i1 %cmp12 to i32
192  %cmp16 = icmp ne i32 %spec.select22, %inc14.neg
193  %cond = zext i1 %cmp16 to i32
194  ret i32 %cond
195}
196
197; Function Attrs: nounwind
198declare dso_local i32 @fesetround(i32) local_unnamed_addr #1
199