| Index: src/hydrogen.cc
|
| ===================================================================
|
| --- src/hydrogen.cc (revision 12582)
|
| +++ src/hydrogen.cc (working copy)
|
| @@ -1021,6 +1021,98 @@
|
| };
|
|
|
|
|
| +// Help with TryRotate pattern matching by checking if sub is 32 - s. It's okay
|
| +// if the right operand of sub isn't the same HValue as s if both are HChange
|
| +// instructions from the same value. This is called twice to determine whether
|
| +// we do a left or right rotation.
|
| +static bool TryMatchShiftAmountForRotate(HValue* s, HValue* sub) {
|
| + if (!sub->IsSub())
|
| + return false;
|
| + HValue* subl = HSub::cast(sub)->left();
|
| + HValue* subr = HSub::cast(sub)->right();
|
| + return subl->representation().IsInteger32() &&
|
| + subl->IsConstant() &&
|
| + HConstant::cast(subl)->Integer32Value() == 32 &&
|
| + (s == subr ||
|
| + (subr->IsChange() && s->IsChange() &&
|
| + subr->OperandAt(0) == s->OperandAt(0)));
|
| +}
|
| +
|
| +
|
| +// Attempt to replace one of the following patterns with a rotate instruction:
|
| +// n << s | n >>> (32 - s) ==> rotate left
|
| +// n >>> s | n << (32 - s) ==> rotate right
|
| +bool HGraph::TryRotate(HInstruction* instr) {
|
| + HBitwise* bor = HBitwise::cast(instr);
|
| + ASSERT(bor->op() == Token::BIT_OR);
|
| + HShl* shl;
|
| + HShr* shr;
|
| + if (bor->left()->IsShl() && bor->right()->IsShr()) {
|
| + shl = HShl::cast(bor->left());
|
| + shr = HShr::cast(bor->right());
|
| + } else if (bor->left()->IsShr() && bor->right()->IsShl()) {
|
| + shl = HShl::cast(bor->right());
|
| + shr = HShr::cast(bor->left());
|
| + } else {
|
| + return false;
|
| + }
|
| +
|
| + // Neither shift can be used elsewhere (or it is not safe to delete them).
|
| + // Also, both must have Integer32 representation, since we can't rotate
|
| + // anything else quickly.
|
| + if (shl->UseCount() > 1 || !shl->representation().IsInteger32() ||
|
| + shr->UseCount() > 1 || !shr->representation().IsInteger32() ||
|
| + !shr->right()->representation().IsInteger32() ||
|
| + !shr->left()->representation().IsInteger32() ||
|
| + !shl->right()->representation().IsInteger32() ||
|
| + !shl->left()->representation().IsInteger32()) {
|
| + return false;
|
| + }
|
| +
|
| + // The value being shifted must be the same.
|
| + if (shl->left() != shr->left())
|
| + return false;
|
| + HValue* number = shl->left();
|
| +
|
| + // The shift values must be s and 32-s. Whether we have found a left or
|
| + // right rotate depends on which shift has 32-s. Note that it's okay if the
|
| + // "s" values on both sides are distinct HChange instructions, as long as
|
| + // their operands are the same value.
|
| + HValue* shift_amount = NULL;
|
| + if (TryMatchShiftAmountForRotate(shl->right(), shr->right()) |
|
| + TryMatchShiftAmountForRotate(shr->right(), shl->right())) {
|
| + shift_amount = shr->right();
|
| + } else {
|
| + return false;
|
| + }
|
| +
|
| + // We have matched all the operands. Do the replacement.
|
| + HRor* ror = new(zone()) HRor(shr->context(), number, shift_amount);
|
| + ror->InsertAfter(bor);
|
| + bor->DeleteAndReplaceWith(ror);
|
| + shl->DeleteAndReplaceWith(NULL);
|
| + shr->DeleteAndReplaceWith(NULL);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +
|
| +void HGraph::ReplaceWithRor() {
|
| + if (!FLAG_use_replace_with_ror) return;
|
| + HPhase phase("H_Replace with ror", this);
|
| + for (int i = 0; i < blocks()->length(); ++i) {
|
| + HInstruction* instr = blocks()->at(i)->first();
|
| + while (instr != NULL) {
|
| + if (instr->IsBitwise() &&
|
| + HBitwise::cast(instr)->op() == Token::BIT_OR) {
|
| + TryRotate(instr);
|
| + }
|
| + instr = instr->next();
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void HGraph::OrderBlocks() {
|
| HPhase phase("H_Block ordering");
|
| BitVector visited(blocks_.length(), zone());
|
| @@ -3402,6 +3494,12 @@
|
| HStackCheckEliminator sce(this);
|
| sce.Process();
|
|
|
| +#if defined(V8_TARGET_ARCH_ARM)
|
| + // TODO: support rotate instructions on other architectures. For now they are
|
| + // only supported on ARM.
|
| + ReplaceWithRor();
|
| +#endif
|
| +
|
| EliminateRedundantBoundsChecks();
|
| DehoistSimpleArrayIndexComputations();
|
|
|
|
|