fp16-ops.c revision e9a54b6cc25f564aa5c99b62e888e484cede3959
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 10typedef unsigned cond_t; 11 12volatile cond_t test; 13volatile __fp16 h0 = 0.0, h1 = 1.0, h2; 14volatile float f0, f1, f2; 15volatile double d0; 16 17void foo(void) { 18 // CHECK-LABEL: define void @foo() 19 20 // Check unary ops 21 22 // NOHALF: [[F16TOF32:call float @llvm.convert.from.fp16.f32]] 23 // HALF: [[F16TOF32:fpext half]] 24 // CHECK: fptoui float 25 // NATIVE-HALF: fptoui half 26 test = (h0); 27 // CHECK: uitofp i32 28 // NOHALF: [[F32TOF16:call i16 @llvm.convert.to.fp16.f32]] 29 // HALF: [[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: fsub float 38 // NOHALF: [[F32TOF16]] 39 // HALF: [[F32TOF16]] 40 // NATIVE-HALF: fsub half 41 h1 = -h1; 42 // CHECK: [[F16TOF32]] 43 // CHECK: [[F32TOF16]] 44 // NATIVE-HALF: load volatile half 45 // NATIVE-HALF-NEXT: store volatile half 46 h1 = +h1; 47 // CHECK: [[F16TOF32]] 48 // CHECK: fadd float 49 // CHECK: [[F32TOF16]] 50 // NATIVE-HALF: fadd half 51 h1++; 52 // CHECK: [[F16TOF32]] 53 // CHECK: fadd float 54 // CHECK: [[F32TOF16]] 55 // NATIVE-HALF: fadd half 56 ++h1; 57 // CHECK: [[F16TOF32]] 58 // CHECK: fadd float 59 // CHECK: [[F32TOF16]] 60 // NATIVE-HALF: fadd half 61 --h1; 62 // CHECK: [[F16TOF32]] 63 // CHECK: fadd float 64 // CHECK: [[F32TOF16]] 65 // NATIVE-HALF: fadd half 66 h1--; 67 68 // Check binary ops with various operands 69 // CHECK: [[F16TOF32]] 70 // CHECK: [[F16TOF32]] 71 // CHECK: fmul float 72 // CHECK: [[F32TOF16]] 73 // NATIVE-HALF: fmul half 74 h1 = h0 * h2; 75 // CHECK: [[F16TOF32]] 76 // NOHALF: [[F32TOF16]] 77 // NOHALF: [[F16TOF32]] 78 // CHECK: fmul float 79 // CHECK: [[F32TOF16]] 80 // NATIVE-HALF: fmul half 81 h1 = h0 * (__fp16) -2.0f; 82 // CHECK: [[F16TOF32]] 83 // CHECK: fmul float 84 // CHECK: [[F32TOF16]] 85 // NATIVE-HALF: fpext half 86 // NATIVE-HALF: fmul float 87 h1 = h0 * f2; 88 // CHECK: [[F16TOF32]] 89 // CHECK: fmul float 90 // CHECK: [[F32TOF16]] 91 // NATIVE-HALF: fpext half 92 // NATIVE-HALF: fmul float 93 h1 = f0 * h2; 94 95 // CHECK: [[F16TOF32]] 96 // CHECK: [[F16TOF32]] 97 // CHECK: fdiv float 98 // CHECK: [[F32TOF16]] 99 // NATIVE-HALF: fdiv half 100 h1 = (h0 / h2); 101 // CHECK: [[F16TOF32]] 102 // NOHALF: [[F16TOF32]] 103 // CHECK: fdiv float 104 // CHECK: [[F32TOF16]] 105 // NATIVE-HALF: fdiv half 106 h1 = (h0 / (__fp16) -2.0f); 107 // CHECK: [[F16TOF32]] 108 // CHECK: fdiv float 109 // CHECK: [[F32TOF16]] 110 // NATIVE-HALF: fpext half 111 // NATIVE-HALF: fdiv float 112 h1 = (h0 / f2); 113 // CHECK: [[F16TOF32]] 114 // CHECK: fdiv float 115 // CHECK: [[F32TOF16]] 116 // NATIVE-HALF: fpext half 117 // NATIVE-HALF: fdiv float 118 h1 = (f0 / h2); 119 120 // CHECK: [[F16TOF32]] 121 // CHECK: [[F16TOF32]] 122 // CHECK: fadd float 123 // CHECK: [[F32TOF16]] 124 // NATIVE-HALF: fadd half 125 h1 = (h2 + h0); 126 // CHECK: [[F16TOF32]] 127 // NOHALF: [[F16TOF32]] 128 // CHECK: fadd float 129 // CHECK: [[F32TOF16]] 130 // NATIVE-HALF: fadd half 131 h1 = ((__fp16)-2.0 + h0); 132 // CHECK: [[F16TOF32]] 133 // CHECK: fadd float 134 // CHECK: [[F32TOF16]] 135 // NATIVE-HALF: fpext half 136 // NATIVE-HALF: fadd float 137 h1 = (h2 + f0); 138 // CHECK: [[F16TOF32]] 139 // CHECK: fadd float 140 // CHECK: [[F32TOF16]] 141 // NATIVE-HALF: fpext half 142 // NATIVE-HALF: fadd float 143 h1 = (f2 + h0); 144 145 // CHECK: [[F16TOF32]] 146 // CHECK: [[F16TOF32]] 147 // CHECK: fsub float 148 // CHECK: [[F32TOF16]] 149 // NATIVE-HALF: fsub half 150 h1 = (h2 - h0); 151 // CHECK: [[F16TOF32]] 152 // NOHALF: [[F16TOF32]] 153 // CHECK: fsub float 154 // CHECK: [[F32TOF16]] 155 // NATIVE-HALF: fsub half 156 h1 = ((__fp16)-2.0f - h0); 157 // CHECK: [[F16TOF32]] 158 // CHECK: fsub float 159 // CHECK: [[F32TOF16]] 160 // NATIVE-HALF: fpext half 161 // NATIVE-HALF: fsub float 162 h1 = (h2 - f0); 163 // CHECK: [[F16TOF32]] 164 // CHECK: fsub float 165 // CHECK: [[F32TOF16]] 166 // NATIVE-HALF: fpext half 167 // NATIVE-HALF: fsub float 168 h1 = (f2 - h0); 169 170 // CHECK: [[F16TOF32]] 171 // CHECK: [[F16TOF32]] 172 // CHECK: fcmp olt float 173 // NATIVE-HALF: fcmp olt half 174 test = (h2 < h0); 175 // CHECK: [[F16TOF32]] 176 // NOHALF: [[F16TOF32]] 177 // CHECK: fcmp olt float 178 // NATIVE-HALF: fcmp olt half 179 test = (h2 < (__fp16)42.0); 180 // CHECK: [[F16TOF32]] 181 // CHECK: fcmp olt float 182 // NATIVE-HALF: fpext half 183 // NATIVE-HALF: fcmp olt float 184 test = (h2 < f0); 185 // CHECK: [[F16TOF32]] 186 // CHECK: fcmp olt float 187 // NATIVE-HALF: fpext half 188 // NATIVE-HALF: fcmp olt float 189 test = (f2 < h0); 190 191 // CHECK: [[F16TOF32]] 192 // CHECK: [[F16TOF32]] 193 // CHECK: fcmp ogt float 194 // NATIVE-HALF: fcmp ogt half 195 test = (h0 > h2); 196 // CHECK: [[F16TOF32]] 197 // NOHALF: [[F16TOF32]] 198 // CHECK: fcmp ogt float 199 // NATIVE-HALF: fcmp ogt half 200 test = ((__fp16)42.0 > h2); 201 // CHECK: [[F16TOF32]] 202 // CHECK: fcmp ogt float 203 // NATIVE-HALF: fpext half 204 // NATIVE-HALF: fcmp ogt float 205 test = (h0 > f2); 206 // CHECK: [[F16TOF32]] 207 // CHECK: fcmp ogt float 208 // NATIVE-HALF: fpext half 209 // NATIVE-HALF: fcmp ogt float 210 test = (f0 > h2); 211 212 // CHECK: [[F16TOF32]] 213 // CHECK: [[F16TOF32]] 214 // CHECK: fcmp ole float 215 // NATIVE-HALF: fcmp ole half 216 test = (h2 <= h0); 217 // CHECK: [[F16TOF32]] 218 // NOHALF: [[F16TOF32]] 219 // CHECK: fcmp ole float 220 // NATIVE-HALF: fcmp ole half 221 test = (h2 <= (__fp16)42.0); 222 // CHECK: [[F16TOF32]] 223 // CHECK: fcmp ole float 224 // NATIVE-HALF: fpext half 225 // NATIVE-HALF: fcmp ole float 226 test = (h2 <= f0); 227 // CHECK: [[F16TOF32]] 228 // CHECK: fcmp ole float 229 // NATIVE-HALF: fpext half 230 // NATIVE-HALF: fcmp ole float 231 test = (f2 <= h0); 232 233 // CHECK: [[F16TOF32]] 234 // CHECK: [[F16TOF32]] 235 // CHECK: fcmp oge float 236 // NATIVE-HALF: fcmp oge half 237 test = (h0 >= h2); 238 // CHECK: [[F16TOF32]] 239 // NOHALF: [[F16TOF32]] 240 // CHECK: fcmp oge float 241 // NATIVE-HALF: fcmp oge half 242 test = (h0 >= (__fp16)-2.0); 243 // CHECK: [[F16TOF32]] 244 // CHECK: fcmp oge float 245 // NATIVE-HALF: fpext half 246 // NATIVE-HALF: fcmp oge float 247 test = (h0 >= f2); 248 // CHECK: [[F16TOF32]] 249 // CHECK: fcmp oge float 250 // NATIVE-HALF: fpext half 251 // NATIVE-HALF: fcmp oge float 252 test = (f0 >= h2); 253 254 // CHECK: [[F16TOF32]] 255 // CHECK: [[F16TOF32]] 256 // CHECK: fcmp oeq float 257 // NATIVE-HALF: fcmp oeq half 258 test = (h1 == h2); 259 // CHECK: [[F16TOF32]] 260 // NOHALF: [[F16TOF32]] 261 // CHECK: fcmp oeq float 262 // NATIVE-HALF: fcmp oeq half 263 test = (h1 == (__fp16)1.0); 264 // CHECK: [[F16TOF32]] 265 // CHECK: fcmp oeq float 266 // NATIVE-HALF: fpext half 267 // NATIVE-HALF: fcmp oeq float 268 test = (h1 == f1); 269 // CHECK: [[F16TOF32]] 270 // CHECK: fcmp oeq float 271 // NATIVE-HALF: fpext half 272 // NATIVE-HALF: fcmp oeq float 273 test = (f1 == h1); 274 275 // CHECK: [[F16TOF32]] 276 // CHECK: [[F16TOF32]] 277 // CHECK: fcmp une float 278 // NATIVE-HALF: fcmp une half 279 test = (h1 != h2); 280 // CHECK: [[F16TOF32]] 281 // NOHALF: [[F16TOF32]] 282 // CHECK: fcmp une float 283 // NATIVE-HALF: fcmp une half 284 test = (h1 != (__fp16)1.0); 285 // CHECK: [[F16TOF32]] 286 // CHECK: fcmp une float 287 // NATIVE-HALF: fpext half 288 // NATIVE-HALF: fcmp une float 289 test = (h1 != f1); 290 // CHECK: [[F16TOF32]] 291 // CHECK: fcmp une float 292 // NATIVE-HALF: fpext half 293 // NATIVE-HALF: fcmp une float 294 test = (f1 != h1); 295 296 // CHECK: [[F16TOF32]] 297 // CHECK: fcmp une float 298 // CHECK: [[F16TOF32]] 299 // CHECK: [[F16TOF32]] 300 // CHECK: [[F32TOF16]] 301 // NATIVE-HALF: fcmp une half {{.*}}, 0xH0000 302 h1 = (h1 ? h2 : h0); 303 // Check assignments (inc. compound) 304 h0 = h1; 305 // NOHALF: [[F32TOF16]] 306 // HALF: store {{.*}} half 0xHC000 307 // NATIVE-HALF: store {{.*}} half 0xHC000 308 h0 = (__fp16)-2.0f; 309 // CHECK: [[F32TOF16]] 310 // NATIVE-HALF: fptrunc float 311 h0 = f0; 312 313 // CHECK: [[F16TOF32]] 314 // CHECK: [[F16TOF32]] 315 // CHECK: fadd float 316 // CHECK: [[F32TOF16]] 317 // NATIVE-HALF: fadd half 318 h0 += h1; 319 // CHECK: [[F16TOF32]] 320 // NOHALF: [[F16TOF32]] 321 // CHECK: fadd float 322 // CHECK: [[F32TOF16]] 323 // NATIVE-HALF: fadd half 324 h0 += (__fp16)1.0f; 325 // CHECK: [[F16TOF32]] 326 // CHECK: fadd float 327 // CHECK: [[F32TOF16]] 328 // NATIVE-HALF: fpext half 329 // NATIVE-HALF: fadd float 330 // NATIVE-HALF: fptrunc float 331 h0 += f2; 332 333 // CHECK: [[F16TOF32]] 334 // CHECK: [[F16TOF32]] 335 // CHECK: fsub float 336 // CHECK: [[F32TOF16]] 337 // NATIVE-HALF: fsub half 338 h0 -= h1; 339 // CHECK: [[F16TOF32]] 340 // NOHALF: [[F16TOF32]] 341 // CHECK: fsub float 342 // CHECK: [[F32TOF16]] 343 // NATIVE-HALF: fsub half 344 h0 -= (__fp16)1.0; 345 // CHECK: [[F16TOF32]] 346 // CHECK: fsub float 347 // CHECK: [[F32TOF16]] 348 // NATIVE-HALF: fpext half 349 // NATIVE-HALF: fsub float 350 // NATIVE-HALF: fptrunc float 351 h0 -= f2; 352 353 // CHECK: [[F16TOF32]] 354 // CHECK: [[F16TOF32]] 355 // CHECK: fmul float 356 // CHECK: [[F32TOF16]] 357 // NATIVE-HALF: fmul half 358 h0 *= h1; 359 // CHECK: [[F16TOF32]] 360 // NOHALF: [[F16TOF32]] 361 // CHECK: fmul float 362 // CHECK: [[F32TOF16]] 363 // NATIVE-HALF: fmul half 364 h0 *= (__fp16)1.0; 365 // CHECK: [[F16TOF32]] 366 // CHECK: fmul float 367 // CHECK: [[F32TOF16]] 368 // NATIVE-HALF: fpext half 369 // NATIVE-HALF: fmul float 370 // NATIVE-HALF: fptrunc float 371 h0 *= f2; 372 373 // CHECK: [[F16TOF32]] 374 // CHECK: [[F16TOF32]] 375 // CHECK: fdiv float 376 // CHECK: [[F32TOF16]] 377 // NATIVE-HALF: fdiv half 378 h0 /= h1; 379 // CHECK: [[F16TOF32]] 380 // NOHALF: [[F16TOF32]] 381 // CHECK: fdiv float 382 // CHECK: [[F32TOF16]] 383 // NATIVE-HALF: fdiv half 384 h0 /= (__fp16)1.0; 385 // CHECK: [[F16TOF32]] 386 // CHECK: fdiv float 387 // CHECK: [[F32TOF16]] 388 // NATIVE-HALF: fpext half 389 // NATIVE-HALF: fdiv float 390 // NATIVE-HALF: fptrunc float 391 h0 /= f2; 392 393 // Check conversions to/from double 394 // NOHALF: call i16 @llvm.convert.to.fp16.f64( 395 // HALF: fptrunc double {{.*}} to half 396 // NATIVE-HALF: fptrunc double {{.*}} to half 397 h0 = d0; 398 399 // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float 400 // NOHALF: call i16 @llvm.convert.to.fp16.f32(float [[MID]]) 401 // HALF: fptrunc float [[MID]] to half 402 // NATIVE-HALF: [[MID:%.*]] = fptrunc double {{%.*}} to float 403 // NATIVE-HALF: fptrunc float {{.*}} to half 404 h0 = (float)d0; 405 406 // NOHALF: call double @llvm.convert.from.fp16.f64( 407 // HALF: fpext half {{.*}} to double 408 // NATIVE-HALF: fpext half {{.*}} to double 409 d0 = h0; 410 411 // NOHALF: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32( 412 // HALF: [[MID:%.*]] = fpext half {{.*}} to float 413 // CHECK: fpext float [[MID]] to double 414 // NATIVE-HALF: [[MID:%.*]] = fpext half {{.*}} to float 415 // NATIVE-HALF: fpext float [[MID]] to double 416 d0 = (float)h0; 417} 418