From 6a6012c0e7c05fa6de80ad3eebbc1fcd2f3c2f0e Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Tue, 20 Nov 2012 14:46:16 +0000 Subject: [PATCH] Emit RSB for subtraction with constant lhs on ARM Instead of generating the following for "100 - x": mov r1, #100 subs r0, r1, r0 this patch makes Crankshaft generate this: rsbs r0, r0, #100 thus saving a register and a mov. BUG= Review URL: https://chromiumcodereview.appspot.com/11308040 Patch from Hans Wennborg . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13017 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 25 +++++++++++++++++++++++++ src/arm/lithium-arm.h | 17 +++++++++++++++++ src/arm/lithium-codegen-arm.cc | 21 +++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 5cd691461f..4b457a134d 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1328,6 +1328,12 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) { if (instr->representation().IsInteger32()) { ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32()); + + if (instr->left()->IsConstant()) { + // If lhs is constant, do reverse subtraction instead. + return DoRSub(instr); + } + LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseOrConstantAtStart(instr->right()); LSubI* sub = new(zone()) LSubI(left, right); @@ -1343,6 +1349,25 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) { } } + +LInstruction* LChunkBuilder::DoRSub(HSub* instr) { + ASSERT(instr->representation().IsInteger32()); + ASSERT(instr->left()->representation().IsInteger32()); + ASSERT(instr->right()->representation().IsInteger32()); + + // Note: The lhs of the subtraction becomes the rhs of the + // reverse-subtraction. + LOperand* left = UseRegisterAtStart(instr->right()); + LOperand* right = UseOrConstantAtStart(instr->left()); + LRSubI* rsb = new(zone()) LRSubI(left, right); + LInstruction* result = DefineAsRegister(rsb); + if (instr->CheckFlag(HValue::kCanOverflow)) { + result = AssignEnvironment(result); + } + return result; +} + + LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { LOperand* multiplier_op = UseRegisterAtStart(mul->left()); LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 0367fd3234..0434ba925d 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -166,6 +166,7 @@ class LCodeGen; V(StringCompareAndBranch) \ V(StringLength) \ V(SubI) \ + V(RSubI) \ V(TaggedToI) \ V(ThisFunction) \ V(Throw) \ @@ -1004,6 +1005,21 @@ class LSubI: public LTemplateInstruction<1, 2, 0> { }; +class LRSubI: public LTemplateInstruction<1, 2, 0> { + public: + LRSubI(LOperand* left, LOperand* right) { + inputs_[0] = left; + inputs_[1] = right; + } + + LOperand* left() { return inputs_[0]; } + LOperand* right() { return inputs_[1]; } + + DECLARE_CONCRETE_INSTRUCTION(RSubI, "rsub-i") + DECLARE_HYDROGEN_ACCESSOR(Sub) +}; + + class LConstantI: public LTemplateInstruction<1, 0, 0> { public: DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i") @@ -2416,6 +2432,7 @@ class LChunkBuilder BASE_EMBEDDED { #undef DECLARE_DO LInstruction* DoMultiplyAdd(HMul* mul, HValue* addend); + LInstruction* DoRSub(HSub* instr); static bool HasMagicNumberForDivisor(int32_t divisor); static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* val); diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 0a28d343ba..204a15586c 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1619,6 +1619,27 @@ void LCodeGen::DoSubI(LSubI* instr) { } +void LCodeGen::DoRSubI(LRSubI* instr) { + LOperand* left = instr->left(); + LOperand* right = instr->right(); + LOperand* result = instr->result(); + bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); + SBit set_cond = can_overflow ? SetCC : LeaveCC; + + if (right->IsStackSlot() || right->IsArgument()) { + Register right_reg = EmitLoadRegister(right, ip); + __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); + } else { + ASSERT(right->IsRegister() || right->IsConstantOperand()); + __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); + } + + if (can_overflow) { + DeoptimizeIf(vs, instr->environment()); + } +} + + void LCodeGen::DoConstantI(LConstantI* instr) { ASSERT(instr->result()->IsRegister()); __ mov(ToRegister(instr->result()), Operand(instr->value()));