10e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===- SPIRVToOCL20.cpp - Transform SPIR-V builtins to OCL20 builtins-------===// 291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// The LLVM/SPIRV Translator 491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// This file is distributed under the University of Illinois Open Source 691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// License. See LICENSE.TXT for details. 791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 1091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Permission is hereby granted, free of charge, to any person obtaining a 1191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// copy of this software and associated documentation files (the "Software"), 1291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// to deal with the Software without restriction, including without limitation 1391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// the rights to use, copy, modify, merge, publish, distribute, sublicense, 1491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// and/or sell copies of the Software, and to permit persons to whom the 1591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Software is furnished to do so, subject to the following conditions: 1691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 1791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Redistributions of source code must retain the above copyright notice, 1891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// this list of conditions and the following disclaimers. 1991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Redistributions in binary form must reproduce the above copyright notice, 2091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// this list of conditions and the following disclaimers in the documentation 2191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// and/or other materials provided with the distribution. 2291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Neither the names of Advanced Micro Devices, Inc., nor the names of its 2391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// contributors may be used to endorse or promote products derived from this 2491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// Software without specific prior written permission. 2591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 3091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 3191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// THE SOFTWARE. 3291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 3391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni//===----------------------------------------------------------------------===// 3491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 3591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// This file implements transform SPIR-V builtins to OCL 2.0 builtins. 3691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni// 3791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni//===----------------------------------------------------------------------===// 3891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#define DEBUG_TYPE "spvtocl20" 3991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 4091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "SPIRVInternal.h" 4191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "OCLUtil.h" 4291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/ADT/StringSwitch.h" 4391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/IR/InstVisitor.h" 4491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/IR/Instructions.h" 4591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/IR/IRBuilder.h" 4691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/IR/Verifier.h" 4791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/Pass.h" 4891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/PassSupport.h" 4991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/Support/CommandLine.h" 5091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/Support/Debug.h" 5191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include "llvm/Support/raw_ostream.h" 5291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 5391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni#include <cstring> 5491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 5591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Niusing namespace llvm; 5691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Niusing namespace SPIRV; 5791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Niusing namespace OCLUtil; 5891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 5991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ninamespace SPIRV { 6091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 6191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nistatic cl::opt<std::string> 6291585d9acd75a2bdbfd177bf56c8b9436f442152Yang NiMangledAtomicTypeNamePrefix("spirv-atomic-prefix", 6391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni cl::desc("Mangled atomic type name prefix"), cl::init("U7_Atomic")); 6491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 6591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Niclass SPIRVToOCL20: public ModulePass, 6691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni public InstVisitor<SPIRVToOCL20> { 6791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nipublic: 6891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni SPIRVToOCL20():ModulePass(ID), M(nullptr), Ctx(nullptr) { 6991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni initializeSPIRVToOCL20Pass(*PassRegistry::getPassRegistry()); 7091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 7191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni virtual bool runOnModule(Module &M); 7291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 7391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallInst(CallInst &CI); 7491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 7591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // SPIR-V reader should translate vector casts into OCL built-ins because 7691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // such conversions are not defined neither by OpenCL C/C++ nor 7791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // by SPIR 1.2/2.0 standards. So, it is safer to convert such casts into 7891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // appropriate calls to conversion built-ins defined by the standards. 7991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCastInst(CastInst &CI); 8091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 8191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform __spirv_ImageQuerySize[Lod] into vector of the same lenght 8291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// containing {[get_image_width | get_image_dim], get_image_array_size} 8391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// for all images except image1d_t which is always converted into 8491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// get_image_width returning scalar result. 8591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallSPRIVImageQuerySize(CallInst *CI); 8691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 8791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform __spirv_Atomic* to atomic_*. 8891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// __spirv_Atomic*(atomic_op, scope, sema, ops, ...) => 8991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// atomic_*(atomic_op, ops, ..., order(sema), map(scope)) 9091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC); 9191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 9291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform __spirv_Group* to {work_group|sub_group}_*. 9391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// 9491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Special handling of work_group_broadcast. 9591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// __spirv_GroupBroadcast(a, vec3(x, y, z)) 9691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// => 9791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// work_group_broadcast(a, x, y, z) 9891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// 9991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform OpenCL group builtin function names from group_ 10091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// to workgroup_ and sub_group_. 10191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Insert group operation part: reduce_/inclusive_scan_/exclusive_scan_ 10291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform the operation part: 10391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// fadd/iadd/sadd => add 10491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// fmax/smax => max 10591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// fmin/smin => min 10691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Keep umax/umin unchanged. 10791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallSPIRVGroupBuiltin(CallInst *CI, Op OC); 10891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 10991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform __spirv_MemoryBarrier to atomic_work_item_fence. 11091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// __spirv_MemoryBarrier(scope, sema) => 11191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// atomic_work_item_fence(flag(sema), order(sema), map(scope)) 11291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallSPIRVMemoryBarrier(CallInst *CI); 11391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 11491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform __spirv_{PipeOpName} to OCL pipe builtin functions. 11591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallSPIRVPipeBuiltin(CallInst *CI, Op OC); 11691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 11791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Transform __spirv_* builtins to OCL 2.0 builtins. 11891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// No change with arguments. 11991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void visitCallSPIRVBuiltin(CallInst *CI, Op OC); 12091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 12191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Translate mangled atomic type name: "atomic_" => 12291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// MangledAtomicTypeNamePrefix 12391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni void translateMangledAtomicTypeName(); 12491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 12591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Get prefix work_/sub_ for OCL group builtin functions. 12691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// Assuming the first argument of \param CI is a constant integer for 12791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni /// workgroup/subgroup scope enums. 12891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string getGroupBuiltinPrefix(CallInst *CI); 12991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 13091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni static char ID; 13191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Niprivate: 13291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Module *M; 13391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni LLVMContext *Ctx; 13491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni}; 13591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 13691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nichar SPIRVToOCL20::ID = 0; 13791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 13891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nibool 13991585d9acd75a2bdbfd177bf56c8b9436f442152Yang NiSPIRVToOCL20::runOnModule(Module& Module) { 14091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni M = &Module; 14191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Ctx = &M->getContext(); 14291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visit(*M); 14391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 14491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni translateMangledAtomicTypeName(); 14591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 14691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni eraseUselessFunctions(&Module); 14791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 14891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DEBUG(dbgs() << "After SPIRVToOCL20:\n" << *M); 14991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 15091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string Err; 15191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni raw_string_ostream ErrorOS(Err); 15291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (verifyModule(*M, &ErrorOS)){ 15391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DEBUG(errs() << "Fails to verify module: " << ErrorOS.str()); 15491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 15591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return true; 15691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 15791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 15891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid 15991585d9acd75a2bdbfd177bf56c8b9436f442152Yang NiSPIRVToOCL20::visitCallInst(CallInst& CI) { 16091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DEBUG(dbgs() << "[visistCallInst] " << CI << '\n'); 16191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto F = CI.getCalledFunction(); 16291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!F) 16391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 16491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 16591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto MangledName = F->getName(); 16691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string DemangledName; 16791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Op OC = OpNop; 16891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!oclIsBuiltin(MangledName, &DemangledName) || 16991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni (OC = getSPIRVFuncOC(DemangledName)) == OpNop) 17091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 17191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DEBUG(dbgs() << "DemangledName = " << DemangledName.c_str() << '\n' 17291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni << "OpCode = " << OC << '\n'); 17391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 17491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (OC == OpImageQuerySize || OC == OpImageQuerySizeLod) { 17591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visitCallSPRIVImageQuerySize(&CI); 17691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 17791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 17891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (OC == OpMemoryBarrier) { 17991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visitCallSPIRVMemoryBarrier(&CI); 18091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 18191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 18291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (isAtomicOpCode(OC)) { 18391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visitCallSPIRVAtomicBuiltin(&CI, OC); 18491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 18591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 18691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (isGroupOpCode(OC)) { 18791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visitCallSPIRVGroupBuiltin(&CI, OC); 18891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 18991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 19091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (isPipeOpCode(OC)) { 19191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visitCallSPIRVPipeBuiltin(&CI, OC); 19291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 19391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 19491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (OCLSPIRVBuiltinMap::rfind(OC)) 19591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni visitCallSPIRVBuiltin(&CI, OC); 19691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 19791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 19891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 19991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCallSPIRVMemoryBarrier(CallInst* CI) { 20091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet Attrs = CI->getCalledFunction()->getAttributes(); 20191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mutateCallInstOCL(M, CI, [=](CallInst *, std::vector<Value *> &Args){ 20291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto getArg = [=](unsigned I){ 20391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return cast<ConstantInt>(Args[I])->getZExtValue(); 20491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }; 20591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto MScope = static_cast<Scope>(getArg(0)); 20691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto Sema = mapSPIRVMemSemanticToOCL(getArg(1)); 20791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args.resize(3); 20891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args[0] = getInt32(M, Sema.first); 20991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args[1] = getInt32(M, Sema.second); 21091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args[2] = getInt32(M, rmap<OCLScopeKind>(MScope)); 21191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return kOCLBuiltinName::AtomicWorkItemFence; 21291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }, &Attrs); 21391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 21491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 21591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCallSPRIVImageQuerySize(CallInst *CI) { 21691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Function * func = CI->getCalledFunction(); 21791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Get image type 21891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Type * argTy = func->getFunctionType()->getParamType(0); 21991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(argTy->isPointerTy() && "argument must be a pointer to opaque structure"); 22091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni StructType * imgTy = cast<StructType>(argTy->getPointerElementType()); 22191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(imgTy->isOpaque() && "image type must be an opaque structure"); 22291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni StringRef imgTyName = imgTy->getName(); 22391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(imgTyName.startswith("opencl.image") && "not an OCL image type"); 22491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 22591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni unsigned imgDim = 0; 22691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni bool imgArray = false; 22791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 22891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (imgTyName.startswith("opencl.image1d")) { 22991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni imgDim = 1; 23091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } else if (imgTyName.startswith("opencl.image2d")) { 23191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni imgDim = 2; 23291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } else if (imgTyName.startswith("opencl.image3d")) { 23391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni imgDim = 3; 23491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 23591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(imgDim != 0 && "unexpected image dimensionality"); 23691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 23791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (imgTyName.count("_array_") != 0) { 23891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni imgArray = true; 23991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 24091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 24191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet attributes = CI->getCalledFunction()->getAttributes(); 24291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni BuiltinFuncMangleInfo mangle; 24391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Type * int32Ty = Type::getInt32Ty(*Ctx); 24491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Instruction * getImageSize = nullptr; 24591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 24691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (imgDim == 1) { 24791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // OpImageQuerySize from non-arrayed 1d image is always translated 24891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // into get_image_width returning scalar argument 24991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 25091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni addCallInst(M, kOCLBuiltinName::GetImageWidth, int32Ty, 25191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->getArgOperand(0), &attributes, 25291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI, &mangle, CI->getName(), false); 25391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // The width of integer type returning by OpImageQuerySize[Lod] may 25491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // differ from i32 25591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (CI->getType()->getScalarType() != int32Ty) { 25691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 25791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CastInst::CreateIntegerCast(getImageSize, CI->getType()->getScalarType(), false, 25891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->getName(), CI); 25991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 26091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } else { 26191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert((imgDim == 2 || imgDim == 3) && "invalid image type"); 26291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(CI->getType()->isVectorTy() && "this code can handle vector result type only"); 26391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // get_image_dim returns int2 and int4 for 2d and 3d images respecitvely. 26491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni const unsigned imgDimRetEls = imgDim == 2 ? 2 : 4; 26591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni VectorType * retTy = VectorType::get(int32Ty, imgDimRetEls); 26691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 26791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni addCallInst(M, kOCLBuiltinName::GetImageDim, retTy, 26891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->getArgOperand(0), &attributes, 26991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI, &mangle, CI->getName(), false); 27091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // The width of integer type returning by OpImageQuerySize[Lod] may 27191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // differ from i32 27291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (CI->getType()->getScalarType() != int32Ty) { 27391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 27491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CastInst::CreateIntegerCast(getImageSize, 27591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni VectorType::get(CI->getType()->getScalarType(), 27691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize->getType()->getVectorNumElements()), 27791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni false, CI->getName(), CI); 27891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 27991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 28091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 28191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (imgArray || imgDim == 3) { 28291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(CI->getType()->isVectorTy() && 28391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni "OpImageQuerySize[Lod] must return vector for arrayed and 3d images"); 28491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni const unsigned imgQuerySizeRetEls = CI->getType()->getVectorNumElements(); 28591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 28691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (imgDim == 1) { 28791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // get_image_width returns scalar result while OpImageQuerySize 28891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // for image1d_array_t returns <2 x i32> vector. 28991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(imgQuerySizeRetEls == 2 && 29091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni "OpImageQuerySize[Lod] must return <2 x iN> vector type"); 29191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 29291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni InsertElementInst::Create(UndefValue::get(CI->getType()), getImageSize, 29391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni ConstantInt::get(int32Ty, 0), CI->getName(), CI); 29491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } else { 29591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // get_image_dim and OpImageQuerySize returns different vector 29691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // types for arrayed and 3d images. 29791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni SmallVector<Constant*, 4> maskEls; 29891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni for(unsigned idx = 0; idx < imgQuerySizeRetEls; ++idx) 29991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni maskEls.push_back(ConstantInt::get(int32Ty, idx)); 30091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Constant * mask = ConstantVector::get(maskEls); 30191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 30291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 30391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni new ShuffleVectorInst(getImageSize, UndefValue::get(getImageSize->getType()), 30491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mask, CI->getName(), CI); 30591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 30691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 30791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 30891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (imgArray) { 30991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert((imgDim == 1 || imgDim == 2) && "invalid image array type"); 31091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Insert get_image_array_size to the last position of the resulting vector. 31191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Type * sizeTy = Type::getIntNTy(*Ctx, M->getDataLayout().getPointerSizeInBits(0)); 31291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Instruction * getImageArraySize = 31391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni addCallInst(M, kOCLBuiltinName::GetImageArraySize, sizeTy, 31491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->getArgOperand(0), &attributes, 31591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI, &mangle, CI->getName(), false); 31691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // The width of integer type returning by OpImageQuerySize[Lod] may 31791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // differ from size_t which is returned by get_image_array_size 31891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (getImageArraySize->getType() != CI->getType()->getScalarType()) { 31991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageArraySize = 32091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CastInst::CreateIntegerCast(getImageArraySize, CI->getType()->getScalarType(), 32191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni false, CI->getName(), CI); 32291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 32391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni getImageSize = 32491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni InsertElementInst::Create(getImageSize, getImageArraySize, 32591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni ConstantInt::get(int32Ty, 32691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->getType()->getVectorNumElements() - 1), 32791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->getName(), CI); 32891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 32991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 33091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(getImageSize && "must not be null"); 33191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->replaceAllUsesWith(getImageSize); 33291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CI->eraseFromParent(); 33391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 33491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 33591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCallSPIRVAtomicBuiltin(CallInst* CI, Op OC) { 33691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet Attrs = CI->getCalledFunction()->getAttributes(); 33791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Instruction * pInsertBefore = CI; 33891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 33991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mutateCallInstOCL(M, CI, [=](CallInst *, std::vector<Value *> &Args, Type *& RetTy){ 34091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto Ptr = findFirstPtr(Args); 34191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto Name = OCLSPIRVBuiltinMap::rmap(OC); 34291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto NumOrder = getAtomicBuiltinNumMemoryOrderArgs(Name); 34391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto ScopeIdx = Ptr + 1; 34491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto OrderIdx = Ptr + 2; 34591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (OC == OpAtomicIIncrement || 34691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC == OpAtomicIDecrement) { 34791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Since OpenCL 1.2 atomic_inc and atomic_dec builtins don't have, memory 34891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // scope and memory order syntax, and OpenCL 2.0 doesn't have such 34991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // builtins, therefore we translate these instructions to 35091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // atomic_fetch_add_explicit and atomic_fetch_sub_explicit OpenCL 2.0 35191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // builtins with "operand" argument = 1. 35291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Name = OCLSPIRVBuiltinMap::rmap(OC == OpAtomicIIncrement ? 35391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OpAtomicIAdd: OpAtomicISub); 35491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Type* ValueTy = cast<PointerType>(Args[Ptr]->getType())->getElementType(); 35591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(ValueTy->isIntegerTy()); 35691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args.push_back(llvm::ConstantInt::get(ValueTy, 1)); 35791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 35891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args[ScopeIdx] = mapUInt(M, cast<ConstantInt>(Args[ScopeIdx]), 35991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni [](unsigned I) { return rmap<OCLScopeKind>(static_cast<Scope>(I));}); 36091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni for (size_t I = 0; I < NumOrder; ++I) 36191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args[OrderIdx + I] = mapUInt(M, cast<ConstantInt>(Args[OrderIdx + I]), 36291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni [](unsigned Ord) { return mapSPIRVMemOrderToOCL(Ord); }); 36391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::swap(Args[ScopeIdx], Args.back()); 36491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if(OC == OpAtomicCompareExchange || 36591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC == OpAtomicCompareExchangeWeak) { 36691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // OpAtomicCompareExchange[Weak] semantics is different from 36791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // atomic_compare_exchange_[strong|weak] semantics as well as 36891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // arguments order. 36991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // OCL built-ins returns boolean value and stores a new/original 37091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // value by pointer passed as 2nd argument (aka expected) while SPIR-V 37191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // instructions returns this new/original value as a resulting value. 37291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AllocaInst *pExpected = new AllocaInst(CI->getType(), "expected", 37391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni static_cast<Instruction*>(pInsertBefore->getParent()->getParent()->getEntryBlock().getFirstInsertionPt())); 37491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni pExpected->setAlignment(CI->getType()->getScalarSizeInBits() / 8); 37591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni new StoreInst(Args[1], pExpected, pInsertBefore); 37691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args[1] = pExpected; 37791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::swap(Args[3], Args[4]); 37891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::swap(Args[2], Args[3]); 37991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni RetTy = Type::getInt1Ty(*Ctx); 38091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 38191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return Name; 38291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }, 38391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni [=](CallInst * CI) -> Instruction * { 38491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if(OC == OpAtomicCompareExchange || 38591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC == OpAtomicCompareExchangeWeak) { 38691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // OCL built-ins atomic_compare_exchange_[strong|weak] return boolean value. So, 38791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // to obtain the same value as SPIR-V instruction is returning it has to be loaded 38891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // from the memory where 'expected' value is stored. This memory must contain the 38991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // needed value after a call to OCL built-in is completed. 39091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni LoadInst * pOriginal = new LoadInst(CI->getArgOperand(1), "original", pInsertBefore); 39191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return pOriginal; 39291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 39391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // For other built-ins the return values match. 39491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return CI; 39591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }, 39691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni &Attrs); 39791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 39891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 39991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCallSPIRVBuiltin(CallInst* CI, Op OC) { 40091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet Attrs = CI->getCalledFunction()->getAttributes(); 40191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mutateCallInstOCL(M, CI, [=](CallInst *, std::vector<Value *> &Args){ 40291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return OCLSPIRVBuiltinMap::rmap(OC); 40391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }, &Attrs); 40491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 40591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 40691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCallSPIRVGroupBuiltin(CallInst* CI, Op OC) { 40791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto DemangledName = OCLSPIRVBuiltinMap::rmap(OC); 40891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(DemangledName.find(kSPIRVName::GroupPrefix) == 0); 40991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 41091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string Prefix = getGroupBuiltinPrefix(CI); 41191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 41291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni bool HasGroupOperation = hasGroupOperation(OC); 41391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!HasGroupOperation) { 41491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DemangledName = Prefix + DemangledName; 41591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } else { 41691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto GO = getArgAs<spv::GroupOperation>(CI, 1); 41791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni StringRef Op = DemangledName; 41891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Op = Op.drop_front(strlen(kSPIRVName::GroupPrefix)); 41991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni bool Unsigned = Op.front() == 'u'; 42091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!Unsigned) 42191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Op = Op.drop_front(1); 42291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DemangledName = Prefix + kSPIRVName::GroupPrefix + 42391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni SPIRSPIRVGroupOperationMap::rmap(GO) + '_' + Op.str(); 42491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 42591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet Attrs = CI->getCalledFunction()->getAttributes(); 42691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mutateCallInstOCL(M, CI, [=](CallInst *, std::vector<Value *> &Args){ 42791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args.erase(Args.begin(), Args.begin() + (HasGroupOperation ? 2 : 1)); 42891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (OC == OpGroupBroadcast) 42991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni expandVector(CI, Args, 1); 43091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return DemangledName; 43191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }, &Attrs); 43291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 43391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 43491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCallSPIRVPipeBuiltin(CallInst* CI, Op OC) { 43591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni switch(OC) { 43691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni case OpReservedReadPipe: 43791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC = OpReadPipe; 43891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni break; 43991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni case OpReservedWritePipe: 44091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC = OpWritePipe; 44191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni break; 44291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni default: 44391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Do nothing. 44491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni break; 44591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 44691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto DemangledName = OCLSPIRVBuiltinMap::rmap(OC); 44791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 44891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni bool HasScope = DemangledName.find(kSPIRVName::GroupPrefix) == 0; 44991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (HasScope) 45091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DemangledName = getGroupBuiltinPrefix(CI) + DemangledName; 45191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 45291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet Attrs = CI->getCalledFunction()->getAttributes(); 45391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mutateCallInstOCL(M, CI, [=](CallInst *, std::vector<Value *> &Args){ 45491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (HasScope) 45591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Args.erase(Args.begin(), Args.begin() + 1); 45691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 45791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!(OC == OpReadPipe || 45891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC == OpWritePipe || 45991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC == OpReservedReadPipe || 46091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni OC == OpReservedWritePipe)) 46191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return DemangledName; 46291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 46391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto &P = Args[Args.size() - 3]; 46491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto T = P->getType(); 46591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni assert(isa<PointerType>(T)); 46691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto ET = T->getPointerElementType(); 46791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!ET->isIntegerTy(8) || 46891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni T->getPointerAddressSpace() != SPIRAS_Generic) { 46991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto NewTy = PointerType::getInt8PtrTy(*Ctx, SPIRAS_Generic); 47091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni P = CastInst::CreatePointerBitCastOrAddrSpaceCast(P, NewTy, "", CI); 47191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 47291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return DemangledName; 47391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni }, &Attrs); 47491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 47591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 47691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::translateMangledAtomicTypeName() { 47791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni for (auto &I:M->functions()) { 47891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!I.hasName()) 47991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni continue; 48091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string MangledName = I.getName(); 48191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string DemangledName; 48291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if (!oclIsBuiltin(MangledName, &DemangledName) || 48391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni DemangledName.find(kOCLBuiltinName::AtomPrefix) != 0) 48491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni continue; 48591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto Loc = MangledName.find(kOCLBuiltinName::AtomPrefix); 48691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Loc = MangledName.find(kMangledName::AtomicPrefixInternal, Loc); 48791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni MangledName.replace(Loc, strlen(kMangledName::AtomicPrefixInternal), 48891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni MangledAtomicTypeNamePrefix); 48991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni I.setName(MangledName); 49091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 49191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 49291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 49391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nistd::string 49491585d9acd75a2bdbfd177bf56c8b9436f442152Yang NiSPIRVToOCL20::getGroupBuiltinPrefix(CallInst* CI) { 49591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string Prefix; 49691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni auto ES = getArgAsScope(CI, 0); 49791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni switch(ES) { 49891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni case ScopeWorkgroup: 49991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Prefix = kOCLBuiltinName::WorkPrefix; 50091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni break; 50191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni case ScopeSubgroup: 50291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Prefix = kOCLBuiltinName::SubPrefix; 50391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni break; 50491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni default: 50591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni llvm_unreachable("Invalid execution scope"); 50691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni } 50791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return Prefix; 50891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 50991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 51091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Nivoid SPIRVToOCL20::visitCastInst(CastInst &Cast) { 51191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if(!isa<ZExtInst>(Cast) && !isa<SExtInst>(Cast) && 51291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni !isa<TruncInst>(Cast) && !isa<FPTruncInst>(Cast) && 51391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni !isa<FPExtInst>(Cast) && !isa<FPToUIInst>(Cast) && 51491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni !isa<FPToSIInst>(Cast) && !isa<UIToFPInst>(Cast) && 51591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni !isa<SIToFPInst>(Cast)) 51691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 51791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 51891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Type const* srcTy = Cast.getSrcTy(); 51991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Type * dstVecTy = Cast.getDestTy(); 52091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Leave scalar casts as is. Skip boolean vector casts becase there 52191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // are no suitable OCL built-ins. 52291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if(!dstVecTy->isVectorTy() || 52391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni srcTy->getScalarSizeInBits() == 1 || 52491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni dstVecTy->getScalarSizeInBits() == 1) 52591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return; 52691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 52791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Assemble built-in name -> convert_gentypeN 52891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni std::string castBuiltInName(kOCLBuiltinName::ConvertPrefix); 52991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Check if this is 'floating point -> unsigned integer' cast 53091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni castBuiltInName += 53191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mapLLVMTypeToOCLType(dstVecTy, !isa<FPToUIInst>(Cast)); 53291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 53391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // Replace LLVM conversion instruction with call to conversion built-in 53491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni BuiltinFuncMangleInfo mangle; 53591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // It does matter if the source is unsigned integer or not. SExt is for 53691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni // signed source, ZExt and UIToFPInst are for unsigned source. 53791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni if(isa<ZExtInst>(Cast) || isa<UIToFPInst>(Cast)) 53891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni mangle.addUnsignedArg(0); 53991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 54091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni AttributeSet attributes; 54191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni CallInst *call = addCallInst(M, castBuiltInName, dstVecTy, Cast.getOperand(0), 54291585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni &attributes, &Cast, &mangle, Cast.getName(), false); 54391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Cast.replaceAllUsesWith(call); 54491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni Cast.eraseFromParent(); 54591585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 54691585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 54791585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} // namespace SPIRV 54891585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 54991585d9acd75a2bdbfd177bf56c8b9436f442152Yang NiINITIALIZE_PASS(SPIRVToOCL20, "spvtoocl20", 55091585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni "Translate SPIR-V builtins to OCL 2.0 builtins", false, false) 55191585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni 55291585d9acd75a2bdbfd177bf56c8b9436f442152Yang NiModulePass *llvm::createSPIRVToOCL20() { 55391585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni return new SPIRVToOCL20(); 55491585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni} 555