ARM64 backend, part 1 / 11: misc changes to existing code.
- Add a `simple_legalize()` function that invokes a predetermined set of legalizations, without depending on the details of the current backend design. This will be used by the new backend pipeline. - Separate out `has_side_effect()` from the DCE pass. This will be used by the new backends' lowering code. - Add documentation for the `Arm64Call` relocation type.
This commit is contained in:
@@ -54,7 +54,9 @@ pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
|||||||
let mut a64 = CpuMode::new("A64");
|
let mut a64 = CpuMode::new("A64");
|
||||||
|
|
||||||
// TODO refine these.
|
// TODO refine these.
|
||||||
|
let expand_flags = shared_defs.transform_groups.by_name("expand_flags");
|
||||||
let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags");
|
let narrow_flags = shared_defs.transform_groups.by_name("narrow_flags");
|
||||||
|
a64.legalize_monomorphic(expand_flags);
|
||||||
a64.legalize_default(narrow_flags);
|
a64.legalize_default(narrow_flags);
|
||||||
|
|
||||||
let cpu_modes = vec![a64];
|
let cpu_modes = vec![a64];
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ pub enum Reloc {
|
|||||||
X86GOTPCRel4,
|
X86GOTPCRel4,
|
||||||
/// Arm32 call target
|
/// Arm32 call target
|
||||||
Arm32Call,
|
Arm32Call,
|
||||||
/// Arm64 call target
|
/// Arm64 call target. Encoded as bottom 26 bits of instruction. This
|
||||||
|
/// value is sign-extended, multiplied by 4, and added to the PC of
|
||||||
|
/// the call instruction to form the destination address.
|
||||||
Arm64Call,
|
Arm64Call,
|
||||||
/// RISC-V call target
|
/// RISC-V call target
|
||||||
RiscvCall,
|
RiscvCall,
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ fn is_load_with_defined_trapping(opcode: Opcode, data: &InstructionData) -> bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does the given instruction have any side-effect that would preclude it from being removed when
|
||||||
|
/// its value is unused?
|
||||||
|
pub fn has_side_effect(func: &Function, inst: Inst) -> bool {
|
||||||
|
let data = &func.dfg[inst];
|
||||||
|
let opcode = data.opcode();
|
||||||
|
trivially_unsafe_for_dce(opcode) || is_load_with_defined_trapping(opcode, data)
|
||||||
|
}
|
||||||
|
|
||||||
/// Perform DCE on `func`.
|
/// Perform DCE on `func`.
|
||||||
pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) {
|
pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) {
|
||||||
let _tt = timing::dce();
|
let _tt = timing::dce();
|
||||||
@@ -50,10 +58,7 @@ pub fn do_dce(func: &mut Function, domtree: &mut DominatorTree) {
|
|||||||
let mut pos = FuncCursor::new(func).at_bottom(block);
|
let mut pos = FuncCursor::new(func).at_bottom(block);
|
||||||
while let Some(inst) = pos.prev_inst() {
|
while let Some(inst) = pos.prev_inst() {
|
||||||
{
|
{
|
||||||
let data = &pos.func.dfg[inst];
|
if has_side_effect(pos.func, inst)
|
||||||
let opcode = data.opcode();
|
|
||||||
if trivially_unsafe_for_dce(opcode)
|
|
||||||
|| is_load_with_defined_trapping(opcode, &data)
|
|
||||||
|| any_inst_results_used(inst, &live, &pos.func.dfg)
|
|| any_inst_results_used(inst, &live, &pos.func.dfg)
|
||||||
{
|
{
|
||||||
for arg in pos.func.dfg.inst_args(inst) {
|
for arg in pos.func.dfg.inst_args(inst) {
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ impl Imm64 {
|
|||||||
pub fn wrapping_neg(self) -> Self {
|
pub fn wrapping_neg(self) -> Self {
|
||||||
Self(self.0.wrapping_neg())
|
Self(self.0.wrapping_neg())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return bits of this immediate.
|
||||||
|
pub fn bits(&self) -> i64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<i64> for Imm64 {
|
impl Into<i64> for Imm64 {
|
||||||
|
|||||||
@@ -196,6 +196,55 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform a simple legalization by expansion of the function, without
|
||||||
|
/// platform-specific transforms.
|
||||||
|
pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa: &dyn TargetIsa) {
|
||||||
|
let mut pos = FuncCursor::new(func);
|
||||||
|
let func_begin = pos.position();
|
||||||
|
pos.set_position(func_begin);
|
||||||
|
while let Some(_block) = pos.next_block() {
|
||||||
|
let mut prev_pos = pos.position();
|
||||||
|
while let Some(inst) = pos.next_inst() {
|
||||||
|
let expanded = match pos.func.dfg[inst].opcode() {
|
||||||
|
ir::Opcode::BrIcmp
|
||||||
|
| ir::Opcode::GlobalValue
|
||||||
|
| ir::Opcode::HeapAddr
|
||||||
|
| ir::Opcode::StackLoad
|
||||||
|
| ir::Opcode::StackStore
|
||||||
|
| ir::Opcode::TableAddr
|
||||||
|
| ir::Opcode::Trapnz
|
||||||
|
| ir::Opcode::Trapz
|
||||||
|
| ir::Opcode::BandImm
|
||||||
|
| ir::Opcode::BorImm
|
||||||
|
| ir::Opcode::BxorImm
|
||||||
|
| ir::Opcode::IaddImm
|
||||||
|
| ir::Opcode::IfcmpImm
|
||||||
|
| ir::Opcode::ImulImm
|
||||||
|
| ir::Opcode::IrsubImm
|
||||||
|
| ir::Opcode::IshlImm
|
||||||
|
| ir::Opcode::RotlImm
|
||||||
|
| ir::Opcode::RotrImm
|
||||||
|
| ir::Opcode::SdivImm
|
||||||
|
| ir::Opcode::SremImm
|
||||||
|
| ir::Opcode::SshrImm
|
||||||
|
| ir::Opcode::UdivImm
|
||||||
|
| ir::Opcode::UremImm
|
||||||
|
| ir::Opcode::UshrImm
|
||||||
|
| ir::Opcode::IcmpImm => expand(inst, &mut pos.func, cfg, isa),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if expanded {
|
||||||
|
// Legalization implementations require fixpoint loop
|
||||||
|
// here. TODO: fix this.
|
||||||
|
pos.set_position(prev_pos);
|
||||||
|
} else {
|
||||||
|
prev_pos = pos.position();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Include legalization patterns that were generated by `gen_legalizer.rs` from the
|
// Include legalization patterns that were generated by `gen_legalizer.rs` from the
|
||||||
// `TransformGroup` in `cranelift-codegen/meta/shared/legalize.rs`.
|
// `TransformGroup` in `cranelift-codegen/meta/shared/legalize.rs`.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user