1 //===-- ARMGlobalMerge.cpp - Internal globals merging --------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
12 #define DEBUG_TYPE "arm-global-merge"
14 #include "llvm/CodeGen/Passes.h"
15 #include "llvm/Attributes.h"
16 #include "llvm/Constants.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Function.h"
19 #include "llvm/GlobalVariable.h"
20 #include "llvm/Instructions.h"
21 #include "llvm/Intrinsics.h"
22 #include "llvm/Module.h"
23 #include "llvm/Pass.h"
24 #include "llvm/Target/TargetData.h"
25 #include "llvm/Target/TargetLowering.h"
29 class VISIBILITY_HIDDEN ARMGlobalMerge : public FunctionPass {
30 /// TLI - Keep a pointer of a TargetLowering to consult for determining
31 /// target type sizes.
32 const TargetLowering *TLI;
33 bool doMerge(std::vector<GlobalVariable*> &Globals, Module &M, bool) const;
36 static char ID; // Pass identification, replacement for typeid.
37 explicit ARMGlobalMerge(const TargetLowering *tli)
38 : FunctionPass(&ID), TLI(tli) {}
40 virtual bool doInitialization(Module &M);
41 virtual bool runOnFunction(Function& F);
43 const char *getPassName() const {
44 return "Merge internal globals";
47 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
49 FunctionPass::getAnalysisUsage(AU);
55 GlobalCmp(const TargetData *td):
58 bool operator() (const GlobalVariable* GV1,
59 const GlobalVariable* GV2) {
60 const Type* Ty1 = cast<PointerType>(GV1->getType())->getElementType();
61 const Type* Ty2 = cast<PointerType>(GV2->getType())->getElementType();
63 return (TD->getTypeAllocSize(Ty1) <
64 TD->getTypeAllocSize(Ty2));
68 } // end anonymous namespace
70 char ARMGlobalMerge::ID = 0;
72 #define MAX_OFFSET 4095
74 bool ARMGlobalMerge::doMerge(std::vector<GlobalVariable*> &Globals,
75 Module &M, bool isConst) const {
76 const TargetData *TD = TLI->getTargetData();
78 // FIXME: Find better heuristics
79 std::stable_sort(Globals.begin(), Globals.end(), GlobalCmp(TD));
81 const Type *Int32Ty = Type::getInt32Ty(M.getContext());
83 for (size_t i = 0, e = Globals.size(); i != e; ) {
85 uint64_t MergedSize = 0;
86 std::vector<const Type*> Tys;
87 std::vector<Constant*> Inits;
88 for (j = i; MergedSize < MAX_OFFSET && j != e; ++j) {
89 const Type* Ty = Globals[j]->getType()->getElementType();
91 Inits.push_back(Globals[j]->getInitializer());
92 MergedSize += TD->getTypeAllocSize(Ty);
95 StructType* MergedTy = StructType::get(M.getContext(), Tys);
96 Constant* MergedInit = ConstantStruct::get(MergedTy, Inits);
97 GlobalVariable* MergedGV = new GlobalVariable(M, MergedTy, isConst,
98 GlobalValue::InternalLinkage,
99 MergedInit, "merged");
100 for (size_t k = i; k < j; ++k) {
101 SmallVector<Constant*, 2> Idx;
102 Idx.push_back(ConstantInt::get(Int32Ty, 0));
103 Idx.push_back(ConstantInt::get(Int32Ty, k-i));
106 ConstantExpr::getInBoundsGetElementPtr(MergedGV,
107 &Idx[0], Idx.size());
109 Globals[k]->replaceAllUsesWith(GEP);
110 Globals[k]->eraseFromParent();
119 bool ARMGlobalMerge::doInitialization(Module& M) {
120 std::vector<GlobalVariable*> Globals, ConstGlobals;
121 bool Changed = false;
122 const TargetData *TD = TLI->getTargetData();
124 // Grab all non-const globals.
125 for (Module::global_iterator I = M.global_begin(),
126 E = M.global_end(); I != E; ++I) {
127 // Ignore fancy-aligned globals for now.
128 if (I->hasLocalLinkage() && I->getAlignment() == 0 &&
129 TD->getTypeAllocSize(I->getType()) < MAX_OFFSET) {
131 ConstGlobals.push_back(I);
133 Globals.push_back(I);
137 Changed |= doMerge(Globals, M, false);
138 Changed |= doMerge(ConstGlobals, M, true);
143 bool ARMGlobalMerge::runOnFunction(Function& F) {
147 FunctionPass *llvm::createARMGlobalMergePass(const TargetLowering *tli) {
148 return new ARMGlobalMerge(tli);