| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 34008d162c5c43a31b2fd8ee6bc4b2001b0ecf70..e5ae2b03eab92004f5b8c84b6ff843568fb91788 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -3313,8 +3313,22 @@ class Uint32Analysis BASE_EMBEDDED {
|
| };
|
|
|
|
|
| +bool IsUint32Operation(HValue* instr) {
|
| + if (instr->IsShr()) return true;
|
| + if (instr->IsLoadKeyed() &&
|
| + HLoadKeyed::cast(instr)->elements_kind() ==
|
| + EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
| + return true;
|
| + }
|
| + if (instr->IsInteger32Constant() && instr->GetInteger32Constant() >= 0) {
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
|
| - // Operations that operatate on bits are safe.
|
| + // Operations that operate on bits are safe.
|
| if (use->IsBitwise() ||
|
| use->IsShl() ||
|
| use->IsSar() ||
|
| @@ -3337,6 +3351,37 @@ bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
|
| return true;
|
| }
|
| }
|
| + } else if (use->IsCompareIDAndBranch()) {
|
| + for (int i = 0; i < use->OperandCount(); ++i) {
|
| + if (!IsUint32Operation(use->OperandAt(i))) return false;
|
| + }
|
| + return true;
|
| + } else if (use->IsDiv()) {
|
| + // Skip OperandAt(0) which is the context.
|
| + for (int i = 1; i < use->OperandCount(); ++i) {
|
| + if (!IsUint32Operation(use->OperandAt(i))) {
|
| + if (FLAG_trace_representation) {
|
| + HValue* op = use->OperandAt(i);
|
| + printf("#%d %s is not a safe uint32 use because of operand #%d %s\n",
|
| + use->id(), use->Mnemonic(), op->id(), op->Mnemonic());
|
| + }
|
| + return false;
|
| + }
|
| + }
|
| + for (HUseIterator it(use->uses()); !it.Done(); it.Advance()) {
|
| + if (!IsSafeUint32Use(use, it.value())) {
|
| + if (FLAG_trace_representation) {
|
| + HValue* op = it.value();
|
| + printf("#%d %s is not a safe uint32 use because of use #%d %s\n",
|
| + use->id(), use->Mnemonic(), op->id(), op->Mnemonic());
|
| + }
|
| + return false;
|
| + }
|
| + }
|
| + if (FLAG_trace_representation) {
|
| + printf("#%d %s is a safe uint32 use :-)\n", use->id(), use->Mnemonic());
|
| + }
|
| + return true;
|
| }
|
|
|
| return false;
|
| @@ -3346,10 +3391,10 @@ bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
|
| // Iterate over all uses and verify that they are uint32 safe: either don't
|
| // distinguish between int32 and uint32 due to their bitwise nature or
|
| // have special support for uint32 values.
|
| -// Encountered phis are optimisitically treated as safe uint32 uses,
|
| +// Encountered phis are optimistically treated as safe uint32 uses,
|
| // marked with kUint32 flag and collected in the phis_ list. A separate
|
| -// path will be performed later by UnmarkUnsafePhis to clear kUint32 from
|
| -// phis that are not actually uint32-safe (it requries fix point iteration).
|
| +// pass will be performed later by UnmarkUnsafePhis to clear kUint32 from
|
| +// phis that are not actually uint32-safe (it requires fix point iteration).
|
| bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) {
|
| bool collect_phi_uses = false;
|
| for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
|
| @@ -3405,7 +3450,7 @@ bool Uint32Analysis::CheckPhiOperands(HPhi* phi) {
|
| for (int j = 0; j < phi->OperandCount(); j++) {
|
| HValue* operand = phi->OperandAt(j);
|
| if (!operand->CheckFlag(HInstruction::kUint32)) {
|
| - // Lazyly mark constants that fit into uint32 range with kUint32 flag.
|
| + // Lazily mark constants that fit into uint32 range with kUint32 flag.
|
| if (operand->IsInteger32Constant() &&
|
| operand->GetInteger32Constant() >= 0) {
|
| operand->SetFlag(HInstruction::kUint32);
|
| @@ -3468,15 +3513,15 @@ void Uint32Analysis::UnmarkUnsafePhis() {
|
|
|
| // Now phis array contains only those phis that have safe
|
| // non-phi uses. Start transitively clearing kUint32 flag
|
| - // from phi operands of discovered non-safe phies until
|
| - // only safe phies are left.
|
| + // from phi operands of discovered non-safe phis until
|
| + // only safe phis are left.
|
| while (!worklist.is_empty()) {
|
| while (!worklist.is_empty()) {
|
| HPhi* phi = worklist.RemoveLast();
|
| UnmarkPhi(phi, &worklist);
|
| }
|
|
|
| - // Check if any operands to safe phies were unmarked
|
| + // Check if any operands to safe phis were unmarked
|
| // turning a safe phi into unsafe. The same value
|
| // can flow into several phis.
|
| int new_phi_count = 0;
|
| @@ -3511,6 +3556,30 @@ void HGraph::ComputeSafeUint32Operations() {
|
| // this information transitively potentially clearing kUint32 flag
|
| // from some non-phi operations that are used as operands to unsafe phis.
|
| analysis.UnmarkUnsafePhis();
|
| +
|
| + // Inform possible uint32 instructions that the decision has been
|
| + // finalized.
|
| + for (int i = 0; i < uint32_instructions_->length(); ++i) {
|
| + HInstruction* current = uint32_instructions_->at(i);
|
| + if (FLAG_trace_representation) {
|
| + printf("Notifying uint32 instr: #%d %s\n",
|
| + current->id(), current->Mnemonic());
|
| + }
|
| + if (current->IsLinked() && current->CheckFlag(HInstruction::kUint32)) {
|
| + for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
|
| + HValue* use = it.value();
|
| + // Only care about special-cased instructions here.
|
| + if (!use->IsDiv() && !use->IsCompareIDAndBranch()) continue;
|
| + use->SetFlag(HInstruction::kUint32);
|
| + use->AssumeRepresentation(Representation::Integer32());
|
| +
|
| + if (FLAG_trace_representation) {
|
| + printf("Setting kUint32 flag on #%d %s\n",
|
| + use->id(), use->Mnemonic());
|
| + }
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
|
|
|
|