summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/src/CMakeLists.txt1
-rw-r--r--backend/src/llvm/llvm_barrier_nodup.cpp117
-rw-r--r--backend/src/llvm/llvm_gen_backend.hpp2
-rw-r--r--backend/src/llvm/llvm_to_gen.cpp2
-rw-r--r--backend/src/ocl_barrier.ll6
5 files changed, 125 insertions, 3 deletions
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 6e37d95d..d6f2d3c6 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -144,6 +144,7 @@ else (GBE_USE_BLOB)
llvm/llvm_passes.cpp
llvm/llvm_scalarize.cpp
llvm/llvm_intrinsic_lowering.cpp
+ llvm/llvm_barrier_nodup.cpp
llvm/llvm_to_gen.cpp
llvm/llvm_gen_backend.hpp
llvm/llvm_gen_ocl_function.hxx
diff --git a/backend/src/llvm/llvm_barrier_nodup.cpp b/backend/src/llvm/llvm_barrier_nodup.cpp
new file mode 100644
index 00000000..cc1e22ce
--- /dev/null
+++ b/backend/src/llvm/llvm_barrier_nodup.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file llvm_barrier_nodup.cpp
+ *
+ * This pass is to remove or add noduplicate function attribute for barrier functions.
+ * Basically, we want to set NoDuplicate for those __gen_barrier_xxx functions. But if
+ * a sub function calls those barrier functions, the sub function will not be inlined
+ * in llvm's inlining pass. This is what we don't want. As inlining such a function in
+ * the caller is safe, we just don't want it to duplicate the call. So Introduce this
+ * pass to remove the NoDuplicate function attribute before the inlining pass and restore
+ * it after.
+ *
+ */
+
+#include "llvm/Config/config.h"
+#if LLVM_VERSION_MINOR <= 2
+#include "llvm/Function.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Module.h"
+#else
+#include "llvm/IR/Function.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#endif /* LLVM_VERSION_MINOR <= 2 */
+#include "llvm/Pass.h"
+#if LLVM_VERSION_MINOR <= 1
+#include "llvm/Support/IRBuilder.h"
+#elif LLVM_VERSION_MINOR == 2
+#include "llvm/IRBuilder.h"
+#else
+#include "llvm/IR/IRBuilder.h"
+#endif /* LLVM_VERSION_MINOR <= 1 */
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Attributes.h"
+
+#include "llvm/llvm_gen_backend.hpp"
+#include "sys/map.hpp"
+
+
+using namespace llvm;
+
+namespace gbe {
+ class BarrierNodup : public ModulePass
+ {
+ public:
+ static char ID;
+ BarrierNodup(bool nodup) :
+ ModulePass(ID), nodup(nodup) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+
+ }
+
+ virtual const char *getPassName() const {
+ return "SPIR backend: set barrier no duplicate attr";
+ }
+
+ virtual bool runOnModule(Module &M)
+ {
+ using namespace llvm;
+ bool changed = false;
+ for (auto &F : M) {
+ if (F.getName() == "__gen_ocl_barrier_local_and_global" ||
+ F.getName() == "__gen_ocl_barrier_local" ||
+ F.getName() == "__gen_ocl_barrier_global") {
+ if (nodup) {
+ if (!F.hasFnAttribute(Attribute::NoDuplicate)) {
+ F.addFnAttr(Attribute::NoDuplicate);
+ changed = true;
+ }
+ } else {
+ if (F.hasFnAttribute(Attribute::NoDuplicate)) {
+ auto attrs = F.getAttributes();
+ F.setAttributes(attrs.removeAttribute(M.getContext(),
+ AttributeSet::FunctionIndex,
+ Attribute::NoDuplicate));
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
+ }
+ private:
+ bool nodup;
+ };
+
+
+ ModulePass *createBarrierNodupPass(bool Nodup) {
+ return new BarrierNodup(Nodup);
+ }
+
+ char BarrierNodup::ID = 0;
+} // end namespace
diff --git a/backend/src/llvm/llvm_gen_backend.hpp b/backend/src/llvm/llvm_gen_backend.hpp
index 389d5f36..56dd27f3 100644
--- a/backend/src/llvm/llvm_gen_backend.hpp
+++ b/backend/src/llvm/llvm_gen_backend.hpp
@@ -86,6 +86,8 @@ namespace gbe
/*! Scalarize all vector op instructions */
llvm::FunctionPass* createScalarizePass();
+ /*! Remove/add NoDuplicate function attribute for barrier functions. */
+ llvm::ModulePass* createBarrierNodupPass(bool);
/*! Convert the Intrinsic call to gen function */
llvm::BasicBlockPass *createIntrinsicLoweringPass();
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index 9e18a578..4d064a24 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -112,7 +112,9 @@ namespace gbe
MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE
MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
MPM.add(createPruneEHPass()); // Remove dead EH info
+ MPM.add(createBarrierNodupPass(false)); // remove noduplicate fnAttr before inlining.
MPM.add(createFunctionInliningPass(200000));
+ MPM.add(createBarrierNodupPass(true)); // restore noduplicate fnAttr after inlining.
MPM.add(createFunctionAttrsPass()); // Set readonly/readnone attrs
//MPM.add(createScalarReplAggregatesPass(64, true, -1, -1, 64))
diff --git a/backend/src/ocl_barrier.ll b/backend/src/ocl_barrier.ll
index 9f463478..4e55fcb7 100644
--- a/backend/src/ocl_barrier.ll
+++ b/backend/src/ocl_barrier.ll
@@ -6,9 +6,9 @@
declare i32 @_get_local_mem_fence() nounwind alwaysinline
declare i32 @_get_global_mem_fence() nounwind alwaysinline
-declare void @__gen_ocl_barrier_local() nounwind alwaysinline
-declare void @__gen_ocl_barrier_global() nounwind alwaysinline
-declare void @__gen_ocl_barrier_local_and_global() nounwind alwaysinline
+declare void @__gen_ocl_barrier_local() nounwind alwaysinline noduplicate
+declare void @__gen_ocl_barrier_global() nounwind alwaysinline noduplicate
+declare void @__gen_ocl_barrier_local_and_global() nounwind alwaysinline noduplicate
define void @barrier(i32 %flags) nounwind noduplicate alwaysinline {
%1 = icmp eq i32 %flags, 3