s390x: clean up lower.rs (#4355)

Now that lowering is fully done in ISLE, clean up some code remnants
in lower.rs.  In particular, move code to lower/isle.rs where
possible, and inline lower_insn_to_regs into its caller and simplify.
This commit is contained in:
Ulrich Weigand
2022-06-30 20:16:59 +02:00
committed by GitHub
parent 919604b8c5
commit 95836ba114
2 changed files with 297 additions and 331 deletions

View File

@@ -1,88 +1,41 @@
//! Lowering rules for S390x. //! Lowering rules for S390x.
use crate::ir::condcodes::IntCC;
use crate::ir::Inst as IRInst; use crate::ir::Inst as IRInst;
use crate::ir::{MemFlags, Opcode}; use crate::ir::Opcode;
use crate::isa::s390x::abi::*; use crate::isa::s390x::inst::Inst;
use crate::isa::s390x::inst::*;
use crate::isa::s390x::settings as s390x_settings;
use crate::isa::s390x::S390xBackend; use crate::isa::s390x::S390xBackend;
use crate::machinst::lower::*; use crate::machinst::{InsnOutput, LowerBackend, LowerCtx, MachLabel};
use crate::machinst::*;
use crate::settings::Flags;
use crate::CodegenResult; use crate::CodegenResult;
use smallvec::SmallVec; use smallvec::SmallVec;
pub mod isle; pub mod isle;
//============================================================================
// Lowering: force instruction input into a register
/// Sign-extend the low `from_bits` bits of `value` to a full u64.
fn sign_extend_to_u64(value: u64, from_bits: u8) -> u64 {
assert!(from_bits <= 64);
if from_bits >= 64 {
value
} else {
(((value << (64 - from_bits)) as i64) >> (64 - from_bits)) as u64
}
}
//============================================================================= //=============================================================================
// Lowering: comparisons // Lowering-backend trait implementation.
/// Determines whether this condcode interprets inputs as signed or impl LowerBackend for S390xBackend {
/// unsigned. See the documentation for the `icmp` instruction in type MInst = Inst;
/// cranelift-codegen/meta/src/shared/instructions.rs for further insights
/// into this.
pub fn condcode_is_signed(cc: IntCC) -> bool {
match cc {
IntCC::Equal => false,
IntCC::NotEqual => false,
IntCC::SignedGreaterThanOrEqual => true,
IntCC::SignedGreaterThan => true,
IntCC::SignedLessThanOrEqual => true,
IntCC::SignedLessThan => true,
IntCC::UnsignedGreaterThanOrEqual => false,
IntCC::UnsignedGreaterThan => false,
IntCC::UnsignedLessThanOrEqual => false,
IntCC::UnsignedLessThan => false,
IntCC::Overflow => true,
IntCC::NotOverflow => true,
}
}
//============================================================================ fn lower<C: LowerCtx<I = Inst>>(&self, ctx: &mut C, ir_inst: IRInst) -> CodegenResult<()> {
// Lowering: main entry point for lowering a instruction let op = ctx.data(ir_inst).opcode();
let outputs: SmallVec<[InsnOutput; 2]> = (0..ctx.num_outputs(ir_inst))
fn lower_insn_to_regs<C: LowerCtx<I = Inst>>( .map(|i| InsnOutput {
ctx: &mut C, insn: ir_inst,
insn: IRInst, output: i,
flags: &Flags, })
isa_flags: &s390x_settings::Flags,
) -> CodegenResult<()> {
let op = ctx.data(insn).opcode();
let outputs: SmallVec<[InsnOutput; 2]> = (0..ctx.num_outputs(insn))
.map(|i| InsnOutput { insn, output: i })
.collect(); .collect();
let ty = if outputs.len() > 0 { let ty = if outputs.len() > 0 {
Some(ctx.output_ty(insn, 0)) Some(ctx.output_ty(ir_inst, 0))
} else { } else {
None None
}; };
if let Ok(()) = super::lower::isle::lower(ctx, flags, isa_flags, &outputs, insn) { if let Ok(()) =
super::lower::isle::lower(ctx, &self.flags, &self.isa_flags, &outputs, ir_inst)
{
return Ok(()); return Ok(());
} }
let implemented_in_isle = || {
unreachable!(
"implemented in ISLE: inst = `{}`, type = `{:?}`",
ctx.dfg().display_inst(insn),
ty
);
};
match op { match op {
Opcode::Nop Opcode::Nop
| Opcode::Copy | Opcode::Copy
@@ -186,42 +139,27 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
| Opcode::Return | Opcode::Return
| Opcode::StackAddr | Opcode::StackAddr
| Opcode::FuncAddr | Opcode::FuncAddr
| Opcode::SymbolValue => implemented_in_isle(), | Opcode::SymbolValue => {
unreachable!(
Opcode::UaddSat | Opcode::SaddSat => unimplemented!(), "implemented in ISLE: inst = `{}`, type = `{:?}`",
Opcode::UsubSat | Opcode::SsubSat => unimplemented!(), ctx.dfg().display_inst(ir_inst),
ty
Opcode::Bitrev => unimplemented!(), )
Opcode::FcvtLowFromSint => unimplemented!("FcvtLowFromSint"),
Opcode::StackLoad | Opcode::StackStore => {
panic!("Direct stack memory access not supported; should not be used by Wasm");
} }
Opcode::ConstAddr => unimplemented!(), Opcode::UaddSat
| Opcode::SaddSat
Opcode::HeapAddr => { | Opcode::UsubSat
panic!("heap_addr should have been removed by legalization!"); | Opcode::SsubSat
} | Opcode::Bitrev
| Opcode::FcvtLowFromSint
Opcode::TableAddr => { | Opcode::ConstAddr
panic!("table_addr should have been removed by legalization!"); | Opcode::TlsValue
} | Opcode::GetPinnedReg
| Opcode::SetPinnedReg
Opcode::GlobalValue => { | Opcode::Isplit
panic!("global_value should have been removed by legalization!"); | Opcode::Iconcat
} | Opcode::RawBitcast
Opcode::TlsValue => {
unimplemented!("Thread-local storage support not implemented!");
}
Opcode::GetPinnedReg | Opcode::SetPinnedReg => {
unimplemented!("Pinned register support not implemented!");
}
Opcode::RawBitcast
| Opcode::Splat | Opcode::Splat
| Opcode::Swizzle | Opcode::Swizzle
| Opcode::Insertlane | Opcode::Insertlane
@@ -260,17 +198,27 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
| Opcode::FvpromoteLow | Opcode::FvpromoteLow
| Opcode::Fvdemote | Opcode::Fvdemote
| Opcode::IaddPairwise => { | Opcode::IaddPairwise => {
// TODO unreachable!(
unimplemented!("Vector ops not implemented."); "TODO: not yet implemented in ISLE: inst = `{}`, type = `{:?}`",
ctx.dfg().display_inst(ir_inst),
ty
)
} }
Opcode::Isplit | Opcode::Iconcat => unimplemented!("Wide integer ops not implemented."), Opcode::StackLoad | Opcode::StackStore => {
panic!("Direct stack memory access not supported; should not be used by Wasm");
Opcode::IfcmpSp => { }
panic!("Unused opcode should not be encountered."); Opcode::HeapAddr => {
panic!("heap_addr should have been removed by legalization!");
}
Opcode::TableAddr => {
panic!("table_addr should have been removed by legalization!");
}
Opcode::GlobalValue => {
panic!("global_value should have been removed by legalization!");
} }
Opcode::Ifcmp Opcode::Ifcmp
| Opcode::IfcmpSp
| Opcode::Ffcmp | Opcode::Ffcmp
| Opcode::Trapff | Opcode::Trapff
| Opcode::Trueif | Opcode::Trueif
@@ -278,7 +226,6 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
| Opcode::Selectif => { | Opcode::Selectif => {
panic!("Flags opcode should not be encountered."); panic!("Flags opcode should not be encountered.");
} }
Opcode::Jump Opcode::Jump
| Opcode::Brz | Opcode::Brz
| Opcode::Brnz | Opcode::Brnz
@@ -288,7 +235,6 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
| Opcode::BrTable => { | Opcode::BrTable => {
panic!("Branch opcode reached non-branch lowering logic!"); panic!("Branch opcode reached non-branch lowering logic!");
} }
Opcode::IaddImm Opcode::IaddImm
| Opcode::ImulImm | Opcode::ImulImm
| Opcode::UdivImm | Opcode::UdivImm
@@ -320,18 +266,6 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
panic!("ALU+imm and ALU+carry ops should not appear here!"); panic!("ALU+imm and ALU+carry ops should not appear here!");
} }
} }
Ok(())
}
//=============================================================================
// Lowering-backend trait implementation.
impl LowerBackend for S390xBackend {
type MInst = Inst;
fn lower<C: LowerCtx<I = Inst>>(&self, ctx: &mut C, ir_inst: IRInst) -> CodegenResult<()> {
lower_insn_to_regs(ctx, ir_inst, &self.flags, &self.isa_flags)
} }
fn lower_branch_group<C: LowerCtx<I = Inst>>( fn lower_branch_group<C: LowerCtx<I = Inst>>(

View File

@@ -4,17 +4,19 @@
pub mod generated_code; pub mod generated_code;
// Types that the generated ISLE code uses via `use super::*`. // Types that the generated ISLE code uses via `use super::*`.
use super::{ use crate::isa::s390x::abi::S390xMachineDeps;
CallIndInfo, CallInfo, Cond, Inst as MInst, MachLabel, MemArg, MemFlags, Opcode, Reg, use crate::isa::s390x::inst::{
S390xMachineDeps, UImm16Shifted, UImm32Shifted, stack_reg, writable_gpr, zero_reg, CallIndInfo, CallInfo, Cond, Inst as MInst, MemArg,
UImm16Shifted, UImm32Shifted,
}; };
use crate::isa::s390x::settings::Flags as IsaFlags; use crate::isa::s390x::settings::Flags as IsaFlags;
use crate::machinst::isle::*; use crate::machinst::isle::*;
use crate::machinst::{MachLabel, Reg};
use crate::settings::Flags; use crate::settings::Flags;
use crate::{ use crate::{
ir::{ ir::{
condcodes::*, immediates::*, types::*, AtomicRmwOp, Endianness, Inst, InstructionData, condcodes::*, immediates::*, types::*, AtomicRmwOp, Endianness, Inst, InstructionData,
StackSlot, TrapCode, Value, ValueList, MemFlags, Opcode, StackSlot, TrapCode, Value, ValueList,
}, },
isa::unwind::UnwindInst, isa::unwind::UnwindInst,
machinst::{InsnOutput, LowerCtx, VCodeConstant, VCodeConstantData}, machinst::{InsnOutput, LowerCtx, VCodeConstant, VCodeConstantData},
@@ -150,12 +152,12 @@ where
#[inline] #[inline]
fn writable_gpr(&mut self, regno: u8) -> WritableReg { fn writable_gpr(&mut self, regno: u8) -> WritableReg {
super::writable_gpr(regno) writable_gpr(regno)
} }
#[inline] #[inline]
fn zero_reg(&mut self) -> Reg { fn zero_reg(&mut self) -> Reg {
super::zero_reg() zero_reg()
} }
#[inline] #[inline]
@@ -282,10 +284,7 @@ where
let inst = self.lower_ctx.dfg().value_def(val).inst()?; let inst = self.lower_ctx.dfg().value_def(val).inst()?;
let constant = self.lower_ctx.get_constant(inst)?; let constant = self.lower_ctx.get_constant(inst)?;
let ty = self.lower_ctx.output_ty(inst, 0); let ty = self.lower_ctx.output_ty(inst, 0);
Some(super::sign_extend_to_u64( Some(sign_extend_to_u64(constant, self.ty_bits(ty).unwrap()))
constant,
self.ty_bits(ty).unwrap(),
))
} }
#[inline] #[inline]
@@ -390,7 +389,7 @@ where
#[inline] #[inline]
fn signed(&mut self, cc: &IntCC) -> Option<()> { fn signed(&mut self, cc: &IntCC) -> Option<()> {
if super::condcode_is_signed(*cc) { if condcode_is_signed(*cc) {
Some(()) Some(())
} else { } else {
None None
@@ -399,7 +398,7 @@ where
#[inline] #[inline]
fn unsigned(&mut self, cc: &IntCC) -> Option<()> { fn unsigned(&mut self, cc: &IntCC) -> Option<()> {
if !super::condcode_is_signed(*cc) { if !condcode_is_signed(*cc) {
Some(()) Some(())
} else { } else {
None None
@@ -468,7 +467,7 @@ where
#[inline] #[inline]
fn memarg_stack_off(&mut self, base: i64, off: i64) -> MemArg { fn memarg_stack_off(&mut self, base: i64, off: i64) -> MemArg {
MemArg::reg_plus_off(super::stack_reg(), base + off, MemFlags::trusted()) MemArg::reg_plus_off(stack_reg(), base + off, MemFlags::trusted())
} }
#[inline] #[inline]
@@ -555,3 +554,36 @@ where
self.lower_ctx.emit(inst.clone()); self.lower_ctx.emit(inst.clone());
} }
} }
/// Sign-extend the low `from_bits` bits of `value` to a full u64.
#[inline]
fn sign_extend_to_u64(value: u64, from_bits: u8) -> u64 {
assert!(from_bits <= 64);
if from_bits >= 64 {
value
} else {
(((value << (64 - from_bits)) as i64) >> (64 - from_bits)) as u64
}
}
/// Determines whether this condcode interprets inputs as signed or
/// unsigned. See the documentation for the `icmp` instruction in
/// cranelift-codegen/meta/src/shared/instructions.rs for further insights
/// into this.
#[inline]
fn condcode_is_signed(cc: IntCC) -> bool {
match cc {
IntCC::Equal => false,
IntCC::NotEqual => false,
IntCC::SignedGreaterThanOrEqual => true,
IntCC::SignedGreaterThan => true,
IntCC::SignedLessThanOrEqual => true,
IntCC::SignedLessThan => true,
IntCC::UnsignedGreaterThanOrEqual => false,
IntCC::UnsignedGreaterThan => false,
IntCC::UnsignedLessThanOrEqual => false,
IntCC::UnsignedLessThan => false,
IntCC::Overflow => true,
IntCC::NotOverflow => true,
}
}