summaryrefslogtreecommitdiff
path: root/include/llvm/Support/StandardPasses.h
blob: 024c0194d4e0a0a6758475474e5a18f9f8bf9168 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
//===-- llvm/Support/StandardPasses.h - Standard pass lists -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines utility functions for creating a "standard" set of
// optimization passes, so that compilers and tools which use optimization
// passes use the same set of standard passes.
//
// These are implemented as inline functions so that we do not have to worry
// about link issues.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_STANDARDPASSES_H
#define LLVM_SUPPORT_STANDARDPASSES_H

#include "llvm/PassManager.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"

namespace llvm {
  /// createStandardFunctionPasses - Add the standard list of function passes to
  /// the provided pass manager.
  ///
  /// \arg OptimizationLevel - The optimization level, corresponding to -O0,
  /// -O1, etc.
  static inline void createStandardFunctionPasses(FunctionPassManager *PM,
                                                  unsigned OptimizationLevel);

  /// createStandardModulePasses - Add the standard list of module passes to the
  /// provided pass manager.
  ///
  /// \arg OptimizationLevel - The optimization level, corresponding to -O0,
  /// -O1, etc.
  /// \arg OptimizeSize - Whether the transformations should optimize for size.
  /// \arg UnitAtATime - Allow passes which may make global module changes.
  /// \arg UnrollLoops - Allow loop unrolling.
  /// \arg SimplifyLibCalls - Allow library calls to be simplified.
  /// \arg HaveExceptions - Whether the module may have code using exceptions.
  /// \arg InliningPass - The inlining pass to use, if any, or null. This will
  /// always be added, even at -O0.a
  static inline void createStandardModulePasses(PassManager *PM,
                                                unsigned OptimizationLevel,
                                                bool OptimizeSize,
                                                bool UnitAtATime,
                                                bool UnrollLoops,
                                                bool SimplifyLibCalls,
                                                bool HaveExceptions,
                                                Pass *InliningPass);

  /// createStandardLTOPasses - Add the standard list of module passes suitable
  /// for link time optimization.
  ///
  /// Internalize - Run the internalize pass.
  /// RunInliner - Use a function inlining pass.
  /// RunSecondGlobalOpt - Run the global optimizer pass twice.
  /// VerifyEach - Run the verifier after each pass.
  //
  // FIXME: RunSecondGlobalOpt should go away once we resolve which of LTO or
  // llvm-ld is better.
  static inline void createStandardLTOPasses(PassManager *PM,
                                             bool Internalize,
                                             bool RunInliner,
                                             bool RunSecondGlobalOpt,
                                             bool VerifyEach);

  // Implementations

  static inline void createStandardFunctionPasses(FunctionPassManager *PM,
                                                  unsigned OptimizationLevel) {
    if (OptimizationLevel > 0) {
      PM->add(createCFGSimplificationPass());
      if (OptimizationLevel == 1)
        PM->add(createPromoteMemoryToRegisterPass());
      else
        PM->add(createScalarReplAggregatesPass());
      PM->add(createInstructionCombiningPass());
    }
  }

  static inline void createStandardModulePasses(PassManager *PM,
                                                unsigned OptimizationLevel,
                                                bool OptimizeSize,
                                                bool UnitAtATime,
                                                bool UnrollLoops,
                                                bool SimplifyLibCalls,
                                                bool HaveExceptions,
                                                Pass *InliningPass) {
    if (OptimizationLevel == 0) {
      if (InliningPass)
        PM->add(InliningPass);
    } else {
      if (UnitAtATime)
        PM->add(createRaiseAllocationsPass());    // call %malloc -> malloc inst
      PM->add(createCFGSimplificationPass());     // Clean up disgusting code
       // Kill useless allocas
      PM->add(createPromoteMemoryToRegisterPass());
      if (UnitAtATime) {
        PM->add(createGlobalOptimizerPass());     // Optimize out global vars
        PM->add(createGlobalDCEPass());           // Remove unused fns and globs
        // IP Constant Propagation
        PM->add(createIPConstantPropagationPass());
        PM->add(createDeadArgEliminationPass());  // Dead argument elimination
      }
      PM->add(createInstructionCombiningPass());  // Clean up after IPCP & DAE
      PM->add(createCFGSimplificationPass());     // Clean up after IPCP & DAE
      if (UnitAtATime) {
        if (HaveExceptions)
          PM->add(createPruneEHPass());           // Remove dead EH info
        PM->add(createFunctionAttrsPass());       // Set readonly/readnone attrs
      }
      if (InliningPass)
        PM->add(InliningPass);
      if (OptimizationLevel > 2)
        PM->add(createArgumentPromotionPass());   // Scalarize uninlined fn args
      if (SimplifyLibCalls)
        PM->add(createSimplifyLibCallsPass());    // Library Call Optimizations
      PM->add(createInstructionCombiningPass());  // Cleanup for scalarrepl.
      PM->add(createJumpThreadingPass());         // Thread jumps.
      PM->add(createCFGSimplificationPass());     // Merge & remove BBs
      PM->add(createScalarReplAggregatesPass());  // Break up aggregate allocas
      PM->add(createInstructionCombiningPass());  // Combine silly seq's
      PM->add(createCondPropagationPass());       // Propagate conditionals
      PM->add(createTailCallEliminationPass());   // Eliminate tail calls
      PM->add(createCFGSimplificationPass());     // Merge & remove BBs
      PM->add(createReassociatePass());           // Reassociate expressions
      PM->add(createLoopRotatePass());            // Rotate Loop
      PM->add(createLICMPass());                  // Hoist loop invariants
      PM->add(createLoopUnswitchPass(OptimizeSize));
      PM->add(createLoopIndexSplitPass());        // Split loop index
      PM->add(createInstructionCombiningPass());  
      PM->add(createIndVarSimplifyPass());        // Canonicalize indvars
      PM->add(createLoopDeletionPass());          // Delete dead loops
      if (UnrollLoops)
        PM->add(createLoopUnrollPass());          // Unroll small loops
      PM->add(createInstructionCombiningPass());  // Clean up after the unroller
      PM->add(createGVNPass());                   // Remove redundancies
      PM->add(createMemCpyOptPass());             // Remove memcpy / form memset
      PM->add(createSCCPPass());                  // Constant prop with SCCP
    
      // Run instcombine after redundancy elimination to exploit opportunities
      // opened up by them.
      PM->add(createInstructionCombiningPass());
      PM->add(createCondPropagationPass());       // Propagate conditionals
      PM->add(createDeadStoreEliminationPass());  // Delete dead stores
      PM->add(createAggressiveDCEPass());         // Delete dead instructions
      PM->add(createCFGSimplificationPass());     // Merge & remove BBs

      if (UnitAtATime) {
        PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
        PM->add(createDeadTypeEliminationPass()); // Eliminate dead types
      }

      if (OptimizationLevel > 1 && UnitAtATime)
        PM->add(createConstantMergePass());       // Merge dup global constants
    }
  }

