diff --git a/cranelift/codegen/src/simple_preopt.rs b/cranelift/codegen/src/simple_preopt.rs index eeaa3c8d91..4d6f31c654 100644 --- a/cranelift/codegen/src/simple_preopt.rs +++ b/cranelift/codegen/src/simple_preopt.rs @@ -556,9 +556,8 @@ enum BranchOptKind { fn branch_opt(pos: &mut FuncCursor, inst: Inst) { let info = match pos.func.dfg[inst] { - InstructionData::BranchInt { - opcode: Opcode::Brif, - cond: br_cond, + InstructionData::Branch { + opcode, destination, ref args, } => { @@ -566,6 +565,7 @@ fn branch_opt(pos: &mut FuncCursor, inst: Inst) { let args = pos.func.dfg.inst_args(inst); args[0] }; + let iconst_inst = if let ValueDef::Result(iconst_inst, _) = pos.func.dfg.value_def(first_arg) { iconst_inst @@ -573,10 +573,11 @@ fn branch_opt(pos: &mut FuncCursor, inst: Inst) { return; }; - if let InstructionData::BinaryImm { - opcode: Opcode::IfcmpImm, - imm: cmp_imm, + if let InstructionData::IntCompareImm { + opcode: Opcode::IcmpImm, arg: cmp_arg, + cond: cmp_cond, + imm: cmp_imm, } = pos.func.dfg[iconst_inst] { let cmp_imm: i64 = cmp_imm.into(); @@ -584,9 +585,17 @@ fn branch_opt(pos: &mut FuncCursor, inst: Inst) { return; } - let kind = match br_cond { - IntCC::NotEqual => BranchOptKind::NotEqualZero, + // icmp_imm returns non-zero when the comparison is true. So, if + // we're branching on zero, we need to invert the condition. + let cond = match opcode { + Opcode::Brz => cmp_cond.inverse(), + Opcode::Brnz => cmp_cond, + _ => return, + }; + + let kind = match cond { IntCC::Equal => BranchOptKind::EqualZero, + IntCC::NotEqual => BranchOptKind::NotEqualZero, _ => return, }; diff --git a/cranelift/filetests/filetests/simple_preopt/branch.clif b/cranelift/filetests/filetests/simple_preopt/branch.clif index b0da32807e..6e5f3dcd52 100644 --- a/cranelift/filetests/filetests/simple_preopt/branch.clif +++ b/cranelift/filetests/filetests/simple_preopt/branch.clif @@ -1,31 +1,58 @@ test simple_preopt target x86_64 -function %brif_to_brz_fold(i32) -> i32 { +function %icmp_to_brz_fold(i32) -> i32 { ebb0(v0: i32): - v1 = ifcmp_imm v0, 0 - brif eq v1, ebb1 + v1 = icmp_imm eq v0, 0 + brnz v1, ebb1 jump ebb2 ebb1: - v2 = iconst.i32 1 - return v2 -ebb2: - v3 = iconst.i32 2 + v3 = iconst.i32 1 return v3 +ebb2: + v4 = iconst.i32 2 + return v4 } -; sameln: function %brif_to_brz_fold +; sameln: function %icmp_to_brz_fold ; nextln: ebb0(v0: i32): -; nextln: v1 = ifcmp_imm v0, 0 +; nextln: v1 = icmp_imm eq v0, 0 ; nextln: brnz v0, ebb2 ; nextln: fallthrough ebb1 ; nextln: ; nextln: ebb1: -; nextln: v2 = iconst.i32 1 -; nextln: return v2 +; nextln: v3 = iconst.i32 1 +; nextln: return v3 ; nextln: ; nextln: ebb2: -; nextln: v3 = iconst.i32 2 +; nextln: v4 = iconst.i32 2 +; nextln: return v4 +; nextln: } + +function %icmp_to_brz_inverted_fold(i32) -> i32 { +ebb0(v0: i32): + v1 = icmp_imm ne v0, 0 + brz v1, ebb1 + jump ebb2 +ebb1: + v3 = iconst.i32 1 + return v3 +ebb2: + v4 = iconst.i32 2 + return v4 +} +; sameln: function %icmp_to_brz_inve +; nextln: ebb0(v0: i32): +; nextln: v1 = icmp_imm ne v0, 0 +; nextln: brnz v0, ebb2 +; nextln: fallthrough ebb1 +; nextln: +; nextln: ebb1: +; nextln: v3 = iconst.i32 1 ; nextln: return v3 +; nextln: +; nextln: ebb2: +; nextln: v4 = iconst.i32 2 +; nextln: return v4 ; nextln: } function %brif_inversion(i32) -> i32 {