Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: src/hydrogen.cc

Issue 288853003: Allow div and cmp to work in uint32 mode (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/ia32/assembler-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/ia32/assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698