9595//! [previous attempt]: https://github.com/rust-lang/rust/pull/47954
9696//! [subsequent approach]: https://github.com/rust-lang/rust/pull/71003
9797
98- use crate :: dataflow:: { self , Analysis } ;
98+ use crate :: dataflow:: impls:: { MaybeInitializedLocals , MaybeLiveLocals } ;
99+ use crate :: dataflow:: Analysis ;
99100use crate :: {
100101 transform:: { MirPass , MirSource } ,
101102 util:: { dump_mir, PassWhere } ,
102103} ;
103- use dataflow :: impls :: { MaybeInitializedLocals , MaybeLiveLocals } ;
104+ use itertools :: Itertools ;
104105use rustc_data_structures:: unify:: { InPlaceUnificationTable , UnifyKey } ;
105106use rustc_index:: {
106107 bit_set:: { BitMatrix , BitSet } ,
@@ -255,12 +256,14 @@ impl Replacements<'tcx> {
255256
256257 // We still return `Err` in any case, as `src` and `dest` do not need to be unified
257258 // *again*.
259+ trace ! ( "push({:?}): already unified" , candidate) ;
258260 return Err ( ( ) ) ;
259261 }
260262
261263 let entry = & mut self . map [ candidate. src ] ;
262264 if entry. is_some ( ) {
263265 // We're already replacing `src` with something else, so this candidate is out.
266+ trace ! ( "push({:?}): src already has replacement" , candidate) ;
264267 return Err ( ( ) ) ;
265268 }
266269
@@ -270,6 +273,7 @@ impl Replacements<'tcx> {
270273 self . kill . insert ( candidate. src ) ;
271274 self . kill . insert ( candidate. dest . local ) ;
272275
276+ trace ! ( "push({:?}): accepted" , candidate) ;
273277 Ok ( ( ) )
274278 }
275279
@@ -535,7 +539,7 @@ impl Conflicts<'a> {
535539
536540 trace ! ( "record conflicts at {:?}" , loc) ;
537541
538- this. record_conflicts ( & mut live_and_init_locals[ statement_index] ) ;
542+ this. record_dataflow_conflicts ( & mut live_and_init_locals[ statement_index] ) ;
539543 }
540544
541545 init. seek_to_block_end ( block) ;
@@ -544,13 +548,13 @@ impl Conflicts<'a> {
544548 conflicts. intersect ( live. get ( ) ) ;
545549 trace ! ( "record conflicts at end of {:?}" , block) ;
546550
547- this. record_conflicts ( & mut conflicts) ;
551+ this. record_dataflow_conflicts ( & mut conflicts) ;
548552 }
549553
550554 this
551555 }
552556
553- fn record_conflicts ( & mut self , new_conflicts : & mut BitSet < Local > ) {
557+ fn record_dataflow_conflicts ( & mut self , new_conflicts : & mut BitSet < Local > ) {
554558 // Remove all locals that are not candidates.
555559 new_conflicts. intersect ( self . relevant_locals ) ;
556560
@@ -559,6 +563,12 @@ impl Conflicts<'a> {
559563 }
560564 }
561565
566+ fn record_local_conflict ( & mut self , a : Local , b : Local , why : & str ) {
567+ trace ! ( "conflict {:?} <-> {:?} due to {}" , a, b, why) ;
568+ self . matrix . insert ( a, b) ;
569+ self . matrix . insert ( b, a) ;
570+ }
571+
562572 /// Records locals that must not overlap during the evaluation of `stmt`. These locals conflict
563573 /// and must not be merged.
564574 fn record_statement_conflicts ( & mut self , stmt : & Statement < ' _ > ) {
@@ -575,8 +585,11 @@ impl Conflicts<'a> {
575585 if !in_place. is_indirect ( ) {
576586 for out_place in & * asm. outputs {
577587 if !out_place. is_indirect ( ) && !in_place. is_indirect ( ) {
578- self . matrix . insert ( in_place. local , out_place. local ) ;
579- self . matrix . insert ( out_place. local , in_place. local ) ;
588+ self . record_local_conflict (
589+ in_place. local ,
590+ out_place. local ,
591+ "aliasing llvm_asm! operands" ,
592+ ) ;
580593 }
581594 }
582595 }
@@ -599,16 +612,22 @@ impl Conflicts<'a> {
599612 TerminatorKind :: DropAndReplace { location, value, target : _, unwind : _ } => {
600613 if let Some ( place) = value. place ( ) {
601614 if !place. is_indirect ( ) && !location. is_indirect ( ) {
602- self . matrix . insert ( place. local , location. local ) ;
603- self . matrix . insert ( location. local , place. local ) ;
615+ self . record_local_conflict (
616+ place. local ,
617+ location. local ,
618+ "DropAndReplace operand overlap" ,
619+ ) ;
604620 }
605621 }
606622 }
607623 TerminatorKind :: Yield { value, resume : _, resume_arg, drop : _ } => {
608624 if let Some ( place) = value. place ( ) {
609625 if !place. is_indirect ( ) && !resume_arg. is_indirect ( ) {
610- self . matrix . insert ( place. local , resume_arg. local ) ;
611- self . matrix . insert ( resume_arg. local , place. local ) ;
626+ self . record_local_conflict (
627+ place. local ,
628+ resume_arg. local ,
629+ "Yield operand overlap" ,
630+ ) ;
612631 }
613632 }
614633 }
@@ -623,8 +642,11 @@ impl Conflicts<'a> {
623642 for arg in args. iter ( ) . chain ( Some ( func) ) {
624643 if let Some ( place) = arg. place ( ) {
625644 if !place. is_indirect ( ) && !dest_place. is_indirect ( ) {
626- self . matrix . insert ( dest_place. local , place. local ) ;
627- self . matrix . insert ( place. local , dest_place. local ) ;
645+ self . record_local_conflict (
646+ dest_place. local ,
647+ place. local ,
648+ "call dest/arg overlap" ,
649+ ) ;
628650 }
629651 }
630652 }
@@ -653,8 +675,11 @@ impl Conflicts<'a> {
653675 InlineAsmOperand :: In { reg : _, value } => {
654676 if let Some ( p) = value. place ( ) {
655677 if !p. is_indirect ( ) && !dest_place. is_indirect ( ) {
656- self . matrix . insert ( p. local , dest_place. local ) ;
657- self . matrix . insert ( dest_place. local , p. local ) ;
678+ self . record_local_conflict (
679+ p. local ,
680+ dest_place. local ,
681+ "asm! operand overlap" ,
682+ ) ;
658683 }
659684 }
660685 }
@@ -664,8 +689,11 @@ impl Conflicts<'a> {
664689 place : Some ( place) ,
665690 } => {
666691 if !place. is_indirect ( ) && !dest_place. is_indirect ( ) {
667- self . matrix . insert ( place. local , dest_place. local ) ;
668- self . matrix . insert ( dest_place. local , place. local ) ;
692+ self . record_local_conflict (
693+ place. local ,
694+ dest_place. local ,
695+ "asm! operand overlap" ,
696+ ) ;
669697 }
670698 }
671699 InlineAsmOperand :: InOut {
@@ -676,15 +704,21 @@ impl Conflicts<'a> {
676704 } => {
677705 if let Some ( place) = in_value. place ( ) {
678706 if !place. is_indirect ( ) && !dest_place. is_indirect ( ) {
679- self . matrix . insert ( place. local , dest_place. local ) ;
680- self . matrix . insert ( dest_place. local , place. local ) ;
707+ self . record_local_conflict (
708+ place. local ,
709+ dest_place. local ,
710+ "asm! operand overlap" ,
711+ ) ;
681712 }
682713 }
683714
684715 if let Some ( place) = out_place {
685716 if !place. is_indirect ( ) && !dest_place. is_indirect ( ) {
686- self . matrix . insert ( place. local , dest_place. local ) ;
687- self . matrix . insert ( dest_place. local , place. local ) ;
717+ self . record_local_conflict (
718+ place. local ,
719+ dest_place. local ,
720+ "asm! operand overlap" ,
721+ ) ;
688722 }
689723 }
690724 }
@@ -750,6 +784,10 @@ impl Conflicts<'a> {
750784 // FIXME: This might be somewhat slow. Conflict graphs are undirected, maybe we can use
751785 // something with union-find to speed this up?
752786
787+ trace ! ( "unify({:?}, {:?})" , a, b) ;
788+ trace ! ( "{:?} conflicts: {:?}" , a, self . matrix. iter( a) . format( ", " ) ) ;
789+ trace ! ( "{:?} conflicts: {:?}" , b, self . matrix. iter( b) . format( ", " ) ) ;
790+
753791 // Make all locals that conflict with `a` also conflict with `b`, and vice versa.
754792 self . unify_cache . clear ( ) ;
755793 for conflicts_with_a in self . matrix . iter ( a) {
0 commit comments