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 56 void 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 135 void 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 291 void 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 330 void 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 364 void 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