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