12d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil/*
26a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * Copyright (C) 2015 The Android Open Source Project
36a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain *
46a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * Licensed under the Apache License, Version 2.0 (the "License");
56a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * you may not use this file except in compliance with the License.
66a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * You may obtain a copy of the License at
76a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain *
86a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain *      http://www.apache.org/licenses/LICENSE-2.0
96a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain *
106a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * Unless required by applicable law or agreed to in writing, software
116a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * distributed under the License is distributed on an "AS IS" BASIS,
126a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * See the License for the specific language governing permissions and
146a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain * limitations under the License.
156a92a033c33e383541d77607fbe8cd982875d13dRoland Levillain */
16b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leungimport java.lang.reflect.Method;
172d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
182d7352ba5311b8f57427b91b7a891e61497373c1David Brazdilpublic class Main {
192d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
202d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static void assertIntEquals(int expected, int result) {
212d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    if (expected != result) {
222d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      throw new Error("Expected: " + expected + ", found: " + result);
232d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
242d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
252d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
262d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static boolean inlineTrue() {
272d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    return true;
282d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
292d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
302d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static boolean inlineFalse() {
312d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    return false;
322d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
332d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
342d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static int testTrueBranch(int x, int y) {
35b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      try {
36b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      Class<?> c = Class.forName("Smali");
37b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      Method m = c.getMethod("testTrueBranch", int.class, int.class);
38b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      return (Integer) m.invoke(null, x, y);
39b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung    } catch (Throwable t) {
40b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      throw new RuntimeException(t);
412d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
422d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
432d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
442d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static int testFalseBranch(int x, int y) {
45b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      try {
46b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      Class<?> c = Class.forName("Smali");
47b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      Method m = c.getMethod("testFalseBranch", int.class, int.class);
48b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      return (Integer) m.invoke(null, x, y);
49b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung    } catch (Throwable t) {
50b03f3ebfef7343718ef609bd677b23a2d7c997bbAlan Leung      throw new RuntimeException(t);
512d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
522d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
532d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
542767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (before)
55a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK:                          Mul
562d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
572767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (after)
58a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      Mul
592d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
602d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static int testRemoveLoop(int x) {
612d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    if (inlineFalse()) {
622d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      for (int i = 0; i < x; ++i) {
632d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil        x *= x;
642d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      }
652d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
662d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    return x;
672d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
682d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
692767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination$after_inlining (before)
70a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      Return
71a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      Exit
722d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
732767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination$after_inlining (after)
74a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      Return
75a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      Exit
762d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
772d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static int testInfiniteLoop(int x) {
782d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    while (inlineTrue()) {
792d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      x++;
802d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
812d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    return x;
822d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
832d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
842767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (before)
85a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      If
86a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      Add
872d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
882767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (after)
89a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
90a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      Return [<<Arg>>]
912d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
922767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (after)
93a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      If
94a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      Add
952d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
962d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static int testDeadLoop(int x) {
972d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    while (inlineFalse()) {
982d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil      x++;
992d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    }
1002d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    return x;
1012d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
1022d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil
1032767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (before)
104a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      If
105a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      If
106a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      Add
10769a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
1082767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (after)
109a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
110a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-DAG:                      Return [<<Arg>>]
11169a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
1122767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (after)
113a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      If
114a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      Add
11569a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
11669a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil  public static int testUpdateLoopInformation(int x) {
11769a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    // Use of Or in the condition generates a dead loop where not all of its
11869a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    // blocks are removed. This forces DCE to update their loop information.
11969a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    while (inlineFalse() || !inlineTrue()) {
12069a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil      x++;
12169a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    }
12269a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    return x;
12369a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil  }
12469a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
1252767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination$after_inlining (before)
126a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK:                          SuspendCheck
127a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK:                          SuspendCheck
128a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK:                          SuspendCheck
129a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      SuspendCheck
13069a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
1312767f4ba2df934fea4c50a016e2955c2cf3f6b19Aart Bik  /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination$after_inlining (after)
132a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK:                          SuspendCheck
133a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK:                          SuspendCheck
134a06d66a4ee60926127b9498b7ff0b3e37a24fccfDavid Brazdil  /// CHECK-NOT:                      SuspendCheck
13569a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
13669a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil  public static int testRemoveSuspendCheck(int x, int y) {
13769a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    // Inner loop will leave behind the header with its SuspendCheck. DCE must
13869a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    // remove it, otherwise the outer loop would end up with two.
13969a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    while (y > 0) {
14069a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil      while (inlineFalse() || !inlineTrue()) {
14169a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil        x++;
14269a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil      }
14369a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil      y--;
14469a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    }
14569a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    return x;
14669a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil  }
14769a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil
1482d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  public static void main(String[] args) {
1492d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    assertIntEquals(7, testTrueBranch(4, 3));
1502d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    assertIntEquals(1, testFalseBranch(4, 3));
1512d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil    assertIntEquals(42, testRemoveLoop(42));
15269a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    assertIntEquals(23, testUpdateLoopInformation(23));
15369a2804c3bb48cf4fd00a66080f613a4fd96c422David Brazdil    assertIntEquals(12, testRemoveSuspendCheck(12, 5));
1542d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil  }
1552d7352ba5311b8f57427b91b7a891e61497373c1David Brazdil}
156