Skip to content

Commit eb7ed85

Browse files
committed
Cranelift: Prevent DSE across divergent paths
1 parent e8ac8c2 commit eb7ed85

2 files changed

Lines changed: 57 additions & 3 deletions

File tree

cranelift/codegen/src/alias_analysis.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
543567
impl<'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) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
test alias-analysis
2+
set opt_level=speed
3+
target aarch64
4+
5+
function %divergent_path(i64, i32) {
6+
region0 = 0 "R0"
7+
8+
block0(v0: i64, v1: i32):
9+
v2 = iconst.i32 111
10+
store notrap aligned region0 v2, v0
11+
brif v1, block1, block2
12+
13+
block1:
14+
v3 = iconst.i32 222
15+
store notrap aligned region0 v3, v0
16+
return
17+
18+
block2:
19+
jump block2
20+
}
21+
22+
; check: store notrap aligned region0 v2, v0
23+
; check: store notrap aligned region0 v3, v0

0 commit comments

Comments
 (0)