Skip to content

Commit 34c671a

Browse files
Merge pull request #210 from Tcode-Motion/optimize-cfg-lookup-16169091484459046166
⚡ O(1) CFG successor lookup in IR verifier
2 parents d263495 + 7594825 commit 34c671a

2 files changed

Lines changed: 13 additions & 4 deletions

File tree

‎.jules/bolt.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@
4141
## 2026-09-24 - Zero-allocation hex decoding
4242
**Learning:** Using `hex::decode` from the `hex` crate provides a significant performance boost over manually iterating through strings and calling `u8::from_str_radix`, even though `hex::decode` allocates a new `Vec<u8>`. It avoids the heavy intermediate allocations and processing overhead of manual string slice iterations.
4343
**Action:** Always prefer `hex::decode` and `hex::encode` when working with hexadecimal encoding/decoding instead of manual iterative string parsing to significantly boost performance.
44+
## 2024-05-18 - Optimized CFG Successor Lookup
45+
**Learning:** During control flow graph validation in `compiler/optimizer/src/verifier.rs`, using `func.blocks.iter().find(|b| b.id == succ)` for every successor of every block created an O(V * E) time complexity bottleneck. By pre-computing a `HashMap` of `BlockId` to `&BasicBlock` in a single pass, the verification complexity was reduced to O(V + E).
46+
**Action:** When validating graph structures or resolving many cross-references within a known collection, construct a lookup map in advance instead of performing repeated O(N) linear scans.

‎compiler/optimizer/src/verifier.rs‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashSet;
1+
use std::collections::{HashMap, HashSet};
22
use techscript_ir::block::BasicBlock;
33
use techscript_ir::function::Function;
44
use techscript_ir::module::Module;
@@ -27,7 +27,14 @@ impl IRVerifier {
2727
}
2828

2929
fn verify_function(&self, func: &Function) -> Result<(), String> {
30-
let block_ids: HashSet<_> = func.blocks.iter().map(|b| b.id).collect();
30+
let mut block_ids: HashSet<_> = HashSet::with_capacity(func.blocks.len());
31+
// ⚡ Bolt Performance Optimization:
32+
// Use HashMap for O(1) block lookups instead of O(N) linear scans during CFG verification.
33+
let mut block_map = HashMap::with_capacity(func.blocks.len());
34+
for b in &func.blocks {
35+
block_ids.insert(b.id);
36+
block_map.insert(b.id, b);
37+
}
3138

3239
for block in &func.blocks {
3340
self.verify_block(block, &block_ids)?;
@@ -36,8 +43,7 @@ impl IRVerifier {
3643
// Verify CFG link mapping consistency
3744
for block in &func.blocks {
3845
for &succ in &block.successors {
39-
let succ_block = func.blocks.iter().find(|b| b.id == succ);
40-
if let Some(sb) = succ_block {
46+
if let Some(&sb) = block_map.get(&succ) {
4147
if !sb.predecessors.contains(&block.id) {
4248
return Err(format!(
4349
"CFG inconsistency: Block '{}' lists '{}' as successor, but '{}' does not list '{}' as predecessor",

0 commit comments

Comments
 (0)