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 |