xref: /llvm-project/llvm/test/CodeGen/X86/llvm.frexp.ll (revision a7dafea384a519342b2fbe210ed101c1e67f3be7)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck -check-prefixes=X64 %s
3; RUN: llc -mtriple=i386-pc-win32 < %s | FileCheck -check-prefix=WIN32 %s
4
5define { half, i32 } @test_frexp_f16_i32(half %a) {
6; X64-LABEL: test_frexp_f16_i32:
7; X64:       # %bb.0:
8; X64-NEXT:    subq $24, %rsp
9; X64-NEXT:    .cfi_def_cfa_offset 32
10; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
11; X64-NEXT:    callq __extendhfsf2@PLT
12; X64-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
13; X64-NEXT:    callq __truncsfhf2@PLT
14; X64-NEXT:    pextrw $0, %xmm0, %ecx
15; X64-NEXT:    movl %ecx, %eax
16; X64-NEXT:    andl $31744, %eax # imm = 0x7C00
17; X64-NEXT:    movdqa (%rsp), %xmm0 # 16-byte Reload
18; X64-NEXT:    pextrw $0, %xmm0, %edx
19; X64-NEXT:    movl %edx, %esi
20; X64-NEXT:    andl $32767, %esi # imm = 0x7FFF
21; X64-NEXT:    cmpl $1024, %esi # imm = 0x400
22; X64-NEXT:    cmovael %edx, %ecx
23; X64-NEXT:    cmovael %esi, %eax
24; X64-NEXT:    shrl $10, %eax
25; X64-NEXT:    leal -12(%rax), %edi
26; X64-NEXT:    cmpl $1024, %esi # imm = 0x400
27; X64-NEXT:    cmovael %eax, %edi
28; X64-NEXT:    addl $-14, %edi
29; X64-NEXT:    andl $-31745, %ecx # imm = 0x83FF
30; X64-NEXT:    orl $14336, %ecx # imm = 0x3800
31; X64-NEXT:    addl $-31744, %esi # imm = 0x8400
32; X64-NEXT:    movzwl %si, %esi
33; X64-NEXT:    xorl %eax, %eax
34; X64-NEXT:    cmpl $33792, %esi # imm = 0x8400
35; X64-NEXT:    cmoval %edi, %eax
36; X64-NEXT:    cmovbel %edx, %ecx
37; X64-NEXT:    pinsrw $0, %ecx, %xmm0
38; X64-NEXT:    addq $24, %rsp
39; X64-NEXT:    .cfi_def_cfa_offset 8
40; X64-NEXT:    retq
41;
42; WIN32-LABEL: test_frexp_f16_i32:
43; WIN32:       # %bb.0:
44; WIN32-NEXT:    pushl %esi
45; WIN32-NEXT:    subl $20, %esp
46; WIN32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
47; WIN32-NEXT:    movl %eax, (%esp)
48; WIN32-NEXT:    calll ___gnu_h2f_ieee
49; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
50; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
51; WIN32-NEXT:    fstpl (%esp)
52; WIN32-NEXT:    calll _frexp
53; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
54; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
55; WIN32-NEXT:    fstps (%esp)
56; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %esi
57; WIN32-NEXT:    calll ___gnu_f2h_ieee
58; WIN32-NEXT:    movl %esi, %edx
59; WIN32-NEXT:    addl $20, %esp
60; WIN32-NEXT:    popl %esi
61; WIN32-NEXT:    retl
62  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
63  ret { half, i32 } %result
64}
65
66define half @test_frexp_f16_i32_only_use_fract(half %a) {
67; X64-LABEL: test_frexp_f16_i32_only_use_fract:
68; X64:       # %bb.0:
69; X64-NEXT:    subq $24, %rsp
70; X64-NEXT:    .cfi_def_cfa_offset 32
71; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
72; X64-NEXT:    callq __extendhfsf2@PLT
73; X64-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
74; X64-NEXT:    callq __truncsfhf2@PLT
75; X64-NEXT:    pextrw $0, %xmm0, %eax
76; X64-NEXT:    movdqa (%rsp), %xmm0 # 16-byte Reload
77; X64-NEXT:    pextrw $0, %xmm0, %ecx
78; X64-NEXT:    movl %ecx, %edx
79; X64-NEXT:    andl $32767, %edx # imm = 0x7FFF
80; X64-NEXT:    cmpl $1024, %edx # imm = 0x400
81; X64-NEXT:    cmovael %ecx, %eax
82; X64-NEXT:    andl $-31745, %eax # imm = 0x83FF
83; X64-NEXT:    orl $14336, %eax # imm = 0x3800
84; X64-NEXT:    addl $-31744, %edx # imm = 0x8400
85; X64-NEXT:    movzwl %dx, %edx
86; X64-NEXT:    cmpl $33792, %edx # imm = 0x8400
87; X64-NEXT:    cmovbel %ecx, %eax
88; X64-NEXT:    pinsrw $0, %eax, %xmm0
89; X64-NEXT:    addq $24, %rsp
90; X64-NEXT:    .cfi_def_cfa_offset 8
91; X64-NEXT:    retq
92;
93; WIN32-LABEL: test_frexp_f16_i32_only_use_fract:
94; WIN32:       # %bb.0:
95; WIN32-NEXT:    subl $20, %esp
96; WIN32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
97; WIN32-NEXT:    movl %eax, (%esp)
98; WIN32-NEXT:    calll ___gnu_h2f_ieee
99; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
100; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
101; WIN32-NEXT:    fstpl (%esp)
102; WIN32-NEXT:    calll _frexp
103; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
104; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
105; WIN32-NEXT:    fstps (%esp)
106; WIN32-NEXT:    calll ___gnu_f2h_ieee
107; WIN32-NEXT:    addl $20, %esp
108; WIN32-NEXT:    retl
109  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
110  %result.0 = extractvalue { half, i32 } %result, 0
111  ret half %result.0
112}
113
114define i32 @test_frexp_f16_i32_only_use_exp(half %a) {
115; X64-LABEL: test_frexp_f16_i32_only_use_exp:
116; X64:       # %bb.0:
117; X64-NEXT:    subq $24, %rsp
118; X64-NEXT:    .cfi_def_cfa_offset 32
119; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
120; X64-NEXT:    callq __extendhfsf2@PLT
121; X64-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
122; X64-NEXT:    callq __truncsfhf2@PLT
123; X64-NEXT:    pextrw $0, %xmm0, %eax
124; X64-NEXT:    andl $31744, %eax # imm = 0x7C00
125; X64-NEXT:    movdqa (%rsp), %xmm0 # 16-byte Reload
126; X64-NEXT:    pextrw $0, %xmm0, %ecx
127; X64-NEXT:    andl $32767, %ecx # imm = 0x7FFF
128; X64-NEXT:    cmpl $1024, %ecx # imm = 0x400
129; X64-NEXT:    cmovael %ecx, %eax
130; X64-NEXT:    shrl $10, %eax
131; X64-NEXT:    leal -12(%rax), %edx
132; X64-NEXT:    cmpl $1024, %ecx # imm = 0x400
133; X64-NEXT:    cmovael %eax, %edx
134; X64-NEXT:    addl $-14, %edx
135; X64-NEXT:    addl $-31744, %ecx # imm = 0x8400
136; X64-NEXT:    movzwl %cx, %ecx
137; X64-NEXT:    xorl %eax, %eax
138; X64-NEXT:    cmpl $33792, %ecx # imm = 0x8400
139; X64-NEXT:    cmoval %edx, %eax
140; X64-NEXT:    addq $24, %rsp
141; X64-NEXT:    .cfi_def_cfa_offset 8
142; X64-NEXT:    retq
143;
144; WIN32-LABEL: test_frexp_f16_i32_only_use_exp:
145; WIN32:       # %bb.0:
146; WIN32-NEXT:    subl $16, %esp
147; WIN32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
148; WIN32-NEXT:    movl %eax, (%esp)
149; WIN32-NEXT:    calll ___gnu_h2f_ieee
150; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
151; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
152; WIN32-NEXT:    fstpl (%esp)
153; WIN32-NEXT:    calll _frexp
154; WIN32-NEXT:    fstp %st(0)
155; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %eax
156; WIN32-NEXT:    addl $16, %esp
157; WIN32-NEXT:    retl
158  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
159  %result.0 = extractvalue { half, i32 } %result, 1
160  ret i32 %result.0
161}
162
163; FIXME
164; define { <2 x half>, <2 x i32> } @test_frexp_v2f16_v2i32(<2 x half> %a) {
165;   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
166;   ret { <2 x half>, <2 x i32> } %result
167; }
168
169; define <2 x half> @test_frexp_v2f16_v2i32_only_use_fract(<2 x half> %a) {
170;   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
171;   %result.0 = extractvalue { <2 x half>, <2 x i32> } %result, 0
172;   ret <2 x half> %result.0
173; }
174
175; define <2 x i32> @test_frexp_v2f16_v2i32_only_use_exp(<2 x half> %a) {
176;   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
177;   %result.1 = extractvalue { <2 x half>, <2 x i32> } %result, 1
178;   ret <2 x i32> %result.1
179; }
180
181define { float, i32 } @test_frexp_f32_i32(float %a) {
182; X64-LABEL: test_frexp_f32_i32:
183; X64:       # %bb.0:
184; X64-NEXT:    pushq %rax
185; X64-NEXT:    .cfi_def_cfa_offset 16
186; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
187; X64-NEXT:    callq frexpf@PLT
188; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
189; X64-NEXT:    popq %rcx
190; X64-NEXT:    .cfi_def_cfa_offset 8
191; X64-NEXT:    retq
192;
193; WIN32-LABEL: test_frexp_f32_i32:
194; WIN32:       # %bb.0:
195; WIN32-NEXT:    subl $20, %esp
196; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
197; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
198; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
199; WIN32-NEXT:    fstpl (%esp)
200; WIN32-NEXT:    calll _frexp
201; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
202; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %eax
203; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
204; WIN32-NEXT:    addl $20, %esp
205; WIN32-NEXT:    retl
206  %result = call { float, i32 } @llvm.frexp.f32.i32(float %a)
207  ret { float, i32 } %result
208}
209
210define float @test_frexp_f32_i32_only_use_fract(float %a) {
211; X64-LABEL: test_frexp_f32_i32_only_use_fract:
212; X64:       # %bb.0:
213; X64-NEXT:    pushq %rax
214; X64-NEXT:    .cfi_def_cfa_offset 16
215; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
216; X64-NEXT:    callq frexpf@PLT
217; X64-NEXT:    popq %rax
218; X64-NEXT:    .cfi_def_cfa_offset 8
219; X64-NEXT:    retq
220;
221; WIN32-LABEL: test_frexp_f32_i32_only_use_fract:
222; WIN32:       # %bb.0:
223; WIN32-NEXT:    subl $20, %esp
224; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
225; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
226; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
227; WIN32-NEXT:    fstpl (%esp)
228; WIN32-NEXT:    calll _frexp
229; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
230; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
231; WIN32-NEXT:    addl $20, %esp
232; WIN32-NEXT:    retl
233  %result = call { float, i32 } @llvm.frexp.f32.i32(float %a)
234  %result.0 = extractvalue { float, i32 } %result, 0
235  ret float %result.0
236}
237
238define i32 @test_frexp_f32_i32_only_use_exp(float %a) {
239; X64-LABEL: test_frexp_f32_i32_only_use_exp:
240; X64:       # %bb.0:
241; X64-NEXT:    pushq %rax
242; X64-NEXT:    .cfi_def_cfa_offset 16
243; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
244; X64-NEXT:    callq frexpf@PLT
245; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
246; X64-NEXT:    popq %rcx
247; X64-NEXT:    .cfi_def_cfa_offset 8
248; X64-NEXT:    retq
249;
250; WIN32-LABEL: test_frexp_f32_i32_only_use_exp:
251; WIN32:       # %bb.0:
252; WIN32-NEXT:    subl $16, %esp
253; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
254; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
255; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
256; WIN32-NEXT:    fstpl (%esp)
257; WIN32-NEXT:    calll _frexp
258; WIN32-NEXT:    fstp %st(0)
259; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %eax
260; WIN32-NEXT:    addl $16, %esp
261; WIN32-NEXT:    retl
262  %result = call { float, i32 } @llvm.frexp.f32.i32(float %a)
263  %result.0 = extractvalue { float, i32 } %result, 1
264  ret i32 %result.0
265}
266
267; FIXME: Widen vector result
268; define { <2 x float>, <2 x i32> } @test_frexp_v2f32_v2i32(<2 x float> %a) {
269;   %result = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %a)
270;   ret { <2 x float>, <2 x i32> } %result
271; }
272
273; define <2 x float> @test_frexp_v2f32_v2i32_only_use_fract(<2 x float> %a) {
274;   %result = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %a)
275;   %result.0 = extractvalue { <2 x float>, <2 x i32> } %result, 0
276;   ret <2 x float> %result.0
277; }
278
279; define <2 x i32> @test_frexp_v2f32_v2i32_only_use_exp(<2 x float> %a) {
280;   %result = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %a)
281;   %result.1 = extractvalue { <2 x float>, <2 x i32> } %result, 1
282;   ret <2 x i32> %result.1
283; }
284
285define { <4 x float>, <4 x i32> } @test_frexp_v4f32_v4i32(<4 x float> %a) {
286; X64-LABEL: test_frexp_v4f32_v4i32:
287; X64:       # %bb.0:
288; X64-NEXT:    subq $72, %rsp
289; X64-NEXT:    .cfi_def_cfa_offset 80
290; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
291; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
292; X64-NEXT:    movq %rsp, %rdi
293; X64-NEXT:    callq frexpf@PLT
294; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
295; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
296; X64-NEXT:    movhlps {{.*#+}} xmm0 = xmm0[1,1]
297; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
298; X64-NEXT:    callq frexpf@PLT
299; X64-NEXT:    unpcklps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
300; X64-NEXT:    # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
301; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
302; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
303; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
304; X64-NEXT:    callq frexpf@PLT
305; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
306; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
307; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
308; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
309; X64-NEXT:    callq frexpf@PLT
310; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
311; X64-NEXT:    unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
312; X64-NEXT:    unpcklpd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Folded Reload
313; X64-NEXT:    # xmm1 = xmm1[0],mem[0]
314; X64-NEXT:    movaps %xmm1, %xmm0
315; X64-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
316; X64-NEXT:    movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
317; X64-NEXT:    unpcklps {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1]
318; X64-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
319; X64-NEXT:    movss {{.*#+}} xmm3 = mem[0],zero,zero,zero
320; X64-NEXT:    unpcklps {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
321; X64-NEXT:    movlhps {{.*#+}} xmm1 = xmm1[0],xmm2[0]
322; X64-NEXT:    addq $72, %rsp
323; X64-NEXT:    .cfi_def_cfa_offset 8
324; X64-NEXT:    retq
325;
326; WIN32-LABEL: test_frexp_v4f32_v4i32:
327; WIN32:       # %bb.0:
328; WIN32-NEXT:    pushl %esi
329; WIN32-NEXT:    subl $44, %esp
330; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %esi
331; WIN32-NEXT:    leal 24(%esi), %eax
332; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
333; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
334; WIN32-NEXT:    fstpl (%esp)
335; WIN32-NEXT:    calll _frexp
336; WIN32-NEXT:    fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
337; WIN32-NEXT:    leal 20(%esi), %eax
338; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
339; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
340; WIN32-NEXT:    fstpl (%esp)
341; WIN32-NEXT:    calll _frexp
342; WIN32-NEXT:    fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
343; WIN32-NEXT:    leal 16(%esi), %eax
344; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
345; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
346; WIN32-NEXT:    fstpl (%esp)
347; WIN32-NEXT:    calll _frexp
348; WIN32-NEXT:    leal 28(%esi), %eax
349; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
350; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
351; WIN32-NEXT:    fstpl (%esp)
352; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
353; WIN32-NEXT:    fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
354; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
355; WIN32-NEXT:    fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
356; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
357; WIN32-NEXT:    calll _frexp
358; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
359; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
360; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
361; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
362; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
363; WIN32-NEXT:    fstps 12(%esi)
364; WIN32-NEXT:    fstps 8(%esi)
365; WIN32-NEXT:    fstps 4(%esi)
366; WIN32-NEXT:    fstps (%esi)
367; WIN32-NEXT:    movl %esi, %eax
368; WIN32-NEXT:    addl $44, %esp
369; WIN32-NEXT:    popl %esi
370; WIN32-NEXT:    retl
371  %result = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %a)
372  ret { <4 x float>, <4 x i32> } %result
373}
374
375define <4 x float> @test_frexp_v4f32_v4i32_only_use_fract(<4 x float> %a) {
376; X64-LABEL: test_frexp_v4f32_v4i32_only_use_fract:
377; X64:       # %bb.0:
378; X64-NEXT:    subq $72, %rsp
379; X64-NEXT:    .cfi_def_cfa_offset 80
380; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
381; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
382; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
383; X64-NEXT:    callq frexpf@PLT
384; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
385; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
386; X64-NEXT:    movhlps {{.*#+}} xmm0 = xmm0[1,1]
387; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
388; X64-NEXT:    callq frexpf@PLT
389; X64-NEXT:    unpcklps (%rsp), %xmm0 # 16-byte Folded Reload
390; X64-NEXT:    # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
391; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
392; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
393; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
394; X64-NEXT:    callq frexpf@PLT
395; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
396; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
397; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
398; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
399; X64-NEXT:    callq frexpf@PLT
400; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
401; X64-NEXT:    unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
402; X64-NEXT:    unpcklpd (%rsp), %xmm1 # 16-byte Folded Reload
403; X64-NEXT:    # xmm1 = xmm1[0],mem[0]
404; X64-NEXT:    movaps %xmm1, %xmm0
405; X64-NEXT:    addq $72, %rsp
406; X64-NEXT:    .cfi_def_cfa_offset 8
407; X64-NEXT:    retq
408;
409; WIN32-LABEL: test_frexp_v4f32_v4i32_only_use_fract:
410; WIN32:       # %bb.0:
411; WIN32-NEXT:    pushl %esi
412; WIN32-NEXT:    subl $60, %esp
413; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %esi
414; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
415; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
416; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
417; WIN32-NEXT:    fstpl (%esp)
418; WIN32-NEXT:    calll _frexp
419; WIN32-NEXT:    fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
420; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
421; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
422; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
423; WIN32-NEXT:    fstpl (%esp)
424; WIN32-NEXT:    calll _frexp
425; WIN32-NEXT:    fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
426; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
427; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
428; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
429; WIN32-NEXT:    fstpl (%esp)
430; WIN32-NEXT:    calll _frexp
431; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
432; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
433; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
434; WIN32-NEXT:    fstpl (%esp)
435; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
436; WIN32-NEXT:    fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
437; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
438; WIN32-NEXT:    fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
439; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
440; WIN32-NEXT:    calll _frexp
441; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
442; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
443; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
444; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
445; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
446; WIN32-NEXT:    fstps 12(%esi)
447; WIN32-NEXT:    fstps 8(%esi)
448; WIN32-NEXT:    fstps 4(%esi)
449; WIN32-NEXT:    fstps (%esi)
450; WIN32-NEXT:    movl %esi, %eax
451; WIN32-NEXT:    addl $60, %esp
452; WIN32-NEXT:    popl %esi
453; WIN32-NEXT:    retl
454  %result = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %a)
455  %result.0 = extractvalue { <4 x float>, <4 x i32> } %result, 0
456  ret <4 x float> %result.0
457}
458
459define <4 x i32> @test_frexp_v4f32_v4i32_only_use_exp(<4 x float> %a) {
460; X64-LABEL: test_frexp_v4f32_v4i32_only_use_exp:
461; X64:       # %bb.0:
462; X64-NEXT:    subq $40, %rsp
463; X64-NEXT:    .cfi_def_cfa_offset 48
464; X64-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
465; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
466; X64-NEXT:    movq %rsp, %rdi
467; X64-NEXT:    callq frexpf@PLT
468; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
469; X64-NEXT:    movhlps {{.*#+}} xmm0 = xmm0[1,1]
470; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
471; X64-NEXT:    callq frexpf@PLT
472; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
473; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
474; X64-NEXT:    callq frexpf@PLT
475; X64-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
476; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
477; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
478; X64-NEXT:    callq frexpf@PLT
479; X64-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
480; X64-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
481; X64-NEXT:    unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
482; X64-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
483; X64-NEXT:    movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
484; X64-NEXT:    unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
485; X64-NEXT:    movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]
486; X64-NEXT:    addq $40, %rsp
487; X64-NEXT:    .cfi_def_cfa_offset 8
488; X64-NEXT:    retq
489;
490; WIN32-LABEL: test_frexp_v4f32_v4i32_only_use_exp:
491; WIN32:       # %bb.0:
492; WIN32-NEXT:    pushl %esi
493; WIN32-NEXT:    subl $12, %esp
494; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %esi
495; WIN32-NEXT:    leal 8(%esi), %eax
496; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
497; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
498; WIN32-NEXT:    fstpl (%esp)
499; WIN32-NEXT:    calll _frexp
500; WIN32-NEXT:    fstp %st(0)
501; WIN32-NEXT:    leal 4(%esi), %eax
502; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
503; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
504; WIN32-NEXT:    fstpl (%esp)
505; WIN32-NEXT:    calll _frexp
506; WIN32-NEXT:    fstp %st(0)
507; WIN32-NEXT:    leal 12(%esi), %eax
508; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
509; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
510; WIN32-NEXT:    fstpl (%esp)
511; WIN32-NEXT:    calll _frexp
512; WIN32-NEXT:    fstp %st(0)
513; WIN32-NEXT:    movl %esi, {{[0-9]+}}(%esp)
514; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
515; WIN32-NEXT:    fstpl (%esp)
516; WIN32-NEXT:    calll _frexp
517; WIN32-NEXT:    fstp %st(0)
518; WIN32-NEXT:    movl %esi, %eax
519; WIN32-NEXT:    addl $12, %esp
520; WIN32-NEXT:    popl %esi
521; WIN32-NEXT:    retl
522  %result = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %a)
523  %result.1 = extractvalue { <4 x float>, <4 x i32> } %result, 1
524  ret <4 x i32> %result.1
525}
526
527define { double, i32 } @test_frexp_f64_i32(double %a) {
528; X64-LABEL: test_frexp_f64_i32:
529; X64:       # %bb.0:
530; X64-NEXT:    pushq %rax
531; X64-NEXT:    .cfi_def_cfa_offset 16
532; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
533; X64-NEXT:    callq frexp@PLT
534; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
535; X64-NEXT:    popq %rcx
536; X64-NEXT:    .cfi_def_cfa_offset 8
537; X64-NEXT:    retq
538;
539; WIN32-LABEL: test_frexp_f64_i32:
540; WIN32:       # %bb.0:
541; WIN32-NEXT:    subl $16, %esp
542; WIN32-NEXT:    fldl {{[0-9]+}}(%esp)
543; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
544; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
545; WIN32-NEXT:    fstpl (%esp)
546; WIN32-NEXT:    calll _frexp
547; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %eax
548; WIN32-NEXT:    addl $16, %esp
549; WIN32-NEXT:    retl
550  %result = call { double, i32 } @llvm.frexp.f64.i32(double %a)
551  ret { double, i32 } %result
552}
553
554define double @test_frexp_f64_i32_only_use_fract(double %a) {
555; X64-LABEL: test_frexp_f64_i32_only_use_fract:
556; X64:       # %bb.0:
557; X64-NEXT:    pushq %rax
558; X64-NEXT:    .cfi_def_cfa_offset 16
559; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
560; X64-NEXT:    callq frexp@PLT
561; X64-NEXT:    popq %rax
562; X64-NEXT:    .cfi_def_cfa_offset 8
563; X64-NEXT:    retq
564;
565; WIN32-LABEL: test_frexp_f64_i32_only_use_fract:
566; WIN32:       # %bb.0:
567; WIN32-NEXT:    subl $16, %esp
568; WIN32-NEXT:    fldl {{[0-9]+}}(%esp)
569; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
570; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
571; WIN32-NEXT:    fstpl (%esp)
572; WIN32-NEXT:    calll _frexp
573; WIN32-NEXT:    addl $16, %esp
574; WIN32-NEXT:    retl
575  %result = call { double, i32 } @llvm.frexp.f64.i32(double %a)
576  %result.0 = extractvalue { double, i32 } %result, 0
577  ret double %result.0
578}
579
580define i32 @test_frexp_f64_i32_only_use_exp(double %a) {
581; X64-LABEL: test_frexp_f64_i32_only_use_exp:
582; X64:       # %bb.0:
583; X64-NEXT:    pushq %rax
584; X64-NEXT:    .cfi_def_cfa_offset 16
585; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
586; X64-NEXT:    callq frexp@PLT
587; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
588; X64-NEXT:    popq %rcx
589; X64-NEXT:    .cfi_def_cfa_offset 8
590; X64-NEXT:    retq
591;
592; WIN32-LABEL: test_frexp_f64_i32_only_use_exp:
593; WIN32:       # %bb.0:
594; WIN32-NEXT:    subl $16, %esp
595; WIN32-NEXT:    fldl {{[0-9]+}}(%esp)
596; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %eax
597; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
598; WIN32-NEXT:    fstpl (%esp)
599; WIN32-NEXT:    calll _frexp
600; WIN32-NEXT:    fstp %st(0)
601; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %eax
602; WIN32-NEXT:    addl $16, %esp
603; WIN32-NEXT:    retl
604  %result = call { double, i32 } @llvm.frexp.f64.i32(double %a)
605  %result.0 = extractvalue { double, i32 } %result, 1
606  ret i32 %result.0
607}
608
609; FIXME: Widen vector result
610; define { <2 x double>, <2 x i32> } @test_frexp_v2f64_v2i32(<2 x double> %a) {
611;   %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
612;   ret { <2 x double>, <2 x i32> } %result
613; }
614
615; define <2 x double> @test_frexp_v2f64_v2i32_only_use_fract(<2 x double> %a) {
616;   %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
617;   %result.0 = extractvalue { <2 x double>, <2 x i32> } %result, 0
618;   ret <2 x double> %result.0
619; }
620
621; define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) {
622;   %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
623;   %result.1 = extractvalue { <2 x double>, <2 x i32> } %result, 1
624;   ret <2 x i32> %result.1
625; }
626
627declare { float, i32 } @llvm.frexp.f32.i32(float) #0
628declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
629declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) #0
630
631declare { half, i32 } @llvm.frexp.f16.i32(half) #0
632declare { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half>) #0
633
634declare { double, i32 } @llvm.frexp.f64.i32(double) #0
635declare { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double>) #0
636
637declare { half, i16 } @llvm.frexp.f16.i16(half) #0
638declare { <2 x half>, <2 x i16> } @llvm.frexp.v2f16.v2i16(<2 x half>) #0
639
640attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
641