[meta-intel] [PATCH 4/6] llvm-spirv: update to sync with opencl-clang

Anuj Mittal anuj.mittal at intel.com
Sun Aug 18 20:57:31 PDT 2019


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 at intel.com>
---
 ...rOpenCL-pass-to-handle-new-blocks-represn.patch | 715 +++++++++------------
 .../clang/files/0001-skip-building-tests.patch     |  50 ++
 .../clang/files/0002-Remove-extra-semicolon.patch  |  27 +
 .../clang/llvm-project-source.bbappend             |   4 +-
 4 files changed, 371 insertions(+), 425 deletions(-)
 create mode 100644 dynamic-layers/clang-layer/recipes-devtools/clang/files/0001-skip-building-tests.patch
 create mode 100644 dynamic-layers/clang-layer/recipes-devtools/clang/files/0002-Remove-extra-semicolon.patch

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



More information about the meta-intel mailing list