From 1e7b324fe517583eb093854e17f1619324da4582 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 7 Apr 2010 18:19:07 +0000 Subject: [PATCH] Some initial version of global merger git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100641 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARM.h | 1 + lib/Target/ARM/ARMGlobalMerge.cpp | 135 ++++++++++++++++++++++++++++ lib/Target/ARM/ARMTargetMachine.cpp | 8 +- lib/Target/ARM/ARMTargetMachine.h | 1 + 4 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 lib/Target/ARM/ARMGlobalMerge.cpp diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index b08f9425776..7376fcdc12b 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -98,6 +98,7 @@ FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); FunctionPass *createARMExpandPseudoPass(); +FunctionPass *createARMGlobalMergePass(const TargetLowering* tli); FunctionPass *createARMConstantIslandPass(); FunctionPass *createNEONPreAllocPass(); FunctionPass *createNEONMoveFixPass(); diff --git a/lib/Target/ARM/ARMGlobalMerge.cpp b/lib/Target/ARM/ARMGlobalMerge.cpp new file mode 100644 index 00000000000..4647795a71b --- /dev/null +++ b/lib/Target/ARM/ARMGlobalMerge.cpp @@ -0,0 +1,135 @@ +//===-- ARMGlobalMerge.cpp - Internal globals merging --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-global-merge" +#include "ARM.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Attributes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +namespace { + class VISIBILITY_HIDDEN ARMGlobalMerge : public FunctionPass { + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLowering *TLI; + + std::vector InternalGlobals; + + public: + static char ID; // Pass identification, replacement for typeid. + explicit ARMGlobalMerge(const TargetLowering *tli) + : FunctionPass(&ID), TLI(tli) {} + + virtual bool doInitialization(Module &M); + virtual bool runOnFunction(Function& F); + + const char *getPassName() const { + return "Merge internal globals"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); + } + + struct GlobalCmp { + const TargetData *TD; + + GlobalCmp(const TargetData *td): + TD(td) { }; + + bool operator() (const GlobalVariable* GV1, + const GlobalVariable* GV2) { + const Type* Ty1 = cast(GV1->getType())->getElementType(); + const Type* Ty2 = cast(GV2->getType())->getElementType(); + + return (TD->getTypeAllocSize(Ty1) < + TD->getTypeAllocSize(Ty2)); + } + }; + }; +} // end anonymous namespace + +char ARMGlobalMerge::ID = 0; + +#define MAX_OFFSET 4095 + +bool ARMGlobalMerge::doInitialization(Module& M) { + const TargetData *TD = TLI->getTargetData(); + + for (Module::global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + // FIXME: Can we just grab all 'local' vars here? + // Won't we break some semantics? + if (I->hasInternalLinkage() && + TD->getTypeAllocSize(I->getType()) < MAX_OFFSET) + InternalGlobals.push_back(I); + } + + // FIXME: Find better heuristics + std::stable_sort(InternalGlobals.begin(), InternalGlobals.end(), + GlobalCmp(TD)); + + const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + + for (size_t i = 0, e = InternalGlobals.size(); i != e; ) { + size_t j = 0; + uint64_t MergedSize = 0; + std::vector Tys; + std::vector Inits; + for (j = i; MergedSize < MAX_OFFSET && j != e; ++j) { + const Type* Ty = + cast(InternalGlobals[j]->getType())->getElementType(); + Tys.push_back(Ty); + Inits.push_back(InternalGlobals[j]->getInitializer()); + MergedSize += TD->getTypeAllocSize(Ty); + } + + StructType* MergedTy = StructType::get(M.getContext(), Tys); + Constant* MergedInit = ConstantStruct::get(MergedTy, Inits); + // FIXME: Should we handle constants and 'normal' globals separately? + GlobalVariable* MergedGV = new GlobalVariable(M, MergedTy, false, + GlobalValue::InternalLinkage, + MergedInit, "merged"); + for (size_t k = i; k < j; ++k) { + SmallVector Idx; + Idx.push_back(ConstantInt::get(Int32Ty, 0)); + Idx.push_back(ConstantInt::get(Int32Ty, k-i)); + + Constant* GEP = + ConstantExpr::getInBoundsGetElementPtr(MergedGV, + &Idx[0], Idx.size()); + + InternalGlobals[k]->replaceAllUsesWith(GEP); + } + i = j; + } + + return true; +} + +bool ARMGlobalMerge::runOnFunction(Function& F) { + return false; +} + +FunctionPass *llvm::createARMGlobalMergePass(const TargetLowering *tli) { + return new ARMGlobalMerge(tli); +} diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 95f57b7b34f..ab299b13b78 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -79,9 +79,15 @@ ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT, TLInfo(*this) { } +// Pass Pipeline Configuration +bool ARMBaseTargetMachine::addPreISel(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + if (OptLevel != CodeGenOpt::None) + PM.add(createARMGlobalMergePass(getTargetLowering())); + return false; +} -// Pass Pipeline Configuration bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { PM.add(createARMISelDag(*this, OptLevel)); diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h index c32f16c77a2..c90c599c98a 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -49,6 +49,7 @@ public: } // Pass Pipeline Configuration + virtual bool addPreISel(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPreSched2(PassManagerBase &PM, CodeGenOpt::Level OptLevel); -- 2.34.1