Commit b4275a70 authored by akos.palfi's avatar akos.palfi Committed by Commit bot

[turbofan] Add CalleeSavedFPRegisters to CallDescriptor.

This change makes possible to save and restore the FP registers
in the Prologue and Return parts for the CallAddress kind functions.

TEST=test-simplified-lowering/RunNumberDivide_2_TruncatingToUint32,
     test-simplified-lowering/RunNumberMultiply_TruncatingToUint32

Review URL: https://codereview.chromium.org/1191513003

Cr-Commit-Position: refs/heads/master@{#29378}
parent e60ce8d1
......@@ -962,16 +962,28 @@ void CodeGenerator::AssemblePrologue() {
__ mov(fp, sp);
saved_pp = false;
}
int register_save_area_size = saved_pp ? kPointerSize : 0;
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0 || saved_pp) {
// Save callee-saved registers.
int register_save_area_size = saved_pp ? kPointerSize : 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
register_save_area_size += kPointerSize;
}
frame()->SetRegisterSaveAreaSize(register_save_area_size);
__ stm(db_w, sp, saves);
register_save_area_size +=
kPointerSize * base::bits::CountPopulation32(saves);
}
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
// Save callee-saved FP registers.
STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
__ vstm(db_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
register_save_area_size += 2 * kPointerSize * (last - first + 1);
}
if (register_save_area_size > 0) {
frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
......@@ -1015,6 +1027,15 @@ void CodeGenerator::AssembleReturn() {
if (stack_slots > 0) {
__ add(sp, sp, Operand(stack_slots * kPointerSize));
}
// Restore FP registers.
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
__ vldm(ia_w, sp, DwVfpRegister::from_code(first),
DwVfpRegister::from_code(last));
}
// Restore registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
......
......@@ -23,6 +23,11 @@ struct ArmLinkageHelperTraits {
return r4.bit() | r5.bit() | r6.bit() | r7.bit() | r8.bit() | r9.bit() |
r10.bit();
}
static RegList CCalleeSaveFPRegisters() {
return (1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) |
(1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) |
(1 << d14.code()) | (1 << d15.code());
}
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {r0, r1, r2, r3};
return register_parameters[i];
......
......@@ -1094,9 +1094,23 @@ void CodeGenerator::AssemblePrologue() {
__ SetStackPointer(csp);
__ Push(lr, fp);
__ Mov(fp, csp);
// TODO(dcarney): correct callee saved registers.
__ PushCalleeSavedRegisters();
frame()->SetRegisterSaveAreaSize(20 * kPointerSize);
// Save FP registers.
CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
descriptor->CalleeSavedFPRegisters());
DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
int saved_count = saves_fp.Count();
__ PushCPURegList(saves_fp);
// Save registers.
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
descriptor->CalleeSavedRegisters());
// TODO(palfia): TF save list is not in sync with
// CPURegList::GetCalleeSaved(): x30 is missing.
// DCHECK(saves.list() == CPURegList::GetCalleeSaved().list());
saved_count += saves.Count();
__ PushCPURegList(saves);
frame()->SetRegisterSaveAreaSize(saved_count * kPointerSize);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ SetStackPointer(jssp);
......@@ -1145,10 +1159,18 @@ void CodeGenerator::AssembleReturn() {
if (stack_slots > 0) {
__ Add(csp, csp, AlignedStackSlots(stack_slots) * kPointerSize);
}
// Restore registers.
// TODO(dcarney): correct callee saved registers.
__ PopCalleeSavedRegisters();
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
descriptor->CalleeSavedRegisters());
__ PopCPURegList(saves);
CPURegList saves_fp =
CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
descriptor->CalleeSavedFPRegisters());
__ PopCPURegList(saves_fp);
}
__ Mov(csp, fp);
__ Pop(fp, lr);
__ Ret();
......
......@@ -20,8 +20,15 @@ struct Arm64LinkageHelperTraits {
static Register RuntimeCallFunctionReg() { return x1; }
static Register RuntimeCallArgCountReg() { return x0; }
static RegList CCalleeSaveRegisters() {
// TODO(dcarney): correct callee saved registers.
return 0;
return (1 << x19.code()) | (1 << x20.code()) | (1 << x21.code()) |
(1 << x22.code()) | (1 << x23.code()) | (1 << x24.code()) |
(1 << x25.code()) | (1 << x26.code()) | (1 << x27.code()) |
(1 << x28.code()) | (1 << x29.code()) | (1 << x30.code());
}
static RegList CCalleeSaveFPRegisters() {
return (1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) |
(1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) |
(1 << d14.code()) | (1 << d15.code());
}
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {x0, x1, x2, x3, x4, x5, x6, x7};
......
......@@ -22,6 +22,7 @@ struct IA32LinkageHelperTraits {
static RegList CCalleeSaveRegisters() {
return esi.bit() | edi.bit() | ebx.bit();
}
static RegList CCalleeSaveFPRegisters() { return 0; }
static Register CRegisterParameter(int i) { return no_reg; }
static int CRegisterParametersLength() { return 0; }
static int CStackBackingStoreLength() { return 0; }
......
......@@ -70,6 +70,7 @@ class LinkageHelper {
js_parameter_count, // js_parameter_count
Operator::kNoProperties, // properties
kNoCalleeSaved, // callee-saved
kNoCalleeSaved, // callee-saved fp
flags, // flags
"js-call");
}
......@@ -131,6 +132,7 @@ class LinkageHelper {
js_parameter_count, // js_parameter_count
properties, // properties
kNoCalleeSaved, // callee-saved
kNoCalleeSaved, // callee-saved fp
flags, // flags
function->name); // debug name
}
......@@ -191,6 +193,7 @@ class LinkageHelper {
js_parameter_count, // js_parameter_count
properties, // properties
kNoCalleeSaved, // callee-saved registers
kNoCalleeSaved, // callee-saved fp
flags, // flags
descriptor.DebugName(isolate));
}
......@@ -217,16 +220,17 @@ class LinkageHelper {
// The target for C calls is always an address (i.e. machine pointer).
MachineType target_type = kMachPtr;
LinkageLocation target_loc = LinkageLocation::AnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kCallAddress, // kind
target_type, // target MachineType
target_loc, // target location
msig, // machine_sig
locations.Build(), // location_sig
0, // js_parameter_count
Operator::kNoProperties, // properties
LinkageTraits::CCalleeSaveRegisters(), // callee-saved registers
CallDescriptor::kNoFlags, // flags
return new (zone) CallDescriptor( // --
CallDescriptor::kCallAddress, // kind
target_type, // target MachineType
target_loc, // target location
msig, // machine_sig
locations.Build(), // location_sig
0, // js_parameter_count
Operator::kNoProperties, // properties
LinkageTraits::CCalleeSaveRegisters(), // callee-saved registers
LinkageTraits::CCalleeSaveFPRegisters(), // callee-saved fp regs
CallDescriptor::kNoFlags, // flags
"c-call");
}
......
......@@ -83,7 +83,8 @@ class CallDescriptor final : public ZoneObject {
const MachineSignature* machine_sig,
LocationSignature* location_sig, size_t js_param_count,
Operator::Properties properties,
RegList callee_saved_registers, Flags flags,
RegList callee_saved_registers,
RegList callee_saved_fp_registers, Flags flags,
const char* debug_name = "")
: kind_(kind),
target_type_(target_type),
......@@ -93,6 +94,7 @@ class CallDescriptor final : public ZoneObject {
js_param_count_(js_param_count),
properties_(properties),
callee_saved_registers_(callee_saved_registers),
callee_saved_fp_registers_(callee_saved_fp_registers),
flags_(flags),
debug_name_(debug_name) {
DCHECK(machine_sig->return_count() == location_sig->return_count());
......@@ -156,6 +158,9 @@ class CallDescriptor final : public ZoneObject {
// Get the callee-saved registers, if any, across this call.
RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
// Get the callee-saved FP registers, if any, across this call.
RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
const char* debug_name() const { return debug_name_; }
bool UsesOnlyRegisters() const;
......@@ -173,6 +178,7 @@ class CallDescriptor final : public ZoneObject {
const size_t js_param_count_;
const Operator::Properties properties_;
const RegList callee_saved_registers_;
const RegList callee_saved_fp_registers_;
const Flags flags_;
const char* const debug_name_;
......
......@@ -1078,17 +1078,20 @@ void CodeGenerator::AssemblePrologue() {
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ Push(ra, fp);
__ mov(fp, sp);
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
// TODO(plind): make callee save size const, possibly DCHECK it.
int register_save_area_size = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
register_save_area_size += kPointerSize;
}
frame()->SetRegisterSaveAreaSize(register_save_area_size);
__ MultiPush(saves);
}
// Save callee-saved registers.
__ MultiPush(saves);
DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves));
int register_save_area_size = kNumCalleeSaved * kPointerSize;
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
// Save callee-saved FPU registers.
__ MultiPushFPU(saves_fpu);
DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
register_save_area_size += kNumCalleeSavedFPU * kDoubleSize * kPointerSize;
frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
......@@ -1131,11 +1134,13 @@ void CodeGenerator::AssembleReturn() {
if (stack_slots > 0) {
__ Addu(sp, sp, Operand(stack_slots * kPointerSize));
}
// Restore registers.
// Restore FPU registers.
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
__ MultiPopFPU(saves_fpu);
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ MultiPop(saves);
}
__ MultiPop(saves);
}
__ mov(sp, fp);
__ Pop(ra, fp);
......
......@@ -23,6 +23,10 @@ struct MipsLinkageHelperTraits {
return s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() |
s6.bit() | s7.bit();
}
static RegList CCalleeSaveFPRegisters() {
return f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() |
f30.bit();
}
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {a0, a1, a2, a3};
return register_parameters[i];
......
......@@ -1151,17 +1151,20 @@ void CodeGenerator::AssemblePrologue() {
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ Push(ra, fp);
__ mov(fp, sp);
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
// TODO(plind): make callee save size const, possibly DCHECK it.
int register_save_area_size = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
register_save_area_size += kPointerSize;
}
frame()->SetRegisterSaveAreaSize(register_save_area_size);
__ MultiPush(saves);
}
// Save callee-saved registers.
__ MultiPush(saves);
DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves));
int register_save_area_size = kNumCalleeSaved * kPointerSize;
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
// Save callee-saved FPU registers.
__ MultiPushFPU(saves_fpu);
DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
register_save_area_size += kNumCalleeSavedFPU * kDoubleSize * kPointerSize;
frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
......@@ -1204,11 +1207,13 @@ void CodeGenerator::AssembleReturn() {
if (stack_slots > 0) {
__ Daddu(sp, sp, Operand(stack_slots * kPointerSize));
}
// Restore registers.
// Restore FPU registers.
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
__ MultiPopFPU(saves_fpu);
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
__ MultiPop(saves);
}
__ MultiPop(saves);
}
__ mov(sp, fp);
__ Pop(ra, fp);
......
......@@ -23,6 +23,10 @@ struct MipsLinkageHelperTraits {
return s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() |
s6.bit() | s7.bit();
}
static RegList CCalleeSaveFPRegisters() {
return f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() |
f30.bit();
}
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {a0, a1, a2, a3, a4, a5, a6, a7};
return register_parameters[i];
......
......@@ -25,6 +25,7 @@ struct PPCLinkageHelperTraits {
r24.bit() | r25.bit() | r26.bit() | r27.bit() | r28.bit() |
r29.bit() | r30.bit() | fp.bit();
}
static RegList CCalleeSaveFPRegisters() { return 0; }
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {r3, r4, r5, r6, r7, r8, r9, r10};
return register_parameters[i];
......
......@@ -1469,14 +1469,31 @@ void CodeGenerator::AssemblePrologue() {
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ pushq(rbp);
__ movq(rbp, rsp);
int register_save_area_size = 0;
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
int register_save_area_size = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ pushq(Register::from_code(i));
register_save_area_size += kPointerSize;
}
}
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) { // Save callee-saved XMM registers.
const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
const int stack_size = saves_fp_count * 16;
// Adjust the stack pointer.
__ subp(rsp, Immediate(stack_size));
// Store the registers on the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ movdqu(Operand(rsp, 16 * slot_idx), XMMRegister::from_code(i));
slot_idx++;
}
register_save_area_size += stack_size;
}
if (register_save_area_size > 0) {
frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
......@@ -1521,8 +1538,22 @@ void CodeGenerator::AssembleReturn() {
if (stack_slots > 0) {
__ addq(rsp, Immediate(stack_slots * kPointerSize));
}
const RegList saves = descriptor->CalleeSavedRegisters();
// Restore registers.
const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (saves_fp != 0) {
const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
const int stack_size = saves_fp_count * 16;
// Load the registers from the stack.
int slot_idx = 0;
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
if (!((1 << i) & saves_fp)) continue;
__ movdqu(XMMRegister::from_code(i), Operand(rsp, 16 * slot_idx));
slot_idx++;
}
// Adjust the stack pointer.
__ addp(rsp, Immediate(stack_size));
}
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
......
......@@ -33,6 +33,16 @@ struct X64LinkageHelperTraits {
return rbx.bit() | r12.bit() | r13.bit() | r14.bit() | r15.bit();
}
}
static RegList CCalleeSaveFPRegisters() {
if (kWin64) {
return (1 << xmm6.code()) | (1 << xmm7.code()) | (1 << xmm8.code()) |
(1 << xmm9.code()) | (1 << xmm10.code()) | (1 << xmm11.code()) |
(1 << xmm12.code()) | (1 << xmm13.code()) | (1 << xmm14.code()) |
(1 << xmm15.code());
} else {
return 0;
}
}
static Register CRegisterParameter(int i) {
if (kWin64) {
static Register register_parameters[] = {rcx, rdx, r8, r9};
......
......@@ -272,8 +272,6 @@
'test-api/ExternalArrays': [PASS, NO_VARIANTS],
# TODO(mips-team): Currently fails on mips board.
'test-simplified-lowering/RunNumberMultiply_TruncatingToUint32': [SKIP],
'test-simplified-lowering/RunNumberDivide_2_TruncatingToUint32': [SKIP],
'test-parsing/TooManyArguments': [SKIP],
'test-api/Threading3': [SKIP],
}], # 'arch == mips'
......
......@@ -33,7 +33,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject0) {
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, CallDescriptor::kNoFlags);
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
......@@ -53,7 +53,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) {
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
......@@ -77,7 +77,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject2) {
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
......@@ -99,7 +99,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction0) {
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, CallDescriptor::kNoFlags);
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
......@@ -119,7 +119,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) {
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
......@@ -143,7 +143,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction2) {
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment