Fold 'ifcmp_imm' + 'brif' where imm is zero and cond is 'eq' or 'ne', into 'brz' or 'brnz'.
This commit is contained in:
committed by
Benjamin Bouvier
parent
9b156fd9bb
commit
fc6876c68e
@@ -5,8 +5,9 @@
|
|||||||
use crate::cursor::{Cursor, FuncCursor};
|
use crate::cursor::{Cursor, FuncCursor};
|
||||||
use crate::divconst_magic_numbers::{magic_s32, magic_s64, magic_u32, magic_u64};
|
use crate::divconst_magic_numbers::{magic_s32, magic_s64, magic_u32, magic_u64};
|
||||||
use crate::divconst_magic_numbers::{MS32, MS64, MU32, MU64};
|
use crate::divconst_magic_numbers::{MS32, MS64, MU32, MU64};
|
||||||
|
use crate::ir::condcodes::IntCC;
|
||||||
use crate::ir::dfg::ValueDef;
|
use crate::ir::dfg::ValueDef;
|
||||||
use crate::ir::instructions::Opcode;
|
use crate::ir::instructions::{Opcode, ValueList};
|
||||||
use crate::ir::types::{I32, I64};
|
use crate::ir::types::{I32, I64};
|
||||||
use crate::ir::Inst;
|
use crate::ir::Inst;
|
||||||
use crate::ir::{DataFlowGraph, Function, InstBuilder, InstructionData, Type, Value};
|
use crate::ir::{DataFlowGraph, Function, InstBuilder, InstructionData, Type, Value};
|
||||||
@@ -536,6 +537,88 @@ fn simplify(pos: &mut FuncCursor, inst: Inst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct BranchOptInfo {
|
||||||
|
br_inst: Inst,
|
||||||
|
cmp_arg: Value,
|
||||||
|
destination: Ebb,
|
||||||
|
args: ValueList,
|
||||||
|
kind: BranchOptKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BranchOptKind {
|
||||||
|
EqualZero,
|
||||||
|
NotEqualZero,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn branch_opt(pos: &mut FuncCursor, inst: Inst) {
|
||||||
|
let info = match pos.func.dfg[inst] {
|
||||||
|
InstructionData::BranchInt {
|
||||||
|
opcode: Opcode::Brif,
|
||||||
|
cond: br_cond,
|
||||||
|
destination,
|
||||||
|
ref args,
|
||||||
|
} => {
|
||||||
|
let first_arg = {
|
||||||
|
let args = pos.func.dfg.inst_args(inst);
|
||||||
|
args[0]
|
||||||
|
};
|
||||||
|
if let ValueDef::Result(iconst_inst, _) = pos.func.dfg.value_def(first_arg) {
|
||||||
|
if let InstructionData::BinaryImm {
|
||||||
|
opcode: Opcode::IfcmpImm,
|
||||||
|
imm: cmp_imm,
|
||||||
|
arg: cmp_arg,
|
||||||
|
} = pos.func.dfg[iconst_inst]
|
||||||
|
{
|
||||||
|
let cmp_imm: i64 = cmp_imm.into();
|
||||||
|
if cmp_imm != 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match br_cond {
|
||||||
|
IntCC::NotEqual => BranchOptInfo {
|
||||||
|
br_inst: inst,
|
||||||
|
cmp_arg: cmp_arg,
|
||||||
|
destination: destination,
|
||||||
|
args: args.clone(),
|
||||||
|
kind: BranchOptKind::NotEqualZero,
|
||||||
|
},
|
||||||
|
IntCC::Equal => BranchOptInfo {
|
||||||
|
br_inst: inst,
|
||||||
|
cmp_arg: cmp_arg,
|
||||||
|
destination: destination,
|
||||||
|
args: args.clone(),
|
||||||
|
kind: BranchOptKind::EqualZero,
|
||||||
|
},
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
match info.kind {
|
||||||
|
BranchOptKind::EqualZero => {
|
||||||
|
let args = info.args.as_slice(&pos.func.dfg.value_lists)[1..].to_vec();
|
||||||
|
pos.func
|
||||||
|
.dfg
|
||||||
|
.replace(info.br_inst)
|
||||||
|
.brz(info.cmp_arg, info.destination, &args);
|
||||||
|
}
|
||||||
|
BranchOptKind::NotEqualZero => {
|
||||||
|
let args = info.args.as_slice(&pos.func.dfg.value_lists)[1..].to_vec();
|
||||||
|
pos.func
|
||||||
|
.dfg
|
||||||
|
.replace(info.br_inst)
|
||||||
|
.brnz(info.cmp_arg, info.destination, &args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The main pre-opt pass.
|
/// The main pre-opt pass.
|
||||||
pub fn do_preopt(func: &mut Function) {
|
pub fn do_preopt(func: &mut Function) {
|
||||||
let _tt = timing::preopt();
|
let _tt = timing::preopt();
|
||||||
@@ -554,6 +637,8 @@ pub fn do_preopt(func: &mut Function) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-- END -- division by constants ------------------
|
//-- END -- division by constants ------------------
|
||||||
|
|
||||||
|
branch_opt(&mut pos, inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
cranelift/filetests/filetests/simple_preopt/branch.clif
Normal file
29
cranelift/filetests/filetests/simple_preopt/branch.clif
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
test simple_preopt
|
||||||
|
target x86_64
|
||||||
|
|
||||||
|
function %brif_to_brz_fold(i32) -> i32 {
|
||||||
|
ebb0(v0: i32):
|
||||||
|
v1 = ifcmp_imm v0, 0
|
||||||
|
brif eq v1, ebb1
|
||||||
|
jump ebb2
|
||||||
|
ebb1:
|
||||||
|
v2 = iconst.i32 1
|
||||||
|
return v2
|
||||||
|
ebb2:
|
||||||
|
v3 = iconst.i32 2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
; sameln: function %brif_to_brz_fold
|
||||||
|
; nextln: ebb0(v0: i32):
|
||||||
|
; nextln: v1 = ifcmp_imm v0, 0
|
||||||
|
; nextln: brz v0, ebb1
|
||||||
|
; nextln: jump ebb2
|
||||||
|
; nextln:
|
||||||
|
; nextln: ebb1:
|
||||||
|
; nextln: v2 = iconst.i32 1
|
||||||
|
; nextln: return v2
|
||||||
|
; nextln:
|
||||||
|
; nextln: ebb2:
|
||||||
|
; nextln: v3 = iconst.i32 2
|
||||||
|
; nextln: return v3
|
||||||
|
; nextln: }
|
||||||
Reference in New Issue
Block a user