Convert the CFG traversal tests to file tests.
Add a "cfg_postorder:" printout to the "test domtree" file tests and use that to check the computed CFG post-order instead of doing it manually with Rust code.
This commit is contained in:
@@ -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
|
if the ``dominates:`` annotations on the immediate dominator instructions are
|
||||||
both correct and complete.
|
both correct and complete.
|
||||||
|
|
||||||
|
This test also sends the computed CFG post-order through filecheck.
|
||||||
|
|
||||||
`test legalizer`
|
`test legalizer`
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ test print-cfg
|
|||||||
test verifier
|
test verifier
|
||||||
|
|
||||||
function %nonsense(i32, i32) -> f32 {
|
function %nonsense(i32, i32) -> f32 {
|
||||||
; check: digraph %nonsense {
|
; check: digraph "%nonsense" {
|
||||||
; regex: I=\binst\d+\b
|
; regex: I=\binst\d+\b
|
||||||
; check: label="{ebb0 | <$(BRZ=$I)>brz ebb2 | <$(JUMP=$I)>jump ebb1}"]
|
; check: label="{ebb0 | <$(BRZ=$I)>brz ebb2 | <$(JUMP=$I)>jump ebb1}"]
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ test print-cfg
|
|||||||
test verifier
|
test verifier
|
||||||
|
|
||||||
function %nonsense(i32) {
|
function %nonsense(i32) {
|
||||||
; check: digraph %nonsense {
|
; check: digraph "%nonsense" {
|
||||||
|
|
||||||
ebb0(v1: i32):
|
ebb0(v1: i32):
|
||||||
trap user0 ; error: terminator instruction was encountered before the end
|
trap user0 ; error: terminator instruction was encountered before the end
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
test print-cfg
|
test print-cfg
|
||||||
|
|
||||||
function %not_reached(i32) -> i32 {
|
function %not_reached(i32) -> i32 {
|
||||||
; check: digraph %not_reached {
|
; check: digraph "%not_reached" {
|
||||||
; check: ebb0 [shape=record, label="{ebb0 | <inst0>brnz ebb2}"]
|
; check: ebb0 [shape=record, label="{ebb0 | <inst0>brnz ebb2}"]
|
||||||
; check: ebb1 [shape=record, label="{ebb1 | <inst4>jump ebb0}"]
|
; check: ebb1 [shape=record, label="{ebb1 | <inst4>jump ebb0}"]
|
||||||
; check: ebb2 [shape=record, label="{ebb2}"]
|
; check: ebb2 [shape=record, label="{ebb2}"]
|
||||||
|
|||||||
@@ -11,3 +11,8 @@ function %test(i32) {
|
|||||||
ebb3:
|
ebb3:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
; check: cfg_postorder:
|
||||||
|
; sameln: ebb2
|
||||||
|
; sameln: ebb3
|
||||||
|
; sameln: ebb1
|
||||||
|
; sameln: ebb0
|
||||||
|
|||||||
@@ -18,3 +18,67 @@ function %test(i32) {
|
|||||||
brz v0, ebb4
|
brz v0, ebb4
|
||||||
return
|
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
|
||||||
|
|||||||
@@ -29,3 +29,29 @@ function %test(i32) {
|
|||||||
ebb9:
|
ebb9:
|
||||||
return
|
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
|
||||||
|
|||||||
@@ -15,9 +15,11 @@ use cretonne::flowgraph::ControlFlowGraph;
|
|||||||
use cretonne::ir::Function;
|
use cretonne::ir::Function;
|
||||||
use cretonne::ir::entities::AnyEntity;
|
use cretonne::ir::entities::AnyEntity;
|
||||||
use cton_reader::TestCommand;
|
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::borrow::{Borrow, Cow};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::{self, Write};
|
||||||
|
use std::result;
|
||||||
use utils::match_directive;
|
use utils::match_directive;
|
||||||
|
|
||||||
struct TestDomtree;
|
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<String, fmt::Error> {
|
||||||
|
let mut s = String::new();
|
||||||
|
|
||||||
|
write!(s, "cfg_postorder:")?;
|
||||||
|
for &ebb in domtree.cfg_postorder() {
|
||||||
|
write!(s, " {}", ebb)?;
|
||||||
|
}
|
||||||
|
writeln!(s, "")?;
|
||||||
|
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ impl<'a> CFGPrinter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn header(&self, w: &mut Write) -> Result {
|
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() {
|
if let Some(entry) = self.func.layout.entry_block() {
|
||||||
writeln!(w, " {{rank=min; {}}}", entry)?;
|
writeln!(w, " {{rank=min; {}}}", entry)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<u32>) {
|
|
||||||
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::<Vec<_>>();
|
|
||||||
let want = ebb_order
|
|
||||||
.iter()
|
|
||||||
.map(|&n| Ebb::with_number(n).unwrap())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
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],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user