Skip to content

Commit 73d87ab

Browse files
committed
Type-safe aliases and control-flow-only BFS for loop body detection
1 parent 33561fc commit 73d87ab

1 file changed

Lines changed: 35 additions & 10 deletions

File tree

  • rust/spirv-tools-opt/src/direct

rust/spirv-tools-opt/src/direct/mod.rs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,27 @@ pub fn optimize_module_direct(module: &Module) -> Result<Module, EgglogOptError>
237237
continue;
238238
}
239239
body_indices.push(idx);
240-
// Follow all branch targets from this block
240+
// Follow control-flow edges (branch targets) from this block.
241+
// Only terminators (Branch/BranchConditional/Switch) and
242+
// merge instructions (LoopMerge/SelectionMerge) reference
243+
// block labels as operands.
241244
if let Some(blk) = func.blocks.get(idx) {
242245
for bi in &blk.instructions {
243-
for op in &bi.operands {
244-
if let Some(target_label) = op.id_ref_any() {
245-
if let Some(&target_idx) =
246-
label_map.get(&target_label)
247-
{
248-
worklist.push(target_idx);
246+
if matches!(
247+
bi.class.opcode,
248+
Op::Branch
249+
| Op::BranchConditional
250+
| Op::Switch
251+
| Op::LoopMerge
252+
| Op::SelectionMerge
253+
) {
254+
for op in &bi.operands {
255+
if let Some(target_label) = op.id_ref_any() {
256+
if let Some(&target_idx) =
257+
label_map.get(&target_label)
258+
{
259+
worklist.push(target_idx);
260+
}
249261
}
250262
}
251263
}
@@ -974,8 +986,16 @@ pub fn optimize_module_direct(module: &Module) -> Result<Module, EgglogOptError>
974986
// Check if the result is just a reference to another ID
975987
if let Some(alias_id) = parse_sym_alias_from_term(parsed_term.as_ref(), &id_map) {
976988
if alias_id != id {
977-
// This instruction becomes an alias to another value
978-
id_aliases.insert(id, alias_id);
989+
// Only alias when both IDs have the same SPIR-V type.
990+
// The egraph may unify values across SPIR-V types (e.g. two
991+
// constants with the same bit pattern but different type IDs).
992+
// Aliasing across types would cause OpStore type mismatches
993+
// when resolve_aliases replaces operand references.
994+
let type_matches = ctx.id_to_type.get(&id)
995+
== ctx.id_to_type.get(&alias_id);
996+
if type_matches {
997+
id_aliases.insert(id, alias_id);
998+
}
979999
used_ids.insert(alias_id);
9801000
// Emit CopyObject to maintain SSA form
9811001
optimized_instructions.insert(
@@ -1019,7 +1039,12 @@ pub fn optimize_module_direct(module: &Module) -> Result<Module, EgglogOptError>
10191039
// emit_term resolved to an existing ID — emit CopyObject
10201040
// if it's a different ID, or skip if same
10211041
if final_id != id {
1022-
id_aliases.insert(id, final_id);
1042+
// Only alias when SPIR-V types match (see above)
1043+
let type_matches = ctx.id_to_type.get(&id)
1044+
== ctx.id_to_type.get(&final_id);
1045+
if type_matches {
1046+
id_aliases.insert(id, final_id);
1047+
}
10231048
used_ids.insert(final_id);
10241049
optimized_instructions.insert(
10251050
id,

0 commit comments

Comments
 (0)