diff options
| author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2015-03-23 17:54:16 +0000 |
|---|---|---|
| committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2015-03-23 17:54:16 +0000 |
| commit | d1801afeac1b125656878d85d04686f9579da31f (patch) | |
| tree | bd0d38455e4763b51821368794dfd4c7ccebfb27 /clang/test/CodeGen | |
| parent | 4c276fb4cc63626bfcfde0af9d2cc97545f38af6 (diff) | |
| download | bcm5719-llvm-d1801afeac1b125656878d85d04686f9579da31f.tar.gz bcm5719-llvm-d1801afeac1b125656878d85d04686f9579da31f.zip | |
[CodeGen] Properly support the half FP type with non-native operations.
On AArch64, the -fallow-half-args-and-returns option is the default.
With it, the half type is considered legal (rather than the i16 used
normally for __fp16), but no operation is, except conversions and
load/stores and such.
The previous behavior was tantamount to saying LangOpts.NativeHalfType
was implied by LangOpts.HalfArgsAndReturns, which isn't true.
Instead, teach the various parts of CodeGen that already know about
half (using the intrinsics or not) about this weird in-between case,
where the "half" type is legal, but operations on it aren't.
This is a smaller intermediate step to the end-goal of removing the
intrinsic, always using "half", and letting the backend legalize.
Builds on r232968.
rdar://20045970, rdar://17468714
Differential Revision: http://reviews.llvm.org/D8367
llvm-svn: 232971
Diffstat (limited to 'clang/test/CodeGen')
| -rw-r--r-- | clang/test/CodeGen/fp16-ops.c | 282 |
1 files changed, 148 insertions, 134 deletions
diff --git a/clang/test/CodeGen/fp16-ops.c b/clang/test/CodeGen/fp16-ops.c index 5dd0b320b28..0c218be0ec5 100644 --- a/clang/test/CodeGen/fp16-ops.c +++ b/clang/test/CodeGen/fp16-ops.c @@ -1,5 +1,8 @@ // REQUIRES: arm-registered-target -// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOHALF --check-prefix=CHECK +// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOHALF --check-prefix=CHECK +// 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 +// 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 typedef unsigned cond_t; volatile cond_t test; @@ -12,289 +15,300 @@ void foo(void) { // Check unary ops - // CHECK: call float @llvm.convert.from.fp16.f32( + // NOHALF: [[F16TOF32:call float @llvm.convert.from.fp16.f32]] + // HALF: [[F16TOF32:fpext half]] // CHECK: fptoui float test = (h0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: uitofp i32 + // NOHALF: [[F32TOF16:call i16 @llvm.convert.to.fp16.f32]] + // HALF: [[F32TOF16:fptrunc float]] + h0 = (test); + // CHECK: [[F16TOF32]] // CHECK: fcmp une float test = (!h1); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fsub float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // NOHALF: [[F32TOF16]] + // HALF: [[F32TOF16]] h1 = -h1; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F32TOF16]] h1 = +h1; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1++; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] ++h1; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] --h1; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1--; // Check binary ops with various operands - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fmul float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = h0 * h2; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call i16 @llvm.convert.to.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F32TOF16]] + // NOHALF: [[F16TOF32]] // CHECK: fmul float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = h0 * (__fp16) -2.0f; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fmul float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = h0 * f2; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fmul float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = f0 * h2; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fdiv float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h0 / h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fdiv float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h0 / (__fp16) -2.0f); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fdiv float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h0 / f2); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fdiv float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (f0 / h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h2 + h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = ((__fp16)-2.0 + h0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h2 + f0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (f2 + h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fsub float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h2 - h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fsub float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = ((__fp16)-2.0f - h0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fsub float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (h2 - f0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fsub float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h1 = (f2 - h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fcmp olt test = (h2 < h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fcmp olt test = (h2 < (__fp16)42.0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp olt test = (h2 < f0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp olt test = (f2 < h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fcmp ogt test = (h0 > h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fcmp ogt test = ((__fp16)42.0 > h2); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp ogt test = (h0 > f2); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp ogt test = (f0 > h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fcmp ole test = (h2 <= h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fcmp ole test = (h2 <= (__fp16)42.0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp ole test = (h2 <= f0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp ole test = (f2 <= h0); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fcmp oge test = (h0 >= h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fcmp oge test = (h0 >= (__fp16)-2.0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp oge test = (h0 >= f2); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp oge test = (f0 >= h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fcmp oeq test = (h1 == h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fcmp oeq test = (h1 == (__fp16)1.0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp oeq test = (h1 == f1); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp oeq test = (f1 == h1); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fcmp une test = (h1 != h2); - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fcmp une test = (h1 != (__fp16)1.0); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp une test = (h1 != f1); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp une test = (f1 != h1); - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fcmp une - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] + // CHECK: [[F32TOF16]] h1 = (h1 ? h2 : h0); // Check assignments (inc. compound) h0 = h1; - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // NOHALF: [[F32TOF16]] + // HALF: store {{.*}} half 0xHC000 h0 = (__fp16)-2.0f; - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 = f0; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fadd float - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 += h1; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fadd - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 += (__fp16)1.0f; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fadd - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 += f2; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fsub - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 -= h1; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fsub - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 -= (__fp16)1.0; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fsub - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 -= f2; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fmul - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 *= h1; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fmul - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 *= (__fp16)1.0; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fmul - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 *= f2; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // CHECK: [[F16TOF32]] // CHECK: fdiv - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 /= h1; - // CHECK: call float @llvm.convert.from.fp16.f32( - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] + // NOHALF: [[F16TOF32]] // CHECK: fdiv - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 /= (__fp16)1.0; - // CHECK: call float @llvm.convert.from.fp16.f32( + // CHECK: [[F16TOF32]] // CHECK: fdiv - // CHECK: call i16 @llvm.convert.to.fp16.f32( + // CHECK: [[F32TOF16]] h0 /= f2; // Check conversions to/from double - // CHECK: call i16 @llvm.convert.to.fp16.f64( + // NOHALF: call i16 @llvm.convert.to.fp16.f64( + // HALF: fptrunc double {{.*}} to half h0 = d0; // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float - // CHECK: call i16 @llvm.convert.to.fp16.f32(float [[MID]]) + // NOHALF: call i16 @llvm.convert.to.fp16.f32(float [[MID]]) + // HALF: fptrunc float [[MID]] to half h0 = (float)d0; - // CHECK: call double @llvm.convert.from.fp16.f64( + // NOHALF: call double @llvm.convert.from.fp16.f64( + // HALF: fpext half {{.*}} to double d0 = h0; - // CHECK: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32( + // NOHALF: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32( + // HALF: [[MID:%.*]] = fpext half {{.*}} to float // CHECK: fpext float [[MID]] to double d0 = (float)h0; } |

