r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 3 13:41:45 PST 2016


On Wed, Feb 3, 2016 at 1:00 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On Wed, Feb 3, 2016 at 11:08 AM, Anastasia Stulova
> <Anastasia.Stulova at arm.com> wrote:
>>
>> I think the main reason is that we have committed pipe type before the
>> release branch was taken. It appears to have no use without the pipe builtin
>> functions.
>>
>> Are there any risks of adding this now?
>
>
> Based on my post-commit review of the patch, I don't think this is yet
> mature enough for 3.8 (in particular, it improperly handles type sugar, and
> should be performing argument conversions in SemaChecking rather than in
> CGBuiltin). If you're confident that this can be cleaned up in time, and
> Hans is prepared to take those cleanup patches onto the branch too, then I
> think this is fine to go into 3.8 to finish off the OpenCL pipe work.

I wouldn't be keen on taking those patches. We've already tagged RC2,
and I want bugfixes only going forward. I think the reality is that
this landed a little too late to make it into the release, and will
have to wait until 3.9.

 - Hans


>> -----Original Message-----
>> From: metafoo at gmail.com [mailto:metafoo at gmail.com] On Behalf Of Richard
>> Smith
>> Sent: 01 February 2016 21:54
>> To: Hans Wennborg
>> Cc: xiuli pan; cfe-commits; Pekka Jääskeläinen; Anastasia Stulova
>> Subject: Re: r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions
>>
>> On Thu, Jan 28, 2016 at 11:25 AM, Hans Wennborg <hwennborg at google.com>
>> wrote:
>> > I don't think we have a specific code owner for OpenCL in Clang, which
>> > means Richard is the owner.
>> >
>> > Richard, what do you think?
>>
>> Is there a reason we want to push this new feature into 3.8 rather than
>> waiting for the next release?
>>
>> > On Wed, Jan 27, 2016 at 10:08 PM, xiuli pan <xiulipan at outlook.com>
>> > wrote:
>> >> Hi hans,
>> >>
>> >> Request to merge it to release 38
>> >>
>> >> It adds Pipe BIFs to be used along with Pipe type committed earlier (in
>> >> r257254).
>> >>
>> >> Thanks
>> >> Xiuli
>> >>
>> >> -----Original Message-----
>> >> From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org] On
>> >> Behalf Of Xiuli Pan via cfe-commits
>> >> Sent: Tuesday, January 26, 2016 12:04 PM
>> >> To: cfe-commits at lists.llvm.org
>> >> Subject: r258782 - Recommit: R258773 [OpenCL] Pipe builtin functions
>> >>
>> >> Author: pxl
>> >> Date: Mon Jan 25 22:03:48 2016
>> >> New Revision: 258782
>> >>
>> >> URL: http://llvm.org/viewvc/llvm-project?rev=258782&view=rev
>> >> Log:
>> >> Recommit: R258773 [OpenCL] Pipe builtin functions Fix arc patch fuzz
>> >> error.
>> >> 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
>> >>
>> >> Added:
>> >>     cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl
>> >>     cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
>> >> Modified:
>> >>     cfe/trunk/include/clang/Basic/Builtins.def
>> >>     cfe/trunk/include/clang/Basic/Builtins.h
>> >>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> >>     cfe/trunk/lib/Basic/Builtins.cpp
>> >>     cfe/trunk/lib/CodeGen/CGBuiltin.cpp
>> >>     cfe/trunk/lib/Sema/SemaChecking.cpp
>> >>
>> >> Modified: cfe/trunk/include/clang/Basic/Builtins.def
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Bui
>> >> ltins.def?rev=258782&r1=258781&r2=258782&view=diff
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/include/clang/Basic/Builtins.def (original)
>> >> +++ cfe/trunk/include/clang/Basic/Builtins.def Mon Jan 25 22:03:48
>> >> +++ 2016
>> >> @@ -1252,6 +1252,32 @@ BUILTIN(__builtin___get_unsafe_stack_ptr
>> >>  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
>> >>
>> >> Modified: cfe/trunk/include/clang/Basic/Builtins.h
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Bui
>> >> ltins.h?rev=258782&r1=258781&r2=258782&view=diff
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/include/clang/Basic/Builtins.h (original)
>> >> +++ cfe/trunk/include/clang/Basic/Builtins.h Mon Jan 25 22:03:48 2016
>> >> @@ -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.
>> >>
>> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Dia
>> >> gnosticSemaKinds.td?rev=258782&r1=258781&r2=258782&view=diff
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>> >> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 25
>> >> +++ 22:03:48 2016
>> >> @@ -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">;
>> >>
>> >> Modified: cfe/trunk/lib/Basic/Builtins.cpp
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Builtins.cpp?
>> >> rev=258782&r1=258781&r2=258782&view=diff
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/lib/Basic/Builtins.cpp (original)
>> >> +++ cfe/trunk/lib/Basic/Builtins.cpp Mon Jan 25 22:03:48 2016
>> >> @@ -69,7 +69,8 @@ bool Builtin::Context::builtinIsSupporte
>> >>    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;  }
>> >>
>> >>
>> >> Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.c
>> >> pp?rev=258782&r1=258781&r2=258782&view=diff
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
>> >> +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Jan 25 22:03:48 2016
>> >> @@ -1963,6 +1963,142 @@ RValue CodeGenFunction::EmitBuiltinExpr(
>> >>        return RValue::get(llvm::ConstantExpr::getBitCast(GV,
>> >> CGM.Int8PtrTy));
>> >>      break;
>> >>    }
>> >> +
>> >> +  // 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}));  }
>> >> +
>> >>    case Builtin::BIprintf:
>> >>      if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice)
>> >>        return EmitCUDADevicePrintfCallExpr(E, ReturnValue);
>> >>
>> >> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.c
>> >> pp?rev=258782&r1=258781&r2=258782&view=diff
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
>> >> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jan 25 22:03:48 2016
>> >> @@ -258,6 +258,192 @@ static bool SemaBuiltinSEHScopeCheck(Sem
>> >>    return false;
>> >>  }
>> >>
>> >> +/// Returns readable name for a call.
>> >> +static StringRef getFunctionName(CallExpr *Call) {
>> >> +  return cast<FunctionDecl>(Call->getCalleeDecl())->getName();
>> >> +}
>> >> +
>> >> +/// Returns OpenCL access qual.
>> >> +// TODO: Refine OpenCLImageAccessAttr to OpenCLAccessAttr since pipe
>> >> +can use // it too static OpenCLImageAccessAttr
>> >> +*getOpenCLArgAccess(const Decl *D) {
>> >> +  if (D->hasAttr<OpenCLImageAccessAttr>())
>> >> +    return D->getAttr<OpenCLImageAccessAttr>();
>> >> +  return nullptr;
>> >> +}
>> >> +
>> >> +/// Returns true if pipe element type is different from the pointer.
>> >> +static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
>> >> +  const Expr *Arg0 = Call->getArg(0);
>> >> +  // First argument type should always be pipe.
>> >> +  if (!Arg0->getType()->isPipeType()) {
>> >> +    S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_first_arg)
>> >> +        << getFunctionName(Call) << Arg0->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +  OpenCLImageAccessAttr *AccessQual =
>> >> +      getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());
>> >> +  // Validates the access qualifier is compatible with the call.
>> >> +  // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should
>> >> +only be
>> >> +  // read_only and write_only, and assumed to be read_only if no
>> >> +qualifier is
>> >> +  // specified.
>> >> +  bool isValid = true;
>> >> +  bool ReadOnly = getFunctionName(Call).find("read") !=
>> >> +StringRef::npos;
>> >> +  if (ReadOnly)
>> >> +    isValid = AccessQual == nullptr || AccessQual->isReadOnly();
>> >> +  else
>> >> +    isValid = AccessQual != nullptr && AccessQual->isWriteOnly();
>> >> +  if (!isValid) {
>> >> +    const char *AM = ReadOnly ? "read_only" : "write_only";
>> >> +    S.Diag(Arg0->getLocStart(),
>> >> +           diag::err_opencl_builtin_pipe_invalid_access_modifier)
>> >> +        << AM << Arg0->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +
>> >> +  return false;
>> >> +}
>> >> +
>> >> +/// Returns true if pipe element type is different from the pointer.
>> >> +static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call,
>> >> +unsigned Idx) {
>> >> +  const Expr *Arg0 = Call->getArg(0);
>> >> +  const Expr *ArgIdx = Call->getArg(Idx);
>> >> +  const PipeType *PipeTy = cast<PipeType>(Arg0->getType());
>> >> +  const Type *EltTy = PipeTy->getElementType().getTypePtr();
>> >> +  const PointerType *ArgTy =
>> >> +      dyn_cast<PointerType>(ArgIdx->getType().getTypePtr());
>> >> +  // The Idx argument should be a pointer and the type of the
>> >> +pointer and
>> >> +  // the type of pipe element should also be the same.
>> >> +  if (!ArgTy || EltTy != ArgTy->getPointeeType().getTypePtr()) {
>> >> +    S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_invalid_arg)
>> >> +        << getFunctionName(Call)
>> >> +        << S.Context.getPointerType(PipeTy->getElementType())
>> >> +        << ArgIdx->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +  return false;
>> >> +}
>> >> +
>> >> +// \brief Performs semantic analysis for the read/write_pipe call.
>> >> +// \param S Reference to the semantic analyzer.
>> >> +// \param Call A pointer to the builtin call.
>> >> +// \return True if a semantic error has been found, false otherwise.
>> >> +static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) {
>> >> +  // Two kinds of read/write pipe
>> >> +  // From OpenCL C Specification 6.13.16.2 the built-in read/write
>> >> +  // functions have following forms.
>> >> +  switch (Call->getNumArgs()) {
>> >> +  case 2: {
>> >> +    if (checkOpenCLPipeArg(S, Call))
>> >> +      return true;
>> >> +    // The call with 2 arguments should be
>> >> +    // read/write_pipe(pipe T, T*)
>> >> +    // check packet type T
>> >> +    if (checkOpenCLPipePacketType(S, Call, 1))
>> >> +      return true;
>> >> +  } break;
>> >> +
>> >> +  case 4: {
>> >> +    if (checkOpenCLPipeArg(S, Call))
>> >> +      return true;
>> >> +    // The call with 4 arguments should be
>> >> +    // read/write_pipe(pipe T, reserve_id_t, uint, T*)
>> >> +    // check reserve_id_t
>> >> +    if (!Call->getArg(1)->getType()->isReserveIDT()) {
>> >> +      S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_invalid_arg)
>> >> +          << getFunctionName(Call) << S.Context.OCLReserveIDTy
>> >> +          << Call->getArg(1)->getSourceRange();
>> >> +      return true;
>> >> +    }
>> >> +
>> >> +    // check the index
>> >> +    const Expr *Arg2 = Call->getArg(2);
>> >> +    if (!Arg2->getType()->isIntegerType() &&
>> >> +        !Arg2->getType()->isUnsignedIntegerType()) {
>> >> +      S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_invalid_arg)
>> >> +          << getFunctionName(Call) << S.Context.UnsignedIntTy
>> >> +          << Arg2->getSourceRange();
>> >> +      return true;
>> >> +    }
>> >> +
>> >> +    // check packet type T
>> >> +    if (checkOpenCLPipePacketType(S, Call, 3))
>> >> +      return true;
>> >> +  } break;
>> >> +  default:
>> >> +    S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num)
>> >> +        << getFunctionName(Call) << Call->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +
>> >> +  return false;
>> >> +}
>> >> +
>> >> +// \brief Performs a semantic analysis on the {work_group_/sub_group_
>> >> +//        /_}reserve_{read/write}_pipe
>> >> +// \param S Reference to the semantic analyzer.
>> >> +// \param Call The call to the builtin function to be analyzed.
>> >> +// \return True if a semantic error was found, false otherwise.
>> >> +static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) {
>> >> +  if (checkArgCount(S, Call, 2))
>> >> +    return true;
>> >> +
>> >> +  if (checkOpenCLPipeArg(S, Call))
>> >> +    return true;
>> >> +
>> >> +  // check the reserve size
>> >> +  if (!Call->getArg(1)->getType()->isIntegerType() &&
>> >> +      !Call->getArg(1)->getType()->isUnsignedIntegerType()) {
>> >> +    S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_invalid_arg)
>> >> +        << getFunctionName(Call) << S.Context.UnsignedIntTy
>> >> +        << Call->getArg(1)->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +
>> >> +  return false;
>> >> +}
>> >> +
>> >> +// \brief Performs a semantic analysis on {work_group_/sub_group_
>> >> +//        /_}commit_{read/write}_pipe
>> >> +// \param S Reference to the semantic analyzer.
>> >> +// \param Call The call to the builtin function to be analyzed.
>> >> +// \return True if a semantic error was found, false otherwise.
>> >> +static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {
>> >> +  if (checkArgCount(S, Call, 2))
>> >> +    return true;
>> >> +
>> >> +  if (checkOpenCLPipeArg(S, Call))
>> >> +    return true;
>> >> +
>> >> +  // check reserve_id_t
>> >> +  if (!Call->getArg(1)->getType()->isReserveIDT()) {
>> >> +    S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_invalid_arg)
>> >> +        << getFunctionName(Call) << S.Context.OCLReserveIDTy
>> >> +        << Call->getArg(1)->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +
>> >> +  return false;
>> >> +}
>> >> +
>> >> +// \brief Performs a semantic analysis on the call to built-in Pipe
>> >> +//        Query Functions.
>> >> +// \param S Reference to the semantic analyzer.
>> >> +// \param Call The call to the builtin function to be analyzed.
>> >> +// \return True if a semantic error was found, false otherwise.
>> >> +static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
>> >> +  if (checkArgCount(S, Call, 1))
>> >> +    return true;
>> >> +
>> >> +  if (!Call->getArg(0)->getType()->isPipeType()) {
>> >> +    S.Diag(Call->getLocStart(),
>> >> diag::err_opencl_builtin_pipe_first_arg)
>> >> +        << getFunctionName(Call) << Call->getArg(0)->getSourceRange();
>> >> +    return true;
>> >> +  }
>> >> +
>> >> +  return false;
>> >> +}
>> >> +
>> >>  ExprResult
>> >>  Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned
>> >> BuiltinID,
>> >>                                 CallExpr *TheCall) { @@ -563,6
>> >> +749,40 @@ Sema::CheckBuiltinFunctionCall(FunctionD
>> >>
>> >>      TheCall->setType(Context.VoidPtrTy);
>> >>      break;
>> >> +  case Builtin::BIread_pipe:
>> >> +  case Builtin::BIwrite_pipe:
>> >> +    // Since those two functions are declared with var args, we need a
>> >> semantic
>> >> +    // check for the argument.
>> >> +    if (SemaBuiltinRWPipe(*this, TheCall))
>> >> +      return ExprError();
>> >> +    break;
>> >> +  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:
>> >> +    if (SemaBuiltinReserveRWPipe(*this, TheCall))
>> >> +      return ExprError();
>> >> +    // Since return type of reserve_read/write_pipe built-in function
>> >> is
>> >> +    // reserve_id_t, which is not defined in the builtin def file , we
>> >> used int
>> >> +    // as return type and need to override the return type of these
>> >> functions.
>> >> +    TheCall->setType(Context.OCLReserveIDTy);
>> >> +    break;
>> >> +  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:
>> >> +    if (SemaBuiltinCommitRWPipe(*this, TheCall))
>> >> +      return ExprError();
>> >> +    break;
>> >> +  case Builtin::BIget_pipe_num_packets:
>> >> +  case Builtin::BIget_pipe_max_packets:
>> >> +    if (SemaBuiltinPipePackets(*this, TheCall))
>> >> +      return ExprError();
>> >> +    break;
>> >>
>> >>    }
>> >>
>> >>
>> >> Added: cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/pipe
>> >> _builtin.cl?rev=258782&view=auto
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl (added)
>> >> +++ cfe/trunk/test/CodeGenOpenCL/pipe_builtin.cl Mon Jan 25 22:03:48
>> >> +++ 2016
>> >> @@ -0,0 +1,61 @@
>> >> +// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck
>> >> +%s
>> >> +
>> >> +// CHECK: %opencl.pipe_t = type opaque // CHECK:
>> >> +%opencl.reserve_id_t = type opaque
>> >> +
>> >> +void test1(read_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8*
>> >> +%{{.*}})
>> >> +  read_pipe(p, ptr);
>> >> +  // CHECK: call %opencl.reserve_id_t*
>> >> + at __reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> >> +  reserve_id_t rid = reserve_read_pipe(p, 2);
>> >> +  // CHECK: call i32 @__read_pipe_4(%opencl.pipe_t* %{{.*}},
>> >> +%opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}})
>> >> +  read_pipe(p, rid, 2, ptr);
>> >> +  // CHECK: call void @__commit_read_pipe(%opencl.pipe_t* %{{.*}},
>> >> +%opencl.reserve_id_t* %{{.*}})
>> >> +  commit_read_pipe(p, rid);
>> >> +}
>> >> +
>> >> +void test2(write_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call i32 @__write_pipe_2(%opencl.pipe_t* %{{.*}}, i8*
>> >> +%{{.*}})
>> >> +  write_pipe(p, ptr);
>> >> +  // CHECK: call %opencl.reserve_id_t*
>> >> + at __reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> >> +  reserve_id_t rid = reserve_write_pipe(p, 2);
>> >> +  // CHECK: call i32 @__write_pipe_4(%opencl.pipe_t* %{{.*}},
>> >> +%opencl.reserve_id_t* %{{.*}}, i32 {{.*}}, i8* %{{.*}})
>> >> +  write_pipe(p, rid, 2, ptr);
>> >> +  // CHECK: call void @__commit_write_pipe(%opencl.pipe_t* %{{.*}},
>> >> +%opencl.reserve_id_t* %{{.*}})
>> >> +  commit_write_pipe(p, rid);
>> >> +}
>> >> +
>> >> +void test3(read_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call %opencl.reserve_id_t*
>> >> + at __work_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> >> +  reserve_id_t rid = work_group_reserve_read_pipe(p, 2);
>> >> +  // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_t*
>> >> +%{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> >> +  work_group_commit_read_pipe(p, rid); }
>> >> +
>> >> +void test4(write_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call %opencl.reserve_id_t*
>> >> + at __work_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32
>> >> +{{.*}})
>> >> +  reserve_id_t rid = work_group_reserve_write_pipe(p, 2);
>> >> +  // CHECK: call void
>> >> + at __work_group_commit_write_pipe(%opencl.pipe_t* %{{.*}},
>> >> +%opencl.reserve_id_t* %{{.*}})
>> >> +  work_group_commit_write_pipe(p, rid); }
>> >> +
>> >> +void test5(read_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call %opencl.reserve_id_t*
>> >> + at __sub_group_reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> >> +  reserve_id_t rid = sub_group_reserve_read_pipe(p, 2);
>> >> +  // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_t*
>> >> +%{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> >> +  sub_group_commit_read_pipe(p, rid); }
>> >> +
>> >> +void test6(write_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call %opencl.reserve_id_t*
>> >> + at __sub_group_reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
>> >> +  reserve_id_t rid = sub_group_reserve_write_pipe(p, 2);
>> >> +  // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_t*
>> >> +%{{.*}}, %opencl.reserve_id_t* %{{.*}})
>> >> +  sub_group_commit_write_pipe(p, rid); }
>> >> +
>> >> +void test7(write_only pipe int p, global int *ptr) {
>> >> +  // CHECK: call i32 @__get_pipe_num_packets(%opencl.pipe_t*
>> >> +%{{.*}})
>> >> +  *ptr = get_pipe_num_packets(p);
>> >> +  // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_t*
>> >> +%{{.*}})
>> >> +  *ptr = get_pipe_max_packets(p);
>> >> +}
>> >>
>> >> Added: cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl
>> >> URL:
>> >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid
>> >> -pipe-builtin-cl2.0.cl?rev=258782&view=auto
>> >> =====================================================================
>> >> =========
>> >> --- cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl (added)
>> >> +++ cfe/trunk/test/SemaOpenCL/invalid-pipe-builtin-cl2.0.cl Mon Jan
>> >> +++ 25 22:03:48 2016
>> >> @@ -0,0 +1,55 @@
>> >> +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
>> >> +
>> >> +void test1(read_only pipe int p, global int* ptr){
>> >> +  int tmp;
>> >> +  reserve_id_t rid;
>> >> +
>> >> +  // read/write_pipe
>> >> +  read_pipe(tmp, p);    // expected-error {{first argument to
>> >> read_pipe must be a pipe type}}
>> >> +  read_pipe(p);   // expected-error {{invalid number of arguments to
>> >> function: read_pipe}}
>> >> +  read_pipe(p, tmp, tmp, ptr);   // expected-error {{invalid argument
>> >> type to function read_pipe (expecting 'reserve_id_t')}}
>> >> +  read_pipe(p, rid, rid, ptr);   // expected-error {{invalid argument
>> >> type to function read_pipe (expecting 'unsigned int')}}
>> >> +  read_pipe(p, tmp);   // expected-error {{invalid argument type to
>> >> function read_pipe (expecting 'int *')}}
>> >> +  write_pipe(p, ptr);    // expected-error {{invalid pipe access
>> >> modifier (expecting write_only)}}
>> >> +  write_pipe(p, rid, tmp, ptr);    // expected-error {{invalid pipe
>> >> access modifier (expecting write_only)}}
>> >> +
>> >> +  // reserve_read/write_pipe
>> >> +  reserve_read_pipe(p, ptr);    // expected-error{{invalid argument
>> >> type to function reserve_read_pipe (expecting 'unsigned int')}}
>> >> +  work_group_reserve_read_pipe(tmp, tmp);    // expected-error{{first
>> >> argument to work_group_reserve_read_pipe must be a pipe type}}
>> >> +  sub_group_reserve_write_pipe(p, tmp);    // expected-error{{invalid
>> >> pipe access modifier (expecting write_only)}}
>> >> +
>> >> +  // commit_read/write_pipe
>> >> +  commit_read_pipe(tmp, rid);    // expected-error{{first argument to
>> >> commit_read_pipe must be a pipe type}}
>> >> +  work_group_commit_read_pipe(p, tmp);    // expected-error{{invalid
>> >> argument type to function work_group_commit_read_pipe (expecting
>> >> 'reserve_id_t')}}
>> >> +  sub_group_commit_write_pipe(p, tmp);    // expected-error{{nvalid
>> >> pipe access modifier (expecting write_only)}}
>> >> +}
>> >> +
>> >> +void test2(write_only pipe int p, global int* ptr){
>> >> +  int tmp;
>> >> +  reserve_id_t rid;
>> >> +
>> >> +  // read/write_pipe
>> >> +  write_pipe(tmp, p);    // expected-error {{first argument to
>> >> write_pipe must be a pipe type}}
>> >> +  write_pipe(p);   // expected-error {{invalid number of arguments to
>> >> function: write_pipe}}
>> >> +  write_pipe(p, tmp, tmp, ptr);   // expected-error {{invalid argument
>> >> type to function write_pipe (expecting 'reserve_id_t')}}
>> >> +  write_pipe(p, rid, rid, ptr);   // expected-error {{invalid argument
>> >> type to function write_pipe (expecting 'unsigned int')}}
>> >> +  write_pipe(p, tmp);   // expected-error {{invalid argument type to
>> >> function write_pipe (expecting 'int *')}}
>> >> +  read_pipe(p, ptr);    // expected-error {{invalid pipe access
>> >> modifier (expecting read_only)}}
>> >> +  read_pipe(p, rid, tmp, ptr);    // expected-error {{invalid pipe
>> >> access modifier (expecting read_only)}}
>> >> +
>> >> +  // reserve_read/write_pipe
>> >> +  reserve_write_pipe(p, ptr);    // expected-error{{invalid argument
>> >> type to function reserve_write_pipe (expecting 'unsigned int')}}
>> >> +  work_group_reserve_write_pipe(tmp, tmp);    // expected-error{{first
>> >> argument to work_group_reserve_write_pipe must be a pipe type}}
>> >> +  sub_group_reserve_read_pipe(p, tmp);    // expected-error{{invalid
>> >> pipe access modifier (expecting read_only)}}
>> >> +
>> >> +  // commit_read/write_pipe
>> >> +  commit_write_pipe(tmp, rid);    // expected-error{{first argument to
>> >> commit_write_pipe must be a pipe type}}
>> >> +  work_group_commit_write_pipe(p, tmp);    // expected-error{{invalid
>> >> argument type to function work_group_commit_write_pipe (expecting
>> >> 'reserve_id_t')}}
>> >> +  sub_group_commit_read_pipe(p, tmp);    // expected-error{{nvalid
>> >> pipe access modifier (expecting read_only)}}
>> >> +}
>> >> +
>> >> +void test3(){
>> >> +  int tmp;
>> >> +  get_pipe_num_packets(tmp);    // expected-error {{first argument to
>> >> get_pipe_num_packets must be a pipe type}}
>> >> +  get_pipe_max_packets(tmp);    // expected-error {{first argument to
>> >> get_pipe_max_packets must be a pipe type}}
>> >> +}
>> >>
>> >>
>> >> _______________________________________________
>> >> cfe-commits mailing list
>> >> cfe-commits at lists.llvm.org
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>


More information about the cfe-commits mailing list