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