x64: Lower tlsvalue, sqmul_round_sat, and uunarrow in ISLE (#4793)

Lower tlsvalue, sqmul_round_sat, and uunarrow in ISLE.
This commit is contained in:
Trevor Elliott
2022-08-26 16:33:48 -07:00
committed by GitHub
parent 8e8dfdf5f9
commit 25d960f9c4
11 changed files with 287 additions and 205 deletions

View File

@@ -2915,7 +2915,10 @@ pub(crate) fn emit(
}
}
Inst::ElfTlsGetAddr { ref symbol } => {
Inst::ElfTlsGetAddr { ref symbol, dst } => {
let dst = allocs.next(dst.to_reg().to_reg());
debug_assert_eq!(dst, regs::rax());
// N.B.: Must be exactly this byte sequence; the linker requires it,
// because it must know how to rewrite the bytes.
@@ -2941,7 +2944,10 @@ pub(crate) fn emit(
sink.put4(0); // offset
}
Inst::MachOTlsGetAddr { ref symbol } => {
Inst::MachOTlsGetAddr { ref symbol, dst } => {
let dst = allocs.next(dst.to_reg().to_reg());
debug_assert_eq!(dst, regs::rax());
// movq gv@tlv(%rip), %rdi
sink.put1(0x48); // REX.w
sink.put1(0x8b); // MOV
@@ -2954,7 +2960,10 @@ pub(crate) fn emit(
sink.put1(0x17);
}
Inst::CoffTlsGetAddr { ref symbol } => {
Inst::CoffTlsGetAddr { ref symbol, dst } => {
let dst = allocs.next(dst.to_reg().to_reg());
debug_assert_eq!(dst, regs::rax());
// See: https://gcc.godbolt.org/z/M8or9x6ss
// And: https://github.com/bjorn3/rustc_codegen_cranelift/issues/388#issuecomment-532930282

View File

@@ -95,6 +95,24 @@ impl Inst {
let dst = WritableGpr::from_writable_reg(dst).unwrap();
Inst::Setcc { cc, dst }
}
fn xmm_rm_r_imm(
op: SseOpcode,
src: RegMem,
dst: Writable<Reg>,
imm: u8,
size: OperandSize,
) -> Inst {
debug_assert!(size.is_one_of(&[OperandSize::Size32, OperandSize::Size64]));
Inst::XmmRmRImm {
op,
src1: dst.to_reg(),
src2: src,
dst,
imm,
size,
}
}
}
#[test]
@@ -4738,6 +4756,7 @@ fn test_x64_emit() {
insns.push((
Inst::ElfTlsGetAddr {
symbol: ExternalName::User(UserExternalNameRef::new(0)),
dst: WritableGpr::from_writable_reg(w_rax).unwrap(),
},
"66488D3D00000000666648E800000000",
"%rax = elf_tls_get_addr User(userextname0)",
@@ -4746,6 +4765,7 @@ fn test_x64_emit() {
insns.push((
Inst::MachOTlsGetAddr {
symbol: ExternalName::User(UserExternalNameRef::new(0)),
dst: WritableGpr::from_writable_reg(w_rax).unwrap(),
},
"488B3D00000000FF17",
"%rax = macho_tls_get_addr User(userextname0)",
@@ -4754,6 +4774,7 @@ fn test_x64_emit() {
insns.push((
Inst::CoffTlsGetAddr {
symbol: ExternalName::User(UserExternalNameRef::new(0)),
dst: WritableGpr::from_writable_reg(w_rax).unwrap(),
},
"8B050000000065488B0C2558000000488B04C1488D8000000000",
"%rax = coff_tls_get_addr User(userextname0)",

View File

@@ -263,12 +263,6 @@ impl Inst {
Inst::MovRR { size, src, dst }
}
pub(crate) fn xmm_load_const(src: VCodeConstant, dst: Writable<Reg>, ty: Type) -> Inst {
debug_assert!(dst.to_reg().class() == RegClass::Float);
debug_assert!(ty.is_vector() && ty.bits() == 128);
Inst::XmmLoadConst { src, dst, ty }
}
/// Convenient helper for unary float operations.
pub(crate) fn xmm_unary_rm_r(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Inst {
src.assert_regclass_is(RegClass::Float);
@@ -377,24 +371,6 @@ impl Inst {
}
}
pub(crate) fn xmm_rm_r_imm(
op: SseOpcode,
src: RegMem,
dst: Writable<Reg>,
imm: u8,
size: OperandSize,
) -> Inst {
debug_assert!(size.is_one_of(&[OperandSize::Size32, OperandSize::Size64]));
Inst::XmmRmRImm {
op,
src1: dst.to_reg(),
src2: src,
dst,
imm,
size,
}
}
pub(crate) fn movzx_rm_r(ext_mode: ExtMode, src: RegMem, dst: Writable<Reg>) -> Inst {
src.assert_regclass_is(RegClass::Int);
debug_assert!(dst.to_reg().class() == RegClass::Int);
@@ -1544,16 +1520,19 @@ impl PrettyPrint for Inst {
Inst::Ud2 { trap_code } => format!("ud2 {}", trap_code),
Inst::ElfTlsGetAddr { ref symbol } => {
format!("%rax = elf_tls_get_addr {:?}", symbol)
Inst::ElfTlsGetAddr { ref symbol, dst } => {
let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
format!("{} = elf_tls_get_addr {:?}", dst, symbol)
}
Inst::MachOTlsGetAddr { ref symbol } => {
format!("%rax = macho_tls_get_addr {:?}", symbol)
Inst::MachOTlsGetAddr { ref symbol, dst } => {
let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
format!("{} = macho_tls_get_addr {:?}", dst, symbol)
}
Inst::CoffTlsGetAddr { ref symbol } => {
format!("%rax = coff_tls_get_addr {:?}", symbol)
Inst::CoffTlsGetAddr { ref symbol, dst } => {
let dst = pretty_print_reg(dst.to_reg().to_reg(), 8, allocs);
format!("{} = coff_tls_get_addr {:?}", dst, symbol)
}
Inst::Unwind { inst } => {
@@ -1994,8 +1973,8 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
// No registers are used.
}
Inst::ElfTlsGetAddr { .. } | Inst::MachOTlsGetAddr { .. } => {
collector.reg_def(Writable::from_reg(regs::rax()));
Inst::ElfTlsGetAddr { dst, .. } | Inst::MachOTlsGetAddr { dst, .. } => {
collector.reg_fixed_def(dst.to_writable_reg(), regs::rax());
// All caller-saves are clobbered.
//
// We use the SysV calling convention here because the
@@ -2007,12 +1986,12 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
collector.reg_clobbers(clobbers);
}
Inst::CoffTlsGetAddr { .. } => {
Inst::CoffTlsGetAddr { dst, .. } => {
// We also use the gs register. But that register is not allocatable by the
// register allocator, so we don't need to mark it as used here.
// We use %rax to set the address
collector.reg_def(Writable::from_reg(regs::rax()));
collector.reg_fixed_def(dst.to_writable_reg(), regs::rax());
// We use %rcx as a temporary variable to load the _tls_index
collector.reg_def(Writable::from_reg(regs::rcx()));