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