  static inline void addOnePass(PassManager *PM, Pass *P, bool AndVerify) {
    PM->add(P);

    if (AndVerify)
      PM->add(createVerifierPass());
  }

  static inline void createStandardLTOPasses(PassManager *PM,
                                             bool Internalize,
                                             bool RunInliner,
                                             bool RunSecondGlobalOpt,
                                             bool VerifyEach) {
    // Now that composite has been compiled, scan through the module, looking
    // for a main function.  If main is defined, mark all other functions
    // internal.
    if (Internalize)
      addOnePass(PM, createInternalizePass(true), VerifyEach);

    // Propagate constants at call sites into the functions they call.  This
    // opens opportunities for globalopt (and inlining) by substituting function
    // pointers passed as arguments to direct uses of functions.  
    addOnePass(PM, createIPSCCPPass(), VerifyEach);

    // Now that we internalized some globals, see if we can hack on them!
    addOnePass(PM, createGlobalOptimizerPass(), VerifyEach);
    
    // Linking modules together can lead to duplicated global constants, only
    // keep one copy of each constant...
    addOnePass(PM, createConstantMergePass(), VerifyEach);
    
    // Remove unused arguments from functions...
    addOnePass(PM, createDeadArgEliminationPass(), VerifyEach);

    // Reduce the code after globalopt and ipsccp.  Both can open up significant
    // simplification opportunities, and both can propagate functions through
    // function pointers.  When this happens, we often have to resolve varargs
    // calls, etc, so let instcombine do this.
    addOnePass(PM, createInstructionCombiningPass(), VerifyEach);

    // Inline small functions
    if (RunInliner)
      addOnePass(PM, createFunctionInliningPass(), VerifyEach);

    addOnePass(PM, createPruneEHPass(), VerifyEach);   // Remove dead EH info.
    // Optimize globals again.
    if (RunSecondGlobalOpt)
      addOnePass(PM, createGlobalOptimizerPass(), VerifyEach);
    addOnePass(PM, createGlobalDCEPass(), VerifyEach); // Remove dead functions.

    // If we didn't decide to inline a function, check to see if we can
    // transform it to pass arguments by value instead of by reference.
    addOnePass(PM, createArgumentPromotionPass(), VerifyEach);

    // The IPO passes may leave cruft around.  Clean up after them.
    addOnePass(PM, createInstructionCombiningPass(), VerifyEach);
    addOnePass(PM, createJumpThreadingPass(), VerifyEach);
    // Break up allocas
    addOnePass(PM, createScalarReplAggregatesPass(), VerifyEach);

    // Run a few AA driven optimizations here and now, to cleanup the code.
    addOnePass(PM, createFunctionAttrsPass(), VerifyEach); // Add nocapture.
    addOnePass(PM, createGlobalsModRefPass(), VerifyEach); // IP alias analysis.

    addOnePass(PM, createLICMPass(), VerifyEach);      // Hoist loop invariants.
    addOnePass(PM, createGVNPass(), VerifyEach);       // Remove redundancies.
    addOnePass(PM, createMemCpyOptPass(), VerifyEach); // Remove dead memcpys.
    // Nuke dead stores.
    addOnePass(PM, createDeadStoreEliminationPass(), VerifyEach);

    // Cleanup and simplify the code after the scalar optimizations.
    addOnePass(PM, createInstructionCombiningPass(), VerifyEach);

    addOnePass(PM, createJumpThreadingPass(), VerifyEach);
    // Cleanup jump threading.
    addOnePass(PM, createPromoteMemoryToRegisterPass(), VerifyEach);
    
    // Delete basic blocks, which optimization passes may have killed...
    addOnePass(PM, createCFGSimplificationPass(), VerifyEach);

    // Now that we have optimized the program, discard unreachable functions.
    addOnePass(PM, createGlobalDCEPass(), VerifyEach);
  }
}

#endif