Skip to content

Commit d801b54

Browse files
authored
ARM: Fix calling convention for gnu half conversion functions (#147951)
I'm surprised at how bad the test coverage is here. There is some overlap with existing tests, but they aren't comprehensive and do not cover all the ABIs, or all the different types. Fixes #147935
1 parent 498aead commit d801b54

File tree

2 files changed

+281
-0
lines changed

2 files changed

+281
-0
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,10 +715,14 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
715715
setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_AAPCS);
716716
setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_AAPCS);
717717
setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_AAPCS);
718+
setLibcallImplCallingConv(RTLIB::__gnu_h2f_ieee, CallingConv::ARM_AAPCS);
719+
setLibcallImplCallingConv(RTLIB::__gnu_f2h_ieee, CallingConv::ARM_AAPCS);
718720
} else {
719721
setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_APCS);
720722
setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_APCS);
721723
setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_APCS);
724+
setLibcallImplCallingConv(RTLIB::__gnu_h2f_ieee, CallingConv::ARM_APCS);
725+
setLibcallImplCallingConv(RTLIB::__gnu_f2h_ieee, CallingConv::ARM_APCS);
722726
}
723727
}
724728

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=arm-unknown-linux-gnueabihf -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-HARD,GNU-AAPCS-HARD %s
3+
; RUN: llc -mtriple=arm-unknown-linux-gnueabi -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-SOFT,GNU-AAPCS-SOFT %s
4+
; RUN: llc -mtriple=arm-unknown-linux-eabihf -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-HARD,EABI-HARD %s
5+
; RUN: llc -mtriple=arm-unknown-linux-eabi -mattr=+vfp2 < %s | FileCheck -check-prefixes=AAPCS-SOFT,EABI-SOFT %s
6+
; RUN: llc -mtriple=armv7-unknown-linux -target-abi=apcs -float-abi=soft < %s | FileCheck -check-prefix=APCS %s
7+
; RUN: llc -mtriple=armv7-unknown-linux -target-abi=apcs -float-abi=hard < %s | FileCheck -check-prefix=APCS %s
8+
9+
define i1 @test(half %self) #0 {
10+
; GNU-AAPCS-HARD-LABEL: test:
11+
; GNU-AAPCS-HARD: @ %bb.0:
12+
; GNU-AAPCS-HARD-NEXT: .save {r11, lr}
13+
; GNU-AAPCS-HARD-NEXT: push {r11, lr}
14+
; GNU-AAPCS-HARD-NEXT: vmov r0, s0
15+
; GNU-AAPCS-HARD-NEXT: bl __gnu_h2f_ieee
16+
; GNU-AAPCS-HARD-NEXT: vmov s0, r0
17+
; GNU-AAPCS-HARD-NEXT: mov r0, #0
18+
; GNU-AAPCS-HARD-NEXT: vcmp.f32 s0, s0
19+
; GNU-AAPCS-HARD-NEXT: vmrs APSR_nzcv, fpscr
20+
; GNU-AAPCS-HARD-NEXT: movvs r0, #1
21+
; GNU-AAPCS-HARD-NEXT: pop {r11, lr}
22+
; GNU-AAPCS-HARD-NEXT: mov pc, lr
23+
;
24+
; GNU-AAPCS-SOFT-LABEL: test:
25+
; GNU-AAPCS-SOFT: @ %bb.0:
26+
; GNU-AAPCS-SOFT-NEXT: .save {r11, lr}
27+
; GNU-AAPCS-SOFT-NEXT: push {r11, lr}
28+
; GNU-AAPCS-SOFT-NEXT: bl __gnu_h2f_ieee
29+
; GNU-AAPCS-SOFT-NEXT: vmov s0, r0
30+
; GNU-AAPCS-SOFT-NEXT: mov r0, #0
31+
; GNU-AAPCS-SOFT-NEXT: vcmp.f32 s0, s0
32+
; GNU-AAPCS-SOFT-NEXT: vmrs APSR_nzcv, fpscr
33+
; GNU-AAPCS-SOFT-NEXT: movvs r0, #1
34+
; GNU-AAPCS-SOFT-NEXT: pop {r11, lr}
35+
; GNU-AAPCS-SOFT-NEXT: mov pc, lr
36+
;
37+
; EABI-HARD-LABEL: test:
38+
; EABI-HARD: @ %bb.0:
39+
; EABI-HARD-NEXT: .save {r11, lr}
40+
; EABI-HARD-NEXT: push {r11, lr}
41+
; EABI-HARD-NEXT: vmov r0, s0
42+
; EABI-HARD-NEXT: bl __aeabi_h2f
43+
; EABI-HARD-NEXT: vmov s0, r0
44+
; EABI-HARD-NEXT: mov r0, #0
45+
; EABI-HARD-NEXT: vcmp.f32 s0, s0
46+
; EABI-HARD-NEXT: vmrs APSR_nzcv, fpscr
47+
; EABI-HARD-NEXT: movvs r0, #1
48+
; EABI-HARD-NEXT: pop {r11, lr}
49+
; EABI-HARD-NEXT: mov pc, lr
50+
;
51+
; EABI-SOFT-LABEL: test:
52+
; EABI-SOFT: @ %bb.0:
53+
; EABI-SOFT-NEXT: .save {r11, lr}
54+
; EABI-SOFT-NEXT: push {r11, lr}
55+
; EABI-SOFT-NEXT: bl __aeabi_h2f
56+
; EABI-SOFT-NEXT: vmov s0, r0
57+
; EABI-SOFT-NEXT: mov r0, #0
58+
; EABI-SOFT-NEXT: vcmp.f32 s0, s0
59+
; EABI-SOFT-NEXT: vmrs APSR_nzcv, fpscr
60+
; EABI-SOFT-NEXT: movvs r0, #1
61+
; EABI-SOFT-NEXT: pop {r11, lr}
62+
; EABI-SOFT-NEXT: mov pc, lr
63+
;
64+
; APCS-LABEL: test:
65+
; APCS: @ %bb.0:
66+
; APCS-NEXT: push {lr}
67+
; APCS-NEXT: bl __gnu_h2f_ieee
68+
; APCS-NEXT: vmov s0, r0
69+
; APCS-NEXT: mov r0, #0
70+
; APCS-NEXT: vcmp.f32 s0, s0
71+
; APCS-NEXT: vmrs APSR_nzcv, fpscr
72+
; APCS-NEXT: movwvs r0, #1
73+
; APCS-NEXT: pop {lr}
74+
; APCS-NEXT: bx lr
75+
%_0 = fcmp une half %self, %self
76+
ret i1 %_0
77+
}
78+
79+
define float @f16_to_f32(ptr %p) #0 {
80+
; GNU-AAPCS-HARD-LABEL: f16_to_f32:
81+
; GNU-AAPCS-HARD: @ %bb.0:
82+
; GNU-AAPCS-HARD-NEXT: .save {r11, lr}
83+
; GNU-AAPCS-HARD-NEXT: push {r11, lr}
84+
; GNU-AAPCS-HARD-NEXT: ldrh r0, [r0]
85+
; GNU-AAPCS-HARD-NEXT: bl __gnu_h2f_ieee
86+
; GNU-AAPCS-HARD-NEXT: vmov s0, r0
87+
; GNU-AAPCS-HARD-NEXT: pop {r11, lr}
88+
; GNU-AAPCS-HARD-NEXT: mov pc, lr
89+
;
90+
; GNU-AAPCS-SOFT-LABEL: f16_to_f32:
91+
; GNU-AAPCS-SOFT: @ %bb.0:
92+
; GNU-AAPCS-SOFT-NEXT: ldrh r0, [r0]
93+
; GNU-AAPCS-SOFT-NEXT: b __gnu_h2f_ieee
94+
;
95+
; EABI-HARD-LABEL: f16_to_f32:
96+
; EABI-HARD: @ %bb.0:
97+
; EABI-HARD-NEXT: .save {r11, lr}
98+
; EABI-HARD-NEXT: push {r11, lr}
99+
; EABI-HARD-NEXT: ldrh r0, [r0]
100+
; EABI-HARD-NEXT: bl __aeabi_h2f
101+
; EABI-HARD-NEXT: vmov s0, r0
102+
; EABI-HARD-NEXT: pop {r11, lr}
103+
; EABI-HARD-NEXT: mov pc, lr
104+
;
105+
; EABI-SOFT-LABEL: f16_to_f32:
106+
; EABI-SOFT: @ %bb.0:
107+
; EABI-SOFT-NEXT: ldrh r0, [r0]
108+
; EABI-SOFT-NEXT: b __aeabi_h2f
109+
;
110+
; APCS-LABEL: f16_to_f32:
111+
; APCS: @ %bb.0:
112+
; APCS-NEXT: ldrh r0, [r0]
113+
; APCS-NEXT: b __gnu_h2f_ieee
114+
%load = load half, ptr %p
115+
%cvt = fpext half %load to float
116+
ret float %cvt
117+
}
118+
119+
define void @f32_to_f16(ptr %p, float %arg) #0 {
120+
; GNU-AAPCS-HARD-LABEL: f32_to_f16:
121+
; GNU-AAPCS-HARD: @ %bb.0:
122+
; GNU-AAPCS-HARD-NEXT: .save {r4, lr}
123+
; GNU-AAPCS-HARD-NEXT: push {r4, lr}
124+
; GNU-AAPCS-HARD-NEXT: mov r4, r0
125+
; GNU-AAPCS-HARD-NEXT: vmov r0, s0
126+
; GNU-AAPCS-HARD-NEXT: bl __gnu_f2h_ieee
127+
; GNU-AAPCS-HARD-NEXT: strh r0, [r4]
128+
; GNU-AAPCS-HARD-NEXT: pop {r4, lr}
129+
; GNU-AAPCS-HARD-NEXT: mov pc, lr
130+
;
131+
; GNU-AAPCS-SOFT-LABEL: f32_to_f16:
132+
; GNU-AAPCS-SOFT: @ %bb.0:
133+
; GNU-AAPCS-SOFT-NEXT: .save {r4, lr}
134+
; GNU-AAPCS-SOFT-NEXT: push {r4, lr}
135+
; GNU-AAPCS-SOFT-NEXT: mov r4, r0
136+
; GNU-AAPCS-SOFT-NEXT: mov r0, r1
137+
; GNU-AAPCS-SOFT-NEXT: bl __gnu_f2h_ieee
138+
; GNU-AAPCS-SOFT-NEXT: strh r0, [r4]
139+
; GNU-AAPCS-SOFT-NEXT: pop {r4, lr}
140+
; GNU-AAPCS-SOFT-NEXT: mov pc, lr
141+
;
142+
; EABI-HARD-LABEL: f32_to_f16:
143+
; EABI-HARD: @ %bb.0:
144+
; EABI-HARD-NEXT: .save {r4, lr}
145+
; EABI-HARD-NEXT: push {r4, lr}
146+
; EABI-HARD-NEXT: mov r4, r0
147+
; EABI-HARD-NEXT: vmov r0, s0
148+
; EABI-HARD-NEXT: bl __aeabi_f2h
149+
; EABI-HARD-NEXT: strh r0, [r4]
150+
; EABI-HARD-NEXT: pop {r4, lr}
151+
; EABI-HARD-NEXT: mov pc, lr
152+
;
153+
; EABI-SOFT-LABEL: f32_to_f16:
154+
; EABI-SOFT: @ %bb.0:
155+
; EABI-SOFT-NEXT: .save {r4, lr}
156+
; EABI-SOFT-NEXT: push {r4, lr}
157+
; EABI-SOFT-NEXT: mov r4, r0
158+
; EABI-SOFT-NEXT: mov r0, r1
159+
; EABI-SOFT-NEXT: bl __aeabi_f2h
160+
; EABI-SOFT-NEXT: strh r0, [r4]
161+
; EABI-SOFT-NEXT: pop {r4, lr}
162+
; EABI-SOFT-NEXT: mov pc, lr
163+
;
164+
; APCS-LABEL: f32_to_f16:
165+
; APCS: @ %bb.0:
166+
; APCS-NEXT: push {r4, lr}
167+
; APCS-NEXT: mov r4, r0
168+
; APCS-NEXT: mov r0, r1
169+
; APCS-NEXT: bl __gnu_f2h_ieee
170+
; APCS-NEXT: strh r0, [r4]
171+
; APCS-NEXT: pop {r4, pc}
172+
%cvt = fptrunc float %arg to half
173+
store half %cvt, ptr %p
174+
ret void
175+
}
176+
177+
define double @f16_to_f64(ptr %p) #0 {
178+
; GNU-AAPCS-HARD-LABEL: f16_to_f64:
179+
; GNU-AAPCS-HARD: @ %bb.0:
180+
; GNU-AAPCS-HARD-NEXT: .save {r11, lr}
181+
; GNU-AAPCS-HARD-NEXT: push {r11, lr}
182+
; GNU-AAPCS-HARD-NEXT: ldrh r0, [r0]
183+
; GNU-AAPCS-HARD-NEXT: bl __gnu_h2f_ieee
184+
; GNU-AAPCS-HARD-NEXT: vmov s0, r0
185+
; GNU-AAPCS-HARD-NEXT: vcvt.f64.f32 d0, s0
186+
; GNU-AAPCS-HARD-NEXT: pop {r11, lr}
187+
; GNU-AAPCS-HARD-NEXT: mov pc, lr
188+
;
189+
; GNU-AAPCS-SOFT-LABEL: f16_to_f64:
190+
; GNU-AAPCS-SOFT: @ %bb.0:
191+
; GNU-AAPCS-SOFT-NEXT: .save {r11, lr}
192+
; GNU-AAPCS-SOFT-NEXT: push {r11, lr}
193+
; GNU-AAPCS-SOFT-NEXT: ldrh r0, [r0]
194+
; GNU-AAPCS-SOFT-NEXT: bl __gnu_h2f_ieee
195+
; GNU-AAPCS-SOFT-NEXT: vmov s0, r0
196+
; GNU-AAPCS-SOFT-NEXT: vcvt.f64.f32 d0, s0
197+
; GNU-AAPCS-SOFT-NEXT: vmov r0, r1, d0
198+
; GNU-AAPCS-SOFT-NEXT: pop {r11, lr}
199+
; GNU-AAPCS-SOFT-NEXT: mov pc, lr
200+
;
201+
; EABI-HARD-LABEL: f16_to_f64:
202+
; EABI-HARD: @ %bb.0:
203+
; EABI-HARD-NEXT: .save {r11, lr}
204+
; EABI-HARD-NEXT: push {r11, lr}
205+
; EABI-HARD-NEXT: ldrh r0, [r0]
206+
; EABI-HARD-NEXT: bl __aeabi_h2f
207+
; EABI-HARD-NEXT: vmov s0, r0
208+
; EABI-HARD-NEXT: vcvt.f64.f32 d0, s0
209+
; EABI-HARD-NEXT: pop {r11, lr}
210+
; EABI-HARD-NEXT: mov pc, lr
211+
;
212+
; EABI-SOFT-LABEL: f16_to_f64:
213+
; EABI-SOFT: @ %bb.0:
214+
; EABI-SOFT-NEXT: .save {r11, lr}
215+
; EABI-SOFT-NEXT: push {r11, lr}
216+
; EABI-SOFT-NEXT: ldrh r0, [r0]
217+
; EABI-SOFT-NEXT: bl __aeabi_h2f
218+
; EABI-SOFT-NEXT: vmov s0, r0
219+
; EABI-SOFT-NEXT: vcvt.f64.f32 d0, s0
220+
; EABI-SOFT-NEXT: vmov r0, r1, d0
221+
; EABI-SOFT-NEXT: pop {r11, lr}
222+
; EABI-SOFT-NEXT: mov pc, lr
223+
;
224+
; APCS-LABEL: f16_to_f64:
225+
; APCS: @ %bb.0:
226+
; APCS-NEXT: push {lr}
227+
; APCS-NEXT: ldrh r0, [r0]
228+
; APCS-NEXT: bl __gnu_h2f_ieee
229+
; APCS-NEXT: vmov s0, r0
230+
; APCS-NEXT: vcvt.f64.f32 d16, s0
231+
; APCS-NEXT: vmov r0, r1, d16
232+
; APCS-NEXT: pop {lr}
233+
; APCS-NEXT: bx lr
234+
%load = load half, ptr %p
235+
%cvt = fpext half %load to double
236+
ret double %cvt
237+
}
238+
239+
define void @f64_to_f16(ptr %p, double %arg) #0 {
240+
; AAPCS-HARD-LABEL: f64_to_f16:
241+
; AAPCS-HARD: @ %bb.0:
242+
; AAPCS-HARD-NEXT: .save {r4, lr}
243+
; AAPCS-HARD-NEXT: push {r4, lr}
244+
; AAPCS-HARD-NEXT: mov r4, r0
245+
; AAPCS-HARD-NEXT: vmov r0, r1, d0
246+
; AAPCS-HARD-NEXT: bl __aeabi_d2h
247+
; AAPCS-HARD-NEXT: strh r0, [r4]
248+
; AAPCS-HARD-NEXT: pop {r4, lr}
249+
; AAPCS-HARD-NEXT: mov pc, lr
250+
;
251+
; AAPCS-SOFT-LABEL: f64_to_f16:
252+
; AAPCS-SOFT: @ %bb.0:
253+
; AAPCS-SOFT-NEXT: .save {r4, lr}
254+
; AAPCS-SOFT-NEXT: push {r4, lr}
255+
; AAPCS-SOFT-NEXT: mov r4, r0
256+
; AAPCS-SOFT-NEXT: mov r1, r3
257+
; AAPCS-SOFT-NEXT: mov r0, r2
258+
; AAPCS-SOFT-NEXT: bl __aeabi_d2h
259+
; AAPCS-SOFT-NEXT: strh r0, [r4]
260+
; AAPCS-SOFT-NEXT: pop {r4, lr}
261+
; AAPCS-SOFT-NEXT: mov pc, lr
262+
;
263+
; APCS-LABEL: f64_to_f16:
264+
; APCS: @ %bb.0:
265+
; APCS-NEXT: push {r4, lr}
266+
; APCS-NEXT: mov r4, r0
267+
; APCS-NEXT: mov r0, r1
268+
; APCS-NEXT: mov r1, r2
269+
; APCS-NEXT: bl __truncdfhf2
270+
; APCS-NEXT: strh r0, [r4]
271+
; APCS-NEXT: pop {r4, pc}
272+
%cvt = fptrunc double %arg to half
273+
store half %cvt, ptr %p
274+
ret void
275+
}
276+
277+
attributes #0 = { nounwind }

0 commit comments

Comments
 (0)