Home | History | Annotate | Download | only in src
      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 
     19   public static void assertIntEquals(int expected, int result) {
     20     if (expected != result) {
     21       throw new Error("Expected: " + expected + ", found: " + result);
     22     }
     23   }
     24 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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