1 19 20 25 26 27 package soot.baf.toolkits.base; 28 import soot.options.*; 29 30 import soot.util.*; 31 import java.util.*; 32 import soot.*; 33 import soot.baf.*; 34 import soot.toolkits.scalar.*; 35 import soot.toolkits.graph.*; 36 import soot.baf.internal.*; 37 38 public class LoadStoreOptimizer extends BodyTransformer 39 { 40 public LoadStoreOptimizer( Singletons.Global g ) {} 41 public static LoadStoreOptimizer v() { return G.v().soot_baf_toolkits_base_LoadStoreOptimizer(); } 42 43 boolean debug = false; 45 46 final static private int FAILURE = 0; 48 final static private int SUCCESS = 1; 49 final static private int MAKE_DUP = 2; 50 final static private int MAKE_DUP1_X1 = 3; 51 final static private int SPECIAL_SUCCESS = 4; 52 final static private int HAS_CHANGED = 5; 53 final static private int SPECIAL_SUCCESS2 = 6; 54 55 final static private int STORE_LOAD_ELIMINATION = 0; 56 final static private int STORE_LOAD_LOAD_ELIMINATION = -1; 57 58 59 private Map gOptions; 60 61 62 63 64 protected void internalTransform(Body body, String phaseName, Map options) 65 { 66 67 gOptions = options; 68 69 Instance instance = new Instance(); 70 instance.mBody = body; 71 instance.mUnits = body.getUnits(); 72 73 debug = PhaseOptions.getBoolean(gOptions, "debug"); 74 75 if(Options.v().verbose()) 76 G.v().out.println("[" + body.getMethod().getName() + "] Performing LoadStore optimizations..."); 77 78 if(debug) { G.v().out.println("\n\nOptimizing Method: " + body.getMethod().getName());} 79 80 instance.go(); 81 } 82 class Instance { 83 private Chain mUnits; 85 private Body mBody; 86 private ExceptionalUnitGraph mExceptionalUnitGraph; 87 private LocalDefs mLocalDefs; 88 private LocalUses mLocalUses; 89 private Map mUnitToBlockMap; private boolean mPass2 = false; 91 92 93 void go() { 94 if(!mUnits.isEmpty()) { 95 buildUnitToBlockMap(); 96 computeLocalDefsAndLocalUsesInfo(); 97 98 99 100 if(debug){G.v().out.println("Calling optimizeLoadStore(1)\n");} 101 optimizeLoadStores(); 102 103 if(PhaseOptions.getBoolean(gOptions, "inter") ) { 104 if(debug){G.v().out.println("Calling doInterBlockOptimizations");} 105 doInterBlockOptimizations(); 106 107 } 113 114 if(PhaseOptions.getBoolean(gOptions, "sl2") || PhaseOptions.getBoolean(gOptions, "sll2") ) { 115 mPass2 = true; 116 if(debug){G.v().out.println("Calling optimizeLoadStore(2)");} 117 optimizeLoadStores(); 118 } 119 } 120 } 121 125 private void buildUnitToBlockMap() 126 { 127 BlockGraph blockGraph = new ZonedBlockGraph(mBody); 128 if(debug) { 129 G.v().out.println("Method " + mBody.getMethod().getName()+ " Block Graph: "); 130 G.v().out.println(blockGraph); 131 } 132 133 List blocks = blockGraph.getBlocks(); 134 mUnitToBlockMap = new HashMap(); 135 136 Iterator blockIt = blocks.iterator(); 137 while(blockIt.hasNext() ) { 138 Block block = (Block) blockIt.next(); 139 140 Iterator unitIt = block.iterator(); 141 while(unitIt.hasNext()) { 142 Unit unit = (Unit) unitIt.next(); 143 mUnitToBlockMap.put(unit, block); 144 } 145 } 146 } 147 148 149 151 private List buildStoreList() 152 { 153 Iterator it = mUnits.iterator(); 154 List storeList = new ArrayList(); 155 156 while(it.hasNext()) { 157 Unit unit = (Unit) it.next(); 158 if(unit instanceof StoreInst) 159 storeList.add(unit); 160 } 161 return storeList; 162 } 163 164 165 166 private void computeLocalDefsAndLocalUsesInfo() 167 { 168 mExceptionalUnitGraph = new ExceptionalUnitGraph(mBody); 169 mLocalDefs = new SmartLocalDefs(mExceptionalUnitGraph, new SimpleLiveLocals(mExceptionalUnitGraph)); 170 mLocalUses = new SimpleLocalUses(mExceptionalUnitGraph, mLocalDefs); 171 } 172 173 174 175 176 177 private void optimizeLoadStores() 179 { 180 Chain units = mUnits; 182 List storeList; 183 184 185 storeList = buildStoreList(); 187 188 189 { 191 192 boolean hasChanged = true; 193 194 boolean hasChangedFlag = false; 195 while(hasChanged) { 196 197 hasChanged = false; 198 199 200 Iterator unitIt = storeList.iterator(); 202 203 nextUnit: 204 while(unitIt.hasNext()){ 205 Unit unit = (Unit) unitIt.next(); 206 List uses = mLocalUses.getUsesOf(unit); 207 208 209 if(uses.size() < 3) { 211 212 { 214 boolean invalidStore = false; 215 Iterator useIt = uses.iterator(); 216 while(useIt.hasNext()) { 217 UnitValueBoxPair pair = (UnitValueBoxPair) useIt.next(); 218 Unit loadUnit = pair.getUnit(); 219 if(!(loadUnit instanceof LoadInst)) 220 continue nextUnit; 221 222 List defs = mLocalDefs.getDefsOfAt((Local) pair.getValueBox().getValue(), loadUnit); 223 if(defs.size() > 1) { 224 continue nextUnit; 225 } 226 else if(defs.get(0) != unit) { 227 continue nextUnit; } 229 } 230 } 231 232 { 234 Block storeBlock = (Block) mUnitToBlockMap.get(unit); 235 236 Iterator useIt = uses.iterator(); 237 while(useIt.hasNext()) { 238 UnitValueBoxPair pair = (UnitValueBoxPair) useIt.next(); 239 Block useBlock = (Block) mUnitToBlockMap.get(pair.getUnit()); 240 if(useBlock != storeBlock) 241 continue nextUnit; 242 } 243 } 244 245 { 247 Block block; 248 switch(uses.size()) { 249 case 0: 257 break; 258 259 case 1: 260 if(PhaseOptions.getBoolean(gOptions, "sl")) { 261 if(!mPass2 || PhaseOptions.getBoolean(gOptions, "sl2")) { 262 Unit loadUnit = ((UnitValueBoxPair)uses.get(0)).getUnit(); 264 block = (Block) mUnitToBlockMap.get(unit); 265 int test = stackIndependent(unit, loadUnit , block, STORE_LOAD_ELIMINATION); 266 267 if(test == SUCCESS || test == SPECIAL_SUCCESS){ 270 271 block.remove(unit); 272 block.remove(loadUnit); 273 unitIt.remove(); 274 hasChanged = true; hasChangedFlag = false; 275 276 if(debug) { G.v().out.println("Store/Load elimination occurred case1.");} 278 } 285 } 286 } 287 break; 288 289 case 2: 290 if(PhaseOptions.getBoolean(gOptions, "sll")) { 291 if(!mPass2 || PhaseOptions.getBoolean(gOptions, "sll2")) { 292 Unit firstLoad = ((UnitValueBoxPair)uses.get(0)).getUnit(); 294 Unit secondLoad = ((UnitValueBoxPair)uses.get(1)).getUnit(); 295 block = (Block) mUnitToBlockMap.get(unit); 296 297 298 299 Unit temp; if(mUnits.follows(firstLoad, secondLoad)) { 301 temp = secondLoad; 302 secondLoad = firstLoad; 303 firstLoad = temp; 304 } 305 306 int result = stackIndependent(unit, firstLoad, block, STORE_LOAD_ELIMINATION); 307 if(result == SUCCESS){ 308 309 block.remove(firstLoad); 311 block.insertAfter(firstLoad, unit); 312 313 314 int res = stackIndependent(unit, secondLoad, block, STORE_LOAD_LOAD_ELIMINATION); 315 if(res == MAKE_DUP) { 316 Dup1Inst dup = Baf.v().newDup1Inst(((LoadInst) secondLoad).getOpType()); 318 dup.addAllTagsOf(unit); 319 replaceUnit(unit, dup); 320 unitIt.remove(); 322 block.remove(firstLoad); 323 block.remove(secondLoad); 324 325 hasChanged = true; hasChangedFlag = false; 326 327 } 351 352 353 } else if(result == SPECIAL_SUCCESS || result == HAS_CHANGED || result == SPECIAL_SUCCESS2){ 354 if(!hasChangedFlag) { 355 hasChangedFlag = true; 356 hasChanged = true; 357 } 358 } 359 } 360 361 } 362 } 363 } 364 } 365 } 366 } 367 } 368 } 369 370 371 372 373 374 381 private boolean isRequiredByFollowingUnits(Unit from, Unit to) 382 { 383 Iterator it = mUnits.iterator(from, to); 384 int stackHeight = 0; 385 boolean res = false; 386 387 if(from != to) { 388 it.next(); 390 while(it.hasNext()) { 391 Unit currentInst = (Unit) it.next(); 392 if(currentInst == to) 393 break; 394 395 stackHeight -= ((Inst)currentInst).getInCount(); 396 if(stackHeight < 0 ) { 397 res = true; 398 break; 399 } 400 stackHeight += ((Inst)currentInst).getOutCount(); 401 } 402 } 403 return res; 404 } 405 406 407 408 409 410 private int pushStoreToLoad(Unit from , Unit to, Block block) 411 { 412 Unit storePred = (Unit) block.getPredOf(from); 413 if(storePred != null) { 414 if(((Inst)storePred).getOutCount() == 1){ 415 Set unitsToMove = new HashSet(); 416 unitsToMove.add(storePred); 417 unitsToMove.add(from); 418 int h = ((Inst)storePred).getInCount(); 419 Unit currentUnit = storePred; 420 if(h != 0) { 421 currentUnit = (Unit)block.getPredOf(storePred); 422 while(currentUnit != null) { 423 424 h-= ((Inst)currentUnit).getOutCount(); 425 if(h<0){ if(debug) { G.v().out.println("xxx: negative");} 427 return FAILURE; 428 } 429 h+= ((Inst)currentUnit).getInCount(); 430 unitsToMove.add(currentUnit); 431 if(h == 0) 432 break; 433 currentUnit = (Unit) block.getPredOf(currentUnit); 434 } 435 } 436 if(currentUnit == null) { 437 if(debug) { G.v().out.println("xxx: null");} 438 return FAILURE; 439 } 440 441 Unit uu = from; 442 for(;;) { 443 uu = (Unit) block.getSuccOf(uu); 444 if(uu == to) 445 break; 446 Iterator it2 = unitsToMove.iterator(); 447 while(it2.hasNext()) { 448 Unit nu = (Unit) it2.next(); 449 if(debug) { G.v().out.println("xxxspecial;success pushing forward stuff.");} 450 451 452 if(!canMoveUnitOver(nu, uu)){ 453 if(debug) { G.v().out.println("xxx: cant move over faillure" + nu);} 454 return FAILURE; 455 } 456 if(debug) { G.v().out.println("can move" + nu + " over " + uu);} 457 } 458 } 459 460 Unit unitToMove = currentUnit; 462 while(unitToMove != from) { 463 Unit succ = (Unit) block.getSuccOf(unitToMove); 464 if(debug) { G.v().out.println("moving " + unitToMove);} 465 block.remove(unitToMove); 466 block.insertBefore(unitToMove, to); 467 unitToMove = succ; 468 } 469 block.remove(from); 470 block.insertBefore(from, to); 471 472 if(debug) { G.v().out.println("xxx1success pushing forward stuff.");} 473 return SPECIAL_SUCCESS; 474 } 475 } 476 477 return FAILURE; 478 } 479 480 481 482 483 493 494 private int stackIndependent(Unit from, Unit to, Block block, int aContext) 495 { 496 if(debug) { 497 G.v().out.println("Trying: " + from + "/" + to + " in block " + block.getIndexInMethod()+":" ); 498 G.v().out.println("context:" + (aContext == STORE_LOAD_ELIMINATION ? 499 "STORE_LOAD_ELIMINATION" : 500 "STORE_LOAD_LOAD_ELIMINATION")); 501 } 502 503 504 int minStackHeightAttained = 0; int stackHeight = 0; Iterator it = mUnits.iterator(mUnits.getSuccOf(from)); 507 int res = FAILURE; 508 509 Unit currentInst = (Unit) it.next(); 511 if(aContext == STORE_LOAD_LOAD_ELIMINATION) { 512 currentInst = (Unit) it.next(); } 514 515 while(currentInst != to) { 517 stackHeight -= ((Inst)currentInst).getInCount(); 518 if(stackHeight < minStackHeightAttained) 519 minStackHeightAttained = stackHeight; 520 521 522 stackHeight += ((Inst)currentInst).getOutCount(); 523 524 currentInst = (Unit) it.next(); 525 } 526 527 530 531 if(debug) { 532 G.v().out.println("nshv = " + stackHeight); 533 G.v().out.println("mshv = " + minStackHeightAttained); 534 } 535 536 537 boolean hasChanged = true; 538 539 while(hasChanged) { 541 hasChanged = false; 542 543 if(aContext == STORE_LOAD_LOAD_ELIMINATION) { 545 546 if(stackHeight == 0 && minStackHeightAttained == 0){ 547 if(debug) { 548 G.v().out.println("xxx: succ: -1, makedup "); 549 } 550 return MAKE_DUP; 551 } 552 else if(stackHeight == -1 && minStackHeightAttained == -1){ 553 if(debug) { G.v().out.println("xxx: succ: -1, makedup , -1");} 554 return MAKE_DUP; 555 } 556 else if(stackHeight == -2 && minStackHeightAttained == -2){if(debug) { G.v().out.println("xxx: succ -1 , make dupx1 ");} 557 return MAKE_DUP1_X1; } 558 559 else if (minStackHeightAttained < -2) { 560 if(debug) { G.v().out.println("xxx: failled due: minStackHeightAttained < -2 ");} 561 return FAILURE; 562 } 563 } 564 565 566 if(aContext == STORE_LOAD_ELIMINATION) { 568 if(stackHeight == 0 && minStackHeightAttained == 0){ 569 if(debug) { G.v().out.println("xxx: success due: 0, SUCCESS ");} 570 return SUCCESS; 571 } 572 585 else if (minStackHeightAttained < 0){ 586 return pushStoreToLoad(from , to, block); 587 } 588 } 589 590 591 it = mUnits.iterator(mUnits.getSuccOf(from), to); 592 593 Unit unitToMove = null; 594 Unit u = (Unit) it.next(); 595 596 if(aContext == STORE_LOAD_LOAD_ELIMINATION) { 597 u = (Unit) it.next(); 598 } 599 int currentH = 0; 600 601 while( u != to) { 603 604 if(((Inst)u).getNetCount() == 1) { 605 if(u instanceof LoadInst || u instanceof PushInst || u instanceof NewInst || u instanceof StaticGetInst || u instanceof Dup1Inst) { 607 608 if(!isRequiredByFollowingUnits(u, (LoadInst) to)) { 610 unitToMove = u; 611 } 612 613 } 614 else{ 615 if(debug) { G.v().out.println("1003:(LoadStoreOptimizer@stackIndependent): found unknown unit w/ getNetCount == 1" + u);} 616 } 617 } 618 619 620 621 622 623 if(unitToMove != null) { 624 int flag = 0; 625 627 if(tryToMoveUnit(unitToMove, block, from, to, flag)) { 628 if(stackHeight > -2 && minStackHeightAttained == -2){ 629 return HAS_CHANGED; 630 } 631 632 stackHeight--; 633 if(stackHeight < minStackHeightAttained) 634 minStackHeightAttained = stackHeight; 635 hasChanged = true; 636 break; 637 } 638 } 639 640 currentH += ((Inst)u).getNetCount(); 641 unitToMove = null; 642 u = (Unit) it.next(); 643 } 644 } 645 646 if(isCommutativeBinOp((Unit) block.getSuccOf(to))) { 647 if(aContext == STORE_LOAD_ELIMINATION && stackHeight == 1 && minStackHeightAttained == 0) { 648 if(debug) { G.v().out.println("xxx: commutative ");} 649 return SPECIAL_SUCCESS; 650 } 651 else if( ((Inst) to).getOutCount() == 1 && 652 ((Inst) to).getInCount() == 0 && 653 ((Inst) mUnits.getPredOf(to)).getOutCount() == 1 && 654 ((Inst) mUnits.getPredOf(to)).getInCount() == 0) { 655 656 Object toPred = mUnits.getPredOf(to); 657 block.remove((Unit) toPred); 658 block.insertAfter((Unit) toPred, to); 659 return HAS_CHANGED; } 661 else return FAILURE; 662 } 663 if (aContext == STORE_LOAD_ELIMINATION) 664 return pushStoreToLoad(from , to, block); 665 666 return res; 667 } 668 669 670 673 private boolean isNonLocalReadOrWrite(Unit aUnit) 674 { 675 if((aUnit instanceof FieldArgInst ) || 676 (aUnit instanceof ArrayReadInst) || 677 (aUnit instanceof ArrayWriteInst) ) 678 return true; 679 else 680 return false; 681 } 682 683 684 688 private boolean canMoveUnitOver(Unit aUnitToMove, Unit aUnitToGoOver) { 690 691 if((aUnitToGoOver instanceof MethodArgInst && aUnitToMove instanceof MethodArgInst) || 693 (aUnitToGoOver instanceof MethodArgInst && isNonLocalReadOrWrite(aUnitToMove)) || 694 (isNonLocalReadOrWrite(aUnitToGoOver) && aUnitToMove instanceof MethodArgInst) || 695 696 (aUnitToGoOver instanceof ArrayReadInst && aUnitToMove instanceof ArrayWriteInst) || 697 (aUnitToGoOver instanceof ArrayWriteInst && aUnitToMove instanceof ArrayReadInst) || 698 (aUnitToGoOver instanceof ArrayWriteInst && aUnitToMove instanceof ArrayWriteInst)|| 699 700 701 (aUnitToGoOver instanceof FieldPutInst && aUnitToMove instanceof FieldGetInst && 702 ((FieldArgInst)aUnitToGoOver).getField() == ((FieldArgInst)aUnitToMove).getField()) || 703 (aUnitToGoOver instanceof FieldGetInst && aUnitToMove instanceof FieldPutInst && 704 ((FieldArgInst)aUnitToGoOver).getField() == ((FieldArgInst)aUnitToMove).getField()) || 705 (aUnitToGoOver instanceof FieldPutInst && aUnitToMove instanceof FieldPutInst && 706 ((FieldArgInst)aUnitToGoOver).getField() == ((FieldArgInst)aUnitToMove).getField()) || 707 708 709 (aUnitToGoOver instanceof StaticPutInst && aUnitToMove instanceof StaticGetInst && 710 ((FieldArgInst)aUnitToGoOver).getField() == ((FieldArgInst)aUnitToMove).getField()) || 711 (aUnitToGoOver instanceof StaticGetInst && aUnitToMove instanceof StaticPutInst && 712 ((FieldArgInst)aUnitToGoOver).getField() == ((FieldArgInst)aUnitToMove).getField())|| 713 (aUnitToGoOver instanceof StaticPutInst && aUnitToMove instanceof StaticPutInst && 714 ((FieldArgInst)aUnitToGoOver).getField() == ((FieldArgInst)aUnitToMove).getField())) 715 return false; 716 717 718 if(aUnitToGoOver instanceof EnterMonitorInst || aUnitToGoOver instanceof ExitMonitorInst) 720 return false; 721 722 if(aUnitToMove instanceof EnterMonitorInst || aUnitToGoOver instanceof ExitMonitorInst) 723 return false; 724 725 if(aUnitToGoOver instanceof IdentityInst || aUnitToMove instanceof IdentityInst) 726 return false; 727 728 729 if(aUnitToMove instanceof LoadInst ) { 730 if(aUnitToGoOver instanceof StoreInst) { 731 if(((StoreInst)aUnitToGoOver).getLocal() == ((LoadInst)aUnitToMove).getLocal()) { 732 return false; 733 } 734 } 735 else if(aUnitToGoOver instanceof IncInst) { 736 if(((IncInst)aUnitToGoOver).getLocal() == ((LoadInst)aUnitToMove).getLocal()){ 737 return false; 738 } 739 } 740 } 741 742 if(aUnitToMove instanceof StoreInst) { 744 if(aUnitToGoOver instanceof LoadInst) { 745 if(((LoadInst)aUnitToGoOver).getLocal() == ((StoreInst)aUnitToMove).getLocal()) { 746 return false; 747 } 748 } 749 else if(aUnitToGoOver instanceof IncInst) { 750 if(((IncInst)aUnitToGoOver).getLocal() == ((StoreInst)aUnitToMove).getLocal()){ 751 return false; 752 } 753 } 754 } 755 756 if(aUnitToMove instanceof IncInst) { 757 if(aUnitToGoOver instanceof StoreInst) { 758 if(((StoreInst)aUnitToGoOver).getLocal() == ((IncInst)aUnitToMove).getLocal()) { 759 return false; 760 } 761 } 762 else if(aUnitToGoOver instanceof LoadInst) { 763 if(((LoadInst)aUnitToGoOver).getLocal() == ((IncInst)aUnitToMove).getLocal()){ 764 return false; 765 } 766 } 767 } 768 return true; 769 } 770 771 772 773 774 775 776 private boolean tryToMoveUnit(Unit unitToMove, Block block, Unit from, Unit to, int flag) 777 { 778 779 int h = 0; 780 Unit current = unitToMove; 781 boolean reachedStore = false; 782 boolean reorderingOccurred =false; 783 784 if(debug) {G.v().out.println("[tryToMoveUnit]: trying to move:" + unitToMove);} 785 if(unitToMove == null) 786 return false; 787 788 while( current != block.getHead()) { current = (Unit) mUnits.getPredOf(current); 790 791 if(!canMoveUnitOver(current, unitToMove)) 792 return false; 793 794 if(current == from) 795 reachedStore = true; 796 797 798 h -= ((Inst)current).getOutCount(); 799 if(h < 0 ){ 800 if(debug) { G.v().out.println("1006:(LoadStoreOptimizer@stackIndependent): Stack went negative while trying to reorder code.");} 801 802 803 804 if(flag == 1) { 805 if(current instanceof DupInst) { 806 block.remove(unitToMove); 807 block.insertAfter(unitToMove, current); 808 } 810 811 } 812 return false; 813 } 814 h += ((Inst)current).getInCount(); 815 816 817 if(h == 0 && reachedStore == true) { 818 if(!isRequiredByFollowingUnits(unitToMove, (LoadInst) to)) { 819 if(debug) { G.v().out.println("10077:(LoadStoreOptimizer@stackIndependent): reordering bytecode move: " + unitToMove + "before: " + current);} 820 block.remove(unitToMove); 821 block.insertBefore(unitToMove, current); 822 823 reorderingOccurred = true; 824 break; 825 } 826 } 827 } 828 829 if(reorderingOccurred) { 830 if(debug) { G.v().out.println("reordering occured");} 831 return true; 832 } else { 833 if(debug) { G.v().out.println("1008:(LoadStoreOptimizer@stackIndependent):failled to find a new slot for unit to move");} 834 return false; 835 } 836 } 837 838 839 840 841 851 private void replaceUnit(Unit aToReplace1, Unit aToReplace2, Unit aReplacement) 852 { 853 Block block = (Block) mUnitToBlockMap.get(aToReplace1); 854 855 if(aToReplace2 != null) { 856 block.insertAfter(aReplacement, aToReplace2); 857 block.remove(aToReplace2); 858 } else { 859 block.insertAfter(aReplacement, aToReplace1); 860 } 861 862 block.remove(aToReplace1); 863 864 mUnitToBlockMap.put(aReplacement, block); 866 } 867 868 869 private void replaceUnit(Unit aToReplace, Unit aReplacement) 870 { 871 replaceUnit(aToReplace, null, aReplacement); 872 } 873 874 875 876 879 private Type type(Unit aUnit) 880 { 881 if(aUnit instanceof InstanceCastInst || aUnit instanceof NewInst) { 882 return RefType.v(); 883 } else if(aUnit instanceof LoadInst) { 884 return ((LoadInst)aUnit).getOpType(); 885 } else if (aUnit instanceof FieldGetInst) 886 return ((FieldGetInst)aUnit).getField().getType(); 887 else if (aUnit instanceof Dup1Inst) 888 return ((Dup1Inst)aUnit).getOp1Type(); 889 else if(aUnit instanceof StaticGetInst) 890 return ((StaticGetInst) aUnit).getField().getType(); 891 else if(aUnit instanceof OpTypeArgInst) 892 return ((OpTypeArgInst)aUnit).getOpType(); 893 else if(aUnit instanceof PushInst) 894 return ((PushInst)aUnit).getConstant().getType(); 895 else if (aUnit instanceof MethodArgInst) 896 return ((MethodArgInst) aUnit).getMethod().getReturnType(); 897 else if(aUnit instanceof Dup1_x1Inst) 898 return ((Dup1_x1Inst) aUnit).getOp1Type(); 899 else if(aUnit instanceof Dup1Inst) 900 return ((Dup1Inst) aUnit).getOp1Type(); 901 else 902 return null; 903 } 904 905 906 910 private boolean isExceptionHandlerBlock(Block aBlock) 911 { 912 Unit blockHead = aBlock.getHead(); 913 Iterator it = mBody.getTraps().iterator(); 914 while(it.hasNext()) { 915 Trap trap = (Trap) it.next(); 916 if(trap.getHandlerUnit() == blockHead) 917 return true; 918 } 919 return false; 920 } 921 922 private Unit getStackItemAt2(Unit aUnit, Block aBlock, int aDeltaHeight) 923 { 924 int h = 0; 925 Unit currentUnit = aUnit; 926 Unit candidate = null; 927 928 while(currentUnit != null) { 929 currentUnit = (Unit) aBlock.getPredOf(currentUnit); 930 if(currentUnit == null) { 931 if(debug) { G.v().out.println(aBlock);} 932 G.v().out.println("xxxxxxxxxxxx " + h); 933 if(isExceptionHandlerBlock(aBlock) ) { 934 return new BLoadInst( RefType.v("dummy") , ((StoreInst) aUnit).getLocal()); } 936 937 aBlock = (Block) aBlock.getPreds().get(0); 938 currentUnit = (Unit) aBlock.getTail(); 939 940 } 941 942 943 h -= ((Inst)currentUnit).getOutCount(); 944 if(h <= aDeltaHeight) { 945 candidate = currentUnit; 946 break; 947 } 948 h += ((Inst)currentUnit).getInCount(); 949 } 950 return candidate; 951 } 952 953 954 955 956 private int getDeltaStackHeightFromTo(Unit aFrom, Unit aTo) 958 { 959 Iterator it = mUnits.iterator(aFrom, aTo); 960 int h = 0; 961 962 while(it.hasNext()) { 963 h += ((Inst)it.next()).getNetCount(); 964 } 965 966 return h; 967 } 968 969 970 971 978 private void doInterBlockOptimizations() 979 { 980 boolean hasChanged = true; 981 while(hasChanged) { 982 hasChanged = false; 983 984 List tempList = new ArrayList(); 985 tempList.addAll(mUnits); 986 Iterator it = tempList.iterator(); 987 while(it.hasNext()) { 988 Unit u = (Unit) it.next(); 989 990 if(u instanceof LoadInst) { 991 if(debug) { G.v().out.println("inter trying: " + u);} 992 Block loadBlock = (Block) mUnitToBlockMap.get(u); 993 List defs = mLocalDefs.getDefsOfAt(((LoadInst)u).getLocal(), u); 994 995 if(defs.size() == 1) { 997 Block defBlock =(Block) mUnitToBlockMap.get(defs.get(0)); 998 if(defBlock != loadBlock && !(isExceptionHandlerBlock(loadBlock))) { 999 Unit storeUnit = (Unit) defs.get(0); 1000 if(storeUnit instanceof StoreInst) { 1001 List uses = mLocalUses.getUsesOf(storeUnit); 1002 if(uses.size() == 1){ 1003 if(allSuccesorsOfAreThePredecessorsOf(defBlock, loadBlock)) { 1004 if(getDeltaStackHeightFromTo((Unit) defBlock.getSuccOf(storeUnit), (Unit)defBlock.getTail()) == 0) { 1005 Iterator it2 = defBlock.getSuccs().iterator(); 1006 boolean res = true; 1007 while(it2.hasNext()) { 1008 Block b = (Block) it2.next(); 1009 if(getDeltaStackHeightFromTo((Unit) b.getHead(), (Unit) b.getTail()) != 0) { 1010 res = false; 1011 break; 1012 } 1013 if(b.getPreds().size() != 1 || b.getSuccs().size() != 1){ 1014 res = false; 1015 break; 1016 } 1017 } 1018 if(debug) { G.v().out.println(defBlock.toString() + loadBlock.toString());} 1019 1020 if(res) { 1021 defBlock.remove(storeUnit); 1022 mUnitToBlockMap.put(storeUnit, loadBlock); 1023 loadBlock.insertBefore(storeUnit, loadBlock.getHead()); 1024 hasChanged = true; 1025 if(debug) { G.v().out.println("inter-block opti occurred " + storeUnit + " " + u);} 1026 if(debug) { G.v().out.println(defBlock.toString() + loadBlock.toString());} 1027 } 1028 } 1029 } 1030 } 1031 } 1032 } 1033 } 1034 else if(defs.size() == 2) { 1036 1037 Unit def0 = (Unit) defs.get(0); 1038 Unit def1 = (Unit) defs.get(1); 1039 1040 Block defBlock0 = (Block) mUnitToBlockMap.get(def0); 1041 Block defBlock1 = (Block) mUnitToBlockMap.get(def1); 1042 if(defBlock0 != loadBlock && defBlock1 != loadBlock && defBlock0 != defBlock1 1043 && !(isExceptionHandlerBlock(loadBlock))) { 1044 if(mLocalUses.getUsesOf(def0).size() == 1 && mLocalUses.getUsesOf(def1).size() == 1) { 1045 List def0Succs = defBlock0.getSuccs(); 1046 List def1Succs = defBlock1.getSuccs(); 1047 if(def0Succs.size()==1 && def1Succs.size()==1) { 1048 if(def0Succs.get(0) == loadBlock && def1Succs.get(0)== loadBlock) { 1049 if(loadBlock.getPreds().size() == 2) { 1050 if( (def0 == defBlock0.getTail()|| 1051 getDeltaStackHeightFromTo((Unit)defBlock0.getSuccOf(def0),(Unit) defBlock0.getTail()) == 0) && 1052 (def1 == defBlock1.getTail() || 1053 getDeltaStackHeightFromTo((Unit)defBlock1.getSuccOf(def1), (Unit) defBlock1.getTail()) == 0)) { 1054 defBlock0.remove(def0); 1055 defBlock1.remove(def1); 1056 loadBlock.insertBefore(def0, loadBlock.getHead()); 1057 mUnitToBlockMap.put(def0, loadBlock); 1058 hasChanged = true; 1059 if(debug) { G.v().out.println("inter-block opti2 occurred " + def0);} 1060 } else { if(debug) { G.v().out.println("failed: inter1");}} 1061 } else { if(debug) { G.v().out.println("failed: inter2");}} 1062 } else { if(debug) { G.v().out.println("failed: inter3");}} 1063 } else { if(debug) { G.v().out.println("failed: inter4");}} 1064 } else { if(debug) { G.v().out.println("failed: inter5");}} 1065 } else { if(debug) { G.v().out.println("failed: inter6");}} 1066 } 1067 } 1068 } 1069 } 1070 } 1071 1072 1073 1074 1078 private boolean allSuccesorsOfAreThePredecessorsOf(Block aFirstBlock, Block aSecondBlock) 1079 { 1080 int size = aFirstBlock.getSuccs().size(); 1081 Iterator it = aFirstBlock.getSuccs().iterator(); 1082 1083 List preds = aSecondBlock.getPreds(); 1084 while(it.hasNext()) { 1085 if(!preds.contains(it.next())) 1086 return false; 1087 } 1088 1089 if(size == preds.size()) 1090 return true; 1091 else 1092 return false; 1093 } 1094 1095 1096 1097 1098 1099 1102 private boolean isCommutativeBinOp(Unit aUnit) 1103 { 1104 if(aUnit == null ) 1105 return false; 1106 1107 if(aUnit instanceof AddInst || 1108 aUnit instanceof MulInst || 1109 aUnit instanceof AndInst || 1110 aUnit instanceof OrInst || 1111 aUnit instanceof XorInst) 1112 return true; 1113 else 1114 return false; 1115 } 1116 1117 1120 private boolean propagateLoadForward(Unit aInst) 1121 { 1122 Unit currentUnit; 1123 Block block = (Block) mUnitToBlockMap.get(aInst); 1124 boolean res = false; 1125 int h = 0; 1126 Unit candidate = null; 1127 1128 if(aInst == block.getTail()) 1129 return false; 1130 1131 currentUnit = (Unit) block.getSuccOf(aInst); 1132 1133 while( currentUnit != block.getTail()) { 1134 1135 if(!canMoveUnitOver(aInst, currentUnit)){ if(debug) { G.v().out.println("can't go over: " + currentUnit);} 1136 break;} 1137 1138 1139 h -= ((Inst)currentUnit).getInCount(); 1140 if(h < 0){ 1141 if(!(aInst instanceof Dup1Inst && currentUnit instanceof Dup1Inst)) { 1142 if(debug) { G.v().out.println("breaking at: " + currentUnit);} 1143 break; 1144 } 1145 } 1146 1147 h += ((Inst)currentUnit).getOutCount(); 1148 1149 if(h == 0){ 1150 candidate = currentUnit; } 1152 1153 currentUnit = (Unit) block.getSuccOf(currentUnit); 1154 } 1155 if(candidate != null) { 1156 if(debug) { G.v().out.println("successfull propagation " + candidate + block.getTail());} 1157 block.remove(aInst); 1158 if(block.getTail() == mUnitToBlockMap.get(candidate)){ 1159 1160 block.insertAfter(aInst, candidate); 1161 if(block.getTail() != aInst) 1162 throw new RuntimeException (); 1163 } 1164 block.insertAfter(aInst, candidate); 1165 return true; 1166 } 1167 1168 return false; 1169 } 1170 1171 1172 1173 1176 private void propagateLoadsForward() 1177 { 1178 boolean hasChanged = true; 1179 1180 while(hasChanged) { 1181 hasChanged = false; 1182 List tempList = new ArrayList(); 1183 tempList.addAll(mUnits); 1184 Iterator it = tempList.iterator(); 1185 1186 while(it.hasNext()) { 1187 Unit u = (Unit) it.next(); 1188 if( u instanceof LoadInst || u instanceof Dup1Inst) { 1189 if(debug) { G.v().out.println("trying to push:" + u);} 1190 boolean res =propagateLoadForward(u); 1191 if(!hasChanged) 1192 hasChanged = res; 1193 } 1194 } 1195 } 1196 } 1197 1198 1199 void propagateBackwardsIndependentHunk() 1200 { 1201 1202 List tempList = new ArrayList(); 1203 tempList.addAll(mUnits); 1204 Iterator it = tempList.iterator(); 1205 1206 while(it.hasNext()) { 1207 Unit u = (Unit) it.next(); 1208 1209 if( u instanceof NewInst) { 1210 Block block = (Block) mUnitToBlockMap.get(u); 1211 Unit succ = (Unit) block.getSuccOf(u); 1212 if( succ instanceof StoreInst) { 1213 Unit currentUnit = u; 1214 Unit candidate = null; 1215 1216 while(currentUnit != block.getHead()) { 1217 currentUnit = (Unit) block.getPredOf(currentUnit); 1218 if(canMoveUnitOver(currentUnit, succ)){ 1219 candidate = currentUnit; 1220 } else 1221 break; 1222 } 1223 if(candidate != null) { 1224 block.remove(u); 1225 block.remove(succ); 1226 block.insertBefore(u, candidate); 1227 block.insertBefore(succ, candidate); 1228 } 1229 } 1230 } 1231 } 1232 } 1233 1234 1235 1236 private void propagateLoadsBackwards() 1239 { 1240 boolean hasChanged = true; 1241 while(hasChanged) { 1242 hasChanged = false; 1243 1244 List tempList = new ArrayList(); 1245 tempList.addAll(mUnits); 1246 1247 Iterator it = tempList.iterator(); 1248 while(it.hasNext()) { 1249 Unit currentInst = (Unit) it.next(); 1250 1251 if(currentInst instanceof LoadInst) { 1252 Block block = (Block) mUnitToBlockMap.get(currentInst); 1253 Unit insertPoint = propagateLoadBackwards(currentInst, block); 1254 1255 if(insertPoint != null) { 1256 block.remove(currentInst); 1257 block.insertBefore(currentInst, insertPoint); 1258 hasChanged = true; 1259 } 1260 } 1261 } 1262 } 1263 } 1264 1265 1266 private Unit propagateLoadBackwards(Unit aInst, Block aBlock) 1269 { 1270 int h = 0; 1271 Unit candidate = null; 1272 Unit currentUnit = aInst; 1273 1274 1276 currentUnit = (Unit) aBlock.getPredOf(currentUnit); 1277 while( currentUnit != null) { 1278 if(!canMoveUnitOver(currentUnit, aInst)) 1279 break; 1280 1281 h -= ((Inst)currentUnit).getOutCount(); 1282 if(h < 0) break; 1283 h += ((Inst)currentUnit).getInCount(); 1284 if(h == 0) candidate = currentUnit; 1285 1286 1287 currentUnit = (Unit) aBlock.getPredOf(currentUnit); 1288 } 1289 1290 return candidate; 1291 } 1292 1293 1294 1295 1506 1507} 1508 1509 1510} 1511 1512 | Popular Tags |