From 4ba5cfeed3cfe447106c7c2f0f934cda25a9c9bf Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 17 Feb 2017 17:07:08 -0800 Subject: [PATCH] Add a 'regalloc' filetest command. Run functions through the register allocator, and then filecheck. --- docs/testing.rst | 14 +++++++++ filetests/regalloc/basic.cton | 12 ++++++++ src/filetest/mod.rs | 11 ++++--- src/filetest/regalloc.rs | 55 +++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 filetests/regalloc/basic.cton create mode 100644 src/filetest/regalloc.rs diff --git a/docs/testing.rst b/docs/testing.rst index a452dc1b58..db027f8fbe 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -300,3 +300,17 @@ Legalize each function for the specified target ISA and run the resulting function through filecheck. This test command can be used to validate the encodings selected for legal instructions as well as the instruction transformations performed by the legalizer. + +`test regalloc` +--------------- + +Test the register allocator. + +First, each function is legalized for the specified target ISA. This is +required for register allocation since the instruction encodings provide +register class constraints to the register allocator. + +Second, the register allocator is run on the function, inserting spill code and +assigning registers and stack slots to all values. + +The resulting function is then run through filecheck. diff --git a/filetests/regalloc/basic.cton b/filetests/regalloc/basic.cton new file mode 100644 index 0000000000..00e204f9b1 --- /dev/null +++ b/filetests/regalloc/basic.cton @@ -0,0 +1,12 @@ +test regalloc + +; We can add more ISAs once they have defined encodings. +isa riscv + +function add(i32, i32) { +ebb0(v1: i32, v2: i32): + v3 = iadd v1, v2 +; check: [R#0c,%x0] +; sameln: iadd + return_reg v3 +} diff --git a/src/filetest/mod.rs b/src/filetest/mod.rs index 28a9b94d45..41b89948a1 100644 --- a/src/filetest/mod.rs +++ b/src/filetest/mod.rs @@ -12,12 +12,14 @@ use print_cfg; use filetest::runner::TestRunner; pub mod subtest; -mod runner; -mod runone; + mod concurrent; mod domtree; -mod verifier; mod legalizer; +mod regalloc; +mod runner; +mod runone; +mod verifier; /// The result of running the test in a file. pub type TestResult = Result; @@ -49,7 +51,7 @@ pub fn run(verbose: bool, files: Vec) -> CommandResult { /// Create a new subcommand trait object to match `parsed.command`. /// /// This function knows how to create all of the possible `test ` commands that can appear in -/// a .cton test file. +/// a `.cton` test file. fn new_subtest(parsed: &TestCommand) -> subtest::Result> { match parsed.command { "cat" => cat::subtest(parsed), @@ -57,6 +59,7 @@ fn new_subtest(parsed: &TestCommand) -> subtest::Result> { "domtree" => domtree::subtest(parsed), "verifier" => verifier::subtest(parsed), "legalizer" => legalizer::subtest(parsed), + "regalloc" => regalloc::subtest(parsed), _ => Err(format!("unknown test command '{}'", parsed.command)), } } diff --git a/src/filetest/regalloc.rs b/src/filetest/regalloc.rs new file mode 100644 index 0000000000..af9dbb2b23 --- /dev/null +++ b/src/filetest/regalloc.rs @@ -0,0 +1,55 @@ +//! Test command for testing the register allocator. +//! +//! The `regalloc` test command runs each function through the register allocator after ensuring +//! that all instructions are legal for the target. +//! +//! The resulting function is sent to `filecheck`. + +use std::borrow::Cow; +use cretonne::{self, write_function}; +use cretonne::ir::Function; +use cton_reader::TestCommand; +use filetest::subtest::{SubTest, Context, Result, run_filecheck}; + +struct TestRegalloc; + +pub fn subtest(parsed: &TestCommand) -> Result> { + assert_eq!(parsed.command, "regalloc"); + if !parsed.options.is_empty() { + Err(format!("No options allowed on {}", parsed)) + } else { + Ok(Box::new(TestRegalloc)) + } +} + +impl SubTest for TestRegalloc { + fn name(&self) -> Cow { + Cow::from("regalloc") + } + + fn is_mutating(&self) -> bool { + true + } + + fn needs_isa(&self) -> bool { + true + } + + fn run(&self, func: Cow, context: &Context) -> Result<()> { + let isa = context.isa.expect("register allocator needs an ISA"); + + // Create a compilation context, and drop in the function. + let mut comp_ctx = cretonne::Context::new(); + comp_ctx.func = func.into_owned(); + + // TODO: Should we have an option to skip legalization? + comp_ctx.legalize(isa); + + comp_ctx.flowgraph(); + comp_ctx.regalloc(isa); + + let mut text = String::new(); + try!(write_function(&mut text, &comp_ctx.func, Some(isa)).map_err(|e| e.to_string())); + run_filecheck(&text, context) + } +}