From 8c4b7d272ac71340394b96835255fee45c227aea Mon Sep 17 00:00:00 2001 From: Dusan Milosavljevic Date: Mon, 22 Dec 2014 18:37:11 +0100 Subject: [PATCH] MIPS: Enable Math rounding operations call reduction optimization in TF. TEST= BUG= R=paul.lind@imgtec.com Review URL: https://codereview.chromium.org/791473003 Cr-Commit-Position: refs/heads/master@{#25931} --- src/compiler/mips/code-generator-mips.cc | 73 +++++++++++++++++++++ src/compiler/mips/instruction-codes-mips.h | 3 + src/compiler/mips/instruction-selector-mips.cc | 23 ++++++- src/compiler/mips64/code-generator-mips64.cc | 75 +++++++++++++++++++--- src/compiler/mips64/instruction-codes-mips64.h | 6 +- src/compiler/mips64/instruction-selector-mips64.cc | 10 +-- 6 files changed, 171 insertions(+), 19 deletions(-) diff --git a/src/compiler/mips/code-generator-mips.cc b/src/compiler/mips/code-generator-mips.cc index b808856..dd92837 100644 --- a/src/compiler/mips/code-generator-mips.cc +++ b/src/compiler/mips/code-generator-mips.cc @@ -20,6 +20,7 @@ namespace compiler { // TODO(plind): Possibly avoid using these lithium names. #define kScratchReg kLithiumScratchReg #define kCompareReg kLithiumScratchReg2 +#define kScratchReg2 kLithiumScratchReg2 #define kScratchDoubleReg kLithiumScratchDouble @@ -162,6 +163,45 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode { Register const result_; }; + +class OutOfLineRound : public OutOfLineCode { + public: + OutOfLineRound(CodeGenerator* gen, DoubleRegister result) + : OutOfLineCode(gen), result_(result) {} + + void Generate() FINAL { + // Handle rounding to zero case where sign has to be preserved. + // High bits of double input already in kScratchReg. + __ srl(at, kScratchReg, 31); + __ sll(at, at, 31); + __ Mthc1(at, result_); + } + + private: + DoubleRegister const result_; +}; + + +class OutOfLineTruncate FINAL : public OutOfLineRound { + public: + OutOfLineTruncate(CodeGenerator* gen, DoubleRegister result) + : OutOfLineRound(gen, result) {} +}; + + +class OutOfLineFloor FINAL : public OutOfLineRound { + public: + OutOfLineFloor(CodeGenerator* gen, DoubleRegister result) + : OutOfLineRound(gen, result) {} +}; + + +class OutOfLineCeil FINAL : public OutOfLineRound { + public: + OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) + : OutOfLineRound(gen, result) {} +}; + } // namespace @@ -239,6 +279,27 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode { } while (0) +#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(asm_instr, operation) \ + do { \ + auto ool = \ + new (zone()) OutOfLine##operation(this, i.OutputDoubleRegister()); \ + Label done; \ + __ Mfhc1(kScratchReg, i.InputDoubleRegister(0)); \ + __ Ext(at, kScratchReg, HeapNumber::kExponentShift, \ + HeapNumber::kExponentBits); \ + __ Branch(USE_DELAY_SLOT, &done, hs, at, \ + Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \ + __ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ + __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ + __ Move(at, kScratchReg2, i.OutputDoubleRegister()); \ + __ or_(at, at, kScratchReg2); \ + __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ + __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ + __ bind(ool->exit()); \ + __ bind(&done); \ + } while (0) + + // Assembles an instruction after register allocation, producing machine code. void CodeGenerator::AssembleArchInstruction(Instruction* instr) { MipsOperandConverter i(this, instr); @@ -407,6 +468,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ MovFromFloatResult(i.OutputDoubleRegister()); break; } + case kMipsFloat64Floor: { + ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor_l_d, Floor); + break; + } + case kMipsFloat64Ceil: { + ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil_l_d, Ceil); + break; + } + case kMipsFloat64RoundTruncate: { + ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc_l_d, Truncate); + break; + } case kMipsSqrtD: { __ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); break; diff --git a/src/compiler/mips/instruction-codes-mips.h b/src/compiler/mips/instruction-codes-mips.h index 1c684cb..3aa508f 100644 --- a/src/compiler/mips/instruction-codes-mips.h +++ b/src/compiler/mips/instruction-codes-mips.h @@ -40,6 +40,9 @@ namespace compiler { V(MipsDivD) \ V(MipsModD) \ V(MipsSqrtD) \ + V(MipsFloat64Floor) \ + V(MipsFloat64Ceil) \ + V(MipsFloat64RoundTruncate) \ V(MipsCvtSD) \ V(MipsCvtDS) \ V(MipsTruncWD) \ diff --git a/src/compiler/mips/instruction-selector-mips.cc b/src/compiler/mips/instruction-selector-mips.cc index 0ebb3cf..5e8e3b1 100644 --- a/src/compiler/mips/instruction-selector-mips.cc +++ b/src/compiler/mips/instruction-selector-mips.cc @@ -69,6 +69,14 @@ static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, } +static void VisitRR(InstructionSelector* selector, ArchOpcode opcode, + Node* node) { + MipsOperandGenerator g(selector); + selector->Emit(opcode, g.DefineAsRegister(node), + g.UseRegister(node->InputAt(0))); +} + + static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node) { MipsOperandGenerator g(selector); @@ -420,14 +428,18 @@ void InstructionSelector::VisitFloat64Sqrt(Node* node) { } -void InstructionSelector::VisitFloat64Floor(Node* node) { UNREACHABLE(); } +void InstructionSelector::VisitFloat64Floor(Node* node) { + VisitRR(this, kMipsFloat64Floor, node); +} -void InstructionSelector::VisitFloat64Ceil(Node* node) { UNREACHABLE(); } +void InstructionSelector::VisitFloat64Ceil(Node* node) { + VisitRR(this, kMipsFloat64Ceil, node); +} void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { - UNREACHABLE(); + VisitRR(this, kMipsFloat64RoundTruncate, node); } @@ -806,6 +818,11 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { // static MachineOperatorBuilder::Flags InstructionSelector::SupportedMachineOperatorFlags() { + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + return MachineOperatorBuilder::kFloat64Floor | + MachineOperatorBuilder::kFloat64Ceil | + MachineOperatorBuilder::kFloat64RoundTruncate; + } return MachineOperatorBuilder::kNoFlags; } diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc index 8e94cee..dee7705 100644 --- a/src/compiler/mips64/code-generator-mips64.cc +++ b/src/compiler/mips64/code-generator-mips64.cc @@ -163,6 +163,46 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode { Register const result_; }; + +class OutOfLineRound : public OutOfLineCode { + public: + OutOfLineRound(CodeGenerator* gen, DoubleRegister result) + : OutOfLineCode(gen), result_(result) {} + + void Generate() FINAL { + // Handle rounding to zero case where sign has to be preserved. + // High bits of double input already in kScratchReg. + __ dsrl(at, kScratchReg, 31); + __ dsll(at, at, 31); + __ mthc1(at, result_); + } + + private: + DoubleRegister const result_; +}; + + +class OutOfLineTruncate FINAL : public OutOfLineRound { + public: + OutOfLineTruncate(CodeGenerator* gen, DoubleRegister result) + : OutOfLineRound(gen, result) {} +}; + + +class OutOfLineFloor FINAL : public OutOfLineRound { + public: + OutOfLineFloor(CodeGenerator* gen, DoubleRegister result) + : OutOfLineRound(gen, result) {} +}; + + +class OutOfLineCeil FINAL : public OutOfLineRound { + public: + OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) + : OutOfLineRound(gen, result) {} +}; + + } // namespace @@ -240,6 +280,26 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode { } while (0) +#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(asm_instr, operation) \ + do { \ + auto ool = \ + new (zone()) OutOfLine##operation(this, i.OutputDoubleRegister()); \ + Label done; \ + __ mfhc1(kScratchReg, i.InputDoubleRegister(0)); \ + __ Ext(at, kScratchReg, HeapNumber::kExponentShift, \ + HeapNumber::kExponentBits); \ + __ Branch(USE_DELAY_SLOT, &done, hs, at, \ + Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \ + __ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ + __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ + __ dmfc1(at, i.OutputDoubleRegister()); \ + __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ + __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ + __ bind(ool->exit()); \ + __ bind(&done); \ + } while (0) + + // Assembles an instruction after register allocation, producing machine code. void CodeGenerator::AssembleArchInstruction(Instruction* instr) { MipsOperandConverter i(this, instr); @@ -472,19 +532,16 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ MovFromFloatResult(i.OutputDoubleRegister()); break; } - case kMips64FloorD: { - __ floor_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); - __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); + case kMips64Float64Floor: { + ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor_l_d, Floor); break; } - case kMips64CeilD: { - __ ceil_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); - __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); + case kMips64Float64Ceil: { + ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil_l_d, Ceil); break; } - case kMips64RoundTruncateD: { - __ trunc_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); - __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); + case kMips64Float64RoundTruncate: { + ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc_l_d, Truncate); break; } case kMips64SqrtD: { diff --git a/src/compiler/mips64/instruction-codes-mips64.h b/src/compiler/mips64/instruction-codes-mips64.h index ff04c34..dd019f9 100644 --- a/src/compiler/mips64/instruction-codes-mips64.h +++ b/src/compiler/mips64/instruction-codes-mips64.h @@ -53,9 +53,9 @@ namespace compiler { V(Mips64DivD) \ V(Mips64ModD) \ V(Mips64SqrtD) \ - V(Mips64FloorD) \ - V(Mips64CeilD) \ - V(Mips64RoundTruncateD) \ + V(Mips64Float64Floor) \ + V(Mips64Float64Ceil) \ + V(Mips64Float64RoundTruncate) \ V(Mips64CvtSD) \ V(Mips64CvtDS) \ V(Mips64TruncWD) \ diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc index 0dba931..35ad16b 100644 --- a/src/compiler/mips64/instruction-selector-mips64.cc +++ b/src/compiler/mips64/instruction-selector-mips64.cc @@ -609,17 +609,17 @@ void InstructionSelector::VisitFloat64Sqrt(Node* node) { void InstructionSelector::VisitFloat64Floor(Node* node) { - VisitRR(this, kMips64FloorD, node); + VisitRR(this, kMips64Float64Floor, node); } void InstructionSelector::VisitFloat64Ceil(Node* node) { - VisitRR(this, kMips64CeilD, node); + VisitRR(this, kMips64Float64Ceil, node); } void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { - VisitRR(this, kMips64RoundTruncateD, node); + VisitRR(this, kMips64Float64RoundTruncate, node); } @@ -1069,7 +1069,9 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { // static MachineOperatorBuilder::Flags InstructionSelector::SupportedMachineOperatorFlags() { - return MachineOperatorBuilder::kNoFlags; + return MachineOperatorBuilder::kFloat64Floor | + MachineOperatorBuilder::kFloat64Ceil | + MachineOperatorBuilder::kFloat64RoundTruncate; } } // namespace compiler -- 2.7.4