@@ -43,6 +43,7 @@ use stable_mir::CrateDef;
4343use stable_mir:: mir:: mono:: { Instance , MonoItem } ;
4444use stable_mir:: rustc_internal;
4545use std:: any:: Any ;
46+ use std:: cmp:: min;
4647use std:: collections:: BTreeMap ;
4748use std:: fmt:: Write ;
4849use std:: fs:: File ;
@@ -74,15 +75,15 @@ impl GotocCodegenBackend {
7475 ///
7576 /// Invariant: iff `check_contract.is_some()` then `return.2.is_some()`
7677 #[ allow( clippy:: too_many_arguments) ]
77- fn codegen_items < ' tcx , const NUM_THREADS : usize > (
78+ fn codegen_items < ' tcx > (
7879 & self ,
7980 tcx : TyCtxt < ' tcx > ,
8081 starting_items : & [ MonoItem ] ,
8182 symtab_goto : & Path ,
8283 machine_model : & MachineModel ,
8384 check_contract : Option < InternalDefId > ,
8485 mut transformer : BodyTransformation ,
85- thread_pool : & ThreadPool < NUM_THREADS > ,
86+ thread_pool : & ThreadPool ,
8687 ) -> ( GotocCtx < ' tcx > , Vec < MonoItem > , Option < AssignsContract > ) {
8788 // This runs reachability analysis before global passes are applied.
8889 //
@@ -349,13 +350,24 @@ impl CodegenBackend for GotocCodegenBackend {
349350 return codegen_results ( tcx, & results. machine_model ) ;
350351 }
351352
352- let export_thread_pool = ThreadPool :: < NUM_FILE_EXPORT_THREADS > :: new ( ) ;
353+ // Create an empty thread pool. We will set the size later once we
354+ // concretely know the # of harnesses we need to analyze.
355+ let mut export_thread_pool = ThreadPool :: empty ( ) ;
353356
354357 match reachability {
355358 ReachabilityType :: AllFns | ReachabilityType :: Harnesses => {
356359 let mut units = CodegenUnits :: new ( & queries, tcx) ;
357360 let mut modifies_instances = vec ! [ ] ;
358361 let mut loop_contracts_instances = vec ! [ ] ;
362+
363+ // If we are verifying all harnesses, cap the number of threads at `[# of harnesses] - 1`.
364+ // This is just a common sense rule to keep us from spinning up threads that couldn't possibly
365+ // provide additional parallelism over existing threads. One thread can potentially work on each
366+ // harness' goto file but the main compiler thread can just handle the last file itself.
367+ let num_harnesses: usize = units. iter ( ) . map ( |unit| unit. harnesses . len ( ) ) . sum ( ) ;
368+ export_thread_pool
369+ . add_workers ( min ( NUM_FILE_EXPORT_THREADS , num_harnesses. saturating_sub ( 1 ) ) ) ;
370+
359371 // Cross-crate collecting of all items that are reachable from the crate harnesses.
360372 for unit in units. iter ( ) {
361373 // We reset the body cache for now because each codegen unit has different
@@ -391,6 +403,11 @@ impl CodegenBackend for GotocCodegenBackend {
391403 ReachabilityType :: None => unreachable ! ( ) ,
392404 ReachabilityType :: PubFns => {
393405 let unit = CodegenUnit :: default ( ) ;
406+
407+ // Here, it's more difficult to determine which functions will be analyzed,
408+ // so just use the max NUM_FILE_EXPORT_THREADS.
409+ export_thread_pool. add_workers ( NUM_FILE_EXPORT_THREADS ) ;
410+
394411 let transformer = BodyTransformation :: new ( & queries, tcx, & unit) ;
395412 let main_instance =
396413 stable_mir:: entry_fn ( ) . map ( |main_fn| Instance :: try_from ( main_fn) . unwrap ( ) ) ;
0 commit comments