summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen
diff options
context:
space:
mode:
authorAhmed Bougacha <ahmed.bougacha@gmail.com>2015-03-23 17:54:16 +0000
committerAhmed Bougacha <ahmed.bougacha@gmail.com>2015-03-23 17:54:16 +0000
commitd1801afeac1b125656878d85d04686f9579da31f (patch)
treebd0d38455e4763b51821368794dfd4c7ccebfb27 /clang/test/CodeGen
parent4c276fb4cc63626bfcfde0af9d2cc97545f38af6 (diff)
downloadbcm5719-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.c282
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;
}
OpenPOWER on IntegriCloud