Browse Source

cranelift/x64: Use immediates for all 32-bit constants (#8445)

On x86-64, instructions which take 32-bit immediate operands in 64-bit
mode sign-extend those immediates.

To accommodate that, we currently only generate an immediate if the
64-bit constant we want is equal to truncating to 32 bits and then
sign-extending back to 64 bits. Otherwise we put the 64-bit constant in
the constant pool.

However, if the constant's type is I32, we don't care about its upper
32 bits. In that case it's safe to generate an immediate whether the
sign bit is set or not. We should never need to use the constant pool
for types smaller than 64 bits on x64.
pull/8450/head
Jamey Sharp 7 months ago
committed by GitHub
parent
commit
f8396199e9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      cranelift/codegen/src/isa/x64/inst.isle
  2. 18
      cranelift/codegen/src/isa/x64/lower/isle.rs

4
cranelift/codegen/src/isa/x64/inst.isle

@ -1792,10 +1792,6 @@
(decl simm32_from_value (GprMemImm) Value)
(extern extractor simm32_from_value simm32_from_value)
;; Extract a constant `RegMemImm.Imm` from an `Imm64` immediate.
(decl simm32_from_imm64 (GprMemImm) Imm64)
(extern extractor simm32_from_imm64 simm32_from_imm64)
;; A load that can be sunk into another operation.
(type SinkableLoad extern (enum))

18
cranelift/codegen/src/isa/x64/lower/isle.rs

@ -146,7 +146,8 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
let inputs = self.lower_ctx.get_value_as_source_or_const(val);
if let Some(c) = inputs.constant {
if let Some(imm) = to_simm32(c as i64) {
let ty = self.lower_ctx.dfg().value_type(val);
if let Some(imm) = to_simm32(c as i64, ty) {
return imm.to_reg_mem_imm();
}
}
@ -158,7 +159,8 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
let inputs = self.lower_ctx.get_value_as_source_or_const(val);
if let Some(c) = inputs.constant {
if let Some(imm) = to_simm32(c as i64) {
let ty = self.lower_ctx.dfg().value_type(val);
if let Some(imm) = to_simm32(c as i64, ty) {
return XmmMemImm::new(imm.to_reg_mem_imm()).unwrap();
}
}
@ -325,13 +327,9 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
fn simm32_from_value(&mut self, val: Value) -> Option<GprMemImm> {
let inst = self.lower_ctx.dfg().value_def(val).inst()?;
let constant: u64 = self.lower_ctx.get_constant(inst)?;
let ty = self.lower_ctx.dfg().value_type(val);
let constant = constant as i64;
to_simm32(constant)
}
#[inline]
fn simm32_from_imm64(&mut self, imm: Imm64) -> Option<GprMemImm> {
to_simm32(imm.bits())
to_simm32(constant, ty)
}
fn sinkable_load(&mut self, val: Value) -> Option<SinkableLoad> {
@ -1052,8 +1050,8 @@ const I8X16_USHR_MASKS: [u8; 128] = [
];
#[inline]
fn to_simm32(constant: i64) -> Option<GprMemImm> {
if constant == ((constant << 32) >> 32) {
fn to_simm32(constant: i64, ty: Type) -> Option<GprMemImm> {
if ty.bits() <= 32 || constant == ((constant << 32) >> 32) {
Some(
GprMemImm::new(RegMemImm::Imm {
simm32: constant as u32,

Loading…
Cancel
Save