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