diff options
Diffstat (limited to 'backend/src/llvm/llvm_barrier_nodup.cpp')
| -rw-r--r-- | backend/src/llvm/llvm_barrier_nodup.cpp | 117 |
1 files changed, 117 insertions, 0 deletions
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 |
