| 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 |