Reviewers: ulan,

Message:
I couldn't measure any performance impact on the benchmarks with this, but
thought I might as well upload it anyway.

Running Octane in the simulator with this patch hits 300k new RST instructions,
so it does occur in benchmarks but perhaps not enough to make a measurable
difference.

I'll leave it to the reviewers to decide whether the improved generated code
quality is worth the changes to V8.

Description:
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, r1, #100

thus saving a mov.

BUG=


Please review this at https://codereview.chromium.org/11308040/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/arm/lithium-arm.h
  M src/arm/lithium-arm.cc
  M src/arm/lithium-codegen-arm.cc


Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 5cd691461f6308949bb47ef62e66fc5f4edcd355..833595c244f6c664da731da7b4d6c704fd8d62e7 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1328,6 +1328,13 @@ 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.
+      ASSERT(!instr->right()->IsConstant());
+      return DoRSub(instr);
+    }
+
     LOperand* left = UseRegisterAtStart(instr->left());
     LOperand* right = UseOrConstantAtStart(instr->right());
     LSubI* sub = new(zone()) LSubI(left, right);
@@ -1343,6 +1350,25 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
   }
 }

+
+LInstruction* LChunkBuilder::DoRSub(HSub* instr) {
+  ASSERT(instr->representation().IsInteger32());
+  ASSERT(instr->left().IsInteger32());
+  ASSERT(instr->right().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());
Index: src/arm/lithium-arm.h
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 0367fd3234abed7a836df1ca8d95bf1828476732..0434ba925d1a7c335da90a5a113b30b67c40e717 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);
Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 0a28d343bac887ccdeb673f9b8ea4180e05da031..204a15586c6fb71d886d8326c3a9a2b2661397c5 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()));


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to