diff --git a/src/cfg.rs b/src/cfg.rs index cf4428c..0ad6c07 100644 --- a/src/cfg.rs +++ b/src/cfg.rs @@ -72,10 +72,12 @@ impl CFGInfo { block_entry[block.index()] = ProgPoint::before(f.block_insns(block).first()); block_exit[block.index()] = ProgPoint::after(f.block_insns(block).last()); + // Check critical edge condition: if there is more than + // one predecessor, each must have only one successor + // (this block). let preds = f.block_preds(block).len() + if block == f.entry_block() { 1 } else { 0 }; if preds > 1 { for (i, &pred) in f.block_preds(block).iter().enumerate() { - // Check critical edge condition. let succs = f.block_succs(pred).len(); if succs > 1 { return Err(RegAllocError::CritEdge(pred, block)); @@ -83,6 +85,25 @@ impl CFGInfo { pred_pos[pred.index()] = i; } } + + // Check branch-arg condition: if any successors have more + // than one predecessor (given above, there will only be + // one such successor), then the last instruction of this + // block (the branch) cannot have any args other than the + // blockparams. + let mut require_no_branch_args = false; + for &succ in f.block_succs(block) { + let preds = f.block_preds(succ).len() + if succ == f.entry_block() { 1 } else { 0 }; + if preds > 1 { + require_no_branch_args = true; + } + } + if require_no_branch_args { + let last = f.block_insns(block).last(); + if f.branch_blockparam_arg_offset(block, last) > 0 { + return Err(RegAllocError::DisallowedBranchArg(last)); + } + } } Ok(CFGInfo { diff --git a/src/lib.rs b/src/lib.rs index 961be75..a4d8185 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -983,6 +983,12 @@ pub enum RegAllocError { Branch(Inst), /// A VReg is live-in on entry; this is not allowed. EntryLivein, + /// A branch has non-blockparam arg(s) and at least one of the + /// successor blocks has more than one predecessor, forcing + /// edge-moves before this branch. This is disallowed because it + /// places a use after the edge moves occur; insert an edge block + /// to avoid the situation. + DisallowedBranchArg(Inst), } impl std::fmt::Display for RegAllocError {