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