From: Pirama Arumuga Nainar Date: Thu, 14 May 2015 23:44:18 +0000 (+0000) Subject: Add flag to enable native half type X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=628b143f45deb7ccdf0eb4e6782a7bc3af6d59e5;p=clang Add flag to enable native half type Summary: r235215 enables support in LLVM for legalizing f16 type in the IR. AArch64 already had support for this. r235215 and some backend patches brought support for ARM, X86, X86-64, Mips and Mips64. This change exposes the LangOption 'NativeHalfType' in the command line, so the backend legalization can be used if desired. NativeHalfType is enabled for OpenCL (current behavior) or if '-fnative-half-type' is set. Reviewers: olista01, steven_wu, ab Subscribers: cfe-commits, srhines, aemerson Differential Revision: http://reviews.llvm.org/D9781 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237406 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index a861428cce..9c1b561bca 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -547,6 +547,8 @@ def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">, HelpText<"Control vtordisp placement on win32 targets">; def fno_rtti_data : Flag<["-"], "fno-rtti-data">, HelpText<"Control emission of RTTI data">; +def fnative_half_type: Flag<["-"], "fnative-half-type">, + HelpText<"Use the native half type for __fp16 instead of promoting to float">; def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">, HelpText<"Allow function arguments and returns of type half">; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index d2514acd6d..1d6723f33a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1587,7 +1587,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ImplementationOfModule = Args.getLastArgValue(OPT_fmodule_implementation_of); Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature); - Opts.NativeHalfType = Opts.NativeHalfType; + Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type); Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns); Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); diff --git a/test/CodeGen/fp16-ops.c b/test/CodeGen/fp16-ops.c index 0c218be0ec..fe0fa2c266 100644 --- a/test/CodeGen/fp16-ops.c +++ b/test/CodeGen/fp16-ops.c @@ -3,6 +3,10 @@ // 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 +// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -fnative-half-type %s \ +// RUN: | FileCheck %s --check-prefix=NATIVE-HALF +// RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi -fnative-half-type %s \ +// RUN: | FileCheck %s --check-prefix=NATIVE-HALF typedef unsigned cond_t; volatile cond_t test; @@ -18,37 +22,47 @@ void foo(void) { // NOHALF: [[F16TOF32:call float @llvm.convert.from.fp16.f32]] // HALF: [[F16TOF32:fpext half]] // CHECK: fptoui float + // NATIVE-HALF: fptoui half test = (h0); // CHECK: uitofp i32 // NOHALF: [[F32TOF16:call i16 @llvm.convert.to.fp16.f32]] // HALF: [[F32TOF16:fptrunc float]] + // NATIVE-HALF: uitofp i32 {{.*}} to half h0 = (test); // CHECK: [[F16TOF32]] // CHECK: fcmp une float + // NATIVE-HALF: fcmp une half test = (!h1); // CHECK: [[F16TOF32]] // CHECK: fsub float // NOHALF: [[F32TOF16]] // HALF: [[F32TOF16]] + // NATIVE-HALF: fsub half h1 = -h1; // CHECK: [[F16TOF32]] // CHECK: [[F32TOF16]] + // NATIVE-HALF: load volatile half + // NATIVE-HALF-NEXT: store volatile half h1 = +h1; // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half h1++; // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half ++h1; // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half --h1; // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half h1--; // Check binary ops with various operands @@ -56,259 +70,348 @@ void foo(void) { // CHECK: [[F16TOF32]] // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fmul half h1 = h0 * h2; // CHECK: [[F16TOF32]] // NOHALF: [[F32TOF16]] // NOHALF: [[F16TOF32]] // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fmul half h1 = h0 * (__fp16) -2.0f; // CHECK: [[F16TOF32]] // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fmul float h1 = h0 * f2; // CHECK: [[F16TOF32]] // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fmul float h1 = f0 * h2; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fdiv half h1 = (h0 / h2); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fdiv half h1 = (h0 / (__fp16) -2.0f); // CHECK: [[F16TOF32]] // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fdiv float h1 = (h0 / f2); // CHECK: [[F16TOF32]] // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fdiv float h1 = (f0 / h2); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half h1 = (h2 + h0); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half h1 = ((__fp16)-2.0 + h0); // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fadd float h1 = (h2 + f0); // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fadd float h1 = (f2 + h0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fsub half h1 = (h2 - h0); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fsub half h1 = ((__fp16)-2.0f - h0); // CHECK: [[F16TOF32]] // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fsub float h1 = (h2 - f0); // CHECK: [[F16TOF32]] // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fsub float h1 = (f2 - h0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fcmp olt + // CHECK: fcmp olt float + // NATIVE-HALF: fcmp olt half test = (h2 < h0); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fcmp olt + // CHECK: fcmp olt float + // NATIVE-HALF: fcmp olt half test = (h2 < (__fp16)42.0); // CHECK: [[F16TOF32]] - // CHECK: fcmp olt + // CHECK: fcmp olt float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp olt float test = (h2 < f0); // CHECK: [[F16TOF32]] - // CHECK: fcmp olt + // CHECK: fcmp olt float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp olt float test = (f2 < h0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fcmp ogt + // CHECK: fcmp ogt float + // NATIVE-HALF: fcmp ogt half test = (h0 > h2); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fcmp ogt + // CHECK: fcmp ogt float + // NATIVE-HALF: fcmp ogt half test = ((__fp16)42.0 > h2); // CHECK: [[F16TOF32]] - // CHECK: fcmp ogt + // CHECK: fcmp ogt float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp ogt float test = (h0 > f2); // CHECK: [[F16TOF32]] - // CHECK: fcmp ogt + // CHECK: fcmp ogt float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp ogt float test = (f0 > h2); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fcmp ole + // CHECK: fcmp ole float + // NATIVE-HALF: fcmp ole half test = (h2 <= h0); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fcmp ole + // CHECK: fcmp ole float + // NATIVE-HALF: fcmp ole half test = (h2 <= (__fp16)42.0); // CHECK: [[F16TOF32]] - // CHECK: fcmp ole + // CHECK: fcmp ole float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp ole float test = (h2 <= f0); // CHECK: [[F16TOF32]] - // CHECK: fcmp ole + // CHECK: fcmp ole float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp ole float test = (f2 <= h0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fcmp oge + // CHECK: fcmp oge float + // NATIVE-HALF: fcmp oge half test = (h0 >= h2); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fcmp oge + // CHECK: fcmp oge float + // NATIVE-HALF: fcmp oge half test = (h0 >= (__fp16)-2.0); // CHECK: [[F16TOF32]] - // CHECK: fcmp oge + // CHECK: fcmp oge float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp oge float test = (h0 >= f2); // CHECK: [[F16TOF32]] - // CHECK: fcmp oge + // CHECK: fcmp oge float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp oge float test = (f0 >= h2); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fcmp oeq + // CHECK: fcmp oeq float + // NATIVE-HALF: fcmp oeq half test = (h1 == h2); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fcmp oeq + // CHECK: fcmp oeq float + // NATIVE-HALF: fcmp oeq half test = (h1 == (__fp16)1.0); // CHECK: [[F16TOF32]] - // CHECK: fcmp oeq + // CHECK: fcmp oeq float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp oeq float test = (h1 == f1); // CHECK: [[F16TOF32]] - // CHECK: fcmp oeq + // CHECK: fcmp oeq float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp oeq float test = (f1 == h1); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fcmp une + // CHECK: fcmp une float + // NATIVE-HALF: fcmp une half test = (h1 != h2); // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fcmp une + // CHECK: fcmp une float + // NATIVE-HALF: fcmp une half test = (h1 != (__fp16)1.0); // CHECK: [[F16TOF32]] - // CHECK: fcmp une + // CHECK: fcmp une float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp une float test = (h1 != f1); // CHECK: [[F16TOF32]] - // CHECK: fcmp une + // CHECK: fcmp une float + // NATIVE-HALF: fpext half + // NATIVE-HALF: fcmp une float test = (f1 != h1); // CHECK: [[F16TOF32]] - // CHECK: fcmp une + // CHECK: fcmp une float // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] // CHECK: [[F32TOF16]] + // NATIVE-HALF: fcmp une half {{.*}}, 0xH0000 h1 = (h1 ? h2 : h0); // Check assignments (inc. compound) h0 = h1; // NOHALF: [[F32TOF16]] // HALF: store {{.*}} half 0xHC000 + // NATIVE-HALF: store {{.*}} half 0xHC000 h0 = (__fp16)-2.0f; // CHECK: [[F32TOF16]] + // NATIVE-HALF: fptrunc float h0 = f0; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half h0 += h1; // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fadd + // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half h0 += (__fp16)1.0f; // CHECK: [[F16TOF32]] - // CHECK: fadd + // CHECK: fadd float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fadd float + // NATIVE-HALF: fptrunc float h0 += f2; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fsub + // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fsub half h0 -= h1; // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fsub + // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fsub half h0 -= (__fp16)1.0; // CHECK: [[F16TOF32]] - // CHECK: fsub + // CHECK: fsub float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fsub float + // NATIVE-HALF: fptrunc float h0 -= f2; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fmul + // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fmul half h0 *= h1; // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fmul + // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fmul half h0 *= (__fp16)1.0; // CHECK: [[F16TOF32]] - // CHECK: fmul + // CHECK: fmul float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fmul float + // NATIVE-HALF: fptrunc float h0 *= f2; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] - // CHECK: fdiv + // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fdiv half h0 /= h1; // CHECK: [[F16TOF32]] // NOHALF: [[F16TOF32]] - // CHECK: fdiv + // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fdiv half h0 /= (__fp16)1.0; // CHECK: [[F16TOF32]] - // CHECK: fdiv + // CHECK: fdiv float // CHECK: [[F32TOF16]] + // NATIVE-HALF: fpext half + // NATIVE-HALF: fdiv float + // NATIVE-HALF: fptrunc float h0 /= f2; // Check conversions to/from double // NOHALF: call i16 @llvm.convert.to.fp16.f64( // HALF: fptrunc double {{.*}} to half + // NATIVE-HALF: fptrunc double {{.*}} to half h0 = d0; // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float // NOHALF: call i16 @llvm.convert.to.fp16.f32(float [[MID]]) // HALF: fptrunc float [[MID]] to half + // NATIVE-HALF: [[MID:%.*]] = fptrunc double {{%.*}} to float + // NATIVE-HALF: fptrunc float {{.*}} to half h0 = (float)d0; // NOHALF: call double @llvm.convert.from.fp16.f64( // HALF: fpext half {{.*}} to double + // NATIVE-HALF: fpext half {{.*}} to double d0 = h0; // NOHALF: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32( // HALF: [[MID:%.*]] = fpext half {{.*}} to float // CHECK: fpext float [[MID]] to double + // NATIVE-HALF: [[MID:%.*]] = fpext half {{.*}} to float + // NATIVE-HALF: fpext float [[MID]] to double d0 = (float)h0; }