blob: 4647795a71b37ddb258343c1e88a16eec8f01d1a [file] [log] [blame]
Anton Korobeynikov3e27a4b2010-04-07 18:19:07 +00001//===-- ARMGlobalMerge.cpp - Internal globals merging --------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//===----------------------------------------------------------------------===//
11
12#define DEBUG_TYPE "arm-global-merge"
13#include "ARM.h"
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"
26using namespace llvm;
27
28namespace {
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
34 std::vector<GlobalVariable*> InternalGlobals;
35
36 public:
37 static char ID; // Pass identification, replacement for typeid.
38 explicit ARMGlobalMerge(const TargetLowering *tli)
39 : FunctionPass(&ID), TLI(tli) {}
40
41 virtual bool doInitialization(Module &M);
42 virtual bool runOnFunction(Function& F);
43
44 const char *getPassName() const {
45 return "Merge internal globals";
46 }
47
48 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
49 AU.setPreservesCFG();
50 FunctionPass::getAnalysisUsage(AU);
51 }
52
53 struct GlobalCmp {
54 const TargetData *TD;
55
56 GlobalCmp(const TargetData *td):
57 TD(td) { };
58
59 bool operator() (const GlobalVariable* GV1,
60 const GlobalVariable* GV2) {
61 const Type* Ty1 = cast<PointerType>(GV1->getType())->getElementType();
62 const Type* Ty2 = cast<PointerType>(GV2->getType())->getElementType();
63
64 return (TD->getTypeAllocSize(Ty1) <
65 TD->getTypeAllocSize(Ty2));
66 }
67 };
68 };
69} // end anonymous namespace
70
71char ARMGlobalMerge::ID = 0;
72
73#define MAX_OFFSET 4095
74
75bool ARMGlobalMerge::doInitialization(Module& M) {
76 const TargetData *TD = TLI->getTargetData();
77
78 for (Module::global_iterator I = M.global_begin(),
79 E = M.global_end(); I != E; ++I) {
80 // FIXME: Can we just grab all 'local' vars here?
81 // Won't we break some semantics?
82 if (I->hasInternalLinkage() &&
83 TD->getTypeAllocSize(I->getType()) < MAX_OFFSET)
84 InternalGlobals.push_back(I);
85 }
86
87 // FIXME: Find better heuristics
88 std::stable_sort(InternalGlobals.begin(), InternalGlobals.end(),
89 GlobalCmp(TD));
90
91 const Type *Int32Ty = Type::getInt32Ty(M.getContext());
92
93 for (size_t i = 0, e = InternalGlobals.size(); i != e; ) {
94 size_t j = 0;
95 uint64_t MergedSize = 0;
96 std::vector<const Type*> Tys;
97 std::vector<Constant*> Inits;
98 for (j = i; MergedSize < MAX_OFFSET && j != e; ++j) {
99 const Type* Ty =
100 cast<PointerType>(InternalGlobals[j]->getType())->getElementType();
101 Tys.push_back(Ty);
102 Inits.push_back(InternalGlobals[j]->getInitializer());
103 MergedSize += TD->getTypeAllocSize(Ty);
104 }
105
106 StructType* MergedTy = StructType::get(M.getContext(), Tys);
107 Constant* MergedInit = ConstantStruct::get(MergedTy, Inits);
108 // FIXME: Should we handle constants and 'normal' globals separately?
109 GlobalVariable* MergedGV = new GlobalVariable(M, MergedTy, false,
110 GlobalValue::InternalLinkage,
111 MergedInit, "merged");
112 for (size_t k = i; k < j; ++k) {
113 SmallVector<Constant*, 2> Idx;
114 Idx.push_back(ConstantInt::get(Int32Ty, 0));
115 Idx.push_back(ConstantInt::get(Int32Ty, k-i));
116
117 Constant* GEP =
118 ConstantExpr::getInBoundsGetElementPtr(MergedGV,
119 &Idx[0], Idx.size());
120
121 InternalGlobals[k]->replaceAllUsesWith(GEP);
122 }
123 i = j;
124 }
125
126 return true;
127}
128
129bool ARMGlobalMerge::runOnFunction(Function& F) {
130 return false;
131}
132
133FunctionPass *llvm::createARMGlobalMergePass(const TargetLowering *tli) {
134 return new ARMGlobalMerge(tli);
135}