From 31ecb4bf602f26866a4e29dcaeab3fbb8b742a36 Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Thu, 7 Sep 2017 19:39:10 +0000 Subject: [PATCH] [OpenCL] Add half load and store builtins This enables load/stores of half type, without half being a legal type. Differential Revision: https://reviews.llvm.org/D37231 llvm-svn: 312742 --- clang/include/clang/Basic/Builtins.def | 6 ++++ clang/include/clang/Basic/Builtins.h | 6 ++-- clang/lib/Basic/Builtins.cpp | 9 ++++-- clang/lib/CodeGen/CGBuiltin.cpp | 18 ++++++++++++ clang/test/CodeGenOpenCL/no-half.cl | 39 ++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGenOpenCL/no-half.cl diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 8941fc5daad96..8d395e1414087 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -1424,6 +1424,12 @@ LANGBUILTIN(to_global, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_local, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG) +// OpenCL half load/store builtin +LANGBUILTIN(__builtin_store_half, "vdh*", "n", ALL_OCLC_LANGUAGES) +LANGBUILTIN(__builtin_store_halff, "vfh*", "n", ALL_OCLC_LANGUAGES) +LANGBUILTIN(__builtin_load_half, "dhC*", "nc", ALL_OCLC_LANGUAGES) +LANGBUILTIN(__builtin_load_halff, "fhC*", "nc", ALL_OCLC_LANGUAGES) + // Builtins for os_log/os_trace BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index 87c1f93eedefe..093adf15a95c6 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -36,10 +36,12 @@ enum LanguageID { CXX_LANG = 0x4, // builtin for cplusplus only. OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ MS_LANG = 0x10, // builtin requires MS mode. - OCLC20_LANG = 0x20, // builtin for OpenCL C only. + OCLC20_LANG = 0x20, // builtin for OpenCL C 2.0 only. + OCLC1X_LANG = 0x40, // builtin for OpenCL C 1.x only. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. - ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. + ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG, // builtin requires MS mode. + ALL_OCLC_LANGUAGES = OCLC1X_LANG | OCLC20_LANG // builtin for OCLC languages. }; namespace Builtin { diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index 28695d649a867..2f0cba41f9603 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -69,9 +69,14 @@ bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo, bool MSModeUnsupported = !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG); bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG; - bool OclCUnsupported = LangOpts.OpenCLVersion != 200 && - BuiltinInfo.Langs == OCLC20_LANG; + bool OclC1Unsupported = (LangOpts.OpenCLVersion / 100) != 1 && + (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES ) == OCLC1X_LANG; + bool OclC2Unsupported = LangOpts.OpenCLVersion != 200 && + (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES) == OCLC20_LANG; + bool OclCUnsupported = !LangOpts.OpenCL && + (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES); return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported && + !OclC1Unsupported && !OclC2Unsupported && !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a4a06193146cc..f80b259f834cd 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2768,6 +2768,24 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Name), {NDRange, Block})); } + + case Builtin::BI__builtin_store_half: + case Builtin::BI__builtin_store_halff: { + Value *Val = EmitScalarExpr(E->getArg(0)); + Address Address = EmitPointerWithAlignment(E->getArg(1)); + Value *HalfVal = Builder.CreateFPTrunc(Val, Builder.getHalfTy()); + return RValue::get(Builder.CreateStore(HalfVal, Address)); + } + case Builtin::BI__builtin_load_half: { + Address Address = EmitPointerWithAlignment(E->getArg(0)); + Value *HalfVal = Builder.CreateLoad(Address); + return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getDoubleTy())); + } + case Builtin::BI__builtin_load_halff: { + Address Address = EmitPointerWithAlignment(E->getArg(0)); + Value *HalfVal = Builder.CreateLoad(Address); + return RValue::get(Builder.CreateFPExt(HalfVal, Builder.getFloatTy())); + } case Builtin::BIprintf: if (getTarget().getTriple().isNVPTX()) return EmitNVPTXDevicePrintfCallExpr(E, ReturnValue); diff --git a/clang/test/CodeGenOpenCL/no-half.cl b/clang/test/CodeGenOpenCL/no-half.cl new file mode 100644 index 0000000000000..aee8f678f01a5 --- /dev/null +++ b/clang/test/CodeGenOpenCL/no-half.cl @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 %s -cl-std=cl2.0 -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=cl1.2 -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=cl1.1 -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s + +#pragma OPENCL EXTENSION cl_khr_fp64:enable + +// CHECK-LABEL: @test_store_float(float %foo, half addrspace({{.}}){{.*}} %bar) +__kernel void test_store_float(float foo, __global half* bar) +{ + __builtin_store_halff(foo, bar); +// CHECK: [[HALF_VAL:%.*]] = fptrunc float %foo to half +// CHECK: store half [[HALF_VAL]], half addrspace({{.}})* %bar, align 2 +} + +// CHECK-LABEL: @test_store_double(double %foo, half addrspace({{.}}){{.*}} %bar) +__kernel void test_store_double(double foo, __global half* bar) +{ + __builtin_store_half(foo, bar); +// CHECK: [[HALF_VAL:%.*]] = fptrunc double %foo to half +// CHECK: store half [[HALF_VAL]], half addrspace({{.}})* %bar, align 2 +} + +// CHECK-LABEL: @test_load_float(float addrspace({{.}}){{.*}} %foo, half addrspace({{.}}){{.*}} %bar) +__kernel void test_load_float(__global float* foo, __global half* bar) +{ + foo[0] = __builtin_load_halff(bar); +// CHECK: [[HALF_VAL:%.*]] = load half, half addrspace({{.}})* %bar +// CHECK: [[FULL_VAL:%.*]] = fpext half [[HALF_VAL]] to float +// CHECK: store float [[FULL_VAL]], float addrspace({{.}})* %foo +} + +// CHECK-LABEL: @test_load_double(double addrspace({{.}}){{.*}} %foo, half addrspace({{.}}){{.*}} %bar) +__kernel void test_load_double(__global double* foo, __global half* bar) +{ + foo[0] = __builtin_load_half(bar); +// CHECK: [[HALF_VAL:%.*]] = load half, half addrspace({{.}})* %bar +// CHECK: [[FULL_VAL:%.*]] = fpext half [[HALF_VAL]] to double +// CHECK: store double [[FULL_VAL]], double addrspace({{.}})* %foo +}