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,
@@ -705,9 +719,56 @@ 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
+ let thin_bc_out = cgcx. output_filenames . temp_path ( OutputType :: ThinBitcode , module_name) ;
749
+ if let Err ( err) = fs:: write ( & thin_bc_out, thin_lto_buffer. data ( ) ) {
750
+ dcx. emit_err ( WriteBytecode { path : & thin_bc_out, err } ) ;
751
+ }
752
+ let bc_summary_out =
753
+ cgcx. output_filenames . temp_path ( OutputType :: ThinLinkBitcode , module_name) ;
754
+ if config. emit_thin_lto_summary
755
+ && let Some ( thin_link_bitcode_filename) = bc_summary_out. file_name ( )
756
+ {
757
+ let summary_data = thin_lto_buffer. thin_link_data ( ) ;
758
+ cgcx. prof . artifact_size (
759
+ "llvm_bitcode_summary" ,
760
+ thin_link_bitcode_filename. to_string_lossy ( ) ,
761
+ summary_data. len ( ) as u64 ,
762
+ ) ;
763
+ let _timer = cgcx. prof . generic_activity_with_arg (
764
+ "LLVM_module_codegen_emit_bitcode_summary" ,
765
+ & * module. name ,
766
+ ) ;
767
+ if let Err ( err) = fs:: write ( & bc_summary_out, summary_data) {
768
+ dcx. emit_err ( WriteBytecode { path : & bc_summary_out, err } ) ;
769
+ }
770
+ }
771
+ }
711
772
}
712
773
Ok ( ( ) )
713
774
}
@@ -760,59 +821,47 @@ pub(crate) unsafe fn codegen(
760
821
// otherwise requested.
761
822
762
823
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
824
let obj_out = cgcx. output_filenames . temp_path ( OutputType :: Object , module_name) ;
766
825
767
826
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
827
if config. emit_bc || config. emit_obj == EmitObj :: Bitcode {
828
+ let thin = {
829
+ let _timer = cgcx. prof . generic_activity_with_arg (
830
+ "LLVM_module_codegen_make_bitcode" ,
831
+ & * module. name ,
832
+ ) ;
833
+ ThinBuffer :: new ( llmod, config. emit_thin_lto , false )
834
+ } ;
835
+ let data = thin. data ( ) ;
802
836
let _timer = cgcx
803
837
. prof
804
838
. generic_activity_with_arg ( "LLVM_module_codegen_emit_bitcode" , & * module. name ) ;
839
+ if let Some ( bitcode_filename) = bc_out. file_name ( ) {
840
+ cgcx. prof . artifact_size (
841
+ "llvm_bitcode" ,
842
+ bitcode_filename. to_string_lossy ( ) ,
843
+ data. len ( ) as u64 ,
844
+ ) ;
845
+ }
805
846
if let Err ( err) = fs:: write ( & bc_out, data) {
806
847
dcx. emit_err ( WriteBytecode { path : & bc_out, err } ) ;
807
848
}
808
849
}
809
850
810
- if config. emit_obj == EmitObj :: ObjectCode ( BitcodeSection :: Full ) {
851
+ if config. emit_obj == EmitObj :: ObjectCode ( BitcodeSection :: Full )
852
+ && module. kind == ModuleKind :: Regular
853
+ {
811
854
let _timer = cgcx
812
855
. prof
813
856
. generic_activity_with_arg ( "LLVM_module_codegen_embed_bitcode" , & * module. name ) ;
857
+ let thin_bc_out =
858
+ cgcx. output_filenames . temp_path ( OutputType :: ThinBitcode , module_name) ;
859
+ assert ! ( thin_bc_out. exists( ) , "cannot find {:?} as embedded bitcode" , thin_bc_out) ;
860
+ let data = fs:: read ( & thin_bc_out) . unwrap ( ) ;
861
+ debug ! ( "removing embed bitcode file {:?}" , thin_bc_out) ;
862
+ ensure_removed ( dcx, & thin_bc_out) ;
814
863
unsafe {
815
- embed_bitcode ( cgcx, llcx, llmod, & config. bc_cmdline , data) ;
864
+ embed_bitcode ( cgcx, llcx, llmod, & config. bc_cmdline , & data) ;
816
865
}
817
866
}
818
867
}
0 commit comments