diff options
author | 2015-12-01 14:58:23 +0000 | |
---|---|---|
committer | 2015-12-02 10:48:16 +0000 | |
commit | f64242a30c6e05a8e4302a64eab4bcc28297dc9e (patch) | |
tree | 98cbceab543c81f523c5bb676e10853ddfbc9881 | |
parent | b1aa617639c01c0dffaafd1641e0304ad179b6a2 (diff) |
Optimizing: Add checker tests for sharpening.
This is a follow-up to
https://android-review.googlesource.com/184116 .
Change-Id: Ib03c424fb673afc5ccce15d7d072b7572b47799a
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 4 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 23 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 1 | ||||
-rw-r--r-- | test/488-checker-inline-recursive-calls/src/Main.java | 4 | ||||
-rw-r--r-- | test/552-checker-sharpening/expected.txt | 0 | ||||
-rw-r--r-- | test/552-checker-sharpening/info.txt | 1 | ||||
-rw-r--r-- | test/552-checker-sharpening/src/Main.java | 198 |
7 files changed, 225 insertions, 6 deletions
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 48bcd10b10..1f65c083cc 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -393,9 +393,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { 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 847d147b69..9b26de44fe 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -2132,6 +2132,26 @@ void HInvokeStaticOrDirect::RemoveInputAt(size_t index) { } } +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 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckReq 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 441aa0493a..6c3e6f4a25 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -3622,6 +3622,7 @@ class HInvokeStaticOrDirect : public HInvoke { 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 c1f25b3004..87ff3f7b5a 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 @@ public class Main { } /// 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 0000000000..e69de29bb2 --- /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 0000000000..c84539ce01 --- /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 0000000000..d50edd8f2f --- /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)); + } +} |