From 93fe6abc6c0d80fb2c48b1127fe5382c0ea08894 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Thu, 9 Aug 2012 08:28:52 +0000 Subject: [PATCH] MIPS: Refactor Math.min/max to be a single HInstruction. Port r12265 (7501dd73) BUG= TEST= Review URL: https://chromiumcodereview.appspot.com/10854053 Patch from Akos Palfi . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12282 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/lithium-codegen-mips.cc | 62 ++++++++++++++++++++++++++++++++++++++++ src/mips/lithium-mips.cc | 19 ++++++++++++ src/mips/lithium-mips.h | 15 +++++++++- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index ac0395d..723099a 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -1360,6 +1360,68 @@ void LCodeGen::DoAddI(LAddI* instr) { } +void LCodeGen::DoMathMinMax(LMathMinMax* instr) { + LOperand* left = instr->InputAt(0); + LOperand* right = instr->InputAt(1); + HMathMinMax::Operation operation = instr->hydrogen()->operation(); + Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; + if (instr->hydrogen()->representation().IsInteger32()) { + Register left_reg = ToRegister(left); + Operand right_op = (right->IsRegister() || right->IsConstantOperand()) + ? ToOperand(right) + : Operand(EmitLoadRegister(right, at)); + Register result_reg = ToRegister(instr->result()); + Label return_right, done; + if (!result_reg.is(left_reg)) { + __ Branch(&return_right, NegateCondition(condition), left_reg, right_op); + __ mov(result_reg, left_reg); + __ Branch(&done); + } + __ Branch(&done, condition, left_reg, right_op); + __ bind(&return_right); + __ Addu(result_reg, zero_reg, right_op); + __ bind(&done); + } else { + ASSERT(instr->hydrogen()->representation().IsDouble()); + FPURegister left_reg = ToDoubleRegister(left); + FPURegister right_reg = ToDoubleRegister(right); + FPURegister result_reg = ToDoubleRegister(instr->result()); + Label check_nan_left, check_zero, return_left, return_right, done; + __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg); + __ BranchF(&return_left, NULL, condition, left_reg, right_reg); + __ Branch(&return_right); + + __ bind(&check_zero); + // left == right != 0. + __ BranchF(&return_left, NULL, ne, left_reg, kDoubleRegZero); + // At this point, both left and right are either 0 or -0. + if (operation == HMathMinMax::kMathMin) { + __ neg_d(left_reg, left_reg); + __ sub_d(result_reg, left_reg, right_reg); + __ neg_d(result_reg, result_reg); + } else { + __ add_d(result_reg, left_reg, right_reg); + } + __ Branch(&done); + + __ bind(&check_nan_left); + // left == NaN. + __ BranchF(NULL, &return_left, eq, left_reg, left_reg); + __ bind(&return_right); + if (!right_reg.is(result_reg)) { + __ mov_d(result_reg, right_reg); + } + __ Branch(&done); + + __ bind(&return_left); + if (!left_reg.is(result_reg)) { + __ mov_d(result_reg, left_reg); + } + __ bind(&done); + } +} + + void LCodeGen::DoArithmeticD(LArithmeticD* instr) { DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 3513d20..6cbb2a1 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1296,6 +1296,25 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } +LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { + LOperand* left = NULL; + LOperand* right = NULL; + if (instr->representation().IsInteger32()) { + ASSERT(instr->left()->representation().IsInteger32()); + ASSERT(instr->right()->representation().IsInteger32()); + left = UseRegisterAtStart(instr->LeastConstantOperand()); + right = UseOrConstantAtStart(instr->MostConstantOperand()); + } else { + ASSERT(instr->representation().IsDouble()); + ASSERT(instr->left()->representation().IsDouble()); + ASSERT(instr->right()->representation().IsDouble()); + left = UseRegisterAtStart(instr->left()); + right = UseRegisterAtStart(instr->right()); + } + return DefineAsRegister(new(zone()) LMathMinMax(left, right)); +} + + LInstruction* LChunkBuilder::DoPower(HPower* instr) { ASSERT(instr->representation().IsDouble()); // We call a C function for double power. It can't trigger a GC. diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index 5d5de5e..5aba86d 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -115,7 +115,6 @@ class LCodeGen; V(IsStringAndBranch) \ V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ - V(StringCompareAndBranch) \ V(JSArrayLength) \ V(Label) \ V(LazyBailout) \ @@ -132,6 +131,7 @@ class LCodeGen; V(LoadNamedField) \ V(LoadNamedFieldPolymorphic) \ V(LoadNamedGeneric) \ + V(MathMinMax) \ V(ModI) \ V(MulI) \ V(NumberTagD) \ @@ -162,6 +162,7 @@ class LCodeGen; V(StringAdd) \ V(StringCharCodeAt) \ V(StringCharFromCode) \ + V(StringCompareAndBranch) \ V(StringLength) \ V(SubI) \ V(TaggedToI) \ @@ -1049,6 +1050,18 @@ class LAddI: public LTemplateInstruction<1, 2, 0> { }; +class LMathMinMax: public LTemplateInstruction<1, 2, 0> { + public: + LMathMinMax(LOperand* left, LOperand* right) { + inputs_[0] = left; + inputs_[1] = right; + } + + DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "min-max") + DECLARE_HYDROGEN_ACCESSOR(MathMinMax) +}; + + class LPower: public LTemplateInstruction<1, 2, 0> { public: LPower(LOperand* left, LOperand* right) { -- 2.7.4