[turbofan] Enable complex memory operands for push instructions on ia32/6x4

Change-Id: Id10be318965d7ec81af8fce8ec230557d3bf1369
Reviewed-on: https://chromium-review.googlesource.com/442126
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Daniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43191}
This commit is contained in:
Daniel Clifford 2017-02-14 12:52:32 +01:00 committed by Commit Bot
parent 310f921377
commit 95d6ec827f
5 changed files with 79 additions and 43 deletions

View File

@ -1862,7 +1862,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
break;
case kIA32Push:
if (instr->InputAt(0)->IsFPRegister()) {
if (AddressingModeField::decode(instr->opcode()) != kMode_None) {
size_t index = 0;
Operand operand = i.MemoryOperand(&index);
__ push(operand);
frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
} else if (instr->InputAt(0)->IsFPRegister()) {
__ sub(esp, Immediate(kFloatSize));
__ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);

View File

@ -1089,22 +1089,35 @@ void InstructionSelector::EmitPrepareArguments(
}
} else {
// Push any stack arguments.
int effect_level = GetEffectLevel(node);
for (PushParameter input : base::Reversed(*arguments)) {
// Skip any alignment holes in pushed nodes.
Node* input_node = input.node();
if (input.node() == nullptr) continue;
InstructionOperand value =
g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: IsSupported(ATOM) ||
sequence()->IsFP(GetVirtualRegister(input.node()))
? g.UseRegister(input.node())
: g.Use(input.node());
if (input.type() == MachineType::Float32()) {
Emit(kIA32PushFloat32, g.NoOutput(), value);
} else if (input.type() == MachineType::Float64()) {
Emit(kIA32PushFloat64, g.NoOutput(), value);
if (g.CanBeMemoryOperand(kIA32Push, node, input_node, effect_level)) {
InstructionOperand outputs[1];
InstructionOperand inputs[4];
size_t input_count = 0;
InstructionCode opcode = kIA32Push;
AddressingMode mode = g.GetEffectiveAddressMemoryOperand(
input_node, inputs, &input_count);
opcode |= AddressingModeField::encode(mode);
Emit(opcode, 0, outputs, input_count, inputs);
} else {
Emit(kIA32Push, g.NoOutput(), value);
InstructionOperand value =
g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: IsSupported(ATOM) ||
sequence()->IsFP(GetVirtualRegister(input.node()))
? g.UseRegister(input.node())
: g.Use(input.node());
if (input.type() == MachineType::Float32()) {
Emit(kIA32PushFloat32, g.NoOutput(), value);
} else if (input.type() == MachineType::Float64()) {
Emit(kIA32PushFloat64, g.NoOutput(), value);
} else {
Emit(kIA32Push, g.NoOutput(), value);
}
}
}
}

View File

@ -847,6 +847,7 @@ void InstructionSelector::VisitBlock(BasicBlock* block) {
int effect_level = 0;
for (Node* const node : *block) {
SetEffectLevel(node, effect_level);
if (node->opcode() == IrOpcode::kStore ||
node->opcode() == IrOpcode::kUnalignedStore ||
node->opcode() == IrOpcode::kCheckedStore ||
@ -855,7 +856,6 @@ void InstructionSelector::VisitBlock(BasicBlock* block) {
node->opcode() == IrOpcode::kProtectedStore) {
++effect_level;
}
SetEffectLevel(node, effect_level);
}
// We visit the control first, then the nodes in the block, so the block's

View File

@ -2097,30 +2097,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ incl(i.OutputRegister());
break;
case kX64Push:
if (HasImmediateInput(instr, 0)) {
if (AddressingModeField::decode(instr->opcode()) != kMode_None) {
size_t index = 0;
Operand operand = i.MemoryOperand(&index);
__ pushq(operand);
frame_access_state()->IncreaseSPDelta(1);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kPointerSize);
} else if (HasImmediateInput(instr, 0)) {
__ pushq(i.InputImmediate(0));
frame_access_state()->IncreaseSPDelta(1);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kPointerSize);
} else if (instr->InputAt(0)->IsRegister()) {
__ pushq(i.InputRegister(0));
frame_access_state()->IncreaseSPDelta(1);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kPointerSize);
} else if (instr->InputAt(0)->IsFPRegister()) {
// TODO(titzer): use another machine instruction?
__ subq(rsp, Immediate(kDoubleSize));
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kDoubleSize);
__ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
} else {
if (instr->InputAt(0)->IsRegister()) {
__ pushq(i.InputRegister(0));
frame_access_state()->IncreaseSPDelta(1);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kPointerSize);
} else if (instr->InputAt(0)->IsFPRegister()) {
// TODO(titzer): use another machine instruction?
__ subq(rsp, Immediate(kDoubleSize));
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kDoubleSize);
__ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
} else {
__ pushq(i.InputOperand(0));
frame_access_state()->IncreaseSPDelta(1);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kPointerSize);
}
__ pushq(i.InputOperand(0));
frame_access_state()->IncreaseSPDelta(1);
unwinding_info_writer_.MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kPointerSize);
}
break;
case kX64Poke: {

View File

@ -58,6 +58,7 @@ class X64OperandGenerator final : public OperandGenerator {
MachineRepresentation rep =
LoadRepresentationOf(input->op()).representation();
switch (opcode) {
case kX64Push:
case kX64Cmp:
case kX64Test:
return rep == MachineRepresentation::kWord64 || IsAnyTagged(rep);
@ -1504,17 +1505,29 @@ void InstructionSelector::EmitPrepareArguments(
}
} else {
// Push any stack arguments.
int effect_level = GetEffectLevel(node);
for (PushParameter input : base::Reversed(*arguments)) {
// TODO(titzer): X64Push cannot handle stack->stack double moves
// because there is no way to encode fixed double slots.
InstructionOperand value =
g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: IsSupported(ATOM) ||
sequence()->IsFP(GetVirtualRegister(input.node()))
? g.UseRegister(input.node())
: g.Use(input.node());
Emit(kX64Push, g.NoOutput(), value);
Node* input_node = input.node();
if (g.CanBeImmediate(input_node)) {
Emit(kX64Push, g.NoOutput(), g.UseImmediate(input_node));
} else if (IsSupported(ATOM) ||
sequence()->IsFP(GetVirtualRegister(input_node))) {
// TODO(titzer): X64Push cannot handle stack->stack double moves
// because there is no way to encode fixed double slots.
Emit(kX64Push, g.NoOutput(), g.UseRegister(input_node));
} else if (g.CanBeMemoryOperand(kX64Push, node, input_node,
effect_level)) {
InstructionOperand outputs[1];
InstructionOperand inputs[4];
size_t input_count = 0;
InstructionCode opcode = kX64Push;
AddressingMode mode = g.GetEffectiveAddressMemoryOperand(
input_node, inputs, &input_count);
opcode |= AddressingModeField::encode(mode);
Emit(opcode, 0, outputs, input_count, inputs);
} else {
Emit(kX64Push, g.NoOutput(), g.Use(input_node));
}
}
}
}