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