summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsamliu <yaxun.liu@amd.com>2015-09-08 22:47:50 -0400
committersamliu <yaxun.liu@amd.com>2015-09-08 22:47:50 -0400
commit4a73b33562bde4b75a1585cc3bce2d911c710019 (patch)
tree51853f9c5934364d6af0af295051944d04c10258
parentc712a1e855b5248c296e60bd2e383a5cc9b37893 (diff)
[SPIRV]Fix bug causing verify module error msg not output.
Fix bug about OpMemoryBarrier word count. Fix build failure on Ubuntu due to class member named as Op. Refactoring translation of atomic builtin functions.
-rw-r--r--lib/SPIRV/CMakeLists.txt3
-rw-r--r--lib/SPIRV/OCL20To12.cpp140
-rw-r--r--lib/SPIRV/OCLUtil.cpp114
-rw-r--r--lib/SPIRV/OCLUtil.h87
-rw-r--r--lib/SPIRV/SPRVInternal.h156
-rw-r--r--lib/SPIRV/SPRVReader.cpp68
-rw-r--r--lib/SPIRV/SPRVRegularizeOCL20.cpp273
-rw-r--r--lib/SPIRV/SPRVToOCL20.cpp189
-rw-r--r--lib/SPIRV/SPRVUtil.cpp52
-rw-r--r--lib/SPIRV/SPRVWriter.cpp259
-rw-r--r--lib/SPIRV/libSPIRV/SPRVEnum.h47
-rw-r--r--lib/SPIRV/libSPIRV/SPRVInstruction.h34
-rw-r--r--lib/SPIRV/libSPIRV/SPRVModule.cpp18
-rw-r--r--lib/SPIRV/libSPIRV/SPRVModule.h8
-rw-r--r--tools/llvm-spirv/llvm-spirv.cpp2
15 files changed, 1067 insertions, 383 deletions
diff --git a/lib/SPIRV/CMakeLists.txt b/lib/SPIRV/CMakeLists.txt
index 2eea62b..ce431ea 100644
--- a/lib/SPIRV/CMakeLists.txt
+++ b/lib/SPIRV/CMakeLists.txt
@@ -17,10 +17,13 @@ add_llvm_library(LLVMSPIRVLib
Mangler/Mangler.cpp
Mangler/ManglingUtils.cpp
Mangler/ParameterType.cpp
+ OCL20To12.cpp
+ OCLUtil.cpp
SPRVLowerBool.cpp
SPRVLowerOCLBlocks.cpp
SPRVReader.cpp
SPRVRegularizeOCL20.cpp
+ SPRVToOCL20.cpp
SPRVUtil.cpp
SPRVWriter.cpp
)
diff --git a/lib/SPIRV/OCL20To12.cpp b/lib/SPIRV/OCL20To12.cpp
new file mode 100644
index 0000000..ab645ad
--- /dev/null
+++ b/lib/SPIRV/OCL20To12.cpp
@@ -0,0 +1,140 @@
+//===- OCL20To12.cpp - Transform OCL 2.0 builtins to OCL 1.2 builtins -----===//
+//
+// The LLVM/SPIRV Translator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// Copyright (c) 2014 Advanced Micro Devices, Inc. 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 Advanced Micro Devices, Inc., 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements transform OCL 2.0 builtins to OCL 1.2 builtins.
+//
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "ocl20to12"
+
+#include "SPRVInternal.h"
+#include "OCLUtil.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/PassSupport.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace SPRV;
+using namespace OCLUtil;
+
+namespace SPRV {
+class OCL20To12: public ModulePass,
+ public InstVisitor<OCL20To12> {
+public:
+ OCL20To12():ModulePass(ID), M(nullptr), Ctx(nullptr) {
+ initializeOCL20To12Pass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M);
+ virtual void visitCallInst(CallInst &CI);
+
+ /// Transform atomic_work_item_fence to mem_fence.
+ /// atomic_work_item_fence(flag, relaxed, work_group) =>
+ /// mem_fence(flag)
+ void visitCallAtomicWorkItemFence(CallInst *CI);
+
+ static char ID;
+private:
+ Module *M;
+ LLVMContext *Ctx;
+};
+
+char OCL20To12::ID = 0;
+
+bool
+OCL20To12::runOnModule(Module& Module) {
+ M = &Module;
+ if (getOCLVersion(M) >= 20)
+ return false;
+
+ Ctx = &M->getContext();
+ visit(*M);
+
+ DEBUG(dbgs() << "After OCL20To12:\n" << *M);
+
+ std::string Err;
+ raw_string_ostream ErrorOS(Err);
+ if (verifyModule(*M, &ErrorOS)){
+ DEBUG(errs() << "Fails to verify module: " << ErrorOS.str());
+ }
+ return true;
+}
+
+void
+OCL20To12::visitCallInst(CallInst& CI) {
+ DEBUG(dbgs() << "[visistCallInst] " << CI << '\n');
+ auto F = CI.getCalledFunction();
+ if (!F)
+ return;
+
+ auto MangledName = F->getName();
+ std::string DemangledName;
+ if (!oclIsBuiltin(MangledName, 20, &DemangledName))
+ return;
+ DEBUG(dbgs() << "DemangledName = " << DemangledName.c_str() << '\n');
+
+ if (DemangledName == kOCLBuiltinName::AtomicWorkItemFence) {
+ visitCallAtomicWorkItemFence(&CI);
+ return;
+ }
+}
+
+void OCL20To12::visitCallAtomicWorkItemFence(CallInst* CI) {
+ auto Lit = getAtomicWorkItemFenceLiterals(CI);
+ if (std::get<1>(Lit) != OCLLegacyAtomicMemOrder ||
+ std::get<2>(Lit) != OCLLegacyAtomicMemScope)
+ report_fatal_error("OCL 2.0 builtin atomic_work_item_fence used in 1.2",
+ false);
+
+ AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
+ mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ Args.resize(1);
+ Args[0] = getInt32(M, std::get<0>(Lit));
+ return kOCLBuiltinName::MemFence;
+ }, true, &Attrs);
+}
+
+}
+
+INITIALIZE_PASS(OCL20To12, "ocl20to12",
+ "Translate OCL 2.0 builtins to OCL 1.2 builtins", false, false)
+
+ModulePass *llvm::createOCL20To12() {
+ return new OCL20To12();
+}
diff --git a/lib/SPIRV/OCLUtil.cpp b/lib/SPIRV/OCLUtil.cpp
new file mode 100644
index 0000000..f458177
--- /dev/null
+++ b/lib/SPIRV/OCLUtil.cpp
@@ -0,0 +1,114 @@
+//===- OCLUtil.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) 2014 Advanced Micro Devices, Inc. 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 Advanced Micro Devices, Inc., 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements OCL utility functions.
+//
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "oclutil"
+
+#include "SPRVInternal.h"
+#include "OCLUtil.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/PassSupport.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace SPRV;
+
+namespace OCLUtil {
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Functions for getting builtin call info
+//
+///////////////////////////////////////////////////////////////////////////////
+AtomicWorkItemFenceLiterals getAtomicWorkItemFenceLiterals(CallInst* CI) {
+ AtomicWorkItemFenceLiterals Tup;
+ auto getArg = [=](unsigned I){
+ return cast<ConstantInt>(CI->getArgOperand(I))->getZExtValue();
+ };
+ return std::make_tuple(getArg(0),
+ static_cast<OCLMemOrderKind>(getArg(1)),
+ static_cast<OCLMemScopeKind>(getArg(2)));
+}
+
+size_t getAtomicBuiltinNumMemoryOrderArgs(StringRef Name) {
+ if (Name.find("compare_exchange_strong") != StringRef::npos)
+ return 2;
+ return 1;
+}
+///////////////////////////////////////////////////////////////////////////////
+//
+// Functions for getting metadata
+//
+///////////////////////////////////////////////////////////////////////////////
+int
+getMDOperandAsInt(MDNode* N, unsigned I) {
+ return mdconst::dyn_extract<ConstantInt>(N->getOperand(I))->getZExtValue();
+}
+
+std::string
+getMDOperandAsString(MDNode* N, unsigned I) {
+ Metadata* Op = N->getOperand(I);
+
+ if (!Op)
+ return "";
+ if (MDString* Str = dyn_cast<MDString>(Op)) {
+ return Str->getString().str();
+ }
+ return "";
+}
+
+Type*
+getMDOperandAsType(MDNode* N, unsigned I) {
+ return cast<ValueAsMetadata>(N->getOperand(I))->getType();
+}
+
+unsigned getOCLVersion(Module *M) {
+ NamedMDNode *NamedMD = M->getNamedMetadata(SPIR_MD_OCL_VERSION);
+ assert (NamedMD && "Invalid SPIR");
+ assert (NamedMD->getNumOperands() == 1 && "Invalid SPIR");
+ MDNode *MD = NamedMD->getOperand(0);
+ unsigned Major = getMDOperandAsInt(MD, 0);
+ unsigned Minor = getMDOperandAsInt(MD, 1);
+ return Major * 10 + Minor;
+}
+}
+
diff --git a/lib/SPIRV/OCLUtil.h b/lib/SPIRV/OCLUtil.h
new file mode 100644
index 0000000..ee71a86
--- /dev/null
+++ b/lib/SPIRV/OCLUtil.h
@@ -0,0 +1,87 @@
+//===- OCLUtil.h - OCL Utilities declarations -------------------*- C++ -*-===//
+//
+// The LLVM/SPIRV Translator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// Copyright (c) 2014 Advanced Micro Devices, Inc. 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 Advanced Micro Devices, Inc., 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares OCL utility functions.
+//
+//===----------------------------------------------------------------------===//
+#include "SPRVInternal.h"
+
+#include <utility>
+#include <tuple>
+#include <functional>
+using namespace SPRV;
+using namespace llvm;
+
+namespace OCLUtil {
+
+typedef std::tuple<unsigned, OCLMemOrderKind, OCLMemScopeKind>
+ AtomicWorkItemFenceLiterals;
+
+/// Information for translating OCL builtin.
+struct OCLBuiltinTransInfo {
+ std::string UniqName;
+ /// Postprocessor of operands
+ std::function<void(std::vector<Value *>&)> PostProc;
+ OCLBuiltinTransInfo(){
+ PostProc = [](std::vector<Value *>&){};
+ }
+};
+
+/// OCL 1.x atomic memory order when translated to 2.0 atomics.
+const OCLMemOrderKind OCLLegacyAtomicMemOrder = OCLMO_seq_cst;
+
+/// OCL 1.x atomic memory scope when translated to 2.0 atomics.
+const OCLMemScopeKind OCLLegacyAtomicMemScope = OCLMS_device;
+
+/// Get literal arguments of call of atomic_work_item_fence.
+AtomicWorkItemFenceLiterals getAtomicWorkItemFenceLiterals(CallInst* CI);
+
+/// Get number of memory order arguments for atomic builtin function.
+size_t getAtomicBuiltinNumMemoryOrderArgs(StringRef Name);
+
+/// Get metadata operand as int.
+int getMDOperandAsInt(MDNode* N, unsigned I);
+
+/// Get metadata operand as string.
+std::string getMDOperandAsString(MDNode* N, unsigned I);
+
+/// Get metadata operand as type.
+Type* getMDOperandAsType(MDNode* N, unsigned I);
+
+/// Get OCL version from metadata opencl.ocl.version.
+/// \return 20 for OCL 2.0, 12 for OCL 1.2.
+unsigned getOCLVersion(Module *M);
+
+}
+
diff --git a/lib/SPIRV/SPRVInternal.h b/lib/SPIRV/SPRVInternal.h
index 363627d..f08b485 100644
--- a/lib/SPIRV/SPRVInternal.h
+++ b/lib/SPIRV/SPRVInternal.h
@@ -49,6 +49,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/Support/SPIRV.h"
+#include <utility>
#include <functional>
using namespace SPRV;
@@ -177,29 +178,26 @@ enum SPIRAddressSpace {
SPIRAS_Count,
};
-enum SPIRMemFenceFlagKind {
-#define _SPRV_OP(x,y) SPIRMFF_##x = y,
-_SPRV_OP(Local, 1)
-_SPRV_OP(Global, 2)
-_SPRV_OP(Image, 4)
-#undef _SPRV_OP
+enum OCLMemFenceKind {
+ OCLMF_Local = 1,
+ OCLMF_Global = 2,
+ OCLMF_Image = 4,
};
-enum SPIRMemScopeKind {
- SPIRMS_work_item,
- SPIRMS_work_group,
- SPIRMS_device,
- SPIRMS_all_svm_devices,
- SPIRMS_sub_group,
- SPIRMS_Count,
+enum OCLMemScopeKind {
+ OCLMS_work_item,
+ OCLMS_work_group,
+ OCLMS_device,
+ OCLMS_all_svm_devices,
+ OCLMS_sub_group,
};
-enum SPIRMemoryOrderKind {
- SPIRMO_relaxed,
- SPIRMO_acquire,
- SPIRMO_release,
- SPIRMO_acq_rel,
- SPIRMO_seq_cst
+enum OCLMemOrderKind {
+ OCLMO_relaxed,
+ OCLMO_acquire,
+ OCLMO_release,
+ OCLMO_acq_rel,
+ OCLMO_seq_cst
};
template<> inline void
@@ -306,7 +304,6 @@ _SPRV_OP(fetch_max_explicit, AtomicSMax)
_SPRV_OP(fetch_and_explicit, AtomicAnd)
_SPRV_OP(fetch_or_explicit, AtomicOr)
_SPRV_OP(fetch_xor_explicit, AtomicXor)
-_SPRV_OP(work_item_fence, MemoryBarrier)
#undef _SPRV_OP
#define _SPRV_OP(x,y) add(#x, Op##y);
_SPRV_OP(dot, Dot)
@@ -392,7 +389,7 @@ _SPRV_OP(get_image_num_samples, ImageQuerySamples)
#undef _SPRV_OP
}
typedef SPRVMap<std::string, Op, SPRVInstruction>
- SPIRSPRVBuiltinInstMap;
+ OCLSPRVBuiltinMap;
template<> inline void
SPRVMap<GlobalValue::LinkageTypes, SPRVLinkageTypeKind>::init() {
@@ -435,28 +432,52 @@ typedef SPRVMap<Attribute::AttrKind, SPRVFunctionControlMaskKind>
SPIRSPRVFuncCtlMaskMap;
template<> inline void
-SPRVMap<SPIRMemFenceFlagKind, SPRVMemorySemanticsMaskKind>::init() {
-#define _SPRV_OP(x,y) add(SPIRMFF_##x, SPRVMSM_##y);
-_SPRV_OP(Local, WorkgroupLocalMemory)
-_SPRV_OP(Global, WorkgroupGlobalMemory)
-_SPRV_OP(Image, ImageMemory)
-#undef _SPRV_OP
+SPRVMap<OCLMemFenceKind, MemorySemanticsMask>::init() {
+ add(OCLMF_Local, MemorySemanticsWorkgroupLocalMemoryMask);
+ add(OCLMF_Global, MemorySemanticsWorkgroupGlobalMemoryMask);
+ add(OCLMF_Image, MemorySemanticsImageMemoryMask);
}
-typedef SPRVMap<SPIRMemFenceFlagKind, SPRVMemorySemanticsMaskKind>
- SPIRSPRVMemFenceFlagMap;
+typedef SPRVMap<OCLMemFenceKind, MemorySemanticsMask>
+ OCLMemFenceMap;
template<> inline void
-SPRVMap<SPIRMemScopeKind, SPRVMemoryScopeKind>::init() {
-#define _SPRV_OP(x,y) add(SPIRMS_##x, SPRVMS_##y);
- _SPRV_OP(work_item, Invocation)
- _SPRV_OP(work_group, Workgroup)
- _SPRV_OP(device, Device)
- _SPRV_OP(all_svm_devices, CrossDevice)
- _SPRV_OP(sub_group, Subgroup)
-#undef _SPRV_OP
+SPRVMap<OCLMemOrderKind, unsigned, MemorySemanticsMask>::init() {
+ add(OCLMO_relaxed, MemorySemanticsRelaxedMask);
+ add(OCLMO_acquire, MemorySemanticsAcquireMask);
+ add(OCLMO_release, MemorySemanticsReleaseMask);
+ add(OCLMO_acq_rel, MemorySemanticsAcquireMask|MemorySemanticsReleaseMask);
+ add(OCLMO_seq_cst, MemorySemanticsSequentiallyConsistentMask);
+}
+typedef SPRVMap<OCLMemOrderKind, unsigned, MemorySemanticsMask>
+ OCLMemOrderMap;
+
+inline unsigned mapOCLMemSemanticToSPRV(unsigned MemFenceFlag,
+ OCLMemOrderKind Order) {
+ return OCLMemOrderMap::map(Order) |
+ mapBitMask<OCLMemFenceMap>(MemFenceFlag);
+}
+
+inline std::pair<unsigned, OCLMemOrderKind>
+mapSPRVMemSemanticToOCL(unsigned Sema) {
+ return std::make_pair(rmapBitMask<OCLMemFenceMap>(Sema),
+ OCLMemOrderMap::rmap(Sema & 0xF));
+}
+
+inline OCLMemOrderKind
+mapSPRVMemOrderToOCL(unsigned Sema) {
+ return OCLMemOrderMap::rmap(Sema & 0xF);
+}
+
+template<> inline void
+SPRVMap<OCLMemScopeKind, Scope>::init() {
+ add(OCLMS_work_item, ScopeInvocation);
+ add(OCLMS_work_group, ScopeWorkgroup);
+ add(OCLMS_device, ScopeDevice);
+ add(OCLMS_all_svm_devices, ScopeCrossDevice);
+ add(OCLMS_sub_group, ScopeSubgroup);
}
-typedef SPRVMap<SPIRMemScopeKind, SPRVMemoryScopeKind>
- SPIRSPRVMemScopeMap;
+typedef SPRVMap<OCLMemScopeKind, Scope>
+ OCLMemScopeMap;
template<> inline void
SPRVMap<std::string, SPRVGroupOperationKind>::init() {
@@ -539,7 +560,12 @@ namespace kMangledName {
}
namespace kOCLBuiltinName {
+ const static char AtomPrefix[] = "atom_";
+ const static char AtomCmpXchg[] = "atom_cmpxchg";
const static char AtomicPrefix[] = "atomic_";
+ const static char AtomicCmpXchg[] = "atomic_cmpxchg";
+ const static char AtomicInit[] = "atomic_init";
+ const static char AtomicWorkItemFence[] = "atomic_work_item_fence";
const static char Barrier[] = "barrier";
const static char EnqueueKernel[] = "enqueue_kernel";
const static char GetFence[] = "get_fence";
@@ -547,6 +573,7 @@ namespace kOCLBuiltinName {
const static char GetImageDim[] = "get_image_dim";
const static char GetImageHeight[] = "get_image_height";
const static char GetImageWidth[] = "get_image_width";
+ const static char MemFence[] = "mem_fence";
const static char NDRangePrefix[] = "ndrange_";
const static char ToGlobal[] = "to_global";
const static char ToLocal[] = "to_local";
@@ -689,6 +716,31 @@ getTypes(T V) {
return Tys;
}
+/// Move elements of std::vector from [begin, end) to target.
+template <typename T>
+void move(std::vector<T>& V, size_t begin, size_t end, size_t target) {
+ assert(begin < end && end <= V.size() && target <= V.size() &&
+ !(begin < target && target < end));
+ if (begin <= target && target <= end)
+ return;
+ auto B = V.begin() + begin, E = V.begin() + end;
+ if (target > V.size())
+ target = V.size();
+ if (target > end)
+ target -= (end - begin);
+ std::vector<T> Segment(B, E);
+ V.erase(B, E);
+ V.insert(V.begin() + target, Segment.begin(), Segment.end());
+}
+
+/// Find position of first pointer type value in a vector.
+inline size_t findFirstPtr(const std::vector<Value *> &Args) {
+ auto PtArg = std::find_if(Args.begin(), Args.end(), [](Value *V){
+ return V->getType()->isPointerTy();
+ });
+ return PtArg - Args.begin();
+}
+
void removeFnAttr(LLVMContext *Context, CallInst *Call,
Attribute::AttrKind Attr);
void addFnAttr(LLVMContext *Context, CallInst *Call,
@@ -716,6 +768,12 @@ std::string decorateSPRVFunction(const std::string &S);
std::string undecorateSPRVFunction(const std::string &S);
bool isSPRVFunction(const Function *F, std::string *UndecName = nullptr);
+/// Get a canonical function name for a SPIR-V op code.
+std::string getSPRVFuncName(Op OC);
+
+/// Get SPIR-V op code given the canonical function name.
+Op getSPRVFuncOC(const std::string& S);
+
/// \param Name LLVM function name
/// \param OpenCLVer version of OpenCL source file. Suppotred values are 12, 20
/// and 21.
@@ -777,6 +835,14 @@ ConstantInt *getInt64(Module *M, int64_t value);
/// Get a 32 bit integer constant.
ConstantInt *getInt32(Module *M, int value);
+/// Map an unsigned integer constant by applying a function.
+ConstantInt *mapUInt(Module *M, ConstantInt *I,
+ std::function<unsigned(unsigned)> F);
+
+/// Map a signed integer constant by applying a function.
+ConstantInt *mapSInt(Module *M, ConstantInt *I,
+ std::function<int(int)> F);
+
/// Mangle name for OCL builtin functions.
/// \param UniqName is unique unmangled name for OCL builtin functions,
/// which is transformed and unique version of original unmangled
@@ -815,16 +881,28 @@ getSPRVSampledImageType(Module *M, Type *ImageType);
bool
eraseUselessFunctions(Module *M);
+// Check if a mangled type name is unsigned
+bool
+isMangledTypeUnsigned(char Mangled);
+
+// Check if a mangled function name contains unsigned atomic type
+bool
+containsUnsignedAtomicType(StringRef Name);
+
}
namespace llvm {
void initializeSPRVRegularizeOCL20Pass(PassRegistry&);
void initializeSPRVLowerOCLBlocksPass(PassRegistry&);
void initializeSPRVLowerBoolPass(PassRegistry&);
+void initializeSPRVToOCL20Pass(PassRegistry&);
+void initializeOCL20To12Pass(PassRegistry&);
ModulePass *createSPRVRegularizeOCL20();
ModulePass *createSPRVLowerOCLBlocks();
ModulePass *createSPRVLowerBool();
+ModulePass *createSPRVToOCL20();
+ModulePass *createOCL20To12();
}
#endif
diff --git a/lib/SPIRV/SPRVReader.cpp b/lib/SPIRV/SPRVReader.cpp
index f71afba..33b1dde 100644
--- a/lib/SPIRV/SPRVReader.cpp
+++ b/lib/SPIRV/SPRVReader.cpp
@@ -56,6 +56,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
+#include "llvm/PassManager.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
@@ -288,9 +289,10 @@ public:
bool transSourceExtension();
bool transCompilerOption();
Value *transConvertInst(SPRVValue* BV, Function* F, BasicBlock* BB);
- Instruction *transOCLBuiltinFromInst(const std::string& FuncName,
+ Instruction *transBuiltinFromInst(const std::string& FuncName,
SPRVInstruction* BI, BasicBlock* BB);
Instruction *transOCLBuiltinFromInst(SPRVInstruction *BI, BasicBlock *BB);
+ Instruction *transSPRVBuiltinFromInst(SPRVInstruction *BI, BasicBlock *BB);
Instruction *transOCLBarrierFence(SPRVInstruction* BI, BasicBlock *BB);
Instruction *transOCLDot(SPRVDot *BD, BasicBlock *BB);
void transOCLVectorLoadStore(std::string& UnmangledName,
@@ -619,10 +621,10 @@ SPRVToLLVM::transOCLGroupBuiltinName(std::string &DemangledName,
auto ES = IT->getExecutionScope();
std::string Prefix;
switch(ES) {
- case SPRVES_Workgroup:
+ case ScopeWorkgroup:
Prefix = kOCLBuiltinName::WorkPrefix;
break;
- case SPRVES_Subgroup:
+ case ScopeSubgroup:
Prefix = kOCLBuiltinName::SubPrefix;
break;
default:
@@ -1555,22 +1557,28 @@ SPRVToLLVM::transValueWithoutDecoration(SPRVValue *BV, Function *F,
}
break;
- default:
- if (isSPRVCmpInstTransToLLVMInst(static_cast<SPRVInstruction*>(BV))) {
- return mapValue(BV, transCmpInst(BV, BB, F));
- } else if (SPIRSPRVBuiltinInstMap::rfind(BV->getOpCode(), nullptr)) {
- return mapValue(BV, transOCLBuiltinFromInst(
- static_cast<SPRVInstruction *>(BV), BB));
- } else if (isBinaryShiftLogicalBitwiseOpCode(BV->getOpCode())) {
- return mapValue(BV, transShiftLogicalBitwiseInst(BV, BB, F));
- } else if (isCvtOpCode(BV->getOpCode())) {
- auto BI = static_cast<SPRVInstruction *>(BV);
- Value *Inst = nullptr;
- if (BI->hasFPRoundingMode() || BI->isSaturatedConversion())
- Inst = transOCLBuiltinFromInst(BI, BB);
- else
- Inst = transConvertInst(BV, F, BB);
- return mapValue(BV, Inst);
+ default: {
+ auto OC = BV->getOpCode();
+ if (isSPRVCmpInstTransToLLVMInst(static_cast<SPRVInstruction*>(BV))) {
+ return mapValue(BV, transCmpInst(BV, BB, F));
+ } else if (OCLSPRVBuiltinMap::rfind(OC, nullptr) &&
+ !isAtomicOpCode(OC)) {
+ return mapValue(BV, transOCLBuiltinFromInst(
+ static_cast<SPRVInstruction *>(BV), BB));
+ } else if (isBinaryShiftLogicalBitwiseOpCode(OC) ||
+ isLogicalOpCode(OC)) {
+ return mapValue(BV, transShiftLogicalBitwiseInst(BV, BB, F));
+ } else if (isCvtOpCode(OC)) {
+ auto BI = static_cast<SPRVInstruction *>(BV);
+ Value *Inst = nullptr;
+ if (BI->hasFPRoundingMode() || BI->isSaturatedConversion())
+ Inst = transOCLBuiltinFromInst(BI, BB);
+ else
+ Inst = transConvertInst(BV, F, BB);
+ return mapValue(BV, Inst);
+ }
+ return mapValue(BV, transSPRVBuiltinFromInst(
+ static_cast<SPRVInstruction *>(BV), BB));
}
SPRVDBG(bildbgs() << "Cannot translate " << *BV << '\n';)
@@ -1674,9 +1682,6 @@ SPRVToLLVM::transOCLBuiltinFromInstPreproc(SPRVInstruction* BI, Type *&RetTy,
BT->getVectorComponentCount());
else
llvm_unreachable("invalid compare instruction");
- } else if (OC == OpAtomicIIncrement ||
- OC == OpAtomicIDecrement) {
- Args.erase(Args.begin() + Args.size() - 2, Args.end());
}
}
@@ -1700,7 +1705,7 @@ SPRVToLLVM::transOCLBuiltinFromInstPostproc(SPRVInstruction* BI,
}
Instruction *
-SPRVToLLVM::transOCLBuiltinFromInst(const std::string& FuncName,
+SPRVToLLVM::transBuiltinFromInst(const std::string& FuncName,
SPRVInstruction* BI, BasicBlock* BB) {
std::string MangledName;
auto Ops = BI->getOperands();
@@ -1771,7 +1776,7 @@ SPRVToLLVM::getOCLBuiltinName(SPRVInstruction* BI) {
// Do nothing.
break;
}
- auto Name = SPIRSPRVBuiltinInstMap::rmap(OC);
+ auto Name = OCLSPRVBuiltinMap::rmap(OC);
transOCLGroupBuiltinName(Name, BI);
SPRVType *T = nullptr;
@@ -1798,7 +1803,13 @@ Instruction *
SPRVToLLVM::transOCLBuiltinFromInst(SPRVInstruction *BI, BasicBlock *BB) {
assert(BB && "Invalid BB");
auto FuncName = getOCLBuiltinName(BI);
- return transOCLBuiltinFromInst(FuncName, BI, BB);
+ return transBuiltinFromInst(FuncName, BI, BB);
+}
+
+Instruction *
+SPRVToLLVM::transSPRVBuiltinFromInst(SPRVInstruction *BI, BasicBlock *BB) {
+ assert(BB && "Invalid BB");
+ return transBuiltinFromInst(getSPRVFuncName(BI->getOpCode()), BI, BB);
}
bool
@@ -2173,7 +2184,7 @@ SPRVToLLVM::transOCLBarrierFence(SPRVInstruction* MB, BasicBlock *BB) {
Func->addFnAttr(Attribute::NoUnwind);
}
Value *Arg[] = {ConstantInt::get(Int32Ty,
- rmapBitMask<SPIRSPRVMemFenceFlagMap>(MemSema))};
+ rmapBitMask<OCLMemFenceMap>(MemSema))};
auto Call = CallInst::Create(Func, Arg, "", BB);
Call->setName(MB->getName());
setAttrByCalledFunc(Call);
@@ -2290,6 +2301,11 @@ llvm::ReadSPRV(LLVMContext &C, std::istream &IS, Module *&M,
BM->getError(ErrMsg);
Succeed = false;
}
+ PassManager PassMgr;
+ PassMgr.add(createSPRVToOCL20());
+ PassMgr.add(createOCL20To12());
+ PassMgr.run(*M);
+
if (DbgSaveTmpLLVM)
dumpLLVM(M, DbgTmpLLVMFileName);
if (!Succeed) {
diff --git a/lib/SPIRV/SPRVRegularizeOCL20.cpp b/lib/SPIRV/SPRVRegularizeOCL20.cpp
index 641be16..0c74ef9 100644
--- a/lib/SPIRV/SPRVRegularizeOCL20.cpp
+++ b/lib/SPIRV/SPRVRegularizeOCL20.cpp
@@ -1,4 +1,4 @@
-//===- LLVMSPRVRegularizeOCL20.cpp – Regularize OCL20 builtins---*- C++ -*-===//
+//===- SPRVRegularizeOCL20.cpp - Regularize OCL20 builtins-------*- C++ -*-===//
//
// The LLVM/SPIRV Translator
//
@@ -38,6 +38,7 @@
#define DEBUG_TYPE "spvcl20"
#include "SPRVInternal.h"
+#include "OCLUtil.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instructions.h"
@@ -50,8 +51,19 @@
using namespace llvm;
using namespace SPRV;
+using namespace OCLUtil;
namespace SPRV {
+static size_t
+getOCLCpp11AtomicMaxNumOps(StringRef Name) {
+ return StringSwitch<size_t>(Name)
+ .Cases("load", "flag_test_and_set", "flag_clear", 3)
+ .Cases("store", "exchange", 4)
+ .StartsWith("compare_exchange", 6)
+ .StartsWith("fetch", 4)
+ .Default(0);
+}
+
class SPRVRegularizeOCL20: public ModulePass,
public InstVisitor<SPRVRegularizeOCL20> {
public:
@@ -61,32 +73,64 @@ public:
virtual void getAnalysisUsage(AnalysisUsage &AU);
virtual bool runOnModule(Module &M);
virtual void visitCallInst(CallInst &CI);
- void visitCallGetFence(CallInst *CI, const std::string &DemangledName);
- void visitCallNDRange(CallInst *CI, const std::string &DemangledName);
+
+ /// Transform atomic_work_item_fence/mem_fence to __spirv_MemoryBarrier.
+ /// func(flag, order, scope) =>
+ /// __spirv_MemoryBarrier(map(scope), map(flag)|map(order))
+ void transMemoryBarrier(CallInst *CI, AtomicWorkItemFenceLiterals);
+
+ /// Transform atomic_* to __spirv_Atomic*.
+ /// atomic_x(ptr_arg, args, order, scope) =>
+ /// __spirv_AtomicY(ptr_arg, map(order), map(scope), args)
+ void transAtomicBuiltin(CallInst *CI, OCLBuiltinTransInfo &Info);
+
+ /// Transform atomic_work_item_fence to __spirv_MemoryBarrier.
+ /// atomic_work_item_fence(flag, order, scope) =>
+ /// __spirv_MemoryBarrier(map(scope), map(flag)|map(order))
+ void visitCallAtomicWorkItemFence(CallInst *CI);
/// Transform atom_cmpxchg/atomic_cmpxchg to atomic_compare_exchange.
/// In atom_cmpxchg/atomic_cmpxchg, the expected value parameter is a value.
/// However in atomic_compare_exchange it is a pointer. The transformation
/// adds an alloca instruction, store the expected value in the pointer, and
/// pass the pointer as argument.
- void visitCallAtomicCmpXchg(CallInst *CI, const std::string &DemangledName);
+ /// \returns the call instruction of atomic_compare_exchange_strong.
+ CallInst *visitCallAtomicCmpXchg(CallInst *CI, const std::string &DemangledName);
/// Transform atomic_init.
/// atomic_init(p, x) => store p, x
void visitCallAtomicInit(CallInst *CI);
- /// Transform read_image with sampler arguments.
- /// read_image(image, sampler, ...) =>
- /// sampled_image = __spirv_SampledImage__(image, sampler);
- /// return __spirv_ImageSampleExplicitLod__(sampled_image, ...);
- void visitCallReadImage(CallInst *CI, StringRef MangledName,
- const std::string &DemangledName);
+ /// Transform legacy OCL 1.x atomic builtins to SPIR-V builtins for extensions
+ /// cl_khr_int64_base_atomics
+ /// cl_khr_int64_extended_atomics
+ /// Do nothing if the called function is not a legacy atomic builtin.
+ void visitCallAtomicLegacy(CallInst *CI, StringRef MangledName,
+ const std::string &DemangledName);
+
+ /// Transform OCL 2.0 C++11 atomic builtins to SPIR-V builtins.
+ /// Do nothing if the called function is not a C++11 atomic builtin.
+ void visitCallAtomicCpp11(CallInst *CI, StringRef MangledName,
+ const std::string &DemangledName);
/// Transform get_image_{width|height|depth|dim}.
/// get_image_xxx(...) =>
/// dimension = __spirv_ImageQuerySizeLod__(...);
/// return dimension.{x|y|z};
void visitCallGetImageSize(CallInst *CI, StringRef MangledName,
+ const std::string &DemangledName);
+
+ /// Transform mem_fence to __spirv_MemoryBarrier.
+ /// mem_fence(flag) => __spirv_MemoryBarrier(Workgroup, map(flag))
+ void visitCallMemFence(CallInst *CI);
+
+ void visitCallNDRange(CallInst *CI, const std::string &DemangledName);
+
+ /// Transform read_image with sampler arguments.
+ /// read_image(image, sampler, ...) =>
+ /// sampled_image = __spirv_SampledImage__(image, sampler);
+ /// return __spirv_ImageSampleExplicitLod__(sampled_image, ...);
+ void visitCallReadImage(CallInst *CI, StringRef MangledName,
const std::string &DemangledName);
void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I){
@@ -97,6 +141,11 @@ public:
private:
Module *M;
LLVMContext *Ctx;
+
+ ConstantInt *addInt32(int I) {
+ return getInt32(M, I);
+ }
+
};
char SPRVRegularizeOCL20::ID = 0;
@@ -116,7 +165,7 @@ SPRVRegularizeOCL20::runOnModule(Module& Module) {
std::string Err;
raw_string_ostream ErrorOS(Err);
if (verifyModule(*M, &ErrorOS)){
- DEBUG(errs() << "Fails to verify module: " << Err);
+ DEBUG(errs() << "Fails to verify module: " << ErrorOS.str());
}
return true;
}
@@ -137,13 +186,23 @@ SPRVRegularizeOCL20::visitCallInst(CallInst& CI) {
visitCallNDRange(&CI, DemangledName);
return;
}
- if (DemangledName == "atom_cmpxchg" ||
- DemangledName == "atomic_cmpxchg") {
- visitCallAtomicCmpXchg(&CI, DemangledName);
- return;
- }
- if (DemangledName == "atomic_init") {
- visitCallAtomicInit(&CI);
+ if (DemangledName.find(kOCLBuiltinName::AtomicPrefix) == 0 ||
+ DemangledName.find(kOCLBuiltinName::AtomPrefix) == 0) {
+ auto PCI = &CI;
+ if (DemangledName == kOCLBuiltinName::AtomicInit) {
+ visitCallAtomicInit(PCI);
+ return;
+ }
+ if (DemangledName == kOCLBuiltinName::AtomicWorkItemFence) {
+ visitCallAtomicWorkItemFence(PCI);
+ return;
+ }
+ if (DemangledName == kOCLBuiltinName::AtomCmpXchg ||
+ DemangledName == kOCLBuiltinName::AtomicCmpXchg) {
+ PCI = visitCallAtomicCmpXchg(PCI, DemangledName);
+ }
+ visitCallAtomicLegacy(PCI, MangledName, DemangledName);
+ visitCallAtomicCpp11(PCI, MangledName, DemangledName);
return;
}
if (DemangledName.find(kOCLBuiltinName::ReadImage) == 0) {
@@ -157,6 +216,10 @@ SPRVRegularizeOCL20::visitCallInst(CallInst& CI) {
visitCallGetImageSize(&CI, MangledName, DemangledName);
return;
}
+ if (DemangledName == kOCLBuiltinName::MemFence) {
+ visitCallMemFence(&CI);
+ return;
+ }
}
@@ -200,18 +263,28 @@ SPRVRegularizeOCL20::visitCallNDRange(CallInst *CI,
}, true, &Attrs);
}
-void
+CallInst *
SPRVRegularizeOCL20::visitCallAtomicCmpXchg(CallInst* CI,
const std::string& DemangledName) {
AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
- mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ Value *Alloca = nullptr;
+ CallInst *NewCI = nullptr;
+ mutateCallInst(M, CI, [&](CallInst *, std::vector<Value *> &Args,
+ Type *&RetTy){
auto &CmpVal = Args[1];
- auto Alloca = new AllocaInst(CmpVal->getType(), "",
- CI->getParent()->getParent()->front().begin());
+ Alloca = new AllocaInst(CmpVal->getType(), "",
+ CI->getParent()->getParent()->getEntryBlock().getFirstInsertionPt());
auto Store = new StoreInst(CmpVal, Alloca, CI);
CmpVal = Alloca;
+ RetTy = Type::getInt1Ty(*Ctx);
return "atomic_compare_exchange_strong";
- }, true, &Attrs);
+ },
+ [&](CallInst *NCI)->Instruction * {
+ NewCI = NCI;
+ return new LoadInst(Alloca, "", false, NCI->getNextNode());
+ },
+ true, &Attrs);
+ return NewCI;
}
void
@@ -223,6 +296,160 @@ SPRVRegularizeOCL20::visitCallAtomicInit(CallInst* CI) {
}
void
+SPRVRegularizeOCL20::visitCallAtomicWorkItemFence(CallInst* CI) {
+ transMemoryBarrier(CI, getAtomicWorkItemFenceLiterals(CI));
+}
+
+void
+SPRVRegularizeOCL20::visitCallMemFence(CallInst* CI) {
+ transMemoryBarrier(CI, std::make_tuple(
+ cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue(),
+ OCLMO_relaxed,
+ OCLMS_work_group));
+}
+
+void SPRVRegularizeOCL20::transMemoryBarrier(CallInst* CI,
+ AtomicWorkItemFenceLiterals Lit) {
+ AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
+ mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ Args.resize(2);
+ Args[0] = addInt32(map<Scope>(std::get<2>(Lit)));
+ Args[1] = addInt32(mapOCLMemSemanticToSPRV(std::get<0>(Lit),
+ std::get<1>(Lit)));
+ return getSPRVFuncName(OpMemoryBarrier);
+ }, true, &Attrs);
+}
+
+void
+SPRVRegularizeOCL20::visitCallAtomicLegacy(CallInst* CI,
+ StringRef MangledName, const std::string& DemangledName) {
+ StringRef Stem = DemangledName;
+ if (Stem.startswith("atom_"))
+ Stem = Stem.drop_front(strlen("atom_"));
+ else if (Stem.startswith("atomic_"))
+ Stem = Stem.drop_front(strlen("atomic_"));
+ else
+ return;
+
+ std::string Sign;
+ std::string Postfix;
+ std::string Prefix;
+ if (Stem == "add" ||
+ Stem == "sub" ||
+ Stem == "and" ||
+ Stem == "or" ||
+ Stem == "xor" ||
+ Stem == "min" ||
+ Stem == "max") {
+ if ((Stem == "min" || Stem == "max") &&
+ isMangledTypeUnsigned(MangledName.back()))
+ Sign = 'u';
+ Prefix = "fetch_";
+ Postfix = "_explicit";
+ } else if (Stem == "xchg") {
+ Stem = "exchange";
+ Postfix = "_explicit";
+ }
+ else if (Stem == "cmpxchg") {
+ Stem = "compare_exchange_strong";
+ Postfix = "_explicit";
+ }
+ else if (Stem == "inc" ||
+ Stem == "dec") {
+ // do nothing
+ } else
+ return;
+
+ OCLBuiltinTransInfo Info;
+ Info.UniqName = "atomic_" + Prefix + Sign + Stem.str() + Postfix;
+ std::vector<int> PostOps;
+ PostOps.push_back(OCLLegacyAtomicMemOrder);
+ if (Stem.startswith("compare_exchange"))
+ PostOps.push_back(OCLLegacyAtomicMemOrder);
+ PostOps.push_back(OCLLegacyAtomicMemScope);
+
+ Info.PostProc = [=](std::vector<Value *> &Ops){
+ for (auto &I:PostOps){
+ Ops.push_back(addInt32(I));
+ }
+ };
+ transAtomicBuiltin(CI, Info);
+}
+
+void
+SPRVRegularizeOCL20::visitCallAtomicCpp11(CallInst* CI,
+ StringRef MangledName, const std::string& DemangledName) {
+ StringRef Stem = DemangledName;
+ if (Stem.startswith("atomic_"))
+ Stem = Stem.drop_front(strlen("atomic_"));
+ else
+ return;
+
+ std::string NewStem = Stem;
+ std::vector<int> PostOps;
+ if (Stem.startswith("store") ||
+ Stem.startswith("load") ||
+ Stem.startswith("exchange") ||
+ Stem.startswith("compare_exchange") ||
+ Stem.startswith("fetch") ||
+ Stem.startswith("flag")) {
+ if ((Stem.startswith("fetch_min") ||
+ Stem.startswith("fetch_max")) &&
+ containsUnsignedAtomicType(MangledName))
+ NewStem.insert(NewStem.begin() + strlen("fetch_"), 'u');
+
+ if (!Stem.endswith("_explicit")) {
+ NewStem = NewStem + "_explicit";
+ PostOps.push_back(OCLMO_seq_cst);
+ if (Stem.startswith("compare_exchange"))
+ PostOps.push_back(OCLMO_seq_cst);
+ PostOps.push_back(OCLMS_device);
+ } else {
+ auto MaxOps = getOCLCpp11AtomicMaxNumOps(
+ Stem.drop_back(strlen("_explicit")));
+ if (CI->getNumArgOperands() < MaxOps)
+ PostOps.push_back(OCLMS_device);
+ }
+ } else if (Stem == "work_item_fence") {
+ // do nothing
+ } else
+ return;
+
+ OCLBuiltinTransInfo Info;
+ Info.UniqName = std::string("atomic_") + NewStem;
+ Info.PostProc = [=](std::vector<Value *> &Ops){
+ for (auto &I:PostOps){
+ Ops.push_back(addInt32(I));
+ }
+ };
+
+ transAtomicBuiltin(CI, Info);
+}
+
+void
+SPRVRegularizeOCL20::transAtomicBuiltin(CallInst* CI,
+ OCLBuiltinTransInfo& Info) {
+ AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
+ mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ Info.PostProc(Args);
+ auto NumOrder = getAtomicBuiltinNumMemoryOrderArgs(Info.UniqName);
+ auto ScopeIdx = Args.size() - 1;
+ auto OrderIdx = Args.size() - NumOrder - 1;
+ Args[ScopeIdx] = mapUInt(M, cast<ConstantInt>(Args[ScopeIdx]),
+ [](unsigned I){
+ return map<Scope>(static_cast<OCLMemScopeKind>(I));
+ });
+ for (size_t I = 0; I < NumOrder; ++I)
+ Args[OrderIdx + I] = mapUInt(M, cast<ConstantInt>(Args[OrderIdx + I]),
+ [](unsigned Ord) {
+ return mapOCLMemSemanticToSPRV(0, static_cast<OCLMemOrderKind>(Ord));
+ });
+ move(Args, OrderIdx, Args.size(), findFirstPtr(Args) + 1);
+ return getSPRVFuncName(OCLSPRVBuiltinMap::map(Info.UniqName));
+ }, true, &Attrs);
+}
+
+void
SPRVRegularizeOCL20::visitCallReadImage(CallInst* CI,
StringRef MangledName, const std::string& DemangledName) {
if (MangledName.find(kMangledName::Sampler) == StringRef::npos)
diff --git a/lib/SPIRV/SPRVToOCL20.cpp b/lib/SPIRV/SPRVToOCL20.cpp
new file mode 100644
index 0000000..45758ae
--- /dev/null
+++ b/lib/SPIRV/SPRVToOCL20.cpp
@@ -0,0 +1,189 @@
+//===- SPRVToOCL20.cpp - Transform SPIR-V builtins to OCL20 builtins-------===//
+//
+// The LLVM/SPIRV Translator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// Copyright (c) 2014 Advanced Micro Devices, Inc. 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 Advanced Micro Devices, Inc., 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements transform SPIR-V builtins to OCL 2.0 builtins.
+//
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "spvtocl20"
+
+#include "SPRVInternal.h"
+#include "OCLUtil.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/PassSupport.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace SPRV;
+using namespace OCLUtil;
+
+namespace SPRV {
+class SPRVToOCL20: public ModulePass,
+ public InstVisitor<SPRVToOCL20> {
+public:
+ SPRVToOCL20():ModulePass(ID), M(nullptr), Ctx(nullptr) {
+ initializeSPRVToOCL20Pass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M);
+ virtual void visitCallInst(CallInst &CI);
+
+ /// Transform __spirv_MemoryBarrier to atomic_work_item_fence.
+ /// __spirv_MemoryBarrier(scope, sema) =>
+ /// atomic_work_item_fence(flag(sema), order(sema), map(scope))
+ void visitCallSPRVMemoryBarrier(CallInst *CI);
+
+ /// Transform __spirv_Atomic* to atomic_*.
+ /// __spirv_Atomic*(atomic_op, scope, sema, ops, ...) =>
+ /// atomic_*(atomic_op, ops, ..., order(sema), map(scope))
+ void visitCallSPRVAtomicBuiltin(CallInst *CI, Op OC);
+
+ /// Transform __spirv_* builtins to OCL 2.0 builtins.
+ /// No change with arguments.
+ void visitCallSPRVBuiltin(CallInst *CI, Op OC);
+
+ static char ID;
+private:
+ Module *M;
+ LLVMContext *Ctx;
+};
+
+char SPRVToOCL20::ID = 0;
+
+bool
+SPRVToOCL20::runOnModule(Module& Module) {
+ M = &Module;
+ Ctx = &M->getContext();
+ visit(*M);
+
+ DEBUG(dbgs() << "After SPRVToOCL20:\n" << *M);
+
+ std::string Err;
+ raw_string_ostream ErrorOS(Err);
+ if (verifyModule(*M, &ErrorOS)){
+ DEBUG(errs() << "Fails to verify module: " << ErrorOS.str());
+ }
+ return true;
+}
+
+void
+SPRVToOCL20::visitCallInst(CallInst& CI) {
+ DEBUG(dbgs() << "[visistCallInst] " << CI << '\n');
+ auto F = CI.getCalledFunction();
+ if (!F)
+ return;
+
+ auto MangledName = F->getName();
+ std::string DemangledName;
+ Op OC = OpNop;
+ if (!oclIsBuiltin(MangledName, 20, &DemangledName) ||
+ (OC = getSPRVFuncOC(DemangledName)) == OpNop)
+ return;
+ DEBUG(dbgs() << "DemangledName = " << DemangledName.c_str() << '\n'
+ << "OpCode = " << OC << '\n');
+
+ if (OC == OpMemoryBarrier) {
+ visitCallSPRVMemoryBarrier(&CI);
+ return;
+ }
+ if (isAtomicOpCode(OC)) {
+ visitCallSPRVAtomicBuiltin(&CI, OC);
+ return;
+ }
+ visitCallSPRVBuiltin(&CI, OC);
+
+}
+
+void SPRVToOCL20::visitCallSPRVMemoryBarrier(CallInst* CI) {
+ AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
+ mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ auto getArg = [=](unsigned I){
+ return cast<ConstantInt>(Args[I])->getZExtValue();
+ };
+ auto MScope = static_cast<Scope>(getArg(0));
+ auto Sema = mapSPRVMemSemanticToOCL(getArg(1));
+ Args.resize(3);
+ Args[0] = getInt32(M, Sema.first);
+ Args[1] = getInt32(M, Sema.second);
+ Args[2] = getInt32(M, rmap<OCLMemScopeKind>(MScope));
+ return kOCLBuiltinName::AtomicWorkItemFence;
+ }, true, &Attrs);
+}
+
+void SPRVToOCL20::visitCallSPRVAtomicBuiltin(CallInst* CI, Op OC) {
+ AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
+ mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ auto Ptr = findFirstPtr(Args);
+ auto Name = OCLSPRVBuiltinMap::rmap(OC);
+ auto NumOrder = getAtomicBuiltinNumMemoryOrderArgs(Name);
+ auto OrderIdx = Ptr + 1;
+ auto ScopeIdx = Ptr + 1 + NumOrder;
+ if (OC == OpAtomicIIncrement ||
+ OC == OpAtomicIDecrement) {
+ Args.erase(Args.begin() + OrderIdx, Args.begin() + ScopeIdx + 1);
+ } else {
+ Args[ScopeIdx] = mapUInt(M, cast<ConstantInt>(Args[ScopeIdx]),
+ [](unsigned I){
+ return rmap<OCLMemScopeKind>(static_cast<Scope>(I));
+ });
+ for (size_t I = 0; I < NumOrder; ++I)
+ Args[OrderIdx + I] = mapUInt(M, cast<ConstantInt>(Args[OrderIdx + I]),
+ [](unsigned Ord) {
+ return mapSPRVMemOrderToOCL(Ord);
+ });
+ move(Args, OrderIdx, ScopeIdx + 1, Args.size());
+ }
+ return Name;
+ }, true, &Attrs);
+}
+
+void SPRVToOCL20::visitCallSPRVBuiltin(CallInst* CI, Op OC) {
+ AttributeSet Attrs = CI->getCalledFunction()->getAttributes();
+ mutateCallInst(M, CI, [=](CallInst *, std::vector<Value *> &Args){
+ return OCLSPRVBuiltinMap::rmap(OC);
+ }, true, &Attrs);
+}
+
+}
+
+INITIALIZE_PASS(SPRVToOCL20, "spvtoocl20",
+ "Translate SPIR-V builtins to OCL 2.0 builtins", false, false)
+
+ModulePass *llvm::createSPRVToOCL20() {
+ return new SPRVToOCL20();
+}
diff --git a/lib/SPIRV/SPRVUtil.cpp b/lib/SPIRV/SPRVUtil.cpp
index 9bd4de1..b8770c9 100644
--- a/lib/SPIRV/SPRVUtil.cpp
+++ b/lib/SPIRV/SPRVUtil.cpp
@@ -291,6 +291,29 @@ undecorateSPRVFunction(const std::string& S) {
return S.substr(Start, End - Start);
}
+std::string
+prefixSPRVFunction(const std::string &S) {
+ return std::string(kSPRVName::Prefix) + S;
+}
+
+std::string
+dePrefixSPRVFunction(const std::string& S) {
+ StringRef R(S);
+ const size_t Start = strlen(kSPRVName::Prefix);
+ return R.startswith(kSPRVName::Prefix) ? R.drop_front(Start).str() : S;
+}
+
+std::string
+getSPRVFuncName(Op OC) {
+ return prefixSPRVFunction(getName(OC));
+}
+
+Op
+getSPRVFuncOC(const std::string& S) {
+ Op OC;
+ return getByName(dePrefixSPRVFunction(S), OC) ? OC : OpNop;
+}
+
bool oclIsBuiltin(const StringRef &Name, unsigned SrcLangVer,
std::string *DemangledName) {
if (!Name.startswith("_Z"))
@@ -323,6 +346,24 @@ bool oclIsBuiltin(const StringRef &Name, unsigned SrcLangVer,
return true;
}
+// Check if a mangled type name is unsigned
+bool
+isMangledTypeUnsigned(char Mangled) {
+ return Mangled == 'h' /* uchar */
+ || Mangled == 't' /* ushort */
+ || Mangled == 'j' /* uint */
+ || Mangled == 'm' /* ulong */;
+}
+
+// Check if a mangled function name contains unsigned atomic type
+bool
+containsUnsignedAtomicType(StringRef Name) {
+ auto Loc = Name.find(kMangledName::AtomicPrefix);
+ if (Loc == StringRef::npos)
+ return false;
+ return isMangledTypeUnsigned(Name[Loc + strlen(kMangledName::AtomicPrefix)]);
+}
+
bool
isFunctionPointerType(Type *T) {
if (isa<PointerType>(T) &&
@@ -461,6 +502,16 @@ getInt32(Module *M, int value) {
return ConstantInt::get(Type::getInt32Ty(M->getContext()), value, true);
}
+ConstantInt *mapUInt(Module *M, ConstantInt *I,
+ std::function<unsigned(unsigned)> F) {
+ return ConstantInt::get(I->getType(), F(I->getZExtValue()), false);
+}
+
+ConstantInt *mapSInt(Module *M, ConstantInt *I,
+ std::function<int(int)> F) {
+ return ConstantInt::get(I->getType(), F(I->getSExtValue()), true);
+}
+
bool
isSPRVFunction(const Function *F, std::string *UndecoratedName) {
if (!F->hasName() || !F->getName().startswith(kSPRVName::Prefix))
@@ -896,5 +947,6 @@ eraseUselessFunctions(Module *M) {
return changed;
}
+
}
diff --git a/lib/SPIRV/SPRVWriter.cpp b/lib/SPIRV/SPRVWriter.cpp
index 91d5bc0..d5e5fb8 100644
--- a/lib/SPIRV/SPRVWriter.cpp
+++ b/lib/SPIRV/SPRVWriter.cpp
@@ -49,6 +49,7 @@
#include "SPRVExtInst.h"
#include "SPRVUtil.h"
#include "SPRVInternal.h"
+#include "OCLUtil.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
@@ -63,8 +64,8 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
-#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
+#include "llvm/PassManager.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -83,32 +84,12 @@
using namespace llvm;
using namespace SPRV;
+using namespace OCLUtil;
namespace SPRV{
bool SPRVDbgSaveRegularizedModule = false;
-static int
-getMDOperandAsInt(MDNode* N, unsigned I) {
- auto *C = dyn_cast_or_null<ConstantAsMetadata>(N->getOperand(I));
- return C->getValue()->getUniqueInteger().getZExtValue();
-}
-
-static std::string
-getMDOperandAsString(MDNode* N, unsigned I) {
- Metadata* Op = N->getOperand(I);
- if (!Op)
- return "";
- if (MDString* Str = dyn_cast<MDString>(Op)) {
- return Str->getString().str();
- } else
- return "";
-}
-
-static Type*
-getMDOperandAsType(MDNode* N, unsigned I) {
- return dyn_cast<ValueAsMetadata>(N->getOperand(I))->getType();
-}
static void
decodeMDNode(MDNode* N, unsigned& X, unsigned& Y, unsigned& Z) {
@@ -149,11 +130,11 @@ foreachKernelArgMD(MDNode *MD, SPRVFunction *BF,
}
/// Information for translating OCL builtin.
-struct OCLBuiltinTransInfo {
+struct OCLBuiltinSPRVTransInfo {
std::string UniqName;
/// Postprocessor of operands
std::function<void(std::vector<SPRVWord>&)> PostProc;
- OCLBuiltinTransInfo(){
+ OCLBuiltinSPRVTransInfo(){
PostProc = [](std::vector<SPRVWord>&){};
}
};
@@ -292,7 +273,6 @@ private:
bool isFuncParamSigned(const std::string& MangledName);
void eraseSubstitutionFromMangledName(std::string& MangledName);
- bool isMangledTypeUnsigned(char Mangled);
SPRVInstruction* transBinaryInst(BinaryOperator* B, SPRVBasicBlock* BB);
SPRVInstruction* transCmpInst(CmpInst* Cmp, SPRVBasicBlock* BB);
void mutateFunctionType(const std::map<unsigned, Type*>& ChangedType,
@@ -325,25 +305,11 @@ private:
const std::string &MangledName,
const std::string &DeMangledName, SPRVBasicBlock *BB);
- /// Transform OCL legacy atomic builtin functions for extensions:
- /// cl_khr_int64_base_atomics
- /// cl_khr_int64_extended_atomics
- /// \return true if the called function is a legacy atomic builtin.
- bool getOCLLegacyAtomicTransInfo(OCLBuiltinTransInfo &Info, CallInst *CI,
- const std::string &MangledName, const std::string &DeMangledName);
-
- /// Transform OCL C++11 atomic builtin functions.
- /// \return true if the called function is a C++11 atomic builtin.
- bool getOCLCpp11AtomicTransInfo(OCLBuiltinTransInfo &Info, CallInst *CI,
- const std::string &MangledName, const std::string &DeMangledName);
-
- bool getOCLImageBuiltinTransInfo(OCLBuiltinTransInfo &Info, CallInst *CI,
+ bool getOCLImageBuiltinTransInfo(OCLBuiltinSPRVTransInfo &Info, CallInst *CI,
const std::string &DeMangledName);
SPRVValue *oclTransBarrier(CallInst *Call,
const std::string &DeMangledName, SPRVBasicBlock *BB);
- SPRVValue *oclTransMemFence(CallInst *Call,
- const std::string &DeMangledName, SPRVBasicBlock *BB);
SPRVValue *oclTransWorkGroupBarrier(CallInst *Call,
const std::string &DeMangledName, SPRVBasicBlock *BB);
SPRVValue *transOCLBuiltinToInst(CallInst *Call,
@@ -366,15 +332,15 @@ private:
Function* F);
bool oclIsSamplerType(llvm::Type* RT);
- void getOCLBuiltinTransInfo(OCLBuiltinTransInfo &Info, CallInst *CI,
+ void getOCLBuiltinSPRVTransInfo(OCLBuiltinSPRVTransInfo &Info, CallInst *CI,
const std::string &MangledName, const std::string &DemangledName);
// Transform OpenCL group builtin function names from work_group_
// and sub_group_ to group_.
- bool getOCLGroupBuiltinTransInfo(OCLBuiltinTransInfo &Info, CallInst *CI,
+ bool getOCLGroupBuiltinTransInfo(OCLBuiltinSPRVTransInfo &Info, CallInst *CI,
const std::string &DemangledName);
// Transform OpenCL read_pipe/write_pipe builtin function names
// with reserve_id argument to reserved_read_pipe/reserved_write_pipe.
- bool getOCLPipeBuiltinTransInfo(OCLBuiltinTransInfo &Info, CallInst *CI,
+ bool getOCLPipeBuiltinTransInfo(OCLBuiltinSPRVTransInfo &Info, CallInst *CI,
const std::string &DemangledName);
SPRVValue *transSpcvCast(CallInst* CI, SPRVBasicBlock *BB);
SPRVValue *oclTransSpvcCastSampler(CallInst* CI, SPRVBasicBlock *BB);
@@ -423,7 +389,6 @@ LLVMToSPRV::oclIsBuiltinTransToInst(Function *F) {
SourceLanguage SourceLang = BM->getSourceLanguage(nullptr);
if (SourceLang == SourceLanguageOpenCL) {
return DemangledName == "barrier" ||
- DemangledName == "mem_fence" ||
DemangledName == "dot" ||
DemangledName.find("convert_") == 0 ||
DemangledName.find("atomic_") == 0 ||
@@ -431,7 +396,8 @@ LLVMToSPRV::oclIsBuiltinTransToInst(Function *F) {
DemangledName == "wait_group_events" ||
DemangledName.find("work_group_") == 0 ||
DemangledName.find("sub_group_") == 0 ||
- SPIRSPRVBuiltinInstMap::find(DemangledName);
+ getSPRVFuncOC(DemangledName) != OpNop ||
+ OCLSPRVBuiltinMap::find(DemangledName);
}
llvm_unreachable("not supported");
return false;
@@ -940,7 +906,7 @@ LLVMToSPRV::transCmpInst(CmpInst* Cmp, SPRVBasicBlock* BB) {
}
bool
-LLVMToSPRV::getOCLPipeBuiltinTransInfo(OCLBuiltinTransInfo &Info,
+LLVMToSPRV::getOCLPipeBuiltinTransInfo(OCLBuiltinSPRVTransInfo &Info,
CallInst *CI, const std::string &DemangledName) {
std::string NewName = DemangledName;
if (DemangledName.find(kOCLBuiltinName::ReadPipe) != 0 &&
@@ -956,7 +922,7 @@ LLVMToSPRV::getOCLPipeBuiltinTransInfo(OCLBuiltinTransInfo &Info,
// ToDo: Handle unsigned integer texel type
bool
-LLVMToSPRV::getOCLImageBuiltinTransInfo(OCLBuiltinTransInfo &Info,
+LLVMToSPRV::getOCLImageBuiltinTransInfo(OCLBuiltinSPRVTransInfo &Info,
CallInst *CI, const std::string &DemangledName) {
std::string NewName = DemangledName;
if (DemangledName.find(kOCLBuiltinName::ReadImage) == 0) {
@@ -972,7 +938,7 @@ LLVMToSPRV::getOCLImageBuiltinTransInfo(OCLBuiltinTransInfo &Info,
}
bool
-LLVMToSPRV::getOCLGroupBuiltinTransInfo(OCLBuiltinTransInfo &Info,
+LLVMToSPRV::getOCLGroupBuiltinTransInfo(OCLBuiltinSPRVTransInfo &Info,
CallInst *CI, const std::string &OrigDemangledName) {
auto F = CI->getCalledFunction();
std::vector<SPRVWord> PreOps;
@@ -981,10 +947,10 @@ LLVMToSPRV::getOCLGroupBuiltinTransInfo(OCLBuiltinTransInfo &Info,
return false;
if (DemangledName.find(kOCLBuiltinName::WorkGroupPrefix) == 0) {
DemangledName.erase(0, strlen(kOCLBuiltinName::WorkPrefix));
- PreOps.push_back(SPRVES_Workgroup);
+ PreOps.push_back(ScopeWorkgroup);
} else if (DemangledName.find(kOCLBuiltinName::SubGroupPrefix) == 0) {
DemangledName.erase(0, strlen(kOCLBuiltinName::SubPrefix));
- PreOps.push_back(SPRVES_Subgroup);
+ PreOps.push_back(ScopeSubgroup);
} else
return false;
@@ -1024,137 +990,11 @@ LLVMToSPRV::getOCLGroupBuiltinTransInfo(OCLBuiltinTransInfo &Info,
return true;
}
-bool
-LLVMToSPRV::getOCLLegacyAtomicTransInfo(OCLBuiltinTransInfo &Info,
- CallInst *CI, const std::string &MangledName,
- const std::string &DemangledName) {
- StringRef Stem = DemangledName;
- if (Stem.startswith("atom_"))
- Stem = Stem.drop_front(strlen("atom_"));
- else if (Stem.startswith("atomic_"))
- Stem = Stem.drop_front(strlen("atomic_"));
- else
- return false;
-
- std::string Sign;
- std::string Postfix;
- std::string Prefix;
- if (Stem == "add" ||
- Stem == "sub" ||
- Stem == "and" ||
- Stem == "or" ||
- Stem == "xor" ||
- Stem == "min" ||
- Stem == "max") {
- if (Stem == "min" || Stem == "max") {
- auto LastChar = MangledName.back();
- if (LastChar == 'j' || LastChar == 'm')
- Sign = 'u';
- }
- Prefix = "fetch_";
- Postfix = "_explicit";
- } else if (Stem == "xchg") {
- Stem = "exchange";
- Postfix = "_explicit";
- }
- else if (Stem == "cmpxchg") {
- Stem = "compare_exchange_strong";
- Postfix = "_explicit";
- }
- else if (Stem == "inc" ||
- Stem == "dec") {
- // do nothing
- } else
- return false;
-
- Info.UniqName = "atomic_" + Prefix + Sign + Stem.str() + Postfix;
-
- std::vector<int> PostOps;
- PostOps.push_back(SPIRMO_seq_cst);
- if (Stem.startswith("compare_exchange"))
- PostOps.push_back(SPIRMO_seq_cst);
- PostOps.push_back(SPIRMS_device);
-
- Info.PostProc = [=](std::vector<SPRVWord> &Ops){
- for (auto &I:PostOps)
- Ops.push_back(addInt32(I));
- };
- return true;
-}
-
-static size_t
-getOCLCpp11AtomicMaxNumOps(StringRef Name) {
- return StringSwitch<size_t>(Name)
- .Cases("load", "flag_test_and_set", "flag_clear", 3)
- .Cases("store", "exchange", 4)
- .StartsWith("compare_exchange", 6)
- .StartsWith("fetch", 4)
- .Default(0);
-}
-
-bool
-LLVMToSPRV::getOCLCpp11AtomicTransInfo(OCLBuiltinTransInfo &Info,
- CallInst *CI, const std::string &MangledName,
- const std::string &DemangledName) {
- StringRef Stem = DemangledName;
- if (Stem.startswith("atomic_"))
- Stem = Stem.drop_front(strlen("atomic_"));
- else
- return false;
-
- std::string NewStem = Stem;
- std::vector<int> PostOps;
- if (Stem.startswith("store") ||
- Stem.startswith("load") ||
- Stem.startswith("exchange") ||
- Stem.startswith("compare_exchange") ||
- Stem.startswith("fetch") ||
- Stem.startswith("flag")) {
- if (Stem.startswith("fetch_min") ||
- Stem.startswith("fetch_max")) {
- auto Loc = MangledName.find(kMangledName::AtomicPrefix);
- assert (Loc != std::string::npos && Loc + 1 < MangledName.size());
- auto LastChar = MangledName[Loc + strlen(kMangledName::AtomicPrefix)];
- if (LastChar == 'j' || LastChar == 'm')
- NewStem.insert(NewStem.begin() + strlen("fetch_"), 'u');
- }
-
- if (!Stem.endswith("_explicit")) {
- NewStem = NewStem + "_explicit";
- PostOps.push_back(SPIRMO_seq_cst);
- if (Stem.startswith("compare_exchange"))
- PostOps.push_back(SPIRMO_seq_cst);
- PostOps.push_back(SPIRMS_device);
- } else {
- auto MaxOps = getOCLCpp11AtomicMaxNumOps(
- Stem.drop_back(strlen("_explicit")));
- if (CI->getNumArgOperands() < MaxOps)
- PostOps.push_back(SPIRMS_device);
- }
- } else if (Stem == "work_item_fence") {
- // do nothing
- } else
- return false;
-
- Info.UniqName = std::string("atomic_") + NewStem;
- Info.PostProc = [=](std::vector<SPRVWord> &Ops){
- for (auto &I:PostOps){
- Ops.push_back(addInt32(I));
- }
- };
-
- return true;
-}
-
-void LLVMToSPRV::getOCLBuiltinTransInfo(OCLBuiltinTransInfo &Info,
+void LLVMToSPRV::getOCLBuiltinSPRVTransInfo(OCLBuiltinSPRVTransInfo &Info,
CallInst *CI, const std::string & MangledName,
const std::string &DemangledName) {
if (getOCLGroupBuiltinTransInfo(Info, CI, DemangledName))
return;
- if (getOCLLegacyAtomicTransInfo(Info, CI, MangledName, DemangledName))
- return;
- if (getOCLCpp11AtomicTransInfo(Info, CI, MangledName, DemangledName))
- return;
if (getOCLPipeBuiltinTransInfo(Info, CI, DemangledName))
return;
if (getOCLImageBuiltinTransInfo(Info, CI, DemangledName))
@@ -1600,7 +1440,7 @@ LLVMToSPRV::regularize() {
std::string Err;
raw_string_ostream ErrorOS(Err);
if (verifyModule(*M, &ErrorOS)){
- SPRVDBG(errs() << "Fails to verify module: " << Err;)
+ SPRVDBG(errs() << "Fails to verify module: " << ErrorOS.str();)
return false;
}
@@ -1919,7 +1759,7 @@ LLVMToSPRV::transOCLAsyncGroupCopy(CallInst *CI, const std::string &MangledName,
Args.insert(Args.begin()+3, ConstantInt::get(getSizetType(), 1));
}
auto BArgs = transValue(Args, BB);
- return BM->addAsyncGroupCopy(SPRVES_Workgroup, BArgs[0], BArgs[1], BArgs[2],
+ return BM->addAsyncGroupCopy(ScopeWorkgroup, BArgs[0], BArgs[1], BArgs[2],
BArgs[3], BArgs[4], BB);
}
@@ -1928,9 +1768,9 @@ LLVMToSPRV::transOCLGroupBuiltins(CallInst *CI, const std::string &MangledName,
const std::string &DemangledName, SPRVBasicBlock *BB) {
auto Args = getArguments(CI);
auto BArgs = transValue(Args, BB);
- return BM->addGroupInst(SPIRSPRVBuiltinInstMap::map(DemangledName),
+ return BM->addGroupInst(OCLSPRVBuiltinMap::map(DemangledName),
transType(CI->getType()),
- SPRVES_Workgroup, BArgs, BB);
+ ScopeWorkgroup, BArgs, BB);
}
SPRVWord LLVMToSPRV::oclGetVectorLoadWidth(const std::string& DemangledName) {
@@ -1987,25 +1827,13 @@ LLVMToSPRV::oclTransBarrier(CallInst *CI,
assert(CI->getNumArgOperands() == 1);
auto MemFenceFlagVal = CI->getArgOperand(0);
assert(isa<ConstantInt>(MemFenceFlagVal));
- SPRVValue * CB = BM->addControlBarrierInst(SPRVES_Workgroup, SPRVMS_Workgroup,
- mapBitMask<SPIRSPRVMemFenceFlagMap>(dyn_cast<ConstantInt>(
+ SPRVValue * CB = BM->addControlBarrierInst(ScopeWorkgroup, ScopeWorkgroup,
+ mapBitMask<OCLMemFenceMap>(dyn_cast<ConstantInt>(
MemFenceFlagVal)->getZExtValue()), BB);
return CB;
}
SPRVValue *
-LLVMToSPRV::oclTransMemFence(CallInst *CI,
- const std::string &DemangledName, SPRVBasicBlock *BB) {
- assert(CI->getNumArgOperands() == 1);
- auto MemFenceFlagVal = CI->getArgOperand(0);
- assert(isa<ConstantInt>(MemFenceFlagVal));
- auto MB = BM->addMemoryBarrierInst(SPRVES_Workgroup,
- mapBitMask<SPIRSPRVMemFenceFlagMap>(dyn_cast<ConstantInt>(
- MemFenceFlagVal)->getZExtValue()), BB);
- return MB;
-}
-
-SPRVValue *
LLVMToSPRV::oclTransWorkGroupBarrier(CallInst *CI,
const std::string &DemangledName, SPRVBasicBlock *BB) {
assert(CI->getNumArgOperands() == 1 || CI->getNumArgOperands() == 3);
@@ -2013,19 +1841,19 @@ LLVMToSPRV::oclTransWorkGroupBarrier(CallInst *CI,
assert(isa<ConstantInt>(MemFenceFlagVal));
if (CI->getNumArgOperands() == 1){
- return BM->addControlBarrierInst(SPRVES_Workgroup, SPRVMS_Workgroup,
- mapBitMask<SPIRSPRVMemFenceFlagMap>(dyn_cast<ConstantInt>
+ return BM->addControlBarrierInst(ScopeWorkgroup, ScopeWorkgroup,
+ mapBitMask<OCLMemFenceMap>(dyn_cast<ConstantInt>
(MemFenceFlagVal)->getZExtValue()), BB);
}
Value *MemScopeVal = CI->getArgOperand(1);
assert(isa<ConstantInt>(MemScopeVal));
- assert(dyn_cast<ConstantInt>(MemScopeVal)->getZExtValue() < SPIRMS_Count);
+ assert(dyn_cast<ConstantInt>(MemScopeVal)->getZExtValue() <= OCLMS_sub_group);
- SPRVValue * CB = BM->addControlBarrierInst(SPRVES_Workgroup,
- SPIRSPRVMemScopeMap::map(static_cast<SPIRMemScopeKind>(
+ SPRVValue * CB = BM->addControlBarrierInst(ScopeWorkgroup,
+ OCLMemScopeMap::map(static_cast<OCLMemScopeKind>(
dyn_cast<ConstantInt>(MemScopeVal)->getZExtValue())),
- mapBitMask<SPIRSPRVMemFenceFlagMap>(dyn_cast<ConstantInt>
+ mapBitMask<OCLMemFenceMap>(dyn_cast<ConstantInt>
(MemFenceFlagVal)->getZExtValue()), BB);
return CB;
}
@@ -2048,11 +1876,15 @@ LLVMToSPRV::oclGetMutatedArgumentTypesByBuiltin(
SPRVInstruction *
LLVMToSPRV::transOCLBuiltinToInstByMap(const std::string& DemangledName,
const std::string &MangledName, CallInst* CI, SPRVBasicBlock* BB) {
- auto OC = OpNop;
- OCLBuiltinTransInfo Info;
- getOCLBuiltinTransInfo(Info, CI, MangledName, DemangledName);
+ auto OC = getSPRVFuncOC(DemangledName);
+ OCLBuiltinSPRVTransInfo Info;
+
+ if (OC == OpNop) {
+ getOCLBuiltinSPRVTransInfo(Info, CI, MangledName, DemangledName);
+ OCLSPRVBuiltinMap::find(Info.UniqName, &OC);
+ }
- if (SPIRSPRVBuiltinInstMap::find(Info.UniqName, &OC)) {
+ if (OC != OpNop) {
if (isCmpOpCode(OC)) {
assert(CI && CI->getNumArgOperands() == 2 && "Invalid call inst");
auto ResultTy = CI->getType();
@@ -2112,8 +1944,6 @@ LLVMToSPRV::transOCLBuiltinToInst(CallInst *CI, const std::string &MangledName,
const std::string &DemangledName, SPRVBasicBlock *BB) {
if (DemangledName == "barrier")
return oclTransBarrier(CI, DemangledName, BB);
- if (DemangledName.find("mem_fence") != std::string::npos)
- return oclTransMemFence(CI, DemangledName, BB);
if (DemangledName == "work_group_barrier")
return oclTransWorkGroupBarrier(CI, DemangledName, BB);
if (DemangledName.find("convert_") == 0)
@@ -2138,11 +1968,6 @@ LLVMToSPRV::eraseSubstitutionFromMangledName(std::string& MangledName) {
}
bool
-LLVMToSPRV::isMangledTypeUnsigned(char Mangled) {
- return Mangled == 'h' || Mangled == 't' || Mangled == 'j' || Mangled == 'm';
-}
-
-bool
LLVMToSPRV::isFuncParamSigned(const std::string& MangledName) {
auto Copy = MangledName;
eraseSubstitutionFromMangledName(Copy);
@@ -2283,13 +2108,7 @@ LLVMToSPRV::transOCLKernelMetadata() {
bool
LLVMToSPRV::transSourceLanguage() {
- NamedMDNode *NamedMD = M->getNamedMetadata(SPIR_MD_OCL_VERSION);
- assert (NamedMD && "Invalid SPIR");
- assert (NamedMD->getNumOperands() == 1 && "Invalid SPIR");
- MDNode *MD = NamedMD->getOperand(0);
- unsigned Major = getMDOperandAsInt(MD, 0);
- unsigned Minor = getMDOperandAsInt(MD, 1);
- SrcLangVer = Major * 10 + Minor;
+ SrcLangVer = getOCLVersion(M);
BM->setSourceLanguage(SourceLanguageOpenCL, SrcLangVer);
return true;
}
@@ -2322,7 +2141,7 @@ LLVMToSPRV::dumpUsers(Value* V) {
void
LLVMToSPRV::oclRegularize() {
- legacy::PassManager PassMgr;
+ PassManager PassMgr;
PassMgr.add(createSPRVRegularizeOCL20());
PassMgr.add(createSPRVLowerOCLBlocks());
PassMgr.add(createSPRVLowerBool());
diff --git a/lib/SPIRV/libSPIRV/SPRVEnum.h b/lib/SPIRV/libSPIRV/SPRVEnum.h
index 1e15f1a..b9978c4 100644
--- a/lib/SPIRV/libSPIRV/SPRVEnum.h
+++ b/lib/SPIRV/libSPIRV/SPRVEnum.h
@@ -438,53 +438,12 @@ SPRVMap<SPRVBuiltinVariableKind, std::string>::init() {
typedef SPRVMap<SPRVBuiltinVariableKind, std::string>
SPRVBuiltinVariableNameMap;
-enum SPRVExecutionScopeKind {
-#define _SPRV_OP(x) SPRVES_##x,
-_SPRV_OP(CrossDevice)
-_SPRV_OP(Device)
-_SPRV_OP(Workgroup)
-_SPRV_OP(Subgroup)
-_SPRV_OP(Count)
-#undef _SPRV_OP
-};
-
-inline bool isValid(SPRVExecutionScopeKind Kind) {
- return (unsigned)Kind < (unsigned)SPRVES_Count;
+inline bool isValid(Scope Kind) {
+ return (unsigned)Kind <= (unsigned)ScopeInvocation;
}
-enum SPRVMemoryScopeKind {
-#define _SPRV_OP(x) SPRVMS_##x,
-_SPRV_OP(CrossDevice)
-_SPRV_OP(Device)
-_SPRV_OP(Workgroup)
-_SPRV_OP(Subgroup)
-_SPRV_OP(Invocation)
-_SPRV_OP(Count)
-#undef _SPRV_OP
-};
-
-inline bool isValid(SPRVMemoryScopeKind Kind) {
- return (unsigned)Kind < (unsigned)SPRVMS_Count;
-}
-
-enum SPRVMemorySemanticsMaskKind {
-#define _SPRV_OP(x, y) SPRVMSM_##x = y,
-_SPRV_OP(Relaxed, 1)
-_SPRV_OP(SequentiallyConsistent, 2)
-_SPRV_OP(Acquire, 4)
-_SPRV_OP(Release, 8)
-_SPRV_OP(UniformMemory, 16)
-_SPRV_OP(SubgroupMemory, 32)
-_SPRV_OP(WorkgroupLocalMemory, 64)
-_SPRV_OP(WorkgroupGlobalMemory, 128)
-_SPRV_OP(AtomicCounterMemory, 256)
-_SPRV_OP(ImageMemory, 512)
-_SPRV_OP(Max, 1023)
-#undef _SPRV_OP
-};
-
inline bool isValidSPRVMemSemanticsMask(SPRVWord MemMask) {
- return MemMask <= (unsigned)SPRVMSM_Max;
+ return MemMask < 1 << ((unsigned)MemorySemanticsImageMemoryShift + 1);
}
enum SPRVSamplerAddressingModeKind {
diff --git a/lib/SPIRV/libSPIRV/SPRVInstruction.h b/lib/SPIRV/libSPIRV/SPRVInstruction.h
index 6cf0220..75d1726 100644
--- a/lib/SPIRV/libSPIRV/SPRVInstruction.h
+++ b/lib/SPIRV/libSPIRV/SPRVInstruction.h
@@ -65,9 +65,9 @@ bool isSpecConstantOpAllowedOp(Op OC);
class SPRVComponentExecutionScope {
public:
- SPRVComponentExecutionScope(SPRVExecutionScopeKind TheScope = SPRVES_Count):
+ SPRVComponentExecutionScope(Scope TheScope = ScopeInvocation):
ExecScope(TheScope){}
- SPRVExecutionScopeKind ExecScope;
+ Scope ExecScope;
};
class SPRVComponentMemorySemanticsMask {
@@ -299,10 +299,10 @@ public:
return static_cast<SPRVGroupOperationKind>(Ops[1]);
}
- SPRVExecutionScopeKind getExecutionScope() const {
+ Scope getExecutionScope() const {
if(!hasExecScope())
- return SPRVES_Count;
- return static_cast<SPRVExecutionScopeKind>(Ops[0]);
+ return ScopeInvocation;
+ return static_cast<Scope>(Ops[0]);
}
bool hasVariableWordCount() const {
@@ -1528,8 +1528,8 @@ class SPRVControlBarrier:public SPRVInstruction {
public:
static const Op OC = OpControlBarrier;
// Complete constructor
- SPRVControlBarrier(SPRVExecutionScopeKind TheScope,
- SPRVMemoryScopeKind TheMemScope, SPRVWord TheMemSema,
+ SPRVControlBarrier(Scope TheScope,
+ Scope TheMemScope, SPRVWord TheMemSema,
SPRVBasicBlock *TheBB)
:SPRVInstruction(4, OC, TheBB),ExecScope(TheScope),
MemScope(TheMemScope), MemSema(TheMemSema){
@@ -1537,17 +1537,17 @@ public:
assert(TheBB && "Invalid BB");
}
// Incomplete constructor
- SPRVControlBarrier():SPRVInstruction(OC), ExecScope(SPRVES_Count) {
+ SPRVControlBarrier():SPRVInstruction(OC), ExecScope(ScopeInvocation) {
setHasNoId();
setHasNoType();
}
void setWordCount(SPRVWord TheWordCount) {
SPRVEntry::setWordCount(TheWordCount);
}
- SPRVExecutionScopeKind getExecScope() const {
+ Scope getExecScope() const {
return ExecScope;
}
- SPRVMemoryScopeKind getMemScope() const {
+ Scope getMemScope() const {
return MemScope;
}
bool hasMemSemantic() const {
@@ -1565,8 +1565,8 @@ protected:
isValid(ExecScope);
isValid(MemScope);
}
- SPRVExecutionScopeKind ExecScope;
- SPRVMemoryScopeKind MemScope;
+ Scope ExecScope;
+ Scope MemScope;
SPRVWord MemSema;
};
@@ -1575,7 +1575,7 @@ public:
static const Op OC = OpAsyncGroupCopy;
static const SPRVWord WC = 9;
// Complete constructor
- SPRVAsyncGroupCopy(SPRVExecutionScopeKind TheScope, SPRVId TheId,
+ SPRVAsyncGroupCopy(Scope TheScope, SPRVId TheId,
SPRVValue *TheDest, SPRVValue *TheSrc, SPRVValue *TheNumElems,
SPRVValue *TheStride, SPRVValue *TheEvent, SPRVBasicBlock *TheBB)
:SPRVInstruction(WC, OC, TheEvent->getType(), TheId, TheBB),
@@ -1586,12 +1586,12 @@ public:
assert(TheBB && "Invalid BB");
}
// Incomplete constructor
- SPRVAsyncGroupCopy():SPRVInstruction(OC), ExecScope(SPRVES_Count),
+ SPRVAsyncGroupCopy():SPRVInstruction(OC), ExecScope(ScopeInvocation),
Destination(SPRVID_INVALID), Source(SPRVID_INVALID),
NumElements(SPRVID_INVALID), Stride(SPRVID_INVALID),
Event(SPRVID_INVALID){
}
- SPRVExecutionScopeKind getExecScope() const {
+ Scope getExecScope() const {
return ExecScope;
}
SPRVValue *getDestination()const { return getValue(Destination);}
@@ -1618,7 +1618,7 @@ protected:
SPRVInstruction::validate();
isValid(ExecScope);
}
- SPRVExecutionScopeKind ExecScope;
+ Scope ExecScope;
SPRVId Destination;
SPRVId Source;
SPRVId NumElements;
@@ -1741,7 +1741,7 @@ _SPRV_OP(AtomicSMax, true, 7)
_SPRV_OP(AtomicAnd, true, 7)
_SPRV_OP(AtomicOr, true, 7)
_SPRV_OP(AtomicXor, true, 7)
-_SPRV_OP(MemoryBarrier, false, 4)
+_SPRV_OP(MemoryBarrier, false, 3)
#undef _SPRV_OP
class SPRVImageInstBase:public SPRVInstTemplateBase {
diff --git a/lib/SPIRV/libSPIRV/SPRVModule.cpp b/lib/SPIRV/libSPIRV/SPRVModule.cpp
index 1b0a08f..31b0cd5 100644
--- a/lib/SPIRV/libSPIRV/SPRVModule.cpp
+++ b/lib/SPIRV/libSPIRV/SPRVModule.cpp
@@ -208,7 +208,7 @@ public:
// Instruction creation functions
virtual SPRVInstruction *addPtrAccessChainInst(SPRVType *, SPRVValue *,
std::vector<SPRVValue *>, SPRVBasicBlock *, bool);
- virtual SPRVInstruction *addAsyncGroupCopy(SPRVExecutionScopeKind Scope,
+ virtual SPRVInstruction *addAsyncGroupCopy(Scope Scope,
SPRVValue *Dest, SPRVValue *Src, SPRVValue *NumElems, SPRVValue *Stride,
SPRVValue *Event, SPRVBasicBlock *BB);
virtual SPRVInstruction *addExtInst(SPRVType *,
@@ -239,17 +239,17 @@ public:
virtual SPRVInstruction *addCopyMemorySizedInst(SPRVValue *, SPRVValue *,
SPRVValue *, const std::vector<SPRVWord>&, SPRVBasicBlock *);
virtual SPRVInstruction *addControlBarrierInst(
- SPRVExecutionScopeKind ExecKind, SPRVMemoryScopeKind MemKind,
+ Scope ExecKind, Scope MemKind,
SPRVWord MemSema, SPRVBasicBlock *BB);
virtual SPRVInstruction *addGroupInst(Op OpCode, SPRVType *Type,
- SPRVExecutionScopeKind Scope, const std::vector<SPRVValue *> &Ops,
+ Scope Scope, const std::vector<SPRVValue *> &Ops,
SPRVBasicBlock *BB);
virtual SPRVInstruction *addInstruction(SPRVInstruction *Inst,
SPRVBasicBlock *BB);
virtual SPRVInstruction *addInstTemplate(Op OC,
const std::vector<SPRVWord>& Ops, SPRVBasicBlock* BB, SPRVType *Ty);
virtual SPRVInstruction *addMemoryBarrierInst(
- SPRVExecutionScopeKind ScopeKind, SPRVWord MemFlag, SPRVBasicBlock *BB);
+ Scope ScopeKind, SPRVWord MemFlag, SPRVBasicBlock *BB);
virtual SPRVInstruction *addReturnInst(SPRVBasicBlock *);
virtual SPRVInstruction *addReturnValueInst(SPRVValue *, SPRVBasicBlock *);
virtual SPRVInstruction *addSelectInst(SPRVValue *, SPRVValue *, SPRVValue *,
@@ -804,7 +804,7 @@ SPRVModuleImpl::addSwitchInst(SPRVValue *Select, SPRVBasicBlock *Default,
SPRVInstruction *
SPRVModuleImpl::addGroupInst(Op OpCode, SPRVType *Type,
- SPRVExecutionScopeKind Scope, const std::vector<SPRVValue *> &Ops,
+ Scope Scope, const std::vector<SPRVValue *> &Ops,
SPRVBasicBlock *BB) {
auto WordOps = getIds(Ops);
WordOps.insert(WordOps.begin(), Scope);
@@ -922,14 +922,14 @@ SPRVModuleImpl::addCmpInst(Op TheOpCode, SPRVType *TheType,
}
SPRVInstruction *
-SPRVModuleImpl::addControlBarrierInst(SPRVExecutionScopeKind ExecKind,
- SPRVMemoryScopeKind MemKind, SPRVWord MemSema, SPRVBasicBlock *BB) {
+SPRVModuleImpl::addControlBarrierInst(Scope ExecKind,
+ Scope MemKind, SPRVWord MemSema, SPRVBasicBlock *BB) {
return addInstruction(
new SPRVControlBarrier(ExecKind, MemKind, MemSema, BB), BB);
}
SPRVInstruction *
-SPRVModuleImpl::addMemoryBarrierInst(SPRVExecutionScopeKind ScopeKind,
+SPRVModuleImpl::addMemoryBarrierInst(Scope ScopeKind,
SPRVWord MemFlag, SPRVBasicBlock *BB) {
return addInstruction(SPRVInstTemplateBase::create(OpMemoryBarrier,
nullptr, SPRVID_INVALID,
@@ -953,7 +953,7 @@ SPRVModuleImpl::addPtrAccessChainInst(SPRVType *Type, SPRVValue *Base,
}
SPRVInstruction *
-SPRVModuleImpl::addAsyncGroupCopy(SPRVExecutionScopeKind Scope,
+SPRVModuleImpl::addAsyncGroupCopy(Scope Scope,
SPRVValue *Dest, SPRVValue *Src, SPRVValue *NumElems, SPRVValue *Stride,
SPRVValue *Event, SPRVBasicBlock *BB) {
return addInstruction(new SPRVAsyncGroupCopy(Scope, getId(), Dest, Src,
diff --git a/lib/SPIRV/libSPIRV/SPRVModule.h b/lib/SPIRV/libSPIRV/SPRVModule.h
index a893c5a..5ffdec9 100644
--- a/lib/SPIRV/libSPIRV/SPRVModule.h
+++ b/lib/SPIRV/libSPIRV/SPRVModule.h
@@ -209,7 +209,7 @@ public:
// Instruction creation functions
virtual SPRVInstruction *addPtrAccessChainInst(SPRVType *, SPRVValue *,
std::vector<SPRVValue *>, SPRVBasicBlock *, bool) = 0;
- virtual SPRVInstruction *addAsyncGroupCopy(SPRVExecutionScopeKind Scope,
+ virtual SPRVInstruction *addAsyncGroupCopy(Scope Scope,
SPRVValue *Dest, SPRVValue *Src, SPRVValue *NumElems, SPRVValue *Stride,
SPRVValue *Event, SPRVBasicBlock *BB) = 0;
virtual SPRVInstruction *addBinaryInst(Op, SPRVType *, SPRVValue *,
@@ -240,17 +240,17 @@ public:
virtual SPRVInstruction *addCmpInst(Op, SPRVType *, SPRVValue *,
SPRVValue *, SPRVBasicBlock *) = 0;
virtual SPRVInstruction *addControlBarrierInst(
- SPRVExecutionScopeKind ExecKind, SPRVMemoryScopeKind MemKind,
+ Scope ExecKind, Scope MemKind,
SPRVWord MemSema, SPRVBasicBlock *BB) = 0;
virtual SPRVInstruction *addGroupInst(Op OpCode, SPRVType *Type,
- SPRVExecutionScopeKind Scope, const std::vector<SPRVValue *> &Ops,
+ Scope Scope, const std::vector<SPRVValue *> &Ops,
SPRVBasicBlock *BB) = 0;
virtual SPRVInstruction* addInstTemplate(Op OC,
const std::vector<SPRVWord>& Ops, SPRVBasicBlock* BB, SPRVType *Ty) = 0;
virtual SPRVInstruction *addLoadInst(SPRVValue *,
const std::vector<SPRVWord>&, SPRVBasicBlock *) = 0;
virtual SPRVInstruction *addMemoryBarrierInst(
- SPRVExecutionScopeKind ScopeKind, SPRVWord MemFlag, SPRVBasicBlock *BB)
+ Scope ScopeKind, SPRVWord MemFlag, SPRVBasicBlock *BB)
= 0;
virtual SPRVInstruction *addPhiInst(SPRVType *, std::vector<SPRVValue *>,
SPRVBasicBlock *) = 0;
diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp
index b73bf6e..25c34c9 100644
--- a/tools/llvm-spirv/llvm-spirv.cpp
+++ b/tools/llvm-spirv/llvm-spirv.cpp
@@ -165,7 +165,7 @@ convertSPRVToLLVM() {
raw_string_ostream ErrorOS(Err);
if (verifyModule(*M, &ErrorOS)){
- errs() << "Fails to verify module: " << Err;
+ errs() << "Fails to verify module: " << ErrorOS.str();
return -1;
}