diff --git a/cranelift/docs/testing.rst b/cranelift/docs/testing.rst index 02071f872d..2b02bb6d79 100644 --- a/cranelift/docs/testing.rst +++ b/cranelift/docs/testing.rst @@ -342,6 +342,14 @@ Test the DCE pass. The DCE pass is run on each function, and then results are run through filecheck. +`test shrink` +----------------- + +Test the instruction shrinking pass. + +The shrink pass is run on each function, and then results are run +through filecheck. + `test preopt` ----------------- diff --git a/lib/codegen/meta/isa/x86/recipes.py b/lib/codegen/meta/isa/x86/recipes.py index 047408db9c..8828f8a06e 100644 --- a/lib/codegen/meta/isa/x86/recipes.py +++ b/lib/codegen/meta/isa/x86/recipes.py @@ -389,6 +389,7 @@ urm_noflags = TailRecipe( urm_noflags_abcd = TailRecipe( 'urm_noflags_abcd', Unary, size=1, ins=ABCD, outs=GPR, when_prefixed=urm_noflags, + clobbers_flags=False, emit=''' PUT_OP(bits, rex2(in_reg0, out_reg0), sink); modrm_rr(in_reg0, out_reg0, sink); diff --git a/lib/filetests/src/lib.rs b/lib/filetests/src/lib.rs index 811b0e9e10..a86c0a0aae 100644 --- a/lib/filetests/src/lib.rs +++ b/lib/filetests/src/lib.rs @@ -45,6 +45,7 @@ mod test_postopt; mod test_preopt; mod test_print_cfg; mod test_regalloc; +mod test_shrink; mod test_simple_gvn; mod test_verifier; @@ -92,6 +93,7 @@ fn new_subtest(parsed: &TestCommand) -> subtest::SubtestResult test_preopt::subtest(parsed), "print-cfg" => test_print_cfg::subtest(parsed), "regalloc" => test_regalloc::subtest(parsed), + "shrink" => test_shrink::subtest(parsed), "simple-gvn" => test_simple_gvn::subtest(parsed), "verifier" => test_verifier::subtest(parsed), _ => Err(format!("unknown test command '{}'", parsed.command)), diff --git a/lib/filetests/src/test_shrink.rs b/lib/filetests/src/test_shrink.rs new file mode 100644 index 0000000000..4388919f36 --- /dev/null +++ b/lib/filetests/src/test_shrink.rs @@ -0,0 +1,46 @@ +//! Test command for testing the Shrink pass. +//! +//! The `shrink` test command runs each function through the Shrink pass after ensuring +//! that all instructions are legal for the target. +//! +//! The resulting function is sent to `filecheck`. + +use cretonne_codegen; +use cretonne_codegen::ir::Function; +use cretonne_codegen::print_errors::pretty_error; +use cretonne_reader::TestCommand; +use std::borrow::Cow; +use subtest::{run_filecheck, Context, SubTest, SubtestResult}; + +struct TestShrink; + +pub fn subtest(parsed: &TestCommand) -> SubtestResult> { + assert_eq!(parsed.command, "shrink"); + if !parsed.options.is_empty() { + Err(format!("No options allowed on {}", parsed)) + } else { + Ok(Box::new(TestShrink)) + } +} + +impl SubTest for TestShrink { + fn name(&self) -> &'static str { + "shrink" + } + + fn is_mutating(&self) -> bool { + true + } + + fn run(&self, func: Cow, context: &Context) -> SubtestResult<()> { + let isa = context.isa.expect("shrink needs an ISA"); + let mut comp_ctx = cretonne_codegen::Context::for_function(func.into_owned()); + + comp_ctx + .shrink_instructions(isa) + .map_err(|e| pretty_error(&comp_ctx.func, context.isa, Into::into(e)))?; + + let text = comp_ctx.func.to_string(); + run_filecheck(&text, context) + } +}