From 9804b5a0e974a33cd65dab2f33f8c66c8f67064a Mon Sep 17 00:00:00 2001 From: Anuj Mittal Date: Fri, 16 Aug 2019 22:22:33 +0800 Subject: llvm-spirv: update to sync with opencl-clang Also include a patch to not build tests to prevent passing the build flag to every component that is built out of tree. Signed-off-by: Anuj Mittal --- ...rOpenCL-pass-to-handle-new-blocks-represn.patch | 715 +++++++++------------ .../clang/files/0001-skip-building-tests.patch | 50 ++ .../clang/files/0002-Remove-extra-semicolon.patch | 27 + .../clang/llvm-project-source.bbappend | 4 +- 4 files changed, 371 insertions(+), 425 deletions(-) create mode 100644 dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-skip-building-tests.patch create mode 100644 dynamic-layers/clang-layer/recipes-devtools/clang/files/0002-Remove-extra-semicolon.patch diff --git a/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch b/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch index 4a528674..2037421b 100644 --- a/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch +++ b/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch @@ -1,370 +1,57 @@ -From 9ce0fe02fd6cda5fb29fbb0d5037a1798a810b8a Mon Sep 17 00:00:00 2001 +From 177cce531fd3665bb964a03db51890e0241e3e72 Mon Sep 17 00:00:00 2001 From: Alexey Sotkin Date: Thu, 21 Feb 2019 17:14:36 +0300 -Subject: [PATCH 1/3] Update LowerOpenCL pass to handle new blocks - represntation in LLVM IR +Subject: [PATCH] Update LowerOpenCL pass to handle new blocks represntation in + LLVM IR -Upstream-Status: Backport -[https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bd6ddfaf7232cd81c7f2fe9877e66f286731bd8e] +Upstream-Status: Backport [https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bd6ddfaf7232cd81c7f2fe9877e66f286731bd8e] Signed-off-by: Anuj Mittal + --- - lib/SPIRV/SPIRVLowerOCLBlocks.cpp | 413 ++++++++---------------------- - test/global_block.ll | 71 ++--- - test/literal-struct.ll | 31 ++- - test/transcoding/block_w_struct_return.ll | 47 ++-- - test/transcoding/enqueue_kernel.ll | 237 ++++++++++------- - 5 files changed, 317 insertions(+), 482 deletions(-) + lib/SPIRV/SPIRVLowerOCLBlocks.cpp | 249 ++++-------------------------- + test/global_block.ll | 71 ++++----- + test/literal-struct.ll | 31 ++-- + test/transcoding/block_w_struct_return.ll | 47 +++--- + test/transcoding/enqueue_kernel.ll | 237 ++++++++++++++++------------ + 5 files changed, 235 insertions(+), 400 deletions(-) diff --git a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp -index 50e1838..b42a4ec 100644 +index c80bf04..b42a4ec 100644 --- a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp +++ b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp -@@ -1,303 +1,110 @@ --//===- SPIRVLowerOCLBlocks.cpp - OCL Utilities ----------------------------===// --// --// The LLVM/SPIRV Translator --// --// This file is distributed under the University of Illinois Open Source --// License. See LICENSE.TXT for details. --// --// Copyright (c) 2018 Intel Corporation. All rights reserved. --// --// Permission is hereby granted, free of charge, to any person obtaining a --// copy of this software and associated documentation files (the "Software"), --// to deal with the Software without restriction, including without limitation --// the rights to use, copy, modify, merge, publish, distribute, sublicense, --// and/or sell copies of the Software, and to permit persons to whom the --// Software is furnished to do so, subject to the following conditions: --// --// Redistributions of source code must retain the above copyright notice, --// this list of conditions and the following disclaimers. --// Redistributions in binary form must reproduce the above copyright notice, --// this list of conditions and the following disclaimers in the documentation --// and/or other materials provided with the distribution. --// Neither the names of Intel Corporation, nor the names of its --// contributors may be used to endorse or promote products derived from this --// Software without specific prior written permission. --// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH --// THE SOFTWARE. --// --//===----------------------------------------------------------------------===// --// --// SPIR-V specification doesn't allow function pointers, so SPIR-V translator --// is designed to fail if a value with function type (except calls) is occured. --// Currently there is only two cases, when function pointers are generating in --// LLVM IR in OpenCL - block calls and device side enqueue built-in calls. --// --// In both cases values with function type used as intermediate representation --// for block literal structure. --// --// This pass is designed to find such cases and simplify them to avoid any --// function pointer types occurrences in LLVM IR in 4 steps. --// --// 1. Find all function pointer allocas, like --// %block = alloca void () * --// --// Then find a single store to that alloca: --// %blockLit = alloca <{ i32, i32, ...}>, align 4 --// %0 = bitcast <{ i32, i32, ... }>* %blockLit to void ()* --// > store void ()* %0, void ()** %block, align 4 --// --// And replace the alloca users by new instructions which used stored value --// %blockLit itself instead of function pointer alloca %block. --// --// 2. Find consecutive casts from block literal type to i8 addrspace(4)* --// used function pointers as an intermediate type: --// %0 = bitcast <{ i32, i32 }> %block to void() * --// %1 = addrspacecast void() * %0 to i8 addrspace(4)* --// And simplify them: --// %2 = addrspacecast <{ i32, i32 }> %block to i8 addrspace(4)* --// --// 3. Find all unused instructions with function pointer type occured after --// pp.1-2 and remove them. --// --// 4. Find unused globals with function pointer type, like --// @block = constant void ()* --// bitcast ({ i32, i32 }* @__block_literal_global to void ()* --// --// And remove them. --// --//===----------------------------------------------------------------------===// --#define DEBUG_TYPE "spv-lower-ocl-blocks" -- --#include "OCLUtil.h" --#include "SPIRVInternal.h" -- --#include "llvm/ADT/SetVector.h" --#include "llvm/Analysis/ValueTracking.h" --#include "llvm/IR/GlobalVariable.h" --#include "llvm/IR/InstIterator.h" --#include "llvm/IR/Module.h" --#include "llvm/Pass.h" --#include "llvm/PassSupport.h" --#include "llvm/Support/Casting.h" -- --using namespace llvm; -- --namespace { -- --static void --removeUnusedFunctionPtrInst(Instruction *I, -- SmallSetVector &FuncPtrInsts) { -- for (unsigned OpIdx = 0, Ops = I->getNumOperands(); OpIdx != Ops; ++OpIdx) { -- Instruction *OpI = dyn_cast(I->getOperand(OpIdx)); -- I->setOperand(OpIdx, nullptr); -- if (OpI && OpI != I && OpI->user_empty()) -- FuncPtrInsts.insert(OpI); -- } -- I->eraseFromParent(); --} -- --static bool isFuncPtrAlloca(const AllocaInst *AI) { -- auto *ET = dyn_cast(AI->getAllocatedType()); -- return ET && ET->getElementType()->isFunctionTy(); --} -- --static bool hasFuncPtrType(const Value *V) { -- auto *PT = dyn_cast(V->getType()); -- return PT && PT->getElementType()->isFunctionTy(); --} -- --static bool isFuncPtrInst(const Instruction *I) { -- if (auto *AI = dyn_cast(I)) -- return isFuncPtrAlloca(AI); -- -- for (auto &Op : I->operands()) { -- if (auto *AI = dyn_cast(Op)) -- return isFuncPtrAlloca(AI); -- -- auto *OpI = dyn_cast(&Op); -- if (OpI && OpI != I && hasFuncPtrType(OpI)) -- return true; -- } -- return false; --} -- --static StoreInst *findSingleStore(AllocaInst *AI) { -- StoreInst *Store = nullptr; -- for (auto *U : AI->users()) { -- if (!isa(U)) -- continue; // not a store -- if (Store) -- return nullptr; // there are more than one stores -- Store = dyn_cast(U); -- } -- return Store; --} -- --static void fixFunctionPtrAllocaUsers(AllocaInst *AI) { -- // Find and remove a single store to alloca -- auto *SingleStore = findSingleStore(AI); -- assert(SingleStore && "More than one store to the function pointer alloca"); -- auto *StoredVal = SingleStore->getValueOperand(); -- SingleStore->eraseFromParent(); -- -- // Find loads from the alloca and replace thier users -- for (auto *U : AI->users()) { -- auto *LI = dyn_cast(U); -- if (!LI) -- continue; -- -- for (auto *U : LI->users()) { -- auto *UInst = cast(U); -- auto *Cast = CastInst::CreatePointerBitCastOrAddrSpaceCast( -- StoredVal, UInst->getType(), "", UInst); -- UInst->replaceAllUsesWith(Cast); -- } -- } --} -- --static int getBlockLiteralIdx(const Function &F) { -- StringRef FName = F.getName(); -- if (isEnqueueKernelBI(FName)) -- return FName.contains("events") ? 7 : 4; -- if (isKernelQueryBI(FName)) -- return FName.contains("for_ndrange") ? 2 : 1; -- if (FName.startswith("__") && FName.contains("_block_invoke")) -- return F.hasStructRetAttr() ? 1 : 0; -- -- return -1; // No block literal argument --} -- --static bool hasBlockLiteralArg(const Function &F) { -- return getBlockLiteralIdx(F) != -1; --} -- --static bool simplifyFunctionPtrCasts(Function &F) { -- bool Changed = false; -- int BlockLiteralIdx = getBlockLiteralIdx(F); -- for (auto *U : F.users()) { -- auto *Call = dyn_cast(U); -- if (!Call) -- continue; -- if (Call->getFunction()->getName() == F.getName().str() + "_kernel") -- continue; // Skip block invoke function calls inside block invoke kernels -- -- const DataLayout &DL = F.getParent()->getDataLayout(); -- auto *BlockLiteral = Call->getOperand(BlockLiteralIdx); -- auto *BlockLiteralVal = GetUnderlyingObject(BlockLiteral, DL); -- if (isa(BlockLiteralVal)) -- continue; // nothing to do with globals -- -- auto *BlockLiteralAlloca = cast(BlockLiteralVal); -- assert(!BlockLiteralAlloca->getAllocatedType()->isFunctionTy() && -- "Function type shouldn't be there"); -- -- auto *NewBlockLiteral = CastInst::CreatePointerBitCastOrAddrSpaceCast( -- BlockLiteralAlloca, BlockLiteral->getType(), "", Call); -- BlockLiteral->replaceAllUsesWith(NewBlockLiteral); -- Changed |= true; -- } -- return Changed; --} -- --static void --findFunctionPtrAllocas(Module &M, -- SmallVectorImpl &FuncPtrAllocas) { -- for (auto &F : M) { -- if (F.isDeclaration()) -- continue; -- for (auto &I : instructions(F)) { -- auto *AI = dyn_cast(&I); -- if (!AI || !isFuncPtrAlloca(AI)) -- continue; -- FuncPtrAllocas.push_back(AI); -- } -- } --} -- --static void --findUnusedFunctionPtrInsts(Module &M, -- SmallSetVector &FuncPtrInsts) { -- for (auto &F : M) { -- if (F.isDeclaration()) -- continue; -- for (auto &I : instructions(F)) -- if (I.user_empty() && isFuncPtrInst(&I)) -- FuncPtrInsts.insert(&I); -- } --} -- --static void --findUnusedFunctionPtrGlbs(Module &M, -- SmallVectorImpl &FuncPtrGlbs) { -- for (auto &GV : M.globals()) { -- if (!GV.user_empty()) -- continue; -- auto *GVType = dyn_cast(GV.getType()->getElementType()); -- if (GVType && GVType->getElementType()->isFunctionTy()) -- FuncPtrGlbs.push_back(&GV); -- } --} -- --class SPIRVLowerOCLBlocks : public ModulePass { -- --public: -- SPIRVLowerOCLBlocks() : ModulePass(ID) {} -- -- bool runOnModule(Module &M) { -- bool Changed = false; -- -- // 1. Find function pointer allocas and fix their users -- SmallVector FuncPtrAllocas; -- findFunctionPtrAllocas(M, FuncPtrAllocas); -- -- Changed |= !FuncPtrAllocas.empty(); -- for (auto *AI : FuncPtrAllocas) -- fixFunctionPtrAllocaUsers(AI); -- -- // 2. Simplify consecutive casts which use function pointer types -- for (auto &F : M) -- if (hasBlockLiteralArg(F)) -- Changed |= simplifyFunctionPtrCasts(F); -- -- // 3. Cleanup unused instructions with function pointer type -- // which are occured after pp. 1-2 -- SmallSetVector FuncPtrInsts; -- findUnusedFunctionPtrInsts(M, FuncPtrInsts); -- -- Changed |= !FuncPtrInsts.empty(); -- while (!FuncPtrInsts.empty()) { -- Instruction *I = FuncPtrInsts.pop_back_val(); -- removeUnusedFunctionPtrInst(I, FuncPtrInsts); -- } -- -- // 4. Find and remove unused global variables with function pointer type -- SmallVector FuncPtrGlbs; -- findUnusedFunctionPtrGlbs(M, FuncPtrGlbs); -- -- Changed |= !FuncPtrGlbs.empty(); -- for (auto *GV : FuncPtrGlbs) -- GV->eraseFromParent(); -- -- return Changed; -- } -- -- static char ID; --}; // class SPIRVLowerOCLBlocks -- --char SPIRVLowerOCLBlocks::ID = 0; -- --} // namespace -- --INITIALIZE_PASS( -- SPIRVLowerOCLBlocks, "spv-lower-ocl-blocks", -- "Remove function pointers occured in case of using OpenCL blocks", false, -- false) -- --llvm::ModulePass *llvm::createSPIRVLowerOCLBlocks() { -- return new SPIRVLowerOCLBlocks(); --} -+//===- SPIRVLowerOCLBlocks.cpp - OCL Utilities ----------------------------===// -+// -+// The LLVM/SPIRV Translator -+// -+// This file is distributed under the University of Illinois Open Source -+// License. See LICENSE.TXT for details. -+// -+// Copyright (c) 2018 Intel Corporation. All rights reserved. -+// -+// Permission is hereby granted, free of charge, to any person obtaining a -+// copy of this software and associated documentation files (the "Software"), -+// to deal with the Software without restriction, including without limitation -+// the rights to use, copy, modify, merge, publish, distribute, sublicense, -+// and/or sell copies of the Software, and to permit persons to whom the -+// Software is furnished to do so, subject to the following conditions: -+// -+// Redistributions of source code must retain the above copyright notice, -+// this list of conditions and the following disclaimers. -+// Redistributions in binary form must reproduce the above copyright notice, -+// this list of conditions and the following disclaimers in the documentation -+// and/or other materials provided with the distribution. -+// Neither the names of Intel Corporation, nor the names of its -+// contributors may be used to endorse or promote products derived from this -+// Software without specific prior written permission. -+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH -+// THE SOFTWARE. -+// -+//===----------------------------------------------------------------------===// -+// -+// SPIR-V specification doesn't allow function pointers, so SPIR-V translator -+// is designed to fail if a value with function type (except calls) is occured. -+// Currently there is only two cases, when function pointers are generating in -+// LLVM IR in OpenCL - block calls and device side enqueue built-in calls. -+// -+// In both cases values with function type used as intermediate representation -+// for block literal structure. -+// +@@ -40,207 +40,34 @@ + // In both cases values with function type used as intermediate representation + // for block literal structure. + // +-// This pass is designed to find such cases and simplify them to avoid any +-// function pointer types occurrences in LLVM IR in 4 steps. +-// +-// 1. Find all function pointer allocas, like +-// %block = alloca void () * +-// +-// Then find a single store to that alloca: +-// %blockLit = alloca <{ i32, i32, ...}>, align 4 +-// %0 = bitcast <{ i32, i32, ... }>* %blockLit to void ()* +-// > store void ()* %0, void ()** %block, align 4 +-// +-// And replace the alloca users by new instructions which used stored value +-// %blockLit itself instead of function pointer alloca %block. +-// +-// 2. Find consecutive casts from block literal type to i8 addrspace(4)* +-// used function pointers as an intermediate type: +-// %0 = bitcast <{ i32, i32 }> %block to void() * +-// %1 = addrspacecast void() * %0 to i8 addrspace(4)* +-// And simplify them: +-// %2 = addrspacecast <{ i32, i32 }> %block to i8 addrspace(4)* +-// +-// 3. Find all unused instructions with function pointer type occured after +-// pp.1-2 and remove them. +-// +-// 4. Find unused globals with function pointer type, like +-// @block = constant void ()* +-// bitcast ({ i32, i32 }* @__block_literal_global to void ()* +-// +-// And remove them. +// In LLVM IR produced by clang, blocks are represented with the following +// structure: +// %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } @@ -376,32 +63,212 @@ index 50e1838..b42a4ec 100644 +// Clang though has to store function pointers to this structure. Purpose of +// this pass is to replace store of function pointers(not allowed in SPIR-V) +// with null pointers. -+// -+//===----------------------------------------------------------------------===// -+#define DEBUG_TYPE "spv-lower-ocl-blocks" -+ -+#include "SPIRVInternal.h" -+ -+#include "llvm/IR/Module.h" -+#include "llvm/Pass.h" + // + //===----------------------------------------------------------------------===// + #define DEBUG_TYPE "spv-lower-ocl-blocks" + +-#include "OCLUtil.h" + #include "SPIRVInternal.h" + +-#include "llvm/ADT/SetVector.h" +-#include "llvm/Analysis/ValueTracking.h" +-#include "llvm/IR/GlobalVariable.h" +-#include "llvm/IR/InstIterator.h" + #include "llvm/IR/Module.h" + #include "llvm/Pass.h" +-#include "llvm/PassSupport.h" +-#include "llvm/Support/Casting.h" +#include "llvm/Support/Regex.h" -+ -+using namespace llvm; -+ -+namespace { -+ + + using namespace llvm; + + namespace { + +-static void +-removeUnusedFunctionPtrInst(Instruction *I, +- SmallSetVector &FuncPtrInsts) { +- for (unsigned OpIdx = 0, Ops = I->getNumOperands(); OpIdx != Ops; ++OpIdx) { +- Instruction *OpI = dyn_cast(I->getOperand(OpIdx)); +- I->setOperand(OpIdx, nullptr); +- if (OpI && OpI != I && OpI->user_empty()) +- FuncPtrInsts.insert(OpI); +- } +- I->eraseFromParent(); +-} +- +-static bool isFuncPtrAlloca(const AllocaInst *AI) { +- auto *ET = dyn_cast(AI->getAllocatedType()); +- return ET && ET->getElementType()->isFunctionTy(); +-} +- +-static bool hasFuncPtrType(const Value *V) { +- auto *PT = dyn_cast(V->getType()); +- return PT && PT->getElementType()->isFunctionTy(); +-} +- +-static bool isFuncPtrInst(const Instruction *I) { +- if (auto *AI = dyn_cast(I)) +- return isFuncPtrAlloca(AI); +- +- for (auto &Op : I->operands()) { +- if (auto *AI = dyn_cast(Op)) +- return isFuncPtrAlloca(AI); +- +- auto *OpI = dyn_cast(&Op); +- if (OpI && OpI != I && hasFuncPtrType(OpI)) +- return true; +- } +- return false; +-} +- +-static StoreInst *findSingleStore(AllocaInst *AI) { +- StoreInst *Store = nullptr; +- for (auto *U : AI->users()) { +- if (!isa(U)) +- continue; // not a store +- if (Store) +- return nullptr; // there are more than one stores +- Store = dyn_cast(U); +- } +- return Store; +-} +- +-static void fixFunctionPtrAllocaUsers(AllocaInst *AI) { +- // Find and remove a single store to alloca +- auto *SingleStore = findSingleStore(AI); +- assert(SingleStore && "More than one store to the function pointer alloca"); +- auto *StoredVal = SingleStore->getValueOperand(); +- SingleStore->eraseFromParent(); +- +- // Find loads from the alloca and replace thier users +- for (auto *U : AI->users()) { +- auto *LI = dyn_cast(U); +- if (!LI) +- continue; +- +- for (auto *U : LI->users()) { +- auto *UInst = cast(U); +- auto *Cast = CastInst::CreatePointerBitCastOrAddrSpaceCast( +- StoredVal, UInst->getType(), "", UInst); +- UInst->replaceAllUsesWith(Cast); +- } +- } +-} +- +-static int getBlockLiteralIdx(const Function &F) { +- StringRef FName = F.getName(); +- if (isEnqueueKernelBI(FName)) +- return FName.contains("events") ? 7 : 4; +- if (isKernelQueryBI(FName)) +- return FName.contains("for_ndrange") ? 2 : 1; +- if (FName.startswith("__") && FName.contains("_block_invoke")) +- return F.hasStructRetAttr() ? 1 : 0; +- +- return -1; // No block literal argument +-} +- +-static bool hasBlockLiteralArg(const Function &F) { +- return getBlockLiteralIdx(F) != -1; +-} +- +-static bool simplifyFunctionPtrCasts(Function &F) { +- bool Changed = false; +- int BlockLiteralIdx = getBlockLiteralIdx(F); +- for (auto *U : F.users()) { +- auto *Call = dyn_cast(U); +- if (!Call) +- continue; +- if (Call->getFunction()->getName() == F.getName().str() + "_kernel") +- continue; // Skip block invoke function calls inside block invoke kernels +- +- const DataLayout &DL = F.getParent()->getDataLayout(); +- auto *BlockLiteral = Call->getOperand(BlockLiteralIdx); +- auto *BlockLiteralVal = GetUnderlyingObject(BlockLiteral, DL); +- if (isa(BlockLiteralVal)) +- continue; // nothing to do with globals +- +- auto *BlockLiteralAlloca = cast(BlockLiteralVal); +- assert(!BlockLiteralAlloca->getAllocatedType()->isFunctionTy() && +- "Function type shouldn't be there"); +- +- auto *NewBlockLiteral = CastInst::CreatePointerBitCastOrAddrSpaceCast( +- BlockLiteralAlloca, BlockLiteral->getType(), "", Call); +- BlockLiteral->replaceAllUsesWith(NewBlockLiteral); +- Changed |= true; +- } +- return Changed; +-} +- +-static void +-findFunctionPtrAllocas(Module &M, +- SmallVectorImpl &FuncPtrAllocas) { +- for (auto &F : M) { +- if (F.isDeclaration()) +- continue; +- for (auto &I : instructions(F)) { +- auto *AI = dyn_cast(&I); +- if (!AI || !isFuncPtrAlloca(AI)) +- continue; +- FuncPtrAllocas.push_back(AI); +- } +- } +-} +- +-static void +-findUnusedFunctionPtrInsts(Module &M, +- SmallSetVector &FuncPtrInsts) { +- for (auto &F : M) { +- if (F.isDeclaration()) +- continue; +- for (auto &I : instructions(F)) +- if (I.user_empty() && isFuncPtrInst(&I)) +- FuncPtrInsts.insert(&I); +- } +-} +- +-static void +-findUnusedFunctionPtrGlbs(Module &M, +- SmallVectorImpl &FuncPtrGlbs) { +- for (auto &GV : M.globals()) { +- if (!GV.user_empty()) +- continue; +- auto *GVType = dyn_cast(GV.getType()->getElementType()); +- if (GVType && GVType->getElementType()->isFunctionTy()) +- FuncPtrGlbs.push_back(&GV); +- } +static bool isBlockInvoke(Function &F) { + static Regex BlockInvokeRegex("_block_invoke_?[0-9]*$"); + return BlockInvokeRegex.match(F.getName()); -+} -+ -+class SPIRVLowerOCLBlocks : public ModulePass { -+ -+public: -+ SPIRVLowerOCLBlocks() : ModulePass(ID) {} -+ -+ bool runOnModule(Module &M) { -+ bool Changed = false; + } + + class SPIRVLowerOCLBlocks : public ModulePass { +@@ -250,44 +77,24 @@ public: + + bool runOnModule(Module &M) { + bool Changed = false; +- +- // 1. Find function pointer allocas and fix their users +- SmallVector FuncPtrAllocas; +- findFunctionPtrAllocas(M, FuncPtrAllocas); +- +- Changed |= !FuncPtrAllocas.empty(); +- for (auto *AI : FuncPtrAllocas) +- fixFunctionPtrAllocaUsers(AI); +- +- // 2. Simplify consecutive casts which use function pointer types +- for (auto &F : M) +- if (hasBlockLiteralArg(F)) +- Changed |= simplifyFunctionPtrCasts(F); +- +- // 3. Cleanup unused instructions with function pointer type +- // which are occured after pp. 1-2 +- SmallSetVector FuncPtrInsts; +- findUnusedFunctionPtrInsts(M, FuncPtrInsts); +- +- Changed |= !FuncPtrInsts.empty(); +- while (!FuncPtrInsts.empty()) { +- Instruction *I = FuncPtrInsts.pop_back_val(); +- removeUnusedFunctionPtrInst(I, FuncPtrInsts); + for (Function &F : M) { + if (!isBlockInvoke(F)) + continue; @@ -414,31 +281,31 @@ index 50e1838..b42a4ec 100644 + Changed = true; + } + } -+ } -+ return Changed; -+ } -+ -+ static char ID; + } +- +- // 4. Find and remove unused global variables with function pointer type +- SmallVector FuncPtrGlbs; +- findUnusedFunctionPtrGlbs(M, FuncPtrGlbs); +- +- Changed |= !FuncPtrGlbs.empty(); +- for (auto *GV : FuncPtrGlbs) +- GV->eraseFromParent(); +- + return Changed; + } + + static char ID; +-}; // class SPIRVLowerOCLBlocks +}; -+ -+char SPIRVLowerOCLBlocks::ID = 0; -+ -+} // namespace -+ -+INITIALIZE_PASS( -+ SPIRVLowerOCLBlocks, "spv-lower-ocl-blocks", -+ "Remove function pointers occured in case of using OpenCL blocks", false, -+ false) -+ -+llvm::ModulePass *llvm::createSPIRVLowerOCLBlocks() { -+ return new SPIRVLowerOCLBlocks(); -+} + + char SPIRVLowerOCLBlocks::ID = 0; + diff --git a/test/global_block.ll b/test/global_block.ll -index a9267d8..efb4cf3 100644 +index 4fc453b..b558213 100644 --- a/test/global_block.ll +++ b/test/global_block.ll -@@ -16,7 +16,7 @@ - ; RUN: llvm-spirv %t.bc -o %t.spv +@@ -17,7 +17,7 @@ + ; RUN: spirv-val %t.spv ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-LLVM -target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" @@ -446,7 +313,7 @@ index a9267d8..efb4cf3 100644 target triple = "spir-unknown-unknown" ; CHECK-SPIRV: Name [[block_invoke:[0-9]+]] "_block_invoke" -@@ -26,71 +26,56 @@ target triple = "spir-unknown-unknown" +@@ -27,71 +27,56 @@ target triple = "spir-unknown-unknown" ; CHECK-SPIRV: TypePointer [[int8Ptr:[0-9]+]] 8 [[int8]] ; CHECK-SPIRV: TypeFunction [[block_invoke_type:[0-9]+]] [[int]] [[int8Ptr]] [[int]] @@ -546,7 +413,7 @@ index a9267d8..efb4cf3 100644 +!5 = !{!"int*"} +!6 = !{!""} diff --git a/test/literal-struct.ll b/test/literal-struct.ll -index c52170a..52a731a 100644 +index b88187f..dec957a 100644 --- a/test/literal-struct.ll +++ b/test/literal-struct.ll @@ -2,7 +2,7 @@ @@ -558,9 +425,9 @@ index c52170a..52a731a 100644 ; literal-struct.cl: ; void foo() -@@ -14,25 +14,28 @@ - ; RUN: llvm-as < %s | llvm-spirv -spirv-text -o %t - ; RUN: FileCheck < %t %s +@@ -17,25 +17,28 @@ + ; RUN: llvm-spirv %t.bc -o %t.spv + ; RUN: spirv-val %t.spv -; CHECK-DAG: TypeInt [[Int:[0-9]+]] 32 0 -; CHECK-DAG: TypeStruct [[StructType:[0-9]+]] [[Int]] [[Int]] {{$}} @@ -595,7 +462,7 @@ index c52170a..52a731a 100644 ret void } -@@ -40,14 +43,14 @@ entry: +@@ -43,14 +46,14 @@ entry: define internal spir_func void @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor) #0 { entry: %.block_descriptor.addr = alloca i8 addrspace(4)*, align 4 @@ -614,14 +481,14 @@ index c52170a..52a731a 100644 attributes #1 = { convergent } !llvm.module.flags = !{!0} -@@ -57,4 +60,4 @@ attributes #1 = { convergent } +@@ -60,4 +63,4 @@ attributes #1 = { convergent } !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 2, i32 0} -!2 = !{!"clang version 8.0.0 "} +!2 = !{!"clang version 9.0.0 (https://llvm.org/git/clang 04fb8964a801a5c5d7baa5a22272243a7d183896) (https://llvm.org/git/llvm 384f64397f6ad95a361b72d62c07d7bac9f24163)"} diff --git a/test/transcoding/block_w_struct_return.ll b/test/transcoding/block_w_struct_return.ll -index 76e29f0..df89b13 100644 +index a68820f..ebd2c5f 100644 --- a/test/transcoding/block_w_struct_return.ll +++ b/test/transcoding/block_w_struct_return.ll @@ -16,6 +16,8 @@ @@ -633,7 +500,7 @@ index 76e29f0..df89b13 100644 ; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o %t.spv.txt ; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV -@@ -27,12 +29,14 @@ +@@ -28,12 +30,14 @@ ; CHECK-SPIRV: Name [[BlockInv:[0-9]+]] "__block_ret_struct_block_invoke" ; CHECK-SPIRV: 4 TypeInt [[IntTy:[0-9]+]] 32 @@ -649,7 +516,7 @@ index 76e29f0..df89b13 100644 ; CHECK-SPIRV: 7 FunctionCall {{[0-9]+}} {{[0-9]+}} [[BlockInv]] [[StructRet]] [[BlockLit]] [[StructArg]] ; CHECK-LLVM: %[[StructA:.*]] = type { i32 } -@@ -41,20 +45,21 @@ +@@ -42,20 +46,21 @@ target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-unknown" @@ -675,7 +542,7 @@ index 76e29f0..df89b13 100644 %call = call spir_func i64 @_Z13get_global_idj(i32 0) #4 store i64 %call, i64* %tid, align 8 %0 = load i32 addrspace(1)*, i32 addrspace(1)** %res.addr, align 8 -@@ -63,7 +68,7 @@ entry: +@@ -64,7 +69,7 @@ entry: store i32 -1, i32 addrspace(1)* %arrayidx, align 4 %a = getelementptr inbounds %struct.A, %struct.A* %aa, i32 0, i32 0 store i32 5, i32* %a, align 4 @@ -684,7 +551,7 @@ index 76e29f0..df89b13 100644 %a1 = getelementptr inbounds %struct.A, %struct.A* %tmp, i32 0, i32 0 %2 = load i32, i32* %a1, align 4 %sub = sub nsw i32 %2, 6 -@@ -78,10 +83,10 @@ entry: +@@ -79,10 +84,10 @@ entry: define internal spir_func void @__block_ret_struct_block_invoke(%struct.A* noalias sret %agg.result, i8 addrspace(4)* %.block_descriptor, %struct.A* byval align 4 %a) #1 { entry: %.block_descriptor.addr = alloca i8 addrspace(4)*, align 8 @@ -698,7 +565,7 @@ index 76e29f0..df89b13 100644 %a1 = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 0 store i32 6, i32* %a1, align 4 %0 = bitcast %struct.A* %agg.result to i8* -@@ -96,30 +101,22 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture r +@@ -97,30 +102,22 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture r ; Function Attrs: convergent nounwind readnone declare spir_func i64 @_Z13get_global_idj(i32) #3 @@ -738,7 +605,7 @@ index 76e29f0..df89b13 100644 +!5 = !{!"int*"} +!6 = !{!""} diff --git a/test/transcoding/enqueue_kernel.ll b/test/transcoding/enqueue_kernel.ll -index 0d29c71..435871d 100644 +index 1f0b360..761043e 100644 --- a/test/transcoding/enqueue_kernel.ll +++ b/test/transcoding/enqueue_kernel.ll @@ -51,11 +51,12 @@ @@ -781,14 +648,14 @@ index 0d29c71..435871d 100644 ; CHECK-SPIRV: TypeFunction [[BlockTy3:[0-9]+]] [[VoidTy]] [[Int8PtrGenTy]] ; CHECK-SPIRV: ConstantNull [[EventPtrTy]] [[EventNull:[0-9]+]] --; CHECK-LLVM: [[BlockTy1:%[0-9]+]] = type { i32, i32 } --; CHECK-LLVM: [[BlockTy2:%[0-9]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i8 }> --; CHECK-LLVM: [[BlockTy3:%[0-9]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }> --; CHECK-LLVM: [[BlockTy4:%[0-9]+]] = type <{ i32, i32 }> -+; CHECK-LLVM: [[BlockTy1:%[0-9]+]] = type { i32, i32, i8 addrspace(4)* } -+; CHECK-LLVM: [[BlockTy2:%[0-9]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i8 }> -+; CHECK-LLVM: [[BlockTy3:%[0-9]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }> -+; CHECK-LLVM: [[BlockTy4:%[0-9]+]] = type <{ i32, i32, i8 addrspace(4)* }> +-; CHECK-LLVM: [[BlockTy1:%[0-9a-z\.]+]] = type { i32, i32 } +-; CHECK-LLVM: [[BlockTy2:%[0-9a-z\.]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i8 }> +-; CHECK-LLVM: [[BlockTy3:%[0-9a-z\.]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }> +-; CHECK-LLVM: [[BlockTy4:%[0-9a-z\.]+]] = type <{ i32, i32 }> ++; CHECK-LLVM: [[BlockTy1:%[0-9a-z\.]+]] = type { i32, i32, i8 addrspace(4)* } ++; CHECK-LLVM: [[BlockTy2:%[0-9a-z\.]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i8 }> ++; CHECK-LLVM: [[BlockTy3:%[0-9a-z\.]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }> ++; CHECK-LLVM: [[BlockTy4:%[0-9a-z\.]+]] = type <{ i32, i32, i8 addrspace(4)* }> -; CHECK-LLVM: @__block_literal_global = internal addrspace(1) constant [[BlockTy1]] { i32 8, i32 4 }, align 4 -; CHECK-LLVM: @__block_literal_global.1 = internal addrspace(1) constant [[BlockTy1]] { i32 8, i32 4 }, align 4 @@ -1115,5 +982,5 @@ index 0d29c71..435871d 100644 +!5 = !{!"int*", !"int*", !"int", !"char"} +!6 = !{!"", !"", !"", !""} -- -1.8.3.1 +2.7.4 diff --git a/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-skip-building-tests.patch b/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-skip-building-tests.patch new file mode 100644 index 00000000..c58e7d98 --- /dev/null +++ b/dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-skip-building-tests.patch @@ -0,0 +1,50 @@ +From 91db4c3cf7f290a3cab5caa316fc25a60dd409f1 Mon Sep 17 00:00:00 2001 +From: Anuj Mittal +Date: Fri, 16 Aug 2019 20:25:16 +0800 +Subject: [PATCH] llvm-spirv: skip including tests + +Some of these need clang to be built and since we're building this in-tree, +that leads to problems when compiling libcxx, compiler-rt which aren't built +in-tree. + +Instead of using SPIRV_SKIP_CLANG_BUILD to skip clang build and adding this to +all components, disable the building of tests altogether. + +Upstream-Status: Inappropriate + +Signed-off-by: Anuj Mittal +--- + CMakeLists.txt | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index d632a50..81ddf62 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -15,13 +15,6 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + +- if(LLVM_INCLUDE_TESTS) +- set(LLVM_TEST_COMPONENTS +- llvm-as +- llvm-dis +- ) +- endif(LLVM_INCLUDE_TESTS) +- + find_package(LLVM 8.0.0 REQUIRED + COMPONENTS + Analysis +@@ -56,9 +49,6 @@ set(LLVM_SPIRV_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) + + add_subdirectory(lib/SPIRV) + add_subdirectory(tools/llvm-spirv) +-if(LLVM_INCLUDE_TESTS) +- add_subdirectory(test) +-endif(LLVM_INCLUDE_TESTS) + + install( + FILES +-- +2.7.4 + diff --git a/dynamic-layers/clang-layer/recipes-devtools/clang/files/0002-Remove-extra-semicolon.patch b/dynamic-layers/clang-layer/recipes-devtools/clang/files/0002-Remove-extra-semicolon.patch new file mode 100644 index 00000000..5f5a957e --- /dev/null +++ b/dynamic-layers/clang-layer/recipes-devtools/clang/files/0002-Remove-extra-semicolon.patch @@ -0,0 +1,27 @@ +From a2c093c8db7b4e3a5612d0fcce9e4fd1756d6e4b Mon Sep 17 00:00:00 2001 +From: Alexey Sotkin +Date: Mon, 5 Aug 2019 18:18:01 +0300 +Subject: [PATCH] Remove extra semicolon + +Upstream-Status: Backport +Signed-off-by: Anuj Mittal +--- + lib/SPIRV/libSPIRV/SPIRVEnum.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index c93a484..3a071e7 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -124,7 +124,7 @@ template <> inline void SPIRVMap::init() { + add(SPV_INTEL_device_side_avc_motion_estimation, + "SPV_INTEL_device_side_avc_motion_estimation"); + add(SPV_KHR_no_integer_wrap_decoration, "SPV_KHR_no_integer_wrap_decoration"); +-}; ++} + + template <> inline void SPIRVMap::init() { + add(SPIRVEIS_OpenCL, "OpenCL.std"); +-- +2.7.4 + diff --git a/dynamic-layers/clang-layer/recipes-devtools/clang/llvm-project-source.bbappend b/dynamic-layers/clang-layer/recipes-devtools/clang/llvm-project-source.bbappend index 7631c029..50ab25e0 100644 --- a/dynamic-layers/clang-layer/recipes-devtools/clang/llvm-project-source.bbappend +++ b/dynamic-layers/clang-layer/recipes-devtools/clang/llvm-project-source.bbappend @@ -7,6 +7,8 @@ SRC_URI_append_intel-x86-common = " \ file://0001-dont-export-targets-for-binaries.patch \ git://github.com/KhronosGroup/SPIRV-LLVM-Translator.git;protocol=https;branch=llvm_release_80;destsuffix=git/llvm/projects/llvm-spirv;name=spirv \ file://0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch;patchdir=llvm/projects/llvm-spirv \ + file://0002-Remove-extra-semicolon.patch;patchdir=llvm/projects/llvm-spirv \ + file://0001-skip-building-tests.patch;patchdir=llvm/projects/llvm-spirv \ " -SRCREV_spirv = "bd0f28fb92061d49c0f120b4dac3fd8956006745" +SRCREV_spirv = "1d48cd84d04a2f60b43ea3f66eb7c86f4e5973a9" -- cgit v1.2.3-54-g00ecf