1
1
use std:: ffi:: { CStr , CString } ;
2
2
use std:: io:: { self , Write } ;
3
3
use std:: path:: { Path , PathBuf } ;
4
+ use std:: ptr:: null_mut;
4
5
use std:: sync:: Arc ;
5
6
use std:: { fs, slice, str} ;
6
7
@@ -15,7 +16,7 @@ use rustc_codegen_ssa::back::write::{
15
16
TargetMachineFactoryFn ,
16
17
} ;
17
18
use rustc_codegen_ssa:: traits:: * ;
18
- use rustc_codegen_ssa:: { CompiledModule , ModuleCodegen } ;
19
+ use rustc_codegen_ssa:: { CompiledModule , ModuleCodegen , ModuleKind } ;
19
20
use rustc_data_structures:: profiling:: SelfProfilerRef ;
20
21
use rustc_data_structures:: small_c_str:: SmallCStr ;
21
22
use rustc_errors:: { DiagCtxtHandle , FatalError , Level } ;
@@ -551,6 +552,7 @@ pub(crate) unsafe fn llvm_optimize(
551
552
cgcx : & CodegenContext < LlvmCodegenBackend > ,
552
553
dcx : DiagCtxtHandle < ' _ > ,
553
554
module : & ModuleCodegen < ModuleLlvm > ,
555
+ thin_lto_buffer : Option < & mut * mut llvm:: ThinLTOBuffer > ,
554
556
config : & ModuleConfig ,
555
557
opt_level : config:: OptLevel ,
556
558
opt_stage : llvm:: OptStage ,
@@ -584,7 +586,17 @@ pub(crate) unsafe fn llvm_optimize(
584
586
vectorize_loop = config. vectorize_loop ;
585
587
}
586
588
trace ! ( ?unroll_loops, ?vectorize_slp, ?vectorize_loop, ?run_enzyme) ;
587
- let using_thin_buffers = opt_stage == llvm:: OptStage :: PreLinkThinLTO || config. bitcode_needed ( ) ;
589
+ if thin_lto_buffer. is_some ( ) {
590
+ assert ! (
591
+ matches!(
592
+ opt_stage,
593
+ llvm:: OptStage :: PreLinkNoLTO
594
+ | llvm:: OptStage :: PreLinkFatLTO
595
+ | llvm:: OptStage :: PreLinkThinLTO
596
+ ) ,
597
+ "the bitcode for LTO can only be obtained at the pre-link stage"
598
+ ) ;
599
+ }
588
600
let pgo_gen_path = get_pgo_gen_path ( config) ;
589
601
let pgo_use_path = get_pgo_use_path ( config) ;
590
602
let pgo_sample_use_path = get_pgo_sample_use_path ( config) ;
@@ -644,7 +656,9 @@ pub(crate) unsafe fn llvm_optimize(
644
656
config. no_prepopulate_passes ,
645
657
config. verify_llvm_ir ,
646
658
config. lint_llvm_ir ,
647
- using_thin_buffers,
659
+ thin_lto_buffer,
660
+ config. emit_thin_lto ,
661
+ config. emit_thin_lto_summary ,
648
662
config. merge_functions ,
649
663
unroll_loops,
650
664
vectorize_slp,
@@ -675,7 +689,7 @@ pub(crate) unsafe fn llvm_optimize(
675
689
pub ( crate ) unsafe fn optimize (
676
690
cgcx : & CodegenContext < LlvmCodegenBackend > ,
677
691
dcx : DiagCtxtHandle < ' _ > ,
678
- module : & ModuleCodegen < ModuleLlvm > ,
692
+ module : & mut ModuleCodegen < ModuleLlvm > ,
679
693
config : & ModuleConfig ,
680
694
) -> Result < ( ) , FatalError > {
681
695
let _timer = cgcx. prof . generic_activity_with_arg ( "LLVM_module_optimize" , & * module. name ) ;
@@ -705,9 +719,53 @@ pub(crate) unsafe fn optimize(
705
719
// Otherwise we pretend AD is already done and run the normal opt pipeline (=PostAD).
706
720
let consider_ad = cfg ! ( llvm_enzyme) && config. autodiff . contains ( & config:: AutoDiff :: Enable ) ;
707
721
let autodiff_stage = if consider_ad { AutodiffStage :: PreAD } else { AutodiffStage :: PostAD } ;
708
- return unsafe {
709
- llvm_optimize ( cgcx, dcx, module, config, opt_level, opt_stage, autodiff_stage)
722
+ // The embedded bitcode is used to run LTO/ThinLTO.
723
+ // The bitcode obtained during the `codegen` phase is no longer suitable for performing LTO.
724
+ // It may have undergone LTO due to ThinLocal, so we need to obtain the embedded bitcode at
725
+ // this point.
726
+ let mut thin_lto_buffer = if ( module. kind == ModuleKind :: Regular
727
+ && config. emit_obj == EmitObj :: ObjectCode ( BitcodeSection :: Full ) )
728
+ || config. emit_thin_lto_summary
729
+ {
730
+ Some ( null_mut ( ) )
731
+ } else {
732
+ None
710
733
} ;
734
+ unsafe {
735
+ llvm_optimize (
736
+ cgcx,
737
+ dcx,
738
+ module,
739
+ thin_lto_buffer. as_mut ( ) ,
740
+ config,
741
+ opt_level,
742
+ opt_stage,
743
+ autodiff_stage,
744
+ )
745
+ } ?;
746
+ if let Some ( thin_lto_buffer) = thin_lto_buffer {
747
+ let thin_lto_buffer = unsafe { ThinBuffer :: from_raw_ptr ( thin_lto_buffer) } ;
748
+ module. thin_lto_buffer = Some ( thin_lto_buffer. data ( ) . to_vec ( ) ) ;
749
+ let bc_summary_out =
750
+ cgcx. output_filenames . temp_path ( OutputType :: ThinLinkBitcode , module_name) ;
751
+ if config. emit_thin_lto_summary
752
+ && let Some ( thin_link_bitcode_filename) = bc_summary_out. file_name ( )
753
+ {
754
+ let summary_data = thin_lto_buffer. thin_link_data ( ) ;
755
+ cgcx. prof . artifact_size (
756
+ "llvm_bitcode_summary" ,
757
+ thin_link_bitcode_filename. to_string_lossy ( ) ,
758
+ summary_data. len ( ) as u64 ,
759
+ ) ;
760
+ let _timer = cgcx. prof . generic_activity_with_arg (
761
+ "LLVM_module_codegen_emit_bitcode_summary" ,
762
+ & * module. name ,
763
+ ) ;
764
+ if let Err ( err) = fs:: write ( & bc_summary_out, summary_data) {
765
+ dcx. emit_err ( WriteBytecode { path : & bc_summary_out, err } ) ;
766
+ }
767
+ }
768
+ }
711
769
}
712
770
Ok ( ( ) )
713
771
}
@@ -760,59 +818,41 @@ pub(crate) unsafe fn codegen(
760
818
// otherwise requested.
761
819
762
820
let bc_out = cgcx. output_filenames . temp_path ( OutputType :: Bitcode , module_name) ;
763
- let bc_summary_out =
764
- cgcx. output_filenames . temp_path ( OutputType :: ThinLinkBitcode , module_name) ;
765
821
let obj_out = cgcx. output_filenames . temp_path ( OutputType :: Object , module_name) ;
766
822
767
823
if config. bitcode_needed ( ) {
768
- let _timer = cgcx
769
- . prof
770
- . generic_activity_with_arg ( "LLVM_module_codegen_make_bitcode" , & * module. name ) ;
771
- let thin = ThinBuffer :: new ( llmod, config. emit_thin_lto , config. emit_thin_lto_summary ) ;
772
- let data = thin. data ( ) ;
773
-
774
- if let Some ( bitcode_filename) = bc_out. file_name ( ) {
775
- cgcx. prof . artifact_size (
776
- "llvm_bitcode" ,
777
- bitcode_filename. to_string_lossy ( ) ,
778
- data. len ( ) as u64 ,
779
- ) ;
780
- }
781
-
782
- if config. emit_thin_lto_summary
783
- && let Some ( thin_link_bitcode_filename) = bc_summary_out. file_name ( )
784
- {
785
- let summary_data = thin. thin_link_data ( ) ;
786
- cgcx. prof . artifact_size (
787
- "llvm_bitcode_summary" ,
788
- thin_link_bitcode_filename. to_string_lossy ( ) ,
789
- summary_data. len ( ) as u64 ,
790
- ) ;
791
-
792
- let _timer = cgcx. prof . generic_activity_with_arg (
793
- "LLVM_module_codegen_emit_bitcode_summary" ,
794
- & * module. name ,
795
- ) ;
796
- if let Err ( err) = fs:: write ( & bc_summary_out, summary_data) {
797
- dcx. emit_err ( WriteBytecode { path : & bc_summary_out, err } ) ;
798
- }
799
- }
800
-
801
824
if config. emit_bc || config. emit_obj == EmitObj :: Bitcode {
825
+ let thin = {
826
+ let _timer = cgcx. prof . generic_activity_with_arg (
827
+ "LLVM_module_codegen_make_bitcode" ,
828
+ & * module. name ,
829
+ ) ;
830
+ ThinBuffer :: new ( llmod, config. emit_thin_lto , false )
831
+ } ;
832
+ let data = thin. data ( ) ;
802
833
let _timer = cgcx
803
834
. prof
804
835
. generic_activity_with_arg ( "LLVM_module_codegen_emit_bitcode" , & * module. name ) ;
836
+ if let Some ( bitcode_filename) = bc_out. file_name ( ) {
837
+ cgcx. prof . artifact_size (
838
+ "llvm_bitcode" ,
839
+ bitcode_filename. to_string_lossy ( ) ,
840
+ data. len ( ) as u64 ,
841
+ ) ;
842
+ }
805
843
if let Err ( err) = fs:: write ( & bc_out, data) {
806
844
dcx. emit_err ( WriteBytecode { path : & bc_out, err } ) ;
807
845
}
808
846
}
809
847
810
- if config. emit_obj == EmitObj :: ObjectCode ( BitcodeSection :: Full ) {
848
+ if config. embed_bitcode ( ) && module . kind == ModuleKind :: Regular {
811
849
let _timer = cgcx
812
850
. prof
813
851
. generic_activity_with_arg ( "LLVM_module_codegen_embed_bitcode" , & * module. name ) ;
852
+ let thin_bc =
853
+ module. thin_lto_buffer . as_deref ( ) . expect ( "cannot find embedded bitcode" ) ;
814
854
unsafe {
815
- embed_bitcode ( cgcx, llcx, llmod, & config. bc_cmdline , data ) ;
855
+ embed_bitcode ( cgcx, llcx, llmod, & config. bc_cmdline , & thin_bc ) ;
816
856
}
817
857
}
818
858
}
0 commit comments