diff options
author | Anuj Mittal <anuj.mittal@intel.com> | 2019-08-16 22:22:33 +0800 |
---|---|---|
committer | Anuj Mittal <anuj.mittal@intel.com> | 2019-08-21 12:27:06 +0800 |
commit | 9804b5a0e974a33cd65dab2f33f8c66c8f67064a (patch) | |
tree | 360c67cdb50226a58df810631a815ba78527ea75 /dynamic-layers/clang-layer/recipes-devtools | |
parent | e0486da74816f053a775862a57508bfa16bbd453 (diff) | |
download | meta-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/clang-layer/recipes-devtools')
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 @@ | |||
1 | From 9ce0fe02fd6cda5fb29fbb0d5037a1798a810b8a Mon Sep 17 00:00:00 2001 | 1 | From 177cce531fd3665bb964a03db51890e0241e3e72 Mon Sep 17 00:00:00 2001 |
2 | From: Alexey Sotkin <alexey.sotkin@intel.com> | 2 | From: Alexey Sotkin <alexey.sotkin@intel.com> |
3 | Date: Thu, 21 Feb 2019 17:14:36 +0300 | 3 | Date: Thu, 21 Feb 2019 17:14:36 +0300 |
4 | Subject: [PATCH 1/3] Update LowerOpenCL pass to handle new blocks | 4 | Subject: [PATCH] Update LowerOpenCL pass to handle new blocks represntation in |
5 | represntation in LLVM IR | 5 | LLVM IR |
6 | 6 | ||
7 | Upstream-Status: Backport | 7 | Upstream-Status: Backport [https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bd6ddfaf7232cd81c7f2fe9877e66f286731bd8e] |
8 | [https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bd6ddfaf7232cd81c7f2fe9877e66f286731bd8e] | ||
9 | Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> | 8 | Signed-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 | ||
18 | diff --git a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp | 18 | diff --git a/lib/SPIRV/SPIRVLowerOCLBlocks.cpp b/lib/SPIRV/SPIRVLowerOCLBlocks.cpp |
19 | index 50e1838..b42a4ec 100644 | 19 | index 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 | +} | ||
436 | diff --git a/test/global_block.ll b/test/global_block.ll | 303 | diff --git a/test/global_block.ll b/test/global_block.ll |
437 | index a9267d8..efb4cf3 100644 | 304 | index 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 = !{!""} |
548 | diff --git a/test/literal-struct.ll b/test/literal-struct.ll | 415 | diff --git a/test/literal-struct.ll b/test/literal-struct.ll |
549 | index c52170a..52a731a 100644 | 416 | index 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)"} |
623 | diff --git a/test/transcoding/block_w_struct_return.ll b/test/transcoding/block_w_struct_return.ll | 490 | diff --git a/test/transcoding/block_w_struct_return.ll b/test/transcoding/block_w_struct_return.ll |
624 | index 76e29f0..df89b13 100644 | 491 | index 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 = !{!""} |
740 | diff --git a/test/transcoding/enqueue_kernel.ll b/test/transcoding/enqueue_kernel.ll | 607 | diff --git a/test/transcoding/enqueue_kernel.ll b/test/transcoding/enqueue_kernel.ll |
741 | index 0d29c71..435871d 100644 | 608 | index 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 | -- |
1118 | 1.8.3.1 | 985 | 2.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 @@ | |||
1 | From 91db4c3cf7f290a3cab5caa316fc25a60dd409f1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Anuj Mittal <anuj.mittal@intel.com> | ||
3 | Date: Fri, 16 Aug 2019 20:25:16 +0800 | ||
4 | Subject: [PATCH] llvm-spirv: skip including tests | ||
5 | |||
6 | Some of these need clang to be built and since we're building this in-tree, | ||
7 | that leads to problems when compiling libcxx, compiler-rt which aren't built | ||
8 | in-tree. | ||
9 | |||
10 | Instead of using SPIRV_SKIP_CLANG_BUILD to skip clang build and adding this to | ||
11 | all components, disable the building of tests altogether. | ||
12 | |||
13 | Upstream-Status: Inappropriate | ||
14 | |||
15 | Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> | ||
16 | --- | ||
17 | CMakeLists.txt | 10 ---------- | ||
18 | 1 file changed, 10 deletions(-) | ||
19 | |||
20 | diff --git a/CMakeLists.txt b/CMakeLists.txt | ||
21 | index 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 | -- | ||
49 | 2.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 @@ | |||
1 | From a2c093c8db7b4e3a5612d0fcce9e4fd1756d6e4b Mon Sep 17 00:00:00 2001 | ||
2 | From: Alexey Sotkin <alexey.sotkin@intel.com> | ||
3 | Date: Mon, 5 Aug 2019 18:18:01 +0300 | ||
4 | Subject: [PATCH] Remove extra semicolon | ||
5 | |||
6 | Upstream-Status: Backport | ||
7 | Signed-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 | |||
12 | diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h | ||
13 | index 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 | -- | ||
26 | 2.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 | ||
12 | SRCREV_spirv = "bd0f28fb92061d49c0f120b4dac3fd8956006745" | 14 | SRCREV_spirv = "1d48cd84d04a2f60b43ea3f66eb7c86f4e5973a9" |