summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordoe300 <doe300@users.noreply.github.com>2017-06-29 20:38:40 +0200
committerYaxun (Sam) Liu <yaxun.liu@amd.com>2017-06-29 14:38:40 -0400
commitec2026af3091333bef812957109e6217af4ba94a (patch)
treeaf9d7d10c80dc7d929a9010635df52a45b9f8eaa /lib
parentf8b02714c896d992541190b3ef0f08273e1ea92f (diff)
Squashed the lower-memmove pass (#209)
Diffstat (limited to 'lib')
-rw-r--r--lib/SPIRV/CMakeLists.txt1
-rw-r--r--lib/SPIRV/SPIRVLowerMemmove.cpp139
-rw-r--r--lib/SPIRV/SPIRVWriter.cpp1
-rw-r--r--lib/SPIRV/libSPIRV/SPIRVInstruction.h3
4 files changed, 142 insertions, 2 deletions
diff --git a/lib/SPIRV/CMakeLists.txt b/lib/SPIRV/CMakeLists.txt
index 9d28865..d313439 100644
--- a/lib/SPIRV/CMakeLists.txt
+++ b/lib/SPIRV/CMakeLists.txt
@@ -30,6 +30,7 @@ add_llvm_library(LLVMSPIRVLib
SPIRVLowerBool.cpp
SPIRVLowerConstExpr.cpp
SPIRVLowerOCLBlocks.cpp
+ SPIRVLowerMemmove.cpp
SPIRVReader.cpp
SPIRVRegularizeLLVM.cpp
SPIRVToOCL20.cpp
diff --git a/lib/SPIRV/SPIRVLowerMemmove.cpp b/lib/SPIRV/SPIRVLowerMemmove.cpp
new file mode 100644
index 0000000..cd9056c
--- /dev/null
+++ b/lib/SPIRV/SPIRVLowerMemmove.cpp
@@ -0,0 +1,139 @@
+//===- SPIRVLowerMemmove.cpp - Lower llvm.memmove to llvm.memcpys ----------===//
+//
+// 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 lowering llvm.memmove into several llvm.memcpys.
+//
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "spvmemmove"
+
+#include "SPIRVInternal.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/PassSupport.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace SPIRV {
+cl::opt<bool> SPIRVLowerMemmoveValidate("spvmemmove-validate",
+ cl::desc("Validate module after lowering llvm.memmove instructions into "
+ "llvm.memcpy"));
+
+class SPIRVLowerMemmove: public ModulePass,
+ public InstVisitor<SPIRVLowerMemmove> {
+public:
+ SPIRVLowerMemmove():ModulePass(ID), Context(nullptr) {
+ initializeSPIRVLowerMemmovePass(*PassRegistry::getPassRegistry());
+ }
+ virtual void visitMemMoveInst(MemMoveInst &I) {
+ IRBuilder<> Builder(I.getParent());
+ Builder.SetInsertPoint(&I);
+ auto *Dest = I.getRawDest();
+ auto *Src = I.getRawSource();
+ auto *SrcTy = Src->getType();
+ if (!isa<ConstantInt>(I.getLength()))
+ // ToDo: for non-constant length, could use a loop to copy a
+ // fixed length chunk at a time. For now simply fail
+ report_fatal_error("llvm.memmove of non-constant length not supported",
+ false);
+ auto *Length = cast<ConstantInt>(I.getLength());
+ if (isa<BitCastInst>(Src))
+ // The source could be bit-cast from another type,
+ // need the original type for the allocation of the temporary variable
+ SrcTy = cast<BitCastInst>(Src)->getOperand(0)->getType();
+ auto Align = I.getAlignment();
+ auto Volatile = I.isVolatile();
+ Value *NumElements = nullptr;
+ uint64_t ElementsCount = 1;
+ if (SrcTy->isArrayTy()) {
+ NumElements = Builder.getInt32(SrcTy->getArrayNumElements());
+ ElementsCount = SrcTy->getArrayNumElements();
+ }
+ if (Mod->getDataLayout()->getTypeSizeInBits(SrcTy->getPointerElementType())
+ * ElementsCount != Length->getZExtValue() * 8)
+ report_fatal_error("Size of the memcpy should match the allocated memory",
+ false);
+
+ auto *Alloca = Builder.CreateAlloca(SrcTy->getPointerElementType(),
+ NumElements);
+ auto *LifetimeStart = Builder.CreateLifetimeStart(Alloca);
+ auto *FirstCpy = Builder.CreateMemCpy(Alloca, Src, Length, Align, Volatile);
+ auto *SecondCpy = Builder.CreateMemCpy(Dest, Alloca, Length, Align,
+ Volatile);
+ auto *LifetimeEnd = Builder.CreateLifetimeEnd(Alloca);
+
+ SecondCpy->takeName(&I);
+ I.replaceAllUsesWith(SecondCpy);
+ I.dropAllReferences();
+ I.eraseFromParent();
+ }
+ virtual bool runOnModule(Module &M) {
+ Context = &M.getContext();
+ Mod = &M;
+ visit(M);
+
+ if (SPIRVLowerMemmoveValidate) {
+ DEBUG(dbgs() << "After SPIRVLowerMemmove:\n" << M);
+ std::string Err;
+ raw_string_ostream ErrorOS(Err);
+ if (verifyModule(M, &ErrorOS)){
+ Err = std::string("Fails to verify module: ") + Err;
+ report_fatal_error(Err.c_str(), false);
+ }
+ }
+ return true;
+ }
+
+ static char ID;
+private:
+ LLVMContext *Context;
+ Module *Mod;
+};
+
+char SPIRVLowerMemmove::ID = 0;
+}
+
+INITIALIZE_PASS(SPIRVLowerMemmove, "spvmemmove",
+ "Lower llvm.memmove into llvm.memcpy", false, false)
+
+ModulePass *llvm::createSPIRVLowerMemmove() {
+ return new SPIRVLowerMemmove();
+}
diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp
index 44e92b3..9bc2937 100644
--- a/lib/SPIRV/SPIRVWriter.cpp
+++ b/lib/SPIRV/SPIRVWriter.cpp
@@ -1838,6 +1838,7 @@ addPassesForSPIRV(PassManager &PassMgr) {
PassMgr.add(createSPIRVRegularizeLLVM());
PassMgr.add(createSPIRVLowerConstExpr());
PassMgr.add(createSPIRVLowerBool());
+ PassMgr.add(createSPIRVLowerMemmove());
}
bool
diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h
index d8cfa50..a3e0169 100644
--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h
+++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h
@@ -1878,8 +1878,7 @@ protected:
assert(Obj->getStorageClass() == StorageClassFunction &&
"Invalid storage class");
assert(Obj->getType()->isTypePointer() &&
- Obj->getType()->getPointerElementType()->isTypeInt() &&
- "Object type must be an integer type scalar");
+ "Objects type must be a pointer");
if (!Obj->getType()->getPointerElementType()->isTypeVoid() ||
!Module->hasCapability(CapabilityAddresses))
assert(Size == 0 && "Size must be 0");