lto.cpp revision 998051a2211a5f86b38941de0aca241b34895e1e
1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===//
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//                     The LLVM Compiler Infrastructure
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// This file was developed by Devang Patel and is distributed under
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// the University of Illinois Open Source License. See LICENSE.TXT for details.
7727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease//
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//===----------------------------------------------------------------------===//
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// This file implementes link time optimization library. This library is
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// intended to be used by linker to optimize code at link time.
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project//===----------------------------------------------------------------------===//
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Module.h"
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/PassManager.h"
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Linker.h"
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Constants.h"
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/DerivedTypes.h"
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/SymbolTable.h"
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Bytecode/Reader.h"
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Bytecode/Writer.h"
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Support/CommandLine.h"
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Support/FileUtilities.h"
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Support/SystemUtils.h"
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Support/Mangler.h"
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/System/Program.h"
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/System/Signals.h"
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Analysis/Passes.h"
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Analysis/Verifier.h"
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Target/SubtargetFeature.h"
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Target/TargetData.h"
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Target/TargetMachine.h"
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Target/TargetMachineRegistry.h"
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Transforms/IPO.h"
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Transforms/Scalar.h"
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/Analysis/LoadValueNumbering.h"
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "llvm/LinkTimeOptimizer.h"
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <fstream>
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <iostream>
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectusing namespace llvm;
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectextern "C"
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectllvm::LinkTimeOptimizer *createLLVMOptimizer()
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project{
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  llvm::LinkTimeOptimizer *l = new llvm::LinkTimeOptimizer();
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  return l;
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// If symbol is not used then make it internal and let optimizer takes
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// care of it.
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectvoid LLVMSymbol::mayBeNotUsed() {
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gv->setLinkage(GlobalValue::InternalLinkage);
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// Helper routine
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// FIXME : Take advantage of GlobalPrefix from AsmPrinter
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectstatic const char *addUnderscore(const char *name) {
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  size_t namelen = strlen(name);
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  char *symName = (char*)malloc(namelen+2);
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  symName[0] = '_';
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  strcpy(&symName[1], name);
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  return symName;
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// Map LLVM LinkageType to LTO LinakgeType
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectstatic LTOLinkageTypes
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source ProjectgetLTOLinkageType(GlobalValue *v)
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project{
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  LTOLinkageTypes lt;
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (v->hasExternalLinkage())
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    lt = LTOExternalLinkage;
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  else if (v->hasLinkOnceLinkage())
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    lt = LTOLinkOnceLinkage;
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  else if (v->hasWeakLinkage())
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    lt = LTOWeakLinkage;
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  else
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    // Otherwise it is internal linkage for link time optimizer
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    lt = LTOInternalLinkage;
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  return lt;
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project// Find exeternal symbols referenced by VALUE. This is a recursive function.
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectstatic void
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source ProjectfindExternalRefs(Value *value, std::set<std::string> &references,
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 Mangler &mangler) {
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (GlobalValue *gv = dyn_cast<GlobalValue>(value)) {
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    LTOLinkageTypes lt = getLTOLinkageType(gv);
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (lt != LTOInternalLinkage && strncmp (gv->getName().c_str(), "llvm.", 5))
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      references.insert(mangler.getValueName(gv));
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  else if (Constant *c = dyn_cast<Constant>(value))
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    // Handle ConstantExpr, ConstantStruct, ConstantArry etc..
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i)
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      findExternalRefs(c->getOperand(i), references, mangler);
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// InputFilename is a LLVM bytecode file. If Module with InputFilename is
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// available then return it. Otherwise parseInputFilename.
104ec0bab5697bb31ba980810145f62e3799946ec60Victoria LeaseModule *
105ec0bab5697bb31ba980810145f62e3799946ec60Victoria LeaseLinkTimeOptimizer::getModule(const std::string &InputFilename)
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project{
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Module *m = NULL;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  NameToModuleMap::iterator pos = allModules.find(InputFilename.c_str());
110727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  if (pos != allModules.end())
111727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    m = allModules[InputFilename.c_str()];
112727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  else {
113727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    m = ParseBytecodeFile(InputFilename);
114727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    allModules[InputFilename.c_str()] = m;
115727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
116727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  return m;
117727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease}
118727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
119727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/// InputFilename is a LLVM bytecode file. Reade this bytecode file and
120727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/// set corresponding target triplet string.
121727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Leasevoid
122727dee178a392d20eb050d0c446f2fcc29058fa1Victoria LeaseLinkTimeOptimizer::getTargetTriple(const std::string &InputFilename,
123727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease				   std::string &targetTriple)
124727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease{
125727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Module *m = getModule(InputFilename);
126727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  if (m)
127727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    targetTriple = m->getTargetTriple();
128727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease}
129727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
130727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/// InputFilename is a LLVM bytecode file. Read it using bytecode reader.
131727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/// Collect global functions and symbol names in symbols vector.
132727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/// Collect external references in references vector.
133727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease/// Return LTO_READ_SUCCESS if there is no error.
134727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Leaseenum LTOStatus
135727dee178a392d20eb050d0c446f2fcc29058fa1Victoria LeaseLinkTimeOptimizer::readLLVMObjectFile(const std::string &InputFilename,
136727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                      NameToSymbolMap &symbols,
137727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                                      std::set<std::string> &references)
138727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease{
139727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Module *m = getModule(InputFilename);
140727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  if (!m)
141727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return LTO_READ_FAILURE;
142727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
143727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // Use mangler to add GlobalPrefix to names to match linker names.
144727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // FIXME : Instead of hard coding "-" use GlobalPrefix.
145727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Mangler mangler(*m, "_");
146727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
147727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  modules.push_back(m);
148727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
149727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  for (Module::iterator f = m->begin(), e = m->end(); f != e; ++f) {
150727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
151727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    LTOLinkageTypes lt = getLTOLinkageType(f);
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (!f->isExternal() && lt != LTOInternalLinkage
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        && strncmp (f->getName().c_str(), "llvm.", 5)) {
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      LLVMSymbol *newSymbol = new LLVMSymbol(lt, f, f->getName(),
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             mangler.getValueName(f));
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      symbols[newSymbol->getMangledName()] = newSymbol;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      allSymbols[newSymbol->getMangledName()] = newSymbol;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    // Collect external symbols referenced by this function.
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for (Function::iterator b = f->begin(), fe = f->end(); b != fe; ++b)
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (BasicBlock::iterator i = b->begin(), be = b->end();
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           i != be; ++i)
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for (unsigned count = 0, total = i->getNumOperands();
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             count != total; ++count)
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          findExternalRefs(i->getOperand(count), references, mangler);
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  for (Module::global_iterator v = m->global_begin(), e = m->global_end();
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       v !=  e; ++v) {
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    LTOLinkageTypes lt = getLTOLinkageType(v);
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (!v->isExternal() && lt != LTOInternalLinkage
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        && strncmp (v->getName().c_str(), "llvm.", 5)) {
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      LLVMSymbol *newSymbol = new LLVMSymbol(lt, v, v->getName(),
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             mangler.getValueName(v));
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      symbols[newSymbol->getMangledName()] = newSymbol;
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      allSymbols[newSymbol->getMangledName()] = newSymbol;
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for (unsigned count = 0, total = v->getNumOperands();
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           count != total; ++count)
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        findExternalRefs(v->getOperand(count), references, mangler);
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  return LTO_READ_SUCCESS;
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// Optimize module M using various IPO passes. Use exportList to
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// internalize selected symbols. Target platform is selected
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// based on information available to module M. No new target
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// features are selected.
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectstatic enum LTOStatus lto_optimize(Module *M, std::ostream &Out,
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   std::vector<const char *> &exportList)
196aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich{
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Instantiate the pass manager to organize the passes.
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  PassManager Passes;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Collect Target info
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::string Err;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const TargetMachineRegistry::Entry* March =
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TargetMachineRegistry::getClosestStaticTargetForModule(*M, Err);
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (March == 0)
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return LTO_NO_TARGET;
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Create target
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::string Features;
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::auto_ptr<TargetMachine> target(March->CtorFn(*M, Features));
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (!target.get())
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return LTO_NO_TARGET;
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TargetMachine &Target = *target.get();
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Start off with a verification pass.
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createVerifierPass());
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Add an appropriate TargetData instance for this module...
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(new TargetData(*Target.getTargetData()));
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Often if the programmer does not specify proper prototypes for the
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // functions they are calling, they end up calling a vararg version of the
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // function that does not get a body filled in (the real function has typed
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // arguments).  This pass merges the two functions.
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createFunctionResolvingPass());
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Internalize symbols if export list is nonemty
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (!exportList.empty())
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Passes.add(createInternalizePass(exportList));
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Now that we internalized some globals, see if we can hack on them!
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createGlobalOptimizerPass());
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Linking modules together can lead to duplicated global constants, only
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // keep one copy of each constant...
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createConstantMergePass());
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // If the -s command line option was specified, strip the symbols out of the
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // resulting program to make it smaller.  -s is a GLD option that we are
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // supporting.
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createStripSymbolsPass());
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Propagate constants at call sites into the functions they call.
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createIPConstantPropagationPass());
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Remove unused arguments from functions...
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createDeadArgEliminationPass());
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createFunctionInliningPass()); // Inline small functions
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createPruneEHPass());            // Remove dead EH info
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createGlobalDCEPass());          // Remove dead functions
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // If we didn't decide to inline a function, check to see if we can
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // transform it to pass arguments by value instead of by reference.
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createArgumentPromotionPass());
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // The IPO passes may leave cruft around.  Clean up after them.
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.add(createInstructionCombiningPass());
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
263727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createScalarReplAggregatesPass()); // Break up allocas
264727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
265727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // Run a few AA driven optimizations here and now, to cleanup the code.
266ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  Passes.add(createGlobalsModRefPass());      // IP alias analysis
267727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
268727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createLICMPass());               // Hoist loop invariants
269ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  Passes.add(createLoadValueNumberingPass()); // GVN for load instrs
270727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createGCSEPass());               // Remove common subexprs
271727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createDeadStoreEliminationPass()); // Nuke dead stores
272727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
273727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // Cleanup and simplify the code after the scalar optimizations.
274727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createInstructionCombiningPass());
275727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
276727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // Delete basic blocks, which optimization passes may have killed...
277727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createCFGSimplificationPass());
278727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
279727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // Now that we have optimized the program, discard unreachable functions...
280727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createGlobalDCEPass());
281727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
282727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  // Make sure everything is still good.
283727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Passes.add(createVerifierPass());
284727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
285727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FunctionPassManager *CodeGenPasses =
286727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    new FunctionPassManager(new ExistingModuleProvider(M));
287727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
288727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  CodeGenPasses->add(new TargetData(*Target.getTargetData()));
289727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Target.addPassesToEmitFile(*CodeGenPasses, Out, TargetMachine::AssemblyFile,
290727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease			     true);
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Run our queue of passes all at once now, efficiently.
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Passes.run(*M);
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Run the code generator, if present.
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  CodeGenPasses->doInitialization();
297727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (!I->isExternal())
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      CodeGenPasses->run(*I);
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  CodeGenPasses->doFinalization();
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  return LTO_OPT_SUCCESS;
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project///Link all modules together and optimize them using IPO. Generate
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// native object file using OutputFilename
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/// Return appropriate LTOStatus.
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectenum LTOStatus
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source ProjectLinkTimeOptimizer::optimizeModules(const std::string &OutputFilename,
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   std::vector<const char *> &exportList,
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   std::string &targetTriple)
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project{
314aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  if (modules.empty())
315aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    return LTO_NO_WORK;
316aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
317aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  std::ios::openmode io_mode =
318aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    std::ios::out | std::ios::trunc | std::ios::binary;
319aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  std::string *errMsg = NULL;
320727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  Module *bigOne = modules[0];
321aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  Linker theLinker("LinkTimeOptimizer", bigOne, false);
322aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  for (unsigned i = 1, e = modules.size(); i != e; ++i)
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (theLinker.LinkModules(bigOne, modules[i], errMsg))
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return LTO_MODULE_MERGE_FAILURE;
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Enable this when -save-temps is used
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::ofstream Out("big.bc", io_mode);
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  WriteBytecodeToFile(bigOne, Out, true);
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Strip leading underscore because it was added to match names
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // seen by linker.
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  for (unsigned i = 0, e = exportList.size(); i != e; ++i) {
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    const char *name = exportList[i];
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    NameToSymbolMap::iterator itr = allSymbols.find(name);
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (itr != allSymbols.end())
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      exportList[i] = allSymbols[name]->getName();
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  sys::Path tmpAsmFilePath("/tmp/");
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::string ErrMsg;
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (tmpAsmFilePath.createTemporaryFileOnDisk(&ErrMsg)) {
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    std::cerr << "lto: " << ErrMsg << "\n";
345727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return LTO_WRITE_FAILURE;
346727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  sys::RemoveFileOnSignal(tmpAsmFilePath);
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::ofstream asmFile(tmpAsmFilePath.c_str(), io_mode);
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (!asmFile.is_open() || asmFile.bad()) {
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if (tmpAsmFilePath.exists())
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tmpAsmFilePath.eraseFromDisk();
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return LTO_WRITE_FAILURE;
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  enum LTOStatus status = lto_optimize(bigOne, asmFile, exportList);
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  asmFile.close();
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (status != LTO_OPT_SUCCESS) {
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tmpAsmFilePath.eraseFromDisk();
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return status;
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
362727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  targetTriple = bigOne->getTargetTriple();
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Run GCC to assemble and link the program into native code.
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  //
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  // Note:
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  //  We can't just assemble and link the file with the system assembler
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  //  and linker because we don't know where to put the _start symbol.
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  //  GCC mysteriously knows how to do it.
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  const sys::Path gcc = FindExecutable("gcc", "/");
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  if (gcc.isEmpty()) {
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tmpAsmFilePath.eraseFromDisk();
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return LTO_ASM_FAILURE;
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  std::vector<const char*> args;
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back(gcc.c_str());
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back("-c");
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back("-x");
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back("assembler");
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back("-o");
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back(OutputFilename.c_str());
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back(tmpAsmFilePath.c_str());
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  args.push_back(0);
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 1);
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tmpAsmFilePath.eraseFromDisk();
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  return LTO_OPT_SUCCESS;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project}
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project