• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-dce.h"
6 #include "src/v8.h"
7 
8 namespace v8 {
9 namespace internal {
10 
MarkLive(HValue * instr,ZoneList<HValue * > * worklist)11 void HDeadCodeEliminationPhase::MarkLive(
12     HValue* instr, ZoneList<HValue*>* worklist) {
13   if (instr->CheckFlag(HValue::kIsLive)) return;  // Already live.
14 
15   if (FLAG_trace_dead_code_elimination) PrintLive(NULL, instr);
16 
17   // Transitively mark all inputs of live instructions live.
18   worklist->Add(instr, zone());
19   while (!worklist->is_empty()) {
20     HValue* instr = worklist->RemoveLast();
21     instr->SetFlag(HValue::kIsLive);
22     for (int i = 0; i < instr->OperandCount(); ++i) {
23       HValue* input = instr->OperandAt(i);
24       if (!input->CheckFlag(HValue::kIsLive)) {
25         input->SetFlag(HValue::kIsLive);
26         worklist->Add(input, zone());
27         if (FLAG_trace_dead_code_elimination) PrintLive(instr, input);
28       }
29     }
30   }
31 }
32 
33 
PrintLive(HValue * ref,HValue * instr)34 void HDeadCodeEliminationPhase::PrintLive(HValue* ref, HValue* instr) {
35   HeapStringAllocator allocator;
36   StringStream stream(&allocator);
37   if (ref != NULL) {
38     ref->PrintTo(&stream);
39   } else {
40     stream.Add("root ");
41   }
42   stream.Add(" -> ");
43   instr->PrintTo(&stream);
44   PrintF("[MarkLive %s]\n", stream.ToCString().get());
45 }
46 
47 
MarkLiveInstructions()48 void HDeadCodeEliminationPhase::MarkLiveInstructions() {
49   ZoneList<HValue*> worklist(10, zone());
50 
51   // Transitively mark all live instructions, starting from roots.
52   for (int i = 0; i < graph()->blocks()->length(); ++i) {
53     HBasicBlock* block = graph()->blocks()->at(i);
54     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
55       HInstruction* instr = it.Current();
56       if (instr->CannotBeEliminated()) MarkLive(instr, &worklist);
57     }
58     for (int j = 0; j < block->phis()->length(); j++) {
59       HPhi* phi = block->phis()->at(j);
60       if (phi->CannotBeEliminated()) MarkLive(phi, &worklist);
61     }
62   }
63 
64   ASSERT(worklist.is_empty());  // Should have processed everything.
65 }
66 
67 
RemoveDeadInstructions()68 void HDeadCodeEliminationPhase::RemoveDeadInstructions() {
69   ZoneList<HPhi*> worklist(graph()->blocks()->length(), zone());
70 
71   // Remove any instruction not marked kIsLive.
72   for (int i = 0; i < graph()->blocks()->length(); ++i) {
73     HBasicBlock* block = graph()->blocks()->at(i);
74     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
75       HInstruction* instr = it.Current();
76       if (!instr->CheckFlag(HValue::kIsLive)) {
77         // Instruction has not been marked live, so remove it.
78         instr->DeleteAndReplaceWith(NULL);
79       } else {
80         // Clear the liveness flag to leave the graph clean for the next DCE.
81         instr->ClearFlag(HValue::kIsLive);
82       }
83     }
84     // Collect phis that are dead and remove them in the next pass.
85     for (int j = 0; j < block->phis()->length(); j++) {
86       HPhi* phi = block->phis()->at(j);
87       if (!phi->CheckFlag(HValue::kIsLive)) {
88         worklist.Add(phi, zone());
89       } else {
90         phi->ClearFlag(HValue::kIsLive);
91       }
92     }
93   }
94 
95   // Process phis separately to avoid simultaneously mutating the phi list.
96   while (!worklist.is_empty()) {
97     HPhi* phi = worklist.RemoveLast();
98     HBasicBlock* block = phi->block();
99     phi->DeleteAndReplaceWith(NULL);
100     if (phi->HasMergedIndex()) {
101       block->RecordDeletedPhi(phi->merged_index());
102     }
103   }
104 }
105 
106 } }  // namespace v8::internal
107