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 assertIntEquals(int expected, int result)20 public static void assertIntEquals(int expected, int result) { 21 if (expected != result) { 22 throw new Error("Expected: " + expected + ", found: " + result); 23 } 24 } 25 inlineTrue()26 public static boolean inlineTrue() { 27 return true; 28 } 29 inlineFalse()30 public static boolean inlineFalse() { 31 return false; 32 } 33 testTrueBranch(int x, int y)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 testFalseBranch(int x, int y)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 testRemoveLoop(int x)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 testInfiniteLoop(int x)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 testDeadLoop(int x)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 testUpdateLoopInformation(int x)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 testRemoveSuspendCheck(int x, int y)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 main(String[] args)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