@@ -15,7 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
15
15
use rustc_errors:: ErrorGuaranteed ;
16
16
use rustc_session:: Session ;
17
17
use smallvec:: SmallVec ;
18
- use std:: mem;
18
+ use std:: mem:: { self , take } ;
19
19
20
20
type FunctionMap = FxHashMap < Word , Function > ;
21
21
@@ -658,13 +658,15 @@ impl Inliner<'_, '_> {
658
658
if let Some ( call_result_type) = call_result_type {
659
659
// Generate the storage space for the return value: Do this *after* the split above,
660
660
// because if block_idx=0, inserting a variable here shifts call_index.
661
- let ret_var_inst = Instruction :: new (
662
- Op :: Variable ,
663
- Some ( self . ptr_ty ( call_result_type) ) ,
664
- Some ( return_variable. unwrap ( ) ) ,
665
- vec ! [ Operand :: StorageClass ( StorageClass :: Function ) ] ,
661
+ insert_opvariables (
662
+ & mut caller. blocks [ 0 ] ,
663
+ [ Instruction :: new (
664
+ Op :: Variable ,
665
+ Some ( self . ptr_ty ( call_result_type) ) ,
666
+ Some ( return_variable. unwrap ( ) ) ,
667
+ vec ! [ Operand :: StorageClass ( StorageClass :: Function ) ] ,
668
+ ) ] ,
666
669
) ;
667
- self . insert_opvariables ( & mut caller. blocks [ 0 ] , [ ret_var_inst] ) ;
668
670
}
669
671
670
672
// Insert non-entry inlined callee blocks just after the pre-call block.
@@ -710,115 +712,52 @@ impl Inliner<'_, '_> {
710
712
// Fuse the inlined callee entry block into the pre-call block.
711
713
// This is okay because it's illegal to branch to the first BB in a function.
712
714
{
713
- // NOTE(eddyb) `OpExtInst`s have a result ID, even if unused, and
714
- // it has to be unique, so this allocates new IDs as-needed.
715
- let instantiate_debuginfo = |this : & mut Self , inst : & Instruction | {
716
- let mut inst = inst. clone ( ) ;
717
- if let Some ( id) = & mut inst. result_id {
718
- * id = this. id ( ) ;
719
- }
720
- inst
721
- } ;
722
-
723
- let custom_inst_to_inst = |this : & mut Self , inst : CustomInst < _ > | {
724
- Instruction :: new (
725
- Op :: ExtInst ,
726
- Some ( this. op_type_void_id ) ,
727
- Some ( this. id ( ) ) ,
728
- [
729
- Operand :: IdRef ( this. custom_ext_inst_set_import ) ,
730
- Operand :: LiteralExtInstInteger ( inst. op ( ) as u32 ) ,
731
- ]
732
- . into_iter ( )
733
- . chain ( inst. into_operands ( ) )
734
- . collect ( ) ,
735
- )
736
- } ;
737
-
738
715
// Return the subsequence of `insts` made from `OpVariable`s, and any
739
716
// debuginfo instructions (which may apply to them), while removing
740
717
// *only* `OpVariable`s from `insts` (and keeping debuginfo in both).
741
718
let mut steal_vars = |insts : & mut Vec < Instruction > | {
742
- // HACK(eddyb) this duplicates some code from `get_inlined_blocks`,
743
- // but that will be removed once the inliner is refactored to be
744
- // inside-out instead of outside-in (already finished in a branch).
745
- let mut enclosing_inlined_frames = SmallVec :: < [ _ ; 8 ] > :: new ( ) ;
746
- let mut current_debug_src_loc_inst = None ;
747
- let mut vars_and_debuginfo_range = 0 ..0 ;
748
- while vars_and_debuginfo_range. end < insts. len ( ) {
749
- let inst = & insts[ vars_and_debuginfo_range. end ] ;
750
- match inst. class . opcode {
751
- Op :: Line => current_debug_src_loc_inst = Some ( inst) ,
752
- Op :: NoLine => current_debug_src_loc_inst = None ,
753
- Op :: ExtInst
754
- if inst. operands [ 0 ] . unwrap_id_ref ( )
755
- == self . custom_ext_inst_set_import =>
756
- {
757
- match CustomOp :: decode_from_ext_inst ( inst) {
758
- CustomOp :: SetDebugSrcLoc => current_debug_src_loc_inst = Some ( inst) ,
759
- CustomOp :: ClearDebugSrcLoc => current_debug_src_loc_inst = None ,
760
- CustomOp :: PushInlinedCallFrame => {
761
- enclosing_inlined_frames
762
- . push ( ( current_debug_src_loc_inst. take ( ) , inst) ) ;
763
- }
764
- CustomOp :: PopInlinedCallFrame => {
765
- if let Some ( ( callsite_debug_src_loc_inst, _) ) =
766
- enclosing_inlined_frames. pop ( )
767
- {
768
- current_debug_src_loc_inst = callsite_debug_src_loc_inst;
769
- }
770
- }
771
- CustomOp :: Abort => break ,
772
- }
719
+ let mut vars_and_debuginfo = vec ! [ ] ;
720
+ insts. retain_mut ( |inst| {
721
+ let is_debuginfo = match inst. class . opcode {
722
+ Op :: Line | Op :: NoLine => true ,
723
+ Op :: ExtInst => {
724
+ inst. operands [ 0 ] . unwrap_id_ref ( ) == self . custom_ext_inst_set_import
725
+ && CustomOp :: decode_from_ext_inst ( inst) . is_debuginfo ( )
773
726
}
774
- Op :: Variable => { }
775
- _ => break ,
727
+ _ => false ,
728
+ } ;
729
+ if is_debuginfo {
730
+ // NOTE(eddyb) `OpExtInst`s have a result ID,
731
+ // even if unused, and it has to be unique.
732
+ let mut inst = inst. clone ( ) ;
733
+ if let Some ( id) = & mut inst. result_id {
734
+ * id = self . id ( ) ;
735
+ }
736
+ vars_and_debuginfo. push ( inst) ;
737
+ true
738
+ } else if inst. class . opcode == Op :: Variable {
739
+ // HACK(eddyb) we're removing this `Instruction` from
740
+ // `inst`, so it doesn't really matter what we use here.
741
+ vars_and_debuginfo. push ( mem:: replace (
742
+ inst,
743
+ Instruction :: new ( Op :: Nop , None , None , vec ! [ ] ) ,
744
+ ) ) ;
745
+ false
746
+ } else {
747
+ true
776
748
}
777
- vars_and_debuginfo_range. end += 1 ;
778
- }
779
-
780
- // `vars_and_debuginfo_range.end` indicates where `OpVariable`s
781
- // end and other instructions start (module debuginfo), but to
782
- // split the block in two, both sides of the "cut" need "repair":
783
- // - the variables are missing "inlined call frames" pops, that
784
- // may happen later in the block, and have to be synthesized
785
- // - the non-variables are missing "inlined call frames" pushes,
786
- // that must be recreated to avoid ending up with dangling pops
787
- //
788
- // FIXME(eddyb) this only collects to avoid borrow conflicts,
789
- // between e.g. `enclosing_inlined_frames` and mutating `insts`,
790
- // but also between different uses of `self`.
791
- let all_pops_after_vars: SmallVec < [ _ ; 8 ] > = enclosing_inlined_frames
792
- . iter ( )
793
- . map ( |_| custom_inst_to_inst ( self , CustomInst :: PopInlinedCallFrame ) )
794
- . collect ( ) ;
795
- let all_repushes_before_non_vars: SmallVec < [ _ ; 8 ] > =
796
- ( enclosing_inlined_frames. into_iter ( ) . flat_map (
797
- |( callsite_debug_src_loc_inst, push_inlined_call_frame_inst) | {
798
- ( callsite_debug_src_loc_inst. into_iter ( ) )
799
- . chain ( [ push_inlined_call_frame_inst] )
800
- } ,
801
- ) )
802
- . chain ( current_debug_src_loc_inst)
803
- . map ( |inst| instantiate_debuginfo ( self , inst) )
804
- . collect ( ) ;
805
-
806
- let vars_and_debuginfo =
807
- insts. splice ( vars_and_debuginfo_range, all_repushes_before_non_vars) ;
808
- let repaired_vars_and_debuginfo = vars_and_debuginfo. chain ( all_pops_after_vars) ;
809
-
810
- // FIXME(eddyb) collecting shouldn't be necessary but this is
811
- // nested in a closure, and `splice` borrows the original `Vec`.
812
- repaired_vars_and_debuginfo. collect :: < SmallVec < [ _ ; 8 ] > > ( )
749
+ } ) ;
750
+ vars_and_debuginfo
813
751
} ;
814
752
815
753
let [ mut inlined_callee_entry_block] : [ _ ; 1 ] =
816
754
inlined_callee_blocks. try_into ( ) . unwrap ( ) ;
817
755
818
756
// Move the `OpVariable`s of the callee to the caller.
819
- let callee_vars_and_debuginfo =
820
- steal_vars ( & mut inlined_callee_entry_block. instructions ) ;
821
- self . insert_opvariables ( & mut caller. blocks [ 0 ] , callee_vars_and_debuginfo) ;
757
+ insert_opvariables (
758
+ & mut caller. blocks [ 0 ] ,
759
+ steal_vars ( & mut inlined_callee_entry_block. instructions ) ,
760
+ ) ;
822
761
823
762
caller. blocks [ pre_call_block_idx]
824
763
. instructions
@@ -1051,52 +990,15 @@ impl Inliner<'_, '_> {
1051
990
caller_restore_debuginfo_after_call,
1052
991
)
1053
992
}
993
+ }
1054
994
1055
- fn insert_opvariables ( & self , block : & mut Block , insts : impl IntoIterator < Item = Instruction > ) {
1056
- // HACK(eddyb) this isn't as efficient as it could be in theory, but it's
1057
- // very important to make sure sure to never insert new instructions in
1058
- // the middle of debuginfo (as it would be affected by it).
1059
- let mut inlined_frames_depth = 0usize ;
1060
- let mut outermost_has_debug_src_loc = false ;
1061
- let mut last_debugless_var_insertion_point_candidate = None ;
1062
- for ( i, inst) in block. instructions . iter ( ) . enumerate ( ) {
1063
- last_debugless_var_insertion_point_candidate =
1064
- ( inlined_frames_depth == 0 && !outermost_has_debug_src_loc) . then_some ( i) ;
1065
-
1066
- let changed_has_debug_src_loc = match inst. class . opcode {
1067
- Op :: Line => true ,
1068
- Op :: NoLine => false ,
1069
- Op :: ExtInst
1070
- if inst. operands [ 0 ] . unwrap_id_ref ( ) == self . custom_ext_inst_set_import =>
1071
- {
1072
- match CustomOp :: decode_from_ext_inst ( inst) {
1073
- CustomOp :: SetDebugSrcLoc => true ,
1074
- CustomOp :: ClearDebugSrcLoc => false ,
1075
- CustomOp :: PushInlinedCallFrame => {
1076
- inlined_frames_depth += 1 ;
1077
- continue ;
1078
- }
1079
- CustomOp :: PopInlinedCallFrame => {
1080
- inlined_frames_depth = inlined_frames_depth. saturating_sub ( 1 ) ;
1081
- continue ;
1082
- }
1083
- CustomOp :: Abort => break ,
1084
- }
1085
- }
1086
- Op :: Variable => continue ,
1087
- _ => break ,
1088
- } ;
1089
-
1090
- if inlined_frames_depth == 0 {
1091
- outermost_has_debug_src_loc = changed_has_debug_src_loc;
1092
- }
1093
- }
1094
-
1095
- // HACK(eddyb) fallback to inserting at the start, which should be correct.
1096
- // FIXME(eddyb) some level of debuginfo repair could prevent needing this.
1097
- let i = last_debugless_var_insertion_point_candidate. unwrap_or ( 0 ) ;
1098
- block. instructions . splice ( i..i, insts) ;
1099
- }
995
+ fn insert_opvariables ( block : & mut Block , insts : impl IntoIterator < Item = Instruction > ) {
996
+ let first_non_variable = block
997
+ . instructions
998
+ . iter ( )
999
+ . position ( |inst| inst. class . opcode != Op :: Variable ) ;
1000
+ let i = first_non_variable. unwrap_or ( block. instructions . len ( ) ) ;
1001
+ block. instructions . splice ( i..i, insts) ;
1100
1002
}
1101
1003
1102
1004
fn fuse_trivial_branches ( function : & mut Function ) {
@@ -1131,7 +1033,7 @@ fn fuse_trivial_branches(function: &mut Function) {
1131
1033
} ;
1132
1034
let pred_insts = & function. blocks [ pred] . instructions ;
1133
1035
if pred_insts. last ( ) . unwrap ( ) . class . opcode == Op :: Branch {
1134
- let mut dest_insts = mem :: take ( & mut function. blocks [ dest_block] . instructions ) ;
1036
+ let mut dest_insts = take ( & mut function. blocks [ dest_block] . instructions ) ;
1135
1037
let pred_insts = & mut function. blocks [ pred] . instructions ;
1136
1038
pred_insts. pop ( ) ; // pop the branch
1137
1039
pred_insts. append ( & mut dest_insts) ;
0 commit comments