1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 public class Main { 18 assertIntEquals(int expected, int result)19 public static void assertIntEquals(int expected, int result) { 20 if (expected != result) { 21 throw new Error("Expected: " + expected + ", found: " + result); 22 } 23 } 24 assertStringEquals(String expected, String result)25 public static void assertStringEquals(String expected, String result) { 26 if (expected != null ? !expected.equals(result) : result != null) { 27 throw new Error("Expected: " + expected + ", found: " + result); 28 } 29 } 30 assertClassEquals(Class<?> expected, Class<?> result)31 public static void assertClassEquals(Class<?> expected, Class<?> result) { 32 if (expected != result) { 33 throw new Error("Expected: " + expected + ", found: " + result); 34 } 35 } 36 37 public static boolean doThrow = false; 38 $noinline$foo(int x)39 private static int $noinline$foo(int x) { 40 if (doThrow) { throw new Error(); } 41 return x; 42 } 43 44 /// CHECK-START: int Main.testSimple(int) sharpening (before) 45 /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall 46 47 /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: int Main.testSimple(int) sharpening (after) 48 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 49 50 /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (before) 51 /// CHECK-NOT: X86ComputeBaseMethodAddress 52 53 /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after) 54 /// CHECK: X86ComputeBaseMethodAddress 55 /// CHECK-NOT: X86ComputeBaseMethodAddress 56 testSimple(int x)57 public static int testSimple(int x) { 58 // This call should use PC-relative .bss array load to retrieve the target method. 59 return $noinline$foo(x); 60 } 61 62 /// CHECK-START: int Main.testDiamond(boolean, int) sharpening (before) 63 /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall 64 /// CHECK: InvokeStaticOrDirect method_load_kind:RuntimeCall 65 66 /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: int Main.testDiamond(boolean, int) sharpening (after) 67 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 68 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 69 70 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (before) 71 /// CHECK-NOT: X86ComputeBaseMethodAddress 72 73 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 74 /// CHECK: X86ComputeBaseMethodAddress 75 /// CHECK-NOT: X86ComputeBaseMethodAddress 76 77 /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 78 /// CHECK: X86ComputeBaseMethodAddress 79 /// CHECK-NEXT: If 80 testDiamond(boolean negate, int x)81 public static int testDiamond(boolean negate, int x) { 82 // These calls should use PC-relative loads to retrieve the target method. 83 // PC-relative bases used by MIPS32R2 and X86 should be pulled before the If. 84 if (negate) { 85 return $noinline$foo(-x); 86 } else { 87 return $noinline$foo(x); 88 } 89 } 90 91 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before) 92 /// CHECK-NOT: X86ComputeBaseMethodAddress 93 94 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 95 /// CHECK: X86ComputeBaseMethodAddress 96 /// CHECK-NOT: X86ComputeBaseMethodAddress 97 98 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 99 /// CHECK: InvokeStaticOrDirect 100 /// CHECK-NOT: InvokeStaticOrDirect 101 102 /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 103 /// CHECK: ArrayLength 104 /// CHECK-NEXT: X86ComputeBaseMethodAddress 105 /// CHECK-NEXT: Goto 106 /// CHECK: begin_block 107 /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 108 testLoop(int[] array, int x)109 public static int testLoop(int[] array, int x) { 110 // PC-relative bases used by MIPS32R2 and X86 should be pulled before the loop. 111 for (int i : array) { 112 x += $noinline$foo(i); 113 } 114 return x; 115 } 116 117 /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before) 118 /// CHECK-NOT: X86ComputeBaseMethodAddress 119 120 /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after) 121 /// CHECK: If 122 /// CHECK: begin_block 123 /// CHECK: ArrayLength 124 /// CHECK-NEXT: X86ComputeBaseMethodAddress 125 /// CHECK-NEXT: Goto 126 testLoopWithDiamond(int[] array, boolean negate, int x)127 public static int testLoopWithDiamond(int[] array, boolean negate, int x) { 128 // PC-relative bases used by MIPS32R2 and X86 should be pulled before the loop 129 // but not outside the if. 130 if (array != null) { 131 for (int i : array) { 132 if (negate) { 133 x += $noinline$foo(-i); 134 } else { 135 x += $noinline$foo(i); 136 } 137 } 138 } 139 return x; 140 } 141 142 /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$getBootImageString() builder (after) 143 // Note: load kind depends on PIC/non-PIC 144 /// CHECK: LoadString load_kind:{{BootImageAddress|BootImageInternTable}} 145 $noinline$getBootImageString()146 public static String $noinline$getBootImageString() { 147 // Prevent inlining to avoid the string comparison being optimized away. 148 if (doThrow) { throw new Error(); } 149 // Empty string is known to be in the boot image. 150 return ""; 151 } 152 153 /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.String Main.$noinline$getNonBootImageString() builder (after) 154 /// CHECK: LoadString load_kind:BssEntry 155 156 /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (before) 157 /// CHECK-NOT: X86ComputeBaseMethodAddress 158 159 /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (after) 160 /// CHECK-DAG: X86ComputeBaseMethodAddress 161 /// CHECK-DAG: LoadString load_kind:BssEntry 162 $noinline$getNonBootImageString()163 public static String $noinline$getNonBootImageString() { 164 // Prevent inlining to avoid the string comparison being optimized away. 165 if (doThrow) { throw new Error(); } 166 // This string is not in the boot image. 167 return "non-boot-image-string"; 168 } 169 170 /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.Class Main.$noinline$getStringClass() builder (after) 171 // Note: load kind depends on PIC/non-PIC 172 /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String 173 $noinline$getStringClass()174 public static Class<?> $noinline$getStringClass() { 175 // Prevent inlining to avoid the string comparison being optimized away. 176 if (doThrow) { throw new Error(); } 177 // String class is known to be in the boot image. 178 return String.class; 179 } 180 181 /// CHECK-START-{ARM,ARM64,MIPS,MIPS64,X86,X86_64}: java.lang.Class Main.$noinline$getOtherClass() builder (after) 182 /// CHECK: LoadClass load_kind:BssEntry class_name:Other 183 184 /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (before) 185 /// CHECK-NOT: X86ComputeBaseMethodAddress 186 187 /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after) 188 /// CHECK-DAG: X86ComputeBaseMethodAddress 189 /// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other 190 $noinline$getOtherClass()191 public static Class<?> $noinline$getOtherClass() { 192 // Prevent inlining to avoid the string comparison being optimized away. 193 if (doThrow) { throw new Error(); } 194 // Other class is not in the boot image. 195 return Other.class; 196 } 197 main(String[] args)198 public static void main(String[] args) { 199 assertIntEquals(1, testSimple(1)); 200 assertIntEquals(1, testDiamond(false, 1)); 201 assertIntEquals(-1, testDiamond(true, 1)); 202 assertIntEquals(3, testLoop(new int[]{ 2 }, 1)); 203 assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1)); 204 assertIntEquals(1, testLoopWithDiamond(null, false, 1)); 205 assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1)); 206 assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1)); 207 assertStringEquals("", $noinline$getBootImageString()); 208 assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString()); 209 assertClassEquals(String.class, $noinline$getStringClass()); 210 assertClassEquals(Other.class, $noinline$getOtherClass()); 211 } 212 } 213 214 class Other { 215 } 216