xref: /src/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCMergeStringPool.cpp (revision cb2887746f8b9dd4ad6b1e757cdc053a08b25a2e)
1b1c73532SDimitry Andric //===-- PPCMergeStringPool.cpp -------------------------------------------===//
2b1c73532SDimitry Andric //
3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1c73532SDimitry Andric //
7b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
8b1c73532SDimitry Andric //
9b1c73532SDimitry Andric // This transformation tries to merge the strings in the module into one pool
10b1c73532SDimitry Andric // of strings. The idea is to reduce the number of TOC entries in the module so
11b1c73532SDimitry Andric // that instead of having one TOC entry for each string there is only one global
12b1c73532SDimitry Andric // TOC entry and all of the strings are referenced off of that one entry plus
13b1c73532SDimitry Andric // an offset.
14b1c73532SDimitry Andric //
15b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
16b1c73532SDimitry Andric 
17b1c73532SDimitry Andric #include "PPC.h"
18b1c73532SDimitry Andric #include "llvm/ADT/Statistic.h"
19b1c73532SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h"
20b1c73532SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
21b1c73532SDimitry Andric #include "llvm/Analysis/LoopIterator.h"
22b1c73532SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h"
23b1c73532SDimitry Andric #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
24b1c73532SDimitry Andric #include "llvm/IR/Constants.h"
25b1c73532SDimitry Andric #include "llvm/IR/Instructions.h"
26ac9a064cSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
27b1c73532SDimitry Andric #include "llvm/IR/Module.h"
28b1c73532SDimitry Andric #include "llvm/IR/ValueSymbolTable.h"
29b1c73532SDimitry Andric #include "llvm/Pass.h"
30b1c73532SDimitry Andric #include "llvm/Support/CommandLine.h"
31b1c73532SDimitry Andric 
32b1c73532SDimitry Andric #define DEBUG_TYPE "ppc-merge-strings"
33b1c73532SDimitry Andric 
34b1c73532SDimitry Andric STATISTIC(NumPooledStrings, "Number of Strings Pooled");
35b1c73532SDimitry Andric 
36b1c73532SDimitry Andric using namespace llvm;
37b1c73532SDimitry Andric 
38b1c73532SDimitry Andric static cl::opt<unsigned>
39b1c73532SDimitry Andric     MaxStringsPooled("ppc-max-strings-pooled", cl::Hidden, cl::init(-1),
40b1c73532SDimitry Andric                      cl::desc("Maximum Number of Strings to Pool."));
41b1c73532SDimitry Andric 
42b1c73532SDimitry Andric static cl::opt<unsigned>
43b1c73532SDimitry Andric     MinStringsBeforePool("ppc-min-strings-before-pool", cl::Hidden, cl::init(2),
44b1c73532SDimitry Andric                          cl::desc("Minimum number of string candidates before "
45b1c73532SDimitry Andric 				  "pooling is considered."));
46b1c73532SDimitry Andric 
47b1c73532SDimitry Andric namespace {
48b1c73532SDimitry Andric struct {
operator ()__anon5c77626e0111::__anon5c77626e020849b1c73532SDimitry Andric   bool operator()(const GlobalVariable *LHS, const GlobalVariable *RHS) const {
50b1c73532SDimitry Andric     // First priority is alignment.
51b1c73532SDimitry Andric     // If elements are sorted in terms of alignment then there won't be an
52b1c73532SDimitry Andric     // issue with incorrect alignment that would require padding.
53b1c73532SDimitry Andric     Align LHSAlign = LHS->getAlign().valueOrOne();
54b1c73532SDimitry Andric     Align RHSAlign = RHS->getAlign().valueOrOne();
55b1c73532SDimitry Andric     if (LHSAlign > RHSAlign)
56b1c73532SDimitry Andric       return true;
57b1c73532SDimitry Andric     else if (LHSAlign < RHSAlign)
58b1c73532SDimitry Andric       return false;
59b1c73532SDimitry Andric 
60b1c73532SDimitry Andric     // Next priority is the number of uses.
61b1c73532SDimitry Andric     // Smaller offsets are easier to materialize because materializing a large
62b1c73532SDimitry Andric     // offset may require more than one instruction. (ie addis, addi).
63b1c73532SDimitry Andric     if (LHS->getNumUses() > RHS->getNumUses())
64b1c73532SDimitry Andric       return true;
65b1c73532SDimitry Andric     else if (LHS->getNumUses() < RHS->getNumUses())
66b1c73532SDimitry Andric       return false;
67b1c73532SDimitry Andric 
68b1c73532SDimitry Andric     const Constant *ConstLHS = LHS->getInitializer();
69b1c73532SDimitry Andric     const ConstantDataSequential *ConstDataLHS =
70b1c73532SDimitry Andric         dyn_cast<ConstantDataSequential>(ConstLHS);
71b1c73532SDimitry Andric     unsigned LHSSize =
72b1c73532SDimitry Andric         ConstDataLHS->getNumElements() * ConstDataLHS->getElementByteSize();
73b1c73532SDimitry Andric     const Constant *ConstRHS = RHS->getInitializer();
74b1c73532SDimitry Andric     const ConstantDataSequential *ConstDataRHS =
75b1c73532SDimitry Andric         dyn_cast<ConstantDataSequential>(ConstRHS);
76b1c73532SDimitry Andric     unsigned RHSSize =
77b1c73532SDimitry Andric         ConstDataRHS->getNumElements() * ConstDataRHS->getElementByteSize();
78b1c73532SDimitry Andric 
79b1c73532SDimitry Andric     // Finally smaller constants should go first. This is, again, trying to
80b1c73532SDimitry Andric     // minimize the offsets into the final struct.
81b1c73532SDimitry Andric     return LHSSize < RHSSize;
82b1c73532SDimitry Andric   }
83b1c73532SDimitry Andric } CompareConstants;
84b1c73532SDimitry Andric 
85b1c73532SDimitry Andric class PPCMergeStringPool : public ModulePass {
86b1c73532SDimitry Andric public:
87b1c73532SDimitry Andric   static char ID;
PPCMergeStringPool()88b1c73532SDimitry Andric   PPCMergeStringPool() : ModulePass(ID) {}
89b1c73532SDimitry Andric 
doInitialization(Module & M)90ac9a064cSDimitry Andric   bool doInitialization(Module &M) override { return mergeModuleStringPool(M); }
runOnModule(Module & M)91ac9a064cSDimitry Andric   bool runOnModule(Module &M) override { return false; }
92b1c73532SDimitry Andric 
getPassName() const93b1c73532SDimitry Andric   StringRef getPassName() const override { return "PPC Merge String Pool"; }
94b1c73532SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const95b1c73532SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
96b1c73532SDimitry Andric     AU.addPreserved<DominatorTreeWrapperPass>();
97b1c73532SDimitry Andric     AU.addPreserved<LoopInfoWrapperPass>();
98b1c73532SDimitry Andric     AU.addPreserved<ScalarEvolutionWrapperPass>();
99b1c73532SDimitry Andric     AU.addPreserved<SCEVAAWrapperPass>();
100b1c73532SDimitry Andric   }
101b1c73532SDimitry Andric 
102b1c73532SDimitry Andric private:
103b1c73532SDimitry Andric   // Globals in a Module are already unique so a set is not required and a
104b1c73532SDimitry Andric   // vector will do.
105b1c73532SDimitry Andric   std::vector<GlobalVariable *> MergeableStrings;
106b1c73532SDimitry Andric   Align MaxAlignment;
107b1c73532SDimitry Andric   Type *PooledStructType;
108b1c73532SDimitry Andric   LLVMContext *Context;
109b1c73532SDimitry Andric   void collectCandidateConstants(Module &M);
110b1c73532SDimitry Andric   bool mergeModuleStringPool(Module &M);
111b1c73532SDimitry Andric   void replaceUsesWithGEP(GlobalVariable *GlobalToReplace, GlobalVariable *GPool,
112b1c73532SDimitry Andric                           unsigned ElementIndex);
113b1c73532SDimitry Andric };
114b1c73532SDimitry Andric 
115b1c73532SDimitry Andric 
116b1c73532SDimitry Andric // In order for a constant to be pooled we need to be able to replace all of
117b1c73532SDimitry Andric // the uses for that constant. This function checks all of the uses to make
118b1c73532SDimitry Andric // sure that they can be replaced.
hasReplaceableUsers(GlobalVariable & GV)119b1c73532SDimitry Andric static bool hasReplaceableUsers(GlobalVariable &GV) {
120b1c73532SDimitry Andric   for (User *CurrentUser : GV.users()) {
121ac9a064cSDimitry Andric     if (auto *I = dyn_cast<Instruction>(CurrentUser)) {
122ac9a064cSDimitry Andric       // Do not merge globals in exception pads.
123ac9a064cSDimitry Andric       if (I->isEHPad())
124ac9a064cSDimitry Andric         return false;
125ac9a064cSDimitry Andric 
126ac9a064cSDimitry Andric       if (auto *II = dyn_cast<IntrinsicInst>(I)) {
127ac9a064cSDimitry Andric         // Some intrinsics require a plain global.
128ac9a064cSDimitry Andric         if (II->getIntrinsicID() == Intrinsic::eh_typeid_for)
129ac9a064cSDimitry Andric           return false;
130ac9a064cSDimitry Andric       }
131ac9a064cSDimitry Andric 
132ac9a064cSDimitry Andric       // Other instruction users are always valid.
133b1c73532SDimitry Andric       continue;
134ac9a064cSDimitry Andric     }
135b1c73532SDimitry Andric 
136b1c73532SDimitry Andric     // We cannot replace GlobalValue users because they are not just nodes
137b1c73532SDimitry Andric     // in IR. To replace a user like this we would need to create a new
138b1c73532SDimitry Andric     // GlobalValue with the replacement and then try to delete the original
139b1c73532SDimitry Andric     // GlobalValue. Deleting the original would only happen if it has no other
140b1c73532SDimitry Andric     // uses.
141b1c73532SDimitry Andric     if (isa<GlobalValue>(CurrentUser))
142b1c73532SDimitry Andric       return false;
143b1c73532SDimitry Andric 
144b1c73532SDimitry Andric     // We only support Instruction and Constant users.
145b1c73532SDimitry Andric     if (!isa<Constant>(CurrentUser))
146b1c73532SDimitry Andric       return false;
147b1c73532SDimitry Andric   }
148b1c73532SDimitry Andric 
149b1c73532SDimitry Andric   return true;
150b1c73532SDimitry Andric }
151b1c73532SDimitry Andric 
152b1c73532SDimitry Andric // Run through all of the constants in the module and determine if they are
153b1c73532SDimitry Andric // valid candidates to be merged into the string pool. Valid candidates will
154b1c73532SDimitry Andric // be added to MergeableStrings.
collectCandidateConstants(Module & M)155b1c73532SDimitry Andric void PPCMergeStringPool::collectCandidateConstants(Module &M) {
156b1c73532SDimitry Andric   SmallVector<GlobalValue *, 4> UsedV;
157b1c73532SDimitry Andric   collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
158b1c73532SDimitry Andric   SmallVector<GlobalValue *, 4> UsedVCompiler;
159b1c73532SDimitry Andric   collectUsedGlobalVariables(M, UsedVCompiler, /*CompilerUsed=*/true);
160b1c73532SDimitry Andric   // Combine all of the Global Variables marked as used into a SmallPtrSet for
161b1c73532SDimitry Andric   // faster lookup inside the loop.
162b1c73532SDimitry Andric   SmallPtrSet<GlobalValue *, 8> AllUsedGlobals;
163b1c73532SDimitry Andric   AllUsedGlobals.insert(UsedV.begin(), UsedV.end());
164b1c73532SDimitry Andric   AllUsedGlobals.insert(UsedVCompiler.begin(), UsedVCompiler.end());
165b1c73532SDimitry Andric 
166b1c73532SDimitry Andric   for (GlobalVariable &Global : M.globals()) {
167b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "Looking at global:");
168b1c73532SDimitry Andric     LLVM_DEBUG(Global.dump());
169b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "isConstant() " << Global.isConstant() << "\n");
170b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "hasInitializer() " << Global.hasInitializer()
171b1c73532SDimitry Andric                       << "\n");
172b1c73532SDimitry Andric 
173cb288774SDimitry Andric     // We can only pool non-thread-local constants.
174cb288774SDimitry Andric     if (!Global.isConstant() || !Global.hasInitializer() ||
175cb288774SDimitry Andric         Global.isThreadLocal())
176b1c73532SDimitry Andric       continue;
177b1c73532SDimitry Andric 
178b1c73532SDimitry Andric     // If a global constant has a section we do not try to pool it because
179b1c73532SDimitry Andric     // there is no guarantee that other constants will also be in the same
180b1c73532SDimitry Andric     // section. Trying to pool constants from different sections (or no
181b1c73532SDimitry Andric     // section) means that the pool has to be in multiple sections at the same
182b1c73532SDimitry Andric     // time.
183b1c73532SDimitry Andric     if (Global.hasSection())
184b1c73532SDimitry Andric       continue;
185b1c73532SDimitry Andric 
186b1c73532SDimitry Andric     // Do not pool constants with metadata because we should not add metadata
187b1c73532SDimitry Andric     // to the pool when that metadata refers to a single constant in the pool.
188b1c73532SDimitry Andric     if (Global.hasMetadata())
189b1c73532SDimitry Andric       continue;
190b1c73532SDimitry Andric 
191b1c73532SDimitry Andric     ConstantDataSequential *ConstData =
192b1c73532SDimitry Andric         dyn_cast<ConstantDataSequential>(Global.getInitializer());
193b1c73532SDimitry Andric 
194b1c73532SDimitry Andric     // If the constant is undef then ConstData will be null.
195b1c73532SDimitry Andric     if (!ConstData)
196b1c73532SDimitry Andric       continue;
197b1c73532SDimitry Andric 
198b1c73532SDimitry Andric     // Do not pool globals that are part of llvm.used or llvm.compiler.end.
199b1c73532SDimitry Andric     if (AllUsedGlobals.contains(&Global))
200b1c73532SDimitry Andric       continue;
201b1c73532SDimitry Andric 
202b1c73532SDimitry Andric     if (!hasReplaceableUsers(Global))
203b1c73532SDimitry Andric       continue;
204b1c73532SDimitry Andric 
205b1c73532SDimitry Andric     Align AlignOfGlobal = Global.getAlign().valueOrOne();
206b1c73532SDimitry Andric 
207b1c73532SDimitry Andric     // TODO: At this point do not allow over-aligned types. Adding a type
208b1c73532SDimitry Andric     //       with larger alignment may lose the larger alignment once it is
209b1c73532SDimitry Andric     //       added to the struct.
210b1c73532SDimitry Andric     //       Fix this in a future patch.
211b1c73532SDimitry Andric     if (AlignOfGlobal.value() > ConstData->getElementByteSize())
212b1c73532SDimitry Andric       continue;
213b1c73532SDimitry Andric 
214b1c73532SDimitry Andric     // Make sure that the global is only visible inside the compilation unit.
215b1c73532SDimitry Andric     if (Global.getLinkage() != GlobalValue::PrivateLinkage &&
216b1c73532SDimitry Andric         Global.getLinkage() != GlobalValue::InternalLinkage)
217b1c73532SDimitry Andric       continue;
218b1c73532SDimitry Andric 
219b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "Constant data of Global: ");
220b1c73532SDimitry Andric     LLVM_DEBUG(ConstData->dump());
221b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "\n\n");
222b1c73532SDimitry Andric 
223b1c73532SDimitry Andric     MergeableStrings.push_back(&Global);
224b1c73532SDimitry Andric     if (MaxAlignment < AlignOfGlobal)
225b1c73532SDimitry Andric       MaxAlignment = AlignOfGlobal;
226b1c73532SDimitry Andric 
227b1c73532SDimitry Andric     // If we have already reached the maximum number of pooled strings then
228b1c73532SDimitry Andric     // there is no point in looking for more.
229b1c73532SDimitry Andric     if (MergeableStrings.size() >= MaxStringsPooled)
230b1c73532SDimitry Andric       break;
231b1c73532SDimitry Andric   }
232b1c73532SDimitry Andric }
233b1c73532SDimitry Andric 
mergeModuleStringPool(Module & M)234b1c73532SDimitry Andric bool PPCMergeStringPool::mergeModuleStringPool(Module &M) {
235b1c73532SDimitry Andric 
236b1c73532SDimitry Andric   LLVM_DEBUG(dbgs() << "Merging string pool for module: " << M.getName()
237b1c73532SDimitry Andric                     << "\n");
238b1c73532SDimitry Andric   LLVM_DEBUG(dbgs() << "Number of globals is: " << M.global_size() << "\n");
239b1c73532SDimitry Andric 
240b1c73532SDimitry Andric   collectCandidateConstants(M);
241b1c73532SDimitry Andric 
242b1c73532SDimitry Andric   // If we have too few constants in the module that are merge candidates we
243b1c73532SDimitry Andric   // will skip doing the merging.
244b1c73532SDimitry Andric   if (MergeableStrings.size() < MinStringsBeforePool)
245b1c73532SDimitry Andric     return false;
246b1c73532SDimitry Andric 
247b1c73532SDimitry Andric   // Sort the global constants to make access more efficient.
248b1c73532SDimitry Andric   std::sort(MergeableStrings.begin(), MergeableStrings.end(), CompareConstants);
249b1c73532SDimitry Andric 
250b1c73532SDimitry Andric   SmallVector<Constant *> ConstantsInStruct;
251b1c73532SDimitry Andric   for (GlobalVariable *GV : MergeableStrings)
252b1c73532SDimitry Andric     ConstantsInStruct.push_back(GV->getInitializer());
253b1c73532SDimitry Andric 
254b1c73532SDimitry Andric   // Use an anonymous struct to pool the strings.
255b1c73532SDimitry Andric   // TODO: This pass uses a single anonymous struct for all of the pooled
256b1c73532SDimitry Andric   // entries. This may cause a performance issue in the situation where
257b1c73532SDimitry Andric   // computing the offset requires two instructions (addis, addi). For the
258b1c73532SDimitry Andric   // future we may want to split this into multiple structs.
259b1c73532SDimitry Andric   Constant *ConstantPool = ConstantStruct::getAnon(ConstantsInStruct);
260b1c73532SDimitry Andric   PooledStructType = ConstantPool->getType();
261b1c73532SDimitry Andric 
262b1c73532SDimitry Andric   // The GlobalVariable constructor calls
263b1c73532SDimitry Andric   // MM->insertGlobalVariable(PooledGlobal).
264b1c73532SDimitry Andric   GlobalVariable *PooledGlobal =
265b1c73532SDimitry Andric       new GlobalVariable(M, PooledStructType,
266b1c73532SDimitry Andric                          /* isConstant */ true, GlobalValue::PrivateLinkage,
267b1c73532SDimitry Andric                          ConstantPool, "__ModuleStringPool");
268b1c73532SDimitry Andric   PooledGlobal->setAlignment(MaxAlignment);
269b1c73532SDimitry Andric 
270b1c73532SDimitry Andric   LLVM_DEBUG(dbgs() << "Constructing global variable for string pool: ");
271b1c73532SDimitry Andric   LLVM_DEBUG(PooledGlobal->dump());
272b1c73532SDimitry Andric 
273b1c73532SDimitry Andric   Context = &M.getContext();
274b1c73532SDimitry Andric   size_t ElementIndex = 0;
275b1c73532SDimitry Andric   for (GlobalVariable *GV : MergeableStrings) {
276b1c73532SDimitry Andric 
277b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "The global:\n");
278b1c73532SDimitry Andric     LLVM_DEBUG(GV->dump());
279b1c73532SDimitry Andric     LLVM_DEBUG(dbgs() << "Has " << GV->getNumUses() << " uses.\n");
280b1c73532SDimitry Andric 
281b1c73532SDimitry Andric     // Access to the pooled constant strings require an offset. Add a GEP
282b1c73532SDimitry Andric     // before every use in order to compute this offset.
283b1c73532SDimitry Andric     replaceUsesWithGEP(GV, PooledGlobal, ElementIndex);
284b1c73532SDimitry Andric 
285ac9a064cSDimitry Andric     // Replace all the uses by metadata.
286ac9a064cSDimitry Andric     if (GV->isUsedByMetadata()) {
287ac9a064cSDimitry Andric       Constant *Indices[2] = {
288ac9a064cSDimitry Andric           ConstantInt::get(Type::getInt32Ty(*Context), 0),
289ac9a064cSDimitry Andric           ConstantInt::get(Type::getInt32Ty(*Context), ElementIndex)};
290ac9a064cSDimitry Andric       Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr(
291ac9a064cSDimitry Andric           PooledStructType, PooledGlobal, Indices);
292ac9a064cSDimitry Andric       ValueAsMetadata::handleRAUW(GV, ConstGEP);
293ac9a064cSDimitry Andric     }
294ac9a064cSDimitry Andric     assert(!GV->isUsedByMetadata() && "Should be no metadata use anymore");
295ac9a064cSDimitry Andric 
296b1c73532SDimitry Andric     // This GV has no more uses so we can erase it.
297b1c73532SDimitry Andric     if (GV->use_empty())
298b1c73532SDimitry Andric       GV->eraseFromParent();
299b1c73532SDimitry Andric 
300b1c73532SDimitry Andric     NumPooledStrings++;
301b1c73532SDimitry Andric     ElementIndex++;
302b1c73532SDimitry Andric   }
303b1c73532SDimitry Andric   return true;
304b1c73532SDimitry Andric }
305b1c73532SDimitry Andric 
306b1c73532SDimitry Andric // For pooled strings we need to add the offset into the pool for each string.
307b1c73532SDimitry Andric // This is done by adding a Get Element Pointer (GEP) before each user. This
308b1c73532SDimitry Andric // function adds the GEP.
replaceUsesWithGEP(GlobalVariable * GlobalToReplace,GlobalVariable * GPool,unsigned ElementIndex)309b1c73532SDimitry Andric void PPCMergeStringPool::replaceUsesWithGEP(GlobalVariable *GlobalToReplace,
310b1c73532SDimitry Andric                                             GlobalVariable *GPool,
311b1c73532SDimitry Andric                                             unsigned ElementIndex) {
312b1c73532SDimitry Andric   SmallVector<Value *, 2> Indices;
313b1c73532SDimitry Andric   Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), 0));
314b1c73532SDimitry Andric   Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), ElementIndex));
315b1c73532SDimitry Andric 
316ac9a064cSDimitry Andric   Constant *ConstGEP =
317ac9a064cSDimitry Andric       ConstantExpr::getInBoundsGetElementPtr(PooledStructType, GPool, Indices);
318b1c73532SDimitry Andric   LLVM_DEBUG(dbgs() << "Replacing this global:\n");
319b1c73532SDimitry Andric   LLVM_DEBUG(GlobalToReplace->dump());
320b1c73532SDimitry Andric   LLVM_DEBUG(dbgs() << "with this:\n");
321ac9a064cSDimitry Andric   LLVM_DEBUG(ConstGEP->dump());
322ac9a064cSDimitry Andric   GlobalToReplace->replaceAllUsesWith(ConstGEP);
323b1c73532SDimitry Andric }
324b1c73532SDimitry Andric 
325b1c73532SDimitry Andric } // namespace
326b1c73532SDimitry Andric 
327b1c73532SDimitry Andric char PPCMergeStringPool::ID = 0;
328b1c73532SDimitry Andric 
329b1c73532SDimitry Andric INITIALIZE_PASS(PPCMergeStringPool, DEBUG_TYPE, "PPC Merge String Pool", false,
330b1c73532SDimitry Andric                 false)
331b1c73532SDimitry Andric 
createPPCMergeStringPoolPass()332b1c73532SDimitry Andric ModulePass *llvm::createPPCMergeStringPoolPass() {
333b1c73532SDimitry Andric   return new PPCMergeStringPool();
334b1c73532SDimitry Andric }
335