1 // REQUIRES: arm-registered-target 2 // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK 3 // RUN: %clang_cc1 -emit-llvm -o - -triple aarch64 %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK 4 // RUN: %clang_cc1 -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s --check-prefix=NOTNATIVE --check-prefix=CHECK 5 // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -fnative-half-type %s \ 6 // RUN: | FileCheck %s --check-prefix=NATIVE-HALF 7 // RUN: %clang_cc1 -emit-llvm -o - -triple aarch64 -fnative-half-type %s \ 8 // RUN: | FileCheck %s --check-prefix=NATIVE-HALF 9 typedef unsigned cond_t; 10 typedef __fp16 float16_t; 11 12 volatile cond_t test; 13 volatile int i0; 14 volatile __fp16 h0 = 0.0, h1 = 1.0, h2; 15 volatile float f0, f1, f2; 16 volatile double d0; 17 short s0; 18 19 void foo(void) { 20 // CHECK-LABEL: define{{.*}} void @foo() 21 22 // Check unary ops 23 24 // NOTNATIVE: [[F16TOF32:fpext half]] 25 // CHECK: fptoui float 26 // NATIVE-HALF: fptoui half 27 test = (h0); 28 // CHECK: uitofp i32 29 // NOTNATIVE: [[F32TOF16:fptrunc float]] 30 // NATIVE-HALF: uitofp i32 {{.*}} to half 31 h0 = (test); 32 // CHECK: [[F16TOF32]] 33 // CHECK: fcmp une float 34 // NATIVE-HALF: fcmp une half 35 test = (!h1); 36 // CHECK: [[F16TOF32]] 37 // CHECK: fneg float 38 // NOTNATIVE: [[F32TOF16]] 39 // NATIVE-HALF: fneg half 40 h1 = -h1; 41 // CHECK: [[F16TOF32]] 42 // CHECK: [[F32TOF16]] 43 // NATIVE-HALF: load volatile half 44 // NATIVE-HALF-NEXT: store volatile half 45 h1 = +h1; 46 // CHECK: [[F16TOF32]] 47 // CHECK: fadd float 48 // CHECK: [[F32TOF16]] 49 // NATIVE-HALF: fadd half 50 h1++; 51 // CHECK: [[F16TOF32]] 52 // CHECK: fadd float 53 // CHECK: [[F32TOF16]] 54 // NATIVE-HALF: fadd half 55 ++h1; 56 // CHECK: [[F16TOF32]] 57 // CHECK: fadd float 58 // CHECK: [[F32TOF16]] 59 // NATIVE-HALF: fadd half 60 --h1; 61 // CHECK: [[F16TOF32]] 62 // CHECK: fadd float 63 // CHECK: [[F32TOF16]] 64 // NATIVE-HALF: fadd half 65 h1--; 66 67 // Check binary ops with various operands 68 // CHECK: [[F16TOF32]] 69 // CHECK: [[F16TOF32]] 70 // CHECK: fmul float 71 // CHECK: [[F32TOF16]] 72 // NATIVE-HALF: fmul half 73 h1 = h0 * h2; 74 // CHECK: [[F16TOF32]] 75 // CHECK: fmul float 76 // CHECK: [[F32TOF16]] 77 // NATIVE-HALF: fmul half 78 h1 = h0 * (__fp16) -2.0f; 79 // CHECK: [[F16TOF32]] 80 // CHECK: fmul float 81 // CHECK: [[F32TOF16]] 82 // NATIVE-HALF: fpext half 83 // NATIVE-HALF: fmul float 84 h1 = h0 * f2; 85 // CHECK: [[F16TOF32]] 86 // CHECK: fmul float 87 // CHECK: [[F32TOF16]] 88 // NATIVE-HALF: fpext half 89 // NATIVE-HALF: fmul float 90 h1 = f0 * h2; 91 // CHECK: [[F16TOF32]] 92 // CHECK: fmul float 93 // CHECK: [[F32TOF16]] 94 // NATIVE-HALF: fmul half 95 h1 = h0 * i0; 96 97 // CHECK: [[F16TOF32]] 98 // CHECK: [[F16TOF32]] 99 // CHECK: fdiv float 100 // CHECK: [[F32TOF16]] 101 // NATIVE-HALF: fdiv half 102 h1 = (h0 / h2); 103 // CHECK: [[F16TOF32]] 104 // CHECK: fdiv float 105 // CHECK: [[F32TOF16]] 106 // NATIVE-HALF: fdiv half 107 h1 = (h0 / (__fp16) -2.0f); 108 // CHECK: [[F16TOF32]] 109 // CHECK: fdiv float 110 // CHECK: [[F32TOF16]] 111 // NATIVE-HALF: fpext half 112 // NATIVE-HALF: fdiv float 113 h1 = (h0 / f2); 114 // CHECK: [[F16TOF32]] 115 // CHECK: fdiv float 116 // CHECK: [[F32TOF16]] 117 // NATIVE-HALF: fpext half 118 // NATIVE-HALF: fdiv float 119 h1 = (f0 / h2); 120 // CHECK: [[F16TOF32]] 121 // CHECK: fdiv float 122 // CHECK: [[F32TOF16]] 123 // NATIVE-HALF: fdiv half 124 h1 = (h0 / i0); 125 126 // CHECK: [[F16TOF32]] 127 // CHECK: [[F16TOF32]] 128 // CHECK: fadd float 129 // CHECK: [[F32TOF16]] 130 // NATIVE-HALF: fadd half 131 h1 = (h2 + h0); 132 // CHECK: [[F16TOF32]] 133 // CHECK: fadd float 134 // CHECK: [[F32TOF16]] 135 // NATIVE-HALF: fadd half 136 h1 = ((__fp16)-2.0 + h0); 137 // CHECK: [[F16TOF32]] 138 // CHECK: fadd float 139 // CHECK: [[F32TOF16]] 140 // NATIVE-HALF: fpext half 141 // NATIVE-HALF: fadd float 142 h1 = (h2 + f0); 143 // CHECK: [[F16TOF32]] 144 // CHECK: fadd float 145 // CHECK: [[F32TOF16]] 146 // NATIVE-HALF: fpext half 147 // NATIVE-HALF: fadd float 148 h1 = (f2 + h0); 149 // CHECK: [[F16TOF32]] 150 // CHECK: fadd float 151 // CHECK: [[F32TOF16]] 152 // NATIVE-HALF: fadd half 153 h1 = (h0 + i0); 154 155 // CHECK: [[F16TOF32]] 156 // CHECK: [[F16TOF32]] 157 // CHECK: fsub float 158 // CHECK: [[F32TOF16]] 159 // NATIVE-HALF: fsub half 160 h1 = (h2 - h0); 161 // CHECK: [[F16TOF32]] 162 // CHECK: fsub float 163 // CHECK: [[F32TOF16]] 164 // NATIVE-HALF: fsub half 165 h1 = ((__fp16)-2.0f - h0); 166 // CHECK: [[F16TOF32]] 167 // CHECK: fsub float 168 // CHECK: [[F32TOF16]] 169 // NATIVE-HALF: fpext half 170 // NATIVE-HALF: fsub float 171 h1 = (h2 - f0); 172 // CHECK: [[F16TOF32]] 173 // CHECK: fsub float 174 // CHECK: [[F32TOF16]] 175 // NATIVE-HALF: fpext half 176 // NATIVE-HALF: fsub float 177 h1 = (f2 - h0); 178 // CHECK: [[F16TOF32]] 179 // CHECK: fsub float 180 // CHECK: [[F32TOF16]] 181 // NATIVE-HALF: fsub half 182 h1 = (h0 - i0); 183 184 // CHECK: [[F16TOF32]] 185 // CHECK: [[F16TOF32]] 186 // CHECK: fcmp olt float 187 // NATIVE-HALF: fcmp olt half 188 test = (h2 < h0); 189 // CHECK: [[F16TOF32]] 190 // CHECK: fcmp olt float 191 // NATIVE-HALF: fcmp olt half 192 test = (h2 < (__fp16)42.0); 193 // CHECK: [[F16TOF32]] 194 // CHECK: fcmp olt float 195 // NATIVE-HALF: fpext half 196 // NATIVE-HALF: fcmp olt float 197 test = (h2 < f0); 198 // CHECK: [[F16TOF32]] 199 // CHECK: fcmp olt float 200 // NATIVE-HALF: fpext half 201 // NATIVE-HALF: fcmp olt float 202 test = (f2 < h0); 203 // CHECK: [[F16TOF32]] 204 // CHECK: fcmp olt float 205 // NATIVE-HALF: fcmp olt half 206 test = (i0 < h0); 207 // CHECK: [[F16TOF32]] 208 // CHECK: fcmp olt float 209 // NATIVE-HALF: fcmp olt half 210 test = (h0 < i0); 211 212 // CHECK: [[F16TOF32]] 213 // CHECK: [[F16TOF32]] 214 // CHECK: fcmp ogt float 215 // NATIVE-HALF: fcmp ogt half 216 test = (h0 > h2); 217 // CHECK: [[F16TOF32]] 218 // CHECK: fcmp ogt float 219 // NATIVE-HALF: fcmp ogt half 220 test = ((__fp16)42.0 > h2); 221 // CHECK: [[F16TOF32]] 222 // CHECK: fcmp ogt float 223 // NATIVE-HALF: fpext half 224 // NATIVE-HALF: fcmp ogt float 225 test = (h0 > f2); 226 // CHECK: [[F16TOF32]] 227 // CHECK: fcmp ogt float 228 // NATIVE-HALF: fpext half 229 // NATIVE-HALF: fcmp ogt float 230 test = (f0 > h2); 231 // CHECK: [[F16TOF32]] 232 // CHECK: fcmp ogt float 233 // NATIVE-HALF: fcmp ogt half 234 test = (i0 > h0); 235 // CHECK: [[F16TOF32]] 236 // CHECK: fcmp ogt float 237 // NATIVE-HALF: fcmp ogt half 238 test = (h0 > i0); 239 240 // CHECK: [[F16TOF32]] 241 // CHECK: [[F16TOF32]] 242 // CHECK: fcmp ole float 243 // NATIVE-HALF: fcmp ole half 244 test = (h2 <= h0); 245 // CHECK: [[F16TOF32]] 246 // CHECK: fcmp ole float 247 // NATIVE-HALF: fcmp ole half 248 test = (h2 <= (__fp16)42.0); 249 // CHECK: [[F16TOF32]] 250 // CHECK: fcmp ole float 251 // NATIVE-HALF: fpext half 252 // NATIVE-HALF: fcmp ole float 253 test = (h2 <= f0); 254 // CHECK: [[F16TOF32]] 255 // CHECK: fcmp ole float 256 // NATIVE-HALF: fpext half 257 // NATIVE-HALF: fcmp ole float 258 test = (f2 <= h0); 259 // CHECK: [[F16TOF32]] 260 // CHECK: fcmp ole float 261 // NATIVE-HALF: fcmp ole half 262 test = (i0 <= h0); 263 // CHECK: [[F16TOF32]] 264 // CHECK: fcmp ole float 265 // NATIVE-HALF: fcmp ole half 266 test = (h0 <= i0); 267 268 269 // CHECK: [[F16TOF32]] 270 // CHECK: [[F16TOF32]] 271 // CHECK: fcmp oge float 272 // NATIVE-HALF: fcmp oge half 273 test = (h0 >= h2); 274 // CHECK: [[F16TOF32]] 275 // CHECK: fcmp oge float 276 // NATIVE-HALF: fcmp oge half 277 test = (h0 >= (__fp16)-2.0); 278 // CHECK: [[F16TOF32]] 279 // CHECK: fcmp oge float 280 // NATIVE-HALF: fpext half 281 // NATIVE-HALF: fcmp oge float 282 test = (h0 >= f2); 283 // CHECK: [[F16TOF32]] 284 // CHECK: fcmp oge float 285 // NATIVE-HALF: fpext half 286 // NATIVE-HALF: fcmp oge float 287 test = (f0 >= h2); 288 // CHECK: [[F16TOF32]] 289 // CHECK: fcmp oge float 290 // NATIVE-HALF: fcmp oge half 291 test = (i0 >= h0); 292 // CHECK: [[F16TOF32]] 293 // CHECK: fcmp oge float 294 // NATIVE-HALF: fcmp oge half 295 test = (h0 >= i0); 296 297 // CHECK: [[F16TOF32]] 298 // CHECK: [[F16TOF32]] 299 // CHECK: fcmp oeq float 300 // NATIVE-HALF: fcmp oeq half 301 test = (h1 == h2); 302 // CHECK: [[F16TOF32]] 303 // CHECK: fcmp oeq float 304 // NATIVE-HALF: fcmp oeq half 305 test = (h1 == (__fp16)1.0); 306 // CHECK: [[F16TOF32]] 307 // CHECK: fcmp oeq float 308 // NATIVE-HALF: fpext half 309 // NATIVE-HALF: fcmp oeq float 310 test = (h1 == f1); 311 // CHECK: [[F16TOF32]] 312 // CHECK: fcmp oeq float 313 // NATIVE-HALF: fpext half 314 // NATIVE-HALF: fcmp oeq float 315 test = (f1 == h1); 316 // CHECK: [[F16TOF32]] 317 // CHECK: fcmp oeq float 318 // NATIVE-HALF: fcmp oeq half 319 test = (i0 == h0); 320 // CHECK: [[F16TOF32]] 321 // CHECK: fcmp oeq float 322 // NATIVE-HALF: fcmp oeq half 323 test = (h0 == i0); 324 325 // CHECK: [[F16TOF32]] 326 // CHECK: [[F16TOF32]] 327 // CHECK: fcmp une float 328 // NATIVE-HALF: fcmp une half 329 test = (h1 != h2); 330 // CHECK: [[F16TOF32]] 331 // CHECK: fcmp une float 332 // NATIVE-HALF: fcmp une half 333 test = (h1 != (__fp16)1.0); 334 // CHECK: [[F16TOF32]] 335 // CHECK: fcmp une float 336 // NATIVE-HALF: fpext half 337 // NATIVE-HALF: fcmp une float 338 test = (h1 != f1); 339 // CHECK: [[F16TOF32]] 340 // CHECK: fcmp une float 341 // NATIVE-HALF: fpext half 342 // NATIVE-HALF: fcmp une float 343 test = (f1 != h1); 344 // CHECK: [[F16TOF32]] 345 // CHECK: fcmp une float 346 // NATIVE-HALF: fcmp une half 347 test = (i0 != h0); 348 // CHECK: [[F16TOF32]] 349 // CHECK: fcmp une float 350 // NATIVE-HALF: fcmp une half 351 test = (h0 != i0); 352 353 // CHECK: [[F16TOF32]] 354 // CHECK: fcmp une float 355 // CHECK: [[F16TOF32]] 356 // CHECK: [[F16TOF32]] 357 // CHECK: [[F32TOF16]] 358 // NATIVE-HALF: fcmp une half {{.*}}, 0xH0000 359 h1 = (h1 ? h2 : h0); 360 // Check assignments (inc. compound) 361 h0 = h1; 362 // NOTNATIVE: store {{.*}} half 0xHC000 363 // NATIVE-HALF: store {{.*}} half 0xHC000 364 h0 = (__fp16)-2.0f; 365 // CHECK: [[F32TOF16]] 366 // NATIVE-HALF: fptrunc float 367 h0 = f0; 368 369 // CHECK: sitofp i32 {{.*}} to float 370 // CHECK: [[F32TOF16]] 371 // NATIVE-HALF: sitofp i32 {{.*}} to half 372 h0 = i0; 373 // CHECK: [[F16TOF32]] 374 // CHECK: fptosi float {{.*}} to i32 375 // NATIVE-HALF: fptosi half {{.*}} to i32 376 i0 = h0; 377 378 // CHECK: [[F16TOF32]] 379 // CHECK: [[F16TOF32]] 380 // CHECK: fadd float 381 // CHECK: [[F32TOF16]] 382 // NATIVE-HALF: fadd half 383 h0 += h1; 384 // CHECK: [[F16TOF32]] 385 // CHECK: fadd float 386 // CHECK: [[F32TOF16]] 387 // NATIVE-HALF: fadd half 388 h0 += (__fp16)1.0f; 389 // CHECK: [[F16TOF32]] 390 // CHECK: fadd float 391 // CHECK: [[F32TOF16]] 392 // NATIVE-HALF: fpext half 393 // NATIVE-HALF: fadd float 394 // NATIVE-HALF: fptrunc float 395 h0 += f2; 396 // CHECK: [[F16TOF32]] 397 // CHECK: sitofp i32 {{.*}} to float 398 // CHECK: fadd float 399 // CHECK: fptosi float {{.*}} to i32 400 // NATIVE-HALF: sitofp i32 {{.*}} to half 401 // NATIVE-HALF: fadd half 402 // NATIVE-HALF: fptosi half {{.*}} to i32 403 i0 += h0; 404 // CHECK: sitofp i32 {{.*}} to float 405 // CHECK: [[F16TOF32]] 406 // CHECK: fadd float 407 // CHECK: [[F32TOF16]] 408 // NATIVE-HALF: sitofp i32 {{.*}} to half 409 // NATIVE-HALF: fadd half 410 h0 += i0; 411 412 // CHECK: [[F16TOF32]] 413 // CHECK: [[F16TOF32]] 414 // CHECK: fsub float 415 // CHECK: [[F32TOF16]] 416 // NATIVE-HALF: fsub half 417 h0 -= h1; 418 // CHECK: [[F16TOF32]] 419 // CHECK: fsub float 420 // CHECK: [[F32TOF16]] 421 // NATIVE-HALF: fsub half 422 h0 -= (__fp16)1.0; 423 // CHECK: [[F16TOF32]] 424 // CHECK: fsub float 425 // CHECK: [[F32TOF16]] 426 // NATIVE-HALF: fpext half 427 // NATIVE-HALF: fsub float 428 // NATIVE-HALF: fptrunc float 429 h0 -= f2; 430 // CHECK: [[F16TOF32]] 431 // CHECK: sitofp i32 {{.*}} to float 432 // CHECK: fsub float 433 // CHECK: fptosi float {{.*}} to i32 434 // NATIVE-HALF: sitofp i32 {{.*}} to half 435 // NATIVE-HALF: fsub half 436 // NATIVE-HALF: fptosi half {{.*}} to i32 437 i0 -= h0; 438 // CHECK: sitofp i32 {{.*}} to float 439 // CHECK: [[F16TOF32]] 440 // CHECK: fsub float 441 // CHECK: [[F32TOF16]] 442 // NATIVE-HALF: sitofp i32 {{.*}} to half 443 // NATIVE-HALF: fsub half 444 h0 -= i0; 445 446 // CHECK: [[F16TOF32]] 447 // CHECK: [[F16TOF32]] 448 // CHECK: fmul float 449 // CHECK: [[F32TOF16]] 450 // NATIVE-HALF: fmul half 451 h0 *= h1; 452 // CHECK: [[F16TOF32]] 453 // CHECK: fmul float 454 // CHECK: [[F32TOF16]] 455 // NATIVE-HALF: fmul half 456 h0 *= (__fp16)1.0; 457 // CHECK: [[F16TOF32]] 458 // CHECK: fmul float 459 // CHECK: [[F32TOF16]] 460 // NATIVE-HALF: fpext half 461 // NATIVE-HALF: fmul float 462 // NATIVE-HALF: fptrunc float 463 h0 *= f2; 464 // CHECK: [[F16TOF32]] 465 // CHECK: sitofp i32 {{.*}} to float 466 // CHECK: fmul float 467 // CHECK: fptosi float {{.*}} to i32 468 // NATIVE-HALF: sitofp i32 {{.*}} to half 469 // NATIVE-HALF: fmul half 470 // NATIVE-HALF: fptosi half {{.*}} to i32 471 i0 *= h0; 472 // CHECK: sitofp i32 {{.*}} to float 473 // CHECK: [[F16TOF32]] 474 // CHECK: fmul float 475 // CHECK: [[F32TOF16]] 476 // NATIVE-HALF: sitofp i32 {{.*}} to half 477 // NATIVE-HALF: fmul half 478 h0 *= i0; 479 480 // CHECK: [[F16TOF32]] 481 // CHECK: [[F16TOF32]] 482 // CHECK: fdiv float 483 // CHECK: [[F32TOF16]] 484 // NATIVE-HALF: fdiv half 485 h0 /= h1; 486 // CHECK: [[F16TOF32]] 487 // CHECK: fdiv float 488 // CHECK: [[F32TOF16]] 489 // NATIVE-HALF: fdiv half 490 h0 /= (__fp16)1.0; 491 // CHECK: [[F16TOF32]] 492 // CHECK: fdiv float 493 // CHECK: [[F32TOF16]] 494 // NATIVE-HALF: fpext half 495 // NATIVE-HALF: fdiv float 496 // NATIVE-HALF: fptrunc float 497 h0 /= f2; 498 // CHECK: [[F16TOF32]] 499 // CHECK: sitofp i32 {{.*}} to float 500 // CHECK: fdiv float 501 // CHECK: fptosi float {{.*}} to i32 502 // NATIVE-HALF: sitofp i32 {{.*}} to half 503 // NATIVE-HALF: fdiv half 504 // NATIVE-HALF: fptosi half {{.*}} to i32 505 i0 /= h0; 506 // CHECK: sitofp i32 {{.*}} to float 507 // CHECK: [[F16TOF32]] 508 // CHECK: fdiv float 509 // CHECK: [[F32TOF16]] 510 // NATIVE-HALF: sitofp i32 {{.*}} to half 511 // NATIVE-HALF: fdiv half 512 h0 /= i0; 513 514 // Check conversions to/from double 515 // NOTNATIVE: fptrunc double {{.*}} to half 516 // NATIVE-HALF: fptrunc double {{.*}} to half 517 h0 = d0; 518 519 // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float 520 // NOTNATIVE: fptrunc float [[MID]] to half 521 // NATIVE-HALF: [[MID:%.*]] = fptrunc double {{%.*}} to float 522 // NATIVE-HALF: fptrunc float {{.*}} to half 523 h0 = (float)d0; 524 525 // NOTNATIVE: fpext half {{.*}} to double 526 // NATIVE-HALF: fpext half {{.*}} to double 527 d0 = h0; 528 529 // NOTNATIVE: [[MID:%.*]] = fpext half {{.*}} to float 530 // CHECK: fpext float [[MID]] to double 531 // NATIVE-HALF: [[MID:%.*]] = fpext half {{.*}} to float 532 // NATIVE-HALF: fpext float [[MID]] to double 533 d0 = (float)h0; 534 535 // NOTNATIVE: [[V1:%.*]] = load i16, ptr @s0 536 // NOTNATIVE: [[CONV:%.*]] = sitofp i16 [[V1]] to float 537 // NOTNATIVE: [[TRUNC:%.*]] = fptrunc float [[CONV]] to half 538 // NOTNATIVE: store volatile half [[TRUNC]], ptr @h0 539 h0 = s0; 540 } 541 542 // CHECK-LABEL: define{{.*}} void @testTypeDef( 543 // CHECK: %[[CONV:.*]] = fpext <4 x half> %{{.*}} to <4 x float> 544 // CHECK: %[[CONV1:.*]] = fpext <4 x half> %{{.*}} to <4 x float> 545 // CHECK: %[[ADD:.*]] = fadd <4 x float> %[[CONV]], %[[CONV1]] 546 // CHECK: fptrunc <4 x float> %[[ADD]] to <4 x half> 547 548 void testTypeDef() { 549 __fp16 t0 __attribute__((vector_size(8))); 550 float16_t t1 __attribute__((vector_size(8))); 551 t1 = t0 + t1; 552 } 553