Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3398 } | 3398 } |
| 3399 ComputeMinusZeroChecks(); | 3399 ComputeMinusZeroChecks(); |
| 3400 | 3400 |
| 3401 // Eliminate redundant stack checks on backwards branches. | 3401 // Eliminate redundant stack checks on backwards branches. |
| 3402 HStackCheckEliminator sce(this); | 3402 HStackCheckEliminator sce(this); |
| 3403 sce.Process(); | 3403 sce.Process(); |
| 3404 | 3404 |
| 3405 EliminateRedundantBoundsChecks(); | 3405 EliminateRedundantBoundsChecks(); |
| 3406 DehoistSimpleArrayIndexComputations(); | 3406 DehoistSimpleArrayIndexComputations(); |
| 3407 | 3407 |
| 3408 EliminateUnusedInstructions(); | |
| 3409 | |
| 3408 return true; | 3410 return true; |
| 3409 } | 3411 } |
| 3410 | 3412 |
| 3413 void HGraph::EliminateUnusedInstructions() { | |
| 3414 HPhase phase("H_EliminateUnusedInstructions", this); | |
|
ulan
2012/10/01 18:15:19
Maybe I should just do one pass instead of this co
| |
| 3415 ZoneList<HInstruction*> worklist(blocks_.length(), zone()); | |
| 3416 for (int i = 0; i < blocks()->length(); ++i) { | |
| 3417 HInstruction* instr = blocks()->at(i)->first(); | |
| 3418 while (instr != NULL) { | |
| 3419 if (instr->UnusedAndSafeToDelete()) { | |
| 3420 worklist.Add(instr, zone()); | |
| 3421 } | |
| 3422 instr = instr->next(); | |
| 3423 } | |
| 3424 } | |
| 3425 | |
| 3426 while (!worklist.is_empty()) { | |
| 3427 HInstruction* instr = worklist.RemoveLast(); | |
| 3428 instr->DeleteAndReplaceWith(NULL); | |
| 3429 for (int i = 0; i < instr->OperandCount(); ++i) { | |
| 3430 HValue* operand = instr->OperandAt(i); | |
| 3431 if (operand->IsInstruction() && | |
| 3432 HInstruction::cast(operand)->UnusedAndSafeToDelete()) { | |
| 3433 worklist.Add(HInstruction::cast(operand), zone()); | |
| 3434 } | |
| 3435 } | |
| 3436 } | |
| 3437 } | |
| 3411 | 3438 |
| 3412 // We try to "factor up" HBoundsCheck instructions towards the root of the | 3439 // We try to "factor up" HBoundsCheck instructions towards the root of the |
| 3413 // dominator tree. | 3440 // dominator tree. |
| 3414 // For now we handle checks where the index is like "exp + int32value". | 3441 // For now we handle checks where the index is like "exp + int32value". |
| 3415 // If in the dominator tree we check "exp + v1" and later (dominated) | 3442 // If in the dominator tree we check "exp + v1" and later (dominated) |
| 3416 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if | 3443 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if |
| 3417 // v2 > v1 we can use v2 in the 1st check and again remove the second. | 3444 // v2 > v1 we can use v2 in the 1st check and again remove the second. |
| 3418 // To do so we keep a dictionary of all checks where the key if the pair | 3445 // To do so we keep a dictionary of all checks where the key if the pair |
| 3419 // "exp, length". | 3446 // "exp, length". |
| 3420 // The class BoundsCheckKey represents this key. | 3447 // The class BoundsCheckKey represents this key. |
| (...skipping 4826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8247 HValue* index) { | 8274 HValue* index) { |
| 8248 AddInstruction(new(zone()) HCheckNonSmi(string)); | 8275 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 8249 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 8276 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 8250 HStringLength* length = new(zone()) HStringLength(string); | 8277 HStringLength* length = new(zone()) HStringLength(string); |
| 8251 AddInstruction(length); | 8278 AddInstruction(length); |
| 8252 HInstruction* checked_index = | 8279 HInstruction* checked_index = |
| 8253 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 8280 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 8254 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 8281 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| 8255 } | 8282 } |
| 8256 | 8283 |
| 8284 // Checks if the given shift amounts have form: (sa) and (32 - sa). | |
| 8285 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | |
| 8286 HValue* const32_minus_sa) { | |
| 8287 if (!const32_minus_sa->IsSub()) return false; | |
| 8288 HSub* sub = HSub::cast(const32_minus_sa); | |
| 8289 HValue* const32 = sub->left(); | |
| 8290 if (!const32->IsConstant() || | |
| 8291 HConstant::cast(const32)->Integer32Value() != 32) { | |
| 8292 return false; | |
| 8293 } | |
| 8294 return (sub->right() == sa); | |
| 8295 } | |
| 8296 | |
| 8297 | |
| 8298 // Checks if the left and the right are shift instructions with the oposite | |
| 8299 // directions that can be replaced by one rotate right instruction or not. | |
| 8300 // Returns the operand and the shift amount for the rotate instruction in the | |
| 8301 // former case. | |
| 8302 bool HGraphBuilder::MatchRotateRight(HValue* left, | |
| 8303 HValue* right, | |
| 8304 HValue** operand, | |
| 8305 HValue** shift_amount) { | |
| 8306 HShl* shl; | |
| 8307 HShr* shr; | |
| 8308 if (left->IsShl() && right->IsShr()) { | |
| 8309 shl = HShl::cast(left); | |
| 8310 shr = HShr::cast(right); | |
| 8311 } else if (left->IsShr() && right->IsShl()) { | |
| 8312 shl = HShl::cast(right); | |
| 8313 shr = HShr::cast(left); | |
| 8314 } else { | |
| 8315 return false; | |
| 8316 } | |
| 8317 | |
| 8318 if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) && | |
| 8319 !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) { | |
| 8320 return false; | |
| 8321 } | |
| 8322 *operand= shr->left(); | |
| 8323 *shift_amount = shr->right(); | |
| 8324 return true; | |
| 8325 } | |
| 8326 | |
| 8327 | |
| 8328 bool CanBeZero(HValue *right) { | |
| 8329 if (right->IsConstant()) { | |
| 8330 HConstant* right_const = HConstant::cast(right); | |
| 8331 if (right_const->HasInteger32Value() && | |
| 8332 (right_const->Integer32Value() & 0x1f) != 0) { | |
| 8333 return false; | |
| 8334 } | |
| 8335 } | |
| 8336 return true; | |
| 8337 } | |
| 8338 | |
| 8257 | 8339 |
| 8258 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 8340 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
| 8259 HValue* left, | 8341 HValue* left, |
| 8260 HValue* right) { | 8342 HValue* right) { |
| 8261 HValue* context = environment()->LookupContext(); | 8343 HValue* context = environment()->LookupContext(); |
| 8262 TypeInfo info = oracle()->BinaryType(expr); | 8344 TypeInfo info = oracle()->BinaryType(expr); |
| 8263 if (info.IsUninitialized()) { | 8345 if (info.IsUninitialized()) { |
| 8264 AddInstruction(new(zone()) HSoftDeoptimize); | 8346 AddInstruction(new(zone()) HSoftDeoptimize); |
| 8265 current_block()->MarkAsDeoptimizing(); | 8347 current_block()->MarkAsDeoptimizing(); |
| 8266 info = TypeInfo::Unknown(); | 8348 info = TypeInfo::Unknown(); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 8285 instr = HMul::NewHMul(zone(), context, left, right); | 8367 instr = HMul::NewHMul(zone(), context, left, right); |
| 8286 break; | 8368 break; |
| 8287 case Token::MOD: | 8369 case Token::MOD: |
| 8288 instr = HMod::NewHMod(zone(), context, left, right); | 8370 instr = HMod::NewHMod(zone(), context, left, right); |
| 8289 break; | 8371 break; |
| 8290 case Token::DIV: | 8372 case Token::DIV: |
| 8291 instr = HDiv::NewHDiv(zone(), context, left, right); | 8373 instr = HDiv::NewHDiv(zone(), context, left, right); |
| 8292 break; | 8374 break; |
| 8293 case Token::BIT_XOR: | 8375 case Token::BIT_XOR: |
| 8294 case Token::BIT_AND: | 8376 case Token::BIT_AND: |
| 8295 case Token::BIT_OR: | |
| 8296 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); | 8377 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); |
| 8297 break; | 8378 break; |
| 8379 case Token::BIT_OR: { | |
| 8380 HValue* operand, *shift_amount; | |
| 8381 if (info.IsInteger32() && | |
| 8382 MatchRotateRight(left, right, &operand, &shift_amount)) { | |
| 8383 instr = new(zone()) HRor(context, operand, shift_amount); | |
| 8384 } else { | |
| 8385 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); | |
| 8386 } | |
| 8387 break; | |
| 8388 } | |
| 8298 case Token::SAR: | 8389 case Token::SAR: |
| 8299 instr = HSar::NewHSar(zone(), context, left, right); | 8390 instr = HSar::NewHSar(zone(), context, left, right); |
| 8300 break; | 8391 break; |
| 8301 case Token::SHR: | 8392 case Token::SHR: |
| 8302 instr = HShr::NewHShr(zone(), context, left, right); | 8393 instr = HShr::NewHShr(zone(), context, left, right); |
| 8303 if (FLAG_opt_safe_uint32_operations && instr->IsShr()) { | 8394 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
| 8304 bool can_be_shift_by_zero = true; | 8395 CanBeZero(right)) { |
| 8305 if (right->IsConstant()) { | 8396 graph()->RecordUint32Instruction(instr); |
| 8306 HConstant* right_const = HConstant::cast(right); | |
| 8307 if (right_const->HasInteger32Value() && | |
| 8308 (right_const->Integer32Value() & 0x1f) != 0) { | |
| 8309 can_be_shift_by_zero = false; | |
| 8310 } | |
| 8311 } | |
| 8312 | |
| 8313 if (can_be_shift_by_zero) graph()->RecordUint32Instruction(instr); | |
| 8314 } | 8397 } |
| 8315 break; | 8398 break; |
| 8316 case Token::SHL: | 8399 case Token::SHL: |
| 8317 instr = HShl::NewHShl(zone(), context, left, right); | 8400 instr = HShl::NewHShl(zone(), context, left, right); |
| 8318 break; | 8401 break; |
| 8319 default: | 8402 default: |
| 8320 UNREACHABLE(); | 8403 UNREACHABLE(); |
| 8321 } | 8404 } |
| 8322 | 8405 |
| 8323 // If we hit an uninitialized binary op stub we will get type info | 8406 // If we hit an uninitialized binary op stub we will get type info |
| (...skipping 1659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9983 } | 10066 } |
| 9984 } | 10067 } |
| 9985 | 10068 |
| 9986 #ifdef DEBUG | 10069 #ifdef DEBUG |
| 9987 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10070 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 9988 if (allocator_ != NULL) allocator_->Verify(); | 10071 if (allocator_ != NULL) allocator_->Verify(); |
| 9989 #endif | 10072 #endif |
| 9990 } | 10073 } |
| 9991 | 10074 |
| 9992 } } // namespace v8::internal | 10075 } } // namespace v8::internal |
| OLD | NEW |