Commit 68eb1e50 authored by titzer@chromium.org's avatar titzer@chromium.org

Improve dead code elimination by transitively marking live code and removing...

Improve dead code elimination by transitively marking live code and removing all dead code. Replace unreachable phi removal algorithm with the new dead code elimination pass, which is more thorough.

Review URL: https://codereview.chromium.org/14676011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14661 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6862babf
...@@ -207,7 +207,6 @@ DEFINE_bool(string_slices, true, "use string slices") ...@@ -207,7 +207,6 @@ DEFINE_bool(string_slices, true, "use string slices")
DEFINE_bool(crankshaft, true, "use crankshaft") DEFINE_bool(crankshaft, true, "use crankshaft")
DEFINE_string(hydrogen_filter, "", "optimization filter") DEFINE_string(hydrogen_filter, "", "optimization filter")
DEFINE_bool(use_range, true, "use hydrogen range analysis") DEFINE_bool(use_range, true, "use hydrogen range analysis")
DEFINE_bool(eliminate_dead_phis, true, "eliminate dead phis")
DEFINE_bool(use_gvn, true, "use hydrogen global value numbering") DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing") DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing")
DEFINE_bool(use_inlining, true, "use function inlining") DEFINE_bool(use_inlining, true, "use function inlining")
......
...@@ -650,7 +650,6 @@ void HValue::SetOperandAt(int index, HValue* value) { ...@@ -650,7 +650,6 @@ void HValue::SetOperandAt(int index, HValue* value) {
void HValue::DeleteAndReplaceWith(HValue* other) { void HValue::DeleteAndReplaceWith(HValue* other) {
// We replace all uses first, so Delete can assert that there are none. // We replace all uses first, so Delete can assert that there are none.
if (other != NULL) ReplaceAllUsesWith(other); if (other != NULL) ReplaceAllUsesWith(other);
ASSERT(HasNoUses());
Kill(); Kill();
DeleteFromGraph(); DeleteFromGraph();
} }
...@@ -1908,9 +1907,7 @@ void HPhi::PrintTo(StringStream* stream) { ...@@ -1908,9 +1907,7 @@ void HPhi::PrintTo(StringStream* stream) {
int32_non_phi_uses() + int32_indirect_uses(), int32_non_phi_uses() + int32_indirect_uses(),
double_non_phi_uses() + double_indirect_uses(), double_non_phi_uses() + double_indirect_uses(),
tagged_non_phi_uses() + tagged_indirect_uses()); tagged_non_phi_uses() + tagged_indirect_uses());
stream->Add("%s%s", if (!IsConvertibleToInteger()) stream->Add("_ncti");
is_live() ? "_live" : "",
IsConvertibleToInteger() ? "" : "_ncti");
PrintRangeTo(stream); PrintRangeTo(stream);
PrintTypeTo(stream); PrintTypeTo(stream);
stream->Add("]"); stream->Add("]");
......
...@@ -793,6 +793,7 @@ class HValue: public ZoneObject { ...@@ -793,6 +793,7 @@ class HValue: public ZoneObject {
kDeoptimizeOnUndefined, kDeoptimizeOnUndefined,
kIsArguments, kIsArguments,
kTruncatingToInt32, kTruncatingToInt32,
// Set after an instruction is killed.
kIsDead, kIsDead,
// Instructions that are allowed to produce full range unsigned integer // Instructions that are allowed to produce full range unsigned integer
// values are marked with kUint32 flag. If arithmetic shift or a load from // values are marked with kUint32 flag. If arithmetic shift or a load from
...@@ -808,6 +809,8 @@ class HValue: public ZoneObject { ...@@ -808,6 +809,8 @@ class HValue: public ZoneObject {
// has processed this instruction. // has processed this instruction.
kIDefsProcessingDone, kIDefsProcessingDone,
kHasNoObservableSideEffects, kHasNoObservableSideEffects,
// Indicates the instruction is live during dead code elimination.
kIsLive,
kLastFlag = kIDefsProcessingDone kLastFlag = kIDefsProcessingDone
}; };
...@@ -1070,8 +1073,9 @@ class HValue: public ZoneObject { ...@@ -1070,8 +1073,9 @@ class HValue: public ZoneObject {
UNREACHABLE(); UNREACHABLE();
} }
bool IsDead() const { // Check if this instruction has some reason that prevents elimination.
return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); bool CannotBeEliminated() const {
return HasObservableSideEffects() || !IsDeletable();
} }
#ifdef DEBUG #ifdef DEBUG
...@@ -2968,7 +2972,6 @@ class HPhi: public HValue { ...@@ -2968,7 +2972,6 @@ class HPhi: public HValue {
: inputs_(2, zone), : inputs_(2, zone),
merged_index_(merged_index), merged_index_(merged_index),
phi_id_(-1), phi_id_(-1),
is_live_(false),
is_convertible_to_integer_(true) { is_convertible_to_integer_(true) {
for (int i = 0; i < Representation::kNumRepresentations; i++) { for (int i = 0; i < Representation::kNumRepresentations; i++) {
non_phi_uses_[i] = 0; non_phi_uses_[i] = 0;
...@@ -2993,7 +2996,7 @@ class HPhi: public HValue { ...@@ -2993,7 +2996,7 @@ class HPhi: public HValue {
void AddInput(HValue* value); void AddInput(HValue* value);
bool HasRealUses(); bool HasRealUses();
bool IsReceiver() { return merged_index_ == 0; } bool IsReceiver() const { return merged_index_ == 0; }
int merged_index() const { return merged_index_; } int merged_index() const { return merged_index_; }
...@@ -3028,8 +3031,6 @@ class HPhi: public HValue { ...@@ -3028,8 +3031,6 @@ class HPhi: public HValue {
return indirect_uses_[Representation::kDouble]; return indirect_uses_[Representation::kDouble];
} }
int phi_id() { return phi_id_; } int phi_id() { return phi_id_; }
bool is_live() { return is_live_; }
void set_is_live(bool b) { is_live_ = b; }
static HPhi* cast(HValue* value) { static HPhi* cast(HValue* value) {
ASSERT(value->IsPhi()); ASSERT(value->IsPhi());
...@@ -3061,6 +3062,9 @@ class HPhi: public HValue { ...@@ -3061,6 +3062,9 @@ class HPhi: public HValue {
void SimplifyConstantInputs(); void SimplifyConstantInputs();
// TODO(titzer): we can't eliminate the receiver for generating backtraces
virtual bool IsDeletable() const { return !IsReceiver(); }
protected: protected:
virtual void DeleteFromGraph(); virtual void DeleteFromGraph();
virtual void InternalSetOperandAt(int index, HValue* value) { virtual void InternalSetOperandAt(int index, HValue* value) {
...@@ -3079,7 +3083,6 @@ class HPhi: public HValue { ...@@ -3079,7 +3083,6 @@ class HPhi: public HValue {
int non_phi_uses_[Representation::kNumRepresentations]; int non_phi_uses_[Representation::kNumRepresentations];
int indirect_uses_[Representation::kNumRepresentations]; int indirect_uses_[Representation::kNumRepresentations];
int phi_id_; int phi_id_;
bool is_live_;
bool is_convertible_to_integer_; bool is_convertible_to_integer_;
}; };
......
...@@ -104,7 +104,6 @@ void HBasicBlock::AddPhi(HPhi* phi) { ...@@ -104,7 +104,6 @@ void HBasicBlock::AddPhi(HPhi* phi) {
void HBasicBlock::RemovePhi(HPhi* phi) { void HBasicBlock::RemovePhi(HPhi* phi) {
ASSERT(phi->block() == this); ASSERT(phi->block() == this);
ASSERT(phis_.Contains(phi)); ASSERT(phis_.Contains(phi));
ASSERT(phi->HasNoUses() || !phi->is_live());
phi->Kill(); phi->Kill();
phis_.RemoveElement(phi); phis_.RemoveElement(phi);
phi->SetBlock(NULL); phi->SetBlock(NULL);
...@@ -2615,50 +2614,6 @@ void HGraph::EliminateRedundantPhis() { ...@@ -2615,50 +2614,6 @@ void HGraph::EliminateRedundantPhis() {
} }
void HGraph::EliminateUnreachablePhis() {
HPhase phase("H_Unreachable phi elimination", this);
// Initialize worklist.
ZoneList<HPhi*> phi_list(blocks_.length(), zone());
ZoneList<HPhi*> worklist(blocks_.length(), zone());
for (int i = 0; i < blocks_.length(); ++i) {
for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
HPhi* phi = blocks_[i]->phis()->at(j);
phi_list.Add(phi, zone());
// We can't eliminate phis in the receiver position in the environment
// because in case of throwing an error we need this value to
// construct a stack trace.
if (phi->HasRealUses() || phi->IsReceiver()) {
phi->set_is_live(true);
worklist.Add(phi, zone());
}
}
}
// Iteratively mark live phis.
while (!worklist.is_empty()) {
HPhi* phi = worklist.RemoveLast();
for (int i = 0; i < phi->OperandCount(); i++) {
HValue* operand = phi->OperandAt(i);
if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) {
HPhi::cast(operand)->set_is_live(true);
worklist.Add(HPhi::cast(operand), zone());
}
}
}
// Remove unreachable phis.
for (int i = 0; i < phi_list.length(); i++) {
HPhi* phi = phi_list[i];
if (!phi->is_live()) {
HBasicBlock* block = phi->block();
block->RemovePhi(phi);
block->RecordDeletedPhi(phi->merged_index());
}
}
}
bool HGraph::CheckArgumentsPhiUses() { bool HGraph::CheckArgumentsPhiUses() {
int block_count = blocks_.length(); int block_count = blocks_.length();
for (int i = 0; i < block_count; ++i) { for (int i = 0; i < block_count; ++i) {
...@@ -4919,7 +4874,11 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { ...@@ -4919,7 +4874,11 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
"Unsupported phi use of arguments")); "Unsupported phi use of arguments"));
return false; return false;
} }
if (FLAG_eliminate_dead_phis) EliminateUnreachablePhis();
// Remove dead code and phis
if (FLAG_dead_code_elimination) {
DeadCodeElimination("H_Eliminate early dead code");
}
CollectPhis(); CollectPhis();
if (has_osr_loop_entry()) { if (has_osr_loop_entry()) {
...@@ -4967,7 +4926,9 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { ...@@ -4967,7 +4926,9 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
EliminateRedundantBoundsChecks(); EliminateRedundantBoundsChecks();
} }
if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
if (FLAG_dead_code_elimination) DeadCodeElimination(); if (FLAG_dead_code_elimination) {
DeadCodeElimination("H_Eliminate late dead code");
}
RestoreActualValues(); RestoreActualValues();
...@@ -5444,35 +5405,98 @@ void HGraph::DehoistSimpleArrayIndexComputations() { ...@@ -5444,35 +5405,98 @@ void HGraph::DehoistSimpleArrayIndexComputations() {
} }
void HGraph::DeadCodeElimination() { void HGraph::DeadCodeElimination(const char* phase_name) {
HPhase phase("H_Dead code elimination", this); HPhase phase(phase_name, this);
ZoneList<HInstruction*> worklist(blocks_.length(), zone()); MarkLiveInstructions();
RemoveDeadInstructions();
}
void HGraph::MarkLiveInstructions() {
ZoneList<HValue*> worklist(blocks_.length(), zone());
// Mark initial root instructions for dead code elimination.
for (int i = 0; i < blocks()->length(); ++i) { for (int i = 0; i < blocks()->length(); ++i) {
for (HInstruction* instr = blocks()->at(i)->first(); HBasicBlock* block = blocks()->at(i);
for (HInstruction* instr = block->first();
instr != NULL; instr != NULL;
instr = instr->next()) { instr = instr->next()) {
if (instr->IsDead()) worklist.Add(instr, zone()); if (instr->CannotBeEliminated()) MarkLive(NULL, instr, &worklist);
}
for (int j = 0; j < block->phis()->length(); j++) {
HPhi* phi = block->phis()->at(j);
if (phi->CannotBeEliminated()) MarkLive(NULL, phi, &worklist);
} }
} }
// Transitively mark all inputs of live instructions live.
while (!worklist.is_empty()) { while (!worklist.is_empty()) {
HInstruction* instr = worklist.RemoveLast(); HValue* instr = worklist.RemoveLast();
// This happens when an instruction is used multiple times as operand. That for (int i = 0; i < instr->OperandCount(); ++i) {
// in turn could happen through GVN. MarkLive(instr, instr->OperandAt(i), &worklist);
if (!instr->IsLinked()) continue; }
}
}
void HGraph::MarkLive(HValue *ref, HValue* instr,
ZoneList<HValue*>* worklist) {
if (!instr->CheckFlag(HValue::kIsLive)) {
instr->SetFlag(HValue::kIsLive);
worklist->Add(instr, zone());
if (FLAG_trace_dead_code_elimination) { if (FLAG_trace_dead_code_elimination) {
HeapStringAllocator allocator; HeapStringAllocator allocator;
StringStream stream(&allocator); StringStream stream(&allocator);
instr->PrintNameTo(&stream); if (ref != NULL) {
stream.Add(" = "); ref->PrintTo(&stream);
} else {
stream.Add("root ");
}
stream.Add(" -> ");
instr->PrintTo(&stream); instr->PrintTo(&stream);
PrintF("[removing dead instruction %s]\n", *stream.ToCString()); PrintF("[MarkLive %s]\n", *stream.ToCString());
} }
instr->DeleteAndReplaceWith(NULL); }
for (int i = 0; i < instr->OperandCount(); ++i) { }
HValue* operand = instr->OperandAt(i);
if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone());
void HGraph::RemoveDeadInstructions() {
ZoneList<HPhi*> dead_phis(blocks_.length(), zone());
// Remove any instruction not marked kIsLive.
for (int i = 0; i < blocks()->length(); ++i) {
HBasicBlock* block = blocks()->at(i);
for (HInstruction* instr = block->first();
instr != NULL;
instr = instr->next()) {
if (!instr->CheckFlag(HValue::kIsLive)) {
// Instruction has not been marked live; assume it is dead and remove.
// TODO(titzer): we don't remove constants because some special ones
// might be used by later phases and are assumed to be in the graph
if (!instr->IsConstant()) instr->DeleteAndReplaceWith(NULL);
} else {
// Clear the liveness flag to leave the graph clean for the next DCE.
instr->ClearFlag(HValue::kIsLive);
}
} }
// Collect phis that are dead and remove them in the next pass.
for (int j = 0; j < block->phis()->length(); j++) {
HPhi* phi = block->phis()->at(j);
if (!phi->CheckFlag(HValue::kIsLive)) {
dead_phis.Add(phi, zone());
} else {
phi->ClearFlag(HValue::kIsLive);
}
}
}
// Process phis separately to avoid simultaneously mutating the phi list.
while (!dead_phis.is_empty()) {
HPhi* phi = dead_phis.RemoveLast();
HBasicBlock* block = phi->block();
phi->DeleteAndReplaceWith(NULL);
block->RecordDeletedPhi(phi->merged_index());
} }
} }
......
...@@ -277,17 +277,15 @@ class HGraph: public ZoneObject { ...@@ -277,17 +277,15 @@ class HGraph: public ZoneObject {
void GlobalValueNumbering(); void GlobalValueNumbering();
bool ProcessArgumentsObject(); bool ProcessArgumentsObject();
void EliminateRedundantPhis(); void EliminateRedundantPhis();
void EliminateUnreachablePhis();
void Canonicalize(); void Canonicalize();
void OrderBlocks(); void OrderBlocks();
void AssignDominators(); void AssignDominators();
void SetupInformativeDefinitions(); void SetupInformativeDefinitions();
void EliminateRedundantBoundsChecks(); void EliminateRedundantBoundsChecks();
void DehoistSimpleArrayIndexComputations(); void DehoistSimpleArrayIndexComputations();
void DeadCodeElimination();
void RestoreActualValues(); void RestoreActualValues();
void DeadCodeElimination(const char *phase_name);
void PropagateDeoptimizingMark(); void PropagateDeoptimizingMark();
void EliminateUnusedInstructions();
// Returns false if there are phi-uses of the arguments-object // Returns false if there are phi-uses of the arguments-object
// which are not supported by the optimizing compiler. // which are not supported by the optimizing compiler.
...@@ -410,6 +408,9 @@ class HGraph: public ZoneObject { ...@@ -410,6 +408,9 @@ class HGraph: public ZoneObject {
HConstant* GetConstantSmi(SetOncePointer<HConstant>* pointer, HConstant* GetConstantSmi(SetOncePointer<HConstant>* pointer,
int32_t integer_value); int32_t integer_value);
void MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist);
void MarkLiveInstructions();
void RemoveDeadInstructions();
void MarkAsDeoptimizingRecursively(HBasicBlock* block); void MarkAsDeoptimizingRecursively(HBasicBlock* block);
void NullifyUnreachableInstructions(); void NullifyUnreachableInstructions();
void InsertTypeConversions(HInstruction* instr); void InsertTypeConversions(HInstruction* instr);
......
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function dead1(a, b) {
var x = a + b;
return a; // x is dead
}
function dead2(a, b) {
var x = a | 0;
var y = b | 0;
return a; // x and y are both dead
}
function dead3(a, b) {
var z;
if(a == 2) z = a;
else z = b;
return a; // z is dead
}
function dead4(a) {
var z = 3;
for (i = 0; i < 3; i++) {
z++;
}
return a; // z is dead
}
function dead5(a) {
var z = 3;
for (i = 0; i < 3; i++) {
z++;
}
var w = z + a;
return a; // z is dead
}
assertTrue(dead1(33, 32) == 33);
assertTrue(dead2(33, 32) == 33);
assertTrue(dead3(33, 32) == 33);
assertTrue(dead4(33) == 33);
assertTrue(dead5(33) == 33);
assertTrue(dead1(34, 7) == 34);
assertTrue(dead2(34, 7) == 34);
assertTrue(dead3(34, 7) == 34);
assertTrue(dead4(34) == 34);
assertTrue(dead5(34) == 34);
assertTrue(dead1(3.4, 0.1) == 3.4);
assertTrue(dead2(3.4, 0.1) == 3.4);
assertTrue(dead3(3.4, 0.1) == 3.4);
assertTrue(dead4(3.4) == 3.4);
assertTrue(dead5(3.4) == 3.4);
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function dead1(a, b) {
{ var x = a + b; }
return a; // x is dead
}
function dead2(a, b) {
{ var x = a | 0; var y = b | 0; }
return a; // x and y are both dead
}
function dead3(a, b) {
{
var z;
if(a == 2) z = a;
else z = b;
}
return a; // z is dead
}
function dead4(a) {
{
var z = 3;
for (i = 0; i < 3; i++) {
z++;
}
}
return a; // z is dead
}
function dead5(a) {
{
var z = 3;
for (i = 0; i < 3; i++) {
z++;
}
var w = z + a;
}
return a; // z and w are dead
}
assertTrue(dead1(33, 32) == 33);
assertTrue(dead2(33, 32) == 33);
assertTrue(dead3(33, 32) == 33);
assertTrue(dead4(33) == 33);
assertTrue(dead5(33) == 33);
assertTrue(dead1(34, 7) == 34);
assertTrue(dead2(34, 7) == 34);
assertTrue(dead3(34, 7) == 34);
assertTrue(dead4(34) == 34);
assertTrue(dead5(34) == 34);
assertTrue(dead1(3.4, 0.1) == 3.4);
assertTrue(dead2(3.4, 0.1) == 3.4);
assertTrue(dead3(3.4, 0.1) == 3.4);
assertTrue(dead4(3.4) == 3.4);
assertTrue(dead5(3.4) == 3.4);
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function dead1(a, b) {
a + b; // dead
return a;
}
function dead2(a, b) {
a | 0; // dead
b | 0; // dead
return a; // x and y are both dead
}
function dead3(a, b) {
a == 2 ? a : b; // dead
return a;
}
function dead4(a) {
var z = 3;
for (i = 0; i < 3; i++) {
z + 3; // dead
}
return a;
}
function dead5(a) {
var z = 3;
for (i = 0; i < 3; i++) {
z + 3; // dead
z++;
}
var w = z + a;
return a; // z is dead
}
assertTrue(dead1(33, 32) == 33);
assertTrue(dead2(33, 32) == 33);
assertTrue(dead3(33, 32) == 33);
assertTrue(dead4(33) == 33);
assertTrue(dead5(33) == 33);
assertTrue(dead1(34, 7) == 34);
assertTrue(dead2(34, 7) == 34);
assertTrue(dead3(34, 7) == 34);
assertTrue(dead4(34) == 34);
assertTrue(dead5(34) == 34);
assertTrue(dead1(3.4, 0.1) == 3.4);
assertTrue(dead2(3.4, 0.1) == 3.4);
assertTrue(dead3(3.4, 0.1) == 3.4);
assertTrue(dead4(3.4) == 3.4);
assertTrue(dead5(3.4) == 3.4);
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function dead1(a, b) {
(a | 0) + (b | 0); // dead
return a;
}
function dead2(a, b) {
a | 0; // dead
b | 0; // dead
return a; // x and y are both dead
}
function dead3(a, b) {
a == 2 ? (a | 0) : (b | 0); // dead
return a;
}
function dead4(a) {
var z = 3;
for (i = 0; i < 3; i++) {
(z | 0) + 3; // dead
}
return a;
}
function dead5(a) {
var z = 3;
for (i = 0; i < 3; i++) {
(z | 0) + 3; // dead
z++;
}
var w = z + a;
return a; // z is dead
}
assertTrue(dead1(33, 32) == 33);
assertTrue(dead2(33, 32) == 33);
assertTrue(dead3(33, 32) == 33);
assertTrue(dead4(33) == 33);
assertTrue(dead5(33) == 33);
assertTrue(dead1(34, 7) == 34);
assertTrue(dead2(34, 7) == 34);
assertTrue(dead3(34, 7) == 34);
assertTrue(dead4(34) == 34);
assertTrue(dead5(34) == 34);
assertTrue(dead1(3.4, 0.1) == 3.4);
assertTrue(dead2(3.4, 0.1) == 3.4);
assertTrue(dead3(3.4, 0.1) == 3.4);
assertTrue(dead4(3.4) == 3.4);
assertTrue(dead5(3.4) == 3.4);
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function dead1(a, b) {
a * b;
a << b;
a >> b;
a >>> b;
a | b;
a & b;
a ^ b;
return a;
}
function dead2(a, b) {
(a | 0) * b;
(a | 0) << b;
(a | 0) >> b;
(a | 0) >>> b;
(a | 0) | b;
(a | 0) & b;
(a | 0) ^ b;
return a;
}
function dead3(a, b) {
a == 2 ? (a * b) : (b * a); // dead
return a;
}
function dead4(a) {
var z = 3;
for (i = 0; i < 3; i++) {
z * 3; // dead
}
return a;
}
function dead5(a) {
var z = 3;
for (i = 0; i < 3; i++) {
z * 3; // dead
z++;
}
var w = z * a;
return a; // w is dead
}
assertTrue(dead1(33, 32) == 33);
assertTrue(dead2(33, 32) == 33);
assertTrue(dead3(33, 32) == 33);
assertTrue(dead4(33) == 33);
assertTrue(dead5(33) == 33);
assertTrue(dead1(34, 7) == 34);
assertTrue(dead2(34, 7) == 34);
assertTrue(dead3(34, 7) == 34);
assertTrue(dead4(34) == 34);
assertTrue(dead5(34) == 34);
assertTrue(dead1(3.4, 0.1) == 3.4);
assertTrue(dead2(3.4, 0.1) == 3.4);
assertTrue(dead3(3.4, 0.1) == 3.4);
assertTrue(dead4(3.4) == 3.4);
assertTrue(dead5(3.4) == 3.4);
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test some dead code elimination scenarios
function dead1(x, y) {
var a = x | 0, b = y | 0;
a * b;
a << b;
a >> b;
a >>> b;
a | b;
a & b;
a ^ b;
return x;
}
function dead2(x, y) {
var a = x | 0, b = y | 0;
(a | 0) * b;
(a | 0) << b;
(a | 0) >> b;
(a | 0) >>> b;
(a | 0) | b;
(a | 0) & b;
(a | 0) ^ b;
return x;
}
function dead3(a, b) {
a == 2 ? (a * b) : (b * a); // dead
return a;
}
assertTrue(dead1(33, 32) == 33);
assertTrue(dead1(33, 32) == 33);
%OptimizeFunctionOnNextCall(dead1);
assertTrue(dead1(33, 32) == 33);
assertTrue(dead2(34, 11) == 34);
assertTrue(dead2(34, 11) == 34);
%OptimizeFunctionOnNextCall(dead2);
assertTrue(dead2(34, 11) == 34);
assertTrue(dead3(35, 12) == 35);
assertTrue(dead3(35, 12) == 35);
%OptimizeFunctionOnNextCall(dead3);
assertTrue(dead3(35, 12) == 35);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment