[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: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#56497}
This commit is contained in:
parent
7c2aef087e
commit
9f89328416
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user