@@ -140,6 +140,15 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
140
140
config:: OptLevel :: Less => llvm:: CodeGenLevelLess ,
141
141
config:: OptLevel :: Default => llvm:: CodeGenLevelDefault ,
142
142
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 ,
143
152
}
144
153
}
145
154
@@ -237,6 +246,9 @@ pub struct ModuleConfig {
237
246
/// absolutely no optimizations (used for the metadata module).
238
247
opt_level : Option < llvm:: CodeGenOptLevel > ,
239
248
249
+ /// Some(level) to optimize binary size, or None to not affect program size.
250
+ opt_size : Option < llvm:: CodeGenOptSize > ,
251
+
240
252
// Flags indicating which outputs to produce.
241
253
emit_no_opt_bc : bool ,
242
254
emit_bc : bool ,
@@ -268,6 +280,7 @@ impl ModuleConfig {
268
280
tm : tm,
269
281
passes : passes,
270
282
opt_level : None ,
283
+ opt_size : None ,
271
284
272
285
emit_no_opt_bc : false ,
273
286
emit_bc : false ,
@@ -637,6 +650,7 @@ pub fn run_passes(sess: &Session,
637
650
let mut metadata_config = ModuleConfig :: new ( tm, vec ! ( ) ) ;
638
651
639
652
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 ) ) ;
640
654
641
655
// Save all versions of the bytecode if we're saving our temporaries.
642
656
if sess. opts . cg . save_temps {
@@ -991,36 +1005,48 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
991
1005
// reasonable defaults and prepare it to actually populate the pass
992
1006
// manager.
993
1007
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 ) ;
995
1010
let inline_threshold = config. inline_threshold ;
996
1011
997
- llvm:: LLVMRustConfigurePassManagerBuilder ( builder, opt ,
1012
+ llvm:: LLVMRustConfigurePassManagerBuilder ( builder, opt_level ,
998
1013
config. merge_functions ,
999
1014
config. vectorize_slp ,
1000
1015
config. vectorize_loop ) ;
1016
+ llvm:: LLVMPassManagerBuilderSetSizeLevel ( builder, opt_size as u32 ) ;
1017
+
1018
+ if opt_size != llvm:: CodeGenOptSizeNone {
1019
+ llvm:: LLVMPassManagerBuilderSetDisableUnrollLoops ( builder, 1 ) ;
1020
+ }
1001
1021
1002
1022
llvm:: LLVMRustAddBuilderLibraryInfo ( builder, llmod, config. no_builtins ) ;
1003
1023
1004
1024
// Here we match what clang does (kinda). For O0 we only inline
1005
1025
// always-inline functions (but don't add lifetime intrinsics), at O1 we
1006
1026
// inline with lifetime intrinsics, and O2+ we add an inliner with a
1007
1027
// thresholds copied from clang.
1008
- match ( opt , inline_threshold) {
1009
- ( _, Some ( t) ) => {
1028
+ match ( opt_level , opt_size , inline_threshold) {
1029
+ ( _, _ , Some ( t) ) => {
1010
1030
llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, t as u32 ) ;
1011
1031
}
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 , _, _) => {
1013
1042
llvm:: LLVMRustAddAlwaysInlinePass ( builder, false ) ;
1014
1043
}
1015
- ( llvm:: CodeGenLevelLess , _) => {
1044
+ ( llvm:: CodeGenLevelLess , _, _ ) => {
1016
1045
llvm:: LLVMRustAddAlwaysInlinePass ( builder, true ) ;
1017
1046
}
1018
- ( llvm:: CodeGenLevelDefault , _) => {
1047
+ ( llvm:: CodeGenLevelDefault , _, _ ) => {
1019
1048
llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 225 ) ;
1020
1049
}
1021
- ( llvm:: CodeGenLevelAggressive , _) => {
1022
- llvm:: LLVMPassManagerBuilderUseInlinerWithThreshold ( builder, 275 ) ;
1023
- }
1024
1050
}
1025
1051
1026
1052
f ( builder) ;
0 commit comments