Fix all dead-code warnings in cranelift-codegen
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
|
||||
use crate::cursor::{Cursor, FuncCursor};
|
||||
use crate::flowgraph::ControlFlowGraph;
|
||||
use crate::ir::types::{I32, I64};
|
||||
use crate::ir::types::I32;
|
||||
use crate::ir::{self, InstBuilder, MemFlags};
|
||||
use crate::isa::TargetIsa;
|
||||
|
||||
@@ -23,7 +23,6 @@ use crate::timing;
|
||||
use alloc::collections::BTreeSet;
|
||||
|
||||
mod boundary;
|
||||
mod call;
|
||||
mod globalvalue;
|
||||
mod heap;
|
||||
mod libcall;
|
||||
@@ -320,12 +319,6 @@ pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa:
|
||||
}
|
||||
}
|
||||
|
||||
// Include legalization patterns that were generated by `gen_legalizer.rs` from the
|
||||
// `TransformGroup` in `cranelift-codegen/meta/shared/legalize.rs`.
|
||||
//
|
||||
// Concretely, this defines private functions `narrow()`, and `expand()`.
|
||||
include!(concat!(env!("OUT_DIR"), "/legalizer.rs"));
|
||||
|
||||
/// Custom expansion for conditional trap instructions.
|
||||
/// TODO: Add CFG support to the Rust DSL patterns so we won't have to do this.
|
||||
fn expand_cond_trap(
|
||||
@@ -403,189 +396,6 @@ fn expand_cond_trap(
|
||||
cfg.recompute_block(pos.func, new_block_trap);
|
||||
}
|
||||
|
||||
/// Jump tables.
|
||||
fn expand_br_table(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
cfg: &mut ControlFlowGraph,
|
||||
isa: &dyn TargetIsa,
|
||||
) {
|
||||
if isa.flags().enable_jump_tables() {
|
||||
expand_br_table_jt(inst, func, cfg, isa);
|
||||
} else {
|
||||
expand_br_table_conds(inst, func, cfg, isa);
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand br_table to jump table.
|
||||
fn expand_br_table_jt(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
cfg: &mut ControlFlowGraph,
|
||||
isa: &dyn TargetIsa,
|
||||
) {
|
||||
use crate::ir::condcodes::IntCC;
|
||||
|
||||
let (arg, default_block, table) = match func.dfg[inst] {
|
||||
ir::InstructionData::BranchTable {
|
||||
opcode: ir::Opcode::BrTable,
|
||||
arg,
|
||||
destination,
|
||||
table,
|
||||
} => (arg, destination, table),
|
||||
_ => panic!("Expected br_table: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
// Rewrite:
|
||||
//
|
||||
// br_table $idx, default_block, $jt
|
||||
//
|
||||
// To:
|
||||
//
|
||||
// $oob = ifcmp_imm $idx, len($jt)
|
||||
// brif uge $oob, default_block
|
||||
// jump fallthrough_block
|
||||
//
|
||||
// fallthrough_block:
|
||||
// $base = jump_table_base.i64 $jt
|
||||
// $rel_addr = jump_table_entry.i64 $idx, $base, 4, $jt
|
||||
// $addr = iadd $base, $rel_addr
|
||||
// indirect_jump_table_br $addr, $jt
|
||||
|
||||
let block = func.layout.pp_block(inst);
|
||||
let jump_table_block = func.dfg.make_block();
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
// Bounds check.
|
||||
let table_size = pos.func.jump_tables[table].len() as i64;
|
||||
let oob = pos
|
||||
.ins()
|
||||
.icmp_imm(IntCC::UnsignedGreaterThanOrEqual, arg, table_size);
|
||||
|
||||
pos.ins().brnz(oob, default_block, &[]);
|
||||
pos.ins().jump(jump_table_block, &[]);
|
||||
pos.insert_block(jump_table_block);
|
||||
|
||||
let addr_ty = isa.pointer_type();
|
||||
|
||||
let arg = if pos.func.dfg.value_type(arg) == addr_ty {
|
||||
arg
|
||||
} else {
|
||||
pos.ins().uextend(addr_ty, arg)
|
||||
};
|
||||
|
||||
let base_addr = pos.ins().jump_table_base(addr_ty, table);
|
||||
let entry = pos
|
||||
.ins()
|
||||
.jump_table_entry(arg, base_addr, I32.bytes() as u8, table);
|
||||
|
||||
let addr = pos.ins().iadd(base_addr, entry);
|
||||
pos.ins().indirect_jump_table_br(addr, table);
|
||||
|
||||
pos.remove_inst();
|
||||
cfg.recompute_block(pos.func, block);
|
||||
cfg.recompute_block(pos.func, jump_table_block);
|
||||
}
|
||||
|
||||
/// Expand br_table to series of conditionals.
|
||||
fn expand_br_table_conds(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
cfg: &mut ControlFlowGraph,
|
||||
_isa: &dyn TargetIsa,
|
||||
) {
|
||||
use crate::ir::condcodes::IntCC;
|
||||
|
||||
let (arg, default_block, table) = match func.dfg[inst] {
|
||||
ir::InstructionData::BranchTable {
|
||||
opcode: ir::Opcode::BrTable,
|
||||
arg,
|
||||
destination,
|
||||
table,
|
||||
} => (arg, destination, table),
|
||||
_ => panic!("Expected br_table: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
let block = func.layout.pp_block(inst);
|
||||
|
||||
// This is a poor man's jump table using just a sequence of conditional branches.
|
||||
let table_size = func.jump_tables[table].len();
|
||||
let mut cond_failed_block = vec![];
|
||||
if table_size >= 1 {
|
||||
cond_failed_block = alloc::vec::Vec::with_capacity(table_size - 1);
|
||||
for _ in 0..table_size - 1 {
|
||||
cond_failed_block.push(func.dfg.make_block());
|
||||
}
|
||||
}
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
// Ignore the lint for this loop as the range needs to be 0 to table_size
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 0..table_size {
|
||||
let dest = pos.func.jump_tables[table].as_slice()[i];
|
||||
let t = pos.ins().icmp_imm(IntCC::Equal, arg, i as i64);
|
||||
pos.ins().brnz(t, dest, &[]);
|
||||
// Jump to the next case.
|
||||
if i < table_size - 1 {
|
||||
let block = cond_failed_block[i];
|
||||
pos.ins().jump(block, &[]);
|
||||
pos.insert_block(block);
|
||||
}
|
||||
}
|
||||
|
||||
// `br_table` jumps to the default destination if nothing matches
|
||||
pos.ins().jump(default_block, &[]);
|
||||
|
||||
pos.remove_inst();
|
||||
cfg.recompute_block(pos.func, block);
|
||||
for failed_block in cond_failed_block.into_iter() {
|
||||
cfg.recompute_block(pos.func, failed_block);
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand the select instruction.
|
||||
///
|
||||
/// Conditional moves are available in some ISAs for some register classes. The remaining selects
|
||||
/// are handled by a branch.
|
||||
fn expand_select(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
cfg: &mut ControlFlowGraph,
|
||||
_isa: &dyn TargetIsa,
|
||||
) {
|
||||
let (ctrl, tval, fval) = match func.dfg[inst] {
|
||||
ir::InstructionData::Ternary {
|
||||
opcode: ir::Opcode::Select,
|
||||
args,
|
||||
} => (args[0], args[1], args[2]),
|
||||
_ => panic!("Expected select: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
// Replace `result = select ctrl, tval, fval` with:
|
||||
//
|
||||
// brnz ctrl, new_block(tval)
|
||||
// jump new_block(fval)
|
||||
// new_block(result):
|
||||
let old_block = func.layout.pp_block(inst);
|
||||
let result = func.dfg.first_result(inst);
|
||||
func.dfg.clear_results(inst);
|
||||
let new_block = func.dfg.make_block();
|
||||
func.dfg.attach_block_param(new_block, result);
|
||||
|
||||
func.dfg.replace(inst).brnz(ctrl, new_block, &[tval]);
|
||||
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
pos.ins().jump(new_block, &[fval]);
|
||||
pos.insert_block(new_block);
|
||||
|
||||
cfg.recompute_block(pos.func, new_block);
|
||||
cfg.recompute_block(pos.func, old_block);
|
||||
}
|
||||
|
||||
fn expand_br_icmp(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
@@ -620,34 +430,6 @@ fn expand_br_icmp(
|
||||
cfg.recompute_block(pos.func, old_block);
|
||||
}
|
||||
|
||||
/// Expand illegal `f32const` and `f64const` instructions.
|
||||
fn expand_fconst(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
_isa: &dyn TargetIsa,
|
||||
) {
|
||||
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
debug_assert!(!ty.is_vector(), "Only scalar fconst supported: {}", ty);
|
||||
|
||||
// In the future, we may want to generate constant pool entries for these constants, but for
|
||||
// now use an `iconst` and a bit cast.
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
let ival = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::UnaryIeee32 {
|
||||
opcode: ir::Opcode::F32const,
|
||||
imm,
|
||||
} => pos.ins().iconst(ir::types::I32, i64::from(imm.bits())),
|
||||
ir::InstructionData::UnaryIeee64 {
|
||||
opcode: ir::Opcode::F64const,
|
||||
imm,
|
||||
} => pos.ins().iconst(ir::types::I64, imm.bits() as i64),
|
||||
_ => panic!("Expected fconst: {}", pos.func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
pos.func.dfg.replace(inst).bitcast(ty, ival);
|
||||
}
|
||||
|
||||
/// Expand illegal `stack_load` instructions.
|
||||
fn expand_stack_load(
|
||||
inst: ir::Inst,
|
||||
@@ -713,171 +495,3 @@ fn expand_stack_store(
|
||||
mflags.set_aligned();
|
||||
pos.func.dfg.replace(inst).store(mflags, val, addr, 0);
|
||||
}
|
||||
|
||||
/// Split a load into two parts before `iconcat`ing the result together.
|
||||
fn narrow_load(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
isa: &dyn TargetIsa,
|
||||
) {
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let (ptr, offset, flags) = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::Load {
|
||||
opcode: ir::Opcode::Load,
|
||||
arg,
|
||||
offset,
|
||||
flags,
|
||||
} => (arg, offset, flags),
|
||||
_ => panic!("Expected load: {}", pos.func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
let res_ty = pos.func.dfg.ctrl_typevar(inst);
|
||||
let small_ty = res_ty.half_width().expect("Can't narrow load");
|
||||
|
||||
let al = pos.ins().load(small_ty, flags, ptr, offset);
|
||||
let ah = pos.ins().load(
|
||||
small_ty,
|
||||
flags,
|
||||
ptr,
|
||||
offset.try_add_i64(8).expect("load offset overflow"),
|
||||
);
|
||||
let (al, ah) = match flags.endianness(isa.endianness()) {
|
||||
ir::Endianness::Little => (al, ah),
|
||||
ir::Endianness::Big => (ah, al),
|
||||
};
|
||||
pos.func.dfg.replace(inst).iconcat(al, ah);
|
||||
}
|
||||
|
||||
/// Split a store into two parts after `isplit`ing the value.
|
||||
fn narrow_store(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
isa: &dyn TargetIsa,
|
||||
) {
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let (val, ptr, offset, flags) = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::Store {
|
||||
opcode: ir::Opcode::Store,
|
||||
args,
|
||||
offset,
|
||||
flags,
|
||||
} => (args[0], args[1], offset, flags),
|
||||
_ => panic!("Expected store: {}", pos.func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
let (al, ah) = pos.ins().isplit(val);
|
||||
let (al, ah) = match flags.endianness(isa.endianness()) {
|
||||
ir::Endianness::Little => (al, ah),
|
||||
ir::Endianness::Big => (ah, al),
|
||||
};
|
||||
pos.ins().store(flags, al, ptr, offset);
|
||||
pos.ins().store(
|
||||
flags,
|
||||
ah,
|
||||
ptr,
|
||||
offset.try_add_i64(8).expect("store offset overflow"),
|
||||
);
|
||||
pos.remove_inst();
|
||||
}
|
||||
|
||||
/// Expands an illegal iconst value by splitting it into two.
|
||||
fn narrow_iconst(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
isa: &dyn TargetIsa,
|
||||
) {
|
||||
let imm: i64 = if let ir::InstructionData::UnaryImm {
|
||||
opcode: ir::Opcode::Iconst,
|
||||
imm,
|
||||
} = &func.dfg[inst]
|
||||
{
|
||||
(*imm).into()
|
||||
} else {
|
||||
panic!("unexpected instruction in narrow_iconst");
|
||||
};
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let ty = pos.func.dfg.ctrl_typevar(inst);
|
||||
if isa.pointer_bits() == 32 && ty == I64 {
|
||||
let low = pos.ins().iconst(I32, imm & 0xffffffff);
|
||||
let high = pos.ins().iconst(I32, imm >> 32);
|
||||
// The instruction has as many results as iconcat, so no need to replace them.
|
||||
pos.func.dfg.replace(inst).iconcat(low, high);
|
||||
return;
|
||||
}
|
||||
|
||||
unimplemented!("missing encoding or legalization for iconst.{:?}", ty);
|
||||
}
|
||||
|
||||
fn narrow_icmp_imm(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
_isa: &dyn TargetIsa,
|
||||
) {
|
||||
use crate::ir::condcodes::{CondCode, IntCC};
|
||||
|
||||
let (arg, cond, imm): (ir::Value, IntCC, i64) = match func.dfg[inst] {
|
||||
ir::InstructionData::IntCompareImm {
|
||||
opcode: ir::Opcode::IcmpImm,
|
||||
arg,
|
||||
cond,
|
||||
imm,
|
||||
} => (arg, cond, imm.into()),
|
||||
_ => panic!("unexpected instruction in narrow_icmp_imm"),
|
||||
};
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let ty = pos.func.dfg.ctrl_typevar(inst);
|
||||
let ty_half = ty.half_width().unwrap();
|
||||
|
||||
let mask = ((1u128 << ty_half.bits()) - 1) as i64;
|
||||
let imm_low = pos.ins().iconst(ty_half, imm & mask);
|
||||
let imm_high = pos.ins().iconst(
|
||||
ty_half,
|
||||
imm.checked_shr(ty_half.bits().into()).unwrap_or(0) & mask,
|
||||
);
|
||||
let (arg_low, arg_high) = pos.ins().isplit(arg);
|
||||
|
||||
match cond {
|
||||
IntCC::Equal => {
|
||||
let res_low = pos.ins().icmp(cond, arg_low, imm_low);
|
||||
let res_high = pos.ins().icmp(cond, arg_high, imm_high);
|
||||
pos.func.dfg.replace(inst).band(res_low, res_high);
|
||||
}
|
||||
IntCC::NotEqual => {
|
||||
let res_low = pos.ins().icmp(cond, arg_low, imm_low);
|
||||
let res_high = pos.ins().icmp(cond, arg_high, imm_high);
|
||||
pos.func.dfg.replace(inst).bor(res_low, res_high);
|
||||
}
|
||||
IntCC::SignedGreaterThan
|
||||
| IntCC::SignedGreaterThanOrEqual
|
||||
| IntCC::SignedLessThan
|
||||
| IntCC::SignedLessThanOrEqual
|
||||
| IntCC::UnsignedGreaterThan
|
||||
| IntCC::UnsignedGreaterThanOrEqual
|
||||
| IntCC::UnsignedLessThan
|
||||
| IntCC::UnsignedLessThanOrEqual => {
|
||||
let b1 = pos.ins().icmp(cond.without_equal(), arg_high, imm_high);
|
||||
let b2 = pos
|
||||
.ins()
|
||||
.icmp(cond.inverse().without_equal(), arg_high, imm_high);
|
||||
let b3 = pos.ins().icmp(cond.unsigned(), arg_low, imm_low);
|
||||
let c1 = pos.ins().bnot(b2);
|
||||
let c2 = pos.ins().band(c1, b3);
|
||||
pos.func.dfg.replace(inst).bor(b1, c2);
|
||||
}
|
||||
_ => unimplemented!("missing legalization for condition {:?}", cond),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user