Skip to content

Commit

Permalink
[OpenCL] Pipe builtin functions
Browse files Browse the repository at this point in the history
Summary:
Support for the pipe built-in functions for OpenCL 2.0.
The pipe builtin functions may have infinite kinds of element types, one approach
would be to just generate calls that would always use generic types such as void*.
This patch is based on bader's opencl support patch on SPIR-V branch.

Reviewers: Anastasia, pekka.jaaskelainen

Subscribers: keryell, bader, cfe-commits

Differential Revision: http://reviews.llvm.org/D15914

llvm-svn: 258773
  • Loading branch information
xiulipan committed Jan 26, 2016
1 parent 09a8a8a commit 3a9952c
Show file tree
Hide file tree
Showing 8 changed files with 510 additions and 1 deletion.
26 changes: 26 additions & 0 deletions clang/include/clang/Basic/Builtins.def
Expand Up @@ -1252,6 +1252,32 @@ BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
BUILTIN(__builtin_nontemporal_store, "v.", "t")
BUILTIN(__builtin_nontemporal_load, "v.", "t")

// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
// We need the generic prototype, since the packet type could be anything.
LANGBUILTIN(read_pipe, "i.", "tn", OCLC_LANG)
LANGBUILTIN(write_pipe, "i.", "tn", OCLC_LANG)

LANGBUILTIN(reserve_read_pipe, "i.", "tn", OCLC_LANG)
LANGBUILTIN(reserve_write_pipe, "i.", "tn", OCLC_LANG)

LANGBUILTIN(commit_write_pipe, "v.", "tn", OCLC_LANG)
LANGBUILTIN(commit_read_pipe, "v.", "tn", OCLC_LANG)

LANGBUILTIN(sub_group_reserve_read_pipe, "i.", "tn", OCLC_LANG)
LANGBUILTIN(sub_group_reserve_write_pipe, "i.", "tn", OCLC_LANG)

LANGBUILTIN(sub_group_commit_read_pipe, "v.", "tn", OCLC_LANG)
LANGBUILTIN(sub_group_commit_write_pipe, "v.", "tn", OCLC_LANG)

LANGBUILTIN(work_group_reserve_read_pipe, "i.", "tn", OCLC_LANG)
LANGBUILTIN(work_group_reserve_write_pipe, "i.", "tn", OCLC_LANG)

LANGBUILTIN(work_group_commit_read_pipe, "v.", "tn", OCLC_LANG)
LANGBUILTIN(work_group_commit_write_pipe, "v.", "tn", OCLC_LANG)

LANGBUILTIN(get_pipe_num_packets, "Ui.", "tn", OCLC_LANG)
LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC_LANG)

#undef BUILTIN
#undef LIBBUILTIN
#undef LANGBUILTIN
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Builtins.h
Expand Up @@ -36,6 +36,7 @@ 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.
OCLC_LANG = 0x20,// builtin for OpenCL C 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.
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -7680,6 +7680,16 @@ def err_atomic_init_constant : Error<
def err_opencl_implicit_vector_conversion : Error<
"implicit conversions between vector types (%0 and %1) are not permitted">;

// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
def err_opencl_builtin_pipe_first_arg : Error<
"first argument to %0 must be a pipe type">;
def err_opencl_builtin_pipe_arg_num : Error<
"invalid number of arguments to function: %0">;
def err_opencl_builtin_pipe_invalid_arg : Error<
"invalid argument type to function %0 (expecting %1)">;
def err_opencl_builtin_pipe_invalid_access_modifier : Error<
"invalid pipe access modifier (expecting %0)">;

// OpenCL Section 6.8.g
def err_opencl_unknown_type_specifier : Error<
"OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Basic/Builtins.cpp
Expand Up @@ -69,7 +69,8 @@ bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
bool MSModeUnsupported =
!LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
return !BuiltinsUnsupported && !MathBuiltinsUnsupported &&
bool OclCUnsupported = !LangOpts.OpenCL && BuiltinInfo.Langs == OCLC_LANG;
return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&
!GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;
}

Expand Down
135 changes: 135 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Expand Up @@ -3341,6 +3341,141 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
}
return SV;
}

// OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions
case Builtin::BIread_pipe:
case Builtin::BIwrite_pipe: {
Value *Arg0 = EmitScalarExpr(E->getArg(0)),
*Arg1 = EmitScalarExpr(E->getArg(1));

// Type of the generic packet parameter.
unsigned GenericAS =
getContext().getTargetAddressSpace(LangAS::opencl_generic);
llvm::Type *I8PTy = llvm::PointerType::get(
llvm::Type::getInt8Ty(getLLVMContext()), GenericAS);

// Testing which overloaded version we should generate the call for.
if (2U == E->getNumArgs()) {
const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_2"
: "__write_pipe_2";
// Creating a generic function type to be able to call with any builtin or
// user defined type.
llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy};
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
Value *BCast = Builder.CreatePointerCast(Arg1, I8PTy);
return RValue::get(Builder.CreateCall(
CGM.CreateRuntimeFunction(FTy, Name), {Arg0, BCast}));
} else {
assert(4 == E->getNumArgs() &&
"Illegal number of parameters to pipe function");
const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_4"
: "__write_pipe_4";

llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, I8PTy};
Value *Arg2 = EmitScalarExpr(E->getArg(2)),
*Arg3 = EmitScalarExpr(E->getArg(3));
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
Value *BCast = Builder.CreatePointerCast(Arg3, I8PTy);
// We know the third argument is an integer type, but we may need to cast
// it to i32.
if (Arg2->getType() != Int32Ty)
Arg2 = Builder.CreateZExtOrTrunc(Arg2, Int32Ty);
return RValue::get(Builder.CreateCall(
CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1, Arg2, BCast}));
}
}
// OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe reserve read and write
// functions
case Builtin::BIreserve_read_pipe:
case Builtin::BIreserve_write_pipe:
case Builtin::BIwork_group_reserve_read_pipe:
case Builtin::BIwork_group_reserve_write_pipe:
case Builtin::BIsub_group_reserve_read_pipe:
case Builtin::BIsub_group_reserve_write_pipe: {
// Composing the mangled name for the function.
const char *Name;
if (BuiltinID == Builtin::BIreserve_read_pipe)
Name = "__reserve_read_pipe";
else if (BuiltinID == Builtin::BIreserve_write_pipe)
Name = "__reserve_write_pipe";
else if (BuiltinID == Builtin::BIwork_group_reserve_read_pipe)
Name = "__work_group_reserve_read_pipe";
else if (BuiltinID == Builtin::BIwork_group_reserve_write_pipe)
Name = "__work_group_reserve_write_pipe";
else if (BuiltinID == Builtin::BIsub_group_reserve_read_pipe)
Name = "__sub_group_reserve_read_pipe";
else
Name = "__sub_group_reserve_write_pipe";

Value *Arg0 = EmitScalarExpr(E->getArg(0)),
*Arg1 = EmitScalarExpr(E->getArg(1));
llvm::Type *ReservedIDTy = ConvertType(getContext().OCLReserveIDTy);

// Building the generic function prototype.
llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty};
llvm::FunctionType *FTy = llvm::FunctionType::get(
ReservedIDTy, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
// We know the second argument is an integer type, but we may need to cast
// it to i32.
if (Arg1->getType() != Int32Ty)
Arg1 = Builder.CreateZExtOrTrunc(Arg1, Int32Ty);
return RValue::get(
Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1}));
}
// OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe commit read and write
// functions
case Builtin::BIcommit_read_pipe:
case Builtin::BIcommit_write_pipe:
case Builtin::BIwork_group_commit_read_pipe:
case Builtin::BIwork_group_commit_write_pipe:
case Builtin::BIsub_group_commit_read_pipe:
case Builtin::BIsub_group_commit_write_pipe: {
const char *Name;
if (BuiltinID == Builtin::BIcommit_read_pipe)
Name = "__commit_read_pipe";
else if (BuiltinID == Builtin::BIcommit_write_pipe)
Name = "__commit_write_pipe";
else if (BuiltinID == Builtin::BIwork_group_commit_read_pipe)
Name = "__work_group_commit_read_pipe";
else if (BuiltinID == Builtin::BIwork_group_commit_write_pipe)
Name = "__work_group_commit_write_pipe";
else if (BuiltinID == Builtin::BIsub_group_commit_read_pipe)
Name = "__sub_group_commit_read_pipe";
else
Name = "__sub_group_commit_write_pipe";

Value *Arg0 = EmitScalarExpr(E->getArg(0)),
*Arg1 = EmitScalarExpr(E->getArg(1));

// Building the generic function prototype.
llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType()};
llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
llvm::ArrayRef<llvm::Type *>(ArgTys), false);

return RValue::get(
Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1}));
}
// OpenCL v2.0 s6.13.16.4 Built-in pipe query functions
case Builtin::BIget_pipe_num_packets:
case Builtin::BIget_pipe_max_packets: {
const char *Name;
if (BuiltinID == Builtin::BIget_pipe_num_packets)
Name = "__get_pipe_num_packets";
else
Name = "__get_pipe_max_packets";

// Building the generic function prototype.
Value *Arg0 = EmitScalarExpr(E->getArg(0));
llvm::Type *ArgTys[] = {Arg0->getType()};
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);

return RValue::get(
Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0}));
}
}

assert(Int && "Expected valid intrinsic number");
Expand Down

0 comments on commit 3a9952c

Please sign in to comment.