@@ -540,6 +540,30 @@ pub struct AliasAnalysis<'a> {
540540 mem_values : FxHashMap < MemoryLoc , ( Inst , Value ) > ,
541541}
542542
543+ /// Can a path starting at `start` reach a divergent block without first
544+ /// passing through `stop`?
545+ fn can_reach_divergent_block (
546+ post_dom_tree : & PostDominatorTree ,
547+ cfg : & ControlFlowGraph ,
548+ start : Block ,
549+ stop : Block ,
550+ ) -> bool {
551+ let mut worklist = vec ! [ start] ;
552+ let mut visited = FxHashSet :: default ( ) ;
553+
554+ while let Some ( block) = worklist. pop ( ) {
555+ if block == stop || !visited. insert ( block) {
556+ continue ;
557+ }
558+ if post_dom_tree. diverges ( block) {
559+ return true ;
560+ }
561+ worklist. extend ( cfg. succ_iter ( block) ) ;
562+ }
563+
564+ false
565+ }
566+
543567impl < ' a > AliasAnalysis < ' a > {
544568 /// Perform an alias analysis pass.
545569 pub fn new ( func : & Function , domtree : & ' a DominatorTree ) -> AliasAnalysis < ' a > {
@@ -584,9 +608,16 @@ impl<'a> AliasAnalysis<'a> {
584608 return func. layout . pp_cmp ( overwriter, maybe_dead) != Ordering :: Less ;
585609 }
586610
587- self . post_dom_tree
588- . get_or_insert_with ( || PostDominatorTree :: with_cfg ( cfg) )
589- . post_dominates ( overwriter, maybe_dead, & func. layout )
611+ let post_dom_tree = self
612+ . post_dom_tree
613+ . get_or_insert_with ( || PostDominatorTree :: with_cfg ( cfg) ) ;
614+
615+ // The post-dominator tree only considers paths that reach an explicit
616+ // CFG exit. A path into a divergent region may still observe the store
617+ // by trapping, so it must also pass through the overwriter before we
618+ // can remove the original store.
619+ post_dom_tree. post_dominates ( overwriter, maybe_dead, & func. layout )
620+ && !can_reach_divergent_block ( post_dom_tree, cfg, maybe_dead_block, overwriter_block)
590621 }
591622
592623 fn compute_block_input_states ( & mut self , func : & Function ) {
0 commit comments