diff --git a/cranelift/codegen/src/legalizer/mod.rs b/cranelift/codegen/src/legalizer/mod.rs index 70fb614a2d..d00a2ccd79 100644 --- a/cranelift/codegen/src/legalizer/mod.rs +++ b/cranelift/codegen/src/legalizer/mod.rs @@ -21,6 +21,7 @@ use crate::ir::{self, InstBuilder, MemFlags}; use crate::isa::TargetIsa; use crate::predicates; use crate::timing; +use std::collections::BTreeSet; use std::vec::Vec; mod boundary; @@ -146,7 +147,9 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is func.encodings.resize(func.dfg.num_insts()); let mut pos = FuncCursor::new(func); - let mut pending_splits = Vec::new(); + + // This must be a set to prevent trying to legalize `isplit` and `vsplit` twice in certain cases. + let mut pending_splits = BTreeSet::new(); // Process EBBs in layout order. Some legalization actions may split the current EBB or append // new ones to the end. We need to make sure we visit those new EBBs too. @@ -166,7 +169,9 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is // The argument of a `isplit` or `vsplit` instruction didn't resolve to a // `iconcat` or `vconcat` instruction. Try again after legalizing the rest of // the instructions. - LegalizeInstResult::SplitLegalizePending => pending_splits.push(inst), + LegalizeInstResult::SplitLegalizePending => { + pending_splits.insert(inst); + } } } } diff --git a/cranelift/filetests/filetests/isa/x86/isplit-not-legalized-twice.clif b/cranelift/filetests/filetests/isa/x86/isplit-not-legalized-twice.clif new file mode 100644 index 0000000000..4b81a186da --- /dev/null +++ b/cranelift/filetests/filetests/isa/x86/isplit-not-legalized-twice.clif @@ -0,0 +1,20 @@ +test compile +target x86_64 + +function u0:0(i64, i64) -> i128 system_v { +ebb0(v0: i64, v1: i64): + trap user0 + +ebb30: + v245 = iconst.i64 0 + v246 = iconcat v245, v245 + ; The next instruction used to be legalized twice, causing a panic the second time. + v250, v251 = isplit.i128 v370 + v252, v253 = isplit v246 + trap user0 + +ebb45: + v369 = iconst.i64 0 + v370 = load.i128 v369 + trap user0 +}