Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -1423,6 +1423,12 @@ LANGBUILTIN(to_local, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG) +// OpenCL half load/store builtin +BUILTIN(__builtin_store_half, "vdh*", "n") +BUILTIN(__builtin_store_halff, "vfh*", "n") +BUILTIN(__builtin_load_half, "dh*", "nc") +BUILTIN(__builtin_load_halff, "fh*", "nc") + // 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") Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -2724,6 +2724,24 @@ 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); Index: test/CodeGenOpenCL/no-half.cl =================================================================== --- /dev/null +++ test/CodeGenOpenCL/no-half.cl @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 %s -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 +// 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 +// CHECK: [[FULL_VAL:%.*]] = fpext half [[HALF_VAL]] to double +// CHECK: store double [[FULL_VAL]], double addrspace({{.}})* %foo +}