diff --git a/cranelift/filetests/licm/basic.clif b/cranelift/filetests/licm/basic.clif index 84d9242169..f409523c70 100644 --- a/cranelift/filetests/licm/basic.clif +++ b/cranelift/filetests/licm/basic.clif @@ -1,4 +1,5 @@ test licm +target riscv32 function %simple_loop(i32) -> i32 { diff --git a/cranelift/filetests/licm/complex.clif b/cranelift/filetests/licm/complex.clif index 3b339574a8..0f825e3a8e 100644 --- a/cranelift/filetests/licm/complex.clif +++ b/cranelift/filetests/licm/complex.clif @@ -1,4 +1,5 @@ test licm +target riscv32 function %complex(i32) -> i32 system_v { ebb0(v0: i32): diff --git a/cranelift/filetests/licm/encoding.clif b/cranelift/filetests/licm/encoding.clif new file mode 100644 index 0000000000..27a965f55b --- /dev/null +++ b/cranelift/filetests/licm/encoding.clif @@ -0,0 +1,36 @@ +test licm +target riscv32 + +; Ensure that instructions emitted by LICM get encodings. + +function %simple_loop(i32) -> i32 { + ebb0(v0: i32): +[UJ#1b] jump ebb1(v0) + + ebb1(v1: i32): +[Iz#04,%x0] v2 = iconst.i32 1 +[Iz#04,%x1] v3 = iconst.i32 2 +[R#0c,%x2] v4 = iadd v2, v3 +[SBzero#18] brz v1, ebb2(v1) +[R#200c,%x5] v5 = isub v1, v2 +[UJ#1b] jump ebb1(v5) + + ebb2(v6: i32): +[Iret#19] return v6 +} + +; check: function +; nextln: ebb0(v0: i32): +; nextln: [Iz#04,%x0] v2 = iconst.i32 1 +; nextln: [Iz#04,%x1] v3 = iconst.i32 2 +; nextln: [R#0c,%x2] v4 = iadd v2, v3 +; nextln: [UJ#1b] jump ebb1(v0) +; nextln: +; nextln: ebb1(v1: i32): +; nextln: [SBzero#18] brz v1, ebb2(v1) +; nextln: [R#200c,%x5] v5 = isub v1, v2 +; nextln: [UJ#1b] jump ebb1(v5) +; nextln: +; nextln: ebb2(v6: i32): +; nextln: [Iret#19] return v6 +; nextln: } diff --git a/cranelift/filetests/licm/multiple-blocks.clif b/cranelift/filetests/licm/multiple-blocks.clif index d47f8658d2..de5af884e8 100644 --- a/cranelift/filetests/licm/multiple-blocks.clif +++ b/cranelift/filetests/licm/multiple-blocks.clif @@ -1,4 +1,5 @@ test licm +target riscv32 function %multiple_blocks(i32) -> i32 { diff --git a/cranelift/filetests/licm/nested_loops.clif b/cranelift/filetests/licm/nested_loops.clif index 9fb3c08806..f9ade38cf2 100644 --- a/cranelift/filetests/licm/nested_loops.clif +++ b/cranelift/filetests/licm/nested_loops.clif @@ -1,4 +1,5 @@ test licm +target riscv32 function %nested_loops(i32) -> i32 { diff --git a/cranelift/filetests/licm/reject.clif b/cranelift/filetests/licm/reject.clif index 052ae2b6f2..a23decb1eb 100644 --- a/cranelift/filetests/licm/reject.clif +++ b/cranelift/filetests/licm/reject.clif @@ -1,4 +1,5 @@ test licm +target riscv32 function %other_side_effects(i32) -> i32 { @@ -6,9 +7,9 @@ ebb0(v0: i32): jump ebb1(v0) ebb1(v1: i32): - regmove.i32 v0, %10 -> %20 + regmove.i32 v0, %x10 -> %x20 ; check: ebb1(v1: i32): -; check: regmove.i32 v0, %10 -> %20 +; check: regmove.i32 v0, %x10 -> %x20 v2 = iconst.i32 1 brz v1, ebb2(v1) v5 = isub v1, v2 diff --git a/lib/codegen/src/context.rs b/lib/codegen/src/context.rs index ffff2e25ab..a0bd1e680d 100644 --- a/lib/codegen/src/context.rs +++ b/lib/codegen/src/context.rs @@ -275,14 +275,15 @@ impl Context { } /// Perform LICM on the function. - pub fn licm<'a, FOI: Into>>(&mut self, fisa: FOI) -> CodegenResult<()> { + pub fn licm(&mut self, isa: &TargetIsa) -> CodegenResult<()> { do_licm( + isa, &mut self.func, &mut self.cfg, &mut self.domtree, &mut self.loop_analysis, ); - self.verify_if(fisa) + self.verify_if(isa) } /// Perform unreachable code elimination. diff --git a/lib/codegen/src/licm.rs b/lib/codegen/src/licm.rs index f9954087b4..0cba66b53b 100644 --- a/lib/codegen/src/licm.rs +++ b/lib/codegen/src/licm.rs @@ -1,11 +1,12 @@ //! A Loop Invariant Code Motion optimization pass -use cursor::{Cursor, FuncCursor}; +use cursor::{Cursor, FuncCursor, EncCursor}; use dominator_tree::DominatorTree; use entity::{EntityList, ListPool}; use flowgraph::{BasicBlock, ControlFlowGraph}; use fx::FxHashSet; use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value}; +use isa::TargetIsa; use loop_analysis::{Loop, LoopAnalysis}; use std::vec::Vec; use timing; @@ -14,6 +15,7 @@ use timing; /// loop-invariant instructions out of them. /// Changes the CFG and domtree in-place during the operation. pub fn do_licm( + isa: &TargetIsa, func: &mut Function, cfg: &mut ControlFlowGraph, domtree: &mut DominatorTree, @@ -36,7 +38,7 @@ pub fn do_licm( match has_pre_header(&func.layout, cfg, domtree, loop_analysis.loop_header(lp)) { None => { let pre_header = - create_pre_header(loop_analysis.loop_header(lp), func, cfg, domtree); + create_pre_header(isa, loop_analysis.loop_header(lp), func, cfg, domtree); pos = FuncCursor::new(func).at_last_inst(pre_header); } // If there is a natural pre-header we insert new instructions just before the @@ -60,6 +62,7 @@ pub fn do_licm( // Insert a pre-header before the header, modifying the function layout and CFG to reflect it. // A jump instruction to the header is placed at the end of the pre-header. fn create_pre_header( + isa: &TargetIsa, header: Ebb, func: &mut Function, cfg: &mut ControlFlowGraph, @@ -87,7 +90,7 @@ fn create_pre_header( } } { - let mut pos = FuncCursor::new(func).at_top(header); + let mut pos = EncCursor::new(func, isa).at_top(header); // Inserts the pre-header at the right place in the layout. pos.insert_ebb(pre_header); pos.next_inst(); diff --git a/lib/filetests/src/test_licm.rs b/lib/filetests/src/test_licm.rs index 57523cdf59..6c4ef0795d 100644 --- a/lib/filetests/src/test_licm.rs +++ b/lib/filetests/src/test_licm.rs @@ -33,12 +33,13 @@ impl SubTest for TestLICM { } fn run(&self, func: Cow, context: &Context) -> SubtestResult<()> { + let isa = context.isa.expect("LICM needs an ISA"); let mut comp_ctx = cranelift_codegen::Context::for_function(func.into_owned()); comp_ctx.flowgraph(); comp_ctx.compute_loop_analysis(); comp_ctx - .licm(context.flags_or_isa()) + .licm(isa) .map_err(|e| pretty_error(&comp_ctx.func, context.isa, Into::into(e)))?; let text = comp_ctx.func.display(context.isa).to_string();