Index: src/arm/lithium-arm.h |
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h |
index 127badcfe929691bcb595b7fce40dab89361da9c..6eb28374a5bab1a4f706553d01a002c561da7996 100644 |
--- a/src/arm/lithium-arm.h |
+++ b/src/arm/lithium-arm.h |
@@ -1239,7 +1239,14 @@ class LBoundsCheck V8_FINAL : public LTemplateInstruction<0, 2, 0> { |
class LBitI V8_FINAL : public LTemplateInstruction<1, 2, 0> { |
public: |
- LBitI(LOperand* left, LOperand* right) { |
+ LBitI(LOperand* left, LOperand* right) |
+ : shift_(NO_SHIFT), shift_amount_(0) { |
+ inputs_[0] = left; |
+ inputs_[1] = right; |
+ } |
+ |
+ LBitI(LOperand* left, LOperand* right, ShiftOp shift, LOperand* shift_amount) |
+ : shift_(shift), shift_amount_(shift_amount) { |
inputs_[0] = left; |
inputs_[1] = right; |
} |
@@ -1247,10 +1254,17 @@ class LBitI V8_FINAL : public LTemplateInstruction<1, 2, 0> { |
LOperand* left() { return inputs_[0]; } |
LOperand* right() { return inputs_[1]; } |
+ ShiftOp shift() const { return shift_; } |
+ LOperand* shift_amount() const { return shift_amount_; } |
+ |
Token::Value op() const { return hydrogen()->op(); } |
DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i") |
DECLARE_HYDROGEN_ACCESSOR(Bitwise) |
+ |
+ protected: |
+ ShiftOp shift_; |
+ LOperand* shift_amount_; |
}; |
@@ -1277,16 +1291,30 @@ class LShiftI V8_FINAL : public LTemplateInstruction<1, 2, 0> { |
class LSubI V8_FINAL : public LTemplateInstruction<1, 2, 0> { |
public: |
- LSubI(LOperand* left, LOperand* right) { |
+ LSubI(LOperand* left, LOperand* right) |
+ : shift_(NO_SHIFT), shift_amount_(0) { |
+ inputs_[0] = left; |
+ inputs_[1] = right; |
+ } |
+ |
+ LSubI(LOperand* left, LOperand* right, ShiftOp shift, LOperand* shift_amount) |
+ : shift_(shift), shift_amount_(shift_amount) { |
inputs_[0] = left; |
inputs_[1] = right; |
} |
+ ShiftOp shift() const { return shift_; } |
+ LOperand* shift_amount() const { return shift_amount_; } |
+ |
LOperand* left() { return inputs_[0]; } |
LOperand* right() { return inputs_[1]; } |
DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i") |
DECLARE_HYDROGEN_ACCESSOR(Sub) |
+ |
+ protected: |
+ ShiftOp shift_; |
+ LOperand* shift_amount_; |
}; |
@@ -1455,7 +1483,14 @@ class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 4, 0> { |
class LAddI V8_FINAL : public LTemplateInstruction<1, 2, 0> { |
public: |
- LAddI(LOperand* left, LOperand* right) { |
+ LAddI(LOperand* left, LOperand* right) |
+ : shift_(NO_SHIFT), shift_amount_(0) { |
+ inputs_[0] = left; |
+ inputs_[1] = right; |
+ } |
+ |
+ LAddI(LOperand* left, LOperand* right, ShiftOp shift, LOperand* shift_amount) |
+ : shift_(shift), shift_amount_(shift_amount) { |
inputs_[0] = left; |
inputs_[1] = right; |
} |
@@ -1463,8 +1498,15 @@ class LAddI V8_FINAL : public LTemplateInstruction<1, 2, 0> { |
LOperand* left() { return inputs_[0]; } |
LOperand* right() { return inputs_[1]; } |
+ ShiftOp shift() const { return shift_; } |
+ LOperand* shift_amount() const { return shift_amount_; } |
+ |
DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i") |
DECLARE_HYDROGEN_ACCESSOR(Add) |
+ |
+ protected: |
+ ShiftOp shift_; |
+ LOperand* shift_amount_; |
}; |
@@ -2855,6 +2897,49 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { |
void AddInstruction(LInstruction* instr, HInstruction* current); |
void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block); |
+ |
+ int JSShiftAmountFromHConstant(HValue* constant) { |
+ return HConstant::cast(constant)->Integer32Value() & 0x1f; |
+ } |
+ bool LikelyFitsImmField(HInstruction* instr, int imm) { |
+ Instr instr_bits; |
+ // All arithmetic and logical operations accept the same range of |
+ // immediates. In some cases though, the operation itself can be changed to |
+ // get a wider effective range of immediates. |
+ if (instr->IsAdd() || instr->IsSub()) { |
+ // ADD and SUB can be exchanged with a negate immediate. |
+ instr_bits = ADD; |
+ } else if (HBitwise::cast(instr)->op() == Token::BIT_AND) { |
+ ASSERT(instr->IsBitwise()); |
+ // AND and BIC can be exchanged with an inverted immediate. |
+ instr_bits = AND; |
+ } else { |
+ ASSERT(instr->IsBitwise()); |
+ // Use ORR for all other operations, since fits_shifter() can't adapt ORR. |
+ instr_bits = ORR; |
+ } |
+ return fits_shifter(imm, NULL, NULL, &instr_bits); |
+ } |
+ |
+ // Indicates if a sequence of the form |
+ // mov r1, r2 LSL #imm |
+ // add r0, r5, r1 |
+ // can be replaced with: |
+ // add r0, r5, r2 LSL #imm |
+ // If this is not possible, the function returns NULL. Otherwise it returns a |
+ // pointer to the shift instruction that would be optimized away. |
+ HBitwiseBinaryOperation* CanTransformToShiftedOp(HValue* val, |
+ HValue** left = NULL); |
+ // Checks if all uses of the shift operation can optimize it away. |
+ bool ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift); |
+ // Attempts to merge the binary operation and a previous shift operation into |
+ // a single operation. Returns the merged instruction on success, and NULL |
+ // otherwise. |
+ LInstruction* TryDoOpWithShiftedRightOperand(HBinaryOperation* op); |
+ LInstruction* DoShiftedBinaryOp(HBinaryOperation* instr, |
+ HValue* left, |
+ HBitwiseBinaryOperation* shift); |
+ |
LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr); |
LInstruction* DoArithmeticD(Token::Value op, |
HArithmeticBinaryOperation* instr); |