diff options
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | backend/src/llvm/llvm_barrier_nodup.cpp | 117 | ||||
| -rw-r--r-- | backend/src/llvm/llvm_gen_backend.hpp | 2 | ||||
| -rw-r--r-- | backend/src/llvm/llvm_to_gen.cpp | 2 | ||||
| -rw-r--r-- | backend/src/ocl_barrier.ll | 6 |
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 |
