diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index f142d9649a42..2bb04215d6d9 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -4,7 +4,7 @@ pub(super) mod isle; use crate::ir::pcc::{FactContext, PccResult}; -use crate::ir::{types, ExternalName, Inst as IRInst, LibCall, Opcode, Type}; +use crate::ir::{types, ExternalName, Inst as IRInst, InstructionData, LibCall, Opcode, Type}; use crate::isa::x64::abi::*; use crate::isa::x64::inst::args::*; use crate::isa::x64::inst::*; @@ -61,11 +61,10 @@ fn put_input_in_regs(ctx: &mut Lower, spec: InsnInput) -> ValueRegs { if let Some(c) = input.constant { // Generate constants fresh at each use to minimize long-range register pressure. - let from_bits = ty_bits(ty); - let (size, c) = if from_bits < 64 { - (OperandSize::Size32, c & ((1u64 << from_bits) - 1)) + let size = if ty_bits(ty) < 64 { + OperandSize::Size32 } else { - (OperandSize::Size64, c) + OperandSize::Size64 }; assert!(is_int_or_ref_ty(ty)); // Only used for addresses. let cst_copy = ctx.alloc_tmp(ty); @@ -124,16 +123,18 @@ fn is_mergeable_load( // Just testing the opcode is enough, because the width will always match if // the type does (and the type should match if the CLIF is properly // constructed). - if insn_data.opcode() == Opcode::Load { - let offset = insn_data - .load_store_offset() - .expect("load should have offset"); + if let &InstructionData::Load { + opcode: Opcode::Load, + offset, + .. + } = insn_data + { Some(( InsnInput { insn: src_insn, input: 0, }, - offset, + offset.into(), )) } else { None @@ -261,35 +262,21 @@ fn lower_to_amode(ctx: &mut Lower, spec: InsnInput, offset: i32) -> Amode shift_amt, ) } else { - for i in 0..=1 { + for input in 0..=1 { // Try to pierce through uextend. - if let Some(uextend) = matches_input( - ctx, - InsnInput { - insn: add, - input: i, - }, - Opcode::Uextend, - ) { - if let Some(cst) = ctx.get_input_as_source_or_const(uextend, 0).constant { - // Zero the upper bits. - let input_size = ctx.input_ty(uextend, 0).bits() as u64; - let shift: u64 = 64 - input_size; - let uext_cst: u64 = (cst << shift) >> shift; - - let final_offset = (offset as i64).wrapping_add(uext_cst as i64); - if let Ok(final_offset) = i32::try_from(final_offset) { - let base = put_input_in_reg(ctx, add_inputs[1 - i]); - return Amode::imm_reg(final_offset, base).with_flags(flags); - } - } - } + let (inst, inst_input) = if let Some(uextend) = + matches_input(ctx, InsnInput { insn: add, input }, Opcode::Uextend) + { + (uextend, 0) + } else { + (add, input) + }; // If it's a constant, add it directly! - if let Some(cst) = ctx.get_input_as_source_or_const(add, i).constant { + if let Some(cst) = ctx.get_input_as_source_or_const(inst, inst_input).constant { let final_offset = (offset as i64).wrapping_add(cst as i64); if let Ok(final_offset) = i32::try_from(final_offset) { - let base = put_input_in_reg(ctx, add_inputs[1 - i]); + let base = put_input_in_reg(ctx, add_inputs[1 - input]); return Amode::imm_reg(final_offset, base).with_flags(flags); } } diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs index 32d841ebb5da..9c4118542578 100644 --- a/cranelift/codegen/src/machinst/lower.rs +++ b/cranelift/codegen/src/machinst/lower.rs @@ -1218,7 +1218,16 @@ impl<'func, I: VCodeInst> Lower<'func, I> { /// Get the value of a constant instruction (`iconst`, etc.) as a 64-bit /// value, if possible. pub fn get_constant(&self, ir_inst: Inst) -> Option { - self.inst_constants.get(&ir_inst).cloned() + self.inst_constants.get(&ir_inst).map(|&c| { + // The upper bits must be zero, enforced during legalization and by + // the CLIF verifier. + debug_assert_eq!(c, { + let input_size = self.output_ty(ir_inst, 0).bits() as u64; + let shift = 64 - input_size; + (c << shift) >> shift + }); + c + }) } /// Get the input as one of two options other than a direct register: