Assign vector arguments to FPR registers

This commit is contained in:
Andrew Brown
2019-07-11 10:26:08 -07:00
committed by Dan Gohman
parent 659725b465
commit c39a9b4e3f
2 changed files with 62 additions and 10 deletions

View File

@@ -1,6 +1,8 @@
//! x86 ABI implementation.
use super::super::settings as shared_settings;
use super::registers::{FPR, GPR, RU};
use super::settings as isa_settings;
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
use crate::cursor::{Cursor, CursorPosition, EncCursor};
use crate::ir;
@@ -39,10 +41,20 @@ struct Args {
fpr_used: usize,
offset: u32,
call_conv: CallConv,
shared_flags: shared_settings::Flags,
#[allow(dead_code)]
isa_flags: isa_settings::Flags,
}
impl Args {
fn new(bits: u8, gpr: &'static [RU], fpr_limit: usize, call_conv: CallConv) -> Self {
fn new(
bits: u8,
gpr: &'static [RU],
fpr_limit: usize,
call_conv: CallConv,
shared_flags: &shared_settings::Flags,
isa_flags: &isa_settings::Flags,
) -> Self {
let offset = if let CallConv::WindowsFastcall = call_conv {
// [1] "The caller is responsible for allocating space for parameters to the callee,
// and must always allocate sufficient space to store four register parameters"
@@ -61,6 +73,8 @@ impl Args {
fpr_used: 0,
offset,
call_conv,
shared_flags: shared_flags.clone(),
isa_flags: isa_flags.clone(),
}
}
}
@@ -69,11 +83,16 @@ impl ArgAssigner for Args {
fn assign(&mut self, arg: &AbiParam) -> ArgAction {
let ty = arg.value_type;
// Check for a legal type.
// We don't support SIMD yet, so break all vectors down.
// Vectors should stay in vector registers unless SIMD is not enabled--then they are split
if ty.is_vector() {
if self.shared_flags.enable_simd() {
let reg = FPR.unit(self.fpr_used);
self.fpr_used += 1;
return ArgumentLoc::Reg(reg).into();
} else {
return ValueConversion::VectorSplit.into();
}
}
// Large integers and booleans are broken down to fit in a register.
if !ty.is_float() && ty.bits() > u16::from(self.pointer_bits) {
@@ -139,7 +158,13 @@ impl ArgAssigner for Args {
}
/// Legalize `sig`.
pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bool) {
pub fn legalize_signature(
sig: &mut ir::Signature,
triple: &Triple,
_current: bool,
shared_flags: &shared_settings::Flags,
isa_flags: &isa_settings::Flags,
) {
let bits;
let mut args;
@@ -147,14 +172,28 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo
PointerWidth::U16 => panic!(),
PointerWidth::U32 => {
bits = 32;
args = Args::new(bits, &[], 0, sig.call_conv);
args = Args::new(bits, &[], 0, sig.call_conv, shared_flags, isa_flags);
}
PointerWidth::U64 => {
bits = 64;
args = if sig.call_conv == CallConv::WindowsFastcall {
Args::new(bits, &ARG_GPRS_WIN_FASTCALL_X64[..], 4, sig.call_conv)
Args::new(
bits,
&ARG_GPRS_WIN_FASTCALL_X64[..],
4,
sig.call_conv,
shared_flags,
isa_flags,
)
} else {
Args::new(bits, &ARG_GPRS[..], 8, sig.call_conv)
Args::new(
bits,
&ARG_GPRS[..],
8,
sig.call_conv,
shared_flags,
isa_flags,
)
};
}
}
@@ -168,7 +207,14 @@ pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bo
(&RET_GPRS[..], 2)
};
let mut rets = Args::new(bits, regs, fpr_limit, sig.call_conv);
let mut rets = Args::new(
bits,
regs,
fpr_limit,
sig.call_conv,
shared_flags,
isa_flags,
);
legalize_args(&mut sig.returns, &mut rets);
}

View File

@@ -106,7 +106,13 @@ impl TargetIsa for Isa {
}
fn legalize_signature(&self, sig: &mut ir::Signature, current: bool) {
abi::legalize_signature(sig, &self.triple, current)
abi::legalize_signature(
sig,
&self.triple,
current,
&self.shared_flags,
&self.isa_flags,
)
}
fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {