diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 6df29d6fd1..c7654713ea 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -225,7 +225,7 @@ instruction that produces the verifier error*. Both the error message and reported location of the error is verified:: test verifier - + function %test(i32) { ebb0(v0: i32): jump ebb1 ; error: terminator @@ -249,20 +249,20 @@ command:: ; For testing cfg generation. This code is nonsense. test print-cfg test verifier - + function %nonsense(i32, i32) -> f32 { ; check: digraph %nonsense { ; regex: I=\binst\d+\b ; check: label="{ebb0 | <$(BRZ=$I)>brz ebb2 | <$(JUMP=$I)>jump ebb1}"] - + ebb0(v1: i32, v2: i32): brz v2, ebb2 ; unordered: ebb0:$BRZ -> ebb2 v4 = iconst.i32 0 jump ebb1(v4) ; unordered: ebb0:$JUMP -> ebb1 - + ebb1(v5: i32): return v1 - + ebb2: v100 = f32const 0.0 return v100 @@ -275,7 +275,7 @@ Compute the dominator tree of each function and validate it against the ``dominates:`` annotations:: test domtree - + function %test(i32) { ebb0(v0: i32): jump ebb1 ; dominates: ebb1 @@ -293,6 +293,8 @@ Every reachable extended basic block except for the entry block has an if the ``dominates:`` annotations on the immediate dominator instructions are both correct and complete. +This test also sends the computed CFG post-order through filecheck. + `test legalizer` ---------------- diff --git a/cranelift/filetests/cfg/loop.cton b/cranelift/filetests/cfg/loop.cton index 06aa848c7f..728240940f 100644 --- a/cranelift/filetests/cfg/loop.cton +++ b/cranelift/filetests/cfg/loop.cton @@ -3,7 +3,7 @@ test print-cfg test verifier function %nonsense(i32, i32) -> f32 { -; check: digraph %nonsense { +; check: digraph "%nonsense" { ; regex: I=\binst\d+\b ; check: label="{ebb0 | <$(BRZ=$I)>brz ebb2 | <$(JUMP=$I)>jump ebb1}"] diff --git a/cranelift/filetests/cfg/traps_early.cton b/cranelift/filetests/cfg/traps_early.cton index e12c3c65ee..36f3016d5c 100644 --- a/cranelift/filetests/cfg/traps_early.cton +++ b/cranelift/filetests/cfg/traps_early.cton @@ -4,7 +4,7 @@ test print-cfg test verifier function %nonsense(i32) { -; check: digraph %nonsense { +; check: digraph "%nonsense" { ebb0(v1: i32): trap user0 ; error: terminator instruction was encountered before the end diff --git a/cranelift/filetests/cfg/unused_node.cton b/cranelift/filetests/cfg/unused_node.cton index d339e5ea83..80f2402c07 100644 --- a/cranelift/filetests/cfg/unused_node.cton +++ b/cranelift/filetests/cfg/unused_node.cton @@ -2,7 +2,7 @@ test print-cfg function %not_reached(i32) -> i32 { -; check: digraph %not_reached { +; check: digraph "%not_reached" { ; check: ebb0 [shape=record, label="{ebb0 | brnz ebb2}"] ; check: ebb1 [shape=record, label="{ebb1 | jump ebb0}"] ; check: ebb2 [shape=record, label="{ebb2}"] diff --git a/cranelift/filetests/domtree/basic.cton b/cranelift/filetests/domtree/basic.cton index e46c73e67e..94f6d88cdb 100644 --- a/cranelift/filetests/domtree/basic.cton +++ b/cranelift/filetests/domtree/basic.cton @@ -11,3 +11,8 @@ function %test(i32) { ebb3: return } +; check: cfg_postorder: +; sameln: ebb2 +; sameln: ebb3 +; sameln: ebb1 +; sameln: ebb0 diff --git a/cranelift/filetests/domtree/loops.cton b/cranelift/filetests/domtree/loops.cton index 43ad1e1c08..fd659ed421 100644 --- a/cranelift/filetests/domtree/loops.cton +++ b/cranelift/filetests/domtree/loops.cton @@ -18,3 +18,67 @@ function %test(i32) { brz v0, ebb4 return } +; Fall-through-first, prune-at-source DFT: +; +; ebb0 { +; ebb0:brz v0, ebb1 { +; ebb0:jump ebb2 { +; ebb2 { +; ebb2:brz v2, ebb2 - +; ebb2:brz v3, ebb1 - +; ebb2:brz v4, ebb4 { +; ebb2: jump ebb5 { +; ebb5 {} +; } +; ebb4 {} +; } +; } ebb2 +; } +; ebb1 { +; ebb1:jump ebb3 { +; ebb3 {} +; } +; } ebb1 +; } +; } ebb0 +; +; check: cfg_postorder: +; sameln: ebb5 +; sameln: ebb3 +; sameln: ebb4 +; sameln: ebb2 +; sameln: ebb1 +; sameln: ebb0 + +function %loop2(i32) native { + ebb0(v0: i32): + brz v0, ebb1 ; dominates: ebb1 ebb3 ebb4 ebb5 + jump ebb2 ; dominates: ebb2 + ebb1: + jump ebb3 + ebb2: + brz v0, ebb4 + jump ebb5 + ebb3: + jump ebb4 + ebb4: + brz v0, ebb3 + brnz v0, ebb5 + jump ebb6 ; dominates: ebb6 + ebb5: + brz v0, ebb4 + trap user0 + ebb6: + jump ebb7 ; dominates: ebb7 + ebb7: + return +} +; check: cfg_postorder: +; sameln: ebb5 +; sameln: ebb7 +; sameln: ebb6 +; sameln: ebb3 +; sameln: ebb4 +; sameln: ebb2 +; sameln: ebb1 +; sameln: ebb0 diff --git a/cranelift/filetests/domtree/loops2.cton b/cranelift/filetests/domtree/loops2.cton index eeac8343bd..59d98119bd 100644 --- a/cranelift/filetests/domtree/loops2.cton +++ b/cranelift/filetests/domtree/loops2.cton @@ -29,3 +29,29 @@ function %test(i32) { ebb9: return } + +function %test(i32) native { + ebb0(v0: i32): + brz v0, ebb1 ; dominates: ebb1 ebb3 ebb4 ebb5 + jump ebb2 ; dominates: ebb2 + ebb1: + jump ebb3 + ebb2: + brz v0, ebb4 + jump ebb5 + ebb3: + jump ebb4 + ebb4: + brz v0, ebb3 + jump ebb5 + ebb5: + brz v0, ebb4 + return +} +; check: cfg_postorder: +; sameln: ebb5 +; sameln: ebb3 +; sameln: ebb4 +; sameln: ebb2 +; sameln: ebb1 +; sameln: ebb0 diff --git a/cranelift/src/filetest/domtree.rs b/cranelift/src/filetest/domtree.rs index 1063429b17..97fd97bc9a 100644 --- a/cranelift/src/filetest/domtree.rs +++ b/cranelift/src/filetest/domtree.rs @@ -15,9 +15,11 @@ use cretonne::flowgraph::ControlFlowGraph; use cretonne::ir::Function; use cretonne::ir::entities::AnyEntity; use cton_reader::TestCommand; -use filetest::subtest::{SubTest, Context, Result}; +use filetest::subtest::{SubTest, Context, Result, run_filecheck}; use std::borrow::{Borrow, Cow}; use std::collections::HashMap; +use std::fmt::{self, Write}; +use std::result; use utils::match_directive; struct TestDomtree; @@ -108,6 +110,20 @@ impl SubTest for TestDomtree { } } - Ok(()) + let text = filecheck_text(&domtree).expect("formatting error"); + run_filecheck(&text, context) } } + +// Generate some output for filecheck testing +fn filecheck_text(domtree: &DominatorTree) -> result::Result { + let mut s = String::new(); + + write!(s, "cfg_postorder:")?; + for &ebb in domtree.cfg_postorder() { + write!(s, " {}", ebb)?; + } + writeln!(s, "")?; + + Ok(s) +} diff --git a/cranelift/src/print_cfg.rs b/cranelift/src/print_cfg.rs index 8d2b06c8f1..f3b958be77 100644 --- a/cranelift/src/print_cfg.rs +++ b/cranelift/src/print_cfg.rs @@ -46,7 +46,7 @@ impl<'a> CFGPrinter<'a> { } fn header(&self, w: &mut Write) -> Result { - writeln!(w, "digraph {} {{", self.func.name)?; + writeln!(w, "digraph \"{}\" {{", self.func.name)?; if let Some(entry) = self.func.layout.entry_block() { writeln!(w, " {{rank=min; {}}}", entry)?; } diff --git a/cranelift/tests/cfg_traversal.rs b/cranelift/tests/cfg_traversal.rs deleted file mode 100644 index 6709da2e9a..0000000000 --- a/cranelift/tests/cfg_traversal.rs +++ /dev/null @@ -1,228 +0,0 @@ -extern crate cretonne; -extern crate cton_reader; - -use self::cretonne::flowgraph::ControlFlowGraph; -use self::cretonne::dominator_tree::DominatorTree; -use self::cretonne::ir::Ebb; -use self::cton_reader::parse_functions; - -fn test_reverse_postorder_traversal(function_source: &str, ebb_order: Vec) { - let func = &parse_functions(function_source).unwrap()[0]; - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - - let got = domtree - .cfg_postorder() - .iter() - .rev() - .cloned() - .collect::>(); - let want = ebb_order - .iter() - .map(|&n| Ebb::with_number(n).unwrap()) - .collect::>(); - assert_eq!(got, want); -} - -#[test] -fn simple_traversal() { - // Fall-through-first, prune-at-source DFT: - // - // ebb0 { - // ebb0:brz v0, ebb1 { - // ebb0:jump ebb2 { - // ebb2 { - // ebb2:brz v2, ebb2 - - // ebb2:brz v3, ebb1 - - // ebb2:brz v4, ebb4 { - // ebb2: jump ebb5 { - // ebb5 {} - // } - // ebb4 {} - // } - // } ebb2 - // } - // ebb1 { - // ebb1:jump ebb3 { - // ebb3 {} - // } - // } ebb1 - // } - // } ebb0 - - test_reverse_postorder_traversal( - " - function %test(i32) native { - ebb0(v0: i32): - brz v0, ebb1 - jump ebb2 - ebb1: - jump ebb3 - ebb2: - v1 = iconst.i32 1 - v2 = iadd v1, v0 - brz v2, ebb2 - v3 = iadd v1, v2 - brz v3, ebb1 - v4 = iadd v1, v3 - brz v4, ebb4 - jump ebb5 - ebb3: - trap user0 - ebb4: - trap user0 - ebb5: - trap user0 - } - ", - vec![0, 1, 3, 2, 4, 5], - ); -} - -#[test] -fn loops_one() { - // Fall-through-first, prune-at-source DFT: - // ebb0 { - // ebb0:jump ebb1 { - // ebb1 { - // ebb1:brnz v0, ebb3 { - // ebb1:jump ebb2 { - // ebb2 { - // ebb2:jump ebb3 - - // } ebb2 - // } - // ebb3 {} - // } - // } ebb1 - // } - // } ebb0 - - test_reverse_postorder_traversal( - " - function %test(i32) native { - ebb0(v0: i32): - jump ebb1 - ebb1: - brnz v0, ebb3 - jump ebb2 - ebb2: - jump ebb3 - ebb3: - return - } - ", - vec![0, 1, 3, 2], - ); -} - -#[test] -fn loops_two() { - // Fall-through-first, prune-at-source DFT: - // ebb0 { - // ebb0:brz v0, ebb1 { - // ebb0:jump ebb2 { - // ebb2 { - // ebb2:brz v0, ebb4 { - // ebb2:jump ebb5 { - // ebb5 { - // brz v0, ebb4 - - // } ebb5 - // } - // ebb4 { - // ebb4:brz v0, ebb3 { - // ebb4:jump ebb5 - - // ebb3 { - // ebb3:jump ebb4 - - // } ebb3 - // } - // } ebb4 - // } - // } ebb2 - // } - // ebb1 { - // ebb1:jump ebb3 - - // } ebb1 - // } - // } ebb0 - - test_reverse_postorder_traversal( - " - function %test(i32) native { - ebb0(v0: i32): - brz v0, ebb1 - jump ebb2 - ebb1: - jump ebb3 - ebb2: - brz v0, ebb4 - jump ebb5 - ebb3: - jump ebb4 - ebb4: - brz v0, ebb3 - jump ebb5 - ebb5: - brz v0, ebb4 - return - } - ", - vec![0, 1, 2, 4, 3, 5], - ); -} - -#[test] -fn loops_three() { - test_reverse_postorder_traversal( - " - function %test(i32) native { - ebb0(v0: i32): - brz v0, ebb1 - jump ebb2 - ebb1: - jump ebb3 - ebb2: - brz v0, ebb4 - jump ebb5 - ebb3: - jump ebb4 - ebb4: - brz v0, ebb3 - brnz v0, ebb5 - jump ebb6 - ebb5: - brz v0, ebb4 - trap user0 - ebb6: - jump ebb7 - ebb7: - return - } - ", - vec![0, 1, 2, 4, 3, 6, 7, 5], - ); -} - -#[test] -fn back_edge_one() { - test_reverse_postorder_traversal( - " - function %test(i32) native { - ebb0(v0: i32): - brz v0, ebb1 - jump ebb2 - ebb1: - jump ebb3 - ebb2: - brz v0, ebb0 - jump ebb4 - ebb3: - brz v0, ebb2 - brnz v0, ebb0 - return - ebb4: - trap user0 - } - ", - vec![0, 1, 3, 2, 4], - ); -}