@@ -140,6 +140,15 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
140140 config:: OptLevel :: Less => llvm:: CodeGenLevelLess ,
141141 config:: OptLevel :: Default => llvm:: CodeGenLevelDefault ,
142142 config:: OptLevel :: Aggressive => llvm:: CodeGenLevelAggressive ,
143+ _ => llvm:: CodeGenLevelDefault ,
144+ }
145+ }
146+
147+ fn get_llvm_opt_size ( optimize : config:: OptLevel ) -> llvm:: CodeGenOptSize {
148+ match optimize {
149+ config:: OptLevel :: Size => llvm:: CodeGenOptSizeDefault ,
150+ config:: OptLevel :: SizeMin => llvm:: CodeGenOptSizeAggressive ,
151+ _ => llvm:: CodeGenOptSizeNone ,
143152 }
144153}
145154
@@ -237,6 +246,9 @@ pub struct ModuleConfig {
237246 /// absolutely no optimizations (used for the metadata module).
238247 opt_level : Option < llvm:: CodeGenOptLevel > ,
239248
249+ /// Some(level) to optimize binary size, or None to not affect program size.
250+ opt_size : Option < llvm:: CodeGenOptSize > ,
251+
240252 // Flags indicating which outputs to produce.
241253 emit_no_opt_bc : bool ,
242254 emit_bc : bool ,
@@ -268,6 +280,7 @@ impl ModuleConfig {
268280 tm : tm,
269281 passes : passes,
270282 opt_level : None ,
283+ opt_size : None ,
271284
272285 emit_no_opt_bc : false ,
273286 emit_bc : false ,
@@ -637,6 +650,7 @@ pub fn run_passes(sess: &Session,
637650 let mut metadata_config = ModuleConfig :: new ( tm, vec ! ( ) ) ;
638651
639652 modules_config. opt_level = Some ( get_llvm_opt_level ( sess. opts . optimize ) ) ;
653+ modules_config. opt_size = Some ( get_llvm_opt_size ( sess. opts . optimize ) ) ;
640654
641655 // Save all versions of the bytecode if we're saving our temporaries.
642656 if sess. opts . cg . save_temps {
@@ -991,36 +1005,48 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
9911005 // reasonable defaults and prepare it to actually populate the pass
9921006 // manager.
9931007 let builder = llvm:: LLVMPassManagerBuilderCreate ( ) ;
994- let opt = config. opt_level . unwrap_or ( llvm:: CodeGenLevelNone ) ;
1008+ let opt_level = config. opt_level . unwrap_or ( llvm:: CodeGenLevelNone ) ;
1009+ let opt_size = config. opt_size . unwrap_or ( llvm:: CodeGenOptSizeNone ) ;
9951010 let inline_threshold = config. inline_threshold ;
9961011
997- llvm:: LLVMRustConfigurePassManagerBuilder ( builder, opt ,
1012+ llvm:: LLVMRustConfigurePassManagerBuilder ( builder, opt_level ,
9981013 config. merge_functions ,
9991014 config. vectorize_slp ,
10001015 config. vectorize_loop ) ;
1016+ llvm:: LLVMPassManagerBuilderSetSizeLevel ( builder, opt_size as u32 ) ;
1017+
1018+ if opt_size != llvm:: CodeGenOptSizeNone {
1019+ llvm:: LLVMPassManagerBuilderSetDisableUnrollLoops ( builder, 1 ) ;
1020+ }
10011021
10021022 llvm:: LLVMRustAddBuilderLibraryInfo ( builder, llmod, config. no_builtins ) ;
10031023
10041024 // Here we match what clang does (kinda). For O0 we only inline
10051025 // always-inline functions (but don't add lifetime intrinsics), at O1 we
10061026 // inline with lifetime intrinsics, and O2+ we add an inliner with a
10071027 // thresholds copied from clang.
1008- match ( opt , inline_threshold) {
1009- ( _, Some ( t) ) => {
1028+ match ( opt_level , opt_size , inline_threshold) {
1029+ ( _, _ , Some ( t) ) => {
10101030 llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, t as u32 ) ;
10111031 }
1012- ( llvm:: CodeGenLevelNone , _) => {
1032+ ( llvm:: CodeGenLevelAggressive , _, _) => {
1033+ llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 275 ) ;
1034+ }
1035+ ( _, llvm:: CodeGenOptSizeDefault , _) => {
1036+ llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 75 ) ;
1037+ }
1038+ ( _, llvm:: CodeGenOptSizeAggressive , _) => {
1039+ llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 25 ) ;
1040+ }
1041+ ( llvm:: CodeGenLevelNone , _, _) => {
10131042 llvm:: LLVMRustAddAlwaysInlinePass ( builder, false ) ;
10141043 }
1015- ( llvm:: CodeGenLevelLess , _) => {
1044+ ( llvm:: CodeGenLevelLess , _, _ ) => {
10161045 llvm:: LLVMRustAddAlwaysInlinePass ( builder, true ) ;
10171046 }
1018- ( llvm:: CodeGenLevelDefault , _) => {
1047+ ( llvm:: CodeGenLevelDefault , _, _ ) => {
10191048 llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 225 ) ;
10201049 }
1021- ( llvm:: CodeGenLevelAggressive , _) => {
1022- llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 275 ) ;
1023- }
10241050 }
10251051
10261052 f ( builder) ;
0 commit comments