1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "hydrogen-store-elimination.h"
6 #include "hydrogen-instructions.h"
11 #define TRACE(x) if (FLAG_trace_store_elimination) PrintF x
13 // Performs a block-by-block local analysis for removable stores.
14 void HStoreEliminationPhase::Run() {
15 GVNFlagSet flags; // Use GVN flags as an approximation for some instructions.
18 flags.Add(kArrayElements);
19 flags.Add(kArrayLengths);
20 flags.Add(kStringLengths);
21 flags.Add(kBackingStoreFields);
22 flags.Add(kDoubleArrayElements);
23 flags.Add(kDoubleFields);
24 flags.Add(kElementsPointer);
25 flags.Add(kInobjectFields);
26 flags.Add(kExternalMemory);
27 flags.Add(kStringChars);
28 flags.Add(kTypedArrayElements);
30 for (int i = 0; i < graph()->blocks()->length(); i++) {
31 unobserved_.Rewind(0);
32 HBasicBlock* block = graph()->blocks()->at(i);
33 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
34 HInstruction* instr = it.Current();
36 // TODO(titzer): eliminate unobserved HStoreKeyed instructions too.
37 switch (instr->opcode()) {
38 case HValue::kStoreNamedField:
39 // Remove any unobserved stores overwritten by this store.
40 ProcessStore(HStoreNamedField::cast(instr));
42 case HValue::kLoadNamedField:
43 // Observe any unobserved stores on this object + field.
44 ProcessLoad(HLoadNamedField::cast(instr));
47 ProcessInstr(instr, flags);
55 void HStoreEliminationPhase::ProcessStore(HStoreNamedField* store) {
56 HValue* object = store->object()->ActualValue();
58 while (i < unobserved_.length()) {
59 HStoreNamedField* prev = unobserved_.at(i);
60 if (aliasing_->MustAlias(object, prev->object()->ActualValue()) &&
61 store->access().Equals(prev->access())) {
62 // This store is guaranteed to overwrite the previous store.
63 prev->DeleteAndReplaceWith(NULL);
64 TRACE(("++ Unobserved store S%d overwritten by S%d\n",
65 prev->id(), store->id()));
66 unobserved_.Remove(i);
68 // TODO(titzer): remove map word clearing from folded allocations.
72 // Only non-transitioning stores are removable.
73 if (!store->has_transition()) {
74 TRACE(("-- Might remove store S%d\n", store->id()));
75 unobserved_.Add(store, zone());
80 void HStoreEliminationPhase::ProcessLoad(HLoadNamedField* load) {
81 HValue* object = load->object()->ActualValue();
83 while (i < unobserved_.length()) {
84 HStoreNamedField* prev = unobserved_.at(i);
85 if (aliasing_->MayAlias(object, prev->object()->ActualValue()) &&
86 load->access().Equals(prev->access())) {
87 TRACE(("-- Observed store S%d by load L%d\n", prev->id(), load->id()));
88 unobserved_.Remove(i);
96 void HStoreEliminationPhase::ProcessInstr(HInstruction* instr,
98 if (unobserved_.length() == 0) return; // Nothing to do.
99 if (instr->CanDeoptimize()) {
100 TRACE(("-- Observed stores at I%d (might deoptimize)\n", instr->id()));
101 unobserved_.Rewind(0);
104 if (instr->CheckChangesFlag(kNewSpacePromotion)) {
105 TRACE(("-- Observed stores at I%d (might GC)\n", instr->id()));
106 unobserved_.Rewind(0);
109 if (instr->DependsOnFlags().ContainsAnyOf(flags)) {
110 TRACE(("-- Observed stores at I%d (GVN flags)\n", instr->id()));
111 unobserved_.Rewind(0);
116 } } // namespace v8::internal