diff options
-rw-r--r-- | compiler/optimizing/constant_folding.cc | 27 | ||||
-rw-r--r-- | test/442-checker-constant-folding/src/Main.java | 61 | ||||
-rw-r--r-- | test/563-checker-fakestring/smali/TestCase.smali | 9 | ||||
-rw-r--r-- | test/563-checker-fakestring/src/Main.java | 7 |
4 files changed, 101 insertions, 3 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index 0614945ddc..5f39a49d68 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -47,6 +47,9 @@ class InstructionWithAbsorbingInputSimplifier : public HGraphVisitor { private: void VisitShift(HBinaryOperation* shift); + void VisitEqual(HEqual* instruction) OVERRIDE; + void VisitNotEqual(HNotEqual* instruction) OVERRIDE; + void VisitAbove(HAbove* instruction) OVERRIDE; void VisitAboveOrEqual(HAboveOrEqual* instruction) OVERRIDE; void VisitBelow(HBelow* instruction) OVERRIDE; @@ -140,6 +143,30 @@ void InstructionWithAbsorbingInputSimplifier::VisitShift(HBinaryOperation* instr } } +void InstructionWithAbsorbingInputSimplifier::VisitEqual(HEqual* instruction) { + if ((instruction->GetLeft()->IsNullConstant() && !instruction->GetRight()->CanBeNull()) || + (instruction->GetRight()->IsNullConstant() && !instruction->GetLeft()->CanBeNull())) { + // Replace code looking like + // EQUAL lhs, null + // where lhs cannot be null with + // CONSTANT false + instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 0)); + instruction->GetBlock()->RemoveInstruction(instruction); + } +} + +void InstructionWithAbsorbingInputSimplifier::VisitNotEqual(HNotEqual* instruction) { + if ((instruction->GetLeft()->IsNullConstant() && !instruction->GetRight()->CanBeNull()) || + (instruction->GetRight()->IsNullConstant() && !instruction->GetLeft()->CanBeNull())) { + // Replace code looking like + // NOT_EQUAL lhs, null + // where lhs cannot be null with + // CONSTANT true + instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimBoolean, 1)); + instruction->GetBlock()->RemoveInstruction(instruction); + } +} + void InstructionWithAbsorbingInputSimplifier::VisitAbove(HAbove* instruction) { if (instruction->GetLeft()->IsConstant() && instruction->GetLeft()->AsConstant()->IsArithmeticZero()) { diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java index 33ef10bf7f..64180d5273 100644 --- a/test/442-checker-constant-folding/src/Main.java +++ b/test/442-checker-constant-folding/src/Main.java @@ -27,6 +27,12 @@ public class Main { } } + public static void assertTrue(boolean condition) { + if (!condition) { + throw new Error(); + } + } + public static void assertIntEquals(int expected, int result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); @@ -1322,6 +1328,58 @@ public class Main { /** + * Test optimizations of comparisons with null yielding a constant result. + */ + + /// CHECK-START: boolean Main.ConstStringEqualsNull() constant_folding$after_inlining (before) + /// CHECK-DAG: <<ConstStr:l\d+>> LoadString + /// CHECK-DAG: <<Null:l\d+>> NullConstant + /// CHECK-DAG: <<Eq:z\d+>> Equal [<<ConstStr>>,<<Null>>] + /// CHECK-DAG: If [<<Eq>>] + + /// CHECK-START: boolean Main.ConstStringEqualsNull() constant_folding$after_inlining (after) + /// CHECK-DAG: <<False:i\d+>> IntConstant 0 + /// CHECK-DAG: If [<<False>>] + + /// CHECK-START: boolean Main.ConstStringEqualsNull() constant_folding$after_inlining (after) + /// CHECK-NOT: Equal + + public static boolean ConstStringEqualsNull() { + // Due to Jack emitting code using the opposite condition, use != to generate Equal. + if ($inline$ConstString() != null) { + return false; + } else { + return true; + } + } + + /// CHECK-START: boolean Main.ConstStringNotEqualsNull() constant_folding$after_inlining (before) + /// CHECK-DAG: <<ConstStr:l\d+>> LoadString + /// CHECK-DAG: <<Null:l\d+>> NullConstant + /// CHECK-DAG: <<Ne:z\d+>> NotEqual [<<ConstStr>>,<<Null>>] + /// CHECK-DAG: If [<<Ne>>] + + /// CHECK-START: boolean Main.ConstStringNotEqualsNull() constant_folding$after_inlining (after) + /// CHECK-DAG: <<True:i\d+>> IntConstant 1 + /// CHECK-DAG: If [<<True>>] + + /// CHECK-START: boolean Main.ConstStringNotEqualsNull() constant_folding$after_inlining (after) + /// CHECK-NOT: NotEqual + + public static boolean ConstStringNotEqualsNull() { + // Due to Jack emitting code using the opposite condition, use == to generate NotEqual. + if ($inline$ConstString() == null) { + return false; + } else { + return true; + } + } + + public static String $inline$ConstString() { + return ""; + } + + /** * Exercise constant folding on type conversions. */ @@ -1601,6 +1659,9 @@ public class Main { assertFalse(CmpFloatGreaterThanNaN(arbitrary)); assertFalse(CmpDoubleLessThanNaN(arbitrary)); + assertFalse(ConstStringEqualsNull()); + assertTrue(ConstStringNotEqualsNull()); + Main main = new Main(); assertIntEquals(1, main.smaliCmpLongConstants()); assertIntEquals(-1, main.smaliCmpGtFloatConstants()); diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali index 54312a43d0..9f8635239c 100644 --- a/test/563-checker-fakestring/smali/TestCase.smali +++ b/test/563-checker-fakestring/smali/TestCase.smali @@ -42,16 +42,19 @@ # Test usage of String new-instance before it is initialized. ## CHECK-START: void TestCase.compareNewInstance() register (after) -## CHECK-DAG: <<Null:l\d+>> NullConstant +## CHECK-DAG: <<Null:l\d+>> InvokeStaticOrDirect method_name:Main.$noinline$HiddenNull ## CHECK-DAG: <<String:l\d+>> NewInstance -## CHECK-DAG: <<Cond:z\d+>> NotEqual [<<String>>,<<Null>>] +## CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Null>>,<<String>>] ## CHECK-DAG: If [<<Cond>>] .method public static compareNewInstance()V .registers 3 + invoke-static {}, LMain;->$noinline$HiddenNull()Ljava/lang/Object; + move-result-object v1 + new-instance v0, Ljava/lang/String; - if-nez v0, :return + if-ne v0, v1, :return # Will throw NullPointerException if this branch is taken. const v1, 0x0 diff --git a/test/563-checker-fakestring/src/Main.java b/test/563-checker-fakestring/src/Main.java index 1ac8a5bfcf..78cb37ae09 100644 --- a/test/563-checker-fakestring/src/Main.java +++ b/test/563-checker-fakestring/src/Main.java @@ -79,4 +79,11 @@ public class Main { assertEqual(testString, result); } } + + public static boolean doThrow = false; + + public static Object $noinline$HiddenNull() { + if (doThrow) { throw new Error(); } + return null; + } } |