Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 44f9b8a64be51c79fd50bb24d569d57c5730ebc2..ce08766749b7ac7404b72e6233bed00ff8cc28c2 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -3405,9 +3405,36 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
EliminateRedundantBoundsChecks(); |
DehoistSimpleArrayIndexComputations(); |
+ EliminateUnusedInstructions(); |
+ |
return true; |
} |
+void HGraph::EliminateUnusedInstructions() { |
+ HPhase phase("H_EliminateUnusedInstructions", this); |
ulan
2012/10/01 18:15:19
Maybe I should just do one pass instead of this co
|
+ ZoneList<HInstruction*> worklist(blocks_.length(), zone()); |
+ for (int i = 0; i < blocks()->length(); ++i) { |
+ HInstruction* instr = blocks()->at(i)->first(); |
+ while (instr != NULL) { |
+ if (instr->UnusedAndSafeToDelete()) { |
+ worklist.Add(instr, zone()); |
+ } |
+ instr = instr->next(); |
+ } |
+ } |
+ |
+ while (!worklist.is_empty()) { |
+ HInstruction* instr = worklist.RemoveLast(); |
+ instr->DeleteAndReplaceWith(NULL); |
+ for (int i = 0; i < instr->OperandCount(); ++i) { |
+ HValue* operand = instr->OperandAt(i); |
+ if (operand->IsInstruction() && |
+ HInstruction::cast(operand)->UnusedAndSafeToDelete()) { |
+ worklist.Add(HInstruction::cast(operand), zone()); |
+ } |
+ } |
+ } |
+} |
// We try to "factor up" HBoundsCheck instructions towards the root of the |
// dominator tree. |
@@ -8254,6 +8281,61 @@ HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, |
return new(zone()) HStringCharCodeAt(context, string, checked_index); |
} |
+// Checks if the given shift amounts have form: (sa) and (32 - sa). |
+static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
+ HValue* const32_minus_sa) { |
+ if (!const32_minus_sa->IsSub()) return false; |
+ HSub* sub = HSub::cast(const32_minus_sa); |
+ HValue* const32 = sub->left(); |
+ if (!const32->IsConstant() || |
+ HConstant::cast(const32)->Integer32Value() != 32) { |
+ return false; |
+ } |
+ return (sub->right() == sa); |
+} |
+ |
+ |
+// Checks if the left and the right are shift instructions with the oposite |
+// directions that can be replaced by one rotate right instruction or not. |
+// Returns the operand and the shift amount for the rotate instruction in the |
+// former case. |
+bool HGraphBuilder::MatchRotateRight(HValue* left, |
+ HValue* right, |
+ HValue** operand, |
+ HValue** shift_amount) { |
+ HShl* shl; |
+ HShr* shr; |
+ if (left->IsShl() && right->IsShr()) { |
+ shl = HShl::cast(left); |
+ shr = HShr::cast(right); |
+ } else if (left->IsShr() && right->IsShl()) { |
+ shl = HShl::cast(right); |
+ shr = HShr::cast(left); |
+ } else { |
+ return false; |
+ } |
+ |
+ if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) && |
+ !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) { |
+ return false; |
+ } |
+ *operand= shr->left(); |
+ *shift_amount = shr->right(); |
+ return true; |
+} |
+ |
+ |
+bool CanBeZero(HValue *right) { |
+ if (right->IsConstant()) { |
+ HConstant* right_const = HConstant::cast(right); |
+ if (right_const->HasInteger32Value() && |
+ (right_const->Integer32Value() & 0x1f) != 0) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
HValue* left, |
@@ -8292,25 +8374,26 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
break; |
case Token::BIT_XOR: |
case Token::BIT_AND: |
- case Token::BIT_OR: |
instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); |
break; |
+ case Token::BIT_OR: { |
+ HValue* operand, *shift_amount; |
+ if (info.IsInteger32() && |
+ MatchRotateRight(left, right, &operand, &shift_amount)) { |
+ instr = new(zone()) HRor(context, operand, shift_amount); |
+ } else { |
+ instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); |
+ } |
+ break; |
+ } |
case Token::SAR: |
instr = HSar::NewHSar(zone(), context, left, right); |
break; |
case Token::SHR: |
instr = HShr::NewHShr(zone(), context, left, right); |
- if (FLAG_opt_safe_uint32_operations && instr->IsShr()) { |
- bool can_be_shift_by_zero = true; |
- if (right->IsConstant()) { |
- HConstant* right_const = HConstant::cast(right); |
- if (right_const->HasInteger32Value() && |
- (right_const->Integer32Value() & 0x1f) != 0) { |
- can_be_shift_by_zero = false; |
- } |
- } |
- |
- if (can_be_shift_by_zero) graph()->RecordUint32Instruction(instr); |
+ if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
+ CanBeZero(right)) { |
+ graph()->RecordUint32Instruction(instr); |
} |
break; |
case Token::SHL: |