xref: /llvm-project/llvm/test/CodeGen/ARM/llvm.frexp.ll (revision 52864d9c7bd49ca41191bd34fcee47f61cfea743)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2; RUN: llc -mtriple=thumbv7-unknown-linux < %s | FileCheck -check-prefixes=CHECK %s
3
4define { half, i32 } @test_frexp_f16_i32(half %a) {
5; CHECK-LABEL: test_frexp_f16_i32:
6; CHECK:       @ %bb.0:
7; CHECK-NEXT:    push {r7, lr}
8; CHECK-NEXT:    sub sp, #8
9; CHECK-NEXT:    bl __gnu_h2f_ieee
10; CHECK-NEXT:    add r1, sp, #4
11; CHECK-NEXT:    bl frexpf
12; CHECK-NEXT:    bl __gnu_f2h_ieee
13; CHECK-NEXT:    ldr r1, [sp, #4]
14; CHECK-NEXT:    add sp, #8
15; CHECK-NEXT:    pop {r7, pc}
16  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
17  ret { half, i32 } %result
18}
19
20define half @test_frexp_f16_i32_only_use_fract(half %a) {
21; CHECK-LABEL: test_frexp_f16_i32_only_use_fract:
22; CHECK:       @ %bb.0:
23; CHECK-NEXT:    push {r7, lr}
24; CHECK-NEXT:    sub sp, #8
25; CHECK-NEXT:    bl __gnu_h2f_ieee
26; CHECK-NEXT:    add r1, sp, #4
27; CHECK-NEXT:    bl frexpf
28; CHECK-NEXT:    bl __gnu_f2h_ieee
29; CHECK-NEXT:    add sp, #8
30; CHECK-NEXT:    pop {r7, pc}
31  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
32  %result.0 = extractvalue { half, i32 } %result, 0
33  ret half %result.0
34}
35
36define i32 @test_frexp_f16_i32_only_use_exp(half %a) {
37; CHECK-LABEL: test_frexp_f16_i32_only_use_exp:
38; CHECK:       @ %bb.0:
39; CHECK-NEXT:    push {r7, lr}
40; CHECK-NEXT:    sub sp, #8
41; CHECK-NEXT:    bl __gnu_h2f_ieee
42; CHECK-NEXT:    add r1, sp, #4
43; CHECK-NEXT:    bl frexpf
44; CHECK-NEXT:    ldr r0, [sp, #4]
45; CHECK-NEXT:    add sp, #8
46; CHECK-NEXT:    pop {r7, pc}
47  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
48  %result.0 = extractvalue { half, i32 } %result, 1
49  ret i32 %result.0
50}
51
52define { <2 x half>, <2 x i32> } @test_frexp_v2f16_v2i32(<2 x half> %a) {
53; CHECK-LABEL: test_frexp_v2f16_v2i32:
54; CHECK:       @ %bb.0:
55; CHECK-NEXT:    push {r4, r5, r6, lr}
56; CHECK-NEXT:    vpush {d8}
57; CHECK-NEXT:    sub sp, #16
58; CHECK-NEXT:    mov r4, r1
59; CHECK-NEXT:    bl __gnu_h2f_ieee
60; CHECK-NEXT:    add r5, sp, #4
61; CHECK-NEXT:    mov r1, r5
62; CHECK-NEXT:    bl frexpf
63; CHECK-NEXT:    vld1.32 {d8[0]}, [r5:32]
64; CHECK-NEXT:    mov r6, r0
65; CHECK-NEXT:    mov r0, r4
66; CHECK-NEXT:    bl __gnu_h2f_ieee
67; CHECK-NEXT:    add r4, sp, #8
68; CHECK-NEXT:    mov r1, r4
69; CHECK-NEXT:    bl frexpf
70; CHECK-NEXT:    bl __gnu_f2h_ieee
71; CHECK-NEXT:    strh.w r0, [sp, #14]
72; CHECK-NEXT:    mov r0, r6
73; CHECK-NEXT:    bl __gnu_f2h_ieee
74; CHECK-NEXT:    strh.w r0, [sp, #12]
75; CHECK-NEXT:    add r0, sp, #12
76; CHECK-NEXT:    vld1.32 {d8[1]}, [r4:32]
77; CHECK-NEXT:    vld1.32 {d16[0]}, [r0:32]
78; CHECK-NEXT:    vmov r2, r3, d8
79; CHECK-NEXT:    vmovl.u16 q8, d16
80; CHECK-NEXT:    vmov.32 r0, d16[0]
81; CHECK-NEXT:    vmov.32 r1, d16[1]
82; CHECK-NEXT:    add sp, #16
83; CHECK-NEXT:    vpop {d8}
84; CHECK-NEXT:    pop {r4, r5, r6, pc}
85  %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
86  ret { <2 x half>, <2 x i32> } %result
87}
88
89define <2 x half> @test_frexp_v2f16_v2i32_only_use_fract(<2 x half> %a) {
90; CHECK-LABEL: test_frexp_v2f16_v2i32_only_use_fract:
91; CHECK:       @ %bb.0:
92; CHECK-NEXT:    push {r4, lr}
93; CHECK-NEXT:    sub sp, #16
94; CHECK-NEXT:    mov r4, r0
95; CHECK-NEXT:    mov r0, r1
96; CHECK-NEXT:    bl __gnu_h2f_ieee
97; CHECK-NEXT:    add r1, sp, #8
98; CHECK-NEXT:    bl frexpf
99; CHECK-NEXT:    bl __gnu_f2h_ieee
100; CHECK-NEXT:    strh.w r0, [sp, #14]
101; CHECK-NEXT:    mov r0, r4
102; CHECK-NEXT:    bl __gnu_h2f_ieee
103; CHECK-NEXT:    add r1, sp, #4
104; CHECK-NEXT:    bl frexpf
105; CHECK-NEXT:    bl __gnu_f2h_ieee
106; CHECK-NEXT:    strh.w r0, [sp, #12]
107; CHECK-NEXT:    add r0, sp, #12
108; CHECK-NEXT:    vld1.32 {d16[0]}, [r0:32]
109; CHECK-NEXT:    vmovl.u16 q8, d16
110; CHECK-NEXT:    vmov.32 r0, d16[0]
111; CHECK-NEXT:    vmov.32 r1, d16[1]
112; CHECK-NEXT:    add sp, #16
113; CHECK-NEXT:    pop {r4, pc}
114  %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
115  %result.0 = extractvalue { <2 x half>, <2 x i32> } %result, 0
116  ret <2 x half> %result.0
117}
118
119define <2 x i32> @test_frexp_v2f16_v2i32_only_use_exp(<2 x half> %a) {
120; CHECK-LABEL: test_frexp_v2f16_v2i32_only_use_exp:
121; CHECK:       @ %bb.0:
122; CHECK-NEXT:    push {r4, r5, r7, lr}
123; CHECK-NEXT:    sub sp, #8
124; CHECK-NEXT:    mov r4, r1
125; CHECK-NEXT:    bl __gnu_h2f_ieee
126; CHECK-NEXT:    mov r5, sp
127; CHECK-NEXT:    mov r1, r5
128; CHECK-NEXT:    bl frexpf
129; CHECK-NEXT:    mov r0, r4
130; CHECK-NEXT:    bl __gnu_h2f_ieee
131; CHECK-NEXT:    add r4, sp, #4
132; CHECK-NEXT:    mov r1, r4
133; CHECK-NEXT:    bl frexpf
134; CHECK-NEXT:    vld1.32 {d16[0]}, [r5:32]
135; CHECK-NEXT:    vld1.32 {d16[1]}, [r4:32]
136; CHECK-NEXT:    vmov r0, r1, d16
137; CHECK-NEXT:    add sp, #8
138; CHECK-NEXT:    pop {r4, r5, r7, pc}
139  %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
140  %result.1 = extractvalue { <2 x half>, <2 x i32> } %result, 1
141  ret <2 x i32> %result.1
142}
143
144define { float, i32 } @test_frexp_f32_i32(float %a) {
145; CHECK-LABEL: test_frexp_f32_i32:
146; CHECK:       @ %bb.0:
147; CHECK-NEXT:    push {r7, lr}
148; CHECK-NEXT:    sub sp, #8
149; CHECK-NEXT:    add r1, sp, #4
150; CHECK-NEXT:    bl frexpf
151; CHECK-NEXT:    ldr r1, [sp, #4]
152; CHECK-NEXT:    add sp, #8
153; CHECK-NEXT:    pop {r7, pc}
154  %result = call { float, i32 } @llvm.frexp.f32.i32(float %a)
155  ret { float, i32 } %result
156}
157
158define { float, i32 } @test_frexp_f32_i32_tailcall(float %a) {
159; CHECK-LABEL: test_frexp_f32_i32_tailcall:
160; CHECK:       @ %bb.0:
161; CHECK-NEXT:    push {r7, lr}
162; CHECK-NEXT:    sub sp, #8
163; CHECK-NEXT:    add r1, sp, #4
164; CHECK-NEXT:    bl frexpf
165; CHECK-NEXT:    ldr r1, [sp, #4]
166; CHECK-NEXT:    add sp, #8
167; CHECK-NEXT:    pop {r7, pc}
168  %result = tail call { float, i32 } @llvm.frexp.f32.i32(float %a)
169  ret { float, i32 } %result
170}
171
172define float @test_frexp_f32_i32_only_use_fract(float %a) {
173; CHECK-LABEL: test_frexp_f32_i32_only_use_fract:
174; CHECK:       @ %bb.0:
175; CHECK-NEXT:    push {r7, lr}
176; CHECK-NEXT:    sub sp, #8
177; CHECK-NEXT:    add r1, sp, #4
178; CHECK-NEXT:    bl frexpf
179; CHECK-NEXT:    add sp, #8
180; CHECK-NEXT:    pop {r7, pc}
181  %result = call { float, i32 } @llvm.frexp.f32.i32(float %a)
182  %result.0 = extractvalue { float, i32 } %result, 0
183  ret float %result.0
184}
185
186define i32 @test_frexp_f32_i32_only_use_exp(float %a) {
187; CHECK-LABEL: test_frexp_f32_i32_only_use_exp:
188; CHECK:       @ %bb.0:
189; CHECK-NEXT:    push {r7, lr}
190; CHECK-NEXT:    sub sp, #8
191; CHECK-NEXT:    add r1, sp, #4
192; CHECK-NEXT:    bl frexpf
193; CHECK-NEXT:    ldr r0, [sp, #4]
194; CHECK-NEXT:    add sp, #8
195; CHECK-NEXT:    pop {r7, pc}
196  %result = call { float, i32 } @llvm.frexp.f32.i32(float %a)
197  %result.0 = extractvalue { float, i32 } %result, 1
198  ret i32 %result.0
199}
200
201define { <2 x float>, <2 x i32> } @test_frexp_v2f32_v2i32(<2 x float> %a) {
202; CHECK-LABEL: test_frexp_v2f32_v2i32:
203; CHECK:       @ %bb.0:
204; CHECK-NEXT:    push {r4, r5, r7, lr}
205; CHECK-NEXT:    vpush {d8}
206; CHECK-NEXT:    sub sp, #8
207; CHECK-NEXT:    vmov d8, r0, r1
208; CHECK-NEXT:    add r4, sp, #4
209; CHECK-NEXT:    vmov r0, s16
210; CHECK-NEXT:    mov r1, r4
211; CHECK-NEXT:    bl frexpf
212; CHECK-NEXT:    mov r5, r0
213; CHECK-NEXT:    vmov r0, s17
214; CHECK-NEXT:    vld1.32 {d8[0]}, [r4:32]
215; CHECK-NEXT:    mov r4, sp
216; CHECK-NEXT:    mov r1, r4
217; CHECK-NEXT:    bl frexpf
218; CHECK-NEXT:    vld1.32 {d8[1]}, [r4:32]
219; CHECK-NEXT:    mov r1, r0
220; CHECK-NEXT:    mov r0, r5
221; CHECK-NEXT:    vmov r2, r3, d8
222; CHECK-NEXT:    add sp, #8
223; CHECK-NEXT:    vpop {d8}
224; CHECK-NEXT:    pop {r4, r5, r7, pc}
225  %result = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %a)
226  ret { <2 x float>, <2 x i32> } %result
227}
228
229define <2 x float> @test_frexp_v2f32_v2i32_only_use_fract(<2 x float> %a) {
230; CHECK-LABEL: test_frexp_v2f32_v2i32_only_use_fract:
231; CHECK:       @ %bb.0:
232; CHECK-NEXT:    push {r4, lr}
233; CHECK-NEXT:    vpush {d8}
234; CHECK-NEXT:    sub sp, #8
235; CHECK-NEXT:    vmov d8, r0, r1
236; CHECK-NEXT:    mov r1, sp
237; CHECK-NEXT:    vmov r0, s17
238; CHECK-NEXT:    bl frexpf
239; CHECK-NEXT:    mov r4, r0
240; CHECK-NEXT:    vmov r0, s16
241; CHECK-NEXT:    add r1, sp, #4
242; CHECK-NEXT:    bl frexpf
243; CHECK-NEXT:    mov r1, r4
244; CHECK-NEXT:    add sp, #8
245; CHECK-NEXT:    vpop {d8}
246; CHECK-NEXT:    pop {r4, pc}
247  %result = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %a)
248  %result.0 = extractvalue { <2 x float>, <2 x i32> } %result, 0
249  ret <2 x float> %result.0
250}
251
252define <2 x i32> @test_frexp_v2f32_v2i32_only_use_exp(<2 x float> %a) {
253; CHECK-LABEL: test_frexp_v2f32_v2i32_only_use_exp:
254; CHECK:       @ %bb.0:
255; CHECK-NEXT:    push {r4, r5, r7, lr}
256; CHECK-NEXT:    vpush {d8}
257; CHECK-NEXT:    sub sp, #8
258; CHECK-NEXT:    vmov d8, r0, r1
259; CHECK-NEXT:    add r4, sp, #4
260; CHECK-NEXT:    vmov r0, s16
261; CHECK-NEXT:    mov r1, r4
262; CHECK-NEXT:    bl frexpf
263; CHECK-NEXT:    vmov r0, s17
264; CHECK-NEXT:    mov r5, sp
265; CHECK-NEXT:    mov r1, r5
266; CHECK-NEXT:    bl frexpf
267; CHECK-NEXT:    vld1.32 {d16[0]}, [r4:32]
268; CHECK-NEXT:    vld1.32 {d16[1]}, [r5:32]
269; CHECK-NEXT:    vmov r0, r1, d16
270; CHECK-NEXT:    add sp, #8
271; CHECK-NEXT:    vpop {d8}
272; CHECK-NEXT:    pop {r4, r5, r7, pc}
273  %result = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %a)
274  %result.1 = extractvalue { <2 x float>, <2 x i32> } %result, 1
275  ret <2 x i32> %result.1
276}
277
278define { <4 x float>, <4 x i32> } @test_frexp_v4f32_v4i32(<4 x float> %a) {
279; CHECK-LABEL: test_frexp_v4f32_v4i32:
280; CHECK:       @ %bb.0:
281; CHECK-NEXT:    push.w {r4, r5, r6, r7, r8, r9, lr}
282; CHECK-NEXT:    sub sp, #4
283; CHECK-NEXT:    vpush {d8, d9, d10, d11}
284; CHECK-NEXT:    sub sp, #16
285; CHECK-NEXT:    add.w r8, sp, #12
286; CHECK-NEXT:    mov r4, r0
287; CHECK-NEXT:    mov r0, r2
288; CHECK-NEXT:    mov r5, r3
289; CHECK-NEXT:    mov r1, r8
290; CHECK-NEXT:    bl frexpf
291; CHECK-NEXT:    add r6, sp, #8
292; CHECK-NEXT:    mov r9, r0
293; CHECK-NEXT:    mov r0, r5
294; CHECK-NEXT:    mov r1, r6
295; CHECK-NEXT:    bl frexpf
296; CHECK-NEXT:    vldr d16, [sp, #80]
297; CHECK-NEXT:    mov r5, r0
298; CHECK-NEXT:    vld1.32 {d8[0]}, [r8:32]
299; CHECK-NEXT:    add.w r8, sp, #4
300; CHECK-NEXT:    vmov r0, r7, d16
301; CHECK-NEXT:    mov r1, r8
302; CHECK-NEXT:    vld1.32 {d8[1]}, [r6:32]
303; CHECK-NEXT:    bl frexpf
304; CHECK-NEXT:    vld1.32 {d9[0]}, [r8:32]
305; CHECK-NEXT:    vmov s21, r5
306; CHECK-NEXT:    mov r5, sp
307; CHECK-NEXT:    mov r6, r0
308; CHECK-NEXT:    mov r0, r7
309; CHECK-NEXT:    mov r1, r5
310; CHECK-NEXT:    vmov s20, r9
311; CHECK-NEXT:    bl frexpf
312; CHECK-NEXT:    vmov s23, r0
313; CHECK-NEXT:    vld1.32 {d9[1]}, [r5:32]
314; CHECK-NEXT:    vmov s22, r6
315; CHECK-NEXT:    vst1.32 {d10, d11}, [r4]!
316; CHECK-NEXT:    vst1.64 {d8, d9}, [r4]
317; CHECK-NEXT:    add sp, #16
318; CHECK-NEXT:    vpop {d8, d9, d10, d11}
319; CHECK-NEXT:    add sp, #4
320; CHECK-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, pc}
321  %result = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %a)
322  ret { <4 x float>, <4 x i32> } %result
323}
324
325define <4 x float> @test_frexp_v4f32_v4i32_only_use_fract(<4 x float> %a) {
326; CHECK-LABEL: test_frexp_v4f32_v4i32_only_use_fract:
327; CHECK:       @ %bb.0:
328; CHECK-NEXT:    push {r4, r5, r6, lr}
329; CHECK-NEXT:    vpush {d8, d9}
330; CHECK-NEXT:    sub sp, #16
331; CHECK-NEXT:    mov r5, r1
332; CHECK-NEXT:    mov r6, r0
333; CHECK-NEXT:    mov r1, sp
334; CHECK-NEXT:    mov r0, r3
335; CHECK-NEXT:    mov r4, r2
336; CHECK-NEXT:    bl frexpf
337; CHECK-NEXT:    add r1, sp, #4
338; CHECK-NEXT:    vmov s19, r0
339; CHECK-NEXT:    mov r0, r4
340; CHECK-NEXT:    bl frexpf
341; CHECK-NEXT:    add r1, sp, #8
342; CHECK-NEXT:    vmov s18, r0
343; CHECK-NEXT:    mov r0, r5
344; CHECK-NEXT:    bl frexpf
345; CHECK-NEXT:    add r1, sp, #12
346; CHECK-NEXT:    vmov s17, r0
347; CHECK-NEXT:    mov r0, r6
348; CHECK-NEXT:    bl frexpf
349; CHECK-NEXT:    vmov s16, r0
350; CHECK-NEXT:    vmov r2, r3, d9
351; CHECK-NEXT:    vmov r0, r1, d8
352; CHECK-NEXT:    add sp, #16
353; CHECK-NEXT:    vpop {d8, d9}
354; CHECK-NEXT:    pop {r4, r5, r6, pc}
355  %result = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %a)
356  %result.0 = extractvalue { <4 x float>, <4 x i32> } %result, 0
357  ret <4 x float> %result.0
358}
359
360define <4 x i32> @test_frexp_v4f32_v4i32_only_use_exp(<4 x float> %a) {
361; CHECK-LABEL: test_frexp_v4f32_v4i32_only_use_exp:
362; CHECK:       @ %bb.0:
363; CHECK-NEXT:    push {r4, r5, r6, lr}
364; CHECK-NEXT:    sub sp, #16
365; CHECK-NEXT:    mov r6, r1
366; CHECK-NEXT:    add r1, sp, #12
367; CHECK-NEXT:    mov r4, r3
368; CHECK-NEXT:    mov r5, r2
369; CHECK-NEXT:    bl frexpf
370; CHECK-NEXT:    add r1, sp, #8
371; CHECK-NEXT:    mov r0, r6
372; CHECK-NEXT:    bl frexpf
373; CHECK-NEXT:    add r1, sp, #4
374; CHECK-NEXT:    mov r0, r5
375; CHECK-NEXT:    bl frexpf
376; CHECK-NEXT:    mov r1, sp
377; CHECK-NEXT:    mov r0, r4
378; CHECK-NEXT:    bl frexpf
379; CHECK-NEXT:    ldrd r1, r0, [sp, #8]
380; CHECK-NEXT:    ldrd r3, r2, [sp], #16
381; CHECK-NEXT:    pop {r4, r5, r6, pc}
382  %result = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %a)
383  %result.1 = extractvalue { <4 x float>, <4 x i32> } %result, 1
384  ret <4 x i32> %result.1
385}
386
387define { double, i32 } @test_frexp_f64_i32(double %a) {
388; CHECK-LABEL: test_frexp_f64_i32:
389; CHECK:       @ %bb.0:
390; CHECK-NEXT:    push {r7, lr}
391; CHECK-NEXT:    sub sp, #8
392; CHECK-NEXT:    add r2, sp, #4
393; CHECK-NEXT:    bl frexp
394; CHECK-NEXT:    ldr r2, [sp, #4]
395; CHECK-NEXT:    add sp, #8
396; CHECK-NEXT:    pop {r7, pc}
397  %result = call { double, i32 } @llvm.frexp.f64.i32(double %a)
398  ret { double, i32 } %result
399}
400
401define double @test_frexp_f64_i32_only_use_fract(double %a) {
402; CHECK-LABEL: test_frexp_f64_i32_only_use_fract:
403; CHECK:       @ %bb.0:
404; CHECK-NEXT:    push {r7, lr}
405; CHECK-NEXT:    sub sp, #8
406; CHECK-NEXT:    add r2, sp, #4
407; CHECK-NEXT:    bl frexp
408; CHECK-NEXT:    add sp, #8
409; CHECK-NEXT:    pop {r7, pc}
410  %result = call { double, i32 } @llvm.frexp.f64.i32(double %a)
411  %result.0 = extractvalue { double, i32 } %result, 0
412  ret double %result.0
413}
414
415define i32 @test_frexp_f64_i32_only_use_exp(double %a) {
416; CHECK-LABEL: test_frexp_f64_i32_only_use_exp:
417; CHECK:       @ %bb.0:
418; CHECK-NEXT:    push {r7, lr}
419; CHECK-NEXT:    sub sp, #8
420; CHECK-NEXT:    add r2, sp, #4
421; CHECK-NEXT:    bl frexp
422; CHECK-NEXT:    ldr r0, [sp, #4]
423; CHECK-NEXT:    add sp, #8
424; CHECK-NEXT:    pop {r7, pc}
425  %result = call { double, i32 } @llvm.frexp.f64.i32(double %a)
426  %result.0 = extractvalue { double, i32 } %result, 1
427  ret i32 %result.0
428}
429
430define { <2 x double>, <2 x i32> } @test_frexp_v2f64_v2i32(<2 x double> %a) {
431; CHECK-LABEL: test_frexp_v2f64_v2i32:
432; CHECK:       @ %bb.0:
433; CHECK-NEXT:    push.w {r4, r5, r6, r7, r8, lr}
434; CHECK-NEXT:    sub sp, #8
435; CHECK-NEXT:    add.w r8, sp, #4
436; CHECK-NEXT:    mov r4, r0
437; CHECK-NEXT:    mov r0, r2
438; CHECK-NEXT:    mov r1, r3
439; CHECK-NEXT:    mov r2, r8
440; CHECK-NEXT:    bl frexp
441; CHECK-NEXT:    mov r6, r0
442; CHECK-NEXT:    mov r7, r1
443; CHECK-NEXT:    ldrd r0, r1, [sp, #32]
444; CHECK-NEXT:    mov r5, sp
445; CHECK-NEXT:    mov r2, r5
446; CHECK-NEXT:    bl frexp
447; CHECK-NEXT:    vld1.32 {d16[0]}, [r8:32]
448; CHECK-NEXT:    vmov d18, r6, r7
449; CHECK-NEXT:    vmov d19, r0, r1
450; CHECK-NEXT:    vld1.32 {d16[1]}, [r5:32]
451; CHECK-NEXT:    vst1.64 {d18, d19}, [r4]!
452; CHECK-NEXT:    vstr d16, [r4]
453; CHECK-NEXT:    add sp, #8
454; CHECK-NEXT:    pop.w {r4, r5, r6, r7, r8, pc}
455  %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
456  ret { <2 x double>, <2 x i32> } %result
457}
458
459define <2 x double> @test_frexp_v2f64_v2i32_only_use_fract(<2 x double> %a) {
460; CHECK-LABEL: test_frexp_v2f64_v2i32_only_use_fract:
461; CHECK:       @ %bb.0:
462; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
463; CHECK-NEXT:    sub sp, #12
464; CHECK-NEXT:    mov r5, r2
465; CHECK-NEXT:    add r2, sp, #4
466; CHECK-NEXT:    mov r4, r3
467; CHECK-NEXT:    bl frexp
468; CHECK-NEXT:    add r2, sp, #8
469; CHECK-NEXT:    mov r6, r0
470; CHECK-NEXT:    mov r7, r1
471; CHECK-NEXT:    mov r0, r5
472; CHECK-NEXT:    mov r1, r4
473; CHECK-NEXT:    bl frexp
474; CHECK-NEXT:    mov r2, r0
475; CHECK-NEXT:    mov r3, r1
476; CHECK-NEXT:    mov r0, r6
477; CHECK-NEXT:    mov r1, r7
478; CHECK-NEXT:    add sp, #12
479; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
480  %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
481  %result.0 = extractvalue { <2 x double>, <2 x i32> } %result, 0
482  ret <2 x double> %result.0
483}
484
485define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) {
486; CHECK-LABEL: test_frexp_v2f64_v2i32_only_use_exp:
487; CHECK:       @ %bb.0:
488; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
489; CHECK-NEXT:    sub sp, #12
490; CHECK-NEXT:    add r6, sp, #4
491; CHECK-NEXT:    mov r5, r2
492; CHECK-NEXT:    mov r4, r3
493; CHECK-NEXT:    mov r2, r6
494; CHECK-NEXT:    bl frexp
495; CHECK-NEXT:    add r7, sp, #8
496; CHECK-NEXT:    mov r0, r5
497; CHECK-NEXT:    mov r1, r4
498; CHECK-NEXT:    mov r2, r7
499; CHECK-NEXT:    bl frexp
500; CHECK-NEXT:    vld1.32 {d16[0]}, [r6:32]
501; CHECK-NEXT:    vld1.32 {d16[1]}, [r7:32]
502; CHECK-NEXT:    vmov r0, r1, d16
503; CHECK-NEXT:    add sp, #12
504; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
505  %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
506  %result.1 = extractvalue { <2 x double>, <2 x i32> } %result, 1
507  ret <2 x i32> %result.1
508}
509
510declare { float, i32 } @llvm.frexp.f32.i32(float) #0
511declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
512declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) #0
513
514declare { half, i32 } @llvm.frexp.f16.i32(half) #0
515declare { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half>) #0
516
517declare { double, i32 } @llvm.frexp.f64.i32(double) #0
518declare { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double>) #0
519
520declare { half, i16 } @llvm.frexp.f16.i16(half) #0
521declare { <2 x half>, <2 x i16> } @llvm.frexp.v2f16.v2i16(<2 x half>) #0
522
523attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
524