Skip to content

Commit 98d0b5c

Browse files
committed
Compile integer patterns to a switch
Instead of a nested if/else tree we compile such patterns to a Switch instruction, but it results in a cleaner IR and LLVM _might_ benefit from it (though this is hard to verify) in certain scenarios, or at least it won't have to reconstruct an if/else tree to a switch just so it can compile it to a jump table. This fixes #790. Changelog: changed
1 parent 2f74a26 commit 98d0b5c

1 file changed

Lines changed: 17 additions & 40 deletions

File tree

compiler/src/mir/passes.rs

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3493,53 +3493,30 @@ impl<'a> LowerMethod<'a> {
34933493
mut registers: Vec<RegisterId>,
34943494
) -> BlockId {
34953495
let loc = state.location;
3496-
let blocks = self.add_blocks(cases.len());
3496+
let test_block = self.add_block();
3497+
let mut blocks: Vec<(i64, BlockId)> = Vec::new();
34973498

3498-
self.add_edge(parent_block, blocks[0]);
3499-
self.connect_block_sequence(&blocks);
3499+
self.add_edge(parent_block, test_block);
35003500
registers.push(test_reg);
35013501

3502-
let fallback = self.decision(
3503-
state,
3504-
fallback_node,
3505-
blocks[blocks.len() - 1],
3506-
registers.clone(),
3507-
);
3508-
3509-
for (index, case) in cases.into_iter().enumerate() {
3510-
let test_block = blocks[index];
3511-
let fail_block = blocks.get(index + 1).cloned().unwrap_or(fallback);
3512-
let res_reg = self.new_untracked_register(TypeRef::boolean());
3513-
3514-
let test_end_block = match case.constructor {
3515-
pmatch::Constructor::Int(val) => {
3516-
let val_reg = self.new_untracked_register(TypeRef::int());
3517-
3518-
self.block_mut(test_block).i64_literal(val_reg, val, loc);
3519-
self.block_mut(test_block).call_builtin(
3520-
res_reg,
3521-
types::Intrinsic::IntEq,
3522-
vec![test_reg, val_reg],
3523-
loc,
3524-
);
3525-
3526-
test_block
3527-
}
3528-
_ => unreachable!(),
3502+
for case in cases {
3503+
let pmatch::Constructor::Int(val) = case.constructor else {
3504+
unreachable!()
35293505
};
3506+
let block = self.add_block();
35303507

3531-
let ok_block = self.decision(
3532-
state,
3533-
case.node,
3534-
test_end_block,
3535-
registers.clone(),
3536-
);
3537-
3538-
self.block_mut(test_end_block)
3539-
.branch(res_reg, ok_block, fail_block, loc);
3508+
self.add_edge(test_block, block);
3509+
blocks.push((val, block));
3510+
self.decision(state, case.node, block, registers.clone());
35403511
}
35413512

3542-
blocks[0]
3513+
let fallback =
3514+
self.decision(state, fallback_node, test_block, registers.clone());
3515+
3516+
self.block_mut(test_block)
3517+
.switch_with_fallback(test_reg, blocks, fallback, loc);
3518+
3519+
test_block
35433520
}
35443521

35453522
fn type_patterns(

0 commit comments

Comments
 (0)