Merge "Optimizing: Add checker tests for sharpening."
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 48bcd10..1f65c08 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -393,9 +393,7 @@
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
VisitInvoke(invoke);
- StartAttributeStream("recursive") << std::boolalpha
- << invoke->IsRecursive()
- << std::noboolalpha;
+ StartAttributeStream("method_load_kind") << invoke->GetMethodLoadKind();
StartAttributeStream("intrinsic") << invoke->GetIntrinsic();
if (invoke->IsStatic()) {
StartAttributeStream("clinit_check") << invoke->GetClinitCheckRequirement();
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 847d147..9b26de4 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2132,6 +2132,26 @@
}
}
+std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs) {
+ switch (rhs) {
+ case HInvokeStaticOrDirect::MethodLoadKind::kStringInit:
+ return os << "string_init";
+ case HInvokeStaticOrDirect::MethodLoadKind::kRecursive:
+ return os << "recursive";
+ case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
+ return os << "direct";
+ case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup:
+ return os << "direct_fixup";
+ case HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative:
+ return os << "dex_cache_pc_relative";
+ case HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod:
+ return os << "dex_cache_via_method";
+ default:
+ LOG(FATAL) << "Unknown MethodLoadKind: " << static_cast<int>(rhs);
+ UNREACHABLE();
+ }
+}
+
std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs) {
switch (rhs) {
case HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit:
@@ -2141,7 +2161,8 @@
case HInvokeStaticOrDirect::ClinitCheckRequirement::kNone:
return os << "none";
default:
- return os << "unknown:" << static_cast<int>(rhs);
+ LOG(FATAL) << "Unknown ClinitCheckRequirement: " << static_cast<int>(rhs);
+ UNREACHABLE();
}
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 441aa04..6c3e6f4 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -3622,6 +3622,7 @@
DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
};
+std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs);
class HInvokeVirtual : public HInvoke {
diff --git a/test/488-checker-inline-recursive-calls/src/Main.java b/test/488-checker-inline-recursive-calls/src/Main.java
index c1f25b3..87ff3f7 100644
--- a/test/488-checker-inline-recursive-calls/src/Main.java
+++ b/test/488-checker-inline-recursive-calls/src/Main.java
@@ -25,10 +25,10 @@
}
/// CHECK-START: void Main.doTopCall(boolean) inliner (before)
- /// CHECK-NOT: InvokeStaticOrDirect recursive:true
+ /// CHECK-NOT: InvokeStaticOrDirect method_load_kind:recursive
/// CHECK-START: void Main.doTopCall(boolean) inliner (after)
- /// CHECK: InvokeStaticOrDirect recursive:true
+ /// CHECK: InvokeStaticOrDirect method_load_kind:recursive
public static void doTopCall(boolean first_call) {
if (first_call) {
inline1();
diff --git a/test/552-checker-sharpening/expected.txt b/test/552-checker-sharpening/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/552-checker-sharpening/expected.txt
diff --git a/test/552-checker-sharpening/info.txt b/test/552-checker-sharpening/info.txt
new file mode 100644
index 0000000..c84539c
--- /dev/null
+++ b/test/552-checker-sharpening/info.txt
@@ -0,0 +1 @@
+Tests for sharpening.
diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java
new file mode 100644
index 0000000..d50edd8
--- /dev/null
+++ b/test/552-checker-sharpening/src/Main.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+
+ public static void assertIntEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static boolean doThrow = false;
+
+ private static int $noinline$foo(int x) {
+ if (doThrow) { throw new Error(); }
+ return x;
+ }
+
+ /// CHECK-START: int Main.testSimple(int) sharpening (before)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_via_method
+
+ /// CHECK-START-ARM: int Main.testSimple(int) sharpening (after)
+ /// CHECK-NOT: ArmDexCacheArraysBase
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-ARM64: int Main.testSimple(int) sharpening (after)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-X86: int Main.testSimple(int) sharpening (after)
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-X86_64: int Main.testSimple(int) sharpening (after)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-ARM: int Main.testSimple(int) dex_cache_array_fixups_arm (after)
+ /// CHECK: ArmDexCacheArraysBase
+ /// CHECK-NOT: ArmDexCacheArraysBase
+
+ /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after)
+ /// CHECK: X86ComputeBaseMethodAddress
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ public static int testSimple(int x) {
+ // This call should use PC-relative dex cache array load to retrieve the target method.
+ return $noinline$foo(x);
+ }
+
+ /// CHECK-START: int Main.testDiamond(boolean, int) sharpening (before)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_via_method
+
+ /// CHECK-START-ARM: int Main.testDiamond(boolean, int) sharpening (after)
+ /// CHECK-NOT: ArmDexCacheArraysBase
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-ARM64: int Main.testDiamond(boolean, int) sharpening (after)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-X86: int Main.testDiamond(boolean, int) sharpening (after)
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-X86_64: int Main.testDiamond(boolean, int) sharpening (after)
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-ARM: int Main.testDiamond(boolean, int) dex_cache_array_fixups_arm (after)
+ /// CHECK: ArmDexCacheArraysBase
+ /// CHECK-NOT: ArmDexCacheArraysBase
+
+ /// CHECK-START-ARM: int Main.testDiamond(boolean, int) dex_cache_array_fixups_arm (after)
+ /// CHECK: ArmDexCacheArraysBase
+ /// CHECK-NEXT: If
+
+ /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
+ /// CHECK: X86ComputeBaseMethodAddress
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
+ /// CHECK: X86ComputeBaseMethodAddress
+ /// CHECK-NEXT: If
+
+ public static int testDiamond(boolean negate, int x) {
+ // These calls should use PC-relative dex cache array loads to retrieve the target method.
+ // PC-relative bases used by X86 and ARM should be pulled before the If.
+ if (negate) {
+ return $noinline$foo(-x);
+ } else {
+ return $noinline$foo(x);
+ }
+ }
+
+ /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before)
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
+ /// CHECK: X86ComputeBaseMethodAddress
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
+ /// CHECK: ArrayLength
+ /// CHECK-NEXT: X86ComputeBaseMethodAddress
+ /// CHECK-NEXT: Goto
+ /// CHECK: begin_block
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (before)
+ /// CHECK-NOT: ArmDexCacheArraysBase
+
+ /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (after)
+ /// CHECK: ArmDexCacheArraysBase
+ /// CHECK-NOT: ArmDexCacheArraysBase
+
+ /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (after)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START-ARM: int Main.testLoop(int[], int) dex_cache_array_fixups_arm (after)
+ /// CHECK: ArrayLength
+ /// CHECK-NEXT: ArmDexCacheArraysBase
+ /// CHECK-NEXT: Goto
+ /// CHECK: begin_block
+ /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
+
+ public static int testLoop(int[] array, int x) {
+ // PC-relative bases used by X86 and ARM should be pulled before the loop.
+ for (int i : array) {
+ x += $noinline$foo(i);
+ }
+ return x;
+ }
+
+ /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before)
+ /// CHECK-NOT: X86ComputeBaseMethodAddress
+
+ /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after)
+ /// CHECK: If
+ /// CHECK: begin_block
+ /// CHECK: ArrayLength
+ /// CHECK-NEXT: X86ComputeBaseMethodAddress
+ /// CHECK-NEXT: Goto
+
+ /// CHECK-START-ARM: int Main.testLoopWithDiamond(int[], boolean, int) dex_cache_array_fixups_arm (before)
+ /// CHECK-NOT: ArmDexCacheArraysBase
+
+ /// CHECK-START-ARM: int Main.testLoopWithDiamond(int[], boolean, int) dex_cache_array_fixups_arm (after)
+ /// CHECK: If
+ /// CHECK: begin_block
+ /// CHECK: ArrayLength
+ /// CHECK-NEXT: ArmDexCacheArraysBase
+ /// CHECK-NEXT: Goto
+
+ public static int testLoopWithDiamond(int[] array, boolean negate, int x) {
+ // PC-relative bases used by X86 and ARM should be pulled before the loop
+ // but not outside the if.
+ if (array != null) {
+ for (int i : array) {
+ if (negate) {
+ x += $noinline$foo(-i);
+ } else {
+ x += $noinline$foo(i);
+ }
+ }
+ }
+ return x;
+ }
+
+ public static void main(String[] args) {
+ assertIntEquals(1, testSimple(1));
+ assertIntEquals(1, testDiamond(false, 1));
+ assertIntEquals(-1, testDiamond(true, 1));
+ assertIntEquals(3, testLoop(new int[]{ 2 }, 1));
+ assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1));
+ assertIntEquals(1, testLoopWithDiamond(null, false, 1));
+ assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1));
+ assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1));
+ }
+}