From 37ee4a0369ae8dc124c2c9beb06116b7b89475cb Mon Sep 17 00:00:00 2001 From: "titzer@chromium.org" Date: Mon, 29 Jul 2013 12:35:43 +0000 Subject: [PATCH] Fix IsDeletable() for HStringAdd, HStringCharCodeAt, HStringCharFromCode. BUG= R=mstarzinger@chromium.org, svenpanne@chromium.org Review URL: https://codereview.chromium.org/20241005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15934 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/hydrogen-instructions.cc | 5 -- src/hydrogen-instructions.h | 78 +++++++++++++++------ test/mjsunit/compiler/dead-string-add-warm.js | 76 ++++++++++++++++++++ test/mjsunit/compiler/dead-string-add.js | 65 +++++++++++++++++ test/mjsunit/compiler/dead-string-char-code-at.js | 81 ++++++++++++++++++++++ test/mjsunit/compiler/dead-string-char-code-at2.js | 81 ++++++++++++++++++++++ .../mjsunit/compiler/dead-string-char-from-code.js | 76 ++++++++++++++++++++ 7 files changed, 435 insertions(+), 27 deletions(-) create mode 100644 test/mjsunit/compiler/dead-string-add-warm.js create mode 100644 test/mjsunit/compiler/dead-string-add.js create mode 100644 test/mjsunit/compiler/dead-string-char-code-at.js create mode 100644 test/mjsunit/compiler/dead-string-char-code-at2.js create mode 100644 test/mjsunit/compiler/dead-string-char-from-code.js diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 20430c3..3eca181 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3718,11 +3718,6 @@ Representation HUnaryMathOperation::RepresentationFromInputs() { } -HType HStringCharFromCode::CalculateInferredType() { - return HType::String(); -} - - void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, HValue* dominator) { ASSERT(side_effect == kChangesNewSpacePromotion); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 0b81b87..1015b6e 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -423,6 +423,24 @@ class HType { return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); } + bool ToStringOrToNumberCanBeObserved(Representation representation) { + switch (type_) { + case kTaggedPrimitive: // fallthru + case kTaggedNumber: // fallthru + case kSmi: // fallthru + case kHeapNumber: // fallthru + case kString: // fallthru + case kBoolean: + return false; + case kJSArray: // fallthru + case kJSObject: + return true; + case kTagged: + break; + } + return !representation.IsSmiOrInteger32() && !representation.IsDouble(); + } + static HType TypeFromValue(Handle value); const char* ToString(); @@ -1126,6 +1144,18 @@ class HValue: public ZoneObject { } } + // Returns true conservatively if the program might be able to observe a + // ToString() operation on this value. + bool ToStringCanBeObserved() const { + return type().ToStringOrToNumberCanBeObserved(representation()); + } + + // Returns true conservatively if the program might be able to observe a + // ToNumber() operation on this value. + bool ToNumberCanBeObserved() const { + return type().ToStringOrToNumberCanBeObserved(representation()); + } + protected: void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); @@ -3320,9 +3350,6 @@ class HPhi: public HValue { void SimplifyConstantInputs(); - // TODO(titzer): we can't eliminate the receiver for generating backtraces - virtual bool IsDeletable() const { return !IsReceiver(); } - protected: virtual void DeleteFromGraph(); virtual void InternalSetOperandAt(int index, HValue* value) { @@ -3342,6 +3369,9 @@ class HPhi: public HValue { int indirect_uses_[Representation::kNumRepresentations]; int phi_id_; InductionVariableData* induction_variable_data_; + + // TODO(titzer): we can't eliminate the receiver for generating backtraces + virtual bool IsDeletable() const { return !IsReceiver(); } }; @@ -3653,9 +3683,9 @@ class HBinaryOperation: public HTemplateInstruction<3> { observed_input_representation_[1] = Representation::None(); } - HValue* context() { return OperandAt(0); } - HValue* left() { return OperandAt(1); } - HValue* right() { return OperandAt(2); } + HValue* context() const { return OperandAt(0); } + HValue* left() const { return OperandAt(1); } + HValue* right() const { return OperandAt(2); } // True if switching left and right operands likely generates better code. bool AreOperandsBetterSwitched() { @@ -3909,9 +3939,6 @@ class HBoundsCheck: public HTemplateInstruction<2> { virtual Representation RequiredInputRepresentation(int arg_index) { return representation(); } - virtual bool IsDeletable() const { - return skip_check() && !FLAG_debug_code; - } virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* related_value, @@ -3948,6 +3975,11 @@ class HBoundsCheck: public HTemplateInstruction<2> { int scale_; RangeGuaranteeDirection responsibility_direction_; bool allow_equality_; + + private: + virtual bool IsDeletable() const { + return skip_check() && !FLAG_debug_code; + } }; @@ -6451,8 +6483,9 @@ class HStringAdd: public HBinaryOperation { SetGVNFlag(kChangesNewSpacePromotion); } - // TODO(svenpanne) Might be safe, but leave it out until we know for sure. - // virtual bool IsDeletable() const { return true; } + // No side-effects except possible allocation. + // NOTE: this instruction _does not_ call ToString() on its inputs. + virtual bool IsDeletable() const { return true; } const StringAddFlags flags_; }; @@ -6477,9 +6510,9 @@ class HStringCharCodeAt: public HTemplateInstruction<3> { : Representation::Tagged(); } - HValue* context() { return OperandAt(0); } - HValue* string() { return OperandAt(1); } - HValue* index() { return OperandAt(2); } + HValue* context() const { return OperandAt(0); } + HValue* string() const { return OperandAt(1); } + HValue* index() const { return OperandAt(2); } DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) @@ -6490,9 +6523,9 @@ class HStringCharCodeAt: public HTemplateInstruction<3> { return new(zone) Range(0, String::kMaxUtf16CodeUnit); } - // TODO(svenpanne) Might be safe, but leave it out until we know for sure. - // private: - // virtual bool IsDeletable() const { return true; } + private: + // No side effects: runtime function assumes string + number inputs. + virtual bool IsDeletable() const { return true; } }; @@ -6507,10 +6540,10 @@ class HStringCharFromCode: public HTemplateInstruction<2> { ? Representation::Tagged() : Representation::Integer32(); } - virtual HType CalculateInferredType(); + virtual HType CalculateInferredType() { return HType::String(); } - HValue* context() { return OperandAt(0); } - HValue* value() { return OperandAt(1); } + HValue* context() const { return OperandAt(0); } + HValue* value() const { return OperandAt(1); } virtual bool DataEquals(HValue* other) { return true; } @@ -6525,8 +6558,9 @@ class HStringCharFromCode: public HTemplateInstruction<2> { SetGVNFlag(kChangesNewSpacePromotion); } - // TODO(svenpanne) Might be safe, but leave it out until we know for sure. - // virtual bool IsDeletable() const { return true; } + virtual bool IsDeletable() const { + return !value()->ToNumberCanBeObserved(); + } }; diff --git a/test/mjsunit/compiler/dead-string-add-warm.js b/test/mjsunit/compiler/dead-string-add-warm.js new file mode 100644 index 0000000..c211ebd --- /dev/null +++ b/test/mjsunit/compiler/dead-string-add-warm.js @@ -0,0 +1,76 @@ +// Copyright 2013 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 + +function dead1(a, b) { + var x = "a" + "b"; + return a; // x, "a", and "b" are dead code +} + +function dead2(a, b) { + var x = "0" + a; + var y = "0" + b; + return a; // x and y are both dead +} + +function dead3(a, b) { + a = a ? "1" : "0"; + b = b ? "1" : "0"; + var x = a + "0"; + var y = b + "0"; + return a; // x and y are both dead +} + +function run() { + assertEquals(33, dead1(33, 32)); + assertEquals(33, dead2(33, 32)); + assertEquals("1", dead3(33, 32)); + + assertEquals(31, dead1(31, 30)); + assertEquals(31, dead2(31, 30)); + assertEquals("1", dead3(31, 32)); + + assertEquals(0, dead1(0, 30)); + assertEquals(0, dead2(0, 30)); + assertEquals("0", dead3(0, 32)); + + assertEquals(true, dead1(true, 0)); + assertEquals(true, dead2(true, 0)); + assertEquals("1", dead3(true, 0)); + + assertEquals("true", dead1("true", 0)); + assertEquals("true", dead2("true", 0)); + assertEquals("1", dead3("true", 0)); +} + +run(); +run(); +%OptimizeFunctionOnNextCall(dead1); +%OptimizeFunctionOnNextCall(dead2); +%OptimizeFunctionOnNextCall(dead3); +run(); diff --git a/test/mjsunit/compiler/dead-string-add.js b/test/mjsunit/compiler/dead-string-add.js new file mode 100644 index 0000000..04155ef --- /dev/null +++ b/test/mjsunit/compiler/dead-string-add.js @@ -0,0 +1,65 @@ +// Copyright 2013 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, "a", and "b" are dead code +} + +function dead2(a, b) { + var x = a + "0"; + var y = b + "0"; + return a; // x and y are both dead +} + +function dead3(a, b) { + a = a ? "1" : "0"; + b = b ? "1" : "0"; + var x = a + "0"; + var y = b + "0"; + return a; // x and y are both dead +} + +assertEquals(33, dead1(33, 32)); +assertEquals(33, dead2(33, 32)); +assertEquals("1", dead3(33, 32)); + +assertEquals(31, dead1(31, 30)); +assertEquals(31, dead2(31, 30)); +assertEquals("1", dead3(31, 32)); + +assertEquals(0, dead1(0, 30)); +assertEquals(0, dead2(0, 30)); +assertEquals("0", dead3(0, 32)); + +assertEquals(true, dead1(true, 0)); +assertEquals(true, dead2(true, 0)); +assertEquals("1", dead3(true, 0)); + +assertEquals("true", dead1("true", 0)); +assertEquals("true", dead2("true", 0)); +assertEquals("1", dead3("true", 0)); diff --git a/test/mjsunit/compiler/dead-string-char-code-at.js b/test/mjsunit/compiler/dead-string-char-code-at.js new file mode 100644 index 0000000..56835ce --- /dev/null +++ b/test/mjsunit/compiler/dead-string-char-code-at.js @@ -0,0 +1,81 @@ +// Copyright 2013 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 + +var S1 = "string1"; +var S2 = "@@string2"; + +function dead1(a, b) { + var x = %StringCharCodeAt(a, 4); + return a; // x is dead code +} + +function dead2(a, b) { + var x = %StringCharCodeAt(a, 3); + var y = %StringCharCodeAt(b, 1); + return a; // x and y are both dead +} + +function dead3(a, b) { + a = a ? "11" : "12"; + b = b ? "13" : "14"; + var x = %StringCharCodeAt(a, 2); + var y = %StringCharCodeAt(b, 0); + return a; // x and y are both dead +} + +function test() { + var S3 = S1 + S2; + + assertEquals(S1, dead1(S1, S2)); + assertEquals(S1, dead2(S1, S2)); + assertEquals("11", dead3(S1, S2)); + + assertEquals(S2, dead1(S2, 677)); + assertEquals(S2, dead2(S2, S3)); + assertEquals("11", dead3(S2, S3)); + + assertEquals(S3, dead1(S3, 399)); + assertEquals(S3, dead2(S3, "false")); + assertEquals("12", dead3(0, 32)); + + assertEquals(S3, dead1(S3, 0)); + assertEquals(S3, dead2(S3, S1)); + assertEquals("11", dead3(S3, 0)); + + assertEquals("true", dead1("true", 0)); + assertEquals("true", dead2("true", S3)); + assertEquals("11", dead3("true", 0)); +} + +test(); +test(); +%OptimizeFunctionOnNextCall(dead1); +%OptimizeFunctionOnNextCall(dead2); +%OptimizeFunctionOnNextCall(dead3); +test(); diff --git a/test/mjsunit/compiler/dead-string-char-code-at2.js b/test/mjsunit/compiler/dead-string-char-code-at2.js new file mode 100644 index 0000000..9f01541 --- /dev/null +++ b/test/mjsunit/compiler/dead-string-char-code-at2.js @@ -0,0 +1,81 @@ +// Copyright 2013 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 + +var S1 = "string1"; +var S2 = "@@string2"; + +function dead1(a, b) { + var x = %_StringCharCodeAt(a, 4); + return a; // x is dead code +} + +function dead2(a, b) { + var x = %_StringCharCodeAt(a, 3); + var y = %_StringCharCodeAt(b, 1); + return a; // x and y are both dead +} + +function dead3(a, b) { + a = a ? "11" : "12"; + b = b ? "13" : "14"; + var x = %_StringCharCodeAt(a, 2); + var y = %_StringCharCodeAt(b, 0); + return a; // x and y are both dead +} + +function test() { + var S3 = S1 + S2; + + assertEquals(S1, dead1(S1, S2)); + assertEquals(S1, dead2(S1, S2)); + assertEquals("11", dead3(S1, S2)); + + assertEquals(S2, dead1(S2, 677)); + assertEquals(S2, dead2(S2, S3)); + assertEquals("11", dead3(S2, S3)); + + assertEquals(S3, dead1(S3, 399)); + assertEquals(S3, dead2(S3, "false")); + assertEquals("12", dead3(0, 32)); + + assertEquals(S3, dead1(S3, 0)); + assertEquals(S3, dead2(S3, S1)); + assertEquals("11", dead3(S3, 0)); + + assertEquals("true", dead1("true", 0)); + assertEquals("true", dead2("true", S3)); + assertEquals("11", dead3("true", 0)); +} + +test(); +test(); +%OptimizeFunctionOnNextCall(dead1); +%OptimizeFunctionOnNextCall(dead2); +%OptimizeFunctionOnNextCall(dead3); +test(); diff --git a/test/mjsunit/compiler/dead-string-char-from-code.js b/test/mjsunit/compiler/dead-string-char-from-code.js new file mode 100644 index 0000000..1de5d9e --- /dev/null +++ b/test/mjsunit/compiler/dead-string-char-from-code.js @@ -0,0 +1,76 @@ +// Copyright 2013 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 + +function dead1(a, b) { + var x = %_StringCharFromCode(a); + return a; // x is dead code +} + +function dead2(a, b) { + var x = %_StringCharFromCode(a); + var y = %_StringCharFromCode(b); + return a; // x and y are both dead +} + +function dead3(a, b) { + a = a ? 11 : 12; + b = b ? 13 : 14; + var x = %_StringCharFromCode(a); + var y = %_StringCharFromCode(b); + return a; // x and y are both dead +} + +function test() { + assertEquals(33, dead1(33, 32)); + assertEquals(33, dead2(33, 32)); + assertEquals(11, dead3(33, 32)); + + assertEquals(31, dead1(31, 30)); + assertEquals(31, dead2(31, 30)); + assertEquals(11, dead3(31, 32)); + + assertEquals(0, dead1(0, 30)); + assertEquals(0, dead2(0, 30)); + assertEquals(12, dead3(0, 32)); + + assertEquals(true, dead1(true, 0)); + assertEquals(true, dead2(true, 0)); + assertEquals(11, dead3(true, 0)); + + assertEquals("true", dead1("true", 0)); + assertEquals("true", dead2("true", 0)); + assertEquals(11, dead3("true", 0)); +} + +test(); +test(); +%OptimizeFunctionOnNextCall(dead1); +%OptimizeFunctionOnNextCall(dead2); +%OptimizeFunctionOnNextCall(dead3); +test(); -- 2.7.4