@@ -18,8 +18,7 @@ use llvm_sys::prelude::*;
18
18
use llvm_sys:: support:: LLVMParseCommandLineOptions ;
19
19
use llvm_sys:: target:: * ;
20
20
use llvm_sys:: target_machine:: * ;
21
- use llvm_sys:: transforms:: ipo:: * ;
22
- use llvm_sys:: transforms:: pass_manager_builder:: * ;
21
+ use llvm_sys:: transforms:: pass_builder:: * ;
23
22
use llvm_sys:: LLVMAttributeFunctionIndex ;
24
23
use llvm_sys:: { LLVMLinkage , LLVMVisibility } ;
25
24
use log:: * ;
@@ -176,65 +175,48 @@ pub unsafe fn optimize(
176
175
LLVMSetModuleInlineAsm2 ( module, ptr:: null_mut ( ) , 0 ) ;
177
176
}
178
177
179
- let mpm = LLVMCreatePassManager ( ) ;
180
- let fpm = LLVMCreateFunctionPassManagerForModule ( module) ;
181
-
182
- LLVMAddAnalysisPasses ( tm, mpm) ;
183
- LLVMAddAnalysisPasses ( tm, fpm) ;
184
-
185
- // even with -O0 and without LTO we still want to avoid linking in unused code from core etc
186
- LLVMAddGlobalDCEPass ( mpm) ;
187
-
188
- let pmb = LLVMPassManagerBuilderCreate ( ) ;
189
-
190
- use OptLevel :: * ;
191
- let ( inline_threshold, opt) = match opt_level {
192
- No | SizeMin => ( 0 , 1 ) , // Pretty much nothing compiles with -O0 s∫o make it an alias for -O1
193
- Less => ( 25 , 1 ) ,
194
- Default => ( 225 , 2 ) ,
195
- Aggressive => ( 275 , 3 ) ,
196
- Size => ( 25 , 0 ) ,
197
- } ;
198
- LLVMPassManagerBuilderSetOptLevel ( pmb, opt) ;
199
- LLVMPassManagerBuilderSetSizeLevel (
200
- pmb,
201
- match opt_level {
202
- Size => 1 ,
203
- SizeMin => 2 ,
204
- _ => 0 ,
205
- } ,
206
- ) ;
207
- LLVMPassManagerBuilderUseInlinerWithThreshold ( pmb, inline_threshold) ;
208
-
209
- // populate the pass managers
210
- LLVMPassManagerBuilderPopulateFunctionPassManager ( pmb, fpm) ;
211
- LLVMPassManagerBuilderPopulateModulePassManager ( pmb, mpm) ;
212
-
213
178
for sym in module. globals_iter ( ) {
214
179
internalize ( sym, symbol_name ( sym) , export_symbols) ;
215
180
}
216
181
for sym in module. global_aliases_iter ( ) {
217
182
internalize ( sym, symbol_name ( sym) , export_symbols) ;
218
183
}
219
184
220
- debug ! ( "running function passes" ) ;
221
- LLVMInitializeFunctionPassManager ( fpm) ;
222
185
for function in module. functions_iter ( ) {
223
186
let name = symbol_name ( function) ;
224
187
if !name. starts_with ( "llvm." ) {
225
188
if ignore_inline_never {
226
189
remove_attribute ( function, "noinline" ) ;
227
190
}
228
191
internalize ( function, name, export_symbols) ;
229
- if LLVMIsDeclaration ( function) == 0 {
230
- LLVMRunFunctionPassManager ( fpm, function) ;
231
- }
232
192
}
233
193
}
234
- LLVMFinalizeFunctionPassManager ( fpm) ;
235
194
236
- debug ! ( "running module passes" ) ;
237
- LLVMRunPassManager ( mpm, module) ;
195
+ let options = LLVMCreatePassBuilderOptions ( ) ;
196
+
197
+ let passes = [
198
+ // NB: "default<_>" must be the first pass in the list, otherwise it will be ignored.
199
+ match opt_level {
200
+ // Pretty much nothing compiles with -O0 so make it an alias for -O1.
201
+ OptLevel :: No | OptLevel :: Less => "default<O1>" ,
202
+ OptLevel :: Default => "default<O2>" ,
203
+ OptLevel :: Aggressive => "default<O3>" ,
204
+ OptLevel :: Size => "default<Os>" ,
205
+ OptLevel :: SizeMin => "default<Oz>" ,
206
+ } ,
207
+ // NB: This seems to be included in most default pipelines, but not obviously all of them.
208
+ // See
209
+ // https://github.com/llvm/llvm-project/blob/bbe2887f/llvm/lib/Passes/PassBuilderPipelines.cpp#L2011-L2012
210
+ // for a case which includes DCE only conditionally. Better safe than sorry; include it always.
211
+ "dce" ,
212
+ ] ;
213
+
214
+ let passes = passes. join ( "," ) ;
215
+ debug ! ( "running passes: {passes}" ) ;
216
+ let passes = CString :: new ( passes) . unwrap ( ) ;
217
+ LLVMRunPasses ( module, passes. as_ptr ( ) , tm, options) ;
218
+
219
+ LLVMDisposePassBuilderOptions ( options) ;
238
220
239
221
// Some debug info generated by rustc seems to trigger a segfault in the
240
222
// BTF code in llvm, so strip it until that is fixed
0 commit comments