10e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===- SPIRVLowerOCLBlocks.cpp - Lower OpenCL blocks ------------*- C++ -*-===//
20e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
30e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//                     The LLVM/SPIR-V Translator
40e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
50e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// This file is distributed under the University of Illinois Open Source
60e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// License. See LICENSE.TXT for details.
70e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
80e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
90e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Permission is hereby granted, free of charge, to any person obtaining a
110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// copy of this software and associated documentation files (the "Software"),
120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// to deal with the Software without restriction, including without limitation
130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// the rights to use, copy, modify, merge, publish, distribute, sublicense,
140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// and/or sell copies of the Software, and to permit persons to whom the
150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Software is furnished to do so, subject to the following conditions:
160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Redistributions of source code must retain the above copyright notice,
180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// this list of conditions and the following disclaimers.
190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Redistributions in binary form must reproduce the above copyright notice,
200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// this list of conditions and the following disclaimers in the documentation
210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// and/or other materials provided with the distribution.
220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Neither the names of Advanced Micro Devices, Inc., nor the names of its
230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// contributors may be used to endorse or promote products derived from this
240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Software without specific prior written permission.
250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// THE SOFTWARE.
320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===----------------------------------------------------------------------===//
340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// \file
350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// This file implements lowering of OpenCL blocks to functions.
370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===----------------------------------------------------------------------===//
390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#ifndef OCLLOWERBLOCKS_H_
410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define OCLLOWERBLOCKS_H_
420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVInternal.h"
440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "OCLUtil.h"
450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/ADT/DenseMap.h"
470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/ADT/SetVector.h"
480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/ADT/StringSwitch.h"
490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/ADT/Triple.h"
500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Analysis/AliasAnalysis.h"
510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Analysis/AssumptionCache.h"
520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Analysis/CallGraph.h"
530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/Verifier.h"
540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Bitcode/ReaderWriter.h"
550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/Constants.h"
560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/DerivedTypes.h"
570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/Function.h"
580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/InstrTypes.h"
590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/Instructions.h"
600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/Module.h"
610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/IR/Operator.h"
620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Pass.h"
630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/PassSupport.h"
640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Support/Casting.h"
650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Support/Debug.h"
660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Support/raw_ostream.h"
670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Support/ToolOutputFile.h"
680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "llvm/Transforms/Utils/Cloning.h"
690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <iostream>
710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <list>
720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <memory>
730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <set>
740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <sstream>
750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <vector>
760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define DEBUG_TYPE "spvblocks"
780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungusing namespace llvm;
800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungusing namespace SPIRV;
810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungusing namespace OCLUtil;
820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungnamespace SPIRV{
840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// Lower SPIR2 blocks to function calls.
860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// SPIR2 representation of blocks:
880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// block = spir_block_bind(bitcast(block_func), context_len, context_align,
900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///   context)
910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// block_func_ptr = bitcast(spir_get_block_invoke(block))
920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// context_ptr = spir_get_block_context(block)
930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// ret = block_func_ptr(context_ptr, args)
940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// Propagates block_func to each spir_get_block_invoke through def-use chain of
960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// spir_block_bind, so that
970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// ret = block_func(context, args)
980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVLowerOCLBlocks: public ModulePass {
990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
1000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVLowerOCLBlocks():ModulePass(ID), M(nullptr){
1010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    initializeSPIRVLowerOCLBlocksPass(*PassRegistry::getPassRegistry());
1020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
1050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    AU.addRequired<CallGraphWrapperPass>();
1060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    //AU.addRequired<AliasAnalysis>();
1070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    AU.addRequired<AssumptionCacheTracker>();
1080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual bool runOnModule(Module &Module) {
1110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    M = &Module;
1120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    lowerBlockBind();
1130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    lowerGetBlockInvoke();
1140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    lowerGetBlockContext();
1150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    erase(M->getFunction(SPIR_INTRINSIC_GET_BLOCK_INVOKE));
1160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    erase(M->getFunction(SPIR_INTRINSIC_GET_BLOCK_CONTEXT));
1170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    erase(M->getFunction(SPIR_INTRINSIC_BLOCK_BIND));
1180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    DEBUG(dbgs() << "------- After OCLLowerBlocks ------------\n" <<
1190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung                    *M << '\n');
1200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return true;
1210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static char ID;
1240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprivate:
1250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static int MaxIter = 1000;
1260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  Module *M;
1270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool
1290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerBlockBind() {
1300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto F = M->getFunction(SPIR_INTRINSIC_BLOCK_BIND);
1310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!F)
1320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return false;
1330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    int Iter = MaxIter;
1340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    while(lowerBlockBind(F) && Iter > 0){
1350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Iter--;
1360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      DEBUG(dbgs() << "-------------- after iteration " << MaxIter - Iter <<
1370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          " --------------\n" << *M << '\n');
1380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
1390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Iter > 0 && "Too many iterations");
1400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return true;
1410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool
1440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  eraseUselessFunctions() {
1450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    bool changed = false;
1460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto I = M->begin(), E = M->end(); I != E;) {
1470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Function *F = static_cast<Function*>(I++);
1480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (!GlobalValue::isInternalLinkage(F->getLinkage()) &&
1490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          !F->isDeclaration())
1500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        continue;
1510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      dumpUsers(F, "[eraseUselessFunctions] ");
1530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) {
1540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        auto U = *UI++;
1550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        if (auto CE = dyn_cast<ConstantExpr>(U)){
1560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          if (CE->use_empty()) {
1570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            CE->dropAllReferences();
1580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            changed = true;
1590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          }
1600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        }
1610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
1620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (F->use_empty()) {
1630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        erase(F);
1640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        changed = true;
1650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
1660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
1670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return changed;
1680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
1710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerGetBlockInvoke() {
1720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (auto F = M->getFunction(SPIR_INTRINSIC_GET_BLOCK_INVOKE)) {
1730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) {
1740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        auto CI = dyn_cast<CallInst>(*UI++);
1750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        assert(CI && "Invalid usage of spir_get_block_invoke");
1760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        lowerGetBlockInvoke(CI);
1770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
1780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
1790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
1820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerGetBlockContext() {
1830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (auto F = M->getFunction(SPIR_INTRINSIC_GET_BLOCK_CONTEXT)) {
1840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) {
1850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        auto CI = dyn_cast<CallInst>(*UI++);
1860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        assert(CI && "Invalid usage of spir_get_block_context");
1870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        lowerGetBlockContext(CI);
1880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
1890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
1900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Lower calls of spir_block_bind.
1920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Return true if the Module is changed.
1930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool
1940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerBlockBind(Function *BlockBindFunc) {
1950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    bool changed = false;
1960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto I = BlockBindFunc->user_begin(), E = BlockBindFunc->user_end();
1970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        I != E;) {
1980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      DEBUG(dbgs() << "[lowerBlockBind] " << **I << '\n');
1990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      // Handle spir_block_bind(bitcast(block_func), context_len,
2000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      // context_align, context)
2010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto CallBlkBind = cast<CallInst>(*I++);
2020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Function *InvF = nullptr;
2030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Value *Ctx = nullptr;
2040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Value *CtxLen = nullptr;
2050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Value *CtxAlign = nullptr;
2060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      getBlockInvokeFuncAndContext(CallBlkBind, &InvF, &Ctx, &CtxLen,
2070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          &CtxAlign);
2080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      for (auto II = CallBlkBind->user_begin(), EE = CallBlkBind->user_end();
2090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          II != EE;) {
2100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        auto BlkUser = *II++;
2110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRVDBG(dbgs() << "  Block user: " << *BlkUser << '\n');
2120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        if (auto Ret = dyn_cast<ReturnInst>(BlkUser)) {
2130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          bool Inlined = false;
2140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          changed |= lowerReturnBlock(Ret, CallBlkBind, Inlined);
2150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          if (Inlined)
2160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            return true;
2170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        } else if (auto CI = dyn_cast<CallInst>(BlkUser)){
2180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          auto CallBindF = CI->getCalledFunction();
2190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          auto Name = CallBindF->getName();
2200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          std::string DemangledName;
2210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          if (Name == SPIR_INTRINSIC_GET_BLOCK_INVOKE) {
2220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            assert(CI->getArgOperand(0) == CallBlkBind);
2230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            changed |= lowerGetBlockInvoke(CI, cast<Function>(InvF));
2240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          } else if (Name == SPIR_INTRINSIC_GET_BLOCK_CONTEXT) {
2250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            assert(CI->getArgOperand(0) == CallBlkBind);
2260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            // Handle context_ptr = spir_get_block_context(block)
2270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            lowerGetBlockContext(CI, Ctx);
2280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            changed = true;
22991585d9acd75a2bdbfd177bf56c8b9436f442152Yang Ni          } else if (oclIsBuiltin(Name, &DemangledName)) {
2300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            lowerBlockBuiltin(CI, InvF, Ctx, CtxLen, CtxAlign, DemangledName);
2310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            changed = true;
2320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          } else
2330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            llvm_unreachable("Invalid block user");
2340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        }
2350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
2360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      erase(CallBlkBind);
2370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
2380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    changed |= eraseUselessFunctions();
2390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return changed;
2400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
2420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
2430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerGetBlockContext(CallInst *CallGetBlkCtx, Value *Ctx = nullptr) {
2440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!Ctx)
2450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      getBlockInvokeFuncAndContext(CallGetBlkCtx->getArgOperand(0), nullptr,
2460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          &Ctx);
2470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    CallGetBlkCtx->replaceAllUsesWith(Ctx);
2480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    DEBUG(dbgs() << "  [lowerGetBlockContext] " << *CallGetBlkCtx << " => " <<
2490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        *Ctx << "\n\n");
2500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    erase(CallGetBlkCtx);
2510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
2530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool
2540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerGetBlockInvoke(CallInst *CallGetBlkInvoke,
2550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Function *InvokeF = nullptr) {
2560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    bool changed = false;
2570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto UI = CallGetBlkInvoke->user_begin(),
2580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        UE = CallGetBlkInvoke->user_end();
2590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        UI != UE;) {
2600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      // Handle block_func_ptr = bitcast(spir_get_block_invoke(block))
2610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto CallInv = cast<Instruction>(*UI++);
2620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto Cast = dyn_cast<BitCastInst>(CallInv);
2630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (Cast)
2640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        CallInv = dyn_cast<Instruction>(*CallInv->user_begin());
2650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      DEBUG(dbgs() << "[lowerGetBlockInvoke]  " << *CallInv);
2660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      // Handle ret = block_func_ptr(context_ptr, args)
2670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto CI = cast<CallInst>(CallInv);
2680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto F = CI->getCalledValue();
2690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (InvokeF == nullptr) {
2700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getBlockInvokeFuncAndContext(CallGetBlkInvoke->getArgOperand(0),
2710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            &InvokeF, nullptr);
2720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        assert(InvokeF);
2730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
2740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(F->getType() == InvokeF->getType());
2750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      CI->replaceUsesOfWith(F, InvokeF);
2760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      DEBUG(dbgs() << " => " << *CI << "\n\n");
2770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      erase(Cast);
2780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      changed = true;
2790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
2800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    erase(CallGetBlkInvoke);
2810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return changed;
2820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
2840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
2850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerBlockBuiltin(CallInst *CI, Function *InvF, Value *Ctx, Value *CtxLen,
2860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Value *CtxAlign, const std::string& DemangledName) {
2870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    mutateCallInstSPIRV (M, CI, [=](CallInst *CI, std::vector<Value *> &Args) {
2880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      size_t I = 0;
2890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      size_t E = Args.size();
2900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      for (; I != E; ++I) {
2910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        if (isPointerToOpaqueStructType(Args[I]->getType(),
2920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            SPIR_TYPE_NAME_BLOCK_T)) {
2930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          break;
2940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        }
2950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
2960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert (I < E);
2970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Args[I] = castToVoidFuncPtr(InvF);
2980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (I + 1 == E) {
2990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Args.push_back(Ctx);
3000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Args.push_back(CtxLen);
3010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Args.push_back(CtxAlign);
3020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      } else {
3030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Args.insert(Args.begin() + I + 1, CtxAlign);
3040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Args.insert(Args.begin() + I + 1, CtxLen);
3050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Args.insert(Args.begin() + I + 1, Ctx);
3060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
3070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (DemangledName == kOCLBuiltinName::EnqueueKernel) {
3080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        // Insert event arguments if there are not.
3090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        if (!isa<IntegerType>(Args[3]->getType())) {
3100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          Args.insert(Args.begin() + 3, getInt32(M, 0));
3110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          Args.insert(Args.begin() + 4, getOCLNullClkEventPtr());
3120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        }
3130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        if (!isOCLClkEventPtrType(Args[5]->getType()))
3140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          Args.insert(Args.begin() + 5, getOCLNullClkEventPtr());
3150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
3160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return getSPIRVFuncName(OCLSPIRVBuiltinMap::map(DemangledName));
3170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    });
3180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Transform return of a block.
3200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// The function returning a block is inlined since the context cannot be
3210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// passed to another function.
3220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Returns true of module is changed.
3230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool
3240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  lowerReturnBlock(ReturnInst *Ret, Value *CallBlkBind, bool &Inlined) {
3250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto F = Ret->getParent()->getParent();
3260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto changed = false;
3270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto UI = F->user_begin(), UE = F->user_end(); UI != UE;) {
3280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto U = *UI++;
3290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      dumpUsers(U);
3300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto Inst = dyn_cast<Instruction>(U);
3310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (Inst && Inst->use_empty()) {
3320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        erase(Inst);
3330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        changed = true;
3340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        continue;
3350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
3360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto CI = dyn_cast<CallInst>(U);
3370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if(!CI || CI->getCalledFunction() != F)
3380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        continue;
3390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      DEBUG(dbgs() << "[lowerReturnBlock] inline " << F->getName() << '\n');
3410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto CG = &getAnalysis<CallGraphWrapperPass>().getCallGraph();
3420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto ACT = &getAnalysis<AssumptionCacheTracker>();
3430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      //auto AA = &getAnalysis<AliasAnalysis>();
3440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      //InlineFunctionInfo IFI(CG, M->getDataLayout(), AA, ACT);
3450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      InlineFunctionInfo IFI(CG, ACT);
3460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      InlineFunction(CI, IFI);
3470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Inlined = true;
3480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
3490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return changed || Inlined;
3500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
3530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  getBlockInvokeFuncAndContext(Value *Blk, Function **PInvF, Value **PCtx,
3540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Value **PCtxLen = nullptr, Value **PCtxAlign = nullptr){
3550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Function *InvF = nullptr;
3560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Value *Ctx = nullptr;
3570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Value *CtxLen = nullptr;
3580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Value *CtxAlign = nullptr;
3590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (auto CallBlkBind = dyn_cast<CallInst>(Blk)) {
3600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(CallBlkBind->getCalledFunction()->getName() ==
3610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          SPIR_INTRINSIC_BLOCK_BIND && "Invalid block");
3620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      InvF = dyn_cast<Function>(
3630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          CallBlkBind->getArgOperand(0)->stripPointerCasts());
3640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      CtxLen = CallBlkBind->getArgOperand(1);
3650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      CtxAlign = CallBlkBind->getArgOperand(2);
3660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Ctx = CallBlkBind->getArgOperand(3);
3670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else if (auto F = dyn_cast<Function>(Blk->stripPointerCasts())) {
3680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      InvF = F;
3690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Ctx = Constant::getNullValue(IntegerType::getInt8PtrTy(M->getContext()));
3700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else if (auto Load = dyn_cast<LoadInst>(Blk)) {
3710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      auto Op = Load->getPointerOperand();
3720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (auto GV = dyn_cast<GlobalVariable>(Op)) {
3730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        if (GV->isConstant()) {
3740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          InvF = cast<Function>(GV->getInitializer()->stripPointerCasts());
3750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          Ctx = Constant::getNullValue(IntegerType::getInt8PtrTy(M->getContext()));
3760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        } else {
3770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          llvm_unreachable("load non-constant block?");
3780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        }
3790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      } else {
3800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        llvm_unreachable("Loading block from non global?");
3810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
3820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else {
3830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      llvm_unreachable("Invalid block");
3840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
3850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    DEBUG(dbgs() << "  Block invocation func: " << InvF->getName() << '\n' <<
3860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "  Block context: " << *Ctx << '\n');
3870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(InvF && Ctx && "Invalid block");
3880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (PInvF)
3890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      *PInvF = InvF;
3900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (PCtx)
3910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      *PCtx = Ctx;
3920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (PCtxLen)
3930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      *PCtxLen = CtxLen;
3940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (PCtxAlign)
3950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      *PCtxAlign = CtxAlign;
3960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
3980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  erase(Instruction *I) {
3990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!I)
4000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
4010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (I->use_empty()) {
4020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      I->dropAllReferences();
4030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      I->eraseFromParent();
4040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
4050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    else
4060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      dumpUsers(I);
4070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
4090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  erase(ConstantExpr *I) {
4100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!I)
4110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
4120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (I->use_empty()) {
4130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      I->dropAllReferences();
4140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      I->destroyConstant();
4150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else
4160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      dumpUsers(I);
4170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void
4190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  erase(Function *F) {
4200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!F)
4210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
4220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!F->use_empty()) {
4230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      dumpUsers(F);
4240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
4250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
4260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    F->dropAllReferences();
4270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
4280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    CG.removeFunctionFromModule(new CallGraphNode(F));
4290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  llvm::PointerType* getOCLClkEventType() {
4320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getOrCreateOpaquePtrType(M, SPIR_TYPE_NAME_CLK_EVENT_T,
4330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRAS_Global);
4340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  llvm::PointerType* getOCLClkEventPtrType() {
4370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return PointerType::get(getOCLClkEventType(), SPIRAS_Generic);
4380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isOCLClkEventPtrType(Type *T) {
4410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (auto PT = dyn_cast<PointerType>(T))
4420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return isPointerToOpaqueStructType(
4430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        PT->getElementType(), SPIR_TYPE_NAME_CLK_EVENT_T);
4440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return false;
4450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  llvm::Constant* getOCLNullClkEventPtr() {
4480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Constant::getNullValue(getOCLClkEventPtrType());
4490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void dumpGetBlockInvokeUsers(StringRef Prompt) {
4520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    DEBUG(dbgs() << Prompt);
4530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    dumpUsers(M->getFunction(SPIR_INTRINSIC_GET_BLOCK_INVOKE));
4540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
4560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungchar SPIRVLowerOCLBlocks::ID = 0;
4580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung}
4590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungINITIALIZE_PASS_BEGIN(SPIRVLowerOCLBlocks, "spvblocks",
4610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    "SPIR-V lower OCL blocks", false, false)
4620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungINITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
4630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungINITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
4640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
4650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungINITIALIZE_PASS_END(SPIRVLowerOCLBlocks, "spvblocks",
4660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    "SPIR-V lower OCL blocks", false, false)
4670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungModulePass *llvm::createSPIRVLowerOCLBlocks() {
4690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  return new SPIRVLowerOCLBlocks();
4700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung}
4710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#endif /* OCLLOWERBLOCKS_H_ */
473