1 /* 2 * Copyright (C) 2014 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 assertIntEquals(int expected, int result)19 public static void assertIntEquals(int expected, int result) { 20 if (expected != result) { 21 throw new Error("Expected: " + expected + ", found: " + result); 22 } 23 } 24 assertLongEquals(long expected, long result)25 public static void assertLongEquals(long expected, long result) { 26 if (expected != result) { 27 throw new Error("Expected: " + expected + ", found: " + result); 28 } 29 } 30 31 /** 32 * Tiny three-register program exercising int constant folding 33 * on negation. 34 */ 35 36 // CHECK-START: int Main.IntNegation() constant_folding (before) 37 // CHECK-DAG: [[Const42:i\d+]] IntConstant 42 38 // CHECK-DAG: [[Neg:i\d+]] Neg [ [[Const42]] ] 39 // CHECK-DAG: Return [ [[Neg]] ] 40 41 // CHECK-START: int Main.IntNegation() constant_folding (after) 42 // CHECK-DAG: [[ConstN42:i\d+]] IntConstant -42 43 // CHECK-DAG: Return [ [[ConstN42]] ] 44 IntNegation()45 public static int IntNegation() { 46 int x, y; 47 x = 42; 48 y = -x; 49 return y; 50 } 51 52 /** 53 * Tiny three-register program exercising int constant folding 54 * on addition. 55 */ 56 57 // CHECK-START: int Main.IntAddition1() constant_folding (before) 58 // CHECK-DAG: [[Const1:i\d+]] IntConstant 1 59 // CHECK-DAG: [[Const2:i\d+]] IntConstant 2 60 // CHECK-DAG: [[Add:i\d+]] Add [ [[Const1]] [[Const2]] ] 61 // CHECK-DAG: Return [ [[Add]] ] 62 63 // CHECK-START: int Main.IntAddition1() constant_folding (after) 64 // CHECK-DAG: [[Const3:i\d+]] IntConstant 3 65 // CHECK-DAG: Return [ [[Const3]] ] 66 IntAddition1()67 public static int IntAddition1() { 68 int a, b, c; 69 a = 1; 70 b = 2; 71 c = a + b; 72 return c; 73 } 74 75 /** 76 * Small three-register program exercising int constant folding 77 * on addition. 78 */ 79 80 // CHECK-START: int Main.IntAddition2() constant_folding (before) 81 // CHECK-DAG: [[Const1:i\d+]] IntConstant 1 82 // CHECK-DAG: [[Const2:i\d+]] IntConstant 2 83 // CHECK-DAG: [[Const5:i\d+]] IntConstant 5 84 // CHECK-DAG: [[Const6:i\d+]] IntConstant 6 85 // CHECK-DAG: [[Add1:i\d+]] Add [ [[Const1]] [[Const2]] ] 86 // CHECK-DAG: [[Add2:i\d+]] Add [ [[Const5]] [[Const6]] ] 87 // CHECK-DAG: [[Add3:i\d+]] Add [ [[Add1]] [[Add2]] ] 88 // CHECK-DAG: Return [ [[Add3]] ] 89 90 // CHECK-START: int Main.IntAddition2() constant_folding (after) 91 // CHECK-DAG: [[Const14:i\d+]] IntConstant 14 92 // CHECK-DAG: Return [ [[Const14]] ] 93 IntAddition2()94 public static int IntAddition2() { 95 int a, b, c; 96 a = 1; 97 b = 2; 98 a += b; 99 b = 5; 100 c = 6; 101 b += c; 102 c = a + b; 103 return c; 104 } 105 106 /** 107 * Tiny three-register program exercising int constant folding 108 * on subtraction. 109 */ 110 111 // CHECK-START: int Main.IntSubtraction() constant_folding (before) 112 // CHECK-DAG: [[Const6:i\d+]] IntConstant 6 113 // CHECK-DAG: [[Const2:i\d+]] IntConstant 2 114 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Const6]] [[Const2]] ] 115 // CHECK-DAG: Return [ [[Sub]] ] 116 117 // CHECK-START: int Main.IntSubtraction() constant_folding (after) 118 // CHECK-DAG: [[Const4:i\d+]] IntConstant 4 119 // CHECK-DAG: Return [ [[Const4]] ] 120 IntSubtraction()121 public static int IntSubtraction() { 122 int a, b, c; 123 a = 6; 124 b = 2; 125 c = a - b; 126 return c; 127 } 128 129 /** 130 * Tiny three-register program exercising long constant folding 131 * on addition. 132 */ 133 134 // CHECK-START: long Main.LongAddition() constant_folding (before) 135 // CHECK-DAG: [[Const1:j\d+]] LongConstant 1 136 // CHECK-DAG: [[Const2:j\d+]] LongConstant 2 137 // CHECK-DAG: [[Add:j\d+]] Add [ [[Const1]] [[Const2]] ] 138 // CHECK-DAG: Return [ [[Add]] ] 139 140 // CHECK-START: long Main.LongAddition() constant_folding (after) 141 // CHECK-DAG: [[Const3:j\d+]] LongConstant 3 142 // CHECK-DAG: Return [ [[Const3]] ] 143 LongAddition()144 public static long LongAddition() { 145 long a, b, c; 146 a = 1L; 147 b = 2L; 148 c = a + b; 149 return c; 150 } 151 152 /** 153 * Tiny three-register program exercising long constant folding 154 * on subtraction. 155 */ 156 157 // CHECK-START: long Main.LongSubtraction() constant_folding (before) 158 // CHECK-DAG: [[Const6:j\d+]] LongConstant 6 159 // CHECK-DAG: [[Const2:j\d+]] LongConstant 2 160 // CHECK-DAG: [[Sub:j\d+]] Sub [ [[Const6]] [[Const2]] ] 161 // CHECK-DAG: Return [ [[Sub]] ] 162 163 // CHECK-START: long Main.LongSubtraction() constant_folding (after) 164 // CHECK-DAG: [[Const4:j\d+]] LongConstant 4 165 // CHECK-DAG: Return [ [[Const4]] ] 166 LongSubtraction()167 public static long LongSubtraction() { 168 long a, b, c; 169 a = 6L; 170 b = 2L; 171 c = a - b; 172 return c; 173 } 174 175 /** 176 * Three-register program with a constant (static) condition. 177 */ 178 179 // CHECK-START: int Main.StaticCondition() constant_folding (before) 180 // CHECK-DAG: [[Const7:i\d+]] IntConstant 7 181 // CHECK-DAG: [[Const2:i\d+]] IntConstant 2 182 // CHECK-DAG: [[Cond:z\d+]] GreaterThanOrEqual [ [[Const7]] [[Const2]] ] 183 // CHECK-DAG: If [ [[Cond]] ] 184 185 // CHECK-START: int Main.StaticCondition() constant_folding (after) 186 // CHECK-DAG: [[Const1:i\d+]] IntConstant 1 187 // CHECK-DAG: If [ [[Const1]] ] 188 StaticCondition()189 public static int StaticCondition() { 190 int a, b, c; 191 a = 7; 192 b = 2; 193 if (a < b) 194 c = a + b; 195 else 196 c = a - b; 197 return c; 198 } 199 200 /** 201 * Four-variable program with jumps leading to the creation of many 202 * blocks. 203 * 204 * The intent of this test is to ensure that all constant expressions 205 * are actually evaluated at compile-time, thanks to the reverse 206 * (forward) post-order traversal of the the dominator tree. 207 */ 208 209 // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before) 210 // CHECK-DAG: [[Const2:i\d+]] IntConstant 2 211 // CHECK-DAG: [[Const5:i\d+]] IntConstant 5 212 // CHECK-DAG: [[Add:i\d+]] Add [ [[Const5]] [[Const2]] ] 213 // CHECK-DAG: [[Sub:i\d+]] Sub [ [[Const5]] [[Const2]] ] 214 // CHECK-DAG: [[Phi:i\d+]] Phi [ [[Add]] [[Sub]] ] 215 // CHECK-DAG: Return [ [[Phi]] ] 216 217 // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after) 218 // CHECK-DAG: [[Const3:i\d+]] IntConstant 3 219 // CHECK-DAG: [[Const7:i\d+]] IntConstant 7 220 // CHECK-DAG: [[Phi:i\d+]] Phi [ [[Const7]] [[Const3]] ] 221 // CHECK-DAG: Return [ [[Phi]] ] 222 JumpsAndConditionals(boolean cond)223 public static int JumpsAndConditionals(boolean cond) { 224 int a, b, c; 225 a = 5; 226 b = 2; 227 if (cond) 228 c = a + b; 229 else 230 c = a - b; 231 return c; 232 } 233 234 /** 235 * Test optimizations of arithmetic identities yielding a constant result. 236 */ 237 238 // CHECK-START: int Main.And0(int) constant_folding (before) 239 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 240 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 241 // CHECK-DAG: [[And:i\d+]] And [ [[Arg]] [[Const0]] ] 242 // CHECK-DAG: Return [ [[And]] ] 243 244 // CHECK-START: int Main.And0(int) constant_folding (after) 245 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 246 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 247 // CHECK-NOT: And 248 // CHECK-DAG: Return [ [[Const0]] ] 249 And0(int arg)250 public static int And0(int arg) { 251 return arg & 0; 252 } 253 254 // CHECK-START: long Main.Mul0(long) constant_folding (before) 255 // CHECK-DAG: [[Arg:j\d+]] ParameterValue 256 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 257 // CHECK-DAG: [[Mul:j\d+]] Mul [ [[Arg]] [[Const0]] ] 258 // CHECK-DAG: Return [ [[Mul]] ] 259 260 // CHECK-START: long Main.Mul0(long) constant_folding (after) 261 // CHECK-DAG: [[Arg:j\d+]] ParameterValue 262 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 263 // CHECK-NOT: Mul 264 // CHECK-DAG: Return [ [[Const0]] ] 265 Mul0(long arg)266 public static long Mul0(long arg) { 267 return arg * 0; 268 } 269 270 // CHECK-START: int Main.OrAllOnes(int) constant_folding (before) 271 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 272 // CHECK-DAG: [[ConstF:i\d+]] IntConstant -1 273 // CHECK-DAG: [[Or:i\d+]] Or [ [[Arg]] [[ConstF]] ] 274 // CHECK-DAG: Return [ [[Or]] ] 275 276 // CHECK-START: int Main.OrAllOnes(int) constant_folding (after) 277 // CHECK-DAG: [[ConstF:i\d+]] IntConstant -1 278 // CHECK-NOT: Or 279 // CHECK-DAG: Return [ [[ConstF]] ] 280 OrAllOnes(int arg)281 public static int OrAllOnes(int arg) { 282 return arg | -1; 283 } 284 285 // CHECK-START: long Main.Rem0(long) constant_folding (before) 286 // CHECK-DAG: [[Arg:j\d+]] ParameterValue 287 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 288 // CHECK-DAG: [[DivZeroCheck:j\d+]] DivZeroCheck [ [[Arg]] ] 289 // CHECK-DAG: [[Rem:j\d+]] Rem [ [[Const0]] [[DivZeroCheck]] ] 290 // CHECK-DAG: Return [ [[Rem]] ] 291 292 // CHECK-START: long Main.Rem0(long) constant_folding (after) 293 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 294 // CHECK-NOT: Rem 295 // CHECK-DAG: Return [ [[Const0]] ] 296 Rem0(long arg)297 public static long Rem0(long arg) { 298 return 0 % arg; 299 } 300 301 // CHECK-START: int Main.Rem1(int) constant_folding (before) 302 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 303 // CHECK-DAG: [[Const1:i\d+]] IntConstant 1 304 // CHECK-DAG: [[Rem:i\d+]] Rem [ [[Arg]] [[Const1]] ] 305 // CHECK-DAG: Return [ [[Rem]] ] 306 307 // CHECK-START: int Main.Rem1(int) constant_folding (after) 308 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 309 // CHECK-NOT: Rem 310 // CHECK-DAG: Return [ [[Const0]] ] 311 Rem1(int arg)312 public static int Rem1(int arg) { 313 return arg % 1; 314 } 315 316 // CHECK-START: long Main.RemN1(long) constant_folding (before) 317 // CHECK-DAG: [[Arg:j\d+]] ParameterValue 318 // CHECK-DAG: [[ConstN1:j\d+]] LongConstant -1 319 // CHECK-DAG: [[DivZeroCheck:j\d+]] DivZeroCheck [ [[Arg]] ] 320 // CHECK-DAG: [[Rem:j\d+]] Rem [ [[Arg]] [[DivZeroCheck]] ] 321 // CHECK-DAG: Return [ [[Rem]] ] 322 323 // CHECK-START: long Main.RemN1(long) constant_folding (after) 324 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 325 // CHECK-NOT: Rem 326 // CHECK-DAG: Return [ [[Const0]] ] 327 RemN1(long arg)328 public static long RemN1(long arg) { 329 return arg % -1; 330 } 331 332 // CHECK-START: int Main.Shl0(int) constant_folding (before) 333 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 334 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 335 // CHECK-DAG: [[Shl:i\d+]] Shl [ [[Const0]] [[Arg]] ] 336 // CHECK-DAG: Return [ [[Shl]] ] 337 338 // CHECK-START: int Main.Shl0(int) constant_folding (after) 339 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 340 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 341 // CHECK-NOT: Shl 342 // CHECK-DAG: Return [ [[Const0]] ] 343 Shl0(int arg)344 public static int Shl0(int arg) { 345 return 0 << arg; 346 } 347 348 // CHECK-START: long Main.Shr0(int) constant_folding (before) 349 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 350 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 351 // CHECK-DAG: [[Shr:j\d+]] Shr [ [[Const0]] [[Arg]] ] 352 // CHECK-DAG: Return [ [[Shr]] ] 353 354 // CHECK-START: long Main.Shr0(int) constant_folding (after) 355 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 356 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 357 // CHECK-NOT: Shr 358 // CHECK-DAG: Return [ [[Const0]] ] 359 Shr0(int arg)360 public static long Shr0(int arg) { 361 return (long)0 >> arg; 362 } 363 364 // CHECK-START: long Main.SubSameLong(long) constant_folding (before) 365 // CHECK-DAG: [[Arg:j\d+]] ParameterValue 366 // CHECK-DAG: [[Sub:j\d+]] Sub [ [[Arg]] [[Arg]] ] 367 // CHECK-DAG: Return [ [[Sub]] ] 368 369 // CHECK-START: long Main.SubSameLong(long) constant_folding (after) 370 // CHECK-DAG: [[Arg:j\d+]] ParameterValue 371 // CHECK-DAG: [[Const0:j\d+]] LongConstant 0 372 // CHECK-NOT: Sub 373 // CHECK-DAG: Return [ [[Const0]] ] 374 SubSameLong(long arg)375 public static long SubSameLong(long arg) { 376 return arg - arg; 377 } 378 379 // CHECK-START: int Main.UShr0(int) constant_folding (before) 380 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 381 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 382 // CHECK-DAG: [[UShr:i\d+]] UShr [ [[Const0]] [[Arg]] ] 383 // CHECK-DAG: Return [ [[UShr]] ] 384 385 // CHECK-START: int Main.UShr0(int) constant_folding (after) 386 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 387 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 388 // CHECK-NOT: UShr 389 // CHECK-DAG: Return [ [[Const0]] ] 390 UShr0(int arg)391 public static int UShr0(int arg) { 392 return 0 >>> arg; 393 } 394 395 // CHECK-START: int Main.XorSameInt(int) constant_folding (before) 396 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 397 // CHECK-DAG: [[Xor:i\d+]] Xor [ [[Arg]] [[Arg]] ] 398 // CHECK-DAG: Return [ [[Xor]] ] 399 400 // CHECK-START: int Main.XorSameInt(int) constant_folding (after) 401 // CHECK-DAG: [[Arg:i\d+]] ParameterValue 402 // CHECK-DAG: [[Const0:i\d+]] IntConstant 0 403 // CHECK-NOT: Xor 404 // CHECK-DAG: Return [ [[Const0]] ] 405 XorSameInt(int arg)406 public static int XorSameInt(int arg) { 407 return arg ^ arg; 408 } 409 main(String[] args)410 public static void main(String[] args) { 411 assertIntEquals(IntNegation(), -42); 412 assertIntEquals(IntAddition1(), 3); 413 assertIntEquals(IntAddition2(), 14); 414 assertIntEquals(IntSubtraction(), 4); 415 assertLongEquals(LongAddition(), 3L); 416 assertLongEquals(LongSubtraction(), 4L); 417 assertIntEquals(StaticCondition(), 5); 418 assertIntEquals(JumpsAndConditionals(true), 7); 419 assertIntEquals(JumpsAndConditionals(false), 3); 420 int random = 123456; // Chosen randomly. 421 assertIntEquals(And0(random), 0); 422 assertLongEquals(Mul0(random), 0); 423 assertIntEquals(OrAllOnes(random), -1); 424 assertLongEquals(Rem0(random), 0); 425 assertIntEquals(Rem1(random), 0); 426 assertLongEquals(RemN1(random), 0); 427 assertIntEquals(Shl0(random), 0); 428 assertLongEquals(Shr0(random), 0); 429 assertLongEquals(SubSameLong(random), 0); 430 assertIntEquals(UShr0(random), 0); 431 assertIntEquals(XorSameInt(random), 0); 432 } 433 } 434