1 // RUN: %clang_cc1 -no-opaque-pointers -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
2 // RUN: %clang_cc1 -no-opaque-pointers -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 
TestComparisons(void)56 void TestComparisons(void) {
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 
TestIntComparisons(void)135 void TestIntComparisons(void) {
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 
TestComparisonSignage(void)291 void TestComparisonSignage(void) {
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 
TestSaturationComparisons(void)330 void TestSaturationComparisons(void) {
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 
StoreBooleanResult(void)364 void StoreBooleanResult(void) {
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