blob: 4064ac5d2cbc8fd56cb86f0d702c648e23754172 [file] [log] [blame]
Leonard Chan99bda372018-10-15 16:07:02 +00001// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
2// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
3
4void TestFixedPointCastSameType() {
5 _Accum a = 2.5k;
6 _Accum a2 = a;
7 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
8 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
9
10 a2 = (_Accum)a;
11 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
12 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
13}
14
15void TestFixedPointCastDown() {
16 long _Accum la = 2.5lk;
17 _Accum a = la;
18 // DEFAULT: [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
19 // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
20 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
21 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
22
23 a = (_Accum)la;
24 // DEFAULT: [[LACCUM:%[0-9]+]] = load i64, i64* %la, align 8
25 // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9]+]] = ashr i64 [[LACCUM]], 16
26 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
27 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
28
29 short _Accum sa = a;
30 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
31 // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9]+]] = ashr i32 [[ACCUM]], 8
32 // DEFAULT-NEXT: [[SACCUM:%[0-9]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
33 // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
34
35 sa = (short _Accum)a;
36 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
37 // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9]+]] = ashr i32 [[ACCUM]], 8
38 // DEFAULT-NEXT: [[SACCUM:%[0-9]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
39 // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
40}
41
42void TestFixedPointCastUp() {
43 short _Accum sa = 2.5hk;
44 _Accum a = sa;
45 // DEFAULT: [[SACCUM:%[0-9]+]] = load i16, i16* %sa, align 2
46 // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9]+]] = sext i16 [[SACCUM]] to i32
47 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i32 [[SACCUM_BUFF]], 8
48 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
49
50 long _Accum la = a;
51 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
52 // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9]+]] = sext i32 [[ACCUM]] to i64
53 // DEFAULT-NEXT: [[LACCUM:%[0-9]+]] = shl i64 [[ACCUM_BUFF]], 16
54 // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %la, align 8
55
56 a = (_Accum)sa;
57 // DEFAULT: [[SACCUM:%[0-9]+]] = load i16, i16* %sa, align 2
58 // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9]+]] = sext i16 [[SACCUM]] to i32
59 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i32 [[SACCUM_BUFF]], 8
60 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
61
62 la = (long _Accum)a;
63 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
64 // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9]+]] = sext i32 [[ACCUM]] to i64
65 // DEFAULT-NEXT: [[LACCUM:%[0-9]+]] = shl i64 [[ACCUM_BUFF]], 16
66 // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %la, align 8
67}
68
69void TestFixedPointCastSignedness() {
70 _Accum a = 2.5k;
71 unsigned _Accum ua = a;
72 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
73 // DEFAULT-NEXT: [[UACCUM:%[0-9]+]] = shl i32 [[ACCUM]], 1
74 // DEFAULT-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
75 // SAME: TestFixedPointCastSignedness
76 // SAME: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
77 // SAME-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
78
79 a = ua;
80 // DEFAULT: [[UACCUM:%[0-9]+]] = load i32, i32* %ua, align 4
81 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = lshr i32 [[UACCUM]], 1
82 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
83 // SAME: [[ACCUM:%[0-9]+]] = load i32, i32* %ua, align 4
84 // SAME-NEXT: store i32 [[ACCUM]], i32* %a, align 4
85
86 ua = (unsigned _Accum)a;
87 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
88 // DEFAULT-NEXT: [[UACCUM:%[0-9]+]] = shl i32 [[ACCUM]], 1
89 // DEFAULT-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
90
91 a = (_Accum)ua;
92 // DEFAULT: [[UACCUM:%[0-9]+]] = load i32, i32* %ua, align 4
93 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = lshr i32 [[UACCUM]], 1
94 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
95
96 _Accum a2;
97 unsigned long _Accum ula = a2;
98 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a2, align 4
99 // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9]+]] = sext i32 [[ACCUM]] to i64
100 // DEFAULT-NEXT: [[LACCUM:%[0-9]+]] = shl i64 [[ACCUM_EXT]], 17
101 // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
102 // SAME: [[ACCUM:%[0-9]+]] = load i32, i32* %a2, align 4
103 // SAME-NEXT: [[ACCUM_EXT:%[0-9]+]] = sext i32 [[ACCUM]] to i64
104 // SAME-NEXT: [[LACCUM:%[0-9]+]] = shl i64 [[ACCUM_EXT]], 16
105 // SAME-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
106}
107
108void TestFixedPointCastSaturation() {
109 _Accum a;
110 _Sat short _Accum sat_sa;
111 _Sat _Accum sat_a;
112 _Sat long _Accum sat_la;
113 _Sat unsigned short _Accum sat_usa;
114 _Sat unsigned _Accum sat_ua;
115 _Sat unsigned long _Accum sat_ula;
116 _Sat short _Fract sat_sf;
117 _Sat _Fract sat_f;
118 _Sat long _Fract sat_lf;
119
120 // Casting down between types
121 sat_sa = sat_a;
122 // DEFAULT: [[OLD_ACCUM:%[0-9]+]] = load i32, i32* %sat_a, align 4
123 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = ashr i32 [[OLD_ACCUM]], 8
124 // DEFAULT-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i32 [[ACCUM]], 32767
125 // DEFAULT-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
126 // DEFAULT-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i32 [[RESULT]], -32768
127 // DEFAULT-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
128 // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i32 [[RESULT2]] to i16
129 // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_sa, align 2
130
131 // Accum to Fract, decreasing scale
132 sat_sf = sat_a;
133 // DEFAULT: [[OLD_ACCUM:%[0-9]+]] = load i32, i32* %sat_a, align 4
134 // DEFAULT-NEXT: [[FRACT:%[0-9]+]] = ashr i32 [[OLD_ACCUM]], 8
135 // DEFAULT-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i32 [[FRACT]], 127
136 // DEFAULT-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MAX]], i32 127, i32 [[FRACT]]
137 // DEFAULT-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i32 [[RESULT]], -128
138 // DEFAULT-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i32 -128, i32 [[RESULT]]
139 // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i32 [[RESULT2]] to i8
140 // DEFAULT-NEXT: store i8 [[RESULT_TRUNC]], i8* %sat_sf, align 1
141
142 // Accum to Fract, same scale
143 sat_f = a;
144 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
145 // DEFAULT-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i32 [[ACCUM]], 32767
146 // DEFAULT-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
147 // DEFAULT-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i32 [[RESULT]], -32768
148 // DEFAULT-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
149 // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i32 [[RESULT2]] to i16
150 // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_f, align 2
151
152 // Accum to Fract, increasing scale
153 sat_lf = sat_a;
154 // DEFAULT: [[OLD_ACCUM:%[0-9]+]] = load i32, i32* %sat_a, align 4
155 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = sext i32 [[OLD_ACCUM]] to i48
156 // DEFAULT-NEXT: [[FRACT:%[0-9]+]] = shl i48 [[ACCUM]], 16
157 // DEFAULT-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i48 [[FRACT]], 2147483647
158 // DEFAULT-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MAX]], i48 2147483647, i48 [[FRACT]]
159 // DEFAULT-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i48 [[RESULT]], -2147483648
160 // DEFAULT-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i48 -2147483648, i48 [[RESULT]]
161 // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i48 [[RESULT2]] to i32
162 // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_lf, align 4
163
164 // Signed to unsigned, decreasing scale
165 _Sat _Accum sat_a2;
166 sat_usa = sat_a2;
167 // DEFAULT: [[OLD_ACCUM:%[0-9]+]] = load i32, i32* %sat_a2, align 4
168 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = ashr i32 [[OLD_ACCUM]], 7
169 // DEFAULT-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i32 [[ACCUM]], 65535
170 // DEFAULT-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MAX]], i32 65535, i32 [[ACCUM]]
171 // DEFAULT-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i32 [[RESULT]], 0
172 // DEFAULT-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
173 // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i32 [[RESULT2]] to i16
174 // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
175 // SAME: [[OLD_ACCUM:%[0-9]+]] = load i32, i32* %sat_a2, align 4
176 // SAME-NEXT: [[ACCUM:%[0-9]+]] = ashr i32 [[OLD_ACCUM]], 8
177 // SAME-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i32 [[ACCUM]], 32767
178 // SAME-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
179 // SAME-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i32 [[RESULT]], 0
180 // SAME-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
181 // SAME-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i32 [[RESULT2]] to i16
182 // SAME-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
183
184 // Signed to unsigned, increasing scale
185 sat_ua = sat_a;
186 // DEFAULT: [[OLD_ACCUM:%[0-9]+]] = load i32, i32* %sat_a, align 4
187 // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9]+]] = sext i32 [[OLD_ACCUM]] to i33
188 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i33 [[ACCUM_EXT]], 1
189 // DEFAULT-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i33 [[ACCUM]], 0
190 // DEFAULT-NEXT: [[RESULT2:%[0-9]+]] = select i1 [[USE_MIN]], i33 0, i33 [[ACCUM]]
191 // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9]+]] = trunc i33 [[RESULT2]] to i32
192 // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_ua, align 4
193 // SAME: [[ACCUM:%[0-9]+]] = load i32, i32* %sat_a, align 4
194 // SAME-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i32 [[ACCUM]], 0
195 // SAME-NEXT: [[RESULT:%[0-9]+]] = select i1 [[USE_MIN]], i32 0, i32 [[ACCUM]]
196 // SAME-NEXT: store i32 [[RESULT]], i32* %sat_ua, align 4
197
198 // Nothing when saturating to the same type and size
199 sat_a = a;
200 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
201 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %sat_a, align 4
202
203 // Nothing when assigning back
204 a = sat_a;
205 // DEFAULT: [[SAT_ACCUM:%[0-9]+]] = load i32, i32* %sat_a, align 4
206 // DEFAULT-NEXT: store i32 [[SAT_ACCUM]], i32* %a, align 4
207
208 // No overflow when casting from fract to signed accum
209 sat_a = sat_f;
210 // DEFAULT: [[FRACT:%[0-9]+]] = load i16, i16* %sat_f, align 2
211 // DEFAULT-NEXT: [[FRACT_EXT:%[0-9]+]] = sext i16 [[FRACT]] to i32
212 // DEFAULT-NEXT: store i32 [[FRACT_EXT]], i32* %sat_a, align 4
213
214 // Only get overflow checking if signed fract to unsigned accum
215 sat_ua = sat_sf;
216 // DEFAULT: [[FRACT:%[0-9]+]] = load i8, i8* %sat_sf, align 1
217 // DEFAULT-NEXT: [[FRACT_EXT:%[0-9]+]] = sext i8 [[FRACT]] to i17
218 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i17 [[FRACT_EXT]], 9
219 // DEFAULT-NEXT: [[IS_NEG:%[0-9]+]] = icmp slt i17 [[ACCUM]], 0
220 // DEFAULT-NEXT: [[RESULT:%[0-9]+]] = select i1 [[IS_NEG]], i17 0, i17 [[ACCUM]]
221 // DEFAULT-NEXT: [[RESULT_EXT:%[0-9]+]] = sext i17 [[RESULT]] to i32
222 // DEFAULT-NEXT: store i32 [[RESULT_EXT]], i32* %sat_ua, align 4
223 // SAME: [[FRACT:%[0-9]+]] = load i8, i8* %sat_sf, align 1
224 // SAME-NEXT: [[FRACT_EXT:%[0-9]+]] = sext i8 [[FRACT]] to i16
225 // SAME-NEXT: [[ACCUM:%[0-9]+]] = shl i16 [[FRACT_EXT]], 8
226 // SAME-NEXT: [[IS_NEG:%[0-9]+]] = icmp slt i16 [[ACCUM]], 0
227 // SAME-NEXT: [[RESULT:%[0-9]+]] = select i1 [[IS_NEG]], i16 0, i16 [[ACCUM]]
228 // SAME-NEXT: [[RESULT_EXT:%[0-9]+]] = sext i16 [[RESULT]] to i32
229 // SAME-NEXT: store i32 [[RESULT_EXT]], i32* %sat_ua, align 4
230}
231
232void TestFixedPointCastBetFractAccum() {
233 short _Accum sa;
234 _Accum a;
235 long _Accum la;
236 short _Fract sf;
237 _Fract f;
238 long _Fract lf;
239 unsigned _Accum ua;
240 unsigned _Fract uf;
241
242 // To lower scale
243 sf = a;
244 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
245 // DEFAULT-NEXT: [[FRACT:%[0-9]+]] = ashr i32 [[ACCUM]], 8
246 // DEFAULT-NEXT: [[FRACT_TRUNC:%[0-9]+]] = trunc i32 [[FRACT]] to i8
247 // DEFAULT-NEXT: store i8 [[FRACT_TRUNC]], i8* %sf, align 1
248
249 // To higher scale
250 a = sf;
251 // DEFAULT: [[FRACT:%[0-9]+]] = load i8, i8* %sf, align 1
252 // DEFAULT-NEXT: [[FRACT_EXT:%[0-9]+]] = sext i8 [[FRACT]] to i32
253 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = shl i32 [[FRACT_EXT]], 8
254 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
255
256 // To same scale
257 f = a;
258 // DEFAULT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
259 // DEFAULT-NEXT: [[FRACT:%[0-9]+]] = trunc i32 [[ACCUM]] to i16
260 // DEFAULT-NEXT: store i16 [[FRACT]], i16* %f, align 2
261
262 a = f;
263 // DEFAULT: [[FRACT:%[0-9]+]] = load i16, i16* %f, align 2
264 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = sext i16 [[FRACT]] to i32
265 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
266
267 // To unsigned
268 ua = uf;
269 // DEFAULT: [[FRACT:%[0-9]+]] = load i16, i16* %uf, align 2
270 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = zext i16 [[FRACT]] to i32
271 // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
272 // SAME: [[FRACT:%[0-9]+]] = load i16, i16* %uf, align 2
273 // SAME-NEXT: [[ACCUM:%[0-9]+]] = zext i16 [[FRACT]] to i32
274 // SAME-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
275
276 uf = ua;
277 // DEFAULT: [[FRACT:%[0-9]+]] = load i32, i32* %ua, align 4
278 // DEFAULT-NEXT: [[ACCUM:%[0-9]+]] = trunc i32 [[FRACT]] to i16
279 // DEFAULT-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
280 // SAME: [[FRACT:%[0-9]+]] = load i32, i32* %ua, align 4
281 // SAME-NEXT: [[ACCUM:%[0-9]+]] = trunc i32 [[FRACT]] to i16
282 // SAME-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
283}