Line data Source code
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/crankshaft/hydrogen-store-elimination.h"
6 :
7 : #include "src/crankshaft/hydrogen-instructions.h"
8 : #include "src/objects-inl.h"
9 :
10 : namespace v8 {
11 : namespace internal {
12 :
13 : #define TRACE(x) if (FLAG_trace_store_elimination) PrintF x
14 :
15 : // Performs a block-by-block local analysis for removable stores.
16 39 : void HStoreEliminationPhase::Run() {
17 : GVNFlagSet flags; // Use GVN flags as an approximation for some instructions.
18 : flags.RemoveAll();
19 :
20 : flags.Add(kArrayElements);
21 : flags.Add(kArrayLengths);
22 : flags.Add(kStringLengths);
23 : flags.Add(kBackingStoreFields);
24 : flags.Add(kDoubleArrayElements);
25 : flags.Add(kDoubleFields);
26 : flags.Add(kElementsPointer);
27 : flags.Add(kInobjectFields);
28 : flags.Add(kExternalMemory);
29 : flags.Add(kStringChars);
30 : flags.Add(kTypedArrayElements);
31 :
32 724 : for (int i = 0; i < graph()->blocks()->length(); i++) {
33 : unobserved_.Rewind(0);
34 685 : HBasicBlock* block = graph()->blocks()->at(i);
35 323 : if (!block->IsReachable()) continue;
36 3208 : for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
37 : HInstruction* instr = it.Current();
38 5774 : if (instr->CheckFlag(HValue::kIsDead)) continue;
39 :
40 2804 : switch (instr->opcode()) {
41 : case HValue::kStoreNamedField:
42 : // Remove any unobserved stores overwritten by this store.
43 253 : ProcessStore(HStoreNamedField::cast(instr));
44 253 : break;
45 : case HValue::kLoadNamedField:
46 : // Observe any unobserved stores on this object + field.
47 27 : ProcessLoad(HLoadNamedField::cast(instr));
48 27 : break;
49 : default:
50 2524 : ProcessInstr(instr, flags);
51 2524 : break;
52 : }
53 : }
54 : }
55 39 : }
56 :
57 :
58 253 : void HStoreEliminationPhase::ProcessStore(HStoreNamedField* store) {
59 506 : HValue* object = store->object()->ActualValue();
60 : int i = 0;
61 796 : while (i < unobserved_.length()) {
62 833 : HStoreNamedField* prev = unobserved_.at(i);
63 870 : if (aliasing_->MustAlias(object, prev->object()->ActualValue()) &&
64 290 : prev->CanBeReplacedWith(store)) {
65 : // This store is guaranteed to overwrite the previous store.
66 0 : prev->DeleteAndReplaceWith(NULL);
67 0 : TRACE(("++ Unobserved store S%d overwritten by S%d\n",
68 0 : prev->id(), store->id()));
69 0 : unobserved_.Remove(i);
70 : } else {
71 290 : i++;
72 : }
73 : }
74 : // Only non-transitioning stores are removable.
75 253 : if (!store->has_transition()) {
76 195 : TRACE(("-- Might remove store S%d\n", store->id()));
77 195 : unobserved_.Add(store, zone());
78 : }
79 253 : }
80 :
81 :
82 27 : void HStoreEliminationPhase::ProcessLoad(HLoadNamedField* load) {
83 27 : HValue* object = load->object()->ActualValue();
84 : int i = 0;
85 54 : while (i < unobserved_.length()) {
86 27 : HStoreNamedField* prev = unobserved_.at(i);
87 0 : if (aliasing_->MayAlias(object, prev->object()->ActualValue()) &&
88 0 : load->access().Equals(prev->access())) {
89 0 : TRACE(("-- Observed store S%d by load L%d\n", prev->id(), load->id()));
90 0 : unobserved_.Remove(i);
91 : } else {
92 0 : i++;
93 : }
94 : }
95 27 : }
96 :
97 :
98 2524 : void HStoreEliminationPhase::ProcessInstr(HInstruction* instr,
99 : GVNFlagSet flags) {
100 2524 : if (unobserved_.length() == 0) return; // Nothing to do.
101 166 : if (instr->CanDeoptimize()) {
102 79 : TRACE(("-- Observed stores at I%d (%s might deoptimize)\n",
103 0 : instr->id(), instr->Mnemonic()));
104 : unobserved_.Rewind(0);
105 : return;
106 : }
107 87 : if (instr->CheckChangesFlag(kNewSpacePromotion)) {
108 0 : TRACE(("-- Observed stores at I%d (%s might GC)\n",
109 0 : instr->id(), instr->Mnemonic()));
110 : unobserved_.Rewind(0);
111 : return;
112 : }
113 87 : if (instr->DependsOnFlags().ContainsAnyOf(flags)) {
114 0 : TRACE(("-- Observed stores at I%d (GVN flags of %s)\n",
115 0 : instr->id(), instr->Mnemonic()));
116 : unobserved_.Rewind(0);
117 : return;
118 : }
119 : }
120 :
121 : } // namespace internal
122 : } // namespace v8
|