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); |
| 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 |