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()); |
+ } |
+ } |
+ } |
+ } |
} |