Clang Project

clang_source_code/test/Frontend/fixed_point_comparisons.c
1// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
2// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,PADDED
3
4// Fixed point against other fixed point
5_Bool b_eq_true = 2.5hk == 2.5uhk;  // CHECK-DAG: @b_eq_true  = {{.*}}global i8 1, align 1
6_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
7
8_Bool b_ne_true = 2.5hk != 2.4uhk;  // CHECK-DAG: @b_ne_true  = {{.*}}global i8 1, align 1
9_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
10
11_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true  = {{.*}}global i8 1, align 1
12_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
13
14_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true  = {{.*}}global i8 1, align 1
15_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
16_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
17
18_Bool b_gt_true = 2.75hk > 2.5uhk;   // CHECK-DAG: @b_gt_true  = {{.*}}global i8 1, align 1
19_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
20
21_Bool b_ge_true = 2.75hk >= 2.5uhk;   // CHECK-DAG: @b_ge_true  = {{.*}}global i8 1, align 1
22_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
23_Bool b_ge_false = 2.5hk >= 2.75uhk;  // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
24
25// Fixed point against int
26_Bool b_ieq_true = 2.0hk == 2;  // CHECK-DAG: @b_ieq_true  = {{.*}}global i8 1, align 1
27_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
28
29_Bool b_ine_true = 2.0hk != 3;  // CHECK-DAG: @b_ine_true  = {{.*}}global i8 1, align 1
30_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
31
32_Bool b_ilt_true = 2.0hk < 3;  // CHECK-DAG: @b_ilt_true  = {{.*}}global i8 1, align 1
33_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
34
35_Bool b_ile_true = 2.0hk <= 3;  // CHECK-DAG: @b_ile_true  = {{.*}}global i8 1, align 1
36_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
37_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
38
39_Bool b_igt_true = 2.0hk > 1;  // CHECK-DAG: @b_igt_true  = {{.*}}global i8 1, align 1
40_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
41
42_Bool b_ige_true = 2.0hk >= 1;  // CHECK-DAG: @b_ige_true  = {{.*}}global i8 1, align 1
43_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
44_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
45
46// Different signage
47// Since we can have different precisions, non powers of 2 fractions may have
48// different actual values when being compared.
49_Bool b_sne_true = 2.6hk != 2.6uhk;
50// UNPADDED-DAG:   @b_sne_true = {{.*}}global i8 1, align 1
51// PADDED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
52
53_Bool b_seq_true = 2.0hk == 2u;  // CHECK-DAG: @b_seq_true  = {{.*}}global i8 1, align 1
54_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
55
56void TestComparisons() {
57  short _Accum sa;
58  _Accum a;
59  unsigned short _Accum usa;
60  unsigned _Accum ua;
61
62  // Each of these should be a fixed point conversion followed by the actual
63  // comparison operation.
64  sa == a;
65  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
66  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
67  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
68  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
69  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
70
71  sa != a;
72  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
73  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
74  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
75  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
76  // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
77
78  sa > a;
79  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
80  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
81  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
82  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
83  // CHECK-NEXT: {{.*}} = icmp sgt i32 [[UPSCALE_A]], [[A2]]
84
85  sa >= a;
86  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
87  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
88  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
89  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
90  // CHECK-NEXT: {{.*}} = icmp sge i32 [[UPSCALE_A]], [[A2]]
91
92  sa < a;
93  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
94  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
95  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
96  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
97  // CHECK-NEXT: {{.*}} = icmp slt i32 [[UPSCALE_A]], [[A2]]
98
99  sa <= a;
100  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
101  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
102  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
103  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
104  // CHECK-NEXT: {{.*}} = icmp sle i32 [[UPSCALE_A]], [[A2]]
105
106  usa > ua;
107  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
108  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
109  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
110  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
111  // CHECK-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]]
112
113  usa >= ua;
114  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
115  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
116  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
117  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
118  // CHECK-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]]
119
120  usa < ua;
121  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
122  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
123  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
124  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
125  // CHECK-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]]
126
127  usa <= ua;
128  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
129  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
130  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
131  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
132  // CHECK-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]]
133}
134
135void TestIntComparisons() {
136  short _Accum sa;
137  unsigned short _Accum usa;
138
139  int i;
140  unsigned int ui;
141  _Bool b;
142  char c;
143  short s;
144  enum E {
145    A = 2
146  } e;
147
148  // These comparisons shouldn't be that different from comparing against fixed
149  // point types with other fixed point types.
150  sa == i;
151  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
152  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
153  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
154  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
155  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
156  // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
157
158  sa != i;
159  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
160  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
161  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
162  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
163  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
164  // CHECK-NEXT: {{.*}} = icmp ne i39 [[RESIZE_A]], [[UPSCALE_I]]
165
166  sa > i;
167  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
168  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
169  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
170  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
171  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
172  // CHECK-NEXT: {{.*}} = icmp sgt i39 [[RESIZE_A]], [[UPSCALE_I]]
173
174  sa >= i;
175  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
176  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
177  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
178  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
179  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
180  // CHECK-NEXT: {{.*}} = icmp sge i39 [[RESIZE_A]], [[UPSCALE_I]]
181
182  sa < i;
183  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
184  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
185  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
186  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
187  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
188  // CHECK-NEXT: {{.*}} = icmp slt i39 [[RESIZE_A]], [[UPSCALE_I]]
189
190  sa <= i;
191  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
192  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
193  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
194  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
195  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
196  // CHECK-NEXT: {{.*}} = icmp sle i39 [[RESIZE_A]], [[UPSCALE_I]]
197
198  usa > ui;
199  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
200  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
201  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
202  // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
203  // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
204  // UNPADDED-NEXT: {{.*}} = icmp ugt i40 [[RESIZE_A]], [[UPSCALE_I]]
205  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
206  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
207  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
208  // PADDED-NEXT: {{.*}} = icmp ugt i39 [[RESIZE_A]], [[UPSCALE_I]]
209
210  usa >= ui;
211  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
212  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
213  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
214  // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
215  // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
216  // UNPADDED-NEXT: {{.*}} = icmp uge i40 [[RESIZE_A]], [[UPSCALE_I]]
217  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
218  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
219  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
220  // PADDED-NEXT: {{.*}} = icmp uge i39 [[RESIZE_A]], [[UPSCALE_I]]
221
222  usa < ui;
223  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
224  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
225  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
226  // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
227  // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
228  // UNPADDED-NEXT: {{.*}} = icmp ult i40 [[RESIZE_A]], [[UPSCALE_I]]
229  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
230  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
231  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
232  // PADDED-NEXT: {{.*}} = icmp ult i39 [[RESIZE_A]], [[UPSCALE_I]]
233
234  usa <= ui;
235  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
236  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
237  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
238  // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
239  // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
240  // UNPADDED-NEXT: {{.*}} = icmp ule i40 [[RESIZE_A]], [[UPSCALE_I]]
241  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
242  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
243  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
244  // PADDED-NEXT: {{.*}} = icmp ule i39 [[RESIZE_A]], [[UPSCALE_I]]
245
246  // Allow for comparisons with other int like types. These are no different
247  // from comparing to an int other than varying sizes. The integer types are
248  // still converted to ints or unsigned ints from UsualUnaryConversions().
249  sa == b;
250  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
251  // CHECK-NEXT: [[B:%[0-9]+]] = load i8, i8* %b, align 1
252  // CHECK-NEXT: %tobool = trunc i8 [[B]] to i1
253  // CHECK-NEXT: [[CONV_B:%[a-z0-9]+]] = zext i1 %tobool to i32
254  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
255  // CHECK-NEXT: [[RESIZE_B:%[a-z0-9]+]] = sext i32 [[CONV_B]] to i39
256  // CHECK-NEXT: [[UPSCALE_B:%[a-z0-9]+]] = shl i39 [[RESIZE_B]], 7
257  // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_B]]
258
259  sa == c;
260  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
261  // CHECK-NEXT: [[C:%[0-9]+]] = load i8, i8* %c, align 1
262  // CHECK-NEXT: [[CONV_C:%[a-z0-9]+]] = sext i8 [[C]] to i32
263  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
264  // CHECK-NEXT: [[RESIZE_C:%[a-z0-9]+]] = sext i32 [[CONV_C]] to i39
265  // CHECK-NEXT: [[UPSCALE_C:%[a-z0-9]+]] = shl i39 [[RESIZE_C]], 7
266  // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_C]]
267
268  sa == s;
269  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
270  // CHECK-NEXT: [[S:%[0-9]+]] = load i16, i16* %s, align 2
271  // CHECK-NEXT: [[CONV_S:%[a-z0-9]+]] = sext i16 [[S]] to i32
272  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
273  // CHECK-NEXT: [[RESIZE_S:%[a-z0-9]+]] = sext i32 [[CONV_S]] to i39
274  // CHECK-NEXT: [[UPSCALE_S:%[a-z0-9]+]] = shl i39 [[RESIZE_S]], 7
275  // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_S]]
276
277  // An enum value is IntegralCast to an unsigned int.
278  usa == e;
279  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
280  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %e, align 4
281  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
282  // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
283  // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
284  // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
285  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
286  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
287  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
288  // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
289}
290
291void TestComparisonSignage() {
292  short _Accum sa;
293  unsigned short _Accum usa;
294  int i;
295  unsigned int ui;
296
297  // Signed vs unsigned fixed point comparison
298  sa == usa;
299  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
300  // CHECK-NEXT: [[A2:%[0-9]+]] = load i16, i16* %usa, align 2
301  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i17
302  // UNPADDED-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i17 [[RESIZE_A]], 1
303  // UNPADDED-NEXT: [[RESIZE_A2:%[a-z0-9]+]] = zext i16 [[A2]] to i17
304  // UNPADDED-NEXT: {{.*}} = icmp eq i17 [[UPSCALE_A]], [[RESIZE_A2]]
305  // PADDED-NEXT: {{.*}} = icmp eq i16 [[A]], [[A2]]
306
307  // Signed int vs unsigned fixed point
308  sa == ui;
309  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
310  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
311  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i40
312  // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
313  // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
314  // CHECK-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
315
316  // Signed fixed point vs unsigned int
317  usa == i;
318  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %usa, align 2
319  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
320  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
321  // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i40
322  // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
323  // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
324  // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
325  // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
326  // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
327  // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
328}
329
330void TestSaturationComparisons() {
331  short _Accum sa;
332  _Accum a;
333  _Sat short _Accum sat_sa;
334  _Sat _Accum sat_a;
335  _Sat unsigned short _Accum sat_usa;
336
337  // These are effectively the same as conversions with their non-saturating
338  // counterparts since when comparing, we convert both operands to a common
339  // type that should be able to hold both values.
340  sat_sa == sat_a;
341  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
342  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %sat_a, align 4
343  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
344  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
345  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
346
347  sat_sa == a;
348  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
349  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
350  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
351  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
352  // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
353
354  sat_sa == sat_usa;
355  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
356  // CHECK-NEXT: [[A2:%[0-9]+]] = load i16, i16* %sat_usa, align 2
357  // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i17
358  // UNPADDED-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i17 [[RESIZE_A]], 1
359  // UNPADDED-NEXT: [[RESIZE_A2:%[a-z0-9]+]] = zext i16 [[A2]] to i17
360  // UNPADDED-NEXT: {{.*}} = icmp eq i17 [[UPSCALE_A]], [[RESIZE_A2]]
361  // PADDED-NEXT: {{.*}} = icmp eq i16 [[A]], [[A2]]
362}
363
364void StoreBooleanResult() {
365  short _Accum sa;
366  _Accum a;
367  int res;
368
369  // Check that the result can properly be stored as an int.
370  res = sa == a;
371  // CHECK:      [[A:%[0-9]+]] = load i16, i16* %sa, align 2
372  // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
373  // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
374  // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
375  // CHECK-NEXT: [[RES:%[0-9]+]] = icmp eq i32 [[UPSCALE_A]], [[A2]]
376  // CHECK-NEXT: %conv = zext i1 [[RES]] to i32
377  // CHECK-NEXT: store i32 %conv, i32* %res, align 4
378}
379