diff --git a/cranelift/filetests/isa/x86/legalize-br-icmp.clif b/cranelift/filetests/isa/x86/legalize-br-icmp.clif new file mode 100644 index 0000000000..e4694c36b1 --- /dev/null +++ b/cranelift/filetests/isa/x86/legalize-br-icmp.clif @@ -0,0 +1,46 @@ +test legalizer + +target x86_64 + +function %br_icmp(i64) fast { +ebb0(v0: i64): + v1 = iconst.i64 0 + br_icmp eq v0, v1, ebb1 + jump ebb1 + +ebb1: + return +} + +; sameln: function %br_icmp(i64 [%rdi]) fast { +; nextln: ebb0(v0: i64): +; nextln: [RexOp1pu_id#b8] v1 = iconst.i64 0 +; nextln: [RexOp1icscc#8039] v2 = icmp eq v0, v1 +; nextln: [RexOp1t8jccb#75] brnz v2, ebb1 +; nextln: [RexOp1jmpb#eb] jump ebb1 +; nextln: +; nextln: ebb1: +; nextln: [Op1ret#c3] return +; nextln: } + + +function %br_icmp_ebb_args(i64) fast { +ebb0(v0: i64): + v1 = iconst.i64 0 + br_icmp eq v0, v1, ebb1(v0) + jump ebb1(v0) + +ebb1(v2: i64): + return +} + +; sameln: function %br_icmp_ebb_args(i64 [%rdi]) fast { +; nextln: ebb0(v0: i64): +; nextln: [RexOp1pu_id#b8] v1 = iconst.i64 0 +; nextln: [RexOp1icscc#8039] v3 = icmp eq v0, v1 +; nextln: [RexOp1t8jccb#75] brnz v3, ebb1(v0) +; nextln: [RexOp1jmpb#eb] jump ebb1(v0) +; nextln: +; nextln: ebb1(v2: i64): +; nextln: [Op1ret#c3] return +; nextln: } diff --git a/lib/codegen/meta-python/base/legalize.py b/lib/codegen/meta-python/base/legalize.py index cf66074809..3427d8ef44 100644 --- a/lib/codegen/meta-python/base/legalize.py +++ b/lib/codegen/meta-python/base/legalize.py @@ -407,6 +407,7 @@ for ty, minus_zero in [ a << bor(a1, a2) )) +expand.custom_legalize(insts.br_icmp, 'expand_br_icmp') # Expansions using CPU flags. diff --git a/lib/codegen/src/legalizer/mod.rs b/lib/codegen/src/legalizer/mod.rs index 7c24a86723..a7645fb643 100644 --- a/lib/codegen/src/legalizer/mod.rs +++ b/lib/codegen/src/legalizer/mod.rs @@ -244,6 +244,40 @@ fn expand_select( cfg.recompute_ebb(pos.func, old_ebb); } +fn expand_br_icmp( + inst: ir::Inst, + func: &mut ir::Function, + cfg: &mut ControlFlowGraph, + _isa: &TargetIsa, +) { + let (cond, a, b, destination, ebb_args) = match func.dfg[inst] { + ir::InstructionData::BranchIcmp { + cond, + destination, + ref args, + .. + } => ( + cond, + args.get(0, &func.dfg.value_lists).unwrap(), + args.get(1, &func.dfg.value_lists).unwrap(), + destination, + args.as_slice(&func.dfg.value_lists)[2..].to_vec(), + ), + _ => panic!("Expected br_icmp {}", func.dfg.display_inst(inst, None)), + }; + + let old_ebb = func.layout.pp_ebb(inst); + func.dfg.clear_results(inst); + + let icmp_res = func.dfg.replace(inst).icmp(cond, a, b); + let mut pos = FuncCursor::new(func).after_inst(inst); + pos.use_srcloc(inst); + pos.ins().brnz(icmp_res, destination, &ebb_args); + + cfg.recompute_ebb(pos.func, destination); + cfg.recompute_ebb(pos.func, old_ebb); +} + /// Expand illegal `f32const` and `f64const` instructions. fn expand_fconst( inst: ir::Inst,