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 <hans@chromium.org>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13017 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
6add3222ed
commit
6a6012c0e7
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
|
Loading…
Reference in New Issue
Block a user