Commit 9f893284 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[ia32,root] Fix register usage of pair operations

Pair operations needed more than 5 registers; this allows one operand
to go into a slot or an immediate, which allows pair operations even if
ebx if not allocatable because it holds the root register.

Change-Id: Ic08b2e0ca93744a434e3d41af97da45b779756aa
Bug: v8:6666
Reviewed-on: https://chromium-review.googlesource.com/c/1271055
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56497}
parent 7c2aef08
......@@ -1117,7 +1117,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// i.InputRegister(2) ... right low word.
// i.InputRegister(3) ... right high word.
bool use_temp = false;
if (i.OutputRegister(0).code() == i.InputRegister(1).code() ||
if ((instr->InputAt(1)->IsRegister() &&
i.OutputRegister(0).code() == i.InputRegister(1).code()) ||
i.OutputRegister(0).code() == i.InputRegister(3).code()) {
// We cannot write to the output register directly, because it would
// overwrite an input for adc. We have to use the temp register.
......@@ -1127,8 +1128,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} else {
__ add(i.OutputRegister(0), i.InputRegister(2));
}
if (i.OutputRegister(1).code() != i.InputRegister(1).code()) {
__ Move(i.OutputRegister(1), i.InputRegister(1));
InstructionOperand* op = instr->InputAt(1);
if (op->IsImmediate() || op->IsConstant()) {
__ mov(i.OutputRegister(1), i.ToImmediate(op));
} else if (op->IsRegister()) {
__ Move(i.OutputRegister(1), i.ToRegister(op));
} else {
__ mov(i.OutputRegister(1), i.ToOperand(op));
}
__ adc(i.OutputRegister(1), Operand(i.InputRegister(3)));
if (use_temp) {
......@@ -1142,7 +1148,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
// i.InputRegister(2) ... right low word.
// i.InputRegister(3) ... right high word.
bool use_temp = false;
if (i.OutputRegister(0).code() == i.InputRegister(1).code() ||
if ((instr->InputAt(1)->IsRegister() &&
i.OutputRegister(0).code() == i.InputRegister(1).code()) ||
i.OutputRegister(0).code() == i.InputRegister(3).code()) {
// We cannot write to the output register directly, because it would
// overwrite an input for adc. We have to use the temp register.
......@@ -1152,8 +1159,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} else {
__ sub(i.OutputRegister(0), i.InputRegister(2));
}
if (i.OutputRegister(1).code() != i.InputRegister(1).code()) {
__ Move(i.OutputRegister(1), i.InputRegister(1));
InstructionOperand* op = instr->InputAt(1);
if (op->IsImmediate() || op->IsConstant()) {
__ mov(i.OutputRegister(1), i.ToImmediate(op));
} else if (op->IsRegister()) {
__ Move(i.OutputRegister(1), i.ToRegister(op));
} else {
__ mov(i.OutputRegister(1), i.ToOperand(op));
}
__ sbb(i.OutputRegister(1), Operand(i.InputRegister(3)));
if (use_temp) {
......@@ -1163,7 +1175,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
case kIA32MulPair: {
__ imul(i.OutputRegister(1), i.InputOperand(0));
__ mov(i.TempRegister(0), i.InputOperand(1));
InstructionOperand* op = instr->InputAt(1);
if (op->IsImmediate() || op->IsConstant()) {
__ mov(i.TempRegister(0), i.ToImmediate(op));
} else {
__ mov(i.TempRegister(0), i.ToOperand(op));
}
__ imul(i.TempRegister(0), i.InputOperand(2));
__ add(i.OutputRegister(1), i.TempRegister(0));
__ mov(i.OutputRegister(0), i.InputOperand(0));
......
......@@ -629,7 +629,8 @@ void InstructionSelector::VisitInt32PairAdd(Node* node) {
// We use UseUniqueRegister here to avoid register sharing with the temp
// register.
InstructionOperand inputs[] = {
g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
g.UseRegister(node->InputAt(0)),
g.UseUniqueRegisterOrSlotOrConstant(node->InputAt(1)),
g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
InstructionOperand outputs[] = {g.DefineSameAsFirst(node),
......@@ -654,7 +655,8 @@ void InstructionSelector::VisitInt32PairSub(Node* node) {
// We use UseUniqueRegister here to avoid register sharing with the temp
// register.
InstructionOperand inputs[] = {
g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
g.UseRegister(node->InputAt(0)),
g.UseUniqueRegisterOrSlotOrConstant(node->InputAt(1)),
g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
InstructionOperand outputs[] = {g.DefineSameAsFirst(node),
......@@ -678,10 +680,11 @@ void InstructionSelector::VisitInt32PairMul(Node* node) {
if (projection1) {
// InputAt(3) explicitly shares ecx with OutputRegister(1) to save one
// register and one mov instruction.
InstructionOperand inputs[] = {g.UseUnique(node->InputAt(0)),
g.UseUnique(node->InputAt(1)),
g.UseUniqueRegister(node->InputAt(2)),
g.UseFixed(node->InputAt(3), ecx)};
InstructionOperand inputs[] = {
g.UseUnique(node->InputAt(0)),
g.UseUniqueRegisterOrSlotOrConstant(node->InputAt(1)),
g.UseUniqueRegister(node->InputAt(2)),
g.UseFixed(node->InputAt(3), ecx)};
InstructionOperand outputs[] = {
g.DefineAsFixed(node, eax),
......
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