summaryrefslogtreecommitdiffstats
path: root/dynamic-layers
diff options
context:
space:
mode:
authorAnuj Mittal <anuj.mittal@intel.com>2019-08-16 22:22:33 +0800
committerAnuj Mittal <anuj.mittal@intel.com>2019-08-21 12:27:06 +0800
commit9804b5a0e974a33cd65dab2f33f8c66c8f67064a (patch)
tree360c67cdb50226a58df810631a815ba78527ea75 /dynamic-layers
parente0486da74816f053a775862a57508bfa16bbd453 (diff)
downloadmeta-intel-9804b5a0e974a33cd65dab2f33f8c66c8f67064a.tar.gz
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 <anuj.mittal@intel.com>
Diffstat (limited to 'dynamic-layers')
-rw-r--r--dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch715
-rw-r--r--dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-skip-building-tests.patch50
-rw-r--r--dynamic-layers/clang-layer/recipes-devtools/clang/files/0002-Remove-extra-semicolon.patch27
-rw-r--r--dynamic-layers/clang-layer/recipes-devtools/clang/llvm-project-source.bbappend4
4 files changed, 371 insertions, 425 deletions
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 @@
1From 9ce0fe02fd6cda5fb29fbb0d5037a1798a810b8a Mon Sep 17 00:00:00 2001 1From 177cce531fd3665bb964a03db51890e0241e3e72 Mon Sep 17 00:00:00 2001
2From: Alexey Sotkin <alexey.sotkin@intel.com> 2From: Alexey Sotkin <alexey.sotkin@intel.com>
3Date: Thu, 21 Feb 2019 17:14:36 +0300 3Date: Thu, 21 Feb 2019 17:14:36 +0300
4Subject: [PATCH 1/3] Update LowerOpenCL pass to handle new blocks 4Subject: [PATCH] Update LowerOpenCL pass to handle new blocks represntation in
5 represntation in LLVM IR 5 LLVM IR
6 6
7Upstream-Status: Backport 7Upstream-Status: Backport [https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bd6ddfaf7232cd81c7f2fe9877e66f286731bd8e]
8[https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bd6ddfaf7232cd81c7f2fe9877e66f286731bd8e]
9Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> 8Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
9
10--- 10---
11 lib/SPIRV/SPIRVLowerOCLBlocks.cpp | 413 ++++++++---------------------- 11 lib/SPIRV/SPIRVLowerOCLBlocks.cpp | 249 ++++--------------------------
12 test/global_block.ll | 71 ++--- 12 test/global_block.ll | 71 ++++-----
13 test/literal-struct.ll | 31 ++- 13 test/literal-struct.ll | 31 ++--
14 test/transcoding/block_w_struct_return.ll | 47 ++-- 14 test/transcoding/block_w_struct_return.ll | 47 +++---
15 test/transcoding/enqueue_kernel.ll | 237 ++++++++++------- 15 test/transcoding/enqueue_kernel.ll | 237 ++++++++++++++++------------
16 5 files changed, 317 insertions(+), 482 deletions(-) 16 5 files changed, 235 insertions(+), 400 deletions(-)
17 17
18diff --git a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp 18diff --git a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp
19index 50e1838..b42a4ec 100644 19index c80bf04..b42a4ec 100644
20--- a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp 20--- a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp
21+++ b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp 21+++ b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp
22@@ -1,303 +1,110 @@ 22@@ -40,207 +40,34 @@
23-//===- SPIRVLowerOCLBlocks.cpp - OCL Utilities ----------------------------===// 23 // In both cases values with function type used as intermediate representation
24-// 24 // for block literal structure.
25-// The LLVM/SPIRV Translator 25 //
26-// 26-// This pass is designed to find such cases and simplify them to avoid any
27-// This file is distributed under the University of Illinois Open Source 27-// function pointer types occurrences in LLVM IR in 4 steps.
28-// License. See LICENSE.TXT for details. 28-//
29-// 29-// 1. Find all function pointer allocas, like
30-// Copyright (c) 2018 Intel Corporation. All rights reserved. 30-// %block = alloca void () *
31-// 31-//
32-// Permission is hereby granted, free of charge, to any person obtaining a 32-// Then find a single store to that alloca:
33-// copy of this software and associated documentation files (the "Software"), 33-// %blockLit = alloca <{ i32, i32, ...}>, align 4
34-// to deal with the Software without restriction, including without limitation 34-// %0 = bitcast <{ i32, i32, ... }>* %blockLit to void ()*
35-// the rights to use, copy, modify, merge, publish, distribute, sublicense, 35-// > store void ()* %0, void ()** %block, align 4
36-// and/or sell copies of the Software, and to permit persons to whom the 36-//
37-// Software is furnished to do so, subject to the following conditions: 37-// And replace the alloca users by new instructions which used stored value
38-// 38-// %blockLit itself instead of function pointer alloca %block.
39-// Redistributions of source code must retain the above copyright notice, 39-//
40-// this list of conditions and the following disclaimers. 40-// 2. Find consecutive casts from block literal type to i8 addrspace(4)*
41-// Redistributions in binary form must reproduce the above copyright notice, 41-// used function pointers as an intermediate type:
42-// this list of conditions and the following disclaimers in the documentation 42-// %0 = bitcast <{ i32, i32 }> %block to void() *
43-// and/or other materials provided with the distribution. 43-// %1 = addrspacecast void() * %0 to i8 addrspace(4)*
44-// Neither the names of Intel Corporation, nor the names of its 44-// And simplify them:
45-// contributors may be used to endorse or promote products derived from this 45-// %2 = addrspacecast <{ i32, i32 }> %block to i8 addrspace(4)*
46-// Software without specific prior written permission. 46-//
47-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 47-// 3. Find all unused instructions with function pointer type occured after
48-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48-// pp.1-2 and remove them.
49-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 49-//
50-// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 50-// 4. Find unused globals with function pointer type, like
51-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 51-// @block = constant void ()*
52-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 52-// bitcast ({ i32, i32 }* @__block_literal_global to void ()*
53-// THE SOFTWARE. 53-//
54-// 54-// And remove them.
55-//===----------------------------------------------------------------------===//
56-//
57-// SPIR-V specification doesn't allow function pointers, so SPIR-V translator
58-// is designed to fail if a value with function type (except calls) is occured.
59-// Currently there is only two cases, when function pointers are generating in
60-// LLVM IR in OpenCL - block calls and device side enqueue built-in calls.
61-//
62-// In both cases values with function type used as intermediate representation
63-// for block literal structure.
64-//
65-// This pass is designed to find such cases and simplify them to avoid any
66-// function pointer types occurrences in LLVM IR in 4 steps.
67-//
68-// 1. Find all function pointer allocas, like
69-// %block = alloca void () *
70-//
71-// Then find a single store to that alloca:
72-// %blockLit = alloca <{ i32, i32, ...}>, align 4
73-// %0 = bitcast <{ i32, i32, ... }>* %blockLit to void ()*
74-// > store void ()* %0, void ()** %block, align 4
75-//
76-// And replace the alloca users by new instructions which used stored value
77-// %blockLit itself instead of function pointer alloca %block.
78-//
79-// 2. Find consecutive casts from block literal type to i8 addrspace(4)*
80-// used function pointers as an intermediate type:
81-// %0 = bitcast <{ i32, i32 }> %block to void() *
82-// %1 = addrspacecast void() * %0 to i8 addrspace(4)*
83-// And simplify them:
84-// %2 = addrspacecast <{ i32, i32 }> %block to i8 addrspace(4)*
85-//
86-// 3. Find all unused instructions with function pointer type occured after
87-// pp.1-2 and remove them.
88-//
89-// 4. Find unused globals with function pointer type, like
90-// @block = constant void ()*
91-// bitcast ({ i32, i32 }* @__block_literal_global to void ()*
92-//
93-// And remove them.
94-//
95-//===----------------------------------------------------------------------===//
96-#define DEBUG_TYPE "spv-lower-ocl-blocks"
97-
98-#include "OCLUtil.h"
99-#include "SPIRVInternal.h"
100-
101-#include "llvm/ADT/SetVector.h"
102-#include "llvm/Analysis/ValueTracking.h"
103-#include "llvm/IR/GlobalVariable.h"
104-#include "llvm/IR/InstIterator.h"
105-#include "llvm/IR/Module.h"
106-#include "llvm/Pass.h"
107-#include "llvm/PassSupport.h"
108-#include "llvm/Support/Casting.h"
109-
110-using namespace llvm;
111-
112-namespace {
113-
114-static void
115-removeUnusedFunctionPtrInst(Instruction *I,
116- SmallSetVector<Instruction *, 16> &FuncPtrInsts) {
117- for (unsigned OpIdx = 0, Ops = I->getNumOperands(); OpIdx != Ops; ++OpIdx) {
118- Instruction *OpI = dyn_cast<Instruction>(I->getOperand(OpIdx));
119- I->setOperand(OpIdx, nullptr);
120- if (OpI && OpI != I && OpI->user_empty())
121- FuncPtrInsts.insert(OpI);
122- }
123- I->eraseFromParent();
124-}
125-
126-static bool isFuncPtrAlloca(const AllocaInst *AI) {
127- auto *ET = dyn_cast<PointerType>(AI->getAllocatedType());
128- return ET && ET->getElementType()->isFunctionTy();
129-}
130-
131-static bool hasFuncPtrType(const Value *V) {
132- auto *PT = dyn_cast<PointerType>(V->getType());
133- return PT && PT->getElementType()->isFunctionTy();
134-}
135-
136-static bool isFuncPtrInst(const Instruction *I) {
137- if (auto *AI = dyn_cast<AllocaInst>(I))
138- return isFuncPtrAlloca(AI);
139-
140- for (auto &Op : I->operands()) {
141- if (auto *AI = dyn_cast<AllocaInst>(Op))
142- return isFuncPtrAlloca(AI);
143-
144- auto *OpI = dyn_cast<Instruction>(&Op);
145- if (OpI && OpI != I && hasFuncPtrType(OpI))
146- return true;
147- }
148- return false;
149-}
150-
151-static StoreInst *findSingleStore(AllocaInst *AI) {
152- StoreInst *Store = nullptr;
153- for (auto *U : AI->users()) {
154- if (!isa<StoreInst>(U))
155- continue; // not a store
156- if (Store)
157- return nullptr; // there are more than one stores
158- Store = dyn_cast<StoreInst>(U);
159- }
160- return Store;
161-}
162-
163-static void fixFunctionPtrAllocaUsers(AllocaInst *AI) {
164- // Find and remove a single store to alloca
165- auto *SingleStore = findSingleStore(AI);
166- assert(SingleStore && "More than one store to the function pointer alloca");
167- auto *StoredVal = SingleStore->getValueOperand();
168- SingleStore->eraseFromParent();
169-
170- // Find loads from the alloca and replace thier users
171- for (auto *U : AI->users()) {
172- auto *LI = dyn_cast<LoadInst>(U);
173- if (!LI)
174- continue;
175-
176- for (auto *U : LI->users()) {
177- auto *UInst = cast<Instruction>(U);
178- auto *Cast = CastInst::CreatePointerBitCastOrAddrSpaceCast(
179- StoredVal, UInst->getType(), "", UInst);
180- UInst->replaceAllUsesWith(Cast);
181- }
182- }
183-}
184-
185-static int getBlockLiteralIdx(const Function &F) {
186- StringRef FName = F.getName();
187- if (isEnqueueKernelBI(FName))
188- return FName.contains("events") ? 7 : 4;
189- if (isKernelQueryBI(FName))
190- return FName.contains("for_ndrange") ? 2 : 1;
191- if (FName.startswith("__") && FName.contains("_block_invoke"))
192- return F.hasStructRetAttr() ? 1 : 0;
193-
194- return -1; // No block literal argument
195-}
196-
197-static bool hasBlockLiteralArg(const Function &F) {
198- return getBlockLiteralIdx(F) != -1;
199-}
200-
201-static bool simplifyFunctionPtrCasts(Function &F) {
202- bool Changed = false;
203- int BlockLiteralIdx = getBlockLiteralIdx(F);
204- for (auto *U : F.users()) {
205- auto *Call = dyn_cast<CallInst>(U);
206- if (!Call)
207- continue;
208- if (Call->getFunction()->getName() == F.getName().str() + "_kernel")
209- continue; // Skip block invoke function calls inside block invoke kernels
210-
211- const DataLayout &DL = F.getParent()->getDataLayout();
212- auto *BlockLiteral = Call->getOperand(BlockLiteralIdx);
213- auto *BlockLiteralVal = GetUnderlyingObject(BlockLiteral, DL);
214- if (isa<GlobalVariable>(BlockLiteralVal))
215- continue; // nothing to do with globals
216-
217- auto *BlockLiteralAlloca = cast<AllocaInst>(BlockLiteralVal);
218- assert(!BlockLiteralAlloca->getAllocatedType()->isFunctionTy() &&
219- "Function type shouldn't be there");
220-
221- auto *NewBlockLiteral = CastInst::CreatePointerBitCastOrAddrSpaceCast(
222- BlockLiteralAlloca, BlockLiteral->getType(), "", Call);
223- BlockLiteral->replaceAllUsesWith(NewBlockLiteral);
224- Changed |= true;
225- }
226- return Changed;
227-}
228-
229-static void
230-findFunctionPtrAllocas(Module &M,
231- SmallVectorImpl<AllocaInst *> &FuncPtrAllocas) {
232- for (auto &F : M) {
233- if (F.isDeclaration())
234- continue;
235- for (auto &I : instructions(F)) {
236- auto *AI = dyn_cast<AllocaInst>(&I);
237- if (!AI || !isFuncPtrAlloca(AI))
238- continue;
239- FuncPtrAllocas.push_back(AI);
240- }
241- }
242-}
243-
244-static void
245-findUnusedFunctionPtrInsts(Module &M,
246- SmallSetVector<Instruction *, 16> &FuncPtrInsts) {
247- for (auto &F : M) {
248- if (F.isDeclaration())
249- continue;
250- for (auto &I : instructions(F))
251- if (I.user_empty() && isFuncPtrInst(&I))
252- FuncPtrInsts.insert(&I);
253- }
254-}
255-
256-static void
257-findUnusedFunctionPtrGlbs(Module &M,
258- SmallVectorImpl<GlobalVariable *> &FuncPtrGlbs) {
259- for (auto &GV : M.globals()) {
260- if (!GV.user_empty())
261- continue;
262- auto *GVType = dyn_cast<PointerType>(GV.getType()->getElementType());
263- if (GVType && GVType->getElementType()->isFunctionTy())
264- FuncPtrGlbs.push_back(&GV);
265- }
266-}
267-
268-class SPIRVLowerOCLBlocks : public ModulePass {
269-
270-public:
271- SPIRVLowerOCLBlocks() : ModulePass(ID) {}
272-
273- bool runOnModule(Module &M) {
274- bool Changed = false;
275-
276- // 1. Find function pointer allocas and fix their users
277- SmallVector<AllocaInst *, 16> FuncPtrAllocas;
278- findFunctionPtrAllocas(M, FuncPtrAllocas);
279-
280- Changed |= !FuncPtrAllocas.empty();
281- for (auto *AI : FuncPtrAllocas)
282- fixFunctionPtrAllocaUsers(AI);
283-
284- // 2. Simplify consecutive casts which use function pointer types
285- for (auto &F : M)
286- if (hasBlockLiteralArg(F))
287- Changed |= simplifyFunctionPtrCasts(F);
288-
289- // 3. Cleanup unused instructions with function pointer type
290- // which are occured after pp. 1-2
291- SmallSetVector<Instruction *, 16> FuncPtrInsts;
292- findUnusedFunctionPtrInsts(M, FuncPtrInsts);
293-
294- Changed |= !FuncPtrInsts.empty();
295- while (!FuncPtrInsts.empty()) {
296- Instruction *I = FuncPtrInsts.pop_back_val();
297- removeUnusedFunctionPtrInst(I, FuncPtrInsts);
298- }
299-
300- // 4. Find and remove unused global variables with function pointer type
301- SmallVector<GlobalVariable *, 16> FuncPtrGlbs;
302- findUnusedFunctionPtrGlbs(M, FuncPtrGlbs);
303-
304- Changed |= !FuncPtrGlbs.empty();
305- for (auto *GV : FuncPtrGlbs)
306- GV->eraseFromParent();
307-
308- return Changed;
309- }
310-
311- static char ID;
312-}; // class SPIRVLowerOCLBlocks
313-
314-char SPIRVLowerOCLBlocks::ID = 0;
315-
316-} // namespace
317-
318-INITIALIZE_PASS(
319- SPIRVLowerOCLBlocks, "spv-lower-ocl-blocks",
320- "Remove function pointers occured in case of using OpenCL blocks", false,
321- false)
322-
323-llvm::ModulePass *llvm::createSPIRVLowerOCLBlocks() {
324- return new SPIRVLowerOCLBlocks();
325-}
326+//===- SPIRVLowerOCLBlocks.cpp - OCL Utilities ----------------------------===//
327+//
328+// The LLVM/SPIRV Translator
329+//
330+// This file is distributed under the University of Illinois Open Source
331+// License. See LICENSE.TXT for details.
332+//
333+// Copyright (c) 2018 Intel Corporation. All rights reserved.
334+//
335+// Permission is hereby granted, free of charge, to any person obtaining a
336+// copy of this software and associated documentation files (the "Software"),
337+// to deal with the Software without restriction, including without limitation
338+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
339+// and/or sell copies of the Software, and to permit persons to whom the
340+// Software is furnished to do so, subject to the following conditions:
341+//
342+// Redistributions of source code must retain the above copyright notice,
343+// this list of conditions and the following disclaimers.
344+// Redistributions in binary form must reproduce the above copyright notice,
345+// this list of conditions and the following disclaimers in the documentation
346+// and/or other materials provided with the distribution.
347+// Neither the names of Intel Corporation, nor the names of its
348+// contributors may be used to endorse or promote products derived from this
349+// Software without specific prior written permission.
350+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
351+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
353+// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
354+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
355+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
356+// THE SOFTWARE.
357+//
358+//===----------------------------------------------------------------------===//
359+//
360+// SPIR-V specification doesn't allow function pointers, so SPIR-V translator
361+// is designed to fail if a value with function type (except calls) is occured.
362+// Currently there is only two cases, when function pointers are generating in
363+// LLVM IR in OpenCL - block calls and device side enqueue built-in calls.
364+//
365+// In both cases values with function type used as intermediate representation
366+// for block literal structure.
367+//
368+// In LLVM IR produced by clang, blocks are represented with the following 55+// In LLVM IR produced by clang, blocks are represented with the following
369+// structure: 56+// structure:
370+// %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } 57+// %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* }
@@ -376,32 +63,212 @@ index 50e1838..b42a4ec 100644
376+// Clang though has to store function pointers to this structure. Purpose of 63+// Clang though has to store function pointers to this structure. Purpose of
377+// this pass is to replace store of function pointers(not allowed in SPIR-V) 64+// this pass is to replace store of function pointers(not allowed in SPIR-V)
378+// with null pointers. 65+// with null pointers.
379+// 66 //
380+//===----------------------------------------------------------------------===// 67 //===----------------------------------------------------------------------===//
381+#define DEBUG_TYPE "spv-lower-ocl-blocks" 68 #define DEBUG_TYPE "spv-lower-ocl-blocks"
382+ 69
383+#include "SPIRVInternal.h" 70-#include "OCLUtil.h"
384+ 71 #include "SPIRVInternal.h"
385+#include "llvm/IR/Module.h" 72
386+#include "llvm/Pass.h" 73-#include "llvm/ADT/SetVector.h"
74-#include "llvm/Analysis/ValueTracking.h"
75-#include "llvm/IR/GlobalVariable.h"
76-#include "llvm/IR/InstIterator.h"
77 #include "llvm/IR/Module.h"
78 #include "llvm/Pass.h"
79-#include "llvm/PassSupport.h"
80-#include "llvm/Support/Casting.h"
387+#include "llvm/Support/Regex.h" 81+#include "llvm/Support/Regex.h"
388+ 82
389+using namespace llvm; 83 using namespace llvm;
390+ 84
391+namespace { 85 namespace {
392+ 86
87-static void
88-removeUnusedFunctionPtrInst(Instruction *I,
89- SmallSetVector<Instruction *, 16> &FuncPtrInsts) {
90- for (unsigned OpIdx = 0, Ops = I->getNumOperands(); OpIdx != Ops; ++OpIdx) {
91- Instruction *OpI = dyn_cast<Instruction>(I->getOperand(OpIdx));
92- I->setOperand(OpIdx, nullptr);
93- if (OpI && OpI != I && OpI->user_empty())
94- FuncPtrInsts.insert(OpI);
95- }
96- I->eraseFromParent();
97-}
98-
99-static bool isFuncPtrAlloca(const AllocaInst *AI) {
100- auto *ET = dyn_cast<PointerType>(AI->getAllocatedType());
101- return ET && ET->getElementType()->isFunctionTy();
102-}
103-
104-static bool hasFuncPtrType(const Value *V) {
105- auto *PT = dyn_cast<PointerType>(V->getType());
106- return PT && PT->getElementType()->isFunctionTy();
107-}
108-
109-static bool isFuncPtrInst(const Instruction *I) {
110- if (auto *AI = dyn_cast<AllocaInst>(I))
111- return isFuncPtrAlloca(AI);
112-
113- for (auto &Op : I->operands()) {
114- if (auto *AI = dyn_cast<AllocaInst>(Op))
115- return isFuncPtrAlloca(AI);
116-
117- auto *OpI = dyn_cast<Instruction>(&Op);
118- if (OpI && OpI != I && hasFuncPtrType(OpI))
119- return true;
120- }
121- return false;
122-}
123-
124-static StoreInst *findSingleStore(AllocaInst *AI) {
125- StoreInst *Store = nullptr;
126- for (auto *U : AI->users()) {
127- if (!isa<StoreInst>(U))
128- continue; // not a store
129- if (Store)
130- return nullptr; // there are more than one stores
131- Store = dyn_cast<StoreInst>(U);
132- }
133- return Store;
134-}
135-
136-static void fixFunctionPtrAllocaUsers(AllocaInst *AI) {
137- // Find and remove a single store to alloca
138- auto *SingleStore = findSingleStore(AI);
139- assert(SingleStore && "More than one store to the function pointer alloca");
140- auto *StoredVal = SingleStore->getValueOperand();
141- SingleStore->eraseFromParent();
142-
143- // Find loads from the alloca and replace thier users
144- for (auto *U : AI->users()) {
145- auto *LI = dyn_cast<LoadInst>(U);
146- if (!LI)
147- continue;
148-
149- for (auto *U : LI->users()) {
150- auto *UInst = cast<Instruction>(U);
151- auto *Cast = CastInst::CreatePointerBitCastOrAddrSpaceCast(
152- StoredVal, UInst->getType(), "", UInst);
153- UInst->replaceAllUsesWith(Cast);
154- }
155- }
156-}
157-
158-static int getBlockLiteralIdx(const Function &F) {
159- StringRef FName = F.getName();
160- if (isEnqueueKernelBI(FName))
161- return FName.contains("events") ? 7 : 4;
162- if (isKernelQueryBI(FName))
163- return FName.contains("for_ndrange") ? 2 : 1;
164- if (FName.startswith("__") && FName.contains("_block_invoke"))
165- return F.hasStructRetAttr() ? 1 : 0;
166-
167- return -1; // No block literal argument
168-}
169-
170-static bool hasBlockLiteralArg(const Function &F) {
171- return getBlockLiteralIdx(F) != -1;
172-}
173-
174-static bool simplifyFunctionPtrCasts(Function &F) {
175- bool Changed = false;
176- int BlockLiteralIdx = getBlockLiteralIdx(F);
177- for (auto *U : F.users()) {
178- auto *Call = dyn_cast<CallInst>(U);
179- if (!Call)
180- continue;
181- if (Call->getFunction()->getName() == F.getName().str() + "_kernel")
182- continue; // Skip block invoke function calls inside block invoke kernels
183-
184- const DataLayout &DL = F.getParent()->getDataLayout();
185- auto *BlockLiteral = Call->getOperand(BlockLiteralIdx);
186- auto *BlockLiteralVal = GetUnderlyingObject(BlockLiteral, DL);
187- if (isa<GlobalVariable>(BlockLiteralVal))
188- continue; // nothing to do with globals
189-
190- auto *BlockLiteralAlloca = cast<AllocaInst>(BlockLiteralVal);
191- assert(!BlockLiteralAlloca->getAllocatedType()->isFunctionTy() &&
192- "Function type shouldn't be there");
193-
194- auto *NewBlockLiteral = CastInst::CreatePointerBitCastOrAddrSpaceCast(
195- BlockLiteralAlloca, BlockLiteral->getType(), "", Call);
196- BlockLiteral->replaceAllUsesWith(NewBlockLiteral);
197- Changed |= true;
198- }
199- return Changed;
200-}
201-
202-static void
203-findFunctionPtrAllocas(Module &M,
204- SmallVectorImpl<AllocaInst *> &FuncPtrAllocas) {
205- for (auto &F : M) {
206- if (F.isDeclaration())
207- continue;
208- for (auto &I : instructions(F)) {
209- auto *AI = dyn_cast<AllocaInst>(&I);
210- if (!AI || !isFuncPtrAlloca(AI))
211- continue;
212- FuncPtrAllocas.push_back(AI);
213- }
214- }
215-}
216-
217-static void
218-findUnusedFunctionPtrInsts(Module &M,
219- SmallSetVector<Instruction *, 16> &FuncPtrInsts) {
220- for (auto &F : M) {
221- if (F.isDeclaration())
222- continue;
223- for (auto &I : instructions(F))
224- if (I.user_empty() && isFuncPtrInst(&I))
225- FuncPtrInsts.insert(&I);
226- }
227-}
228-
229-static void
230-findUnusedFunctionPtrGlbs(Module &M,
231- SmallVectorImpl<GlobalVariable *> &FuncPtrGlbs) {
232- for (auto &GV : M.globals()) {
233- if (!GV.user_empty())
234- continue;
235- auto *GVType = dyn_cast<PointerType>(GV.getType()->getElementType());
236- if (GVType && GVType->getElementType()->isFunctionTy())
237- FuncPtrGlbs.push_back(&GV);
238- }
393+static bool isBlockInvoke(Function &F) { 239+static bool isBlockInvoke(Function &F) {
394+ static Regex BlockInvokeRegex("_block_invoke_?[0-9]*$"); 240+ static Regex BlockInvokeRegex("_block_invoke_?[0-9]*$");
395+ return BlockInvokeRegex.match(F.getName()); 241+ return BlockInvokeRegex.match(F.getName());
396+} 242 }
397+ 243
398+class SPIRVLowerOCLBlocks : public ModulePass { 244 class SPIRVLowerOCLBlocks : public ModulePass {
399+ 245@@ -250,44 +77,24 @@ public:
400+public: 246
401+ SPIRVLowerOCLBlocks() : ModulePass(ID) {} 247 bool runOnModule(Module &M) {
402+ 248 bool Changed = false;
403+ bool runOnModule(Module &M) { 249-
404+ bool Changed = false; 250- // 1. Find function pointer allocas and fix their users
251- SmallVector<AllocaInst *, 16> FuncPtrAllocas;
252- findFunctionPtrAllocas(M, FuncPtrAllocas);
253-
254- Changed |= !FuncPtrAllocas.empty();
255- for (auto *AI : FuncPtrAllocas)
256- fixFunctionPtrAllocaUsers(AI);
257-
258- // 2. Simplify consecutive casts which use function pointer types
259- for (auto &F : M)
260- if (hasBlockLiteralArg(F))
261- Changed |= simplifyFunctionPtrCasts(F);
262-
263- // 3. Cleanup unused instructions with function pointer type
264- // which are occured after pp. 1-2
265- SmallSetVector<Instruction *, 16> FuncPtrInsts;
266- findUnusedFunctionPtrInsts(M, FuncPtrInsts);
267-
268- Changed |= !FuncPtrInsts.empty();
269- while (!FuncPtrInsts.empty()) {
270- Instruction *I = FuncPtrInsts.pop_back_val();
271- removeUnusedFunctionPtrInst(I, FuncPtrInsts);
405+ for (Function &F : M) { 272+ for (Function &F : M) {
406+ if (!isBlockInvoke(F)) 273+ if (!isBlockInvoke(F))
407+ continue; 274+ continue;
@@ -414,31 +281,31 @@ index 50e1838..b42a4ec 100644
414+ Changed = true; 281+ Changed = true;
415+ } 282+ }
416+ } 283+ }
417+ } 284 }
418+ return Changed; 285-
419+ } 286- // 4. Find and remove unused global variables with function pointer type
420+ 287- SmallVector<GlobalVariable *, 16> FuncPtrGlbs;
421+ static char ID; 288- findUnusedFunctionPtrGlbs(M, FuncPtrGlbs);
289-
290- Changed |= !FuncPtrGlbs.empty();
291- for (auto *GV : FuncPtrGlbs)
292- GV->eraseFromParent();
293-
294 return Changed;
295 }
296
297 static char ID;
298-}; // class SPIRVLowerOCLBlocks
422+}; 299+};
423+ 300
424+char SPIRVLowerOCLBlocks::ID = 0; 301 char SPIRVLowerOCLBlocks::ID = 0;
425+ 302
426+} // namespace
427+
428+INITIALIZE_PASS(
429+ SPIRVLowerOCLBlocks, "spv-lower-ocl-blocks",
430+ "Remove function pointers occured in case of using OpenCL blocks", false,
431+ false)
432+
433+llvm::ModulePass *llvm::createSPIRVLowerOCLBlocks() {
434+ return new SPIRVLowerOCLBlocks();
435+}
436diff --git a/test/global_block.ll b/test/global_block.ll 303diff --git a/test/global_block.ll b/test/global_block.ll
437index a9267d8..efb4cf3 100644 304index 4fc453b..b558213 100644
438--- a/test/global_block.ll 305--- a/test/global_block.ll
439+++ b/test/global_block.ll 306+++ b/test/global_block.ll
440@@ -16,7 +16,7 @@ 307@@ -17,7 +17,7 @@
441 ; RUN: llvm-spirv %t.bc -o %t.spv 308 ; RUN: spirv-val %t.spv
442 ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-LLVM 309 ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-LLVM
443 310
444-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" 311-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
446 target triple = "spir-unknown-unknown" 313 target triple = "spir-unknown-unknown"
447 314
448 ; CHECK-SPIRV: Name [[block_invoke:[0-9]+]] "_block_invoke" 315 ; CHECK-SPIRV: Name [[block_invoke:[0-9]+]] "_block_invoke"
449@@ -26,71 +26,56 @@ target triple = "spir-unknown-unknown" 316@@ -27,71 +27,56 @@ target triple = "spir-unknown-unknown"
450 ; CHECK-SPIRV: TypePointer [[int8Ptr:[0-9]+]] 8 [[int8]] 317 ; CHECK-SPIRV: TypePointer [[int8Ptr:[0-9]+]] 8 [[int8]]
451 ; CHECK-SPIRV: TypeFunction [[block_invoke_type:[0-9]+]] [[int]] [[int8Ptr]] [[int]] 318 ; CHECK-SPIRV: TypeFunction [[block_invoke_type:[0-9]+]] [[int]] [[int8Ptr]] [[int]]
452 319
@@ -546,7 +413,7 @@ index a9267d8..efb4cf3 100644
546+!5 = !{!"int*"} 413+!5 = !{!"int*"}
547+!6 = !{!""} 414+!6 = !{!""}
548diff --git a/test/literal-struct.ll b/test/literal-struct.ll 415diff --git a/test/literal-struct.ll b/test/literal-struct.ll
549index c52170a..52a731a 100644 416index b88187f..dec957a 100644
550--- a/test/literal-struct.ll 417--- a/test/literal-struct.ll
551+++ b/test/literal-struct.ll 418+++ b/test/literal-struct.ll
552@@ -2,7 +2,7 @@ 419@@ -2,7 +2,7 @@
@@ -558,9 +425,9 @@ index c52170a..52a731a 100644
558 425
559 ; literal-struct.cl: 426 ; literal-struct.cl:
560 ; void foo() 427 ; void foo()
561@@ -14,25 +14,28 @@ 428@@ -17,25 +17,28 @@
562 ; RUN: llvm-as < %s | llvm-spirv -spirv-text -o %t 429 ; RUN: llvm-spirv %t.bc -o %t.spv
563 ; RUN: FileCheck < %t %s 430 ; RUN: spirv-val %t.spv
564 431
565-; CHECK-DAG: TypeInt [[Int:[0-9]+]] 32 0 432-; CHECK-DAG: TypeInt [[Int:[0-9]+]] 32 0
566-; CHECK-DAG: TypeStruct [[StructType:[0-9]+]] [[Int]] [[Int]] {{$}} 433-; CHECK-DAG: TypeStruct [[StructType:[0-9]+]] [[Int]] [[Int]] {{$}}
@@ -595,7 +462,7 @@ index c52170a..52a731a 100644
595 ret void 462 ret void
596 } 463 }
597 464
598@@ -40,14 +43,14 @@ entry: 465@@ -43,14 +46,14 @@ entry:
599 define internal spir_func void @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor) #0 { 466 define internal spir_func void @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor) #0 {
600 entry: 467 entry:
601 %.block_descriptor.addr = alloca i8 addrspace(4)*, align 4 468 %.block_descriptor.addr = alloca i8 addrspace(4)*, align 4
@@ -614,14 +481,14 @@ index c52170a..52a731a 100644
614 attributes #1 = { convergent } 481 attributes #1 = { convergent }
615 482
616 !llvm.module.flags = !{!0} 483 !llvm.module.flags = !{!0}
617@@ -57,4 +60,4 @@ attributes #1 = { convergent } 484@@ -60,4 +63,4 @@ attributes #1 = { convergent }
618 485
619 !0 = !{i32 1, !"wchar_size", i32 4} 486 !0 = !{i32 1, !"wchar_size", i32 4}
620 !1 = !{i32 2, i32 0} 487 !1 = !{i32 2, i32 0}
621-!2 = !{!"clang version 8.0.0 "} 488-!2 = !{!"clang version 8.0.0 "}
622+!2 = !{!"clang version 9.0.0 (https://llvm.org/git/clang 04fb8964a801a5c5d7baa5a22272243a7d183896) (https://llvm.org/git/llvm 384f64397f6ad95a361b72d62c07d7bac9f24163)"} 489+!2 = !{!"clang version 9.0.0 (https://llvm.org/git/clang 04fb8964a801a5c5d7baa5a22272243a7d183896) (https://llvm.org/git/llvm 384f64397f6ad95a361b72d62c07d7bac9f24163)"}
623diff --git a/test/transcoding/block_w_struct_return.ll b/test/transcoding/block_w_struct_return.ll 490diff --git a/test/transcoding/block_w_struct_return.ll b/test/transcoding/block_w_struct_return.ll
624index 76e29f0..df89b13 100644 491index a68820f..ebd2c5f 100644
625--- a/test/transcoding/block_w_struct_return.ll 492--- a/test/transcoding/block_w_struct_return.ll
626+++ b/test/transcoding/block_w_struct_return.ll 493+++ b/test/transcoding/block_w_struct_return.ll
627@@ -16,6 +16,8 @@ 494@@ -16,6 +16,8 @@
@@ -633,7 +500,7 @@ index 76e29f0..df89b13 100644
633 ; RUN: llvm-as %s -o %t.bc 500 ; RUN: llvm-as %s -o %t.bc
634 ; RUN: llvm-spirv %t.bc -spirv-text -o %t.spv.txt 501 ; RUN: llvm-spirv %t.bc -spirv-text -o %t.spv.txt
635 ; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV 502 ; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV
636@@ -27,12 +29,14 @@ 503@@ -28,12 +30,14 @@
637 ; CHECK-SPIRV: Name [[BlockInv:[0-9]+]] "__block_ret_struct_block_invoke" 504 ; CHECK-SPIRV: Name [[BlockInv:[0-9]+]] "__block_ret_struct_block_invoke"
638 505
639 ; CHECK-SPIRV: 4 TypeInt [[IntTy:[0-9]+]] 32 506 ; CHECK-SPIRV: 4 TypeInt [[IntTy:[0-9]+]] 32
@@ -649,7 +516,7 @@ index 76e29f0..df89b13 100644
649 ; CHECK-SPIRV: 7 FunctionCall {{[0-9]+}} {{[0-9]+}} [[BlockInv]] [[StructRet]] [[BlockLit]] [[StructArg]] 516 ; CHECK-SPIRV: 7 FunctionCall {{[0-9]+}} {{[0-9]+}} [[BlockInv]] [[StructRet]] [[BlockLit]] [[StructArg]]
650 517
651 ; CHECK-LLVM: %[[StructA:.*]] = type { i32 } 518 ; CHECK-LLVM: %[[StructA:.*]] = type { i32 }
652@@ -41,20 +45,21 @@ 519@@ -42,20 +46,21 @@
653 target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" 520 target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
654 target triple = "spir64-unknown-unknown" 521 target triple = "spir64-unknown-unknown"
655 522
@@ -675,7 +542,7 @@ index 76e29f0..df89b13 100644
675 %call = call spir_func i64 @_Z13get_global_idj(i32 0) #4 542 %call = call spir_func i64 @_Z13get_global_idj(i32 0) #4
676 store i64 %call, i64* %tid, align 8 543 store i64 %call, i64* %tid, align 8
677 %0 = load i32 addrspace(1)*, i32 addrspace(1)** %res.addr, align 8 544 %0 = load i32 addrspace(1)*, i32 addrspace(1)** %res.addr, align 8
678@@ -63,7 +68,7 @@ entry: 545@@ -64,7 +69,7 @@ entry:
679 store i32 -1, i32 addrspace(1)* %arrayidx, align 4 546 store i32 -1, i32 addrspace(1)* %arrayidx, align 4
680 %a = getelementptr inbounds %struct.A, %struct.A* %aa, i32 0, i32 0 547 %a = getelementptr inbounds %struct.A, %struct.A* %aa, i32 0, i32 0
681 store i32 5, i32* %a, align 4 548 store i32 5, i32* %a, align 4
@@ -684,7 +551,7 @@ index 76e29f0..df89b13 100644
684 %a1 = getelementptr inbounds %struct.A, %struct.A* %tmp, i32 0, i32 0 551 %a1 = getelementptr inbounds %struct.A, %struct.A* %tmp, i32 0, i32 0
685 %2 = load i32, i32* %a1, align 4 552 %2 = load i32, i32* %a1, align 4
686 %sub = sub nsw i32 %2, 6 553 %sub = sub nsw i32 %2, 6
687@@ -78,10 +83,10 @@ entry: 554@@ -79,10 +84,10 @@ entry:
688 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 { 555 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 {
689 entry: 556 entry:
690 %.block_descriptor.addr = alloca i8 addrspace(4)*, align 8 557 %.block_descriptor.addr = alloca i8 addrspace(4)*, align 8
@@ -698,7 +565,7 @@ index 76e29f0..df89b13 100644
698 %a1 = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 0 565 %a1 = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 0
699 store i32 6, i32* %a1, align 4 566 store i32 6, i32* %a1, align 4
700 %0 = bitcast %struct.A* %agg.result to i8* 567 %0 = bitcast %struct.A* %agg.result to i8*
701@@ -96,30 +101,22 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture r 568@@ -97,30 +102,22 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture r
702 ; Function Attrs: convergent nounwind readnone 569 ; Function Attrs: convergent nounwind readnone
703 declare spir_func i64 @_Z13get_global_idj(i32) #3 570 declare spir_func i64 @_Z13get_global_idj(i32) #3
704 571
@@ -738,7 +605,7 @@ index 76e29f0..df89b13 100644
738+!5 = !{!"int*"} 605+!5 = !{!"int*"}
739+!6 = !{!""} 606+!6 = !{!""}
740diff --git a/test/transcoding/enqueue_kernel.ll b/test/transcoding/enqueue_kernel.ll 607diff --git a/test/transcoding/enqueue_kernel.ll b/test/transcoding/enqueue_kernel.ll
741index 0d29c71..435871d 100644 608index 1f0b360..761043e 100644
742--- a/test/transcoding/enqueue_kernel.ll 609--- a/test/transcoding/enqueue_kernel.ll
743+++ b/test/transcoding/enqueue_kernel.ll 610+++ b/test/transcoding/enqueue_kernel.ll
744@@ -51,11 +51,12 @@ 611@@ -51,11 +51,12 @@
@@ -781,14 +648,14 @@ index 0d29c71..435871d 100644
781 ; CHECK-SPIRV: TypeFunction [[BlockTy3:[0-9]+]] [[VoidTy]] [[Int8PtrGenTy]] 648 ; CHECK-SPIRV: TypeFunction [[BlockTy3:[0-9]+]] [[VoidTy]] [[Int8PtrGenTy]]
782 ; CHECK-SPIRV: ConstantNull [[EventPtrTy]] [[EventNull:[0-9]+]] 649 ; CHECK-SPIRV: ConstantNull [[EventPtrTy]] [[EventNull:[0-9]+]]
783 650
784-; CHECK-LLVM: [[BlockTy1:%[0-9]+]] = type { i32, i32 } 651-; CHECK-LLVM: [[BlockTy1:%[0-9a-z\.]+]] = type { i32, i32 }
785-; CHECK-LLVM: [[BlockTy2:%[0-9]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i8 }> 652-; CHECK-LLVM: [[BlockTy2:%[0-9a-z\.]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i8 }>
786-; CHECK-LLVM: [[BlockTy3:%[0-9]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }> 653-; CHECK-LLVM: [[BlockTy3:%[0-9a-z\.]+]] = type <{ i32, i32, i32 addrspace(1)*, i32, i32 addrspace(1)* }>
787-; CHECK-LLVM: [[BlockTy4:%[0-9]+]] = type <{ i32, i32 }> 654-; CHECK-LLVM: [[BlockTy4:%[0-9a-z\.]+]] = type <{ i32, i32 }>
788+; CHECK-LLVM: [[BlockTy1:%[0-9]+]] = type { i32, i32, i8 addrspace(4)* } 655+; CHECK-LLVM: [[BlockTy1:%[0-9a-z\.]+]] = type { i32, i32, i8 addrspace(4)* }
789+; CHECK-LLVM: [[BlockTy2:%[0-9]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i8 }> 656+; CHECK-LLVM: [[BlockTy2:%[0-9a-z\.]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i8 }>
790+; CHECK-LLVM: [[BlockTy3:%[0-9]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }> 657+; CHECK-LLVM: [[BlockTy3:%[0-9a-z\.]+]] = type <{ i32, i32, i8 addrspace(4)*, i32 addrspace(1)*, i32, i32 addrspace(1)* }>
791+; CHECK-LLVM: [[BlockTy4:%[0-9]+]] = type <{ i32, i32, i8 addrspace(4)* }> 658+; CHECK-LLVM: [[BlockTy4:%[0-9a-z\.]+]] = type <{ i32, i32, i8 addrspace(4)* }>
792 659
793-; CHECK-LLVM: @__block_literal_global = internal addrspace(1) constant [[BlockTy1]] { i32 8, i32 4 }, align 4 660-; CHECK-LLVM: @__block_literal_global = internal addrspace(1) constant [[BlockTy1]] { i32 8, i32 4 }, align 4
794-; CHECK-LLVM: @__block_literal_global.1 = internal addrspace(1) constant [[BlockTy1]] { i32 8, i32 4 }, align 4 661-; 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
1115+!5 = !{!"int*", !"int*", !"int", !"char"} 982+!5 = !{!"int*", !"int*", !"int", !"char"}
1116+!6 = !{!"", !"", !"", !""} 983+!6 = !{!"", !"", !"", !""}
1117-- 984--
11181.8.3.1 9852.7.4
1119 986
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 @@
1From 91db4c3cf7f290a3cab5caa316fc25a60dd409f1 Mon Sep 17 00:00:00 2001
2From: Anuj Mittal <anuj.mittal@intel.com>
3Date: Fri, 16 Aug 2019 20:25:16 +0800
4Subject: [PATCH] llvm-spirv: skip including tests
5
6Some of these need clang to be built and since we're building this in-tree,
7that leads to problems when compiling libcxx, compiler-rt which aren't built
8in-tree.
9
10Instead of using SPIRV_SKIP_CLANG_BUILD to skip clang build and adding this to
11all components, disable the building of tests altogether.
12
13Upstream-Status: Inappropriate
14
15Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
16---
17 CMakeLists.txt | 10 ----------
18 1 file changed, 10 deletions(-)
19
20diff --git a/CMakeLists.txt b/CMakeLists.txt
21index d632a50..81ddf62 100644
22--- a/CMakeLists.txt
23+++ b/CMakeLists.txt
24@@ -15,13 +15,6 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
25 set(CMAKE_CXX_STANDARD 11)
26 set(CMAKE_CXX_STANDARD_REQUIRED ON)
27
28- if(LLVM_INCLUDE_TESTS)
29- set(LLVM_TEST_COMPONENTS
30- llvm-as
31- llvm-dis
32- )
33- endif(LLVM_INCLUDE_TESTS)
34-
35 find_package(LLVM 8.0.0 REQUIRED
36 COMPONENTS
37 Analysis
38@@ -56,9 +49,6 @@ set(LLVM_SPIRV_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include)
39
40 add_subdirectory(lib/SPIRV)
41 add_subdirectory(tools/llvm-spirv)
42-if(LLVM_INCLUDE_TESTS)
43- add_subdirectory(test)
44-endif(LLVM_INCLUDE_TESTS)
45
46 install(
47 FILES
48--
492.7.4
50
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 @@
1From a2c093c8db7b4e3a5612d0fcce9e4fd1756d6e4b Mon Sep 17 00:00:00 2001
2From: Alexey Sotkin <alexey.sotkin@intel.com>
3Date: Mon, 5 Aug 2019 18:18:01 +0300
4Subject: [PATCH] Remove extra semicolon
5
6Upstream-Status: Backport
7Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
8---
9 lib/SPIRV/libSPIRV/SPIRVEnum.h | 2 +-
10 1 file changed, 1 insertion(+), 1 deletion(-)
11
12diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h
13index c93a484..3a071e7 100644
14--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h
15+++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h
16@@ -124,7 +124,7 @@ template <> inline void SPIRVMap<SPIRVExtensionKind, std::string>::init() {
17 add(SPV_INTEL_device_side_avc_motion_estimation,
18 "SPV_INTEL_device_side_avc_motion_estimation");
19 add(SPV_KHR_no_integer_wrap_decoration, "SPV_KHR_no_integer_wrap_decoration");
20-};
21+}
22
23 template <> inline void SPIRVMap<SPIRVExtInstSetKind, std::string>::init() {
24 add(SPIRVEIS_OpenCL, "OpenCL.std");
25--
262.7.4
27
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 = " \
7 file://0001-dont-export-targets-for-binaries.patch \ 7 file://0001-dont-export-targets-for-binaries.patch \
8 git://github.com/KhronosGroup/SPIRV-LLVM-Translator.git;protocol=https;branch=llvm_release_80;destsuffix=git/llvm/projects/llvm-spirv;name=spirv \ 8 git://github.com/KhronosGroup/SPIRV-LLVM-Translator.git;protocol=https;branch=llvm_release_80;destsuffix=git/llvm/projects/llvm-spirv;name=spirv \
9 file://0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch;patchdir=llvm/projects/llvm-spirv \ 9 file://0001-Update-LowerOpenCL-pass-to-handle-new-blocks-represn.patch;patchdir=llvm/projects/llvm-spirv \
10 file://0002-Remove-extra-semicolon.patch;patchdir=llvm/projects/llvm-spirv \
11 file://0001-skip-building-tests.patch;patchdir=llvm/projects/llvm-spirv \
10 " 12 "
11 13
12SRCREV_spirv = "bd0f28fb92061d49c0f120b4dac3fd8956006745" 14SRCREV_spirv = "1d48cd84d04a2f60b43ea3f66eb7c86f4e5973a9"