Home | History | Annotate | Download | only in SPIRV
      1 //===- OCLUtil.cpp - OCL Utilities ----------------------------------------===//
      2 //
      3 //                     The LLVM/SPIRV Translator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
      9 //
     10 // Permission is hereby granted, free of charge, to any person obtaining a
     11 // copy of this software and associated documentation files (the "Software"),
     12 // to deal with the Software without restriction, including without limitation
     13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
     14 // and/or sell copies of the Software, and to permit persons to whom the
     15 // Software is furnished to do so, subject to the following conditions:
     16 //
     17 // Redistributions of source code must retain the above copyright notice,
     18 // this list of conditions and the following disclaimers.
     19 // Redistributions in binary form must reproduce the above copyright notice,
     20 // this list of conditions and the following disclaimers in the documentation
     21 // and/or other materials provided with the distribution.
     22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its
     23 // contributors may be used to endorse or promote products derived from this
     24 // Software without specific prior written permission.
     25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
     31 // THE SOFTWARE.
     32 //
     33 //===----------------------------------------------------------------------===//
     34 //
     35 // This file implements OCL utility functions.
     36 //
     37 //===----------------------------------------------------------------------===//
     38 #define DEBUG_TYPE "oclutil"
     39 
     40 #include "SPIRVInternal.h"
     41 #include "OCLUtil.h"
     42 #include "SPIRVEntry.h"
     43 #include "SPIRVFunction.h"
     44 #include "SPIRVInstruction.h"
     45 #include "llvm/ADT/StringSwitch.h"
     46 #include "llvm/IR/InstVisitor.h"
     47 #include "llvm/IR/Instructions.h"
     48 #include "llvm/IR/IRBuilder.h"
     49 #include "llvm/IR/Verifier.h"
     50 #include "llvm/Pass.h"
     51 #include "llvm/PassSupport.h"
     52 #include "llvm/Support/CommandLine.h"
     53 #include "llvm/Support/Debug.h"
     54 #include "llvm/Support/raw_ostream.h"
     55 
     56 using namespace llvm;
     57 using namespace SPIRV;
     58 
     59 namespace OCLUtil {
     60 
     61 
     62 #ifndef SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
     63   #define SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE SPIRAS_Private
     64 #endif
     65 
     66 #ifndef SPIRV_QUEUE_T_ADDR_SPACE
     67   #define SPIRV_QUEUE_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
     68 #endif
     69 
     70 #ifndef SPIRV_EVENT_T_ADDR_SPACE
     71   #define SPIRV_EVENT_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
     72 #endif
     73 
     74 #ifndef SPIRV_CLK_EVENT_T_ADDR_SPACE
     75   #define SPIRV_CLK_EVENT_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
     76 #endif
     77 
     78 #ifndef SPIRV_RESERVE_ID_T_ADDR_SPACE
     79   #define SPIRV_RESERVE_ID_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
     80 #endif
     81 // Excerpt from SPIR 2.0 spec.:
     82 //   Pipe objects are represented using pointers to the opaque %opencl.pipe LLVM structure type
     83 //   which reside in the global address space.
     84 #ifndef SPIRV_PIPE_ADDR_SPACE
     85   #define SPIRV_PIPE_ADDR_SPACE SPIRAS_Global
     86 #endif
     87 // Excerpt from SPIR 2.0 spec.:
     88 //   Note: Images data types reside in global memory and hence should be marked as such in the
     89 //   "kernel arg addr space" metadata.
     90 #ifndef SPIRV_IMAGE_ADDR_SPACE
     91   #define SPIRV_IMAGE_ADDR_SPACE SPIRAS_Global
     92 #endif
     93 
     94 ///////////////////////////////////////////////////////////////////////////////
     95 //
     96 // Functions for getting builtin call info
     97 //
     98 ///////////////////////////////////////////////////////////////////////////////
     99 AtomicWorkItemFenceLiterals getAtomicWorkItemFenceLiterals(CallInst* CI) {
    100   return std::make_tuple(getArgAsInt(CI, 0),
    101     static_cast<OCLMemOrderKind>(getArgAsInt(CI, 1)),
    102     static_cast<OCLScopeKind>(getArgAsInt(CI, 2)));
    103 }
    104 
    105 size_t getAtomicBuiltinNumMemoryOrderArgs(StringRef Name) {
    106   if (Name.startswith("atomic_compare_exchange"))
    107     return 2;
    108   return 1;
    109 }
    110 
    111 BarrierLiterals getBarrierLiterals(CallInst* CI){
    112   auto N = CI->getNumArgOperands();
    113   assert (N == 1 || N == 2);
    114 
    115   std::string DemangledName;
    116   if (!oclIsBuiltin(CI->getCalledFunction()->getName(), &DemangledName)) {
    117     assert(0 && "call must a builtin (work_group_barrier or sub_group_barrier)");
    118   }
    119 
    120   OCLScopeKind scope = OCLMS_work_group;
    121   if (DemangledName == kOCLBuiltinName::SubGroupBarrier) {
    122     scope = OCLMS_sub_group;
    123   }
    124 
    125   return std::make_tuple(getArgAsInt(CI, 0),
    126     N == 1 ? OCLMS_work_group : static_cast<OCLScopeKind>(getArgAsInt(CI, 1)),
    127     scope);
    128 }
    129 
    130 unsigned
    131 getExtOp(StringRef OrigName, const std::string &GivenDemangledName) {
    132   std::string DemangledName = GivenDemangledName;
    133   if (!oclIsBuiltin(OrigName, DemangledName.empty() ? &DemangledName : nullptr))
    134     return ~0U;
    135   DEBUG(dbgs() << "getExtOp: demangled name: " << DemangledName << '\n');
    136   OCLExtOpKind EOC;
    137   bool Found = OCLExtOpMap::rfind(DemangledName, &EOC);
    138   if (!Found) {
    139     std::string Prefix;
    140     switch (LastFuncParamType(OrigName)) {
    141     case ParamType::UNSIGNED:
    142       Prefix = "u_";
    143       break;
    144     case ParamType::SIGNED:
    145       Prefix = "s_";
    146       break;
    147     case ParamType::FLOAT:
    148       Prefix = "f";
    149       break;
    150     default:
    151       llvm_unreachable("unknown mangling!");
    152     }
    153     Found = OCLExtOpMap::rfind(Prefix + DemangledName, &EOC);
    154   }
    155   if (Found)
    156     return EOC;
    157   else
    158     return ~0U;
    159 }
    160 
    161 std::unique_ptr<SPIRVEntry>
    162 getSPIRVInst(const OCLBuiltinTransInfo &Info) {
    163   Op OC = OpNop;
    164   unsigned ExtOp = ~0U;
    165   SPIRVEntry *Entry = nullptr;
    166   if (OCLSPIRVBuiltinMap::find(Info.UniqName, &OC))
    167     Entry = SPIRVEntry::create(OC);
    168   else if ((ExtOp = getExtOp(Info.MangledName, Info.UniqName)) != ~0U)
    169     Entry = static_cast<SPIRVEntry*>(
    170         SPIRVEntry::create_unique(SPIRVEIS_OpenCL, ExtOp).get());
    171   return std::unique_ptr<SPIRVEntry>(Entry);
    172 }
    173 
    174 ///////////////////////////////////////////////////////////////////////////////
    175 //
    176 // Functions for getting module info
    177 //
    178 ///////////////////////////////////////////////////////////////////////////////
    179 
    180 unsigned
    181 encodeOCLVer(unsigned short Major,
    182     unsigned char Minor, unsigned char Rev) {
    183   return (Major * 100 + Minor) * 1000 + Rev;
    184 }
    185 
    186 std::tuple<unsigned short, unsigned char, unsigned char>
    187 decodeOCLVer(unsigned Ver) {
    188   unsigned short Major = Ver / 100000;
    189   unsigned char Minor = (Ver % 100000) / 1000;
    190   unsigned char Rev = Ver % 1000;
    191   return std::make_tuple(Major, Minor, Rev);
    192 }
    193 
    194 unsigned getOCLVersion(Module *M, bool AllowMulti) {
    195   NamedMDNode *NamedMD = M->getNamedMetadata(kSPIR2MD::OCLVer);
    196   if (!NamedMD)
    197     return 0;
    198   assert (NamedMD->getNumOperands() > 0 && "Invalid SPIR");
    199   if (!AllowMulti && NamedMD->getNumOperands() != 1)
    200     report_fatal_error("Multiple OCL version metadata not allowed");
    201 
    202   // If the module was linked with another module, there may be multiple
    203   // operands.
    204   auto getVer = [=](unsigned I) {
    205     auto MD = NamedMD->getOperand(I);
    206     return std::make_pair(getMDOperandAsInt(MD, 0), getMDOperandAsInt(MD, 1));
    207   };
    208   auto Ver = getVer(0);
    209   for (unsigned I = 1, E = NamedMD->getNumOperands(); I != E; ++I)
    210     if (Ver != getVer(I))
    211       report_fatal_error("OCL version mismatch");
    212 
    213   return encodeOCLVer(Ver.first, Ver.second, 0);
    214 }
    215 
    216 void
    217 decodeMDNode(MDNode* N, unsigned& X, unsigned& Y, unsigned& Z) {
    218   if (N == NULL)
    219     return;
    220   X = getMDOperandAsInt(N, 1);
    221   Y = getMDOperandAsInt(N, 2);
    222   Z = getMDOperandAsInt(N, 3);
    223 }
    224 
    225 /// Encode LLVM type by SPIR-V execution mode VecTypeHint
    226 unsigned
    227 encodeVecTypeHint(Type *Ty){
    228   if (Ty->isHalfTy())
    229     return 4;
    230   if (Ty->isFloatTy())
    231     return 5;
    232   if (Ty->isDoubleTy())
    233     return 6;
    234   if (IntegerType* intTy = dyn_cast<IntegerType>(Ty)) {
    235     switch (intTy->getIntegerBitWidth()) {
    236     case 8:
    237       return 0;
    238     case 16:
    239       return 1;
    240     case 32:
    241       return 2;
    242     case 64:
    243       return 3;
    244     default:
    245       llvm_unreachable("invalid integer type");
    246     }
    247   }
    248   if (VectorType* VecTy = dyn_cast<VectorType>(Ty)) {
    249     Type* EleTy = VecTy->getElementType();
    250     unsigned Size = VecTy->getVectorNumElements();
    251     return Size << 16 | encodeVecTypeHint(EleTy);
    252   }
    253   llvm_unreachable("invalid type");
    254 }
    255 
    256 Type *
    257 decodeVecTypeHint(LLVMContext &C, unsigned code) {
    258   unsigned VecWidth = code >> 16;
    259   unsigned Scalar = code & 0xFFFF;
    260   Type *ST = nullptr;
    261   switch(Scalar) {
    262   case 0:
    263   case 1:
    264   case 2:
    265   case 3:
    266     ST = IntegerType::get(C, 1 << (3 + Scalar));
    267     break;
    268   case 4:
    269     ST = Type::getHalfTy(C);
    270     break;
    271   case 5:
    272     ST = Type::getFloatTy(C);
    273     break;
    274   case 6:
    275     ST = Type::getDoubleTy(C);
    276     break;
    277   default:
    278     llvm_unreachable("Invalid vec type hint");
    279   }
    280   if (VecWidth < 1)
    281     return ST;
    282   return VectorType::get(ST, VecWidth);
    283 }
    284 
    285 unsigned
    286 transVecTypeHint(MDNode* Node) {
    287   return encodeVecTypeHint(getMDOperandAsType(Node, 1));
    288 }
    289 
    290 SPIRAddressSpace
    291 getOCLOpaqueTypeAddrSpace(Op OpCode) {
    292   switch (OpCode) {
    293   case OpTypeQueue:
    294     return SPIRV_QUEUE_T_ADDR_SPACE;
    295   case OpTypeEvent:
    296     return SPIRV_EVENT_T_ADDR_SPACE;
    297   case OpTypeDeviceEvent:
    298     return SPIRV_CLK_EVENT_T_ADDR_SPACE;
    299   case OpTypeReserveId:
    300     return SPIRV_RESERVE_ID_T_ADDR_SPACE;
    301   case OpTypePipe:
    302   case OpTypePipeStorage:
    303     return SPIRV_PIPE_ADDR_SPACE;
    304   case OpTypeImage:
    305   case OpTypeSampledImage:
    306     return SPIRV_IMAGE_ADDR_SPACE;
    307   default:
    308     assert(false && "No address space is determined for some OCL type");
    309     return SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE;
    310   }
    311 }
    312 
    313 static SPIR::TypeAttributeEnum
    314 mapAddrSpaceEnums(SPIRAddressSpace addrspace)
    315 {
    316   switch (addrspace) {
    317   case SPIRAS_Private:
    318     return SPIR::ATTR_PRIVATE;
    319   case SPIRAS_Global:
    320     return SPIR::ATTR_GLOBAL;
    321   case SPIRAS_Constant:
    322     return SPIR::ATTR_CONSTANT;
    323   case SPIRAS_Local:
    324     return SPIR::ATTR_LOCAL;
    325   case SPIRAS_Generic:
    326     return SPIR::ATTR_GENERIC;
    327   default:
    328     llvm_unreachable("Invalid addrspace enum member");
    329   }
    330 }
    331 
    332 SPIR::TypeAttributeEnum
    333 getOCLOpaqueTypeAddrSpace(SPIR::TypePrimitiveEnum prim) {
    334   switch (prim) {
    335   case SPIR::PRIMITIVE_QUEUE_T:
    336     return mapAddrSpaceEnums(SPIRV_QUEUE_T_ADDR_SPACE);
    337   case SPIR::PRIMITIVE_EVENT_T:
    338     return mapAddrSpaceEnums(SPIRV_EVENT_T_ADDR_SPACE);
    339   case SPIR::PRIMITIVE_CLK_EVENT_T:
    340     return mapAddrSpaceEnums(SPIRV_CLK_EVENT_T_ADDR_SPACE);
    341   case SPIR::PRIMITIVE_RESERVE_ID_T:
    342     return mapAddrSpaceEnums(SPIRV_RESERVE_ID_T_ADDR_SPACE);
    343   case SPIR::PRIMITIVE_PIPE_T:
    344     return mapAddrSpaceEnums(SPIRV_PIPE_ADDR_SPACE);
    345   case SPIR::PRIMITIVE_IMAGE_1D_T:
    346   case SPIR::PRIMITIVE_IMAGE_1D_ARRAY_T:
    347   case SPIR::PRIMITIVE_IMAGE_1D_BUFFER_T:
    348   case SPIR::PRIMITIVE_IMAGE_2D_T:
    349   case SPIR::PRIMITIVE_IMAGE_2D_ARRAY_T:
    350   case SPIR::PRIMITIVE_IMAGE_3D_T:
    351   case SPIR::PRIMITIVE_IMAGE_2D_MSAA_T:
    352   case SPIR::PRIMITIVE_IMAGE_2D_ARRAY_MSAA_T:
    353   case SPIR::PRIMITIVE_IMAGE_2D_MSAA_DEPTH_T:
    354   case SPIR::PRIMITIVE_IMAGE_2D_ARRAY_MSAA_DEPTH_T:
    355   case SPIR::PRIMITIVE_IMAGE_2D_DEPTH_T:
    356   case SPIR::PRIMITIVE_IMAGE_2D_ARRAY_DEPTH_T:
    357     return mapAddrSpaceEnums(SPIRV_IMAGE_ADDR_SPACE);
    358   default:
    359     llvm_unreachable("No address space is determined for a SPIR primitive");
    360   }
    361 }
    362 
    363 // Fetch type of invoke function passed to device execution built-ins
    364 static FunctionType *
    365 getBlockInvokeTy(Function * F, unsigned blockIdx) {
    366     auto params = F->getFunctionType()->params();
    367     PointerType * funcPtr = cast<PointerType>(params[blockIdx]);
    368     return cast<FunctionType>(funcPtr->getElementType());
    369 }
    370 
    371 class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
    372 public:
    373   OCLBuiltinFuncMangleInfo(Function * f) : F(f) {}
    374   void init(const std::string &UniqName) {
    375   UnmangledName = UniqName;
    376   size_t Pos = std::string::npos;
    377 
    378   if (UnmangledName.find("async_work_group") == 0) {
    379     addUnsignedArg(-1);
    380     setArgAttr(1, SPIR::ATTR_CONST);
    381   } else if (UnmangledName.find("write_imageui") == 0)
    382       addUnsignedArg(2);
    383   else if (UnmangledName == "prefetch") {
    384     addUnsignedArg(1);
    385     setArgAttr(0, SPIR::ATTR_CONST);
    386   } else if(UnmangledName == "get_kernel_work_group_size" ||
    387             UnmangledName == "get_kernel_preferred_work_group_size_multiple") {
    388     assert(F && "lack of necessary information");
    389     const size_t blockArgIdx = 0;
    390     FunctionType * InvokeTy = getBlockInvokeTy(F, blockArgIdx);
    391     if(InvokeTy->getNumParams() > 1) setLocalArgBlock(blockArgIdx);
    392   } else if (UnmangledName == "enqueue_kernel") {
    393     assert(F && "lack of necessary information");
    394     setEnumArg(1, SPIR::PRIMITIVE_KERNEL_ENQUEUE_FLAGS_T);
    395     addUnsignedArg(3);
    396     setArgAttr(4, SPIR::ATTR_CONST);
    397     // If there are arguments other then block context then these are pointers
    398     // to local memory so this built-in must be mangled accordingly.
    399     const size_t blockArgIdx = 6;
    400     FunctionType * InvokeTy = getBlockInvokeTy(F, blockArgIdx);
    401     if(InvokeTy->getNumParams() > 1) {
    402        setLocalArgBlock(blockArgIdx);
    403        addUnsignedArg(blockArgIdx + 1);
    404        setVarArg(blockArgIdx + 2);
    405     }
    406   } else if (UnmangledName.find("get_") == 0 ||
    407       UnmangledName == "nan" ||
    408       UnmangledName == "mem_fence" ||
    409       UnmangledName.find("shuffle") == 0){
    410     addUnsignedArg(-1);
    411     if (UnmangledName.find(kOCLBuiltinName::GetFence) == 0){
    412       setArgAttr(0, SPIR::ATTR_CONST);
    413       addVoidPtrArg(0);
    414     }
    415   } else if (UnmangledName.find("barrier") == 0 ||
    416              UnmangledName.find("work_group_barrier") == 0 ||
    417              UnmangledName.find("sub_group_barrier") == 0) {
    418     addUnsignedArg(0);
    419   } else if (UnmangledName.find("atomic_work_item_fence") == 0) {
    420     addUnsignedArg(0);
    421   } else if (UnmangledName.find("atomic") == 0) {
    422     setArgAttr(0, SPIR::ATTR_VOLATILE);
    423     if (UnmangledName.find("atomic_umax") == 0 ||
    424         UnmangledName.find("atomic_umin") == 0) {
    425       addUnsignedArg(0);
    426       addUnsignedArg(1);
    427       UnmangledName.erase(7, 1);
    428     } else if (UnmangledName.find("atomic_fetch_umin") == 0 ||
    429                UnmangledName.find("atomic_fetch_umax") == 0) {
    430       addUnsignedArg(0);
    431       addUnsignedArg(1);
    432       UnmangledName.erase(13, 1);
    433     }
    434     // Don't set atomic property to the first argument of 1.2 atomic built-ins.
    435     if(UnmangledName.find("atomic_add")  != 0 && UnmangledName.find("atomic_sub") != 0 &&
    436        UnmangledName.find("atomic_xchg") != 0 && UnmangledName.find("atomic_inc") != 0 &&
    437        UnmangledName.find("atomic_dec")  != 0 && UnmangledName.find("atomic_cmpxchg") != 0 &&
    438        UnmangledName.find("atomic_min")  != 0 && UnmangledName.find("atomic_max") != 0 &&
    439        UnmangledName.find("atomic_and")  != 0 && UnmangledName.find("atomic_or") != 0 &&
    440        UnmangledName.find("atomic_xor")  != 0 && UnmangledName.find("atom_") != 0) {
    441       addAtomicArg(0);
    442     }
    443 
    444   } else if (UnmangledName.find("uconvert_") == 0) {
    445     addUnsignedArg(0);
    446     UnmangledName.erase(0, 1);
    447   } else if (UnmangledName.find("s_") == 0) {
    448     UnmangledName.erase(0, 2);
    449   } else if (UnmangledName.find("u_") == 0) {
    450     addUnsignedArg(-1);
    451     UnmangledName.erase(0, 2);
    452   } else if (UnmangledName == "fclamp") {
    453     UnmangledName.erase(0, 1);
    454   } else if (UnmangledName == "read_pipe" || UnmangledName == "write_pipe") {
    455     assert(F && "lack of necessary information");
    456     // handle [read|write]pipe builtins (plus two i32 literal args
    457     // required by SPIR 2.0 provisional specification):
    458     if (F->getArgumentList().size() == 6) {
    459       // with 4 arguments (plus two i32 literals):
    460       // int read_pipe (read_only pipe gentype p, reserve_id_t reserve_id, uint index, gentype *ptr)
    461       // int write_pipe (write_only pipe gentype p, reserve_id_t reserve_id, uint index, const gentype *ptr)
    462       addUnsignedArg(2);
    463       addVoidPtrArg(3);
    464       addUnsignedArg(4);
    465       addUnsignedArg(5);
    466     } else if (F->getArgumentList().size() == 4) {
    467       // with 2 arguments (plus two i32 literals):
    468       // int read_pipe (read_only pipe gentype p, gentype *ptr)
    469       // int write_pipe (write_only pipe gentype p, const gentype *ptr)
    470       addVoidPtrArg(1);
    471       addUnsignedArg(2);
    472       addUnsignedArg(3);
    473     } else {
    474       llvm_unreachable("read/write pipe builtin with unexpected number of arguments");
    475     }
    476   } else if (UnmangledName.find("reserve_read_pipe") != std::string::npos ||
    477              UnmangledName.find("reserve_write_pipe") != std::string::npos) {
    478     // process [|work_group|sub_group]reserve[read|write]pipe builtins
    479     addUnsignedArg(1);
    480     addUnsignedArg(2);
    481     addUnsignedArg(3);
    482   } else if (UnmangledName.find("commit_read_pipe") != std::string::npos ||
    483              UnmangledName.find("commit_write_pipe") != std::string::npos) {
    484     // process [|work_group|sub_group]commit[read|write]pipe builtins
    485     addUnsignedArg(2);
    486     addUnsignedArg(3);
    487   } else if (UnmangledName == "capture_event_profiling_info") {
    488     addVoidPtrArg(2);
    489     setEnumArg(1, SPIR::PRIMITIVE_CLK_PROFILING_INFO);
    490   } else if (UnmangledName == "enqueue_marker") {
    491     setArgAttr(2, SPIR::ATTR_CONST);
    492     addUnsignedArg(1);
    493   } else if (UnmangledName.find("vload") == 0) {
    494     addUnsignedArg(0);
    495     setArgAttr(1, SPIR::ATTR_CONST);
    496   } else if (UnmangledName.find("vstore") == 0 ){
    497     addUnsignedArg(1);
    498   } else if (UnmangledName.find("ndrange_") == 0) {
    499     addUnsignedArg(-1);
    500     if (UnmangledName[8] == '2' || UnmangledName[8] == '3') {
    501       setArgAttr(-1, SPIR::ATTR_CONST);
    502     }
    503   } else if ((Pos = UnmangledName.find("umax")) != std::string::npos ||
    504              (Pos = UnmangledName.find("umin")) != std::string::npos) {
    505     addUnsignedArg(-1);
    506     UnmangledName.erase(Pos, 1);
    507   } else if (UnmangledName.find("broadcast") != std::string::npos)
    508     addUnsignedArg(-1);
    509   else if (UnmangledName.find(kOCLBuiltinName::SampledReadImage) == 0) {
    510     UnmangledName.erase(0, strlen(kOCLBuiltinName::Sampled));
    511     addSamplerArg(1);
    512   }
    513 }
    514 // Auxiliarry information, it is expected what it is relevant at the moment
    515 // the init method is called.
    516 Function * F; // SPIRV decorated function
    517 };
    518 
    519 CallInst *
    520 mutateCallInstOCL(Module *M, CallInst *CI,
    521     std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate,
    522     AttributeSet *Attrs) {
    523   OCLBuiltinFuncMangleInfo BtnInfo(CI->getCalledFunction());
    524   return mutateCallInst(M, CI, ArgMutate, &BtnInfo, Attrs);
    525 }
    526 
    527 Instruction *
    528 mutateCallInstOCL(Module *M, CallInst *CI,
    529     std::function<std::string (CallInst *, std::vector<Value *> &,
    530         Type *&RetTy)> ArgMutate,
    531     std::function<Instruction *(CallInst *)> RetMutate,
    532     AttributeSet *Attrs) {
    533   OCLBuiltinFuncMangleInfo BtnInfo(CI->getCalledFunction());
    534   return mutateCallInst(M, CI, ArgMutate, RetMutate, &BtnInfo, Attrs);
    535 }
    536 
    537 void
    538 mutateFunctionOCL(Function *F,
    539     std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate,
    540     AttributeSet *Attrs) {
    541   OCLBuiltinFuncMangleInfo BtnInfo(F);
    542   return mutateFunction(F, ArgMutate, &BtnInfo, Attrs, false);
    543 }
    544 
    545 static std::pair<StringRef, StringRef>
    546 getSrcAndDstElememntTypeName(BitCastInst* BIC) {
    547   if (!BIC)
    548     return std::pair<StringRef, StringRef>("", "");
    549 
    550   Type *SrcTy = BIC->getSrcTy();
    551   Type *DstTy = BIC->getDestTy();
    552   if (SrcTy->isPointerTy())
    553     SrcTy = SrcTy->getPointerElementType();
    554   if (DstTy->isPointerTy())
    555     DstTy = DstTy->getPointerElementType();
    556   auto SrcST = dyn_cast<StructType>(SrcTy);
    557   auto DstST = dyn_cast<StructType>(DstTy);
    558   if (!DstST || !DstST->hasName() || !SrcST || !SrcST->hasName())
    559     return std::pair<StringRef, StringRef>("", "");
    560 
    561   return std::make_pair(SrcST->getName(), DstST->getName());
    562 }
    563 
    564 bool
    565 isSamplerInitializer(Instruction *Inst) {
    566   BitCastInst *BIC = dyn_cast<BitCastInst>(Inst);
    567   auto Names = getSrcAndDstElememntTypeName(BIC);
    568   if (Names.second == getSPIRVTypeName(kSPIRVTypeName::Sampler) &&
    569       Names.first == getSPIRVTypeName(kSPIRVTypeName::ConstantSampler))
    570     return true;
    571 
    572   return false;
    573 }
    574 
    575 bool
    576 isPipeStorageInitializer(Instruction *Inst) {
    577   BitCastInst *BIC = dyn_cast<BitCastInst>(Inst);
    578   auto Names = getSrcAndDstElememntTypeName(BIC);
    579   if (Names.second == getSPIRVTypeName(kSPIRVTypeName::PipeStorage) &&
    580     Names.first == getSPIRVTypeName(kSPIRVTypeName::ConstantPipeStorage))
    581     return true;
    582 
    583   return false;
    584 }
    585 
    586 bool
    587 isSpecialTypeInitializer(Instruction* Inst) {
    588   return isSamplerInitializer(Inst) || isPipeStorageInitializer(Inst);
    589 }
    590 
    591 } // namespace OCLUtil
    592 
    593 void
    594 llvm::MangleOpenCLBuiltin(const std::string &UniqName,
    595     ArrayRef<Type*> ArgTypes, std::string &MangledName) {
    596   OCLUtil::OCLBuiltinFuncMangleInfo BtnInfo(nullptr);
    597   MangledName = SPIRV::mangleBuiltin(UniqName, ArgTypes, &BtnInfo);
    598 }
    599