AArch64: Better codegen for storing to __fp16.
[oota-llvm.git] / test / CodeGen / AArch64 / f16-convert.ll
1 ; RUN: llc < %s -mtriple=arm64-apple-ios -asm-verbose=false | FileCheck %s
2
3 define float @load0(i16* nocapture readonly %a) nounwind {
4 ; CHECK-LABEL: load0:
5 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0]
6 ; CHECK-NEXT: fcvt s0, [[HREG]]
7 ; CHECK-NEXT: ret
8
9   %tmp = load i16* %a, align 2
10   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
11   ret float %tmp1
12 }
13
14 define double @load1(i16* nocapture readonly %a) nounwind {
15 ; CHECK-LABEL: load1:
16 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0]
17 ; CHECK-NEXT: fcvt d0, [[HREG]]
18 ; CHECK-NEXT: ret
19
20   %tmp = load i16* %a, align 2
21   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
22   %conv = fpext float %tmp1 to double
23   ret double %conv
24 }
25
26 define float @load2(i16* nocapture readonly %a, i32 %i) nounwind {
27 ; CHECK-LABEL: load2:
28 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1]
29 ; CHECK-NEXT: fcvt s0, [[HREG]]
30 ; CHECK-NEXT: ret
31
32   %idxprom = sext i32 %i to i64
33   %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
34   %tmp = load i16* %arrayidx, align 2
35   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
36   ret float %tmp1
37 }
38
39 define double @load3(i16* nocapture readonly %a, i32 %i) nounwind {
40 ; CHECK-LABEL: load3:
41 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1]
42 ; CHECK-NEXT: fcvt d0, [[HREG]]
43 ; CHECK-NEXT: ret
44
45   %idxprom = sext i32 %i to i64
46   %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
47   %tmp = load i16* %arrayidx, align 2
48   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
49   %conv = fpext float %tmp1 to double
50   ret double %conv
51 }
52
53 define float @load4(i16* nocapture readonly %a, i64 %i) nounwind {
54 ; CHECK-LABEL: load4:
55 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1]
56 ; CHECK-NEXT: fcvt s0, [[HREG]]
57 ; CHECK-NEXT: ret
58
59   %arrayidx = getelementptr inbounds i16* %a, i64 %i
60   %tmp = load i16* %arrayidx, align 2
61   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
62   ret float %tmp1
63 }
64
65 define double @load5(i16* nocapture readonly %a, i64 %i) nounwind {
66 ; CHECK-LABEL: load5:
67 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1]
68 ; CHECK-NEXT: fcvt d0, [[HREG]]
69 ; CHECK-NEXT: ret
70
71   %arrayidx = getelementptr inbounds i16* %a, i64 %i
72   %tmp = load i16* %arrayidx, align 2
73   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
74   %conv = fpext float %tmp1 to double
75   ret double %conv
76 }
77
78 define float @load6(i16* nocapture readonly %a) nounwind {
79 ; CHECK-LABEL: load6:
80 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20]
81 ; CHECK-NEXT: fcvt s0, [[HREG]]
82 ; CHECK-NEXT: ret
83
84   %arrayidx = getelementptr inbounds i16* %a, i64 10
85   %tmp = load i16* %arrayidx, align 2
86   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
87   ret float %tmp1
88 }
89
90 define double @load7(i16* nocapture readonly %a) nounwind {
91 ; CHECK-LABEL: load7:
92 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20]
93 ; CHECK-NEXT: fcvt d0, [[HREG]]
94 ; CHECK-NEXT: ret
95
96   %arrayidx = getelementptr inbounds i16* %a, i64 10
97   %tmp = load i16* %arrayidx, align 2
98   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
99   %conv = fpext float %tmp1 to double
100   ret double %conv
101 }
102
103 define float @load8(i16* nocapture readonly %a) nounwind {
104 ; CHECK-LABEL: load8:
105 ; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20]
106 ; CHECK-NEXT: fcvt s0, [[HREG]]
107 ; CHECK-NEXT: ret
108
109   %arrayidx = getelementptr inbounds i16* %a, i64 -10
110   %tmp = load i16* %arrayidx, align 2
111   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
112   ret float %tmp1
113 }
114
115 define double @load9(i16* nocapture readonly %a) nounwind {
116 ; CHECK-LABEL: load9:
117 ; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20]
118 ; CHECK-NEXT: fcvt d0, [[HREG]]
119 ; CHECK-NEXT: ret
120
121   %arrayidx = getelementptr inbounds i16* %a, i64 -10
122   %tmp = load i16* %arrayidx, align 2
123   %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp)
124   %conv = fpext float %tmp1 to double
125   ret double %conv
126 }
127
128 define void @store0(i16* nocapture %a, float %val) nounwind {
129 ; CHECK-LABEL: store0:
130 ; CHECK-NEXT: fcvt h0, s0
131 ; CHECK-NEXT: str  h0, [x0]
132 ; CHECK-NEXT: ret
133
134   %tmp = tail call i16 @llvm.convert.to.fp16(float %val)
135   store i16 %tmp, i16* %a, align 2
136   ret void
137 }
138
139 define void @store1(i16* nocapture %a, double %val) nounwind {
140 ; CHECK-LABEL: store1:
141 ; CHECK-NEXT: fcvt h0, d0
142 ; CHECK-NEXT: str  h0, [x0]
143 ; CHECK-NEXT: ret
144
145   %conv = fptrunc double %val to float
146   %tmp = tail call i16 @llvm.convert.to.fp16(float %conv)
147   store i16 %tmp, i16* %a, align 2
148   ret void
149 }
150
151 define void @store2(i16* nocapture %a, i32 %i, float %val) nounwind {
152 ; CHECK-LABEL: store2:
153 ; CHECK-NEXT: fcvt h0, s0
154 ; CHECK-NEXT: str h0, [x0, w1, sxtw #1]
155 ; CHECK-NEXT: ret
156
157   %tmp = tail call i16 @llvm.convert.to.fp16(float %val)
158   %idxprom = sext i32 %i to i64
159   %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
160   store i16 %tmp, i16* %arrayidx, align 2
161   ret void
162 }
163
164 define void @store3(i16* nocapture %a, i32 %i, double %val) nounwind {
165 ; CHECK-LABEL: store3:
166 ; CHECK-NEXT: fcvt h0, d0
167 ; CHECK-NEXT: str h0, [x0, w1, sxtw #1]
168 ; CHECK-NEXT: ret
169
170   %conv = fptrunc double %val to float
171   %tmp = tail call i16 @llvm.convert.to.fp16(float %conv)
172   %idxprom = sext i32 %i to i64
173   %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
174   store i16 %tmp, i16* %arrayidx, align 2
175   ret void
176 }
177
178 define void @store4(i16* nocapture %a, i64 %i, float %val) nounwind {
179 ; CHECK-LABEL: store4:
180 ; CHECK-NEXT: fcvt h0, s0
181 ; CHECK-NEXT: str h0, [x0, x1, lsl #1]
182 ; CHECK-NEXT: ret
183
184   %tmp = tail call i16 @llvm.convert.to.fp16(float %val)
185   %arrayidx = getelementptr inbounds i16* %a, i64 %i
186   store i16 %tmp, i16* %arrayidx, align 2
187   ret void
188 }
189
190 define void @store5(i16* nocapture %a, i64 %i, double %val) nounwind {
191 ; CHECK-LABEL: store5:
192 ; CHECK-NEXT: fcvt h0, d0
193 ; CHECK-NEXT: str h0, [x0, x1, lsl #1]
194 ; CHECK-NEXT: ret
195
196   %conv = fptrunc double %val to float
197   %tmp = tail call i16 @llvm.convert.to.fp16(float %conv)
198   %arrayidx = getelementptr inbounds i16* %a, i64 %i
199   store i16 %tmp, i16* %arrayidx, align 2
200   ret void
201 }
202
203 define void @store6(i16* nocapture %a, float %val) nounwind {
204 ; CHECK-LABEL: store6:
205 ; CHECK-NEXT: fcvt h0, s0
206 ; CHECK-NEXT: str h0, [x0, #20]
207 ; CHECK-NEXT: ret
208
209   %tmp = tail call i16 @llvm.convert.to.fp16(float %val)
210   %arrayidx = getelementptr inbounds i16* %a, i64 10
211   store i16 %tmp, i16* %arrayidx, align 2
212   ret void
213 }
214
215 define void @store7(i16* nocapture %a, double %val) nounwind {
216 ; CHECK-LABEL: store7:
217 ; CHECK-NEXT: fcvt h0, d0
218 ; CHECK-NEXT: str h0, [x0, #20]
219 ; CHECK-NEXT: ret
220
221   %conv = fptrunc double %val to float
222   %tmp = tail call i16 @llvm.convert.to.fp16(float %conv)
223   %arrayidx = getelementptr inbounds i16* %a, i64 10
224   store i16 %tmp, i16* %arrayidx, align 2
225   ret void
226 }
227
228 define void @store8(i16* nocapture %a, float %val) nounwind {
229 ; CHECK-LABEL: store8:
230 ; CHECK-NEXT: fcvt h0, s0
231 ; CHECK-NEXT: stur h0, [x0, #-20]
232 ; CHECK-NEXT: ret
233
234   %tmp = tail call i16 @llvm.convert.to.fp16(float %val)
235   %arrayidx = getelementptr inbounds i16* %a, i64 -10
236   store i16 %tmp, i16* %arrayidx, align 2
237   ret void
238 }
239
240 define void @store9(i16* nocapture %a, double %val) nounwind {
241 ; CHECK-LABEL: store9:
242 ; CHECK-NEXT: fcvt h0, d0
243 ; CHECK-NEXT: stur h0, [x0, #-20]
244 ; CHECK-NEXT: ret
245
246   %conv = fptrunc double %val to float
247   %tmp = tail call i16 @llvm.convert.to.fp16(float %conv)
248   %arrayidx = getelementptr inbounds i16* %a, i64 -10
249   store i16 %tmp, i16* %arrayidx, align 2
250   ret void
251 }
252
253 declare i16 @llvm.convert.to.fp16(float) nounwind readnone
254 declare float @llvm.convert.from.fp16(i16) nounwind readnone