cranelift: add i64.{ishl,ushr,ashr} libcalls.

These libcalls are useful for 32-bit platforms.

On x86_32 in particular, commit 4ec16fa0 added support for legalizing
64-bit shifts through SIMD operations. However, that legalization
requires SIMD to be enabled and SSE 4.1 to be supported, which is not
acceptable as a hard requirement.
This commit is contained in:
whitequark
2020-05-29 15:53:52 +00:00
committed by Andrew Brown
parent be20c92205
commit bc555468a7
7 changed files with 99 additions and 9 deletions

View File

@@ -13,6 +13,7 @@ use crate::isa::encoding::base_size;
use crate::isa::encoding::{Encoding, RecipeSizing};
use crate::isa::RegUnit;
use crate::isa::{self, TargetIsa};
use crate::legalizer::expand_as_libcall;
use crate::predicates;
use crate::regalloc::RegDiversions;
@@ -1428,10 +1429,20 @@ fn convert_ushr(
pos.func.dfg.replace(inst).x86_psrl(arg0, shift_index);
} else if arg0_type == I64 {
// 64 bit shifts need to be legalized on x86_32.
let value = expand_dword_to_xmm(&mut pos, arg0, arg0_type);
let amount = expand_dword_to_xmm(&mut pos, arg1, arg1_type);
let shifted = pos.ins().x86_psrl(value, amount);
contract_dword_from_xmm(&mut pos, inst, shifted, arg0_type);
let x86_isa = isa
.as_any()
.downcast_ref::<isa::x86::Isa>()
.expect("the target ISA must be x86 at this point");
if x86_isa.isa_flags.has_sse41() {
// if we have pinstrq/pextrq (SSE 4.1), legalize to that
let value = expand_dword_to_xmm(&mut pos, arg0, arg0_type);
let amount = expand_dword_to_xmm(&mut pos, arg1, arg1_type);
let shifted = pos.ins().x86_psrl(value, amount);
contract_dword_from_xmm(&mut pos, inst, shifted, arg0_type);
} else {
// otherwise legalize to libcall
expand_as_libcall(inst, func, isa);
}
} else {
// Everything else should be already legal.
unreachable!()
@@ -1502,10 +1513,20 @@ fn convert_ishl(
pos.func.dfg.replace(inst).x86_psll(arg0, shift_index);
} else if arg0_type == I64 {
// 64 bit shifts need to be legalized on x86_32.
let value = expand_dword_to_xmm(&mut pos, arg0, arg0_type);
let amount = expand_dword_to_xmm(&mut pos, arg1, arg1_type);
let shifted = pos.ins().x86_psll(value, amount);
contract_dword_from_xmm(&mut pos, inst, shifted, arg0_type);
let x86_isa = isa
.as_any()
.downcast_ref::<isa::x86::Isa>()
.expect("the target ISA must be x86 at this point");
if x86_isa.isa_flags.has_sse41() {
// if we have pinstrq/pextrq (SSE 4.1), legalize to that
let value = expand_dword_to_xmm(&mut pos, arg0, arg0_type);
let amount = expand_dword_to_xmm(&mut pos, arg1, arg1_type);
let shifted = pos.ins().x86_psll(value, amount);
contract_dword_from_xmm(&mut pos, inst, shifted, arg0_type);
} else {
// otherwise legalize to libcall
expand_as_libcall(inst, func, isa);
}
} else {
// Everything else should be already legal.
unreachable!()