OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "src/hydrogen-instructions.h" | |
6 #include "src/hydrogen-store-elimination.h" | |
7 | |
8 namespace v8 { | |
9 namespace internal { | |
10 | |
11 #define TRACE(x) if (FLAG_trace_store_elimination) PrintF x | |
12 | |
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. | |
16 flags.RemoveAll(); | |
17 | |
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); | |
29 | |
30 for (int i = 0; i < graph()->blocks()->length(); i++) { | |
31 unobserved_.Rewind(0); | |
32 HBasicBlock* block = graph()->blocks()->at(i); | |
33 if (!block->IsReachable()) continue; | |
34 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { | |
35 HInstruction* instr = it.Current(); | |
36 if (instr->CheckFlag(HValue::kIsDead)) continue; | |
37 | |
38 // TODO(titzer): eliminate unobserved HStoreKeyed instructions too. | |
39 switch (instr->opcode()) { | |
40 case HValue::kStoreNamedField: | |
41 // Remove any unobserved stores overwritten by this store. | |
42 ProcessStore(HStoreNamedField::cast(instr)); | |
43 break; | |
44 case HValue::kLoadNamedField: | |
45 // Observe any unobserved stores on this object + field. | |
46 ProcessLoad(HLoadNamedField::cast(instr)); | |
47 break; | |
48 default: | |
49 ProcessInstr(instr, flags); | |
50 break; | |
51 } | |
52 } | |
53 } | |
54 } | |
55 | |
56 | |
57 void HStoreEliminationPhase::ProcessStore(HStoreNamedField* store) { | |
58 HValue* object = store->object()->ActualValue(); | |
59 int i = 0; | |
60 while (i < unobserved_.length()) { | |
61 HStoreNamedField* prev = unobserved_.at(i); | |
62 if (aliasing_->MustAlias(object, prev->object()->ActualValue()) && | |
63 prev->CanBeReplacedWith(store)) { | |
64 // This store is guaranteed to overwrite the previous store. | |
65 prev->DeleteAndReplaceWith(NULL); | |
66 TRACE(("++ Unobserved store S%d overwritten by S%d\n", | |
67 prev->id(), store->id())); | |
68 unobserved_.Remove(i); | |
69 } else { | |
70 // TODO(titzer): remove map word clearing from folded allocations. | |
71 i++; | |
72 } | |
73 } | |
74 // Only non-transitioning stores are removable. | |
75 if (!store->has_transition()) { | |
76 TRACE(("-- Might remove store S%d\n", store->id())); | |
77 unobserved_.Add(store, zone()); | |
78 } | |
79 } | |
80 | |
81 | |
82 void HStoreEliminationPhase::ProcessLoad(HLoadNamedField* load) { | |
83 HValue* object = load->object()->ActualValue(); | |
84 int i = 0; | |
85 while (i < unobserved_.length()) { | |
86 HStoreNamedField* prev = unobserved_.at(i); | |
87 if (aliasing_->MayAlias(object, prev->object()->ActualValue()) && | |
88 load->access().Equals(prev->access())) { | |
89 TRACE(("-- Observed store S%d by load L%d\n", prev->id(), load->id())); | |
90 unobserved_.Remove(i); | |
91 } else { | |
92 i++; | |
93 } | |
94 } | |
95 } | |
96 | |
97 | |
98 void HStoreEliminationPhase::ProcessInstr(HInstruction* instr, | |
99 GVNFlagSet flags) { | |
100 if (unobserved_.length() == 0) return; // Nothing to do. | |
101 if (instr->CanDeoptimize()) { | |
102 TRACE(("-- Observed stores at I%d (%s might deoptimize)\n", | |
103 instr->id(), instr->Mnemonic())); | |
104 unobserved_.Rewind(0); | |
105 return; | |
106 } | |
107 if (instr->CheckChangesFlag(kNewSpacePromotion)) { | |
108 TRACE(("-- Observed stores at I%d (%s might GC)\n", | |
109 instr->id(), instr->Mnemonic())); | |
110 unobserved_.Rewind(0); | |
111 return; | |
112 } | |
113 if (instr->DependsOnFlags().ContainsAnyOf(flags)) { | |
114 TRACE(("-- Observed stores at I%d (GVN flags of %s)\n", | |
115 instr->id(), instr->Mnemonic())); | |
116 unobserved_.Rewind(0); | |
117 return; | |
118 } | |
119 } | |
120 | |
121 } // namespace internal | |
122 } // namespace v8 | |
OLD | NEW |