1 //! Test command for testing the optimization phases. 2 //! 3 //! The `optimize` test command runs each function through the 4 //! optimization passes, but not lowering or regalloc. The output for 5 //! filecheck purposes is the resulting CLIF. 6 //! 7 //! Some legalization may be ISA-specific, so this requires an ISA 8 //! (for now). 9 10 use crate::subtest::{Context, SubTest, check_precise_output, run_filecheck}; 11 use anyhow::Result; 12 use cranelift_codegen::ir; 13 use cranelift_control::ControlPlane; 14 use cranelift_reader::{TestCommand, TestOption}; 15 use std::borrow::Cow; 16 17 struct TestOptimize { 18 /// Flag indicating that the text expectation, comments after the function, 19 /// must be a precise 100% match on the compiled output of the function. 20 /// This test assertion is also automatically-update-able to allow tweaking 21 /// the code generator and easily updating all affected tests. 22 precise_output: bool, 23 } 24 25 pub fn subtest(parsed: &TestCommand) -> Result<Box<dyn SubTest>> { 26 assert_eq!(parsed.command, "optimize"); 27 let mut test = TestOptimize { 28 precise_output: false, 29 }; 30 for option in parsed.options.iter() { 31 match option { 32 TestOption::Flag("precise-output") => test.precise_output = true, 33 _ => anyhow::bail!("unknown option on {parsed}"), 34 } 35 } 36 Ok(Box::new(test)) 37 } 38 39 impl SubTest for TestOptimize { 40 fn name(&self) -> &'static str { 41 "optimize" 42 } 43 44 fn is_mutating(&self) -> bool { 45 true 46 } 47 48 fn needs_isa(&self) -> bool { 49 true 50 } 51 52 fn run(&self, func: Cow<ir::Function>, context: &Context) -> Result<()> { 53 let isa = context.isa.expect("optimize needs an ISA"); 54 let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); 55 56 comp_ctx 57 .optimize(isa, &mut ControlPlane::default()) 58 .map_err(|e| crate::pretty_anyhow_error(&comp_ctx.func, e))?; 59 60 let clif = format!("{:?}", comp_ctx.func); 61 62 if self.precise_output { 63 let actual: Vec<_> = clif.lines().collect(); 64 check_precise_output(&actual, context) 65 } else { 66 run_filecheck(&clif, context) 67 } 68 } 69 } 70