001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt; 014 015 import static org.jikesrvm.compilers.opt.ir.Operators.*; 016 017 import java.util.Enumeration; 018 import java.util.HashSet; 019 import java.util.Iterator; 020 021 import org.jikesrvm.VM; 022 import org.jikesrvm.classloader.TypeReference; 023 import org.jikesrvm.compilers.opt.ir.Binary; 024 import org.jikesrvm.compilers.opt.ir.BooleanCmp; 025 import org.jikesrvm.compilers.opt.ir.BoundsCheck; 026 import org.jikesrvm.compilers.opt.ir.CondMove; 027 import org.jikesrvm.compilers.opt.ir.GuardedBinary; 028 import org.jikesrvm.compilers.opt.ir.GuardedUnary; 029 import org.jikesrvm.compilers.opt.ir.IR; 030 import org.jikesrvm.compilers.opt.ir.IRTools; 031 import org.jikesrvm.compilers.opt.ir.IfCmp; 032 import org.jikesrvm.compilers.opt.ir.IfCmp2; 033 import org.jikesrvm.compilers.opt.ir.InstanceOf; 034 import org.jikesrvm.compilers.opt.ir.Instruction; 035 import org.jikesrvm.compilers.opt.ir.Move; 036 import org.jikesrvm.compilers.opt.ir.New; 037 import org.jikesrvm.compilers.opt.ir.NewArray; 038 import org.jikesrvm.compilers.opt.ir.NullCheck; 039 import org.jikesrvm.compilers.opt.ir.Register; 040 import org.jikesrvm.compilers.opt.ir.Unary; 041 import org.jikesrvm.compilers.opt.ir.ZeroCheck; 042 import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand; 043 import org.jikesrvm.compilers.opt.ir.operand.BranchOperand; 044 import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand; 045 import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand; 046 import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; 047 import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; 048 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 049 import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand; 050 import org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand; 051 import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand; 052 import org.jikesrvm.compilers.opt.ir.operand.Operand; 053 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 054 import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand; 055 import org.jikesrvm.runtime.Magic; 056 import org.jikesrvm.runtime.RuntimeEntrypoints; 057 import org.vmmagic.unboxed.Address; 058 import org.vmmagic.unboxed.Word; 059 060 /** 061 * This class simplifies expressions globally, if in SSA form, or locally within 062 * a basic block if not. 063 */ 064 public class ExpressionFolding extends IRTools { 065 /** 066 * Only fold operations when the result of the 1st operation becomes dead 067 * after folding 068 * TODO: doesn't apply to local folding 069 */ 070 private static final boolean RESTRICT_TO_DEAD_EXPRESSIONS = false; 071 072 /** 073 * Fold across uninterruptible regions 074 */ 075 private static final boolean FOLD_OVER_UNINTERRUPTIBLE = false; 076 /** 077 * Fold operations on ints 078 */ 079 private static final boolean FOLD_INTS = true; 080 /** 081 * Fold operations on word like things 082 */ 083 private static final boolean FOLD_REFS = true; 084 /** 085 * Fold operations on longs 086 */ 087 private static final boolean FOLD_LONGS = true; 088 /** 089 * Fold operations on floats 090 */ 091 private static final boolean FOLD_FLOATS = true; 092 /** 093 * Fold operations on doubles 094 */ 095 private static final boolean FOLD_DOUBLES = true; 096 097 /** 098 * Fold binary SUB operations 099 */ 100 private static final boolean FOLD_SUBS = true; 101 102 /** 103 * Fold binary ADD operations 104 */ 105 private static final boolean FOLD_ADDS = true; 106 107 /** 108 * Fold binary multiply operations 109 */ 110 private static final boolean FOLD_MULTS = true; 111 112 /** 113 * Fold binary divide operations 114 */ 115 private static final boolean FOLD_DIVS = true; 116 117 /** 118 * Fold binary shift left operations 119 */ 120 private static final boolean FOLD_SHIFTLS = true; 121 122 /** 123 * Fold binary shift right operations 124 */ 125 private static final boolean FOLD_SHIFTRS = true; 126 127 /** 128 * Fold binary CMP operations 129 */ 130 private static final boolean FOLD_CMPS = true; 131 132 /** 133 * Fold binary XOR operations 134 */ 135 private static final boolean FOLD_XORS = true; 136 137 /** 138 * Fold binary OR operations 139 */ 140 private static final boolean FOLD_ORS = true; 141 142 /** 143 * Fold binary AND operations 144 */ 145 private static final boolean FOLD_ANDS = true; 146 147 /** 148 * Fold unary NEG operations 149 */ 150 private static final boolean FOLD_NEGS = true; 151 152 /** 153 * Fold unary NOT operations 154 */ 155 private static final boolean FOLD_NOTS = true; 156 157 /** 158 * Fold operations that create a constant on the LHS? This may produce less 159 * optimal code on 2 address architectures where the constant would need 160 * loading into a register prior to the operation. 161 */ 162 private static final boolean FOLD_CONSTANTS_TO_LHS = true; 163 164 /** 165 * Fold IFCMP operations 166 */ 167 private static final boolean FOLD_IFCMPS = true; 168 169 /** 170 * Fold COND_MOVE operations 171 */ 172 private static final boolean FOLD_CONDMOVES = true; 173 174 /** 175 * Fold xxx_2xxx where the precision is increased then decreased achieving a 176 * nop effect 177 */ 178 private static final boolean FOLD_2CONVERSION = true; 179 180 /** 181 * Fold ZeroCheck where we're testing whether a value is 0 or not 182 */ 183 private static final boolean FOLD_CHECKS = true; 184 185 /** 186 * Print out debug information 187 */ 188 private static final boolean VERBOSE = false; 189 190 /** 191 * Perform expression folding on individual basic blocks 192 */ 193 public static boolean performLocal(IR ir) { 194 Instruction outer = ir.cfg.entry().firstRealInstruction(); 195 if (VERBOSE) { 196 System.out.println("Start of expression folding for: " + ir.method.toString()); 197 } 198 boolean didSomething = false; 199 // Outer loop: walk over every instruction of basic block looking for candidates 200 while (outer != null) { 201 Register outerDef = isCandidateExpression(outer, false); 202 if (outerDef != null) { 203 if (VERBOSE) { 204 System.out.println("Found outer candidate of: " + outer.toString()); 205 } 206 Instruction inner = outer.nextInstructionInCodeOrder(); 207 // Inner loop: walk over instructions in block, after outer instruction, 208 // checking whether inner and outer could be folded together. 209 // if not check for a dependency that means there are potential hazards 210 // to stop the search 211 loop_over_inner_instructions: 212 while ((inner != null) && (inner.operator() != BBEND) && !inner.isGCPoint()) { 213 if (!FOLD_OVER_UNINTERRUPTIBLE && 214 ((inner.operator() == UNINT_BEGIN) || (inner.operator() == UNINT_END))) { 215 break loop_over_inner_instructions; 216 } 217 Register innerDef = isCandidateExpression(inner, false); 218 // 1. check for true dependence (does inner use outer's def?) 219 if (innerDef != null) { 220 if (VERBOSE) { 221 System.out.println("Found inner candidate of: " + inner.toString()); 222 } 223 RegisterOperand use = getUseFromCandidate(inner); 224 if ((use != null) && (use.getRegister() == outerDef)) { 225 // Optimization case 226 Instruction newInner; 227 try { 228 if (VERBOSE) { 229 System.out.println("Trying to fold:" + outer.toString()); 230 System.out.println(" with:" + inner.toString()); 231 } 232 newInner = transform(inner, outer); 233 } catch (OptimizingCompilerException e) { 234 OptimizingCompilerException newE = new OptimizingCompilerException("Error transforming " + outer + " ; " + inner); 235 newE.initCause(e); 236 throw newE; 237 } 238 if (newInner != null) { 239 if (VERBOSE) { 240 System.out.println("Replacing:" + inner.toString()); 241 System.out.println(" with:" + newInner.toString()); 242 } 243 DefUse.replaceInstructionAndUpdateDU(inner, CPOS(inner,newInner)); 244 inner = newInner; 245 didSomething = true; 246 } 247 } 248 } 249 // 2. check for output dependence (does inner kill outer's def?) 250 if (innerDef == outerDef) { 251 if (VERBOSE) { 252 System.out.println("Stopping search as innerDef == outerDef " + innerDef.toString()); 253 } 254 break loop_over_inner_instructions; 255 } 256 if (innerDef == null) { 257 Enumeration<Operand> defs = inner.getDefs(); 258 while(defs.hasMoreElements()) { 259 Operand def = defs.nextElement(); 260 if (def.isRegister()) { 261 Register defReg = def.asRegister().getRegister(); 262 if (defReg == outerDef) { 263 if (VERBOSE) { 264 System.out.println("Stopping search as innerDef == outerDef " + defReg.toString()); 265 } 266 break loop_over_inner_instructions; 267 } 268 } 269 } 270 } 271 // 3. check for anti dependence (do we define something that outer uses?) 272 if (innerDef != null) { 273 Enumeration<Operand> uses = outer.getUses(); 274 while(uses.hasMoreElements()) { 275 Operand use = uses.nextElement(); 276 if (use.isRegister() && (use.asRegister().getRegister() == innerDef)) { 277 if (VERBOSE) { 278 System.out.println("Stopping search as anti-dependence " + use.toString()); 279 } 280 break loop_over_inner_instructions; 281 } 282 } 283 } else { 284 Enumeration<Operand> defs = inner.getDefs(); 285 while(defs.hasMoreElements()) { 286 Operand def = defs.nextElement(); 287 if (def.isRegister()) { 288 Enumeration<Operand> uses = outer.getUses(); 289 while(uses.hasMoreElements()) { 290 Operand use = uses.nextElement(); 291 if (use.similar(def)) { 292 if (VERBOSE) { 293 System.out.println("Stopping search as anti-dependence " + use.toString()); 294 } 295 break loop_over_inner_instructions; 296 } 297 } 298 } 299 } 300 } 301 inner = inner.nextInstructionInCodeOrder(); 302 } // loop over inner instructions 303 } 304 outer = outer.nextInstructionInCodeOrder(); 305 } // loop over outer instructions 306 return didSomething; 307 } 308 309 /** 310 * Get the register that's used by the candidate instruction 311 * @param s the instruction 312 * @return register used by candidate or {@code null} if this isn't a candidate 313 */ 314 private static RegisterOperand getUseFromCandidate(Instruction s) { 315 if (Binary.conforms(s)) { 316 return Binary.getVal1(s).asRegister(); 317 } else if (GuardedBinary.conforms(s)) { 318 return GuardedBinary.getVal1(s).asRegister(); 319 } else if (Unary.conforms(s)) { 320 return Unary.getVal(s).asRegister(); 321 } else if (GuardedUnary.conforms(s)) { 322 return GuardedUnary.getVal(s).asRegister(); 323 } else if (BooleanCmp.conforms(s)) { 324 return BooleanCmp.getVal1(s).asRegister(); 325 } else if (IfCmp.conforms(s)) { 326 return IfCmp.getVal1(s).asRegister(); 327 } else if (IfCmp2.conforms(s)) { 328 return IfCmp2.getVal1(s).asRegister(); 329 } else if (CondMove.conforms(s)) { 330 return CondMove.getVal1(s).asRegister(); 331 } else if (ZeroCheck.conforms(s)) { 332 return ZeroCheck.getValue(s).asRegister(); 333 } else if (BoundsCheck.conforms(s)) { 334 return BoundsCheck.getRef(s).asRegister(); 335 } else if (NullCheck.conforms(s)) { 336 return NullCheck.getRef(s).asRegister(); 337 } else if (InstanceOf.conforms(s)) { 338 return InstanceOf.getRef(s).asRegister(); 339 } else if (NewArray.conforms(s) || New.conforms(s)) { 340 return null; 341 } else { 342 OptimizingCompilerException.UNREACHABLE(); 343 return null; 344 } 345 } 346 347 /** 348 * Get the register that's defined by the candidate instruction 349 * @param first is this the first instruction? 350 * @param s the instruction 351 * @return register used by candidate or {@code null} if this isn't a candidate 352 */ 353 private static RegisterOperand getDefFromCandidate(Instruction s, boolean first) { 354 if (Binary.conforms(s)) { 355 return Binary.getResult(s); 356 } else if (GuardedBinary.conforms(s)) { 357 return GuardedBinary.getResult(s); 358 } else if (Unary.conforms(s)) { 359 return Unary.getResult(s); 360 } else if (GuardedUnary.conforms(s)) { 361 return GuardedUnary.getResult(s); 362 } else if (BooleanCmp.conforms(s)) { 363 return BooleanCmp.getResult(s); 364 } else if (IfCmp.conforms(s)) { 365 if (first) { 366 return null; 367 } else { 368 return IfCmp.getGuardResult(s); 369 } 370 } else if (IfCmp2.conforms(s)) { 371 if (first) { 372 return null; 373 } else { 374 return IfCmp2.getGuardResult(s); 375 } 376 } else if (CondMove.conforms(s)) { 377 if (first) { 378 return null; 379 } else { 380 return CondMove.getResult(s); 381 } 382 } else if (ZeroCheck.conforms(s)) { 383 return ZeroCheck.getGuardResult(s); 384 } else if (BoundsCheck.conforms(s)) { 385 return BoundsCheck.getGuardResult(s); 386 } else if (NullCheck.conforms(s)) { 387 return NullCheck.getGuardResult(s); 388 } else if (InstanceOf.conforms(s)) { 389 return InstanceOf.getResult(s); 390 } else if (NewArray.conforms(s)) { 391 if (first) { 392 return NewArray.getResult(s).asRegister(); 393 } else { 394 return null; 395 } 396 } else if (New.conforms(s)) { 397 if (first) { 398 return New.getResult(s).asRegister(); 399 } else { 400 return null; 401 } 402 } else { 403 OptimizingCompilerException.UNREACHABLE(); 404 return null; 405 } 406 } 407 /** 408 * Perform the transformation. 409 * 410 * If we have, in SSA form, 411 * 412 * <pre> 413 * x = a op1 c1 414 * y = x op2 c2 415 * </pre> 416 * 417 * where c1 and c2 are constants, replace the def of y by 418 * 419 * <pre> 420 * y = a op1 (c1 op3 c2) 421 * </pre> 422 * 423 * Where op1, op2 and op3 are add, subtract, multiply, and, or, xor and 424 * compare. Repeatedly apply transformation until all expressions are folded. 425 * 426 * <p> 427 * PRECONDITIONS: SSA form, register lists computed 428 * 429 * @param ir 430 * the governing IR 431 */ 432 public static void perform(IR ir) { 433 // Create a set of potential computations to fold. 434 HashSet<Register> candidates = new HashSet<Register>(20); 435 436 for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) { 437 Instruction s = e.nextElement(); 438 // Check if s is a candidate for expression folding 439 Register r = isCandidateExpression(s, true); 440 if (r != null) { 441 candidates.add(r); 442 } 443 } 444 445 if (RESTRICT_TO_DEAD_EXPRESSIONS) { 446 pruneCandidates(candidates); 447 } 448 449 boolean didSomething = true; 450 while (didSomething) { 451 didSomething = false; 452 453 iterate_over_candidates: 454 for (Iterator<Register> it = candidates.iterator(); it.hasNext();) { 455 Register r = it.next(); 456 Instruction s = r.getFirstDef(); 457 Operand val1 = getUseFromCandidate(s); 458 if (val1 == null) continue; // operator that's not being optimized 459 if (VERBOSE) { 460 System.out.println("Found candidate instruction: " + s.toString()); 461 } 462 Instruction def = val1.asRegister().getRegister().getFirstDef(); 463 // filter out moves to get the real defining instruction 464 while (Move.conforms(def)) { 465 Operand op = Move.getVal(def); 466 if (op.isRegister()) { 467 def = op.asRegister().getRegister().getFirstDef(); 468 } else { 469 // The non-constant operand of the candidate expression is the 470 // result of moving a constant. Remove as a candidate and leave 471 // for constant propagation and simplification. 472 it.remove(); 473 continue iterate_over_candidates; 474 } 475 } 476 if (candidates.contains(val1.asRegister().getRegister())) { 477 if (VERBOSE) { 478 System.out.println(" Found candidate definition: " + def.toString()); 479 } 480 // check if the defining instruction has not mutated yet 481 if (isCandidateExpression(def, true) == null) { 482 if (VERBOSE) { 483 System.out.println(" Ignoring definition that is no longer a candidate"); 484 } 485 continue; 486 } 487 488 Instruction newS = transform(s, def); 489 if (newS != null) { 490 if (VERBOSE) { 491 System.out.println(" Replacing: " + s.toString() + "\n with:" + newS.toString()); 492 } 493 // check if this expression is still an optimisation candidate 494 if (isCandidateExpression(newS, true) == null) { 495 it.remove(); 496 } 497 DefUse.replaceInstructionAndUpdateDU(s, CPOS(s,newS)); 498 didSomething = true; 499 } 500 } 501 } 502 } 503 } 504 505 /** 506 * Prune the candidate set; restrict candidates to only allow transformations 507 * that result in dead code to be eliminated 508 */ 509 private static void pruneCandidates(HashSet<Register> candidates) { 510 for (Iterator<Register> i = candidates.iterator(); i.hasNext();) { 511 Register r = i.next(); 512 Instruction s = r.getFirstDef(); 513 Operand val1 = getUseFromCandidate(s); 514 if (val1 == null) continue; // operator that's not being optimized 515 516 if (VM.VerifyAssertions) { 517 VM._assert(val1.isRegister(), "Error with val1 of " + s); 518 } 519 520 Register v1 = val1.asRegister().getRegister(); 521 if (candidates.contains(v1)) { 522 Enumeration<RegisterOperand> uses = DefUse.uses(v1); 523 while (uses.hasMoreElements()) { 524 RegisterOperand op = uses.nextElement(); 525 Instruction u = op.instruction; 526 if ((isCandidateExpression(u, true) == null) && !Move.conforms(u)) { 527 i.remove(); 528 break; 529 } 530 } 531 } 532 } 533 } 534 535 /** 536 * Perform the transformation on the instruction 537 * 538 * @param s 539 * the instruction to transform of the form y = x op c1 540 * @param def 541 * the definition of x, the defining instruction is of the form x = a 542 * op c2 543 * @return the new instruction to replace s; 544 */ 545 private static Instruction transform(Instruction s, Instruction def) { 546 // x = a op1 c1 <-- def 547 // y = x op2 c2 <-- s 548 final RegisterOperand a = getUseFromCandidate(def); 549 final RegisterOperand x = getDefFromCandidate(def, true); 550 if (x == null) { 551 return null; 552 } 553 final RegisterOperand y = getDefFromCandidate(s, false); 554 if (y == null) { 555 return null; 556 } 557 558 if (VM.VerifyAssertions) { 559 RegisterOperand x2; 560 x2 = getUseFromCandidate(s); 561 VM._assert(x.similar(x2), "x not similar to x2 " + x + " : " + x2); 562 } 563 564 switch (s.operator.opcode) { 565 // Foldable operators 566 case INT_ADD_opcode: { 567 if (FOLD_INTS && FOLD_ADDS) { 568 int c2 = getIntValue(Binary.getVal2(s)); 569 if (def.operator == INT_ADD) { 570 int c1 = getIntValue(Binary.getVal2(def)); 571 // x = a + c1; y = x + c2 572 return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 + c2)); 573 } else if (def.operator == INT_SUB) { 574 int c1 = getIntValue(Binary.getVal2(def)); 575 // x = a - c1; y = x + c2 576 return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c2 - c1)); 577 } else if (def.operator == INT_NEG && FOLD_CONSTANTS_TO_LHS) { 578 // x = -a; y = x + c2; 579 return Binary.create(INT_SUB, y.copyRO(), IC(c2), a.copyRO()); 580 } 581 } 582 return null; 583 } 584 case REF_ADD_opcode: { 585 if (FOLD_REFS && FOLD_ADDS) { 586 Address c2 = getAddressValue(Binary.getVal2(s)); 587 if (def.operator == REF_ADD) { 588 Address c1 = getAddressValue(Binary.getVal2(def)); 589 // x = a + c1; y = x + c2 590 return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress())); 591 } else if (def.operator == REF_SUB) { 592 Address c1 = getAddressValue(Binary.getVal2(def)); 593 // x = a - c1; y = x + c2 594 return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress())); 595 } else if (def.operator == REF_NEG && FOLD_CONSTANTS_TO_LHS) { 596 // x = -a; y = x + c2; 597 return Binary.create(REF_SUB, y.copyRO(), AC(c2), a.copyRO()); 598 } 599 } 600 return null; 601 } 602 case LONG_ADD_opcode: { 603 if (FOLD_LONGS && FOLD_ADDS) { 604 long c2 = getLongValue(Binary.getVal2(s)); 605 if (def.operator == LONG_ADD) { 606 long c1 = getLongValue(Binary.getVal2(def)); 607 // x = a + c1; y = x + c2 608 return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 + c2)); 609 } else if (def.operator == LONG_SUB) { 610 long c1 = getLongValue(Binary.getVal2(def)); 611 // x = a - c1; y = x + c2 612 return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c2 - c1)); 613 } else if (def.operator == LONG_NEG && FOLD_CONSTANTS_TO_LHS) { 614 // x = -a; y = x + c2; 615 return Binary.create(LONG_SUB, y.copyRO(), LC(c2), a.copyRO()); 616 } 617 } 618 return null; 619 } 620 case FLOAT_ADD_opcode: { 621 if (FOLD_FLOATS && FOLD_ADDS) { 622 float c2 = getFloatValue(Binary.getVal2(s)); 623 if (def.operator == FLOAT_ADD) { 624 float c1 = getFloatValue(Binary.getVal2(def)); 625 // x = a + c1; y = x + c2 626 return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 + c2)); 627 } else if (def.operator == FLOAT_SUB) { 628 float c1 = getFloatValue(Binary.getVal2(def)); 629 // x = a - c1; y = x + c2 630 return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c2 - c1)); 631 } else if (def.operator == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) { 632 // x = -a; y = x + c2; 633 return Binary.create(FLOAT_SUB, y.copyRO(), FC(c2), a.copyRO()); 634 } 635 } 636 return null; 637 } 638 case DOUBLE_ADD_opcode: { 639 if (FOLD_DOUBLES && FOLD_ADDS) { 640 double c2 = getDoubleValue(Binary.getVal2(s)); 641 if (def.operator == DOUBLE_ADD) { 642 double c1 = getDoubleValue(Binary.getVal2(def)); 643 // x = a + c1; y = x + c2 644 return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 + c2)); 645 } else if (def.operator == DOUBLE_SUB) { 646 double c1 = getDoubleValue(Binary.getVal2(def)); 647 // x = a - c1; y = x + c2 648 return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c2 - c1)); 649 } else if (def.operator == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) { 650 // x = -a; y = x + c2; 651 return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c2), a.copyRO()); 652 } 653 } 654 return null; 655 } 656 case INT_SUB_opcode: { 657 if (FOLD_INTS && FOLD_SUBS) { 658 int c2 = getIntValue(Binary.getVal2(s)); 659 if (def.operator == INT_ADD) { 660 int c1 = getIntValue(Binary.getVal2(def)); 661 // x = a + c1; y = x - c2 662 return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 - c2)); 663 } else if (def.operator == INT_SUB) { 664 int c1 = getIntValue(Binary.getVal2(def)); 665 // x = a - c1; y = x - c2 666 return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(-c1 - c2)); 667 } else if (def.operator == INT_NEG && FOLD_CONSTANTS_TO_LHS) { 668 // x = -a; y = x - c2; 669 return Binary.create(INT_SUB, y.copyRO(), IC(-c2), a.copyRO()); 670 } 671 } 672 return null; 673 } 674 case REF_SUB_opcode: { 675 if (FOLD_REFS && FOLD_SUBS) { 676 Address c2 = getAddressValue(Binary.getVal2(s)); 677 if (def.operator == REF_ADD) { 678 Address c1 = getAddressValue(Binary.getVal2(def)); 679 // x = a + c1; y = x - c2 680 return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().minus(c2.toWord()).toAddress())); 681 } else if (def.operator == REF_SUB) { 682 Address c1 = getAddressValue(Binary.getVal2(def)); 683 // x = a - c1; y = x - c2 684 return Binary.create(REF_ADD, 685 y.copyRO(), 686 a.copyRO(), 687 AC(Word.zero().minus(c1.toWord()).minus(c2.toWord()).toAddress())); 688 } else if (def.operator == REF_NEG && FOLD_CONSTANTS_TO_LHS) { 689 // x = -a; y = x - c2; 690 return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), a.copyRO()); 691 } 692 } 693 return null; 694 } 695 case LONG_SUB_opcode: { 696 if (FOLD_LONGS && FOLD_SUBS) { 697 long c2 = getLongValue(Binary.getVal2(s)); 698 if (def.operator == LONG_ADD) { 699 long c1 = getLongValue(Binary.getVal2(def)); 700 // x = a + c1; y = x - c2 701 return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 - c2)); 702 } else if (def.operator == LONG_SUB) { 703 long c1 = getLongValue(Binary.getVal2(def)); 704 // x = a - c1; y = x - c2 705 return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(-c1 - c2)); 706 } else if (def.operator == LONG_NEG && FOLD_CONSTANTS_TO_LHS) { 707 // x = -a; y = x - c2; 708 return Binary.create(LONG_SUB, y.copyRO(), LC(-c2), a.copyRO()); 709 } 710 } 711 return null; 712 } 713 case FLOAT_SUB_opcode: { 714 if (FOLD_FLOATS && FOLD_SUBS) { 715 float c2 = getFloatValue(Binary.getVal2(s)); 716 if (def.operator == FLOAT_ADD) { 717 float c1 = getFloatValue(Binary.getVal2(def)); 718 // x = a + c1; y = x - c2 719 return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 - c2)); 720 } else if (def.operator == FLOAT_SUB) { 721 float c1 = getFloatValue(Binary.getVal2(def)); 722 // x = a - c1; y = x - c2 723 return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(-c1 - c2)); 724 } else if (def.operator == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) { 725 // x = -a; y = x - c2; 726 return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c2), a.copyRO()); 727 } 728 } 729 return null; 730 } 731 case DOUBLE_SUB_opcode: { 732 if (FOLD_DOUBLES && FOLD_SUBS) { 733 double c2 = getDoubleValue(Binary.getVal2(s)); 734 if (def.operator == FLOAT_ADD) { 735 double c1 = getDoubleValue(Binary.getVal2(def)); 736 // x = a + c1; y = x - c2 737 return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 - c2)); 738 } else if (def.operator == DOUBLE_SUB) { 739 double c1 = getDoubleValue(Binary.getVal2(def)); 740 // x = a - c1; y = x + c2 741 return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(-c1 - c2)); 742 } else if (def.operator == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) { 743 // x = -a; y = x - c2; 744 return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c2), a.copyRO()); 745 } 746 } 747 return null; 748 } 749 case INT_MUL_opcode: { 750 if (FOLD_INTS && FOLD_MULTS) { 751 int c2 = getIntValue(Binary.getVal2(s)); 752 if (def.operator == INT_MUL) { 753 int c1 = getIntValue(Binary.getVal2(def)); 754 // x = a * c1; y = x * c2 755 return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(c1 * c2)); 756 } else if (def.operator == INT_NEG) { 757 // x = -a; y = x * c2; 758 return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c2)); 759 } 760 } 761 return null; 762 } 763 case LONG_MUL_opcode: { 764 if (FOLD_LONGS && FOLD_MULTS) { 765 long c2 = getLongValue(Binary.getVal2(s)); 766 if (def.operator == LONG_MUL) { 767 long c1 = getLongValue(Binary.getVal2(def)); 768 // x = a * c1; y = x * c2 769 return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(c1 * c2)); 770 } else if (def.operator == LONG_NEG) { 771 // x = -a; y = x * c2; 772 return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c2)); 773 } 774 } 775 return null; 776 } 777 case FLOAT_MUL_opcode: { 778 if (FOLD_FLOATS && FOLD_MULTS) { 779 float c2 = getFloatValue(Binary.getVal2(s)); 780 if (def.operator == FLOAT_MUL) { 781 float c1 = getFloatValue(Binary.getVal2(def)); 782 // x = a * c1; y = x * c2 783 return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(c1 * c2)); 784 } else if (def.operator == FLOAT_NEG) { 785 // x = -a; y = x * c2; 786 return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c2)); 787 } 788 } 789 return null; 790 } 791 case DOUBLE_MUL_opcode: { 792 if (FOLD_DOUBLES && FOLD_MULTS) { 793 double c2 = getDoubleValue(Binary.getVal2(s)); 794 if (def.operator == DOUBLE_MUL) { 795 double c1 = getDoubleValue(Binary.getVal2(def)); 796 // x = a * c1; y = x * c2 797 return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(c1 * c2)); 798 } else if (def.operator == DOUBLE_NEG) { 799 // x = -a; y = x * c2; 800 return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c2)); 801 } 802 } 803 return null; 804 } 805 case INT_DIV_opcode: { 806 if (FOLD_INTS && FOLD_DIVS) { 807 int c2 = getIntValue(GuardedBinary.getVal2(s)); 808 if (def.operator == INT_DIV) { 809 int c1 = getIntValue(GuardedBinary.getVal2(def)); 810 Operand guard = GuardedBinary.getGuard(def); 811 // x = a / c1; y = x / c2 812 return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(c1 * c2), guard); 813 } else if (def.operator == INT_NEG) { 814 Operand guard = GuardedBinary.getGuard(s); 815 // x = -a; y = x / c2; 816 return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c2), guard); 817 } 818 } 819 return null; 820 } 821 case LONG_DIV_opcode: { 822 if (FOLD_LONGS && FOLD_DIVS) { 823 long c2 = getLongValue(GuardedBinary.getVal2(s)); 824 if (def.operator == LONG_DIV) { 825 long c1 = getLongValue(GuardedBinary.getVal2(def)); 826 Operand guard = GuardedBinary.getGuard(def); 827 // x = a / c1; y = x / c2 828 return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(c1 * c2), guard); 829 } else if (def.operator == LONG_NEG) { 830 Operand guard = GuardedBinary.getGuard(s); 831 // x = -a; y = x / c2; 832 return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c2), guard); 833 } 834 } 835 return null; 836 } 837 case FLOAT_DIV_opcode: { 838 if (FOLD_FLOATS && FOLD_DIVS) { 839 float c2 = getFloatValue(Binary.getVal2(s)); 840 if (def.operator == FLOAT_DIV) { 841 float c1 = getFloatValue(Binary.getVal2(def)); 842 // x = a / c1; y = x / c2 843 return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(c1 * c2)); 844 } else if (def.operator == FLOAT_NEG) { 845 // x = -a; y = x / c2; 846 return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c2)); 847 } 848 } 849 return null; 850 } 851 case DOUBLE_DIV_opcode: { 852 if (FOLD_DOUBLES && FOLD_DIVS) { 853 double c2 = getDoubleValue(Binary.getVal2(s)); 854 if (def.operator == DOUBLE_DIV) { 855 double c1 = getDoubleValue(Binary.getVal2(def)); 856 // x = a / c1; y = x / c2 857 return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(c1 * c2)); 858 } else if (def.operator == DOUBLE_NEG) { 859 // x = -a; y = x / c2; 860 return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c2)); 861 } 862 } 863 return null; 864 } 865 case INT_SHL_opcode: { 866 if (FOLD_INTS && FOLD_SHIFTLS) { 867 int c2 = getIntValue(Binary.getVal2(s)); 868 if (def.operator == INT_SHL) { 869 int c1 = getIntValue(Binary.getVal2(def)); 870 // x = a << c1; y = x << c2 871 return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2)); 872 } else if ((def.operator == INT_SHR) || (def.operator == INT_USHR)) { 873 int c1 = getIntValue(Binary.getVal2(def)); 874 if (c1 == c2) { 875 // x = a >> c1; y = x << c1 876 return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 << c1)); 877 } 878 } else if (def.operator == INT_AND) { 879 int c1 = getIntValue(Binary.getVal2(def)); 880 // x = a & c1; y = << c2 881 if ((c1 << c2) == (-1 << c2)) { 882 // the first mask is redundant 883 return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2)); 884 } 885 } else if ((def.operator == INT_OR)||(def.operator == INT_XOR)) { 886 int c1 = getIntValue(Binary.getVal2(def)); 887 // x = a | c1; y = << c2 888 if ((c1 << c2) == 0) { 889 // the first mask is redundant 890 return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2)); 891 } 892 } 893 } 894 return null; 895 } 896 case REF_SHL_opcode: { 897 if (FOLD_REFS && FOLD_SHIFTLS) { 898 int c2 = getIntValue(Binary.getVal2(s)); 899 if (def.operator == REF_SHL) { 900 int c1 = getIntValue(Binary.getVal2(def)); 901 // x = a << c1; y = x << c2 902 return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2)); 903 } else if ((def.operator == REF_SHR) || (def.operator == REF_USHR)) { 904 int c1 = getIntValue(Binary.getVal2(def)); 905 if (c1 == c2) { 906 // x = a >> c1; y = x << c1 907 return Binary.create(REF_AND, 908 y.copyRO(), 909 a.copyRO(), 910 AC(Word.zero().minus(Word.one()).lsh(c1).toAddress())); 911 } 912 } else if (def.operator == REF_AND) { 913 Address c1 = getAddressValue(Binary.getVal2(def)); 914 // x = a & c1; y = x << c2 915 if (c1.toWord().lsh(c2).EQ(Word.fromIntSignExtend(-1).lsh(c2))) { 916 // the first mask is redundant 917 return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2)); 918 } 919 } else if ((def.operator == REF_OR)||(def.operator == REF_XOR)) { 920 Address c1 = getAddressValue(Binary.getVal2(def)); 921 // x = a | c1; y = x << c2 922 if (c1.toWord().lsh(c2).EQ(Word.zero())) { 923 // the first mask is redundant 924 return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2)); 925 } 926 } 927 } 928 return null; 929 } 930 case LONG_SHL_opcode: { 931 if (FOLD_LONGS && FOLD_SHIFTLS) { 932 int c2 = getIntValue(Binary.getVal2(s)); 933 if (def.operator == LONG_SHL) { 934 int c1 = getIntValue(Binary.getVal2(def)); 935 // x = a << c1; y = x << c2 936 return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2)); 937 } else if ((def.operator == LONG_SHR) || (def.operator == LONG_USHR)) { 938 int c1 = getIntValue(Binary.getVal2(def)); 939 if (c1 == c2) { 940 // x = a >> c1; y = x << c1 941 return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L << c1)); 942 } 943 } else if (def.operator == LONG_AND) { 944 long c1 = getLongValue(Binary.getVal2(def)); 945 // x = a & c1; y = << c2 946 if ((c1 << c2) == (-1L << c2)) { 947 // the first mask is redundant 948 return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2)); 949 } 950 } else if ((def.operator == LONG_OR)||(def.operator == LONG_XOR)) { 951 long c1 = getLongValue(Binary.getVal2(def)); 952 // x = a | c1; y = << c2 953 if ((c1 << c2) == 0L) { 954 // the first mask is redundant 955 return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2)); 956 } 957 } 958 } 959 return null; 960 } 961 case INT_SHR_opcode: { 962 if (FOLD_INTS && FOLD_SHIFTRS) { 963 int c2 = getIntValue(Binary.getVal2(s)); 964 if (def.operator == INT_SHR) { 965 int c1 = getIntValue(Binary.getVal2(def)); 966 // x = a >> c1; y = x >> c2 967 return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2)); 968 } else if (def.operator == INT_SHL) { 969 int c1 = getIntValue(Binary.getVal2(def)); 970 if (c1 == c2) { 971 if (c1 == 24) { 972 // x = a << 24; y = x >> 24 973 return Unary.create(INT_2BYTE, y.copyRO(), a.copyRO()); 974 } else if (c1 == 16) { 975 // x = a << 16; y = x >> 16 976 return Unary.create(INT_2SHORT, y.copyRO(), a.copyRO()); 977 } 978 } 979 } else if (def.operator == INT_AND) { 980 int c1 = getIntValue(Binary.getVal2(def)); 981 // x = a & c1; y = >> c2 982 if ((c1 >> c2) == -1) { 983 // the first mask is redundant 984 return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2)); 985 } 986 } else if ((def.operator == INT_OR)||(def.operator == INT_XOR)) { 987 int c1 = getIntValue(Binary.getVal2(def)); 988 // x = a | c1; y = >> c2 989 if ((c1 >>> c2) == 0) { 990 // the first mask is redundant 991 return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2)); 992 } 993 } 994 } 995 return null; 996 } 997 case REF_SHR_opcode: { 998 if (FOLD_REFS && FOLD_SHIFTRS) { 999 int c2 = getIntValue(Binary.getVal2(s)); 1000 if (def.operator == REF_SHR) { 1001 int c1 = getIntValue(Binary.getVal2(def)); 1002 // x = a >> c1; y = x >> c2 1003 return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2)); 1004 } else if (def.operator == REF_AND) { 1005 Address c1 = getAddressValue(Binary.getVal2(def)); 1006 // x = a & c1; y = x >> c2 1007 if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) { 1008 // the first mask is redundant 1009 return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2)); 1010 } 1011 } else if ((def.operator == REF_OR)||(def.operator == REF_XOR)) { 1012 Address c1 = getAddressValue(Binary.getVal2(def)); 1013 // x = a | c1; y = x >> c2 1014 if (c1.toWord().rshl(c2).EQ(Word.zero())) { 1015 // the first mask is redundant 1016 return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2)); 1017 } 1018 } 1019 } 1020 return null; 1021 } 1022 case LONG_SHR_opcode: { 1023 if (FOLD_LONGS && FOLD_SHIFTRS) { 1024 int c2 = getIntValue(Binary.getVal2(s)); 1025 if (def.operator == LONG_SHR) { 1026 int c1 = getIntValue(Binary.getVal2(def)); 1027 // x = a >> c1; y = x >> c2 1028 return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2)); 1029 } else if (def.operator == LONG_AND) { 1030 long c1 = getLongValue(Binary.getVal2(def)); 1031 // x = a & c1; y = >> c2 1032 if ((c1 >> c2) == -1L) { 1033 // the first mask is redundant 1034 return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2)); 1035 } 1036 } else if ((def.operator == LONG_OR)||(def.operator == LONG_XOR)) { 1037 long c1 = getLongValue(Binary.getVal2(def)); 1038 // x = a & c1; y = >> c2 1039 if ((c1 >>> c2) == 0L) { 1040 // the first mask is redundant 1041 return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2)); 1042 } 1043 } 1044 } 1045 return null; 1046 } 1047 case INT_USHR_opcode: { 1048 if (FOLD_INTS && FOLD_SHIFTRS) { 1049 int c2 = getIntValue(Binary.getVal2(s)); 1050 if (def.operator == INT_USHR) { 1051 int c1 = getIntValue(Binary.getVal2(def)); 1052 // x = a >>> c1; y = x >>> c2 1053 return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2)); 1054 } else if (def.operator == INT_SHL) { 1055 int c1 = getIntValue(Binary.getVal2(def)); 1056 if (c1 == c2) { 1057 // x = a << c1; y = x >>> c1 1058 return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 >>> c1)); 1059 } 1060 } else if (def.operator == INT_AND) { 1061 int c1 = getIntValue(Binary.getVal2(def)); 1062 // x = a & c1; y = >>> c2 1063 if ((c1 >> c2) == -1L) { 1064 // the first mask is redundant 1065 return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2)); 1066 } 1067 } else if ((def.operator == INT_OR)||(def.operator == INT_XOR)) { 1068 int c1 = getIntValue(Binary.getVal2(def)); 1069 // x = a | c1; y = >>> c2 1070 if ((c1 >>> c2) == 0) { 1071 // the first mask is redundant 1072 return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2)); 1073 } 1074 } 1075 } 1076 return null; 1077 } 1078 case REF_USHR_opcode: { 1079 if (FOLD_REFS && FOLD_SHIFTRS) { 1080 int c2 = getIntValue(Binary.getVal2(s)); 1081 if (def.operator == REF_USHR) { 1082 int c1 = getIntValue(Binary.getVal2(def)); 1083 // x = a >>> c1; y = x >>> c2 1084 return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2)); 1085 } else if (def.operator == REF_SHL) { 1086 int c1 = getIntValue(Binary.getVal2(def)); 1087 if (c1 == c2) { 1088 // x = a << c1; y = x >>> c1 1089 return Binary.create(REF_AND, 1090 y.copyRO(), 1091 a.copyRO(), 1092 AC(Word.zero().minus(Word.one()).rshl(c1).toAddress())); 1093 } 1094 } else if (def.operator == REF_AND) { //IAN!!! 1095 Address c1 = getAddressValue(Binary.getVal2(def)); 1096 // x = a & c1; y = x >>> c2 1097 if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) { 1098 // the first mask is redundant 1099 return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2)); 1100 } 1101 } else if (false) { //(def.operator == REF_OR)||(def.operator == REF_XOR)) { 1102 Address c1 = getAddressValue(Binary.getVal2(def)); 1103 // x = a | c1; y = x >>> c2 1104 if (c1.toWord().rshl(c2).EQ(Word.zero())) { 1105 // the first mask is redundant 1106 return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2)); 1107 } 1108 } 1109 } 1110 return null; 1111 } 1112 case LONG_USHR_opcode: { 1113 if (FOLD_LONGS && FOLD_SHIFTRS) { 1114 int c2 = getIntValue(Binary.getVal2(s)); 1115 if (def.operator == LONG_USHR) { 1116 int c1 = getIntValue(Binary.getVal2(def)); 1117 // x = a >>> c1; y = x >>> c2 1118 return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2)); 1119 } else if (def.operator == LONG_SHL) { 1120 int c1 = getIntValue(Binary.getVal2(def)); 1121 if (c1 == c2) { 1122 // x = a << c1; y = x >>> c1 1123 return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L >>> c1)); 1124 } 1125 } else if (def.operator == LONG_AND) { 1126 long c1 = getLongValue(Binary.getVal2(def)); 1127 // x = a & c1; y = >>> c2 1128 if ((c1 >> c2) == -1L) { 1129 // the first mask is redundant 1130 return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2)); 1131 } 1132 } else if ((def.operator == LONG_OR)||(def.operator == LONG_XOR)) { 1133 long c1 = getLongValue(Binary.getVal2(def)); 1134 // x = a & c1; y = >>> c2 1135 if ((c1 >>> c2) == 0L) { 1136 // the first mask is redundant 1137 return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2)); 1138 } 1139 } 1140 } 1141 return null; 1142 } 1143 case INT_AND_opcode: { 1144 if (FOLD_INTS && FOLD_ANDS) { 1145 int c2 = getIntValue(Binary.getVal2(s)); 1146 if (def.operator == INT_AND) { 1147 int c1 = getIntValue(Binary.getVal2(def)); 1148 // x = a & c1; y = x & c2 1149 return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c1 & c2)); 1150 } else if (def.operator == INT_OR) { 1151 int c1 = getIntValue(Binary.getVal2(def)); 1152 // x = a | c1; y = x & c2 1153 if ((c1 & c2) == 0) { 1154 return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2)); 1155 } 1156 } else if (def.operator == INT_XOR) { 1157 int c1 = getIntValue(Binary.getVal2(def)); 1158 // x = a ^ c1; y = x & c2 1159 if ((c1 & c2) == 0) { 1160 return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2)); 1161 } 1162 } else if (def.operator == INT_SHR) { 1163 int c1 = getIntValue(Binary.getVal2(def)); 1164 // x = a >> c1; y = x & c2 1165 if ((-1 >>> c1) == c2) { 1166 // turn arithmetic shifts into logical shifts if possible 1167 return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1)); 1168 } 1169 } else if (def.operator == INT_SHL) { 1170 int c1 = getIntValue(Binary.getVal2(def)); 1171 // x = a << c1; y = x & c2 1172 if (((-1 << c1) & c2) == (-1 << c1)) { 1173 // does the mask zero bits already cleared by the shift? 1174 return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1)); 1175 } 1176 } else if (def.operator == INT_USHR) { 1177 int c1 = getIntValue(Binary.getVal2(def)); 1178 // x = a >>> c1; y = x & c2 1179 if (((-1 >>> c1) & c2) == (-1 >>> c1)) { 1180 // does the mask zero bits already cleared by the shift? 1181 return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1)); 1182 } 1183 } 1184 } 1185 return null; 1186 } 1187 case REF_AND_opcode: { 1188 if (FOLD_REFS && FOLD_ANDS) { 1189 Address c2 = getAddressValue(Binary.getVal2(s)); 1190 if (def.operator == REF_AND) { 1191 Address c1 = getAddressValue(Binary.getVal2(def)); 1192 // x = a & c1; y = x & c2 1193 return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c1.toWord().and(c2.toWord()).toAddress())); 1194 } else if (def.operator == REF_OR) { 1195 Address c1 = getAddressValue(Binary.getVal2(def)); 1196 // x = a | c1; y = x & c2 1197 if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) { 1198 return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2)); 1199 } 1200 } else if (def.operator == REF_XOR) { 1201 Address c1 = getAddressValue(Binary.getVal2(def)); 1202 // x = a ^ c1; y = x & c2 1203 if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) { 1204 return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2)); 1205 } 1206 } else if (def.operator == REF_SHR) { 1207 int c1 = getIntValue(Binary.getVal2(def)); 1208 // x = a >> c1; y = x & c2 1209 if (Word.zero().minus(Word.one()).rshl(c1).toAddress().EQ(c2)) { 1210 // turn arithmetic shifts into logical ones if possible 1211 return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1)); 1212 } 1213 } else if (def.operator == REF_SHL) { 1214 int c1 = getIntValue(Binary.getVal2(def)); 1215 // x = a << c1; y = x & c2 1216 if (Word.zero().minus(Word.one()).lsh(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).lsh(c1))) { 1217 // does the mask zero bits already cleared by the shift? 1218 return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1)); 1219 } 1220 } else if (def.operator == REF_USHR) { 1221 int c1 = getIntValue(Binary.getVal2(def)); 1222 // x = a >>> c1; y = x & c2 1223 if (Word.zero().minus(Word.one()).rshl(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).rshl(c1))) { 1224 // does the mask zero bits already cleared by the shift? 1225 return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1)); 1226 } 1227 } 1228 } 1229 return null; 1230 } 1231 case LONG_AND_opcode: { 1232 if (FOLD_LONGS && FOLD_ANDS) { 1233 long c2 = getLongValue(Binary.getVal2(s)); 1234 if (def.operator == LONG_AND) { 1235 long c1 = getLongValue(Binary.getVal2(def)); 1236 // x = a & c1; y = x & c2 1237 return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c1 & c2)); 1238 } else if (def.operator == LONG_OR) { 1239 long c1 = getLongValue(Binary.getVal2(def)); 1240 // x = a | c1; y = x & c2 1241 if ((c1 & c2) == 0) { 1242 return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2)); 1243 } 1244 } else if (def.operator == LONG_XOR) { 1245 long c1 = getLongValue(Binary.getVal2(def)); 1246 // x = a ^ c1; y = x & c2 1247 if ((c1 & c2) == 0) { 1248 return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2)); 1249 } 1250 } else if (def.operator == LONG_SHR) { 1251 int c1 = getIntValue(Binary.getVal2(def)); 1252 // x = a >> c1; y = x & c2 1253 if ((-1L >>> c1) == c2) { 1254 // turn arithmetic shifts into logical ones if possible 1255 return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1)); 1256 } 1257 } else if (def.operator == LONG_SHL) { 1258 int c1 = getIntValue(Binary.getVal2(def)); 1259 // x = a << c1; y = x & c2 1260 if (((-1L << c1) & c2) == (-1L << c1)) { 1261 // does the mask zero bits already cleared by the shift? 1262 return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1)); 1263 } 1264 } else if (def.operator == LONG_USHR) { 1265 int c1 = getIntValue(Binary.getVal2(def)); 1266 // x = a >>> c1; y = x & c2 1267 if (((-1L >>> c1) & c2) == (-1L >>> c1)) { 1268 // does the mask zero bits already cleared by the shift? 1269 return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1)); 1270 } 1271 } 1272 } 1273 return null; 1274 } 1275 case INT_OR_opcode: { 1276 if (FOLD_INTS && FOLD_ORS) { 1277 int c2 = getIntValue(Binary.getVal2(s)); 1278 if (def.operator == INT_OR) { 1279 int c1 = getIntValue(Binary.getVal2(def)); 1280 // x = a | c1; y = x | c2 1281 return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c1 | c2)); 1282 } else if (def.operator == INT_AND) { 1283 int c1 = getIntValue(Binary.getVal2(def)); 1284 // x = a & c1; y = x | c2 1285 if ((~c1 | c2) == c2) { 1286 return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2)); 1287 } 1288 } else if (def.operator == INT_XOR) { 1289 int c1 = getIntValue(Binary.getVal2(def)); 1290 // x = a ^ c1; y = x | c2 1291 if ((c1 | c2) == c2) { 1292 return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2)); 1293 } 1294 } 1295 } 1296 return null; 1297 } 1298 case REF_OR_opcode: { 1299 if (FOLD_REFS && FOLD_ORS) { 1300 Address c2 = getAddressValue(Binary.getVal2(s)); 1301 if (def.operator == REF_OR) { 1302 Address c1 = getAddressValue(Binary.getVal2(def)); 1303 // x = a | c1; y = x | c2 1304 return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c1.toWord().or(c2.toWord()).toAddress())); 1305 } else if (def.operator == REF_AND) { 1306 Address c1 = getAddressValue(Binary.getVal2(def)); 1307 // x = a & c1; y = x | c2 1308 if (c1.toWord().not().or(c2.toWord()).EQ(c2.toWord())) { 1309 return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2)); 1310 } 1311 } else if (def.operator == REF_XOR) { 1312 Address c1 = getAddressValue(Binary.getVal2(def)); 1313 // x = a ^ c1; y = x | c2 1314 if (c1.toWord().or(c2.toWord()).EQ(c2.toWord())) { 1315 return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2)); 1316 } 1317 } 1318 } 1319 return null; 1320 } 1321 case LONG_OR_opcode: { 1322 if (FOLD_LONGS && FOLD_ORS) { 1323 long c2 = getLongValue(Binary.getVal2(s)); 1324 if (def.operator == LONG_OR) { 1325 long c1 = getLongValue(Binary.getVal2(def)); 1326 // x = a | c1; y = x | c2 1327 return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c1 | c2)); 1328 } else if (def.operator == LONG_AND) { 1329 long c1 = getLongValue(Binary.getVal2(def)); 1330 // x = a & c1; y = x | c2 1331 if ((~c1 | c2) == c2) { 1332 return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2)); 1333 } 1334 } else if (def.operator == LONG_XOR) { 1335 long c1 = getLongValue(Binary.getVal2(def)); 1336 // x = a ^ c1; y = x | c2 1337 if ((c1 | c2) == c2) { 1338 return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2)); 1339 } 1340 } 1341 } 1342 return null; 1343 } 1344 case INT_XOR_opcode: { 1345 if (FOLD_INTS && FOLD_XORS) { 1346 int c2 = getIntValue(Binary.getVal2(s)); 1347 if (def.operator == INT_XOR) { 1348 int c1 = getIntValue(Binary.getVal2(def)); 1349 // x = a ^ c1; y = x ^ c2 1350 return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c1 ^ c2)); 1351 } else if (def.operator == INT_NOT) { 1352 // x = ~a; y = x ^ c2 1353 return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(~c2)); 1354 } else if (def.operator == BOOLEAN_NOT) { 1355 // x = !a; y = x ^ c2 1356 return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c2 ^ 1)); 1357 } 1358 } 1359 return null; 1360 } 1361 case REF_XOR_opcode: { 1362 if (FOLD_REFS && FOLD_XORS) { 1363 Address c2 = getAddressValue(Binary.getVal2(s)); 1364 if (def.operator == REF_XOR) { 1365 Address c1 = getAddressValue(Binary.getVal2(def)); 1366 // x = a ^ c1; y = x ^ c2 1367 return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c1.toWord().xor(c2.toWord()).toAddress())); 1368 } else if (def.operator == REF_NOT) { 1369 // x = ~a; y = x ^ c2 1370 return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c2.toWord().not().toAddress())); 1371 } 1372 } 1373 return null; 1374 } 1375 case LONG_XOR_opcode: { 1376 if (FOLD_LONGS && FOLD_XORS) { 1377 long c2 = getLongValue(Binary.getVal2(s)); 1378 if (def.operator == LONG_XOR) { 1379 long c1 = getLongValue(Binary.getVal2(def)); 1380 // x = a ^ c1; y = x ^ c2 1381 return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(c1 ^ c2)); 1382 } else if (def.operator == LONG_NOT) { 1383 // x = ~a; y = x ^ c2 1384 return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(~c2)); 1385 } 1386 } 1387 return null; 1388 } 1389 case LONG_CMP_opcode: { 1390 if (FOLD_LONGS && FOLD_CMPS) { 1391 long c2 = getLongValue(Binary.getVal2(s)); 1392 if (def.operator == LONG_NEG) { 1393 // x = -a; y = x cmp c2 1394 return Binary.create(LONG_CMP, y.copyRO(), LC(-c2), a.copyRO()); 1395 } 1396 } 1397 return null; 1398 } 1399 case FLOAT_CMPL_opcode: 1400 case FLOAT_CMPG_opcode: { 1401 if (FOLD_FLOATS && FOLD_CMPS) { 1402 float c2 = getFloatValue(Binary.getVal2(s)); 1403 if (def.operator == FLOAT_ADD) { 1404 float c1 = getFloatValue(Binary.getVal2(def)); 1405 // x = a + c1; y = x cmp c2 1406 return Binary.create(s.operator, y.copyRO(), a.copyRO(), FC(c2 - c1)); 1407 } else if (def.operator == FLOAT_SUB) { 1408 float c1 = getFloatValue(Binary.getVal2(def)); 1409 // x = a - c1; y = x cmp c2 1410 return Binary.create(s.operator, y.copyRO(), a.copyRO(), FC(c1 + c2)); 1411 } else if (def.operator == FLOAT_NEG) { 1412 // x = -a; y = x cmp c2 1413 return Binary.create(s.operator, y.copyRO(), FC(-c2), a.copyRO()); 1414 } 1415 } 1416 return null; 1417 } 1418 case DOUBLE_CMPL_opcode: 1419 case DOUBLE_CMPG_opcode: { 1420 if (FOLD_DOUBLES && FOLD_CMPS) { 1421 double c2 = getDoubleValue(Binary.getVal2(s)); 1422 if (def.operator == DOUBLE_ADD) { 1423 double c1 = getDoubleValue(Binary.getVal2(def)); 1424 // x = a + c1; y = x cmp c2 1425 return Binary.create(s.operator, y.copyRO(), a.copyRO(), DC(c2 - c1)); 1426 } else if (def.operator == DOUBLE_SUB) { 1427 double c1 = getDoubleValue(Binary.getVal2(def)); 1428 // x = a - c1; y = x cmp c2 1429 return Binary.create(s.operator, y.copyRO(), a.copyRO(), DC(c1 + c2)); 1430 } else if (def.operator == DOUBLE_NEG) { 1431 // x = -a; y = x cmp c2 1432 return Binary.create(s.operator, y.copyRO(), DC(-c2), a.copyRO()); 1433 } 1434 } 1435 return null; 1436 } 1437 case BOOLEAN_CMP_INT_opcode: { 1438 if (FOLD_INTS && FOLD_CMPS) { 1439 int c2 = getIntValue(BooleanCmp.getVal2(s)); 1440 ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy(); 1441 BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy(); 1442 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1443 if (def.operator == INT_ADD) { 1444 int c1 = getIntValue(Binary.getVal2(def)); 1445 // x = a + c1; y = x cmp c2 1446 return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, prof); 1447 } else if (def.operator == INT_SUB) { 1448 int c1 = getIntValue(Binary.getVal2(def)); 1449 // x = a - c1; y = x cmp c2 1450 return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, prof); 1451 } else if (def.operator == INT_NEG) { 1452 // x = -a; y = x cmp c2 1453 return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), prof); 1454 } else if (def.operator == BOOLEAN_CMP_INT) { 1455 int c1 = getIntValue(BooleanCmp.getVal2(def)); 1456 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1457 // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false 1458 if ((cond.isEQUAL() && c2 == 1)|| 1459 (cond.isNOT_EQUAL() && c2 == 0)) { 1460 // Fold away redundancy boolean_cmp 1461 return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2, prof); 1462 } else if ((cond.isEQUAL() && c2 == 0)|| 1463 (cond.isNOT_EQUAL() && c2 == 1)) { 1464 // Fold away redundancy boolean_cmp 1465 return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), prof); 1466 } 1467 } else if (def.operator == BOOLEAN_CMP_LONG) { 1468 long c1 = getLongValue(BooleanCmp.getVal2(def)); 1469 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1470 // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false 1471 if ((cond.isEQUAL() && c2 == 1)|| 1472 (cond.isNOT_EQUAL() && c2 == 0)) { 1473 // Fold away redundancy boolean_cmp 1474 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2, prof); 1475 } else if ((cond.isEQUAL() && c2 == 0)|| 1476 (cond.isNOT_EQUAL() && c2 == 1)) { 1477 // Fold away redundancy boolean_cmp 1478 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), prof); 1479 } 1480 } else if (def.operator == BOOLEAN_CMP_ADDR) { 1481 Address c1 = getAddressValue(BooleanCmp.getVal2(def)); 1482 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1483 // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false 1484 if ((cond.isEQUAL() && c2 == 1)|| 1485 (cond.isNOT_EQUAL() && c2 == 0)) { 1486 // Fold away redundancy boolean_cmp 1487 return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2, prof); 1488 } else if ((cond.isEQUAL() && c2 == 0)|| 1489 (cond.isNOT_EQUAL() && c2 == 1)) { 1490 // Fold away redundancy boolean_cmp 1491 return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), prof); 1492 } 1493 } else if (def.operator == BOOLEAN_CMP_FLOAT) { 1494 float c1 = getFloatValue(BooleanCmp.getVal2(def)); 1495 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1496 // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false 1497 if ((cond.isEQUAL() && c2 == 1)|| 1498 (cond.isNOT_EQUAL() && c2 == 0)) { 1499 // Fold away redundancy boolean_cmp 1500 return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2, prof); 1501 } else if ((cond.isEQUAL() && c2 == 0)|| 1502 (cond.isNOT_EQUAL() && c2 == 1)) { 1503 // Fold away redundancy boolean_cmp 1504 return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), prof); 1505 } 1506 } else if (def.operator == BOOLEAN_CMP_DOUBLE) { 1507 double c1 = getDoubleValue(BooleanCmp.getVal2(def)); 1508 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1509 // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false 1510 if ((cond.isEQUAL() && c2 == 1)|| 1511 (cond.isNOT_EQUAL() && c2 == 0)) { 1512 // Fold away redundancy boolean_cmp 1513 return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2, prof); 1514 } else if ((cond.isEQUAL() && c2 == 0)|| 1515 (cond.isNOT_EQUAL() && c2 == 1)) { 1516 // Fold away redundancy boolean_cmp 1517 return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), prof); 1518 } 1519 } else if (def.operator == LONG_CMP) { 1520 long c1 = getLongValue(Binary.getVal2(def)); 1521 // x = a lcmp c1; y = y = x cmp c2 ? true : false 1522 if (cond.isEQUAL() && c2 == 0) { 1523 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), 1524 ConditionOperand.EQUAL(), prof); 1525 } else if (cond.isNOT_EQUAL() && c2 == 0) { 1526 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), 1527 ConditionOperand.NOT_EQUAL(), prof); 1528 } else if ((cond.isEQUAL() && c2 == 1)||(cond.isGREATER() && c2 == 0)){ 1529 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), 1530 ConditionOperand.GREATER(), prof); 1531 } else if (cond.isGREATER_EQUAL() && c2 == 0){ 1532 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), 1533 ConditionOperand.GREATER_EQUAL(), prof); 1534 } else if ((cond.isEQUAL() && c2 == -1)||(cond.isLESS() && c2 == 0)) { 1535 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), 1536 ConditionOperand.LESS(), prof); 1537 } else if (cond.isLESS_EQUAL() && c2 == 0) { 1538 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), 1539 ConditionOperand.LESS_EQUAL(), prof); 1540 } 1541 } 1542 } 1543 } 1544 return null; 1545 } 1546 case BOOLEAN_CMP_LONG_opcode: { 1547 if (FOLD_LONGS && FOLD_CMPS) { 1548 long c2 = getLongValue(BooleanCmp.getVal2(s)); 1549 ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy(); 1550 BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy(); 1551 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1552 if (def.operator == LONG_ADD) { 1553 long c1 = getLongValue(Binary.getVal2(def)); 1554 // x = a + c1; y = x cmp c2 1555 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, prof); 1556 } else if (def.operator == LONG_SUB) { 1557 long c1 = getLongValue(Binary.getVal2(def)); 1558 // x = a - c1; y = x cmp c2 1559 return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, prof); 1560 } else if (def.operator == LONG_NEG) { 1561 // x = -a; y = x cmp c2 1562 return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), prof); 1563 } 1564 } 1565 } 1566 return null; 1567 } 1568 case BOOLEAN_CMP_ADDR_opcode: { 1569 if (FOLD_REFS && FOLD_CMPS) { 1570 Address c2 = getAddressValue(BooleanCmp.getVal2(s)); 1571 ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy(); 1572 BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy(); 1573 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1574 if (def.operator == REF_ADD) { 1575 Address c1 = getAddressValue(Binary.getVal2(def)); 1576 // x = a + c1; y = x cmp c2 1577 return BooleanCmp.create(BOOLEAN_CMP_ADDR, 1578 y.copyRO(), 1579 a.copyRO(), 1580 AC(c2.toWord().minus(c1.toWord()).toAddress()), 1581 cond, 1582 prof); 1583 } else if (def.operator == REF_SUB) { 1584 Address c1 = getAddressValue(Binary.getVal2(def)); 1585 // x = a - c1; y = x cmp c2 1586 return BooleanCmp.create(BOOLEAN_CMP_ADDR, 1587 y.copyRO(), 1588 a.copyRO(), 1589 AC(c1.toWord().plus(c2.toWord()).toAddress()), 1590 cond, 1591 prof); 1592 } else if (def.operator == REF_NEG) { 1593 // x = -a; y = x cmp c2 1594 return BooleanCmp.create(BOOLEAN_CMP_ADDR, 1595 y.copyRO(), 1596 a.copyRO(), 1597 AC(Word.zero().minus(c2.toWord()).toAddress()), 1598 cond.flipOperands(), 1599 prof); 1600 } 1601 } 1602 } 1603 return null; 1604 } 1605 case INT_IFCMP_opcode: { 1606 if (FOLD_INTS && FOLD_IFCMPS) { 1607 int c2 = getIntValue(IfCmp.getVal2(s)); 1608 ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy(); 1609 BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy(); 1610 BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy(); 1611 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1612 if (def.operator == INT_ADD) { 1613 int c1 = getIntValue(Binary.getVal2(def)); 1614 // x = a + c1; y = x cmp c2 1615 return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, target, prof); 1616 } else if (def.operator == INT_SUB) { 1617 int c1 = getIntValue(Binary.getVal2(def)); 1618 // x = a - c1; y = x cmp c2 1619 return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, target, prof); 1620 } else if (def.operator == INT_NEG) { 1621 // x = -a; y = x cmp c2 1622 return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), target, prof); 1623 } else if (def.operator == BOOLEAN_CMP_INT) { 1624 int c1 = getIntValue(BooleanCmp.getVal2(def)); 1625 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1626 // x = a cmp<cond2> c1 ? true : false; y = x cmp<cond> c2 1627 if ((cond.isEQUAL() && c2 == 1)|| 1628 (cond.isNOT_EQUAL() && c2 == 0)) { 1629 // Fold away redundant boolean_cmp 1630 // x = a cmp<cond2> c1; y = x == 1 ==> y = a cmp<cond2> c1 1631 return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2, target, prof); 1632 } else if ((cond.isEQUAL() && c2 == 0)|| 1633 (cond.isNOT_EQUAL() && c2 == 1)) { 1634 // Fold away redundant boolean_cmp 1635 // x = a cmp<cond2> c1; y = x == 0 ==> y = a cmp<!cond2> c1 1636 return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), target, prof); 1637 } 1638 } else if (def.operator == BOOLEAN_CMP_LONG) { 1639 long c1 = getLongValue(BooleanCmp.getVal2(def)); 1640 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1641 // x = a cmp c1 ? true : false; y = x cmp c2 1642 if ((cond.isEQUAL() && c2 == 1)|| 1643 (cond.isNOT_EQUAL() && c2 == 0)) { 1644 // Fold away redundant boolean_cmp 1645 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2, target, prof); 1646 } else if ((cond.isEQUAL() && c2 == 0)|| 1647 (cond.isNOT_EQUAL() && c2 == 1)) { 1648 // Fold away redundant boolean_cmp 1649 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), target, prof); 1650 } 1651 } else if (def.operator == BOOLEAN_CMP_ADDR) { 1652 Address c1 = getAddressValue(BooleanCmp.getVal2(def)); 1653 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1654 // x = a cmp c1 ? true : false; y = x cmp c2 1655 if ((cond.isEQUAL() && c2 == 1)|| 1656 (cond.isNOT_EQUAL() && c2 == 0)) { 1657 // Fold away redundant boolean_cmp 1658 return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2, target, prof); 1659 } else if ((cond.isEQUAL() && c2 == 0)|| 1660 (cond.isNOT_EQUAL() && c2 == 1)) { 1661 // Fold away redundant boolean_cmp 1662 return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), target, prof); 1663 } 1664 } else if (def.operator == BOOLEAN_CMP_FLOAT) { 1665 float c1 = getFloatValue(BooleanCmp.getVal2(def)); 1666 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1667 // x = a cmp c1 ? true : false; y = x cmp c2 1668 if ((cond.isEQUAL() && c2 == 1)|| 1669 (cond.isNOT_EQUAL() && c2 == 0)) { 1670 // Fold away redundant boolean_cmp 1671 return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2, target, prof); 1672 } else if ((cond.isEQUAL() && c2 == 0)|| 1673 (cond.isNOT_EQUAL() && c2 == 1)) { 1674 // Fold away redundant boolean_cmp 1675 return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), target, prof); 1676 } 1677 } else if (def.operator == BOOLEAN_CMP_DOUBLE) { 1678 double c1 = getDoubleValue(BooleanCmp.getVal2(def)); 1679 ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition(); 1680 // x = a cmp c1 ? true : false; y = x cmp c2 1681 if ((cond.isEQUAL() && c2 == 1)|| 1682 (cond.isNOT_EQUAL() && c2 == 0)) { 1683 // Fold away redundant boolean_cmp 1684 return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2, target, prof); 1685 } else if ((cond.isEQUAL() && c2 == 0)|| 1686 (cond.isNOT_EQUAL() && c2 == 1)) { 1687 // Fold away redundant boolean_cmp 1688 return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), target, prof); 1689 } 1690 } else if (def.operator == LONG_CMP) { 1691 long c1 = getLongValue(Binary.getVal2(def)); 1692 // x = a lcmp c1; y = y = x cmp c2 1693 if (cond.isEQUAL() && c2 == 0) { 1694 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), 1695 ConditionOperand.EQUAL(), target, prof); 1696 } else if (cond.isNOT_EQUAL() && c2 == 0) { 1697 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), 1698 ConditionOperand.NOT_EQUAL(), target, prof); 1699 } else if ((cond.isEQUAL() && c2 == 1)||(cond.isGREATER() && c2 == 0)){ 1700 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), 1701 ConditionOperand.GREATER(), target, prof); 1702 } else if (cond.isGREATER_EQUAL() && c2 == 0){ 1703 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), 1704 ConditionOperand.GREATER_EQUAL(), target, prof); 1705 } else if ((cond.isEQUAL() && c2 == -1)||(cond.isLESS() && c2 == 0)) { 1706 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), 1707 ConditionOperand.LESS(), target, prof); 1708 } else if (cond.isLESS_EQUAL() && c2 == 0) { 1709 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), 1710 ConditionOperand.LESS_EQUAL(), target, prof); 1711 } 1712 } 1713 } 1714 } 1715 return null; 1716 } 1717 case LONG_IFCMP_opcode: { 1718 if (FOLD_LONGS && FOLD_IFCMPS) { 1719 long c2 = getLongValue(IfCmp.getVal2(s)); 1720 ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy(); 1721 BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy(); 1722 BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy(); 1723 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1724 if (def.operator == LONG_ADD) { 1725 long c1 = getLongValue(Binary.getVal2(def)); 1726 // x = a + c1; y = x cmp c2 1727 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, target, prof); 1728 } else if (def.operator == LONG_SUB) { 1729 long c1 = getLongValue(Binary.getVal2(def)); 1730 // x = a - c1; y = x cmp c2 1731 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, target, prof); 1732 } else if (def.operator == LONG_NEG) { 1733 // x = -a; y = x cmp c2 1734 return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), target, prof); 1735 } 1736 } 1737 } 1738 return null; 1739 } 1740 case FLOAT_IFCMP_opcode: { 1741 if (FOLD_FLOATS && FOLD_IFCMPS) { 1742 float c2 = getFloatValue(IfCmp.getVal2(s)); 1743 ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy(); 1744 BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy(); 1745 BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy(); 1746 if (def.operator == FLOAT_ADD) { 1747 float c1 = getFloatValue(Binary.getVal2(def)); 1748 // x = a + c1; y = x cmp c2 1749 return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c2 - c1), cond, target, prof); 1750 } else if (def.operator == FLOAT_SUB) { 1751 float c1 = getFloatValue(Binary.getVal2(def)); 1752 // x = a - c1; y = x cmp c2 1753 return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1 + c2), cond, target, prof); 1754 } else if (def.operator == FLOAT_NEG) { 1755 // x = -a; y = x cmp c2 1756 return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(-c2), cond.flipOperands(), target, prof); 1757 } 1758 } 1759 return null; 1760 } 1761 case DOUBLE_IFCMP_opcode: { 1762 if (FOLD_DOUBLES && FOLD_IFCMPS) { 1763 double c2 = getDoubleValue(IfCmp.getVal2(s)); 1764 ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy(); 1765 BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy(); 1766 BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy(); 1767 if (def.operator == DOUBLE_ADD) { 1768 double c1 = getDoubleValue(Binary.getVal2(def)); 1769 // x = a + c1; y = x cmp c2 1770 return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c2 - c1), cond, target, prof); 1771 } else if (def.operator == DOUBLE_SUB) { 1772 double c1 = getDoubleValue(Binary.getVal2(def)); 1773 // x = a - c1; y = x cmp c2 1774 return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1 + c2), cond, target, prof); 1775 } else if (def.operator == DOUBLE_NEG) { 1776 // x = -a; y = x cmp c2 1777 return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(-c2), cond.flipOperands(), target, prof); 1778 } 1779 } 1780 return null; 1781 } 1782 case REF_IFCMP_opcode: { 1783 if (FOLD_REFS && FOLD_IFCMPS) { 1784 Address c2 = getAddressValue(IfCmp.getVal2(s)); 1785 ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy(); 1786 BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy(); 1787 BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy(); 1788 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1789 if ((def.operator == NEW || def.operator == NEWARRAY) && c2.EQ(Address.zero())) { 1790 // x = new ... ; y = x cmp null 1791 return IfCmp.create(REF_IFCMP, 1792 y.copyRO(), 1793 AC(Address.zero()), 1794 AC(Address.zero()), 1795 cond.flipCode(), 1796 target, 1797 prof); 1798 } else if (def.operator == REF_ADD) { 1799 Address c1 = getAddressValue(Binary.getVal2(def)); 1800 // x = a + c1; y = x cmp c2 1801 return IfCmp.create(REF_IFCMP, 1802 y.copyRO(), 1803 a.copyRO(), 1804 AC(c2.toWord().minus(c1.toWord()).toAddress()), 1805 cond, 1806 target, 1807 prof); 1808 } else if (def.operator == REF_SUB) { 1809 Address c1 = getAddressValue(Binary.getVal2(def)); 1810 // x = a - c1; y = x cmp c2 1811 return IfCmp.create(REF_IFCMP, 1812 y.copyRO(), 1813 a.copyRO(), 1814 AC(c1.toWord().plus(c2.toWord()).toAddress()), 1815 cond, 1816 target, 1817 prof); 1818 } else if (def.operator == REF_NEG) { 1819 // x = -a; y = x cmp c2 1820 return IfCmp.create(REF_IFCMP, 1821 y.copyRO(), 1822 a.copyRO(), 1823 AC(Word.zero().minus(c2.toWord()).toAddress()), 1824 cond.flipOperands(), 1825 target, 1826 prof); 1827 } 1828 } 1829 } 1830 return null; 1831 } 1832 case INT_IFCMP2_opcode: { 1833 if (FOLD_INTS && FOLD_IFCMPS) { 1834 int c2 = getIntValue(IfCmp2.getVal2(s)); 1835 ConditionOperand cond1 = (ConditionOperand) IfCmp2.getCond1(s).copy(); 1836 ConditionOperand cond2 = (ConditionOperand) IfCmp2.getCond2(s).copy(); 1837 BranchOperand target1 = (BranchOperand) IfCmp2.getTarget1(s).copy(); 1838 BranchOperand target2 = (BranchOperand) IfCmp2.getTarget2(s).copy(); 1839 BranchProfileOperand prof1 = (BranchProfileOperand) IfCmp2.getBranchProfile1(s).copy(); 1840 BranchProfileOperand prof2 = (BranchProfileOperand) IfCmp2.getBranchProfile2(s).copy(); 1841 if ((cond1.isEQUAL() || cond1.isNOT_EQUAL())&&(cond2.isEQUAL() || cond2.isNOT_EQUAL())) { 1842 if (def.operator == INT_ADD) { 1843 int c1 = getIntValue(Binary.getVal2(def)); 1844 // x = a + c1; y = x cmp c2 1845 return IfCmp2.create(INT_IFCMP2, 1846 y.copyRO(), 1847 a.copyRO(), 1848 IC(c2 - c1), 1849 cond1, 1850 target1, 1851 prof1, 1852 cond2, 1853 target2, 1854 prof2); 1855 } else if (def.operator == INT_SUB) { 1856 int c1 = getIntValue(Binary.getVal2(def)); 1857 // x = a - c1; y = x cmp c2 1858 return IfCmp2.create(INT_IFCMP2, 1859 y.copyRO(), 1860 a.copyRO(), 1861 IC(c1 + c2), 1862 cond1, 1863 target1, 1864 prof1, 1865 cond2, 1866 target2, 1867 prof2); 1868 } else if (def.operator == INT_NEG) { 1869 // x = -a; y = x cmp c2 1870 return IfCmp2.create(INT_IFCMP2, 1871 y.copyRO(), 1872 a.copyRO(), 1873 IC(-c2), 1874 cond1.flipOperands(), 1875 target1, 1876 prof1, 1877 cond2.flipOperands(), 1878 target2, 1879 prof2); 1880 } 1881 } 1882 } 1883 return null; 1884 } 1885 1886 case INT_COND_MOVE_opcode: 1887 case LONG_COND_MOVE_opcode: 1888 case REF_COND_MOVE_opcode: 1889 case FLOAT_COND_MOVE_opcode: 1890 case DOUBLE_COND_MOVE_opcode: 1891 case GUARD_COND_MOVE_opcode: { 1892 if (FOLD_INTS && FOLD_CONDMOVES) { 1893 Operand trueValue = CondMove.getTrueValue(s); 1894 Operand falseValue = CondMove.getFalseValue(s); 1895 ConditionOperand cond = (ConditionOperand) CondMove.getCond(s).copy(); 1896 boolean isEqualityTest = cond.isEQUAL() || cond.isNOT_EQUAL(); 1897 switch (def.operator.opcode) { 1898 case INT_ADD_opcode: 1899 if (isEqualityTest) { 1900 int c1 = getIntValue(Binary.getVal2(def)); 1901 int c2 = getIntValue(CondMove.getVal2(s)); 1902 // x = a + c1; y = x cmp c2 ? trueValue : falseValue 1903 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c2 - c1), cond, trueValue, falseValue); 1904 } 1905 break; 1906 case LONG_ADD_opcode: 1907 if (isEqualityTest) { 1908 long c1 = getLongValue(Binary.getVal2(def)); 1909 long c2 = getLongValue(CondMove.getVal2(s)); 1910 // x = a + c1; y = x cmp c2 ? trueValue : falseValue 1911 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c2 - c1), cond, trueValue, falseValue); 1912 } 1913 break; 1914 case REF_ADD_opcode: 1915 if (isEqualityTest) { 1916 Address c1 = getAddressValue(Binary.getVal2(def)); 1917 Address c2 = getAddressValue(CondMove.getVal2(s)); 1918 // x = a + c1; y = x cmp c2 ? trueValue : falseValue 1919 return CondMove.create(s.operator(), 1920 y.copyRO(), 1921 a.copyRO(), 1922 AC(c2.toWord().minus(c1.toWord()).toAddress()), 1923 cond, 1924 trueValue, 1925 falseValue); 1926 } 1927 break; 1928 case FLOAT_ADD_opcode: { 1929 float c1 = getFloatValue(Binary.getVal2(def)); 1930 float c2 = getFloatValue(CondMove.getVal2(s)); 1931 // x = a + c1; y = x cmp c2 ? trueValue : falseValue 1932 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c2 - c1), cond, trueValue, falseValue); 1933 } 1934 case DOUBLE_ADD_opcode: { 1935 double c1 = getDoubleValue(Binary.getVal2(def)); 1936 double c2 = getDoubleValue(CondMove.getVal2(s)); 1937 // x = a + c1; y = x cmp c2 ? trueValue : falseValue 1938 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c2 - c1), cond, trueValue, falseValue); 1939 } 1940 case INT_SUB_opcode: 1941 if (isEqualityTest) { 1942 int c1 = getIntValue(Binary.getVal2(def)); 1943 int c2 = getIntValue(CondMove.getVal2(s)); 1944 // x = a - c1; y = x cmp c2 ? trueValue : falseValue 1945 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1 + c2), cond, trueValue, falseValue); 1946 } 1947 break; 1948 case LONG_SUB_opcode: 1949 if (isEqualityTest) { 1950 1951 long c1 = getLongValue(Binary.getVal2(def)); 1952 long c2 = getLongValue(CondMove.getVal2(s)); 1953 // x = a - c1; y = x cmp c2 ? trueValue : falseValue 1954 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1 + c2), cond, trueValue, falseValue); 1955 } 1956 break; 1957 case REF_SUB_opcode: 1958 if (isEqualityTest) { 1959 Address c1 = getAddressValue(Binary.getVal2(def)); 1960 Address c2 = getAddressValue(CondMove.getVal2(s)); 1961 // x = a - c1; y = x cmp c2 ? trueValue : falseValue 1962 return CondMove.create(s.operator(), 1963 y.copyRO(), 1964 a.copyRO(), 1965 AC(c1.toWord().plus(c2.toWord()).toAddress()), 1966 cond, 1967 trueValue, 1968 falseValue); 1969 } 1970 break; 1971 case FLOAT_SUB_opcode: { 1972 float c1 = getFloatValue(Binary.getVal2(def)); 1973 float c2 = getFloatValue(CondMove.getVal2(s)); 1974 // x = a - c1; y = x cmp c2 ? trueValue : falseValue 1975 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1 + c2), cond, trueValue, falseValue); 1976 } 1977 case DOUBLE_SUB_opcode: { 1978 double c1 = getDoubleValue(Binary.getVal2(def)); 1979 double c2 = getDoubleValue(CondMove.getVal2(s)); 1980 // x = a - c1; y = x cmp c2 ? trueValue : falseValue 1981 return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1 + c2), cond, trueValue, falseValue); 1982 } 1983 case INT_NEG_opcode: 1984 if (isEqualityTest) { 1985 int c2 = getIntValue(CondMove.getVal2(s)); 1986 // x = -a; y = x cmp c2 ? trueValue : falseValue 1987 return CondMove.create(s.operator(), 1988 y.copyRO(), 1989 a.copyRO(), 1990 IC(-c2), 1991 cond.flipOperands(), 1992 trueValue, 1993 falseValue); 1994 } 1995 break; 1996 case LONG_NEG_opcode: 1997 if (isEqualityTest) { 1998 long c2 = getLongValue(CondMove.getVal2(s)); 1999 // x = -a; y = x cmp c2 ? trueValue : falseValue 2000 return CondMove.create(s.operator(), 2001 y.copyRO(), 2002 a.copyRO(), 2003 LC(-c2), 2004 cond.flipOperands(), 2005 trueValue, 2006 falseValue); 2007 } 2008 break; 2009 case REF_NEG_opcode: 2010 if (isEqualityTest) { 2011 Address c2 = getAddressValue(CondMove.getVal2(s)); 2012 // x = -a; y = x cmp c2 ? trueValue : falseValue 2013 return CondMove.create(s.operator(), 2014 y.copyRO(), 2015 a.copyRO(), 2016 AC(Word.zero().minus(c2.toWord()).toAddress()), 2017 cond.flipOperands(), 2018 trueValue, 2019 falseValue); 2020 } 2021 break; 2022 case FLOAT_NEG_opcode: { 2023 float c2 = getFloatValue(CondMove.getVal2(s)); 2024 // x = -a; y = x cmp c2 ? trueValue : falseValue 2025 return CondMove.create(s.operator(), 2026 y.copyRO(), 2027 a.copyRO(), 2028 FC(-c2), 2029 cond.flipOperands(), 2030 trueValue, 2031 falseValue); 2032 } 2033 case DOUBLE_NEG_opcode: { 2034 double c2 = getDoubleValue(CondMove.getVal2(s)); 2035 // x = -a; y = x cmp c2 ? trueValue : falseValue 2036 return CondMove.create(s.operator(), 2037 y.copyRO(), 2038 a.copyRO(), 2039 DC(-c2), 2040 cond.flipOperands(), 2041 trueValue, 2042 falseValue); 2043 } 2044 case BOOLEAN_CMP_INT_opcode: { 2045 int c1 = getIntValue(BooleanCmp.getVal2(def)); 2046 int c2 = getIntValue(CondMove.getVal2(s)); 2047 // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue 2048 if ((cond.isEQUAL() && c2 == 1)|| 2049 (cond.isNOT_EQUAL() && c2 == 0)) { 2050 return CondMove.create(s.operator(), 2051 y.copyRO(), 2052 a.copyRO(), 2053 IC(c1), 2054 BooleanCmp.getCond(def).copy().asCondition(), 2055 trueValue, 2056 falseValue); 2057 } else if ((cond.isEQUAL() && c2 == 0)|| 2058 (cond.isNOT_EQUAL() && c2 == 1)) { 2059 return CondMove.create(s.operator(), 2060 y.copyRO(), 2061 a.copyRO(), 2062 IC(c1), 2063 BooleanCmp.getCond(def).copy().asCondition().flipCode(), 2064 trueValue, 2065 falseValue); 2066 } 2067 break; 2068 } 2069 case BOOLEAN_CMP_ADDR_opcode: { 2070 Address c1 = getAddressValue(BooleanCmp.getVal2(def)); 2071 int c2 = getIntValue(CondMove.getVal2(s)); 2072 // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue 2073 if ((cond.isEQUAL() && c2 == 1)|| 2074 (cond.isNOT_EQUAL() && c2 == 0)) { 2075 return CondMove.create(s.operator(), 2076 y.copyRO(), 2077 a.copyRO(), 2078 AC(c1), 2079 BooleanCmp.getCond(def).copy().asCondition(), 2080 trueValue, 2081 falseValue); 2082 } else if ((cond.isEQUAL() && c2 == 0)|| 2083 (cond.isNOT_EQUAL() && c2 == 1)) { 2084 return CondMove.create(s.operator(), 2085 y.copyRO(), 2086 a.copyRO(), 2087 AC(c1), 2088 BooleanCmp.getCond(def).flipCode(), 2089 trueValue, 2090 falseValue); 2091 } 2092 break; 2093 } 2094 case BOOLEAN_CMP_LONG_opcode: { 2095 long c1 = getLongValue(BooleanCmp.getVal2(def)); 2096 int c2 = getIntValue(CondMove.getVal2(s)); 2097 // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue 2098 if ((cond.isEQUAL() && c2 == 1)|| 2099 (cond.isNOT_EQUAL() && c2 == 0)) { 2100 return CondMove.create(s.operator(), 2101 y.copyRO(), 2102 a.copyRO(), 2103 LC(c1), 2104 BooleanCmp.getCond(def).copy().asCondition(), 2105 trueValue, 2106 falseValue); 2107 } else if ((cond.isEQUAL() && c2 == 0)|| 2108 (cond.isNOT_EQUAL() && c2 == 1)) { 2109 return CondMove.create(s.operator(), 2110 y.copyRO(), 2111 a.copyRO(), 2112 LC(c1), 2113 BooleanCmp.getCond(def).copy().asCondition().flipCode(), 2114 trueValue, 2115 falseValue); 2116 } else { 2117 return null; 2118 } 2119 } 2120 case BOOLEAN_CMP_DOUBLE_opcode: { 2121 double c1 = getDoubleValue(BooleanCmp.getVal2(def)); 2122 int c2 = getIntValue(CondMove.getVal2(s)); 2123 // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue 2124 if ((cond.isEQUAL() && c2 == 1)|| 2125 (cond.isNOT_EQUAL() && c2 == 0)) { 2126 return CondMove.create(s.operator(), 2127 y.copyRO(), 2128 a.copyRO(), 2129 DC(c1), 2130 BooleanCmp.getCond(def).copy().asCondition(), 2131 trueValue, 2132 falseValue); 2133 } else if ((cond.isEQUAL() && c2 == 0)|| 2134 (cond.isNOT_EQUAL() && c2 == 1)) { 2135 return CondMove.create(s.operator(), 2136 y.copyRO(), 2137 a.copyRO(), 2138 DC(c1), 2139 BooleanCmp.getCond(def).copy().asCondition().flipCode(), 2140 trueValue, 2141 falseValue); 2142 } 2143 break; 2144 } 2145 case BOOLEAN_CMP_FLOAT_opcode: { 2146 float c1 = getFloatValue(BooleanCmp.getVal2(def)); 2147 int c2 = getIntValue(CondMove.getVal2(s)); 2148 // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue 2149 if ((cond.isEQUAL() && c2 == 1)|| 2150 (cond.isNOT_EQUAL() && c2 == 0)) { 2151 return CondMove.create(s.operator(), 2152 y.copyRO(), 2153 a.copyRO(), 2154 FC(c1), 2155 BooleanCmp.getCond(def).copy().asCondition(), 2156 trueValue, 2157 falseValue); 2158 } else if ((cond.isEQUAL() && c2 == 0)|| 2159 (cond.isNOT_EQUAL() && c2 == 1)) { 2160 return CondMove.create(s.operator(), 2161 y.copyRO(), 2162 a.copyRO(), 2163 FC(c1), 2164 BooleanCmp.getCond(def).copy().asCondition().flipCode(), 2165 trueValue, 2166 falseValue); 2167 } 2168 break; 2169 } 2170 case LONG_CMP_opcode: { 2171 long c1 = getLongValue(Binary.getVal2(def)); 2172 int c2 = getIntValue(CondMove.getVal2(s)); 2173 // x = a lcmp c1; y = y = x cmp c2 ? trueValue : falseValue 2174 if (cond.isEQUAL() && c2 == 0) { 2175 return CondMove.create(s.operator(), 2176 y.copyRO(), 2177 a.copyRO(), 2178 LC(c1), 2179 ConditionOperand.EQUAL(), 2180 trueValue, 2181 falseValue); 2182 } else if (cond.isNOT_EQUAL() && c2 == 0) { 2183 return CondMove.create(s.operator(), 2184 y.copyRO(), 2185 a.copyRO(), 2186 LC(c1), 2187 ConditionOperand.NOT_EQUAL(), 2188 trueValue, 2189 falseValue); 2190 } else if ((cond.isEQUAL() && c2 == 1)||(cond.isGREATER() && c2 == 0)){ 2191 return CondMove.create(s.operator(), 2192 y.copyRO(), 2193 a.copyRO(), 2194 LC(c1), 2195 ConditionOperand.GREATER(), 2196 trueValue, 2197 falseValue); 2198 } else if (cond.isGREATER_EQUAL() && c2 == 0){ 2199 return CondMove.create(s.operator(), 2200 y.copyRO(), 2201 a.copyRO(), 2202 LC(c1), 2203 ConditionOperand.GREATER_EQUAL(), 2204 trueValue, 2205 falseValue); 2206 } else if ((cond.isEQUAL() && c2 == -1)||(cond.isLESS() && c2 == 0)) { 2207 return CondMove.create(s.operator(), 2208 y.copyRO(), 2209 a.copyRO(), 2210 LC(c1), 2211 ConditionOperand.LESS(), 2212 trueValue, 2213 falseValue); 2214 } else if (cond.isLESS_EQUAL() && c2 == 0) { 2215 return CondMove.create(s.operator(), 2216 y.copyRO(), 2217 a.copyRO(), 2218 LC(c1), 2219 ConditionOperand.LESS_EQUAL(), 2220 trueValue, 2221 falseValue); 2222 } 2223 break; 2224 } 2225 default: 2226 } 2227 } 2228 return null; 2229 } 2230 2231 case INT_NEG_opcode: { 2232 if (FOLD_INTS && FOLD_NEGS) { 2233 if (def.operator == INT_NEG) { 2234 // x = -z; y = -x; 2235 return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy()); 2236 } else if (def.operator == INT_MUL) { 2237 int c1 = getIntValue(Binary.getVal2(def)); 2238 // x = a * c1; y = -x; 2239 return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c1)); 2240 } else if (def.operator == INT_DIV) { 2241 int c1 = getIntValue(GuardedBinary.getVal2(def)); 2242 Operand guard = GuardedBinary.getGuard(def); 2243 // x = a / c1; y = -x; 2244 return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c1), guard.copy()); 2245 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == INT_ADD)) { 2246 int c1 = getIntValue(Binary.getVal2(def)); 2247 // x = a + c1; y = -x; 2248 return Binary.create(INT_SUB, y.copyRO(), IC(-c1), a.copyRO()); 2249 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == INT_SUB)) { 2250 int c1 = getIntValue(Binary.getVal2(def)); 2251 // x = a - c1; y = -x; 2252 return Binary.create(INT_SUB, y.copyRO(), IC(c1), a.copyRO()); 2253 } 2254 } 2255 return null; 2256 } 2257 2258 case REF_NEG_opcode: { 2259 if (FOLD_REFS && FOLD_NEGS) { 2260 if (def.operator == REF_NEG) { 2261 // x = -z; y = -x; 2262 return Move.create(REF_MOVE, y.copyRO(), Unary.getVal(def).copy()); 2263 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == REF_ADD)) { 2264 Address c1 = getAddressValue(Binary.getVal2(def)); 2265 // x = a + c1; y = -x; 2266 return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c1.toWord()).toAddress()), a.copyRO()); 2267 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == REF_SUB)) { 2268 Address c1 = getAddressValue(Binary.getVal2(def)); 2269 // x = a - c1; y = -x; 2270 return Binary.create(REF_SUB, y.copyRO(), AC(c1), a.copyRO()); 2271 } 2272 } 2273 return null; 2274 } 2275 2276 case LONG_NEG_opcode: { 2277 if (FOLD_LONGS && FOLD_NEGS) { 2278 if (def.operator == LONG_NEG) { 2279 // x = -z; y = -x; 2280 return Move.create(LONG_MOVE, y.copyRO(), Unary.getVal(def).copy()); 2281 } else if (def.operator == LONG_MUL) { 2282 long c1 = getLongValue(Binary.getVal2(def)); 2283 // x = a * c1; y = -x; 2284 return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c1)); 2285 } else if (def.operator == LONG_DIV) { 2286 long c1 = getLongValue(GuardedBinary.getVal2(def)); 2287 Operand guard = GuardedBinary.getGuard(def); 2288 // x = a / c1; y = -x; 2289 return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c1), guard.copy()); 2290 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == LONG_ADD)) { 2291 long c1 = getLongValue(Binary.getVal2(def)); 2292 // x = a + c1; y = -x; 2293 return Binary.create(LONG_SUB, y.copyRO(), LC(-c1), a.copyRO()); 2294 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == LONG_SUB)) { 2295 long c1 = getLongValue(Binary.getVal2(def)); 2296 // x = a - c1; y = -x; 2297 return Binary.create(LONG_SUB, y.copyRO(), LC(c1), a.copyRO()); 2298 } 2299 } 2300 return null; 2301 } 2302 2303 case FLOAT_NEG_opcode: { 2304 if (FOLD_FLOATS && FOLD_NEGS) { 2305 if (def.operator == FLOAT_NEG) { 2306 // x = -z; y = -x; 2307 return Move.create(FLOAT_MOVE, y.copyRO(), Unary.getVal(def).copy()); 2308 } else if (def.operator == FLOAT_MUL) { 2309 float c1 = getFloatValue(Binary.getVal2(def)); 2310 // x = a * c1; y = -x; 2311 return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c1)); 2312 } else if (def.operator == FLOAT_DIV) { 2313 float c1 = getFloatValue(Binary.getVal2(def)); 2314 // x = a / c1; y = -x; 2315 return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c1)); 2316 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == FLOAT_ADD)) { 2317 float c1 = getFloatValue(Binary.getVal2(def)); 2318 // x = a + c1; y = -x; 2319 return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c1), a.copyRO()); 2320 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == FLOAT_SUB)) { 2321 float c1 = getFloatValue(Binary.getVal2(def)); 2322 // x = a - c1; y = -x; 2323 return Binary.create(FLOAT_SUB, y.copyRO(), FC(c1), a.copyRO()); 2324 } 2325 } 2326 return null; 2327 } 2328 2329 case DOUBLE_NEG_opcode: { 2330 if (FOLD_DOUBLES && FOLD_NEGS) { 2331 if (def.operator == DOUBLE_NEG) { 2332 // x = -z; y = -x; 2333 return Move.create(DOUBLE_MOVE, y.copyRO(), Unary.getVal(def).copy()); 2334 } else if (def.operator == DOUBLE_MUL) { 2335 double c1 = getDoubleValue(Binary.getVal2(def)); 2336 // x = a * c1; y = -x; 2337 return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c1)); 2338 } else if (def.operator == DOUBLE_DIV) { 2339 double c1 = getDoubleValue(Binary.getVal2(def)); 2340 // x = a / c1; y = -x; 2341 return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c1)); 2342 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == DOUBLE_ADD)) { 2343 double c1 = getDoubleValue(Binary.getVal2(def)); 2344 // x = a + c1; y = -x; 2345 return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c1), a.copyRO()); 2346 } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == DOUBLE_SUB)) { 2347 double c1 = getDoubleValue(Binary.getVal2(def)); 2348 // x = a - c1; y = -x; 2349 return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c1), a.copyRO()); 2350 } 2351 } 2352 return null; 2353 } 2354 2355 case BOOLEAN_NOT_opcode: { 2356 if (FOLD_INTS && FOLD_NOTS) { 2357 if (def.operator == BOOLEAN_NOT) { 2358 // x = 1 ^ a; y = 1 ^ x; 2359 return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy()); 2360 } else if (BooleanCmp.conforms(def)) { 2361 // x = a cmp b; y = !x 2362 return BooleanCmp.create(def.operator, 2363 y.copyRO(), 2364 BooleanCmp.getVal1(def).copy(), 2365 BooleanCmp.getVal2(def).copy(), 2366 ((ConditionOperand) BooleanCmp.getCond(def).copy()).flipCode(), 2367 ((BranchProfileOperand) BooleanCmp.getBranchProfile(def).copy())); 2368 } 2369 } 2370 return null; 2371 } 2372 2373 case INT_NOT_opcode: { 2374 if (FOLD_INTS && FOLD_NOTS) { 2375 if (def.operator == INT_NOT) { 2376 // x = -1 ^ a; y = -1 ^ x; 2377 return Move.create(INT_MOVE, y.copyRO(), a.copy()); 2378 } 2379 } 2380 return null; 2381 } 2382 2383 case REF_NOT_opcode: { 2384 if (FOLD_REFS && FOLD_NOTS) { 2385 if (def.operator == REF_NOT) { 2386 // x = -1 ^ a; y = -1 ^ x; 2387 return Move.create(REF_MOVE, y.copyRO(), a.copy()); 2388 } 2389 } 2390 return null; 2391 } 2392 2393 case LONG_NOT_opcode: { 2394 if (FOLD_LONGS && FOLD_NOTS) { 2395 if (def.operator == LONG_NOT) { 2396 // x = -1 ^ a; y = -1 ^ x; 2397 return Move.create(LONG_MOVE, y.copyRO(), a.copy()); 2398 } 2399 } 2400 return null; 2401 } 2402 2403 case INT_2BYTE_opcode: { 2404 if (FOLD_INTS && FOLD_2CONVERSION) { 2405 if ((def.operator == INT_2BYTE) || (def.operator == INT_2SHORT)) { 2406 // x = (short)a; y = (byte)x; 2407 return Unary.create(INT_2BYTE, y.copyRO(), a.copy()); 2408 } else if (def.operator == INT_2USHORT) { 2409 // x = (char)a; y = (byte)x; 2410 return Binary.create(INT_AND, y.copyRO(), a.copy(), IC(0xFF)); 2411 } 2412 } 2413 return null; 2414 } 2415 case INT_2SHORT_opcode: { 2416 if (FOLD_INTS && FOLD_2CONVERSION) { 2417 if (def.operator == INT_2BYTE) { 2418 // x = (byte)a; y = (short)x; 2419 return Unary.create(INT_2BYTE, y.copyRO(), a.copy()); 2420 } else if (def.operator == INT_2SHORT) { 2421 // x = (short)a; y = (short)x; 2422 return Unary.create(INT_2SHORT, y.copyRO(), a.copy()); 2423 } else if (def.operator == INT_2USHORT) { 2424 // x = (char)a; y = (short)x; 2425 return Unary.create(INT_2USHORT, y.copyRO(), a.copy()); 2426 } 2427 } 2428 return null; 2429 } 2430 case INT_2USHORT_opcode: { 2431 if (FOLD_INTS && FOLD_2CONVERSION) { 2432 if ((def.operator == INT_2SHORT) || (def.operator == INT_2USHORT)) { 2433 // x = (short)a; y = (char)x; 2434 return Unary.create(INT_2USHORT, y.copyRO(), a.copy()); 2435 } 2436 } 2437 return null; 2438 } 2439 2440 case LONG_2INT_opcode: { 2441 if (FOLD_LONGS && FOLD_2CONVERSION) { 2442 if (def.operator == INT_2LONG) { 2443 // x = (long)a; y = (int)x; 2444 return Move.create(INT_MOVE, y.copyRO(), a.copy()); 2445 } 2446 } 2447 return null; 2448 } 2449 case INT_2LONG_opcode: 2450 // unused 2451 return null; 2452 2453 case DOUBLE_2FLOAT_opcode: { 2454 if (FOLD_DOUBLES && FOLD_2CONVERSION) { 2455 if (def.operator == FLOAT_2DOUBLE) { 2456 // x = (double)a; y = (float)x; 2457 return Move.create(FLOAT_MOVE, y.copyRO(), a.copy()); 2458 } 2459 } 2460 return null; 2461 } 2462 2463 case FLOAT_2DOUBLE_opcode: 2464 // unused 2465 return null; 2466 case INT_ZERO_CHECK_opcode: { 2467 if (FOLD_INTS && FOLD_CHECKS) { 2468 if (def.operator == INT_NEG) { 2469 // x = -z; y = zerocheck x; 2470 return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy()); 2471 } 2472 } 2473 return null; 2474 } 2475 case LONG_ZERO_CHECK_opcode: { 2476 if (FOLD_INTS && FOLD_CHECKS) { 2477 if (def.operator == INT_NEG) { 2478 // x = -z; y = zerocheck x; 2479 return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy()); 2480 } 2481 } 2482 return null; 2483 } 2484 case NEWARRAY_opcode: 2485 // unused 2486 return null; 2487 case BOUNDS_CHECK_opcode: { 2488 if (FOLD_CHECKS) { 2489 if (def.operator == NEWARRAY) { 2490 // x = newarray xxx[c1]; y = boundscheck x, c2; 2491 int c1 = getIntValue(NewArray.getSize(def)); 2492 int c2 = getIntValue(BoundsCheck.getIndex(s)); 2493 if (c2 >= 0 && c2 < c1) { 2494 return Move.create(GUARD_MOVE, y.copyRO(), BoundsCheck.getGuard(def).copy()); 2495 } 2496 } 2497 } 2498 return null; 2499 } 2500 case NULL_CHECK_opcode: { 2501 if (FOLD_CHECKS) { 2502 if (def.operator == NEWARRAY || def.operator == NEW) { 2503 // x = new xxx; y = nullcheck x; 2504 return Move.create(GUARD_MOVE, y.copyRO(), new TrueGuardOperand()); 2505 } 2506 } 2507 return null; 2508 } 2509 case INSTANCEOF_opcode: { 2510 if (FOLD_CHECKS) { 2511 TypeReference newType; 2512 if (def.operator == NEW) { 2513 // x = new xxx; y = instanceof x, zzz; 2514 newType = New.getType(def).getTypeRef(); 2515 } else if (def.operator == NEWARRAY) { 2516 // x = newarray xxx; y = instanceof x, zzz; 2517 newType = NewArray.getType(def).getTypeRef(); 2518 } else { 2519 return null; 2520 } 2521 TypeReference instanceofType = InstanceOf.getType(s).getTypeRef(); 2522 if (newType == instanceofType) { 2523 return Move.create(INT_MOVE, y.copyRO(), IC(1)); 2524 } else { 2525 return Move.create(INT_MOVE, y.copyRO(), IC(RuntimeEntrypoints.isAssignableWith(instanceofType.resolve(), newType.resolve()) ? 1 : 0)); 2526 } 2527 } 2528 return null; 2529 } 2530 case ARRAYLENGTH_opcode: { 2531 if (FOLD_CHECKS) { 2532 if (def.operator() == NEWARRAY) { 2533 // x = newarray xxx[c1]; y = arraylength x; 2534 return Move.create(INT_MOVE, y.copyRO(), NewArray.getSize(def).copy()); 2535 } 2536 } 2537 return null; 2538 } 2539 default: 2540 OptimizingCompilerException.UNREACHABLE(); 2541 return null; 2542 } 2543 } 2544 2545 /** 2546 * Does instruction s compute a register r = candidate expression? 2547 * 2548 * @param s the instruction 2549 * @param ssa are we in SSA form? 2550 * @return the computed register, or {@code null} 2551 */ 2552 private static Register isCandidateExpression(Instruction s, boolean ssa) { 2553 2554 switch (s.operator.opcode) { 2555 // Foldable operators 2556 case BOOLEAN_NOT_opcode: 2557 case INT_NOT_opcode: 2558 case REF_NOT_opcode: 2559 case LONG_NOT_opcode: 2560 2561 case INT_NEG_opcode: 2562 case REF_NEG_opcode: 2563 case LONG_NEG_opcode: 2564 case FLOAT_NEG_opcode: 2565 case DOUBLE_NEG_opcode: 2566 2567 case INT_2BYTE_opcode: 2568 case INT_2SHORT_opcode: 2569 case INT_2USHORT_opcode: 2570 case INT_2LONG_opcode: 2571 case LONG_2INT_opcode: 2572 case FLOAT_2DOUBLE_opcode: 2573 case DOUBLE_2FLOAT_opcode: { 2574 Operand val1 = Unary.getVal(s); 2575 // if val1 is constant too, this should've been constant folded 2576 // beforehand. Give up. 2577 if (val1.isConstant()) { 2578 return null; 2579 } 2580 Register result = Unary.getResult(s).asRegister().getRegister(); 2581 if (ssa) { 2582 return result; 2583 } else if (val1.asRegister().getRegister() != result) { 2584 return result; 2585 } else { 2586 return null; 2587 } 2588 } 2589 2590 case ARRAYLENGTH_opcode: { 2591 Operand val1 = GuardedUnary.getVal(s); 2592 // if val1 is constant too, this should've been constant folded 2593 // beforehand. Give up. 2594 if (val1.isConstant()) { 2595 return null; 2596 } 2597 Register result = GuardedUnary.getResult(s).asRegister().getRegister(); 2598 // don't worry about the input and output bring the same as their types differ 2599 return result; 2600 } 2601 2602 case INT_ADD_opcode: 2603 case REF_ADD_opcode: 2604 case LONG_ADD_opcode: 2605 case FLOAT_ADD_opcode: 2606 case DOUBLE_ADD_opcode: 2607 2608 case INT_SUB_opcode: 2609 case REF_SUB_opcode: 2610 case LONG_SUB_opcode: 2611 case FLOAT_SUB_opcode: 2612 case DOUBLE_SUB_opcode: 2613 2614 case INT_MUL_opcode: 2615 case LONG_MUL_opcode: 2616 case FLOAT_MUL_opcode: 2617 case DOUBLE_MUL_opcode: 2618 2619 case FLOAT_DIV_opcode: 2620 case DOUBLE_DIV_opcode: 2621 2622 case INT_SHL_opcode: 2623 case REF_SHL_opcode: 2624 case LONG_SHL_opcode: 2625 2626 case INT_SHR_opcode: 2627 case REF_SHR_opcode: 2628 case LONG_SHR_opcode: 2629 2630 case INT_USHR_opcode: 2631 case REF_USHR_opcode: 2632 case LONG_USHR_opcode: 2633 2634 case INT_AND_opcode: 2635 case REF_AND_opcode: 2636 case LONG_AND_opcode: 2637 2638 case INT_OR_opcode: 2639 case REF_OR_opcode: 2640 case LONG_OR_opcode: 2641 2642 case INT_XOR_opcode: 2643 case REF_XOR_opcode: 2644 case LONG_XOR_opcode: 2645 2646 case LONG_CMP_opcode: 2647 case FLOAT_CMPL_opcode: 2648 case DOUBLE_CMPL_opcode: 2649 case FLOAT_CMPG_opcode: 2650 case DOUBLE_CMPG_opcode: { 2651 2652 Operand val2 = Binary.getVal2(s); 2653 if (!val2.isObjectConstant() && !val2.isTIBConstant()) { 2654 if (val2.isConstant()) { 2655 Operand val1 = Binary.getVal1(s); 2656 // if val1 is constant too, this should've been constant folded 2657 // beforehand. Give up. 2658 if (val1.isConstant()) { 2659 return null; 2660 } 2661 2662 Register result = Binary.getResult(s).asRegister().getRegister(); 2663 if (ssa) { 2664 return result; 2665 } else if (val1.asRegister().getRegister() != result) { 2666 return result; 2667 } else { 2668 return null; 2669 } 2670 } else { 2671 if (VM.VerifyAssertions) { 2672 VM._assert(val2.isRegister()); 2673 } 2674 2675 Operand val1 = Binary.getVal1(s); 2676 if (s.operator.isCommutative() && val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) { 2677 Binary.setVal1(s, Binary.getClearVal2(s)); 2678 Binary.setVal2(s, val1); 2679 Register result = Binary.getResult(s).asRegister().getRegister(); 2680 if (ssa) { 2681 return result; 2682 } else if (val2.asRegister().getRegister() != result) { 2683 return result; 2684 } else { 2685 return null; 2686 } 2687 } 2688 } 2689 } 2690 return null; 2691 } 2692 2693 case INT_DIV_opcode: 2694 case LONG_DIV_opcode: { 2695 Operand val2 = GuardedBinary.getVal2(s); 2696 if (val2.isConstant()) { 2697 Operand val1 = GuardedBinary.getVal1(s); 2698 // if val1 is constant too, this should've been constant folded 2699 // beforehand. Give up. 2700 if (val1.isConstant()) { 2701 return null; 2702 } 2703 Register result = GuardedBinary.getResult(s).asRegister().getRegister(); 2704 if (ssa) { 2705 return result; 2706 } else if (val1.asRegister().getRegister() != result) { 2707 return result; 2708 } 2709 } 2710 return null; 2711 } 2712 2713 case BOOLEAN_CMP_INT_opcode: 2714 case BOOLEAN_CMP_LONG_opcode: 2715 case BOOLEAN_CMP_ADDR_opcode: { 2716 Operand val2 = BooleanCmp.getVal2(s); 2717 if (val2.isConstant() && !val2.isMovableObjectConstant() && !val2.isTIBConstant()) { 2718 Operand val1 = BooleanCmp.getVal1(s); 2719 // if val1 is constant too, this should've been constant folded 2720 // beforehand. Give up. 2721 if (val1.isConstant()) { 2722 return null; 2723 } 2724 Register result = BooleanCmp.getResult(s).asRegister().getRegister(); 2725 if (ssa) { 2726 return result; 2727 } else if (val1.asRegister().getRegister() != result) { 2728 return result; 2729 } 2730 } else if (val2.isRegister()) { 2731 Operand val1 = BooleanCmp.getVal1(s); 2732 if (val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) { 2733 BooleanCmp.setVal1(s, BooleanCmp.getClearVal2(s)); 2734 BooleanCmp.setVal2(s, val1); 2735 BooleanCmp.getCond(s).flipOperands(); 2736 Register result = BooleanCmp.getResult(s).asRegister().getRegister(); 2737 if (ssa) { 2738 return result; 2739 } else if (val2.asRegister().getRegister() != result) { 2740 return result; 2741 } 2742 } 2743 } 2744 return null; 2745 } 2746 case INT_IFCMP_opcode: 2747 case LONG_IFCMP_opcode: 2748 case FLOAT_IFCMP_opcode: 2749 case DOUBLE_IFCMP_opcode: 2750 case REF_IFCMP_opcode: { 2751 Operand val2 = IfCmp.getVal2(s); 2752 if (!val2.isObjectConstant() && !val2.isTIBConstant()) { 2753 if (val2.isConstant()) { 2754 Operand val1 = IfCmp.getVal1(s); 2755 // if val1 is constant too, this should've been constant folded 2756 // beforehand. Give up. 2757 if (val1.isConstant()) { 2758 return null; 2759 } 2760 2761 Register result = IfCmp.getGuardResult(s).asRegister().getRegister(); 2762 if (ssa) { 2763 return result; 2764 } else if (val1.asRegister().getRegister() != result) { 2765 return result; 2766 } 2767 } else { 2768 if (VM.VerifyAssertions) { 2769 VM._assert(val2.isRegister()); 2770 } 2771 Operand val1 = IfCmp.getVal1(s); 2772 if (val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) { 2773 IfCmp.setVal1(s, IfCmp.getClearVal2(s)); 2774 IfCmp.setVal2(s, val1); 2775 IfCmp.getCond(s).flipOperands(); 2776 Register result = IfCmp.getGuardResult(s).asRegister().getRegister(); 2777 if (ssa) { 2778 return result; 2779 } else if (val2.asRegister().getRegister() != result) { 2780 return result; 2781 } 2782 } 2783 } 2784 } 2785 return null; 2786 } 2787 case INT_IFCMP2_opcode: { 2788 Operand val2 = IfCmp2.getVal2(s); 2789 if (!val2.isObjectConstant() && !val2.isTIBConstant()) { 2790 if (val2.isConstant()) { 2791 Operand val1 = IfCmp2.getVal1(s); 2792 // if val1 is constant too, this should've been constant folded 2793 // beforehand. Give up. 2794 if (val1.isConstant()) { 2795 return null; 2796 } 2797 2798 Register result = IfCmp2.getGuardResult(s).asRegister().getRegister(); 2799 if (ssa) { 2800 return result; 2801 } else if (val1.asRegister().getRegister() != result) { 2802 return result; 2803 } 2804 } else { 2805 if (VM.VerifyAssertions) { 2806 VM._assert(val2.isRegister()); 2807 } 2808 Operand val1 = IfCmp2.getVal1(s); 2809 if (val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) { 2810 IfCmp2.setVal1(s, IfCmp2.getClearVal2(s)); 2811 IfCmp2.setVal2(s, val1); 2812 IfCmp2.getCond1(s).flipOperands(); 2813 IfCmp2.getCond2(s).flipOperands(); 2814 Register result = IfCmp2.getGuardResult(s).asRegister().getRegister(); 2815 if (ssa) { 2816 return result; 2817 } else if (val2.asRegister().getRegister() != result) { 2818 return result; 2819 } 2820 } 2821 } 2822 } 2823 return null; 2824 } 2825 case INT_COND_MOVE_opcode: 2826 case LONG_COND_MOVE_opcode: 2827 case REF_COND_MOVE_opcode: 2828 case FLOAT_COND_MOVE_opcode: 2829 case DOUBLE_COND_MOVE_opcode: 2830 case GUARD_COND_MOVE_opcode: { 2831 Operand val2 = CondMove.getVal2(s); 2832 if (!val2.isObjectConstant()) { 2833 if (val2.isConstant()) { 2834 Operand val1 = CondMove.getVal1(s); 2835 // if val1 is constant too, this should've been constant folded 2836 // beforehand. Give up. 2837 if (val1.isConstant()) { 2838 return null; 2839 } 2840 Register result = CondMove.getResult(s).asRegister().getRegister(); 2841 if (ssa) { 2842 return result; 2843 } else if (val1.asRegister().getRegister() != result) { 2844 return result; 2845 } 2846 } else { 2847 if (VM.VerifyAssertions) { 2848 VM._assert(val2.isRegister()); 2849 } 2850 Operand val1 = CondMove.getVal1(s); 2851 if (val1.isConstant() && !val1.isMovableObjectConstant()) { 2852 CondMove.setVal1(s, CondMove.getClearVal2(s)); 2853 CondMove.setVal2(s, val1); 2854 CondMove.getCond(s).flipOperands(); 2855 Register result = CondMove.getResult(s).asRegister().getRegister(); 2856 if (ssa) { 2857 return result; 2858 } else if (val2.asRegister().getRegister() != result) { 2859 return result; 2860 } 2861 } 2862 } 2863 } 2864 return null; 2865 } 2866 case BOUNDS_CHECK_opcode: { 2867 Operand ref = BoundsCheck.getRef(s); 2868 Operand index = BoundsCheck.getIndex(s); 2869 if (index.isConstant()) { 2870 if (ref.isConstant()) { 2871 // this should have been constant folded. Give up. 2872 return null; 2873 } 2874 // don't worry about the input and output bring the same as their types differ 2875 return BoundsCheck.getGuardResult(s).asRegister().getRegister(); 2876 } 2877 return null; 2878 } 2879 case NULL_CHECK_opcode: { 2880 Operand ref = NullCheck.getRef(s); 2881 if (ref.isConstant()) { 2882 // this should have been constant folded. Give up. 2883 return null; 2884 } 2885 // don't worry about the input and output bring the same as their types differ 2886 return NullCheck.getGuardResult(s).asRegister().getRegister(); 2887 } 2888 case INSTANCEOF_opcode: { 2889 Operand ref = InstanceOf.getRef(s); 2890 if (ref.isConstant()) { 2891 // this should have been constant folded. Give up. 2892 return null; 2893 } 2894 // don't worry about the input and output bring the same as their types differ 2895 return InstanceOf.getResult(s).getRegister(); 2896 } 2897 case NEWARRAY_opcode: { 2898 Operand size = NewArray.getSize(s); 2899 if (size.isConstant()) { 2900 // don't worry about the input and output bring the same as their types differ 2901 return NewArray.getResult(s).getRegister(); 2902 } 2903 return null; 2904 } 2905 case NEW_opcode: { 2906 return New.getResult(s).getRegister(); 2907 } 2908 case INT_ZERO_CHECK_opcode: 2909 case LONG_ZERO_CHECK_opcode: { 2910 Operand val1 = ZeroCheck.getValue(s); 2911 // if val1 is constant, this should've been constant folded 2912 // beforehand. Give up. 2913 if (val1.isConstant()) { 2914 return null; 2915 } 2916 // don't worry about the input and output bring the same as their types differ 2917 return ZeroCheck.getGuardResult(s).asRegister().getRegister(); 2918 } 2919 default: 2920 // Operator can't be folded 2921 return null; 2922 } 2923 } 2924 2925 private static int getIntValue(Operand op) { 2926 if (op instanceof IntConstantOperand) { 2927 return op.asIntConstant().value; 2928 } 2929 if (VM.BuildFor32Addr) { 2930 return getAddressValue(op).toInt(); 2931 } 2932 throw new OptimizingCompilerException( 2933 "Cannot getIntValue from this operand " + op + 2934 " of instruction " + op.instruction); 2935 } 2936 2937 private static long getLongValue(Operand op) { 2938 if (op instanceof LongConstantOperand) 2939 return op.asLongConstant().value; 2940 if (VM.BuildFor64Addr) { 2941 return getAddressValue(op).toLong(); 2942 } 2943 throw new OptimizingCompilerException( 2944 "Cannot getLongValue from this operand " + op + 2945 " of instruction " + op.instruction); 2946 } 2947 2948 private static float getFloatValue(Operand op) { 2949 if (op instanceof FloatConstantOperand) 2950 return op.asFloatConstant().value; 2951 throw new OptimizingCompilerException( 2952 "Cannot getFloatValue from this operand " + op + 2953 " of instruction " + op.instruction); 2954 } 2955 2956 private static double getDoubleValue(Operand op) { 2957 if (op instanceof DoubleConstantOperand) 2958 return op.asDoubleConstant().value; 2959 throw new OptimizingCompilerException( 2960 "Cannot getDoubleValue from this operand " + op + 2961 " of instruction " + op.instruction); 2962 } 2963 2964 private static Address getAddressValue(Operand op) { 2965 if (op instanceof NullConstantOperand) { 2966 return Address.zero(); 2967 } 2968 if (op instanceof AddressConstantOperand) { 2969 return op.asAddressConstant().value; 2970 } 2971 if (op instanceof IntConstantOperand) { 2972 return Address.fromIntSignExtend(op.asIntConstant().value); 2973 } 2974 if (VM.BuildFor64Addr && op instanceof LongConstantOperand) { 2975 return Address.fromLong(op.asLongConstant().value); 2976 } 2977 if (op instanceof ObjectConstantOperand) { 2978 if (VM.VerifyAssertions) VM._assert(!op.isMovableObjectConstant()); 2979 return Magic.objectAsAddress(op.asObjectConstant().value); 2980 } 2981 throw new OptimizingCompilerException( 2982 "Cannot getAddressValue from this operand " + op + 2983 " of instruction " + op.instruction); 2984 } 2985 }