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 
subtest(parsed: &TestCommand) -> Result<Box<dyn SubTest>>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 {
name(&self) -> &'static str40     fn name(&self) -> &'static str {
41         "optimize"
42     }
43 
is_mutating(&self) -> bool44     fn is_mutating(&self) -> bool {
45         true
46     }
47 
needs_isa(&self) -> bool48     fn needs_isa(&self) -> bool {
49         true
50     }
51 
run(&self, func: Cow<ir::Function>, context: &Context) -> Result<()>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