From 9f89328416eade283c097c413e93cd57934e598e Mon Sep 17 00:00:00 2001 From: Sigurd Schneider Date: Tue, 9 Oct 2018 16:12:11 +0200 Subject: [PATCH] [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 Reviewed-by: Andreas Haas Cr-Commit-Position: refs/heads/master@{#56497} --- src/compiler/ia32/code-generator-ia32.cc | 31 ++++++++++++++----- .../ia32/instruction-selector-ia32.cc | 15 +++++---- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc index cbde44da37..dd733d2907 100644 --- a/src/compiler/ia32/code-generator-ia32.cc +++ b/src/compiler/ia32/code-generator-ia32.cc @@ -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)); diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc index a1dbcf0bfa..c8ff7c3700 100644 --- a/src/compiler/ia32/instruction-selector-ia32.cc +++ b/src/compiler/ia32/instruction-selector-ia32.cc @@ -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),