| 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 3295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3306 bool IsSafeUint32Use(HValue* val, HValue* use); | 3306 bool IsSafeUint32Use(HValue* val, HValue* use); |
| 3307 bool Uint32UsesAreSafe(HValue* uint32val); | 3307 bool Uint32UsesAreSafe(HValue* uint32val); |
| 3308 bool CheckPhiOperands(HPhi* phi); | 3308 bool CheckPhiOperands(HPhi* phi); |
| 3309 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist); | 3309 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist); |
| 3310 | 3310 |
| 3311 Zone* zone_; | 3311 Zone* zone_; |
| 3312 ZoneList<HPhi*> phis_; | 3312 ZoneList<HPhi*> phis_; |
| 3313 }; | 3313 }; |
| 3314 | 3314 |
| 3315 | 3315 |
| 3316 bool IsUint32Operation(HValue* instr) { |
| 3317 if (instr->IsShr()) return true; |
| 3318 if (instr->IsLoadKeyed() && |
| 3319 HLoadKeyed::cast(instr)->elements_kind() == |
| 3320 EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 3321 return true; |
| 3322 } |
| 3323 if (instr->IsInteger32Constant() && instr->GetInteger32Constant() >= 0) { |
| 3324 return true; |
| 3325 } |
| 3326 return false; |
| 3327 } |
| 3328 |
| 3329 |
| 3316 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) { | 3330 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) { |
| 3317 // Operations that operatate on bits are safe. | 3331 // Operations that operate on bits are safe. |
| 3318 if (use->IsBitwise() || | 3332 if (use->IsBitwise() || |
| 3319 use->IsShl() || | 3333 use->IsShl() || |
| 3320 use->IsSar() || | 3334 use->IsSar() || |
| 3321 use->IsShr() || | 3335 use->IsShr() || |
| 3322 use->IsBitNot()) { | 3336 use->IsBitNot()) { |
| 3323 return true; | 3337 return true; |
| 3324 } else if (use->IsChange() || use->IsSimulate()) { | 3338 } else if (use->IsChange() || use->IsSimulate()) { |
| 3325 // Conversions and deoptimization have special support for unt32. | 3339 // Conversions and deoptimization have special support for unt32. |
| 3326 return true; | 3340 return true; |
| 3327 } else if (use->IsStoreKeyed()) { | 3341 } else if (use->IsStoreKeyed()) { |
| 3328 HStoreKeyed* store = HStoreKeyed::cast(use); | 3342 HStoreKeyed* store = HStoreKeyed::cast(use); |
| 3329 if (store->is_external()) { | 3343 if (store->is_external()) { |
| 3330 // Storing a value into an external integer array is a bit level | 3344 // Storing a value into an external integer array is a bit level |
| 3331 // operation. | 3345 // operation. |
| 3332 if (store->value() == val) { | 3346 if (store->value() == val) { |
| 3333 // Clamping or a conversion to double should have beed inserted. | 3347 // Clamping or a conversion to double should have beed inserted. |
| 3334 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS); | 3348 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS); |
| 3335 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS); | 3349 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS); |
| 3336 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS); | 3350 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS); |
| 3337 return true; | 3351 return true; |
| 3338 } | 3352 } |
| 3339 } | 3353 } |
| 3354 } else if (use->IsCompareIDAndBranch()) { |
| 3355 for (int i = 0; i < use->OperandCount(); ++i) { |
| 3356 if (!IsUint32Operation(use->OperandAt(i))) return false; |
| 3357 } |
| 3358 return true; |
| 3359 } else if (use->IsDiv()) { |
| 3360 // Skip OperandAt(0) which is the context. |
| 3361 for (int i = 1; i < use->OperandCount(); ++i) { |
| 3362 if (!IsUint32Operation(use->OperandAt(i))) { |
| 3363 if (FLAG_trace_representation) { |
| 3364 HValue* op = use->OperandAt(i); |
| 3365 printf("#%d %s is not a safe uint32 use because of operand #%d %s\n", |
| 3366 use->id(), use->Mnemonic(), op->id(), op->Mnemonic()); |
| 3367 } |
| 3368 return false; |
| 3369 } |
| 3370 } |
| 3371 for (HUseIterator it(use->uses()); !it.Done(); it.Advance()) { |
| 3372 if (!IsSafeUint32Use(use, it.value())) { |
| 3373 if (FLAG_trace_representation) { |
| 3374 HValue* op = it.value(); |
| 3375 printf("#%d %s is not a safe uint32 use because of use #%d %s\n", |
| 3376 use->id(), use->Mnemonic(), op->id(), op->Mnemonic()); |
| 3377 } |
| 3378 return false; |
| 3379 } |
| 3380 } |
| 3381 if (FLAG_trace_representation) { |
| 3382 printf("#%d %s is a safe uint32 use :-)\n", use->id(), use->Mnemonic()); |
| 3383 } |
| 3384 return true; |
| 3340 } | 3385 } |
| 3341 | 3386 |
| 3342 return false; | 3387 return false; |
| 3343 } | 3388 } |
| 3344 | 3389 |
| 3345 | 3390 |
| 3346 // Iterate over all uses and verify that they are uint32 safe: either don't | 3391 // Iterate over all uses and verify that they are uint32 safe: either don't |
| 3347 // distinguish between int32 and uint32 due to their bitwise nature or | 3392 // distinguish between int32 and uint32 due to their bitwise nature or |
| 3348 // have special support for uint32 values. | 3393 // have special support for uint32 values. |
| 3349 // Encountered phis are optimisitically treated as safe uint32 uses, | 3394 // Encountered phis are optimistically treated as safe uint32 uses, |
| 3350 // marked with kUint32 flag and collected in the phis_ list. A separate | 3395 // marked with kUint32 flag and collected in the phis_ list. A separate |
| 3351 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from | 3396 // pass will be performed later by UnmarkUnsafePhis to clear kUint32 from |
| 3352 // phis that are not actually uint32-safe (it requries fix point iteration). | 3397 // phis that are not actually uint32-safe (it requires fix point iteration). |
| 3353 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) { | 3398 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) { |
| 3354 bool collect_phi_uses = false; | 3399 bool collect_phi_uses = false; |
| 3355 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | 3400 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { |
| 3356 HValue* use = it.value(); | 3401 HValue* use = it.value(); |
| 3357 | 3402 |
| 3358 if (use->IsPhi()) { | 3403 if (use->IsPhi()) { |
| 3359 if (!use->CheckFlag(HInstruction::kUint32)) { | 3404 if (!use->CheckFlag(HInstruction::kUint32)) { |
| 3360 // There is a phi use of this value from a phis that is not yet | 3405 // There is a phi use of this value from a phis that is not yet |
| 3361 // collected in phis_ array. Separate pass is required. | 3406 // collected in phis_ array. Separate pass is required. |
| 3362 collect_phi_uses = true; | 3407 collect_phi_uses = true; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3398 // Check if all operands to the given phi are marked with kUint32 flag. | 3443 // Check if all operands to the given phi are marked with kUint32 flag. |
| 3399 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { | 3444 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { |
| 3400 if (!phi->CheckFlag(HInstruction::kUint32)) { | 3445 if (!phi->CheckFlag(HInstruction::kUint32)) { |
| 3401 // This phi is not uint32 safe. No need to check operands. | 3446 // This phi is not uint32 safe. No need to check operands. |
| 3402 return false; | 3447 return false; |
| 3403 } | 3448 } |
| 3404 | 3449 |
| 3405 for (int j = 0; j < phi->OperandCount(); j++) { | 3450 for (int j = 0; j < phi->OperandCount(); j++) { |
| 3406 HValue* operand = phi->OperandAt(j); | 3451 HValue* operand = phi->OperandAt(j); |
| 3407 if (!operand->CheckFlag(HInstruction::kUint32)) { | 3452 if (!operand->CheckFlag(HInstruction::kUint32)) { |
| 3408 // Lazyly mark constants that fit into uint32 range with kUint32 flag. | 3453 // Lazily mark constants that fit into uint32 range with kUint32 flag. |
| 3409 if (operand->IsInteger32Constant() && | 3454 if (operand->IsInteger32Constant() && |
| 3410 operand->GetInteger32Constant() >= 0) { | 3455 operand->GetInteger32Constant() >= 0) { |
| 3411 operand->SetFlag(HInstruction::kUint32); | 3456 operand->SetFlag(HInstruction::kUint32); |
| 3412 continue; | 3457 continue; |
| 3413 } | 3458 } |
| 3414 | 3459 |
| 3415 // This phi is not safe, some operands are not uint32 values. | 3460 // This phi is not safe, some operands are not uint32 values. |
| 3416 return false; | 3461 return false; |
| 3417 } | 3462 } |
| 3418 } | 3463 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3461 | 3506 |
| 3462 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) { | 3507 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) { |
| 3463 phis_[phi_count++] = phi; | 3508 phis_[phi_count++] = phi; |
| 3464 } else { | 3509 } else { |
| 3465 UnmarkPhi(phi, &worklist); | 3510 UnmarkPhi(phi, &worklist); |
| 3466 } | 3511 } |
| 3467 } | 3512 } |
| 3468 | 3513 |
| 3469 // Now phis array contains only those phis that have safe | 3514 // Now phis array contains only those phis that have safe |
| 3470 // non-phi uses. Start transitively clearing kUint32 flag | 3515 // non-phi uses. Start transitively clearing kUint32 flag |
| 3471 // from phi operands of discovered non-safe phies until | 3516 // from phi operands of discovered non-safe phis until |
| 3472 // only safe phies are left. | 3517 // only safe phis are left. |
| 3473 while (!worklist.is_empty()) { | 3518 while (!worklist.is_empty()) { |
| 3474 while (!worklist.is_empty()) { | 3519 while (!worklist.is_empty()) { |
| 3475 HPhi* phi = worklist.RemoveLast(); | 3520 HPhi* phi = worklist.RemoveLast(); |
| 3476 UnmarkPhi(phi, &worklist); | 3521 UnmarkPhi(phi, &worklist); |
| 3477 } | 3522 } |
| 3478 | 3523 |
| 3479 // Check if any operands to safe phies were unmarked | 3524 // Check if any operands to safe phis were unmarked |
| 3480 // turning a safe phi into unsafe. The same value | 3525 // turning a safe phi into unsafe. The same value |
| 3481 // can flow into several phis. | 3526 // can flow into several phis. |
| 3482 int new_phi_count = 0; | 3527 int new_phi_count = 0; |
| 3483 for (int i = 0; i < phi_count; i++) { | 3528 for (int i = 0; i < phi_count; i++) { |
| 3484 HPhi* phi = phis_[i]; | 3529 HPhi* phi = phis_[i]; |
| 3485 | 3530 |
| 3486 if (CheckPhiOperands(phi)) { | 3531 if (CheckPhiOperands(phi)) { |
| 3487 phis_[new_phi_count++] = phi; | 3532 phis_[new_phi_count++] = phi; |
| 3488 } else { | 3533 } else { |
| 3489 UnmarkPhi(phi, &worklist); | 3534 UnmarkPhi(phi, &worklist); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3504 if (current->IsLinked() && current->representation().IsInteger32()) { | 3549 if (current->IsLinked() && current->representation().IsInteger32()) { |
| 3505 analysis.Analyze(current); | 3550 analysis.Analyze(current); |
| 3506 } | 3551 } |
| 3507 } | 3552 } |
| 3508 | 3553 |
| 3509 // Some phis might have been optimistically marked with kUint32 flag. | 3554 // Some phis might have been optimistically marked with kUint32 flag. |
| 3510 // Remove this flag from those phis that are unsafe and propagate | 3555 // Remove this flag from those phis that are unsafe and propagate |
| 3511 // this information transitively potentially clearing kUint32 flag | 3556 // this information transitively potentially clearing kUint32 flag |
| 3512 // from some non-phi operations that are used as operands to unsafe phis. | 3557 // from some non-phi operations that are used as operands to unsafe phis. |
| 3513 analysis.UnmarkUnsafePhis(); | 3558 analysis.UnmarkUnsafePhis(); |
| 3559 |
| 3560 // Inform possible uint32 instructions that the decision has been |
| 3561 // finalized. |
| 3562 for (int i = 0; i < uint32_instructions_->length(); ++i) { |
| 3563 HInstruction* current = uint32_instructions_->at(i); |
| 3564 if (FLAG_trace_representation) { |
| 3565 printf("Notifying uint32 instr: #%d %s\n", |
| 3566 current->id(), current->Mnemonic()); |
| 3567 } |
| 3568 if (current->IsLinked() && current->CheckFlag(HInstruction::kUint32)) { |
| 3569 for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) { |
| 3570 HValue* use = it.value(); |
| 3571 // Only care about special-cased instructions here. |
| 3572 if (!use->IsDiv() && !use->IsCompareIDAndBranch()) continue; |
| 3573 use->SetFlag(HInstruction::kUint32); |
| 3574 use->AssumeRepresentation(Representation::Integer32()); |
| 3575 |
| 3576 if (FLAG_trace_representation) { |
| 3577 printf("Setting kUint32 flag on #%d %s\n", |
| 3578 use->id(), use->Mnemonic()); |
| 3579 } |
| 3580 } |
| 3581 } |
| 3582 } |
| 3514 } | 3583 } |
| 3515 | 3584 |
| 3516 | 3585 |
| 3517 void HGraph::ComputeMinusZeroChecks() { | 3586 void HGraph::ComputeMinusZeroChecks() { |
| 3518 HPhase phase("H_Compute minus zero checks", this); | 3587 HPhase phase("H_Compute minus zero checks", this); |
| 3519 BitVector visited(GetMaximumValueID(), zone()); | 3588 BitVector visited(GetMaximumValueID(), zone()); |
| 3520 for (int i = 0; i < blocks_.length(); ++i) { | 3589 for (int i = 0; i < blocks_.length(); ++i) { |
| 3521 for (HInstruction* current = blocks_[i]->first(); | 3590 for (HInstruction* current = blocks_[i]->first(); |
| 3522 current != NULL; | 3591 current != NULL; |
| 3523 current = current->next()) { | 3592 current = current->next()) { |
| (...skipping 8092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11616 } | 11685 } |
| 11617 } | 11686 } |
| 11618 | 11687 |
| 11619 #ifdef DEBUG | 11688 #ifdef DEBUG |
| 11620 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11689 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11621 if (allocator_ != NULL) allocator_->Verify(); | 11690 if (allocator_ != NULL) allocator_->Verify(); |
| 11622 #endif | 11691 #endif |
| 11623 } | 11692 } |
| 11624 | 11693 |
| 11625 } } // namespace v8::internal | 11694 } } // namespace v8::internal |
| OLD | NEW |