Skip to main content

oxilean_codegen/mlir_backend/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use std::collections::HashMap;
6
7use super::types::{
8    AffineMap, CmpfPred, CmpiPred, MLIRAnalysisCache, MLIRConstantFoldingHelper, MLIRDepGraph,
9    MLIRDominatorTree, MLIRExtCache, MLIRExtConstFolder, MLIRExtDepGraph, MLIRExtDomTree,
10    MLIRExtLiveness, MLIRExtPassConfig, MLIRExtPassPhase, MLIRExtPassRegistry, MLIRExtPassStats,
11    MLIRExtWorklist, MLIRLivenessInfo, MLIRPassConfig, MLIRPassPhase, MLIRPassRegistry,
12    MLIRPassStats, MLIRWorklist, MlirAttr, MlirBackend, MlirBlock, MlirBuilder, MlirDialect,
13    MlirFunc, MlirGlobal, MlirModule, MlirRegion, MlirType, MlirValue, SsaCounter,
14};
15
16#[cfg(test)]
17mod tests {
18    use super::*;
19    #[test]
20    pub(super) fn test_mlir_type_integer_display() {
21        assert_eq!(MlirType::Integer(64, false).to_string(), "i64");
22        assert_eq!(MlirType::Integer(32, false).to_string(), "i32");
23        assert_eq!(MlirType::Integer(1, false).to_string(), "i1");
24    }
25    #[test]
26    pub(super) fn test_mlir_type_signed_integer_display() {
27        assert_eq!(MlirType::Integer(32, true).to_string(), "si32");
28    }
29    #[test]
30    pub(super) fn test_mlir_type_float_display() {
31        assert_eq!(MlirType::Float(32).to_string(), "f32");
32        assert_eq!(MlirType::Float(64).to_string(), "f64");
33        assert_eq!(MlirType::Float(16).to_string(), "f16");
34    }
35    #[test]
36    pub(super) fn test_mlir_type_index() {
37        assert_eq!(MlirType::Index.to_string(), "index");
38    }
39    #[test]
40    pub(super) fn test_mlir_type_none() {
41        assert_eq!(MlirType::NoneType.to_string(), "none");
42    }
43    #[test]
44    pub(super) fn test_mlir_type_tensor() {
45        let ty = MlirType::Tensor(vec![2, 3], Box::new(MlirType::Float(32)));
46        assert_eq!(ty.to_string(), "tensor<2x3xf32>");
47    }
48    #[test]
49    pub(super) fn test_mlir_type_tensor_dynamic() {
50        let ty = MlirType::Tensor(vec![-1, 4], Box::new(MlirType::Integer(64, false)));
51        assert_eq!(ty.to_string(), "tensor<?x4xi64>");
52    }
53    #[test]
54    pub(super) fn test_mlir_type_vector() {
55        let ty = MlirType::Vector(vec![4], Box::new(MlirType::Float(32)));
56        assert_eq!(ty.to_string(), "vector<4xf32>");
57    }
58    #[test]
59    pub(super) fn test_mlir_type_memref() {
60        let ty = MlirType::MemRef(
61            Box::new(MlirType::Float(64)),
62            vec![10, 20],
63            AffineMap::Constant,
64        );
65        assert!(ty.to_string().starts_with("memref<10x20xf64"));
66    }
67    #[test]
68    pub(super) fn test_mlir_type_tuple() {
69        let ty = MlirType::Tuple(vec![MlirType::Integer(32, false), MlirType::Float(64)]);
70        assert_eq!(ty.to_string(), "tuple<i32, f64>");
71    }
72    #[test]
73    pub(super) fn test_mlir_type_func_type() {
74        let ty = MlirType::FuncType(
75            vec![MlirType::Integer(64, false), MlirType::Integer(64, false)],
76            vec![MlirType::Integer(64, false)],
77        );
78        assert_eq!(ty.to_string(), "(i64, i64) -> i64");
79    }
80    #[test]
81    pub(super) fn test_mlir_value_numbered() {
82        let v = MlirValue::numbered(0, MlirType::Integer(64, false));
83        assert_eq!(v.to_string(), "%0");
84    }
85    #[test]
86    pub(super) fn test_mlir_value_named() {
87        let v = MlirValue::named("arg0", MlirType::Float(32));
88        assert_eq!(v.to_string(), "%arg0");
89    }
90    #[test]
91    pub(super) fn test_attr_integer() {
92        let attr = MlirAttr::Integer(42, MlirType::Integer(64, false));
93        assert_eq!(attr.to_string(), "42 : i64");
94    }
95    #[test]
96    pub(super) fn test_attr_string() {
97        let attr = MlirAttr::Str("hello".to_string());
98        assert_eq!(attr.to_string(), "\"hello\"");
99    }
100    #[test]
101    pub(super) fn test_attr_string_escaping() {
102        let attr = MlirAttr::Str("say \"hi\"".to_string());
103        assert!(attr.to_string().contains("\\\""));
104    }
105    #[test]
106    pub(super) fn test_attr_symbol() {
107        let attr = MlirAttr::Symbol("add".to_string());
108        assert_eq!(attr.to_string(), "@add");
109    }
110    #[test]
111    pub(super) fn test_attr_array() {
112        let attr = MlirAttr::Array(vec![
113            MlirAttr::Integer(1, MlirType::Integer(32, false)),
114            MlirAttr::Integer(2, MlirType::Integer(32, false)),
115        ]);
116        assert!(attr.to_string().starts_with('['));
117        assert!(attr.to_string().ends_with(']'));
118    }
119    #[test]
120    pub(super) fn test_attr_dict() {
121        let attr = MlirAttr::Dict(vec![("key".to_string(), MlirAttr::Bool(true))]);
122        let s = attr.to_string();
123        assert!(s.contains("key"));
124        assert!(s.contains("true"));
125    }
126    #[test]
127    pub(super) fn test_builder_const_int() {
128        let mut b = MlirBuilder::new();
129        let v = b.const_int(42, 64);
130        assert_eq!(v.name, "0");
131        assert!(matches!(v.ty, MlirType::Integer(64, false)));
132        let ops = b.take_ops();
133        assert_eq!(ops.len(), 1);
134        assert_eq!(ops[0].op_name, "arith.constant");
135    }
136    #[test]
137    pub(super) fn test_builder_const_float() {
138        let mut b = MlirBuilder::new();
139        let v = b.const_float(3.14, 64);
140        assert!(matches!(v.ty, MlirType::Float(64)));
141        let ops = b.take_ops();
142        assert_eq!(ops[0].op_name, "arith.constant");
143    }
144    #[test]
145    pub(super) fn test_builder_addi() {
146        let mut b = MlirBuilder::new();
147        let lhs = MlirValue::named("x", MlirType::Integer(64, false));
148        let rhs = MlirValue::named("y", MlirType::Integer(64, false));
149        let result = b.addi(lhs, rhs);
150        assert!(matches!(result.ty, MlirType::Integer(64, false)));
151        let ops = b.take_ops();
152        assert_eq!(ops[0].op_name, "arith.addi");
153    }
154    #[test]
155    pub(super) fn test_builder_muli() {
156        let mut b = MlirBuilder::new();
157        let lhs = MlirValue::named("a", MlirType::Integer(32, false));
158        let rhs = MlirValue::named("b", MlirType::Integer(32, false));
159        let _ = b.muli(lhs, rhs);
160        let ops = b.take_ops();
161        assert_eq!(ops[0].op_name, "arith.muli");
162    }
163    #[test]
164    pub(super) fn test_builder_cmpi() {
165        let mut b = MlirBuilder::new();
166        let lhs = MlirValue::named("a", MlirType::Integer(64, false));
167        let rhs = MlirValue::named("b", MlirType::Integer(64, false));
168        let result = b.cmpi(CmpiPred::Slt, lhs, rhs);
169        assert!(matches!(result.ty, MlirType::Integer(1, false)));
170        let ops = b.take_ops();
171        assert_eq!(ops[0].op_name, "arith.cmpi");
172    }
173    #[test]
174    pub(super) fn test_builder_math_sin() {
175        let mut b = MlirBuilder::new();
176        let v = MlirValue::named("x", MlirType::Float(64));
177        let _ = b.sin(v);
178        let ops = b.take_ops();
179        assert_eq!(ops[0].op_name, "math.sin");
180    }
181    #[test]
182    pub(super) fn test_builder_return_op() {
183        let mut b = MlirBuilder::new();
184        let v = MlirValue::named("result", MlirType::Integer(64, false));
185        b.return_op(vec![v]);
186        let ops = b.take_ops();
187        assert_eq!(ops[0].op_name, "func.return");
188    }
189    #[test]
190    pub(super) fn test_builder_call() {
191        let mut b = MlirBuilder::new();
192        let arg = MlirValue::named("x", MlirType::Integer(64, false));
193        let results = b.call("foo", vec![arg], vec![MlirType::Integer(64, false)]);
194        assert_eq!(results.len(), 1);
195        let ops = b.take_ops();
196        assert_eq!(ops[0].op_name, "func.call");
197    }
198    #[test]
199    pub(super) fn test_module_emit_empty() {
200        let module = MlirModule::new();
201        let output = module.emit();
202        assert!(output.starts_with("module {"));
203        assert!(output.ends_with("}\n"));
204    }
205    #[test]
206    pub(super) fn test_module_emit_named() {
207        let module = MlirModule::named("my_module");
208        let output = module.emit();
209        assert!(output.starts_with("module @my_module {"));
210    }
211    #[test]
212    pub(super) fn test_module_emit_func() {
213        let mut module = MlirModule::new();
214        let int_ty = MlirType::Integer(64, false);
215        let mut builder = MlirBuilder::new();
216        let arg0 = MlirValue::named("arg0", int_ty.clone());
217        let arg1 = MlirValue::named("arg1", int_ty.clone());
218        let sum = builder.addi(arg0.clone(), arg1.clone());
219        builder.return_op(vec![sum]);
220        let block = MlirBlock::entry(vec![arg0, arg1], builder.take_ops());
221        let func = MlirFunc::new(
222            "add",
223            vec![
224                ("arg0".to_string(), int_ty.clone()),
225                ("arg1".to_string(), int_ty.clone()),
226            ],
227            vec![int_ty],
228            MlirRegion::single_block(block),
229        );
230        module.add_function(func);
231        let output = module.emit();
232        assert!(output.contains("func.func @add"));
233        assert!(output.contains("arith.addi"));
234        assert!(output.contains("func.return"));
235    }
236    #[test]
237    pub(super) fn test_backend_compile_add_func() {
238        let mut backend = MlirBackend::new();
239        backend.compile_add_func("add64", 64);
240        let output = backend.emit_module();
241        assert!(output.contains("module {"));
242        assert!(output.contains("func.func"));
243    }
244    #[test]
245    pub(super) fn test_backend_run_passes_empty() {
246        let backend = MlirBackend::new();
247        assert_eq!(backend.run_passes(), "");
248    }
249    #[test]
250    pub(super) fn test_backend_run_passes_nonempty() {
251        let mut backend = MlirBackend::new();
252        backend.add_pass("convert-arith-to-llvm");
253        backend.add_pass("convert-func-to-llvm");
254        let passes = backend.run_passes();
255        assert!(passes.contains("mlir-opt"));
256        assert!(passes.contains("convert-arith-to-llvm"));
257    }
258    #[test]
259    pub(super) fn test_mlir_global_emit() {
260        let global = MlirGlobal::constant("pi", MlirType::Float(64), MlirAttr::Float(3.14159));
261        let output = global.emit();
262        assert!(output.contains("@pi"));
263        assert!(output.contains("constant"));
264    }
265    #[test]
266    pub(super) fn test_ssa_counter_sequential() {
267        let mut counter = SsaCounter::new();
268        let v0 = counter.next(MlirType::Integer(64, false));
269        let v1 = counter.next(MlirType::Integer(64, false));
270        assert_eq!(v0.name, "0");
271        assert_eq!(v1.name, "1");
272    }
273    #[test]
274    pub(super) fn test_ssa_counter_reset() {
275        let mut counter = SsaCounter::new();
276        let _ = counter.next(MlirType::Integer(32, false));
277        counter.reset();
278        let v = counter.next(MlirType::Integer(32, false));
279        assert_eq!(v.name, "0");
280    }
281    #[test]
282    pub(super) fn test_dialect_display() {
283        assert_eq!(MlirDialect::Arith.to_string(), "arith");
284        assert_eq!(MlirDialect::Func.to_string(), "func");
285        assert_eq!(MlirDialect::SCF.to_string(), "scf");
286        assert_eq!(MlirDialect::GPU.to_string(), "gpu");
287        assert_eq!(MlirDialect::Linalg.to_string(), "linalg");
288    }
289    #[test]
290    pub(super) fn test_cmpi_pred_display() {
291        assert_eq!(CmpiPred::Eq.to_string(), "eq");
292        assert_eq!(CmpiPred::Slt.to_string(), "slt");
293        assert_eq!(CmpiPred::Uge.to_string(), "uge");
294    }
295    #[test]
296    pub(super) fn test_cmpf_pred_display() {
297        assert_eq!(CmpfPred::Oeq.to_string(), "oeq");
298        assert_eq!(CmpfPred::Une.to_string(), "une");
299    }
300    #[test]
301    pub(super) fn test_builder_extsi() {
302        let mut b = MlirBuilder::new();
303        let v = MlirValue::named("small", MlirType::Integer(32, false));
304        let result = b.extsi(v, 64);
305        assert!(matches!(result.ty, MlirType::Integer(64, false)));
306        let ops = b.take_ops();
307        assert_eq!(ops[0].op_name, "arith.extsi");
308    }
309    #[test]
310    pub(super) fn test_builder_trunci() {
311        let mut b = MlirBuilder::new();
312        let v = MlirValue::named("big", MlirType::Integer(64, false));
313        let result = b.trunci(v, 32);
314        assert!(matches!(result.ty, MlirType::Integer(32, false)));
315        let ops = b.take_ops();
316        assert_eq!(ops[0].op_name, "arith.trunci");
317    }
318    #[test]
319    pub(super) fn test_backend_compile_decl() {
320        let mut backend = MlirBackend::new();
321        backend.compile_decl(
322            "my_func",
323            vec![MlirType::Integer(64, false)],
324            MlirType::Integer(64, false),
325        );
326        let output = backend.emit_module();
327        assert!(output.contains("my_func"));
328    }
329    #[test]
330    pub(super) fn test_affine_map_identity() {
331        let am = AffineMap::Identity(2);
332        let s = am.to_string();
333        assert!(s.contains("affine_map"));
334        assert!(s.contains("d0"));
335        assert!(s.contains("d1"));
336    }
337    #[test]
338    pub(super) fn test_mlir_block_labeled() {
339        let block = MlirBlock::labeled("bb1", vec![], vec![]);
340        let s = format!("{}", block);
341        assert!(s.contains("^bb1"));
342    }
343    #[test]
344    pub(super) fn test_mlir_func_declaration() {
345        let decl = MlirFunc::declaration(
346            "extern_func",
347            vec![MlirType::Integer(32, false)],
348            vec![MlirType::Integer(32, false)],
349        );
350        let output = decl.emit();
351        assert!(output.contains("extern_func"));
352        assert!(output.contains("private"));
353    }
354    #[test]
355    pub(super) fn test_builder_math_ops() {
356        let mut b = MlirBuilder::new();
357        let v = MlirValue::named("x", MlirType::Float(32));
358        let _ = b.cos(v.clone());
359        let _ = b.exp(v.clone());
360        let _ = b.log(v.clone());
361        let _ = b.sqrt(v);
362        let ops = b.take_ops();
363        assert_eq!(ops[0].op_name, "math.cos");
364        assert_eq!(ops[1].op_name, "math.exp");
365        assert_eq!(ops[2].op_name, "math.log");
366        assert_eq!(ops[3].op_name, "math.sqrt");
367    }
368    #[test]
369    pub(super) fn test_unranked_memref() {
370        let ty = MlirType::UnrankedMemRef(Box::new(MlirType::Float(32)));
371        assert_eq!(ty.to_string(), "memref<*xf32>");
372    }
373    #[test]
374    pub(super) fn test_complex_type() {
375        let ty = MlirType::Complex(Box::new(MlirType::Float(32)));
376        assert_eq!(ty.to_string(), "complex<f32>");
377    }
378}
379#[cfg(test)]
380mod MLIR_infra_tests {
381    use super::*;
382    #[test]
383    pub(super) fn test_pass_config() {
384        let config = MLIRPassConfig::new("test_pass", MLIRPassPhase::Transformation);
385        assert!(config.enabled);
386        assert!(config.phase.is_modifying());
387        assert_eq!(config.phase.name(), "transformation");
388    }
389    #[test]
390    pub(super) fn test_pass_stats() {
391        let mut stats = MLIRPassStats::new();
392        stats.record_run(10, 100, 3);
393        stats.record_run(20, 200, 5);
394        assert_eq!(stats.total_runs, 2);
395        assert!((stats.average_changes_per_run() - 15.0).abs() < 0.01);
396        assert!((stats.success_rate() - 1.0).abs() < 0.01);
397        let s = stats.format_summary();
398        assert!(s.contains("Runs: 2/2"));
399    }
400    #[test]
401    pub(super) fn test_pass_registry() {
402        let mut reg = MLIRPassRegistry::new();
403        reg.register(MLIRPassConfig::new("pass_a", MLIRPassPhase::Analysis));
404        reg.register(MLIRPassConfig::new("pass_b", MLIRPassPhase::Transformation).disabled());
405        assert_eq!(reg.total_passes(), 2);
406        assert_eq!(reg.enabled_count(), 1);
407        reg.update_stats("pass_a", 5, 50, 2);
408        let stats = reg.get_stats("pass_a").expect("stats should exist");
409        assert_eq!(stats.total_changes, 5);
410    }
411    #[test]
412    pub(super) fn test_analysis_cache() {
413        let mut cache = MLIRAnalysisCache::new(10);
414        cache.insert("key1".to_string(), vec![1, 2, 3]);
415        assert!(cache.get("key1").is_some());
416        assert!(cache.get("key2").is_none());
417        assert!((cache.hit_rate() - 0.5).abs() < 0.01);
418        cache.invalidate("key1");
419        assert!(!cache.entries["key1"].valid);
420        assert_eq!(cache.size(), 1);
421    }
422    #[test]
423    pub(super) fn test_worklist() {
424        let mut wl = MLIRWorklist::new();
425        assert!(wl.push(1));
426        assert!(wl.push(2));
427        assert!(!wl.push(1));
428        assert_eq!(wl.len(), 2);
429        assert_eq!(wl.pop(), Some(1));
430        assert!(!wl.contains(1));
431        assert!(wl.contains(2));
432    }
433    #[test]
434    pub(super) fn test_dominator_tree() {
435        let mut dt = MLIRDominatorTree::new(5);
436        dt.set_idom(1, 0);
437        dt.set_idom(2, 0);
438        dt.set_idom(3, 1);
439        assert!(dt.dominates(0, 3));
440        assert!(dt.dominates(1, 3));
441        assert!(!dt.dominates(2, 3));
442        assert!(dt.dominates(3, 3));
443    }
444    #[test]
445    pub(super) fn test_liveness() {
446        let mut liveness = MLIRLivenessInfo::new(3);
447        liveness.add_def(0, 1);
448        liveness.add_use(1, 1);
449        assert!(liveness.defs[0].contains(&1));
450        assert!(liveness.uses[1].contains(&1));
451    }
452    #[test]
453    pub(super) fn test_constant_folding() {
454        assert_eq!(MLIRConstantFoldingHelper::fold_add_i64(3, 4), Some(7));
455        assert_eq!(MLIRConstantFoldingHelper::fold_div_i64(10, 0), None);
456        assert_eq!(MLIRConstantFoldingHelper::fold_div_i64(10, 2), Some(5));
457        assert_eq!(
458            MLIRConstantFoldingHelper::fold_bitand_i64(0b1100, 0b1010),
459            0b1000
460        );
461        assert_eq!(MLIRConstantFoldingHelper::fold_bitnot_i64(0), -1);
462    }
463    #[test]
464    pub(super) fn test_dep_graph() {
465        let mut g = MLIRDepGraph::new();
466        g.add_dep(1, 2);
467        g.add_dep(2, 3);
468        g.add_dep(1, 3);
469        assert_eq!(g.dependencies_of(2), vec![1]);
470        let topo = g.topological_sort();
471        assert_eq!(topo.len(), 3);
472        assert!(!g.has_cycle());
473        let pos: std::collections::HashMap<u32, usize> =
474            topo.iter().enumerate().map(|(i, &n)| (n, i)).collect();
475        assert!(pos[&1] < pos[&2]);
476        assert!(pos[&1] < pos[&3]);
477        assert!(pos[&2] < pos[&3]);
478    }
479}
480#[cfg(test)]
481mod mlirext_pass_tests {
482    use super::*;
483    #[test]
484    pub(super) fn test_mlirext_phase_order() {
485        assert_eq!(MLIRExtPassPhase::Early.order(), 0);
486        assert_eq!(MLIRExtPassPhase::Middle.order(), 1);
487        assert_eq!(MLIRExtPassPhase::Late.order(), 2);
488        assert_eq!(MLIRExtPassPhase::Finalize.order(), 3);
489        assert!(MLIRExtPassPhase::Early.is_early());
490        assert!(!MLIRExtPassPhase::Early.is_late());
491    }
492    #[test]
493    pub(super) fn test_mlirext_config_builder() {
494        let c = MLIRExtPassConfig::new("p")
495            .with_phase(MLIRExtPassPhase::Late)
496            .with_max_iter(50)
497            .with_debug(1);
498        assert_eq!(c.name, "p");
499        assert_eq!(c.max_iterations, 50);
500        assert!(c.is_debug_enabled());
501        assert!(c.enabled);
502        let c2 = c.disabled();
503        assert!(!c2.enabled);
504    }
505    #[test]
506    pub(super) fn test_mlirext_stats() {
507        let mut s = MLIRExtPassStats::new();
508        s.visit();
509        s.visit();
510        s.modify();
511        s.iterate();
512        assert_eq!(s.nodes_visited, 2);
513        assert_eq!(s.nodes_modified, 1);
514        assert!(s.changed);
515        assert_eq!(s.iterations, 1);
516        let e = s.efficiency();
517        assert!((e - 0.5).abs() < 1e-9);
518    }
519    #[test]
520    pub(super) fn test_mlirext_registry() {
521        let mut r = MLIRExtPassRegistry::new();
522        r.register(MLIRExtPassConfig::new("a").with_phase(MLIRExtPassPhase::Early));
523        r.register(MLIRExtPassConfig::new("b").disabled());
524        assert_eq!(r.len(), 2);
525        assert_eq!(r.enabled_passes().len(), 1);
526        assert_eq!(r.passes_in_phase(&MLIRExtPassPhase::Early).len(), 1);
527    }
528    #[test]
529    pub(super) fn test_mlirext_cache() {
530        let mut c = MLIRExtCache::new(4);
531        assert!(c.get(99).is_none());
532        c.put(99, vec![1, 2, 3]);
533        let v = c.get(99).expect("v should be present in map");
534        assert_eq!(v, &[1u8, 2, 3]);
535        assert!(c.hit_rate() > 0.0);
536        assert_eq!(c.live_count(), 1);
537    }
538    #[test]
539    pub(super) fn test_mlirext_worklist() {
540        let mut w = MLIRExtWorklist::new(10);
541        w.push(5);
542        w.push(3);
543        w.push(5);
544        assert_eq!(w.len(), 2);
545        assert!(w.contains(5));
546        let first = w.pop().expect("first should be available to pop");
547        assert!(!w.contains(first));
548    }
549    #[test]
550    pub(super) fn test_mlirext_dom_tree() {
551        let mut dt = MLIRExtDomTree::new(5);
552        dt.set_idom(1, 0);
553        dt.set_idom(2, 0);
554        dt.set_idom(3, 1);
555        dt.set_idom(4, 1);
556        assert!(dt.dominates(0, 3));
557        assert!(dt.dominates(1, 4));
558        assert!(!dt.dominates(2, 3));
559        assert_eq!(dt.depth_of(3), 2);
560    }
561    #[test]
562    pub(super) fn test_mlirext_liveness() {
563        let mut lv = MLIRExtLiveness::new(3);
564        lv.add_def(0, 1);
565        lv.add_use(1, 1);
566        assert!(lv.var_is_def_in_block(0, 1));
567        assert!(lv.var_is_used_in_block(1, 1));
568        assert!(!lv.var_is_def_in_block(1, 1));
569    }
570    #[test]
571    pub(super) fn test_mlirext_const_folder() {
572        let mut cf = MLIRExtConstFolder::new();
573        assert_eq!(cf.add_i64(3, 4), Some(7));
574        assert_eq!(cf.div_i64(10, 0), None);
575        assert_eq!(cf.mul_i64(6, 7), Some(42));
576        assert_eq!(cf.and_i64(0b1100, 0b1010), 0b1000);
577        assert_eq!(cf.fold_count(), 3);
578        assert_eq!(cf.failure_count(), 1);
579    }
580    #[test]
581    pub(super) fn test_mlirext_dep_graph() {
582        let mut g = MLIRExtDepGraph::new(4);
583        g.add_edge(0, 1);
584        g.add_edge(1, 2);
585        g.add_edge(2, 3);
586        assert!(!g.has_cycle());
587        assert_eq!(g.topo_sort(), Some(vec![0, 1, 2, 3]));
588        assert_eq!(g.reachable(0).len(), 4);
589        let sccs = g.scc();
590        assert_eq!(sccs.len(), 4);
591    }
592}