Merge pull request #1900 from cfallin/clarify-lowering-docs

MachInst isel and aarch64 backend: docs / clarity improvements.
This commit is contained in:
Chris Fallin
2020-06-23 09:59:07 -07:00
committed by GitHub
3 changed files with 163 additions and 159 deletions

View File

@@ -168,7 +168,7 @@ pub(crate) fn output_to_const_f128<C: LowerCtx<I = Inst>>(
} }
/// How to handle narrow values loaded into registers; see note on `narrow_mode` /// How to handle narrow values loaded into registers; see note on `narrow_mode`
/// parameter to `input_to_*` below. /// parameter to `put_input_in_*` below.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum NarrowValueMode { pub(crate) enum NarrowValueMode {
None, None,
@@ -193,7 +193,7 @@ impl NarrowValueMode {
} }
/// Allocate a register for an instruction output and return it. /// Allocate a register for an instruction output and return it.
pub(crate) fn output_to_reg<C: LowerCtx<I = Inst>>(ctx: &mut C, out: InsnOutput) -> Writable<Reg> { pub(crate) fn get_output_reg<C: LowerCtx<I = Inst>>(ctx: &mut C, out: InsnOutput) -> Writable<Reg> {
ctx.get_output(out.insn, out.output) ctx.get_output(out.insn, out.output)
} }
@@ -202,12 +202,12 @@ pub(crate) fn output_to_reg<C: LowerCtx<I = Inst>>(ctx: &mut C, out: InsnOutput)
/// The given register will be extended appropriately, according to /// The given register will be extended appropriately, according to
/// `narrow_mode` and the input's type. If extended, the value is /// `narrow_mode` and the input's type. If extended, the value is
/// always extended to 64 bits, for simplicity. /// always extended to 64 bits, for simplicity.
pub(crate) fn input_to_reg<C: LowerCtx<I = Inst>>( pub(crate) fn put_input_in_reg<C: LowerCtx<I = Inst>>(
ctx: &mut C, ctx: &mut C,
input: InsnInput, input: InsnInput,
narrow_mode: NarrowValueMode, narrow_mode: NarrowValueMode,
) -> Reg { ) -> Reg {
debug!("input_to_reg: input {:?}", input); debug!("put_input_in_reg: input {:?}", input);
let ty = ctx.input_ty(input.insn, input.input); let ty = ctx.input_ty(input.insn, input.input);
let from_bits = ty_bits(ty) as u8; let from_bits = ty_bits(ty) as u8;
let inputs = ctx.get_input(input.insn, input.input); let inputs = ctx.get_input(input.insn, input.input);
@@ -302,7 +302,7 @@ pub(crate) fn input_to_reg<C: LowerCtx<I = Inst>>(
/// divide or a right-shift or a compare-to-zero), `narrow_mode` should be /// divide or a right-shift or a compare-to-zero), `narrow_mode` should be
/// set to `ZeroExtend` or `SignExtend` as appropriate, and the resulting /// set to `ZeroExtend` or `SignExtend` as appropriate, and the resulting
/// register will be provided the extended value. /// register will be provided the extended value.
fn input_to_rs<C: LowerCtx<I = Inst>>( fn put_input_in_rs<C: LowerCtx<I = Inst>>(
ctx: &mut C, ctx: &mut C,
input: InsnInput, input: InsnInput,
narrow_mode: NarrowValueMode, narrow_mode: NarrowValueMode,
@@ -317,21 +317,21 @@ fn input_to_rs<C: LowerCtx<I = Inst>>(
// Can we get the shift amount as an immediate? // Can we get the shift amount as an immediate?
if let Some(shiftimm) = input_to_shiftimm(ctx, shift_amt) { if let Some(shiftimm) = input_to_shiftimm(ctx, shift_amt) {
let reg = input_to_reg(ctx, shiftee, narrow_mode); let reg = put_input_in_reg(ctx, shiftee, narrow_mode);
return ResultRS::RegShift(reg, ShiftOpAndAmt::new(ShiftOp::LSL, shiftimm)); return ResultRS::RegShift(reg, ShiftOpAndAmt::new(ShiftOp::LSL, shiftimm));
} }
} }
} }
ResultRS::Reg(input_to_reg(ctx, input, narrow_mode)) ResultRS::Reg(put_input_in_reg(ctx, input, narrow_mode))
} }
/// Lower an instruction input to a reg or reg/shift, or reg/extend operand. /// Lower an instruction input to a reg or reg/shift, or reg/extend operand.
/// This does not actually codegen the source instruction; it just uses the /// This does not actually codegen the source instruction; it just uses the
/// vreg into which the source instruction will generate its value. /// vreg into which the source instruction will generate its value.
/// ///
/// See note on `input_to_rs` for a description of `narrow_mode`. /// See note on `put_input_in_rs` for a description of `narrow_mode`.
fn input_to_rse<C: LowerCtx<I = Inst>>( fn put_input_in_rse<C: LowerCtx<I = Inst>>(
ctx: &mut C, ctx: &mut C,
input: InsnInput, input: InsnInput,
narrow_mode: NarrowValueMode, narrow_mode: NarrowValueMode,
@@ -349,7 +349,7 @@ fn input_to_rse<C: LowerCtx<I = Inst>>(
&& ((narrow_mode.is_32bit() && out_bits < 32) && ((narrow_mode.is_32bit() && out_bits < 32)
|| (!narrow_mode.is_32bit() && out_bits < 64)) || (!narrow_mode.is_32bit() && out_bits < 64))
{ {
let reg = input_to_reg(ctx, InsnInput { insn, input: 0 }, NarrowValueMode::None); let reg = put_input_in_reg(ctx, InsnInput { insn, input: 0 }, NarrowValueMode::None);
let extendop = match (narrow_mode, out_bits) { let extendop = match (narrow_mode, out_bits) {
(NarrowValueMode::SignExtend32, 1) | (NarrowValueMode::SignExtend64, 1) => { (NarrowValueMode::SignExtend32, 1) | (NarrowValueMode::SignExtend64, 1) => {
ExtendOp::SXTB ExtendOp::SXTB
@@ -394,15 +394,15 @@ fn input_to_rse<C: LowerCtx<I = Inst>>(
(false, 32) => ExtendOp::UXTW, (false, 32) => ExtendOp::UXTW,
_ => unreachable!(), _ => unreachable!(),
}; };
let reg = input_to_reg(ctx, InsnInput { insn, input: 0 }, NarrowValueMode::None); let reg = put_input_in_reg(ctx, InsnInput { insn, input: 0 }, NarrowValueMode::None);
return ResultRSE::RegExtend(reg, extendop); return ResultRSE::RegExtend(reg, extendop);
} }
} }
ResultRSE::from_rs(input_to_rs(ctx, input, narrow_mode)) ResultRSE::from_rs(put_input_in_rs(ctx, input, narrow_mode))
} }
pub(crate) fn input_to_rse_imm12<C: LowerCtx<I = Inst>>( pub(crate) fn put_input_in_rse_imm12<C: LowerCtx<I = Inst>>(
ctx: &mut C, ctx: &mut C,
input: InsnInput, input: InsnInput,
narrow_mode: NarrowValueMode, narrow_mode: NarrowValueMode,
@@ -413,10 +413,10 @@ pub(crate) fn input_to_rse_imm12<C: LowerCtx<I = Inst>>(
} }
} }
ResultRSEImm12::from_rse(input_to_rse(ctx, input, narrow_mode)) ResultRSEImm12::from_rse(put_input_in_rse(ctx, input, narrow_mode))
} }
pub(crate) fn input_to_rs_immlogic<C: LowerCtx<I = Inst>>( pub(crate) fn put_input_in_rs_immlogic<C: LowerCtx<I = Inst>>(
ctx: &mut C, ctx: &mut C,
input: InsnInput, input: InsnInput,
narrow_mode: NarrowValueMode, narrow_mode: NarrowValueMode,
@@ -429,10 +429,10 @@ pub(crate) fn input_to_rs_immlogic<C: LowerCtx<I = Inst>>(
} }
} }
ResultRSImmLogic::from_rs(input_to_rs(ctx, input, narrow_mode)) ResultRSImmLogic::from_rs(put_input_in_rs(ctx, input, narrow_mode))
} }
pub(crate) fn input_to_reg_immshift<C: LowerCtx<I = Inst>>( pub(crate) fn put_input_in_reg_immshift<C: LowerCtx<I = Inst>>(
ctx: &mut C, ctx: &mut C,
input: InsnInput, input: InsnInput,
) -> ResultRegImmShift { ) -> ResultRegImmShift {
@@ -442,7 +442,7 @@ pub(crate) fn input_to_reg_immshift<C: LowerCtx<I = Inst>>(
} }
} }
ResultRegImmShift::Reg(input_to_reg(ctx, input, NarrowValueMode::None)) ResultRegImmShift::Reg(put_input_in_reg(ctx, input, NarrowValueMode::None))
} }
//============================================================================ //============================================================================
@@ -546,7 +546,7 @@ pub(crate) fn lower_address<C: LowerCtx<I = Inst>>(
// Handle one reg and offset. // Handle one reg and offset.
if addends.len() == 1 { if addends.len() == 1 {
let reg = input_to_reg(ctx, addends[0], NarrowValueMode::ZeroExtend64); let reg = put_input_in_reg(ctx, addends[0], NarrowValueMode::ZeroExtend64);
return MemArg::RegOffset(reg, offset as i64, elem_ty); return MemArg::RegOffset(reg, offset as i64, elem_ty);
} }
@@ -560,9 +560,9 @@ pub(crate) fn lower_address<C: LowerCtx<I = Inst>>(
maybe_input_insn_multi(ctx, addends[i], &[Opcode::Uextend, Opcode::Sextend]) maybe_input_insn_multi(ctx, addends[i], &[Opcode::Uextend, Opcode::Sextend])
{ {
// Non-extended addend. // Non-extended addend.
let r1 = input_to_reg(ctx, addends[1 - i], NarrowValueMode::ZeroExtend64); let r1 = put_input_in_reg(ctx, addends[1 - i], NarrowValueMode::ZeroExtend64);
// Extended addend. // Extended addend.
let r2 = input_to_reg( let r2 = put_input_in_reg(
ctx, ctx,
InsnInput { InsnInput {
insn: ext_insn, insn: ext_insn,
@@ -596,8 +596,8 @@ pub(crate) fn lower_address<C: LowerCtx<I = Inst>>(
// Handle two regs and a zero offset in the general case, if possible. // Handle two regs and a zero offset in the general case, if possible.
if addends.len() == 2 && offset == 0 { if addends.len() == 2 && offset == 0 {
let ra = input_to_reg(ctx, addends[0], NarrowValueMode::ZeroExtend64); let ra = put_input_in_reg(ctx, addends[0], NarrowValueMode::ZeroExtend64);
let rb = input_to_reg(ctx, addends[1], NarrowValueMode::ZeroExtend64); let rb = put_input_in_reg(ctx, addends[1], NarrowValueMode::ZeroExtend64);
return MemArg::reg_plus_reg(ra, rb); return MemArg::reg_plus_reg(ra, rb);
} }
@@ -609,7 +609,7 @@ pub(crate) fn lower_address<C: LowerCtx<I = Inst>>(
// Add each addend to the address. // Add each addend to the address.
for addend in addends { for addend in addends {
let reg = input_to_reg(ctx, *addend, NarrowValueMode::ZeroExtend64); let reg = put_input_in_reg(ctx, *addend, NarrowValueMode::ZeroExtend64);
// In an addition, the stack register is the zero register, so divert it to another // In an addition, the stack register is the zero register, so divert it to another
// register just before doing the actual add. // register just before doing the actual add.
@@ -997,8 +997,8 @@ pub(crate) fn lower_icmp_or_ifcmp_to_flags<C: LowerCtx<I = Inst>>(
}, },
]; ];
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rm = input_to_rse_imm12(ctx, inputs[1], narrow_mode); let rm = put_input_in_rse_imm12(ctx, inputs[1], narrow_mode);
debug!("lower_icmp_or_ifcmp_to_flags: rn = {:?} rm = {:?}", rn, rm); debug!("lower_icmp_or_ifcmp_to_flags: rn = {:?} rm = {:?}", rn, rm);
let alu_op = choose_32_64(ty, ALUOp::SubS32, ALUOp::SubS64); let alu_op = choose_32_64(ty, ALUOp::SubS32, ALUOp::SubS64);
let rd = writable_zero_reg(); let rd = writable_zero_reg();
@@ -1018,8 +1018,8 @@ pub(crate) fn lower_fcmp_or_ffcmp_to_flags<C: LowerCtx<I = Inst>>(ctx: &mut C, i
input: 1, input: 1,
}, },
]; ];
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
match bits { match bits {
32 => { 32 => {
ctx.emit(Inst::FpuCmp32 { rn, rm }); ctx.emit(Inst::FpuCmp32 { rn, rm });

View File

@@ -42,31 +42,31 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
match op { match op {
Opcode::Iconst | Opcode::Bconst | Opcode::Null => { Opcode::Iconst | Opcode::Bconst | Opcode::Null => {
let value = ctx.get_constant(insn).unwrap(); let value = ctx.get_constant(insn).unwrap();
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
lower_constant_u64(ctx, rd, value); lower_constant_u64(ctx, rd, value);
} }
Opcode::F32const => { Opcode::F32const => {
let value = f32::from_bits(ctx.get_constant(insn).unwrap() as u32); let value = f32::from_bits(ctx.get_constant(insn).unwrap() as u32);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
lower_constant_f32(ctx, rd, value); lower_constant_f32(ctx, rd, value);
} }
Opcode::F64const => { Opcode::F64const => {
let value = f64::from_bits(ctx.get_constant(insn).unwrap()); let value = f64::from_bits(ctx.get_constant(insn).unwrap());
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
lower_constant_f64(ctx, rd, value); lower_constant_f64(ctx, rd, value);
} }
Opcode::Iadd => { Opcode::Iadd => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_rse_imm12(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_rse_imm12(ctx, inputs[1], NarrowValueMode::None);
let ty = ty.unwrap(); let ty = ty.unwrap();
let alu_op = choose_32_64(ty, ALUOp::Add32, ALUOp::Add64); let alu_op = choose_32_64(ty, ALUOp::Add32, ALUOp::Add64);
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm)); ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
} }
Opcode::Isub => { Opcode::Isub => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_rse_imm12(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_rse_imm12(ctx, inputs[1], NarrowValueMode::None);
let ty = ty.unwrap(); let ty = ty.unwrap();
let alu_op = choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64); let alu_op = choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64);
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm)); ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
@@ -87,9 +87,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}; };
let va = ctx.alloc_tmp(RegClass::V128, I128); let va = ctx.alloc_tmp(RegClass::V128, I128);
let vb = ctx.alloc_tmp(RegClass::V128, I128); let vb = ctx.alloc_tmp(RegClass::V128, I128);
let ra = input_to_reg(ctx, inputs[0], narrow_mode); let ra = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rb = input_to_reg(ctx, inputs[1], narrow_mode); let rb = put_input_in_reg(ctx, inputs[1], narrow_mode);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::MovToVec64 { rd: va, rn: ra }); ctx.emit(Inst::MovToVec64 { rd: va, rn: ra });
ctx.emit(Inst::MovToVec64 { rd: vb, rn: rb }); ctx.emit(Inst::MovToVec64 { rd: vb, rn: rb });
ctx.emit(Inst::VecRRR { ctx.emit(Inst::VecRRR {
@@ -121,9 +121,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}; };
let va = ctx.alloc_tmp(RegClass::V128, I128); let va = ctx.alloc_tmp(RegClass::V128, I128);
let vb = ctx.alloc_tmp(RegClass::V128, I128); let vb = ctx.alloc_tmp(RegClass::V128, I128);
let ra = input_to_reg(ctx, inputs[0], narrow_mode); let ra = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rb = input_to_reg(ctx, inputs[1], narrow_mode); let rb = put_input_in_reg(ctx, inputs[1], narrow_mode);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::MovToVec64 { rd: va, rn: ra }); ctx.emit(Inst::MovToVec64 { rd: va, rn: ra });
ctx.emit(Inst::MovToVec64 { rd: vb, rn: rb }); ctx.emit(Inst::MovToVec64 { rd: vb, rn: rb });
ctx.emit(Inst::VecRRR { ctx.emit(Inst::VecRRR {
@@ -142,18 +142,18 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Ineg => { Opcode::Ineg => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = zero_reg(); let rn = zero_reg();
let rm = input_to_rse_imm12(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_rse_imm12(ctx, inputs[0], NarrowValueMode::None);
let ty = ty.unwrap(); let ty = ty.unwrap();
let alu_op = choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64); let alu_op = choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64);
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm)); ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
} }
Opcode::Imul => { Opcode::Imul => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let ty = ty.unwrap(); let ty = ty.unwrap();
let alu_op = choose_32_64(ty, ALUOp::MAdd32, ALUOp::MAdd64); let alu_op = choose_32_64(ty, ALUOp::MAdd32, ALUOp::MAdd64);
ctx.emit(Inst::AluRRRR { ctx.emit(Inst::AluRRRR {
@@ -166,7 +166,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Umulhi | Opcode::Smulhi => { Opcode::Umulhi | Opcode::Smulhi => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let is_signed = op == Opcode::Smulhi; let is_signed = op == Opcode::Smulhi;
let input_ty = ctx.input_ty(insn, 0); let input_ty = ctx.input_ty(insn, 0);
assert!(ctx.input_ty(insn, 1) == input_ty); assert!(ctx.input_ty(insn, 1) == input_ty);
@@ -174,8 +174,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
match input_ty { match input_ty {
I64 => { I64 => {
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let ra = zero_reg(); let ra = zero_reg();
let alu_op = if is_signed { let alu_op = if is_signed {
ALUOp::SMulH ALUOp::SMulH
@@ -196,8 +196,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} else { } else {
NarrowValueMode::ZeroExtend64 NarrowValueMode::ZeroExtend64
}; };
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rm = input_to_reg(ctx, inputs[1], narrow_mode); let rm = put_input_in_reg(ctx, inputs[1], narrow_mode);
let ra = zero_reg(); let ra = zero_reg();
ctx.emit(Inst::AluRRRR { ctx.emit(Inst::AluRRRR {
alu_op: ALUOp::MAdd64, alu_op: ALUOp::MAdd64,
@@ -254,9 +254,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
ALUOp::UDiv64 ALUOp::UDiv64
}; };
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rm = input_to_reg(ctx, inputs[1], narrow_mode); let rm = put_input_in_reg(ctx, inputs[1], narrow_mode);
// The div instruction does not trap on divide by zero or signed overflow // The div instruction does not trap on divide by zero or signed overflow
// so checks are inserted below. // so checks are inserted below.
// //
@@ -372,8 +372,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// If we reach this point, we weren't able to incorporate the extend as // If we reach this point, we weren't able to incorporate the extend as
// a register-mode on another instruction, so we have a 'None' // a register-mode on another instruction, so we have a 'None'
// narrow-value/extend mode here, and we emit the explicit instruction. // narrow-value/extend mode here, and we emit the explicit instruction.
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::Extend { ctx.emit(Inst::Extend {
rd, rd,
rn, rn,
@@ -385,15 +385,15 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Bnot => { Opcode::Bnot => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ty = ty.unwrap(); let ty = ty.unwrap();
if ty_bits(ty) < 128 { if ty_bits(ty) < 128 {
let rm = input_to_rs_immlogic(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_rs_immlogic(ctx, inputs[0], NarrowValueMode::None);
let alu_op = choose_32_64(ty, ALUOp::OrrNot32, ALUOp::OrrNot64); let alu_op = choose_32_64(ty, ALUOp::OrrNot32, ALUOp::OrrNot64);
// NOT rd, rm ==> ORR_NOT rd, zero, rm // NOT rd, rm ==> ORR_NOT rd, zero, rm
ctx.emit(alu_inst_immlogic(alu_op, rd, zero_reg(), rm)); ctx.emit(alu_inst_immlogic(alu_op, rd, zero_reg(), rm));
} else { } else {
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
ctx.emit(Inst::VecMisc { ctx.emit(Inst::VecMisc {
op: VecMisc2::Not, op: VecMisc2::Not,
rd, rd,
@@ -409,11 +409,11 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
| Opcode::BandNot | Opcode::BandNot
| Opcode::BorNot | Opcode::BorNot
| Opcode::BxorNot => { | Opcode::BxorNot => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ty = ty.unwrap(); let ty = ty.unwrap();
if ty_bits(ty) < 128 { if ty_bits(ty) < 128 {
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_rs_immlogic(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_rs_immlogic(ctx, inputs[1], NarrowValueMode::None);
let alu_op = match op { let alu_op = match op {
Opcode::Band => choose_32_64(ty, ALUOp::And32, ALUOp::And64), Opcode::Band => choose_32_64(ty, ALUOp::And32, ALUOp::And64),
Opcode::Bor => choose_32_64(ty, ALUOp::Orr32, ALUOp::Orr64), Opcode::Bor => choose_32_64(ty, ALUOp::Orr32, ALUOp::Orr64),
@@ -433,9 +433,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
_ => unreachable!(), _ => unreachable!(),
}; };
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::VecRRR { ctx.emit(Inst::VecRRR {
alu_op, alu_op,
@@ -458,9 +458,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(Opcode::Sshr, InstSize::Size32) => NarrowValueMode::SignExtend32, (Opcode::Sshr, InstSize::Size32) => NarrowValueMode::SignExtend32,
_ => unreachable!(), _ => unreachable!(),
}; };
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rm = input_to_reg_immshift(ctx, inputs[1]); let rm = put_input_in_reg_immshift(ctx, inputs[1]);
let alu_op = match op { let alu_op = match op {
Opcode::Ishl => choose_32_64(ty, ALUOp::Lsl32, ALUOp::Lsl64), Opcode::Ishl => choose_32_64(ty, ALUOp::Lsl32, ALUOp::Lsl64),
Opcode::Ushr => choose_32_64(ty, ALUOp::Lsr32, ALUOp::Lsr64), Opcode::Ushr => choose_32_64(ty, ALUOp::Lsr32, ALUOp::Lsr64),
@@ -503,8 +503,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let ty = ty.unwrap(); let ty = ty.unwrap();
let ty_bits_size = ty_bits(ty) as u8; let ty_bits_size = ty_bits(ty) as u8;
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg( let rn = put_input_in_reg(
ctx, ctx,
inputs[0], inputs[0],
if ty_bits_size <= 32 { if ty_bits_size <= 32 {
@@ -513,7 +513,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
NarrowValueMode::ZeroExtend64 NarrowValueMode::ZeroExtend64
}, },
); );
let rm = input_to_reg_immshift(ctx, inputs[1]); let rm = put_input_in_reg_immshift(ctx, inputs[1]);
if ty_bits_size == 32 || ty_bits_size == 64 { if ty_bits_size == 32 || ty_bits_size == 64 {
let alu_op = choose_32_64(ty, ALUOp::RotR32, ALUOp::RotR64); let alu_op = choose_32_64(ty, ALUOp::RotR32, ALUOp::RotR64);
@@ -652,7 +652,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Bitrev | Opcode::Clz | Opcode::Cls | Opcode::Ctz => { Opcode::Bitrev | Opcode::Clz | Opcode::Cls | Opcode::Ctz => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let needs_zext = match op { let needs_zext = match op {
Opcode::Bitrev | Opcode::Ctz => false, Opcode::Bitrev | Opcode::Ctz => false,
Opcode::Clz | Opcode::Cls => true, Opcode::Clz | Opcode::Cls => true,
@@ -666,7 +666,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} else { } else {
NarrowValueMode::None NarrowValueMode::None
}; };
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let op_ty = match ty { let op_ty = match ty {
I8 | I16 | I32 => I32, I8 | I16 | I32 => I32,
I64 => I64, I64 => I64,
@@ -722,11 +722,11 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// x += x << 32 // x += x << 32
// x >> 56 // x >> 56
let ty = ty.unwrap(); let ty = ty.unwrap();
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
// FIXME(#1537): zero-extend 8/16/32-bit operands only to 32 bits, // FIXME(#1537): zero-extend 8/16/32-bit operands only to 32 bits,
// and fix the sequence below to work properly for this. // and fix the sequence below to work properly for this.
let narrow_mode = NarrowValueMode::ZeroExtend64; let narrow_mode = NarrowValueMode::ZeroExtend64;
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let tmp = ctx.alloc_tmp(RegClass::I64, I64); let tmp = ctx.alloc_tmp(RegClass::I64, I64);
// If this is a 32-bit Popcnt, use Lsr32 to clear the top 32 bits of the register, then // If this is a 32-bit Popcnt, use Lsr32 to clear the top 32 bits of the register, then
@@ -903,7 +903,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let is_float = ty_is_float(elem_ty); let is_float = ty_is_float(elem_ty);
let mem = lower_address(ctx, elem_ty, &inputs[..], off); let mem = lower_address(ctx, elem_ty, &inputs[..], off);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let memflags = ctx.memflags(insn).expect("memory flags"); let memflags = ctx.memflags(insn).expect("memory flags");
let srcloc = if !memflags.notrap() { let srcloc = if !memflags.notrap() {
@@ -967,7 +967,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let is_float = ty_is_float(elem_ty); let is_float = ty_is_float(elem_ty);
let mem = lower_address(ctx, elem_ty, &inputs[1..], off); let mem = lower_address(ctx, elem_ty, &inputs[1..], off);
let rd = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rd = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let memflags = ctx.memflags(insn).expect("memory flags"); let memflags = ctx.memflags(insn).expect("memory flags");
let srcloc = if !memflags.notrap() { let srcloc = if !memflags.notrap() {
@@ -997,7 +997,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} => (stack_slot, offset), } => (stack_slot, offset),
_ => unreachable!(), _ => unreachable!(),
}; };
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let offset: i32 = offset.into(); let offset: i32 = offset.into();
let inst = ctx let inst = ctx
.abi() .abi()
@@ -1031,7 +1031,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(ALUOp::SubS32, NarrowValueMode::ZeroExtend32) (ALUOp::SubS32, NarrowValueMode::ZeroExtend32)
}; };
let rcond = input_to_reg(ctx, inputs[0], narrow_mode); let rcond = put_input_in_reg(ctx, inputs[0], narrow_mode);
// cmp rcond, #0 // cmp rcond, #0
ctx.emit(Inst::AluRRR { ctx.emit(Inst::AluRRR {
alu_op: cmp_op, alu_op: cmp_op,
@@ -1052,9 +1052,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
}; };
// csel.COND rd, rn, rm // csel.COND rd, rn, rm
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[2], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[2], NarrowValueMode::None);
let ty = ctx.output_ty(insn, 0); let ty = ctx.output_ty(insn, 0);
let bits = ty_bits(ty); let bits = ty_bits(ty);
if ty_is_float(ty) && bits == 32 { if ty_is_float(ty) && bits == 32 {
@@ -1070,10 +1070,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let ty = ty.unwrap(); let ty = ty.unwrap();
if ty_bits(ty) < 128 { if ty_bits(ty) < 128 {
let tmp = ctx.alloc_tmp(RegClass::I64, I64); let tmp = ctx.alloc_tmp(RegClass::I64, I64);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rcond = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rcond = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rn = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[2], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[2], NarrowValueMode::None);
// AND rTmp, rn, rcond // AND rTmp, rn, rcond
ctx.emit(Inst::AluRRR { ctx.emit(Inst::AluRRR {
alu_op: ALUOp::And64, alu_op: ALUOp::And64,
@@ -1096,10 +1096,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
rm: tmp.to_reg(), rm: tmp.to_reg(),
}); });
} else { } else {
let rcond = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rcond = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rn = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[2], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[2], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::gen_move(rd, rcond, ty)); ctx.emit(Inst::gen_move(rd, rcond, ty));
ctx.emit(Inst::VecRRR { ctx.emit(Inst::VecRRR {
@@ -1120,7 +1120,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// single-def ifcmp. // single-def ifcmp.
let ifcmp_insn = maybe_input_insn(ctx, inputs[0], Opcode::Ifcmp).unwrap(); let ifcmp_insn = maybe_input_insn(ctx, inputs[0], Opcode::Ifcmp).unwrap();
lower_icmp_or_ifcmp_to_flags(ctx, ifcmp_insn, is_signed); lower_icmp_or_ifcmp_to_flags(ctx, ifcmp_insn, is_signed);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::CSet { rd, cond }); ctx.emit(Inst::CSet { rd, cond });
} }
@@ -1129,7 +1129,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let cond = lower_fp_condcode(condcode); let cond = lower_fp_condcode(condcode);
let ffcmp_insn = maybe_input_insn(ctx, inputs[0], Opcode::Ffcmp).unwrap(); let ffcmp_insn = maybe_input_insn(ctx, inputs[0], Opcode::Ffcmp).unwrap();
lower_fcmp_or_ffcmp_to_flags(ctx, ffcmp_insn); lower_fcmp_or_ffcmp_to_flags(ctx, ffcmp_insn);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::CSet { rd, cond }); ctx.emit(Inst::CSet { rd, cond });
} }
@@ -1138,8 +1138,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Copy => { Opcode::Copy => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
ctx.emit(Inst::gen_move(rd, rn, ty)); ctx.emit(Inst::gen_move(rd, rn, ty));
} }
@@ -1157,16 +1157,16 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// - Ireduce: changing width of an integer. Smaller ints are stored // - Ireduce: changing width of an integer. Smaller ints are stored
// with undefined high-order bits, so we can simply do a copy. // with undefined high-order bits, so we can simply do a copy.
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
ctx.emit(Inst::gen_move(rd, rn, ty)); ctx.emit(Inst::gen_move(rd, rn, ty));
} }
Opcode::Bmask => { Opcode::Bmask => {
// Bool is {0, 1}, so we can subtract from 0 to get all-1s. // Bool is {0, 1}, so we can subtract from 0 to get all-1s.
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64); let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);
ctx.emit(Inst::AluRRR { ctx.emit(Inst::AluRRR {
alu_op: ALUOp::Sub64, alu_op: ALUOp::Sub64,
rd, rd,
@@ -1176,7 +1176,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Bitcast => { Opcode::Bitcast => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ity = ctx.input_ty(insn, 0); let ity = ctx.input_ty(insn, 0);
let oty = ctx.output_ty(insn, 0); let oty = ctx.output_ty(insn, 0);
match (ty_is_float(ity), ty_is_float(oty)) { match (ty_is_float(ity), ty_is_float(oty)) {
@@ -1186,19 +1186,19 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} else { } else {
NarrowValueMode::ZeroExtend64 NarrowValueMode::ZeroExtend64
}; };
let rm = input_to_reg(ctx, inputs[0], narrow_mode); let rm = put_input_in_reg(ctx, inputs[0], narrow_mode);
ctx.emit(Inst::gen_move(rd, rm, oty)); ctx.emit(Inst::gen_move(rd, rm, oty));
} }
(false, false) => { (false, false) => {
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
ctx.emit(Inst::gen_move(rd, rm, oty)); ctx.emit(Inst::gen_move(rd, rm, oty));
} }
(false, true) => { (false, true) => {
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);
ctx.emit(Inst::MovToVec64 { rd, rn }); ctx.emit(Inst::MovToVec64 { rd, rn });
} }
(true, false) => { (true, false) => {
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
ctx.emit(Inst::MovFromVec { ctx.emit(Inst::MovFromVec {
rd, rd,
rn, rn,
@@ -1214,7 +1214,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// N.B.: according to the AArch64 ABI, the top bits of a register // N.B.: according to the AArch64 ABI, the top bits of a register
// (above the bits for the value's type) are undefined, so we // (above the bits for the value's type) are undefined, so we
// need not extend the return values. // need not extend the return values.
let reg = input_to_reg(ctx, *input, NarrowValueMode::None); let reg = put_input_in_reg(ctx, *input, NarrowValueMode::None);
let retval_reg = ctx.retval(i); let retval_reg = ctx.retval(i);
let ty = ctx.input_ty(insn, i); let ty = ctx.input_ty(insn, i);
ctx.emit(Inst::gen_move(retval_reg, reg, ty)); ctx.emit(Inst::gen_move(retval_reg, reg, ty));
@@ -1234,7 +1234,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let condcode = inst_condcode(ctx.data(insn)).unwrap(); let condcode = inst_condcode(ctx.data(insn)).unwrap();
let cond = lower_condcode(condcode); let cond = lower_condcode(condcode);
let is_signed = condcode_is_signed(condcode); let is_signed = condcode_is_signed(condcode);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
let bits = ty_bits(ty); let bits = ty_bits(ty);
let narrow_mode = match (bits <= 32, is_signed) { let narrow_mode = match (bits <= 32, is_signed) {
@@ -1243,15 +1243,15 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(false, true) => NarrowValueMode::SignExtend64, (false, true) => NarrowValueMode::SignExtend64,
(false, false) => NarrowValueMode::ZeroExtend64, (false, false) => NarrowValueMode::ZeroExtend64,
}; };
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
if ty_bits(ty) < 128 { if ty_bits(ty) < 128 {
let alu_op = choose_32_64(ty, ALUOp::SubS32, ALUOp::SubS64); let alu_op = choose_32_64(ty, ALUOp::SubS32, ALUOp::SubS64);
let rm = input_to_rse_imm12(ctx, inputs[1], narrow_mode); let rm = put_input_in_rse_imm12(ctx, inputs[1], narrow_mode);
ctx.emit(alu_inst_imm12(alu_op, writable_zero_reg(), rn, rm)); ctx.emit(alu_inst_imm12(alu_op, writable_zero_reg(), rn, rm));
ctx.emit(Inst::CondSet { cond, rd }); ctx.emit(Inst::CondSet { cond, rd });
} else { } else {
let rm = input_to_reg(ctx, inputs[1], narrow_mode); let rm = put_input_in_reg(ctx, inputs[1], narrow_mode);
lower_vector_compare(ctx, rd, rn, rm, ty, cond)?; lower_vector_compare(ctx, rd, rn, rm, ty, cond)?;
} }
} }
@@ -1260,9 +1260,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let condcode = inst_fp_condcode(ctx.data(insn)).unwrap(); let condcode = inst_fp_condcode(ctx.data(insn)).unwrap();
let cond = lower_fp_condcode(condcode); let cond = lower_fp_condcode(condcode);
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
if ty_bits(ty) < 128 { if ty_bits(ty) < 128 {
match ty_bits(ty) { match ty_bits(ty) {
@@ -1344,7 +1344,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::FuncAddr => { Opcode::FuncAddr => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let (extname, _) = ctx.call_target(insn).unwrap(); let (extname, _) = ctx.call_target(insn).unwrap();
let extname = extname.clone(); let extname = extname.clone();
let loc = ctx.srcloc(insn); let loc = ctx.srcloc(insn);
@@ -1361,7 +1361,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::SymbolValue => { Opcode::SymbolValue => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let (extname, _, offset) = ctx.symbol_value(insn).unwrap(); let (extname, _, offset) = ctx.symbol_value(insn).unwrap();
let extname = extname.clone(); let extname = extname.clone();
let loc = ctx.srcloc(insn); let loc = ctx.srcloc(insn);
@@ -1388,7 +1388,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
) )
} }
Opcode::CallIndirect => { Opcode::CallIndirect => {
let ptr = input_to_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64); let ptr = put_input_in_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);
let sig = ctx.call_sig(insn).unwrap(); let sig = ctx.call_sig(insn).unwrap();
assert!(inputs.len() - 1 == sig.params.len()); assert!(inputs.len() - 1 == sig.params.len());
assert!(outputs.len() == sig.returns.len()); assert!(outputs.len() == sig.returns.len());
@@ -1400,24 +1400,24 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
abi.emit_stack_pre_adjust(ctx); abi.emit_stack_pre_adjust(ctx);
assert!(inputs.len() == abi.num_args()); assert!(inputs.len() == abi.num_args());
for (i, input) in inputs.iter().enumerate() { for (i, input) in inputs.iter().enumerate() {
let arg_reg = input_to_reg(ctx, *input, NarrowValueMode::None); let arg_reg = put_input_in_reg(ctx, *input, NarrowValueMode::None);
abi.emit_copy_reg_to_arg(ctx, i, arg_reg); abi.emit_copy_reg_to_arg(ctx, i, arg_reg);
} }
abi.emit_call(ctx); abi.emit_call(ctx);
for (i, output) in outputs.iter().enumerate() { for (i, output) in outputs.iter().enumerate() {
let retval_reg = output_to_reg(ctx, *output); let retval_reg = get_output_reg(ctx, *output);
abi.emit_copy_retval_to_reg(ctx, i, retval_reg); abi.emit_copy_retval_to_reg(ctx, i, retval_reg);
} }
abi.emit_stack_post_adjust(ctx); abi.emit_stack_post_adjust(ctx);
} }
Opcode::GetPinnedReg => { Opcode::GetPinnedReg => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::mov(rd, xreg(PINNED_REG))); ctx.emit(Inst::mov(rd, xreg(PINNED_REG)));
} }
Opcode::SetPinnedReg => { Opcode::SetPinnedReg => {
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
ctx.emit(Inst::mov(writable_xreg(PINNED_REG), rm)); ctx.emit(Inst::mov(writable_xreg(PINNED_REG), rm));
} }
@@ -1451,13 +1451,13 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
Opcode::Vconst => { Opcode::Vconst => {
let value = output_to_const_f128(ctx, outputs[0]).unwrap(); let value = output_to_const_f128(ctx, outputs[0]).unwrap();
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
lower_constant_f128(ctx, rd, value); lower_constant_f128(ctx, rd, value);
} }
Opcode::RawBitcast => { Opcode::RawBitcast => {
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
ctx.emit(Inst::gen_move(rd, rm, ty)); ctx.emit(Inst::gen_move(rd, rm, ty));
} }
@@ -1465,8 +1465,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
Opcode::Extractlane => { Opcode::Extractlane => {
if let InstructionData::BinaryImm8 { imm, .. } = ctx.data(insn) { if let InstructionData::BinaryImm8 { imm, .. } = ctx.data(insn) {
let idx = *imm; let idx = *imm;
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let ty = ty.unwrap(); let ty = ty.unwrap();
if ty_is_int(ty) { if ty_is_int(ty) {
@@ -1483,8 +1483,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::Splat => { Opcode::Splat => {
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let ty = ctx.input_ty(insn, 0); let ty = ctx.input_ty(insn, 0);
let inst = if ty_is_int(ty) { let inst = if ty_is_int(ty) {
Inst::VecDup { rd, rn, ty } Inst::VecDup { rd, rn, ty }
@@ -1495,8 +1495,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
Opcode::VanyTrue | Opcode::VallTrue => { Opcode::VanyTrue | Opcode::VallTrue => {
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let tmp = ctx.alloc_tmp(RegClass::V128, ty.unwrap()); let tmp = ctx.alloc_tmp(RegClass::V128, ty.unwrap());
// This operation is implemented by using umaxp or uminv to // This operation is implemented by using umaxp or uminv to
@@ -1581,9 +1581,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(Opcode::Fmax, 64) => FPUOp2::Max64, (Opcode::Fmax, 64) => FPUOp2::Max64,
_ => panic!("Unknown op/bits combination"), _ => panic!("Unknown op/bits combination"),
}; };
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::FpuRRR { fpu_op, rd, rn, rm }); ctx.emit(Inst::FpuRRR { fpu_op, rd, rn, rm });
} }
@@ -1602,8 +1602,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(Opcode::Fdemote, 64) => panic!("Cannot demote to 64 bits"), (Opcode::Fdemote, 64) => panic!("Cannot demote to 64 bits"),
_ => panic!("Unknown op/bits combination"), _ => panic!("Unknown op/bits combination"),
}; };
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::FpuRR { fpu_op, rd, rn }); ctx.emit(Inst::FpuRR { fpu_op, rd, rn });
} }
@@ -1620,8 +1620,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(Opcode::Nearest, 64) => FpuRoundMode::Nearest64, (Opcode::Nearest, 64) => FpuRoundMode::Nearest64,
_ => panic!("Unknown op/bits combination"), _ => panic!("Unknown op/bits combination"),
}; };
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::FpuRound { op, rd, rn }); ctx.emit(Inst::FpuRound { op, rd, rn });
} }
@@ -1632,10 +1632,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
64 => FPUOp3::MAdd64, 64 => FPUOp3::MAdd64,
_ => panic!("Unknown op size"), _ => panic!("Unknown op size"),
}; };
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let ra = input_to_reg(ctx, inputs[2], NarrowValueMode::None); let ra = put_input_in_reg(ctx, inputs[2], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::FpuRRRR { ctx.emit(Inst::FpuRRRR {
fpu_op, fpu_op,
rn, rn,
@@ -1658,9 +1658,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let ty = ctx.output_ty(insn, 0); let ty = ctx.output_ty(insn, 0);
let bits = ty_bits(ty) as u8; let bits = ty_bits(ty) as u8;
assert!(bits == 32 || bits == 64); assert!(bits == 32 || bits == 64);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_reg(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let tmp = ctx.alloc_tmp(RegClass::V128, F64); let tmp = ctx.alloc_tmp(RegClass::V128, F64);
// Copy LHS to rd. // Copy LHS to rd.
@@ -1699,8 +1699,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
_ => panic!("Unknown input/output-bits combination"), _ => panic!("Unknown input/output-bits combination"),
}; };
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
// First, check the output: it's important to carry the NaN conversion before the // First, check the output: it's important to carry the NaN conversion before the
// in-bounds conversion, per wasm semantics. // in-bounds conversion, per wasm semantics.
@@ -1842,8 +1842,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
(true, 64) => NarrowValueMode::SignExtend64, (true, 64) => NarrowValueMode::SignExtend64,
_ => panic!("Unknown input size"), _ => panic!("Unknown input size"),
}; };
let rn = input_to_reg(ctx, inputs[0], narrow_mode); let rn = put_input_in_reg(ctx, inputs[0], narrow_mode);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
ctx.emit(Inst::IntToFpu { op, rd, rn }); ctx.emit(Inst::IntToFpu { op, rd, rn });
} }
@@ -1853,8 +1853,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let out_ty = ctx.output_ty(insn, 0); let out_ty = ctx.output_ty(insn, 0);
let out_bits = ty_bits(out_ty); let out_bits = ty_bits(out_ty);
let out_signed = op == Opcode::FcvtToSintSat; let out_signed = op == Opcode::FcvtToSintSat;
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
// FIMM Vtmp1, u32::MAX or u64::MAX or i32::MAX or i64::MAX // FIMM Vtmp1, u32::MAX or u64::MAX or i32::MAX or i64::MAX
// FMIN Vtmp2, Vin, Vtmp1 // FMIN Vtmp2, Vin, Vtmp1
@@ -1991,9 +1991,9 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
// Now handle the iadd as above, except use an AddS opcode that sets // Now handle the iadd as above, except use an AddS opcode that sets
// flags. // flags.
let rd = output_to_reg(ctx, outputs[0]); let rd = get_output_reg(ctx, outputs[0]);
let rn = input_to_reg(ctx, inputs[0], NarrowValueMode::None); let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
let rm = input_to_rse_imm12(ctx, inputs[1], NarrowValueMode::None); let rm = put_input_in_rse_imm12(ctx, inputs[1], NarrowValueMode::None);
let ty = ty.unwrap(); let ty = ty.unwrap();
let alu_op = choose_32_64(ty, ALUOp::AddS32, ALUOp::AddS64); let alu_op = choose_32_64(ty, ALUOp::AddS32, ALUOp::AddS64);
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm)); ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
@@ -2139,7 +2139,7 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
kind: CondBrKind::Cond(cond), kind: CondBrKind::Cond(cond),
}); });
} else { } else {
let rt = input_to_reg( let rt = put_input_in_reg(
ctx, ctx,
InsnInput { InsnInput {
insn: branches[0], insn: branches[0],
@@ -2173,7 +2173,7 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
(false, true) => NarrowValueMode::SignExtend64, (false, true) => NarrowValueMode::SignExtend64,
(false, false) => NarrowValueMode::ZeroExtend64, (false, false) => NarrowValueMode::ZeroExtend64,
}; };
let rn = input_to_reg( let rn = put_input_in_reg(
ctx, ctx,
InsnInput { InsnInput {
insn: branches[0], insn: branches[0],
@@ -2181,7 +2181,7 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
}, },
narrow_mode, narrow_mode,
); );
let rm = input_to_rse_imm12( let rm = put_input_in_rse_imm12(
ctx, ctx,
InsnInput { InsnInput {
insn: branches[0], insn: branches[0],
@@ -2220,7 +2220,7 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
} else { } else {
// If the ifcmp result is actually placed in a // If the ifcmp result is actually placed in a
// register, we need to move it back into the flags. // register, we need to move it back into the flags.
let rn = input_to_reg(ctx, flag_input, NarrowValueMode::None); let rn = put_input_in_reg(ctx, flag_input, NarrowValueMode::None);
ctx.emit(Inst::MovToNZCV { rn }); ctx.emit(Inst::MovToNZCV { rn });
ctx.emit(Inst::CondBr { ctx.emit(Inst::CondBr {
taken, taken,
@@ -2248,7 +2248,7 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
} else { } else {
// If the ffcmp result is actually placed in a // If the ffcmp result is actually placed in a
// register, we need to move it back into the flags. // register, we need to move it back into the flags.
let rn = input_to_reg(ctx, flag_input, NarrowValueMode::None); let rn = put_input_in_reg(ctx, flag_input, NarrowValueMode::None);
ctx.emit(Inst::MovToNZCV { rn }); ctx.emit(Inst::MovToNZCV { rn });
ctx.emit(Inst::CondBr { ctx.emit(Inst::CondBr {
taken, taken,
@@ -2294,7 +2294,7 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
needed_space: 4 * (6 + jt_size) as CodeOffset, needed_space: 4 * (6 + jt_size) as CodeOffset,
}); });
let ridx = input_to_reg( let ridx = put_input_in_reg(
ctx, ctx,
InsnInput { InsnInput {
insn: branches[0], insn: branches[0],

View File

@@ -132,7 +132,11 @@ pub trait LowerCtx {
fn get_input(&self, ir_inst: Inst, idx: usize) -> LowerInput; fn get_input(&self, ir_inst: Inst, idx: usize) -> LowerInput;
/// Get the `idx`th output register of the given IR instruction. When /// Get the `idx`th output register of the given IR instruction. When
/// `backend.lower_inst_to_regs(ctx, inst)` is called, it is expected that /// `backend.lower_inst_to_regs(ctx, inst)` is called, it is expected that
/// the backend will write results to these output register(s). /// the backend will write results to these output register(s). This
/// register will always be "fresh"; it is guaranteed not to overlap with
/// any of the inputs, and can be freely used as a scratch register within
/// the lowered instruction sequence, as long as its final value is the
/// result of the computation.
fn get_output(&self, ir_inst: Inst, idx: usize) -> Writable<Reg>; fn get_output(&self, ir_inst: Inst, idx: usize) -> Writable<Reg>;
// Codegen primitives: allocate temps, emit instructions, set result registers, // Codegen primitives: allocate temps, emit instructions, set result registers,