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