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 assertIntEquals(int expected, int actual)19 public static void assertIntEquals(int expected, int actual) { 20 if (expected != actual) { 21 throw new Error("Expected: " + expected + ", found: " + actual); 22 } 23 } 24 assertLongEquals(long expected, long actual)25 public static void assertLongEquals(long expected, long actual) { 26 if (expected != actual) { 27 throw new Error("Expected: " + expected + ", found: " + actual); 28 } 29 } 30 31 // (i >>> #distance) | (i << #(reg_bits - distance)) 32 33 /// CHECK-START: int Main.ror_int_constant_c_c(int) instruction_simplifier (before) 34 /// CHECK: <<ArgValue:i\d+>> ParameterValue 35 /// CHECK: <<Const2:i\d+>> IntConstant 2 36 /// CHECK: <<Const30:i\d+>> IntConstant 30 37 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<Const2>>] 38 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<Const30>>] 39 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 40 /// CHECK: Return [<<Or>>] 41 42 /// CHECK-START: int Main.ror_int_constant_c_c(int) instruction_simplifier (after) 43 /// CHECK: <<ArgValue:i\d+>> ParameterValue 44 /// CHECK: <<Const2:i\d+>> IntConstant 2 45 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<Const2>>] 46 /// CHECK: Return [<<Ror>>] 47 48 /// CHECK-START: int Main.ror_int_constant_c_c(int) instruction_simplifier (after) 49 /// CHECK-NOT: UShr 50 /// CHECK-NOT: Shl ror_int_constant_c_c(int value)51 public static int ror_int_constant_c_c(int value) { 52 return (value >>> 2) | (value << 30); 53 } 54 55 /// CHECK-START: int Main.ror_int_constant_c_c_0(int) instruction_simplifier (after) 56 /// CHECK: <<ArgValue:i\d+>> ParameterValue 57 /// CHECK: <<Const2:i\d+>> IntConstant 2 58 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<Const2>>] 59 /// CHECK: Return [<<Ror>>] 60 61 /// CHECK-START: int Main.ror_int_constant_c_c_0(int) instruction_simplifier (after) 62 /// CHECK-NOT: UShr 63 /// CHECK-NOT: Shl ror_int_constant_c_c_0(int value)64 public static int ror_int_constant_c_c_0(int value) { 65 return (value >>> 2) | (value << 62); 66 } 67 68 // (j >>> #distance) | (j << #(reg_bits - distance)) 69 70 /// CHECK-START: long Main.ror_long_constant_c_c(long) instruction_simplifier (before) 71 /// CHECK: <<ArgValue:j\d+>> ParameterValue 72 /// CHECK: <<Const2:i\d+>> IntConstant 2 73 /// CHECK: <<Const62:i\d+>> IntConstant 62 74 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Const2>>] 75 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<Const62>>] 76 /// CHECK: <<Or:j\d+>> Or [<<UShr>>,<<Shl>>] 77 /// CHECK: Return [<<Or>>] 78 79 /// CHECK-START: long Main.ror_long_constant_c_c(long) instruction_simplifier (after) 80 /// CHECK: <<ArgValue:j\d+>> ParameterValue 81 /// CHECK: <<Const2:i\d+>> IntConstant 2 82 /// CHECK: <<Ror:j\d+>> Ror [<<ArgValue>>,<<Const2>>] 83 /// CHECK: Return [<<Ror>>] 84 85 /// CHECK-START: long Main.ror_long_constant_c_c(long) instruction_simplifier (after) 86 /// CHECK-NOT: UShr 87 /// CHECK-NOT: Shl ror_long_constant_c_c(long value)88 public static long ror_long_constant_c_c(long value) { 89 return (value >>> 2) | (value << 62); 90 } 91 92 /// CHECK-START: long Main.ror_long_constant_c_c_0(long) instruction_simplifier (after) 93 /// CHECK-NOT: Ror ror_long_constant_c_c_0(long value)94 public static long ror_long_constant_c_c_0(long value) { 95 return (value >>> 2) | (value << 30); 96 } 97 98 // (i >>> #distance) | (i << #-distance) 99 100 /// CHECK-START: int Main.ror_int_constant_c_negc(int) instruction_simplifier$after_inlining (before) 101 /// CHECK: <<ArgValue:i\d+>> ParameterValue 102 /// CHECK: <<Const2:i\d+>> IntConstant 2 103 /// CHECK: <<ConstNeg2:i\d+>> IntConstant -2 104 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<Const2>>] 105 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<ConstNeg2>>] 106 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 107 /// CHECK: Return [<<Or>>] 108 109 /// CHECK-START: int Main.ror_int_constant_c_negc(int) instruction_simplifier$after_inlining (after) 110 /// CHECK: <<ArgValue:i\d+>> ParameterValue 111 /// CHECK: <<Const2:i\d+>> IntConstant 2 112 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<Const2>>] 113 /// CHECK: Return [<<Ror>>] 114 115 /// CHECK-START: int Main.ror_int_constant_c_negc(int) instruction_simplifier$after_inlining (after) 116 /// CHECK-NOT: UShr 117 /// CHECK-NOT: Shl ror_int_constant_c_negc(int value)118 public static int ror_int_constant_c_negc(int value) { 119 return (value >>> 2) | (value << $opt$inline$IntConstantM2()); 120 } 121 122 // Hiding constants outside the range [0, 32) used for int shifts from Jack. 123 // (Jack extracts only the low 5 bits.) $opt$inline$IntConstantM2()124 public static int $opt$inline$IntConstantM2() { return -2; } 125 126 // (j >>> #distance) | (j << #-distance) 127 128 /// CHECK-START: long Main.ror_long_constant_c_negc(long) instruction_simplifier (before) 129 /// CHECK: <<ArgValue:j\d+>> ParameterValue 130 /// CHECK: <<Const2:i\d+>> IntConstant 2 131 /// CHECK: <<ConstNeg2:i\d+>> IntConstant -2 132 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Const2>>] 133 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ConstNeg2>>] 134 /// CHECK: <<Or:j\d+>> Or [<<UShr>>,<<Shl>>] 135 /// CHECK: Return [<<Or>>] 136 137 /// CHECK-START: long Main.ror_long_constant_c_negc(long) instruction_simplifier (after) 138 /// CHECK: <<ArgValue:j\d+>> ParameterValue 139 /// CHECK: <<Const2:i\d+>> IntConstant 2 140 /// CHECK: <<Ror:j\d+>> Ror [<<ArgValue>>,<<Const2>>] 141 /// CHECK: Return [<<Ror>>] 142 143 /// CHECK-START: long Main.ror_long_constant_c_negc(long) instruction_simplifier (after) 144 /// CHECK-NOT: UShr 145 /// CHECK-NOT: Shl ror_long_constant_c_negc(long value)146 public static long ror_long_constant_c_negc(long value) { 147 return (value >>> 2) | (value << -2); 148 } 149 150 // (i >>> distance) | (i << (#reg_bits - distance) 151 152 /// CHECK-START: int Main.ror_int_reg_v_csubv(int, int) instruction_simplifier (before) 153 /// CHECK: <<ArgValue:i\d+>> ParameterValue 154 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 155 /// CHECK: <<Const32:i\d+>> IntConstant 32 156 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<ArgDistance>>] 157 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const32>>,<<ArgDistance>>] 158 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<Sub>>] 159 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 160 /// CHECK: Return [<<Or>>] 161 162 /// CHECK-START: int Main.ror_int_reg_v_csubv(int, int) instruction_simplifier (after) 163 /// CHECK: <<ArgValue:i\d+>> ParameterValue 164 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 165 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<ArgDistance>>] 166 /// CHECK: Return [<<Ror>>] 167 168 /// CHECK-START: int Main.ror_int_reg_v_csubv(int, int) instruction_simplifier (after) 169 /// CHECK-NOT: UShr 170 /// CHECK-NOT: Shl 171 /// CHECK-NOT: Sub ror_int_reg_v_csubv(int value, int distance)172 public static int ror_int_reg_v_csubv(int value, int distance) { 173 return (value >>> distance) | (value << (32 - distance)); 174 } 175 176 // (distance = x - y) 177 // (i >>> distance) | (i << (#reg_bits - distance) 178 179 /// CHECK-START: int Main.ror_int_subv_csubv(int, int, int) instruction_simplifier (before) 180 /// CHECK: <<ArgValue:i\d+>> ParameterValue 181 /// CHECK: <<ArgX:i\d+>> ParameterValue 182 /// CHECK: <<ArgY:i\d+>> ParameterValue 183 /// CHECK: <<Const32:i\d+>> IntConstant 32 184 /// CHECK-DAG: <<SubDistance:i\d+>> Sub [<<ArgX>>,<<ArgY>>] 185 /// CHECK-DAG: <<Sub32:i\d+>> Sub [<<Const32>>,<<SubDistance>>] 186 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<Sub32>>] 187 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<SubDistance>>] 188 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 189 /// CHECK: Return [<<Or>>] 190 191 /// CHECK-START: int Main.ror_int_subv_csubv(int, int, int) instruction_simplifier (after) 192 /// CHECK: <<ArgValue:i\d+>> ParameterValue 193 /// CHECK: <<ArgX:i\d+>> ParameterValue 194 /// CHECK: <<ArgY:i\d+>> ParameterValue 195 /// CHECK: <<SubDistance:i\d+>> Sub [<<ArgX>>,<<ArgY>>] 196 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<SubDistance>>] 197 /// CHECK: Return [<<Ror>>] 198 199 /// CHECK-START: int Main.ror_int_subv_csubv(int, int, int) instruction_simplifier (after) 200 /// CHECK: Sub 201 /// CHECK-NOT: Sub 202 203 /// CHECK-START: int Main.ror_int_subv_csubv(int, int, int) instruction_simplifier (after) 204 /// CHECK-NOT: UShr 205 /// CHECK-NOT: Shl ror_int_subv_csubv(int value, int x, int y)206 public static int ror_int_subv_csubv(int value, int x, int y) { 207 int distance = x - y; 208 return (value >>> distance) | (value << (32 - distance)); 209 } 210 211 /// CHECK-START: int Main.ror_int_subv_csubv_env(int, int, int) instruction_simplifier (before) 212 /// CHECK: <<ArgValue:i\d+>> ParameterValue 213 /// CHECK: <<ArgX:i\d+>> ParameterValue 214 /// CHECK: <<ArgY:i\d+>> ParameterValue 215 /// CHECK: <<Const32:i\d+>> IntConstant 32 216 /// CHECK-DAG: <<SubDistance:i\d+>> Sub [<<ArgX>>,<<ArgY>>] 217 /// CHECK-DAG: <<Sub32:i\d+>> Sub [<<Const32>>,<<SubDistance>>] 218 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<SubDistance>>] 219 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<Sub32>>] 220 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 221 /// CHECK: <<Add:i\d+>> Add [<<Or>>,<<Sub32>>] 222 /// CHECK: Return [<<Add>>] 223 224 /// CHECK-START: int Main.ror_int_subv_csubv_env(int, int, int) instruction_simplifier (after) 225 /// CHECK: <<ArgValue:i\d+>> ParameterValue 226 /// CHECK: <<ArgX:i\d+>> ParameterValue 227 /// CHECK: <<ArgY:i\d+>> ParameterValue 228 /// CHECK: <<Const32:i\d+>> IntConstant 32 229 /// CHECK-DAG: <<SubDistance:i\d+>> Sub [<<ArgX>>,<<ArgY>>] 230 /// CHECK-DAG: <<Sub32:i\d+>> Sub [<<Const32>>,<<SubDistance>>] 231 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<SubDistance>>] 232 /// CHECK: <<Add:i\d+>> Add [<<Ror>>,<<Sub32>>] 233 /// CHECK: Return [<<Add>>] 234 235 /// CHECK-START: int Main.ror_int_subv_csubv_env(int, int, int) instruction_simplifier (after) 236 /// CHECK-NOT: UShr 237 /// CHECK-NOT: Shl ror_int_subv_csubv_env(int value, int x, int y)238 public static int ror_int_subv_csubv_env(int value, int x, int y) { 239 int distance = x - y; 240 int bits_minus_dist = 32 - distance; 241 return ((value >>> distance) | (value << bits_minus_dist)) + bits_minus_dist; 242 } 243 244 // (j >>> distance) | (j << (#reg_bits - distance) 245 246 /// CHECK-START: long Main.ror_long_reg_v_csubv(long, int) instruction_simplifier (before) 247 /// CHECK: <<ArgValue:j\d+>> ParameterValue 248 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 249 /// CHECK: <<Const64:i\d+>> IntConstant 64 250 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<ArgDistance>>] 251 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const64>>,<<ArgDistance>>] 252 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<Sub>>] 253 /// CHECK: <<Or:j\d+>> Or [<<UShr>>,<<Shl>>] 254 /// CHECK: Return [<<Or>>] 255 256 /// CHECK-START: long Main.ror_long_reg_v_csubv(long, int) instruction_simplifier (after) 257 /// CHECK: <<ArgValue:j\d+>> ParameterValue 258 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 259 /// CHECK: <<Ror:j\d+>> Ror [<<ArgValue>>,<<ArgDistance>>] 260 /// CHECK: Return [<<Ror>>] 261 262 /// CHECK-START: long Main.ror_long_reg_v_csubv(long, int) instruction_simplifier (after) 263 /// CHECK-NOT: UShr 264 /// CHECK-NOT: Shl 265 /// CHECK-NOT: Sub ror_long_reg_v_csubv(long value, int distance)266 public static long ror_long_reg_v_csubv(long value, int distance) { 267 return (value >>> distance) | (value << (64 - distance)); 268 } 269 270 /// CHECK-START: long Main.ror_long_reg_v_csubv_0(long, int) instruction_simplifier (after) 271 /// CHECK-NOT: Ror ror_long_reg_v_csubv_0(long value, int distance)272 public static long ror_long_reg_v_csubv_0(long value, int distance) { 273 return (value >>> distance) | (value << (32 - distance)); 274 } 275 276 /// CHECK-START: long Main.ror_long_subv_csubv_0(long, int, int) instruction_simplifier (after) 277 /// CHECK-NOT: Ror ror_long_subv_csubv_0(long value, int x, int y)278 public static long ror_long_subv_csubv_0(long value, int x, int y) { 279 int distance = x - y; 280 return (value >>> distance) | (value << (32 - distance)); 281 } 282 283 // (i >>> (#reg_bits - distance)) | (i << distance) 284 285 /// CHECK-START: int Main.rol_int_reg_csubv_v(int, int) instruction_simplifier (before) 286 /// CHECK: <<ArgValue:i\d+>> ParameterValue 287 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 288 /// CHECK: <<Const32:i\d+>> IntConstant 32 289 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const32>>,<<ArgDistance>>] 290 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<Sub>>] 291 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 292 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 293 /// CHECK: Return [<<Or>>] 294 295 /// CHECK-START: int Main.rol_int_reg_csubv_v(int, int) instruction_simplifier (after) 296 /// CHECK: <<ArgValue:i\d+>> ParameterValue 297 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 298 /// CHECK: <<Const32:i\d+>> IntConstant 32 299 /// CHECK: <<Sub:i\d+>> Sub [<<Const32>>,<<ArgDistance>>] 300 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<Sub>>] 301 /// CHECK: Return [<<Ror>>] 302 303 /// CHECK-START: int Main.rol_int_reg_csubv_v(int, int) instruction_simplifier (after) 304 /// CHECK-NOT: UShr 305 /// CHECK-NOT: Shl rol_int_reg_csubv_v(int value, int distance)306 public static int rol_int_reg_csubv_v(int value, int distance) { 307 return (value >>> (32 - distance)) | (value << distance); 308 } 309 310 // (distance = x - y) 311 // (i >>> (#reg_bits - distance)) | (i << distance) 312 313 /// CHECK-START: int Main.rol_int_csubv_subv(int, int, int) instruction_simplifier (before) 314 /// CHECK: <<ArgValue:i\d+>> ParameterValue 315 /// CHECK: <<ArgX:i\d+>> ParameterValue 316 /// CHECK: <<ArgY:i\d+>> ParameterValue 317 /// CHECK: <<Const32:i\d+>> IntConstant 32 318 /// CHECK-DAG: <<SubDistance:i\d+>> Sub [<<ArgX>>,<<ArgY>>] 319 /// CHECK-DAG: <<Sub32:i\d+>> Sub [<<Const32>>,<<SubDistance>>] 320 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<SubDistance>>] 321 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<Sub32>>] 322 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 323 /// CHECK: Return [<<Or>>] 324 325 /// CHECK-START: int Main.rol_int_csubv_subv(int, int, int) instruction_simplifier (after) 326 /// CHECK: <<ArgValue:i\d+>> ParameterValue 327 /// CHECK: <<ArgX:i\d+>> ParameterValue 328 /// CHECK: <<ArgY:i\d+>> ParameterValue 329 /// CHECK: <<Const32:i\d+>> IntConstant 32 330 /// CHECK: <<SubDistance:i\d+>> Sub [<<ArgX>>,<<ArgY>>] 331 /// CHECK: <<Sub:i\d+>> Sub [<<Const32>>,<<SubDistance>>] 332 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<Sub>>] 333 /// CHECK: Return [<<Ror>>] 334 335 /// CHECK-START: int Main.rol_int_csubv_subv(int, int, int) instruction_simplifier (after) 336 /// CHECK: Sub 337 /// CHECK: Sub 338 339 /// CHECK-START: int Main.rol_int_csubv_subv(int, int, int) instruction_simplifier (after) 340 /// CHECK-NOT: UShr 341 /// CHECK-NOT: Shl rol_int_csubv_subv(int value, int x, int y)342 public static int rol_int_csubv_subv(int value, int x, int y) { 343 int distance = x - y; 344 return (value >>> (32 - distance)) | (value << distance); 345 } 346 347 // (j >>> (#reg_bits - distance)) | (j << distance) 348 349 /// CHECK-START: long Main.rol_long_reg_csubv_v(long, int) instruction_simplifier (before) 350 /// CHECK: <<ArgValue:j\d+>> ParameterValue 351 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 352 /// CHECK: <<Const64:i\d+>> IntConstant 64 353 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const64>>,<<ArgDistance>>] 354 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Sub>>] 355 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 356 /// CHECK: <<Or:j\d+>> Or [<<UShr>>,<<Shl>>] 357 /// CHECK: Return [<<Or>>] 358 359 /// CHECK-START: long Main.rol_long_reg_csubv_v(long, int) instruction_simplifier (after) 360 /// CHECK: <<ArgValue:j\d+>> ParameterValue 361 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 362 /// CHECK: <<Const64:i\d+>> IntConstant 64 363 /// CHECK: <<Sub:i\d+>> Sub [<<Const64>>,<<ArgDistance>>] 364 /// CHECK: <<Ror:j\d+>> Ror [<<ArgValue>>,<<Sub>>] 365 /// CHECK: Return [<<Ror>>] 366 367 /// CHECK-START: long Main.rol_long_reg_csubv_v(long, int) instruction_simplifier (after) 368 /// CHECK-NOT: UShr 369 /// CHECK-NOT: Shl rol_long_reg_csubv_v(long value, int distance)370 public static long rol_long_reg_csubv_v(long value, int distance) { 371 return (value >>> (64 - distance)) | (value << distance); 372 } 373 374 /// CHECK-START: long Main.rol_long_reg_csubv_v_0(long, int) instruction_simplifier (after) 375 /// CHECK-NOT: Ror rol_long_reg_csubv_v_0(long value, int distance)376 public static long rol_long_reg_csubv_v_0(long value, int distance) { 377 return (value >>> (32 - distance)) | (value << distance); 378 } 379 380 // (i >>> distance) | (i << -distance) (i.e. libcore's Integer.rotateRight) 381 382 /// CHECK-START: int Main.ror_int_reg_v_negv(int, int) instruction_simplifier (before) 383 /// CHECK: <<ArgValue:i\d+>> ParameterValue 384 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 385 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<ArgDistance>>] 386 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 387 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<Neg>>] 388 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 389 /// CHECK: Return [<<Or>>] 390 391 /// CHECK-START: int Main.ror_int_reg_v_negv(int, int) instruction_simplifier (after) 392 /// CHECK: <<ArgValue:i\d+>> ParameterValue 393 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 394 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<ArgDistance>>] 395 /// CHECK: Return [<<Ror>>] 396 397 /// CHECK-START: int Main.ror_int_reg_v_negv(int, int) instruction_simplifier (after) 398 /// CHECK-NOT: UShr 399 /// CHECK-NOT: Shl 400 /// CHECK-NOT: Neg ror_int_reg_v_negv(int value, int distance)401 public static int ror_int_reg_v_negv(int value, int distance) { 402 return (value >>> distance) | (value << -distance); 403 } 404 405 /// CHECK-START: int Main.ror_int_reg_v_negv_env(int, int) instruction_simplifier (before) 406 /// CHECK: <<ArgValue:i\d+>> ParameterValue 407 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 408 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 409 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<ArgDistance>>] 410 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<Neg>>] 411 /// CHECK: <<Or:i\d+>> Or [<<UShr>>,<<Shl>>] 412 /// CHECK: <<Add:i\d+>> Add [<<Or>>,<<Neg>>] 413 /// CHECK: Return [<<Add>>] 414 415 /// CHECK-START: int Main.ror_int_reg_v_negv_env(int, int) instruction_simplifier (after) 416 /// CHECK: <<ArgValue:i\d+>> ParameterValue 417 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 418 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<ArgDistance>>] 419 /// CHECK: <<Sub:i\d+>> Sub [<<Ror>>,<<ArgDistance>>] 420 /// CHECK: Return [<<Sub>>] 421 422 /// CHECK-START: int Main.ror_int_reg_v_negv_env(int, int) instruction_simplifier (after) 423 /// CHECK-NOT: UShr 424 /// CHECK-NOT: Shl ror_int_reg_v_negv_env(int value, int distance)425 public static int ror_int_reg_v_negv_env(int value, int distance) { 426 int neg_distance = -distance; 427 return ((value >>> distance) | (value << neg_distance)) + neg_distance; 428 } 429 430 // (j >>> distance) | (j << -distance) (i.e. libcore's Long.rotateRight) 431 432 /// CHECK-START: long Main.ror_long_reg_v_negv(long, int) instruction_simplifier (before) 433 /// CHECK: <<ArgValue:j\d+>> ParameterValue 434 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 435 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<ArgDistance>>] 436 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 437 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<Neg>>] 438 /// CHECK: <<Or:j\d+>> Or [<<UShr>>,<<Shl>>] 439 /// CHECK: Return [<<Or>>] 440 441 /// CHECK-START: long Main.ror_long_reg_v_negv(long, int) instruction_simplifier (after) 442 /// CHECK: <<ArgValue:j\d+>> ParameterValue 443 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 444 /// CHECK: <<Ror:j\d+>> Ror [<<ArgValue>>,<<ArgDistance>>] 445 /// CHECK: Return [<<Ror>>] 446 447 /// CHECK-START: long Main.ror_long_reg_v_negv(long, int) instruction_simplifier (after) 448 /// CHECK-NOT: UShr 449 /// CHECK-NOT: Shl 450 /// CHECK-NOT: Neg ror_long_reg_v_negv(long value, int distance)451 public static long ror_long_reg_v_negv(long value, int distance) { 452 return (value >>> distance) | (value << -distance); 453 } 454 455 // (i << distance) | (i >>> -distance) (i.e. libcore's Integer.rotateLeft) 456 457 /// CHECK-START: int Main.rol_int_reg_negv_v(int, int) instruction_simplifier (before) 458 /// CHECK: <<ArgValue:i\d+>> ParameterValue 459 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 460 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 461 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<ArgValue>>,<<Neg>>] 462 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 463 /// CHECK: <<Or:i\d+>> Or [<<Shl>>,<<UShr>>] 464 /// CHECK: Return [<<Or>>] 465 466 /// CHECK-START: int Main.rol_int_reg_negv_v(int, int) instruction_simplifier (after) 467 /// CHECK: <<ArgValue:i\d+>> ParameterValue 468 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 469 /// CHECK: <<Neg:i\d+>> Neg [<<ArgDistance>>] 470 /// CHECK: <<Ror:i\d+>> Ror [<<ArgValue>>,<<Neg>>] 471 /// CHECK: Return [<<Ror>>] 472 473 /// CHECK-START: int Main.rol_int_reg_negv_v(int, int) instruction_simplifier (after) 474 /// CHECK-NOT: UShr 475 /// CHECK-NOT: Shl rol_int_reg_negv_v(int value, int distance)476 public static int rol_int_reg_negv_v(int value, int distance) { 477 return (value << distance) | (value >>> -distance); 478 } 479 480 // (j << distance) | (j >>> -distance) (i.e. libcore's Long.rotateLeft) 481 482 /// CHECK-START: long Main.rol_long_reg_negv_v(long, int) instruction_simplifier (before) 483 /// CHECK: <<ArgValue:j\d+>> ParameterValue 484 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 485 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 486 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Neg>>] 487 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 488 /// CHECK: <<Or:j\d+>> Or [<<Shl>>,<<UShr>>] 489 /// CHECK: Return [<<Or>>] 490 491 /// CHECK-START: long Main.rol_long_reg_negv_v(long, int) instruction_simplifier (after) 492 /// CHECK: <<ArgValue:j\d+>> ParameterValue 493 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 494 /// CHECK: <<Neg:i\d+>> Neg [<<ArgDistance>>] 495 /// CHECK: <<Ror:j\d+>> Ror [<<ArgValue>>,<<Neg>>] 496 /// CHECK: Return [<<Ror>>] 497 498 /// CHECK-START: long Main.rol_long_reg_negv_v(long, int) instruction_simplifier (after) 499 /// CHECK-NOT: UShr 500 /// CHECK-NOT: Shl rol_long_reg_negv_v(long value, int distance)501 public static long rol_long_reg_negv_v(long value, int distance) { 502 return (value << distance) | (value >>> -distance); 503 } 504 505 // (j << distance) + (j >>> -distance) 506 // We can't perform the optimization as distance might be `0`, resulting in the wrong value. 507 508 /// CHECK-START: long Main.rol_long_reg_v_negv_add(long, int) instruction_simplifier (before) 509 /// CHECK: <<ArgValue:j\d+>> ParameterValue 510 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 511 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 512 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Neg>>] 513 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 514 /// CHECK: <<Add:j\d+>> Add [<<Shl>>,<<UShr>>] 515 /// CHECK: Return [<<Add>>] 516 517 /// CHECK-START: long Main.rol_long_reg_v_negv_add(long, int) instruction_simplifier (after) 518 /// CHECK: <<ArgValue:j\d+>> ParameterValue 519 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 520 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 521 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Neg>>] 522 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 523 /// CHECK: <<Add:j\d+>> Add [<<Shl>>,<<UShr>>] 524 /// CHECK: Return [<<Add>>] rol_long_reg_v_negv_add(long value, int distance)525 public static long rol_long_reg_v_negv_add(long value, int distance) { 526 return (value << distance) + (value >>> -distance); 527 } 528 529 // (j << distance) ^ (j >>> -distance) 530 // We can't perform the optimization as distance might be `0`, resulting in the wrong value. 531 532 /// CHECK-START: long Main.rol_long_reg_v_negv_xor(long, int) instruction_simplifier (before) 533 /// CHECK: <<ArgValue:j\d+>> ParameterValue 534 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 535 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 536 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Neg>>] 537 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 538 /// CHECK: <<Xor:j\d+>> Xor [<<Shl>>,<<UShr>>] 539 /// CHECK: Return [<<Xor>>] 540 541 /// CHECK-START: long Main.rol_long_reg_v_negv_xor(long, int) instruction_simplifier (after) 542 /// CHECK: <<ArgValue:j\d+>> ParameterValue 543 /// CHECK: <<ArgDistance:i\d+>> ParameterValue 544 /// CHECK-DAG: <<Neg:i\d+>> Neg [<<ArgDistance>>] 545 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<ArgValue>>,<<Neg>>] 546 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<ArgValue>>,<<ArgDistance>>] 547 /// CHECK: <<Xor:j\d+>> Xor [<<Shl>>,<<UShr>>] 548 /// CHECK: Return [<<Xor>>] 549 rol_long_reg_v_negv_xor(long value, int distance)550 public static long rol_long_reg_v_negv_xor(long value, int distance) { 551 return (value << distance) ^ (value >>> -distance); 552 } 553 554 /// CHECK-START: void Main.$noinline$testDontOptimizeAddIntoRotate_Int() disassembly (after) 555 /// CHECK-NOT: Ror $noinline$testDontOptimizeAddIntoRotate_Int()556 public static void $noinline$testDontOptimizeAddIntoRotate_Int() { 557 int distance = returnFalse() ? 1 : 0; 558 int value = -512667375; 559 int expected_result = 2 * value; 560 int result = (value >>> distance) + (value << -distance); 561 assertIntEquals(expected_result, result); 562 } 563 564 /// CHECK-START: void Main.$noinline$testDontOptimizeAddIntoRotate_Long() disassembly (after) 565 /// CHECK-NOT: Ror $noinline$testDontOptimizeAddIntoRotate_Long()566 public static void $noinline$testDontOptimizeAddIntoRotate_Long() { 567 int distance = returnFalse() ? 1 : 0; 568 long value = -512667375L; 569 long expected_result = 2L * value; 570 long result = (value >>> distance) + (value << -distance); 571 assertLongEquals(expected_result, result); 572 } 573 574 /// CHECK-START: void Main.$noinline$testDontOptimizeXorIntoRotate_Int() disassembly (after) 575 /// CHECK-NOT: Ror $noinline$testDontOptimizeXorIntoRotate_Int()576 public static void $noinline$testDontOptimizeXorIntoRotate_Int() { 577 int distance = returnFalse() ? 1 : 0; 578 int value = -512667375; 579 int expected_result = 0; 580 int result = (value >>> distance) ^ (value << -distance); 581 assertIntEquals(expected_result, result); 582 } 583 584 /// CHECK-START: void Main.$noinline$testDontOptimizeXorIntoRotate_Long() disassembly (after) 585 /// CHECK-NOT: Ror $noinline$testDontOptimizeXorIntoRotate_Long()586 public static void $noinline$testDontOptimizeXorIntoRotate_Long() { 587 int distance = returnFalse() ? 1 : 0; 588 long value = -512667375L; 589 long expected_result = 0; 590 long result = (value >>> distance) ^ (value << -distance); 591 assertLongEquals(expected_result, result); 592 } 593 returnFalse()594 static boolean returnFalse() { 595 return false; 596 } 597 main(String[] args)598 public static void main(String[] args) { 599 assertIntEquals(2, ror_int_constant_c_c(8)); 600 assertIntEquals(2, ror_int_constant_c_c_0(8)); 601 assertLongEquals(2L, ror_long_constant_c_c(8L)); 602 603 assertIntEquals(2, ror_int_constant_c_negc(8)); 604 assertLongEquals(2L, ror_long_constant_c_negc(8L)); 605 606 assertIntEquals(2, ror_int_reg_v_csubv(8, 2)); 607 assertLongEquals(2L, ror_long_reg_v_csubv(8L, 2)); 608 609 assertIntEquals(2, ror_int_subv_csubv(8, 2, 0)); 610 assertIntEquals(32, ror_int_subv_csubv_env(8, 2, 0)); 611 assertIntEquals(32, rol_int_csubv_subv(8, 2, 0)); 612 613 assertIntEquals(32, rol_int_reg_csubv_v(8, 2)); 614 assertLongEquals(32L, rol_long_reg_csubv_v(8L, 2)); 615 616 assertIntEquals(2, ror_int_reg_v_negv(8, 2)); 617 assertIntEquals(0, ror_int_reg_v_negv_env(8, 2)); 618 assertLongEquals(2L, ror_long_reg_v_negv(8L, 2)); 619 620 assertIntEquals(32, rol_int_reg_negv_v(8, 2)); 621 assertLongEquals(32L, rol_long_reg_negv_v(8L, 2)); 622 623 assertLongEquals(32L, rol_long_reg_v_negv_add(8L, 2)); 624 assertLongEquals(32L, rol_long_reg_v_negv_xor(8L, 2)); 625 626 $noinline$testDontOptimizeAddIntoRotate_Int(); 627 $noinline$testDontOptimizeAddIntoRotate_Long(); 628 629 $noinline$testDontOptimizeXorIntoRotate_Int(); 630 $noinline$testDontOptimizeXorIntoRotate_Long(); 631 } 632 } 633