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 import java.lang.reflect.Method;
     17 
     18 public class Main {
     19 
     20   public static void assertIntEquals(int expected, int result) {
     21     if (expected != result) {
     22       throw new Error("Expected: " + expected + ", found: " + result);
     23     }
     24   }
     25 
     26   public static boolean inlineTrue() {
     27     return true;
     28   }
     29 
     30   public static boolean inlineFalse() {
     31     return false;
     32   }
     33 
     34   public static int testTrueBranch(int x, int y) {
     35       try {
     36       Class<?> c = Class.forName("Smali");
     37       Method m = c.getMethod("testTrueBranch", int.class, int.class);
     38       return (Integer) m.invoke(null, x, y);
     39     } catch (Throwable t) {
     40       throw new RuntimeException(t);
     41     }
     42   }
     43 
     44   public static int testFalseBranch(int x, int y) {
     45       try {
     46       Class<?> c = Class.forName("Smali");
     47       Method m = c.getMethod("testFalseBranch", int.class, int.class);
     48       return (Integer) m.invoke(null, x, y);
     49     } catch (Throwable t) {
     50       throw new RuntimeException(t);
     51     }
     52   }
     53 
     54   /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (before)
     55   /// CHECK:                          Mul
     56 
     57   /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (after)
     58   /// CHECK-NOT:                      Mul
     59 
     60   public static int testRemoveLoop(int x) {
     61     if (inlineFalse()) {
     62       for (int i = 0; i < x; ++i) {
     63         x *= x;
     64       }
     65     }
     66     return x;
     67   }
     68 
     69   /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination$after_inlining (before)
     70   /// CHECK-DAG:                      Return
     71   /// CHECK-DAG:                      Exit
     72 
     73   /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination$after_inlining (after)
     74   /// CHECK-NOT:                      Return
     75   /// CHECK-NOT:                      Exit
     76 
     77   public static int testInfiniteLoop(int x) {
     78     while (inlineTrue()) {
     79       x++;
     80     }
     81     return x;
     82   }
     83 
     84   /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (before)
     85   /// CHECK-DAG:                      If
     86   /// CHECK-DAG:                      Add
     87 
     88   /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (after)
     89   /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
     90   /// CHECK-DAG:                      Return [<<Arg>>]
     91 
     92   /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (after)
     93   /// CHECK-NOT:                      If
     94   /// CHECK-NOT:                      Add
     95 
     96   public static int testDeadLoop(int x) {
     97     while (inlineFalse()) {
     98       x++;
     99     }
    100     return x;
    101   }
    102 
    103   /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (before)
    104   /// CHECK-DAG:                      If
    105   /// CHECK-DAG:                      If
    106   /// CHECK-DAG:                      Add
    107 
    108   /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (after)
    109   /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
    110   /// CHECK-DAG:                      Return [<<Arg>>]
    111 
    112   /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (after)
    113   /// CHECK-NOT:                      If
    114   /// CHECK-NOT:                      Add
    115 
    116   public static int testUpdateLoopInformation(int x) {
    117     // Use of Or in the condition generates a dead loop where not all of its
    118     // blocks are removed. This forces DCE to update their loop information.
    119     while (inlineFalse() || !inlineTrue()) {
    120       x++;
    121     }
    122     return x;
    123   }
    124 
    125   /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination$after_inlining (before)
    126   /// CHECK:                          SuspendCheck
    127   /// CHECK:                          SuspendCheck
    128   /// CHECK:                          SuspendCheck
    129   /// CHECK-NOT:                      SuspendCheck
    130 
    131   /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination$after_inlining (after)
    132   /// CHECK:                          SuspendCheck
    133   /// CHECK:                          SuspendCheck
    134   /// CHECK-NOT:                      SuspendCheck
    135 
    136   public static int testRemoveSuspendCheck(int x, int y) {
    137     // Inner loop will leave behind the header with its SuspendCheck. DCE must
    138     // remove it, otherwise the outer loop would end up with two.
    139     while (y > 0) {
    140       while (inlineFalse() || !inlineTrue()) {
    141         x++;
    142       }
    143       y--;
    144     }
    145     return x;
    146   }
    147 
    148   public static void main(String[] args) {
    149     assertIntEquals(7, testTrueBranch(4, 3));
    150     assertIntEquals(1, testFalseBranch(4, 3));
    151     assertIntEquals(42, testRemoveLoop(42));
    152     assertIntEquals(23, testUpdateLoopInformation(23));
    153     assertIntEquals(12, testRemoveSuspendCheck(12, 5));
    154   }
    155 }
    156