OLD | NEW |
1 //===-- PNaClABISimplify.cpp - Lists PNaCl ABI simplification passes ------===// | 1 //===-- PNaClABISimplify.cpp - Lists PNaCl ABI simplification passes ------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the meta-passes "-pnacl-abi-simplify-preopt" | 10 // This file implements the meta-passes "-pnacl-abi-simplify-preopt" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "llvm/Transforms/Scalar.h" | 21 #include "llvm/Transforms/Scalar.h" |
22 | 22 |
23 using namespace llvm; | 23 using namespace llvm; |
24 | 24 |
25 static cl::opt<bool> | 25 static cl::opt<bool> |
26 EnableSjLjEH("enable-pnacl-sjlj-eh", | 26 EnableSjLjEH("enable-pnacl-sjlj-eh", |
27 cl::desc("Enable use of SJLJ-based C++ exception handling " | 27 cl::desc("Enable use of SJLJ-based C++ exception handling " |
28 "as part of the pnacl-abi-simplify passes"), | 28 "as part of the pnacl-abi-simplify passes"), |
29 cl::init(false)); | 29 cl::init(false)); |
30 | 30 |
31 // Emscripten options: | |
32 static cl::opt<bool> | |
33 EnableEmCxxExceptions("enable-emscripten-cxx-exceptions", | |
34 cl::desc("Enables C++ exceptions in emscripten"), | |
35 cl::init(false)); | |
36 | |
37 static cl::opt<bool> EnableEmAsyncify( | |
38 "emscripten-asyncify", | |
39 cl::desc("Enable asyncify transformation (see emscripten ASYNCIFY option)"), | |
40 cl::init(false)); | |
41 // Emscripten options end. | |
42 | |
43 void llvm::PNaClABISimplifyAddPreOptPasses(Triple *T, PassManagerBase &PM) { | 31 void llvm::PNaClABISimplifyAddPreOptPasses(Triple *T, PassManagerBase &PM) { |
44 bool isEmscripten = T->isOSEmscripten(); | |
45 | |
46 PM.add(createStripDanglingDISubprogramsPass()); | 32 PM.add(createStripDanglingDISubprogramsPass()); |
47 if (EnableSjLjEH) { | 33 if (EnableSjLjEH) { |
48 // This comes before ExpandTls because it introduces references to | 34 // This comes before ExpandTls because it introduces references to |
49 // a TLS variable, __pnacl_eh_stack. This comes before | 35 // a TLS variable, __pnacl_eh_stack. This comes before |
50 // InternalizePass because it assumes various variables (including | 36 // InternalizePass because it assumes various variables (including |
51 // __pnacl_eh_stack) have not been internalized yet. | 37 // __pnacl_eh_stack) have not been internalized yet. |
52 PM.add(createPNaClSjLjEHPass()); | 38 PM.add(createPNaClSjLjEHPass()); |
53 } else if (EnableEmCxxExceptions) { | |
54 PM.add(createLowerEmExceptionsPass()); | |
55 } else { | 39 } else { |
56 // LowerInvoke prevents use of C++ exception handling by removing | 40 // LowerInvoke prevents use of C++ exception handling by removing |
57 // references to BasicBlocks which handle exceptions. | 41 // references to BasicBlocks which handle exceptions. |
58 PM.add(createLowerInvokePass()); | 42 PM.add(createLowerInvokePass()); |
59 } | 43 } |
60 // Run CFG simplification passes for a few reasons: | 44 // Run CFG simplification passes for a few reasons: |
61 // (1) Landingpad blocks can be made unreachable by LowerInvoke | 45 // (1) Landingpad blocks can be made unreachable by LowerInvoke |
62 // when EnableSjLjEH is not enabled, so clean those up to ensure | 46 // when EnableSjLjEH is not enabled, so clean those up to ensure |
63 // there are no landingpad instructions in the stable ABI. | 47 // there are no landingpad instructions in the stable ABI. |
64 // (2) Unreachable blocks can have strange properties like self-referencing | 48 // (2) Unreachable blocks can have strange properties like self-referencing |
65 // instructions, so remove them. | 49 // instructions, so remove them. |
66 PM.add(createCFGSimplificationPass()); | 50 PM.add(createCFGSimplificationPass()); |
67 | 51 |
68 if (isEmscripten) | |
69 PM.add(createLowerEmSetjmpPass()); | |
70 | |
71 // Internalize all symbols in the module except the entry point. A PNaCl | 52 // Internalize all symbols in the module except the entry point. A PNaCl |
72 // pexe is only allowed to export "_start", whereas a PNaCl PSO is only | 53 // pexe is only allowed to export "_start", whereas a PNaCl PSO is only |
73 // allowed to export "__pnacl_pso_root". | 54 // allowed to export "__pnacl_pso_root". |
74 const char *SymbolsToPreserve[] = {"_start", "__pnacl_pso_root"}; | 55 const char *SymbolsToPreserve[] = {"_start", "__pnacl_pso_root"}; |
75 if (!isEmscripten) // Preserve arbitrary symbols. | 56 PM.add(createInternalizePass(SymbolsToPreserve)); |
76 PM.add(createInternalizePass(SymbolsToPreserve)); | 57 PM.add(createInternalizeUsedGlobalsPass()); |
77 if (!isEmscripten) | |
78 PM.add(createInternalizeUsedGlobalsPass()); | |
79 | 58 |
80 // Expand out computed gotos (indirectbr and blockaddresses) into switches. | 59 // Expand out computed gotos (indirectbr and blockaddresses) into switches. |
81 PM.add(createExpandIndirectBrPass()); | 60 PM.add(createExpandIndirectBrPass()); |
82 | 61 |
83 // LowerExpect converts Intrinsic::expect into branch weights, | 62 // LowerExpect converts Intrinsic::expect into branch weights, |
84 // which can then be removed after BlockPlacement. | 63 // which can then be removed after BlockPlacement. |
85 if (!isEmscripten) // JSBackend supports the expect intrinsic. | 64 PM.add(createLowerExpectIntrinsicPass()); |
86 PM.add(createLowerExpectIntrinsicPass()); | |
87 | 65 |
88 // Rewrite unsupported intrinsics to simpler and portable constructs. | 66 // Rewrite unsupported intrinsics to simpler and portable constructs. |
89 if (!isEmscripten) | 67 PM.add(createRewriteLLVMIntrinsicsPass()); |
90 PM.add(createRewriteLLVMIntrinsicsPass()); | |
91 | 68 |
92 // ExpandStructRegs must be run after ExpandVarArgs so that struct-typed | 69 // ExpandStructRegs must be run after ExpandVarArgs so that struct-typed |
93 // "va_arg" instructions have been removed. | 70 // "va_arg" instructions have been removed. |
94 PM.add(createExpandVarArgsPass()); | 71 PM.add(createExpandVarArgsPass()); |
95 | 72 |
96 // Convert struct reg function params to struct* byval. This needs to be | 73 // Convert struct reg function params to struct* byval. This needs to be |
97 // before ExpandStructRegs so it has a chance to rewrite aggregates from | 74 // before ExpandStructRegs so it has a chance to rewrite aggregates from |
98 // function arguments and returns into something ExpandStructRegs can expand. | 75 // function arguments and returns into something ExpandStructRegs can expand. |
99 PM.add(createSimplifyStructRegSignaturesPass()); | 76 PM.add(createSimplifyStructRegSignaturesPass()); |
100 | 77 |
101 // TODO(mtrofin) Remove the following and only run it as a post-opt pass once | 78 // TODO(mtrofin) Remove the following and only run it as a post-opt pass once |
102 // the following bug is fixed. | 79 // the following bug is fixed. |
103 // https://code.google.com/p/nativeclient/issues/detail?id=3857 | 80 // https://code.google.com/p/nativeclient/issues/detail?id=3857 |
104 PM.add(createExpandStructRegsPass()); | 81 PM.add(createExpandStructRegsPass()); |
105 | 82 |
106 PM.add(createExpandCtorsPass()); | 83 PM.add(createExpandCtorsPass()); |
107 | 84 |
108 if (!isEmscripten) // Handled by JSBackend. | 85 PM.add(createResolveAliasesPass()); |
109 PM.add(createResolveAliasesPass()); | |
110 | 86 |
111 if (!isEmscripten) // No TLS in JavaScript. | 87 PM.add(createExpandTlsPass()); |
112 PM.add(createExpandTlsPass()); | |
113 | 88 |
114 // GlobalCleanup needs to run after ExpandTls because | 89 // GlobalCleanup needs to run after ExpandTls because |
115 // __tls_template_start etc. are extern_weak before expansion. | 90 // __tls_template_start etc. are extern_weak before expansion. |
116 if (!isEmscripten) // JSBackend can handle external_weak. | 91 PM.add(createGlobalCleanupPass()); |
117 PM.add(createGlobalCleanupPass()); | |
118 | |
119 if (EnableEmAsyncify) | |
120 PM.add(createLowerEmAsyncifyPass()); | |
121 } | 92 } |
122 | 93 |
123 void llvm::PNaClABISimplifyAddPostOptPasses(Triple *T, PassManagerBase &PM) { | 94 void llvm::PNaClABISimplifyAddPostOptPasses(Triple *T, PassManagerBase &PM) { |
124 bool isEmscripten = T->isOSEmscripten(); | 95 PM.add(createRewritePNaClLibraryCallsPass()); |
125 | |
126 if (!isEmscripten) // setjmp/longjmp are handled in LowerEmSetjmp, | |
127 // memcpy/memmove/memset are handled in JSBackend. | |
128 PM.add(createRewritePNaClLibraryCallsPass()); | |
129 | 96 |
130 // ExpandStructRegs must be run after ExpandArithWithOverflow to expand out | 97 // ExpandStructRegs must be run after ExpandArithWithOverflow to expand out |
131 // the insertvalue instructions that ExpandArithWithOverflow introduces. | 98 // the insertvalue instructions that ExpandArithWithOverflow introduces. |
132 PM.add(createExpandArithWithOverflowPass()); | 99 PM.add(createExpandArithWithOverflowPass()); |
133 | 100 |
134 // We place ExpandByVal after optimization passes because some byval | 101 // We place ExpandByVal after optimization passes because some byval |
135 // arguments can be expanded away by the ArgPromotion pass. Leaving | 102 // arguments can be expanded away by the ArgPromotion pass. Leaving |
136 // in "byval" during optimization also allows some dead stores to be | 103 // in "byval" during optimization also allows some dead stores to be |
137 // eliminated, because "byval" is a stronger constraint than what | 104 // eliminated, because "byval" is a stronger constraint than what |
138 // ExpandByVal expands it to. | 105 // ExpandByVal expands it to. |
139 PM.add(createExpandByValPass()); | 106 PM.add(createExpandByValPass()); |
140 | 107 |
141 // We place ExpandSmallArguments after optimization passes because | 108 // We place ExpandSmallArguments after optimization passes because |
142 // some optimizations undo its changes. Note that | 109 // some optimizations undo its changes. Note that |
143 // ExpandSmallArguments requires that ExpandVarArgs has already been | 110 // ExpandSmallArguments requires that ExpandVarArgs has already been |
144 // run. | 111 // run. |
145 if (!isEmscripten) | 112 PM.add(createExpandSmallArgumentsPass()); |
146 PM.add(createExpandSmallArgumentsPass()); | |
147 | 113 |
148 PM.add(createPromoteI1OpsPass()); | 114 PM.add(createPromoteI1OpsPass()); |
149 | 115 |
150 // Vector simplifications. | 116 // Vector simplifications. |
151 // | 117 // |
152 // The following pass relies on ConstantInsertExtractElementIndex running | 118 // The following pass relies on ConstantInsertExtractElementIndex running |
153 // after it, and it must run before GlobalizeConstantVectors because the mask | 119 // after it, and it must run before GlobalizeConstantVectors because the mask |
154 // argument of shufflevector must be a constant (the pass would otherwise | 120 // argument of shufflevector must be a constant (the pass would otherwise |
155 // violate this requirement). | 121 // violate this requirement). |
156 if (!isEmscripten) // JSBackend handles shufflevector. | 122 PM.add(createExpandShuffleVectorPass()); |
157 PM.add(createExpandShuffleVectorPass()); | |
158 // We should not place arbitrary passes after ExpandConstantExpr | 123 // We should not place arbitrary passes after ExpandConstantExpr |
159 // because they might reintroduce ConstantExprs. | 124 // because they might reintroduce ConstantExprs. |
160 PM.add(createExpandConstantExprPass()); | 125 PM.add(createExpandConstantExprPass()); |
161 // GlobalizeConstantVectors does not handle nested ConstantExprs, so we | 126 // GlobalizeConstantVectors does not handle nested ConstantExprs, so we |
162 // run ExpandConstantExpr first. | 127 // run ExpandConstantExpr first. |
163 if (!isEmscripten) // JSBackend handles constant vectors. | 128 PM.add(createGlobalizeConstantVectorsPass()); |
164 PM.add(createGlobalizeConstantVectorsPass()); | |
165 // The following pass inserts GEPs, it must precede ExpandGetElementPtr. It | 129 // The following pass inserts GEPs, it must precede ExpandGetElementPtr. It |
166 // also creates vector loads and stores, the subsequent pass cleans them up to | 130 // also creates vector loads and stores, the subsequent pass cleans them up to |
167 // fix their alignment. | 131 // fix their alignment. |
168 PM.add(createConstantInsertExtractElementIndexPass()); | 132 PM.add(createConstantInsertExtractElementIndexPass()); |
169 if (!isEmscripten) // JSBackend handles unaligned vector load/store. | 133 PM.add(createFixVectorLoadStoreAlignmentPass()); |
170 PM.add(createFixVectorLoadStoreAlignmentPass()); | |
171 | 134 |
172 // Optimization passes and ExpandByVal introduce | 135 // Optimization passes and ExpandByVal introduce |
173 // memset/memcpy/memmove intrinsics with a 64-bit size argument. | 136 // memset/memcpy/memmove intrinsics with a 64-bit size argument. |
174 // This pass converts those arguments to 32-bit. | 137 // This pass converts those arguments to 32-bit. |
175 PM.add(createCanonicalizeMemIntrinsicsPass()); | 138 PM.add(createCanonicalizeMemIntrinsicsPass()); |
176 | 139 |
177 // We place StripMetadata after optimization passes because | 140 // We place StripMetadata after optimization passes because |
178 // optimizations depend on the metadata. | 141 // optimizations depend on the metadata. |
179 if (!isEmscripten) // Run this later, JSBackend's optimizations rely on it. | 142 PM.add(createStripMetadataPass()); |
180 PM.add(createStripMetadataPass()); | |
181 | 143 |
182 // ConstantMerge cleans up after passes such as GlobalizeConstantVectors. It | 144 // ConstantMerge cleans up after passes such as GlobalizeConstantVectors. It |
183 // must run before the FlattenGlobals pass because FlattenGlobals loses | 145 // must run before the FlattenGlobals pass because FlattenGlobals loses |
184 // information that otherwise helps ConstantMerge do a good job. | 146 // information that otherwise helps ConstantMerge do a good job. |
185 PM.add(createConstantMergePass()); | 147 PM.add(createConstantMergePass()); |
186 // FlattenGlobals introduces ConstantExpr bitcasts of globals which | 148 // FlattenGlobals introduces ConstantExpr bitcasts of globals which |
187 // are expanded out later. ReplacePtrsWithInts also creates some | 149 // are expanded out later. ReplacePtrsWithInts also creates some |
188 // ConstantExprs, and it locally creates an ExpandConstantExprPass | 150 // ConstantExprs, and it locally creates an ExpandConstantExprPass |
189 // to clean both of these up. | 151 // to clean both of these up. |
190 PM.add(createFlattenGlobalsPass()); | 152 PM.add(createFlattenGlobalsPass()); |
191 | 153 |
192 // The type legalization passes (ExpandLargeIntegers and PromoteIntegers) do | 154 // The type legalization passes (ExpandLargeIntegers and PromoteIntegers) do |
193 // not handle constexprs and create GEPs, so they go between those passes. | 155 // not handle constexprs and create GEPs, so they go between those passes. |
194 PM.add(createExpandLargeIntegersPass()); | 156 PM.add(createExpandLargeIntegersPass()); |
195 PM.add(createPromoteIntegersPass()); | 157 PM.add(createPromoteIntegersPass()); |
196 // ExpandGetElementPtr must follow ExpandConstantExpr to expand the | 158 // ExpandGetElementPtr must follow ExpandConstantExpr to expand the |
197 // getelementptr instructions it creates. | 159 // getelementptr instructions it creates. |
198 if (!isEmscripten) // Handled by JSBackend. | 160 PM.add(createExpandGetElementPtrPass()); |
199 PM.add(createExpandGetElementPtrPass()); | |
200 // Rewrite atomic and volatile instructions with intrinsic calls. | 161 // Rewrite atomic and volatile instructions with intrinsic calls. |
201 PM.add(createRewriteAtomicsPass()); | 162 PM.add(createRewriteAtomicsPass()); |
202 // Remove ``asm("":::"memory")``. This must occur after rewriting | 163 // Remove ``asm("":::"memory")``. This must occur after rewriting |
203 // atomics: a ``fence seq_cst`` surrounded by ``asm("":::"memory")`` | 164 // atomics: a ``fence seq_cst`` surrounded by ``asm("":::"memory")`` |
204 // has special meaning and is translated differently. | 165 // has special meaning and is translated differently. |
205 if (!isEmscripten) // No special semantics in JavaScript. | 166 PM.add(createRemoveAsmMemoryPass()); |
206 PM.add(createRemoveAsmMemoryPass()); | |
207 | 167 |
208 PM.add(createSimplifyAllocasPass()); | 168 PM.add(createSimplifyAllocasPass()); |
209 | 169 |
210 // ReplacePtrsWithInts assumes that getelementptr instructions and | 170 // ReplacePtrsWithInts assumes that getelementptr instructions and |
211 // ConstantExprs have already been expanded out. | 171 // ConstantExprs have already been expanded out. |
212 if (!isEmscripten) // Handled by JSBackend. | 172 PM.add(createReplacePtrsWithIntsPass()); |
213 PM.add(createReplacePtrsWithIntsPass()); | |
214 | 173 |
215 // The atomic cmpxchg instruction returns a struct, and is rewritten to an | 174 // The atomic cmpxchg instruction returns a struct, and is rewritten to an |
216 // intrinsic as a post-opt pass, we therefore need to expand struct regs. | 175 // intrinsic as a post-opt pass, we therefore need to expand struct regs. |
217 PM.add(createExpandStructRegsPass()); | 176 PM.add(createExpandStructRegsPass()); |
218 | 177 |
219 // We place StripAttributes after optimization passes because many | 178 // We place StripAttributes after optimization passes because many |
220 // analyses add attributes to reflect their results. | 179 // analyses add attributes to reflect their results. |
221 // StripAttributes must come after ExpandByVal and | 180 // StripAttributes must come after ExpandByVal and |
222 // ExpandSmallArguments. | 181 // ExpandSmallArguments. |
223 if (!isEmscripten) | 182 PM.add(createStripAttributesPass()); |
224 PM.add(createStripAttributesPass()); | |
225 | 183 |
226 // Many passes create loads and stores. This pass changes their alignment. | 184 // Many passes create loads and stores. This pass changes their alignment. |
227 if (!isEmscripten) | 185 PM.add(createNormalizeAlignmentPass()); |
228 PM.add(createNormalizeAlignmentPass()); | |
229 | 186 |
230 // Strip dead prototytes to appease the intrinsic ABI checks. | 187 // Strip dead prototytes to appease the intrinsic ABI checks. |
231 // ExpandVarArgs leaves around vararg intrinsics, and | 188 // ExpandVarArgs leaves around vararg intrinsics, and |
232 // ReplacePtrsWithInts leaves the lifetime.start/end intrinsics. | 189 // ReplacePtrsWithInts leaves the lifetime.start/end intrinsics. |
233 if (!isEmscripten) // Dead prototypes ignored by JSBackend. | 190 PM.add(createStripDeadPrototypesPass()); |
234 PM.add(createStripDeadPrototypesPass()); | |
235 | 191 |
236 // Eliminate simple dead code that the post-opt passes could have created. | 192 // Eliminate simple dead code that the post-opt passes could have created. |
237 PM.add(createDeadCodeEliminationPass()); | 193 PM.add(createDeadCodeEliminationPass()); |
238 | 194 |
239 // This should be the last step before PNaCl ABI validation. | 195 // This should be the last step before PNaCl ABI validation. |
240 if (!isEmscripten) | 196 PM.add(createCleanupUsedGlobalsMetadataPass()); |
241 PM.add(createCleanupUsedGlobalsMetadataPass()); | |
242 } | 197 } |
OLD | NEW |