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 /// CHECK-START: Main Main.keepTest(Main) instruction_simplifier (before) 20 /// CHECK: NullCheck 21 /// CHECK: InvokeStaticOrDirect 22 23 /// CHECK-START: Main Main.keepTest(Main) instruction_simplifier (after) 24 /// CHECK: NullCheck 25 /// CHECK: InvokeStaticOrDirect keepTest(Main m)26 public Main keepTest(Main m) { 27 return m.g(); 28 } 29 30 /// CHECK-START: Main Main.thisTest() builder (after) 31 /// CHECK-NOT: NullCheck 32 /// CHECK: InvokeStaticOrDirect thisTest()33 public Main thisTest() { 34 return g(); 35 } 36 37 /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after) 38 /// CHECK: NewInstance 39 /// CHECK: InvokeStaticOrDirect 40 /// CHECK: InvokeStaticOrDirect 41 42 /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after) 43 /// CHECK-NOT: NullCheck newInstanceRemoveTest()44 public Main newInstanceRemoveTest() { 45 Main m = new Main(); 46 return m.g(); 47 } 48 49 /// CHECK-START: Main Main.newArrayRemoveTest() builder (after) 50 /// CHECK: NewArray 51 /// CHECK: ArrayGet 52 53 /// CHECK-START: Main Main.newArrayRemoveTest() builder (after) 54 /// CHECK-NOT: NullCheck newArrayRemoveTest()55 public Main newArrayRemoveTest() { 56 Main[] ms = new Main[1]; 57 return ms[0]; 58 } 59 60 /// CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier (before) 61 /// CHECK: NewInstance 62 /// CHECK: NullCheck 63 64 /// CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier (after) 65 /// CHECK: NewInstance 66 /// CHECK-NOT: NullCheck ifRemoveTest(boolean flag)67 public Main ifRemoveTest(boolean flag) { 68 Main m = null; 69 if (flag) { 70 m = new Main(); 71 } else { 72 m = new Main(1); 73 } 74 return m.g(); 75 } 76 77 /// CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier (before) 78 /// CHECK: NewInstance 79 /// CHECK: NullCheck 80 81 /// CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier (after) 82 /// CHECK: NewInstance 83 /// CHECK: NullCheck ifKeepTest(boolean flag)84 public Main ifKeepTest(boolean flag) { 85 Main m = null; 86 if (flag) { 87 m = new Main(1); 88 } 89 return m.g(); 90 } 91 92 /// CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier (before) 93 /// CHECK: NullCheck 94 95 /// CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier (after) 96 /// CHECK-NOT: NullCheck forRemoveTest(int count)97 public Main forRemoveTest(int count) { 98 Main a = new Main(); 99 Main m = new Main(); 100 for (int i = 0; i < count; i++) { 101 if (i % 2 == 0) { 102 m = a; 103 } 104 } 105 return m.g(); 106 } 107 108 /// CHECK-START: Main Main.forKeepTest(int) instruction_simplifier (before) 109 /// CHECK: NullCheck 110 111 /// CHECK-START: Main Main.forKeepTest(int) instruction_simplifier (after) 112 /// CHECK: NullCheck forKeepTest(int count)113 public Main forKeepTest(int count) { 114 Main a = new Main(); 115 Main m = new Main(); 116 for (int i = 0; i < count; i++) { 117 if (i % 2 == 0) { 118 m = a; 119 } else { 120 m = null; 121 } 122 } 123 return m.g(); 124 } 125 126 /// CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier (before) 127 /// CHECK: NullCheck 128 129 /// CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier (after) 130 /// CHECK-NOT: NullCheck phiFlowRemoveTest(int count)131 public Main phiFlowRemoveTest(int count) { 132 Main a = new Main(); 133 Main m = new Main(); 134 for (int i = 0; i < count; i++) { 135 if (i % 2 == 0) { 136 m = a; 137 } 138 } 139 Main n = new Main(); 140 for (int i = 0; i < count; i++) { 141 if (i % 3 == 0) { 142 n = m; 143 } 144 } 145 return n.g(); 146 } 147 148 /// CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier (before) 149 /// CHECK: NullCheck 150 151 /// CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier (after) 152 /// CHECK: NullCheck phiFlowKeepTest(int count)153 public Main phiFlowKeepTest(int count) { 154 Main a = new Main(); 155 Main m = new Main(); 156 for (int i = 0; i < count; i++) { 157 if (i % 2 == 0) { 158 m = a; 159 } else { 160 m = null; 161 } 162 } 163 Main n = new Main(); 164 for (int i = 0; i < count; i++) { 165 if (i % 3 == 0) { 166 n = m; 167 } 168 } 169 return n.g(); 170 } 171 172 /// CHECK-START: Main Main.scopeRemoveTest(int, Main) builder (after) 173 /// CHECK-NOT: NullCheck scopeRemoveTest(int count, Main a)174 public Main scopeRemoveTest(int count, Main a) { 175 Main m = null; 176 for (int i = 0; i < count; i++) { 177 if (i % 2 == 0) { 178 m = new Main(); 179 m.g(); 180 } else { 181 m = a; 182 } 183 } 184 return m; 185 } 186 187 /// CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier (before) 188 /// CHECK: NullCheck 189 190 /// CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier (after) 191 /// CHECK: NullCheck scopeKeepTest(int count, Main a)192 public Main scopeKeepTest(int count, Main a) { 193 Main m = new Main(); 194 for (int i = 0; i < count; i++) { 195 if (i % 2 == 0) { 196 m = a; 197 } else { 198 m = a; 199 m.g(); 200 } 201 } 202 return m; 203 } 204 205 /// CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier (before) 206 /// CHECK: NullCheck 207 208 /// CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier (after) 209 /// CHECK-NOT: NullCheck scopeIfNotNullRemove(Main m)210 public Main scopeIfNotNullRemove(Main m) { 211 if (m != null) { 212 return m.g(); 213 } 214 return m; 215 } 216 217 /// CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier (before) 218 /// CHECK: NullCheck 219 220 /// CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier (after) 221 /// CHECK: NullCheck scopeIfKeep(Main m)222 public Main scopeIfKeep(Main m) { 223 if (m == null) { 224 m = new Main(); 225 } 226 return m.g(); 227 } 228 Main()229 public Main() {} Main(int dummy)230 public Main(int dummy) {} 231 g()232 private Main g() { 233 // avoids inlining 234 throw new RuntimeException(); 235 } 236 main(String[] args)237 public static void main(String[] args) { 238 new Main(); 239 } 240 241 } 242 243 // Regression for when we created and kept equivalent phis with the same type. 244 // The phi used in comparison would be different then the one used for access 245 // so we could not safely discard it. 246 class ListElement { 247 private ListElement next; 248 249 /// CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier (before) 250 /// CHECK: NullCheck 251 /// CHECK: NullCheck 252 253 /// CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier (after) 254 /// CHECK-NOT: NullCheck isShorter(ListElement x, ListElement y)255 static boolean isShorter(ListElement x, ListElement y) { 256 ListElement xTail = x; 257 ListElement yTail = y; 258 while (yTail != null) { 259 if (xTail == null) return true; 260 xTail = xTail.next; 261 yTail = yTail.next; 262 } 263 return false; 264 } 265 } 266